@ours.network/fleet 1.1.0-nightly.1 → 1.1.0-nightly.3
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 +76 -93
- package/dist/application/role-creation-service.d.ts +2 -21
- package/dist/application/role-creation-service.js +15 -64
- package/dist/application/role-removal-service.js +6 -3
- package/dist/application/task-room-service.js +7 -2
- package/dist/application/types.d.ts +1 -1
- package/dist/briefing.js +5 -5
- package/dist/build-info.json +4 -4
- package/dist/cli.js +48 -38
- package/dist/config.d.ts +65 -2
- package/dist/config.js +337 -25
- package/dist/creation.d.ts +1 -1
- package/dist/creation.js +2 -2
- package/dist/docs.d.ts +1 -1
- package/dist/docs.js +48 -97
- package/dist/doctor.js +4 -4
- package/dist/fleet-proxy.js +30 -8
- package/dist/generated-agent-source.d.ts +9 -0
- package/dist/generated-agent-source.js +53 -0
- package/dist/harness/agent-session.d.ts +13 -0
- package/dist/harness/claude-code-session.d.ts +4 -0
- package/dist/harness/claude-code-session.js +4 -0
- package/dist/harness/claude-code.js +10 -0
- package/dist/harness/codex-session.d.ts +4 -0
- package/dist/harness/codex-session.js +4 -0
- package/dist/harness/codex.js +14 -0
- package/dist/harness/registry.js +4 -0
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/dist/init-guidance.d.ts +1 -0
- package/dist/init-guidance.js +5 -0
- package/dist/model-env.d.ts +2 -3
- package/dist/model-env.js +3 -5
- package/dist/ops.js +4 -2
- package/dist/owner-channel/commands.js +2 -1
- package/dist/resolved-plan.d.ts +3 -2
- package/dist/resolved-plan.js +21 -5
- package/dist/rooms-tasks/cli.js +2 -1
- package/dist/rooms-tasks/config.js +24 -9
- package/dist/rooms-tasks/provision.js +71 -36
- package/dist/rooms-tasks/templates.js +6 -6
- package/dist/rooms-tasks/types.d.ts +8 -15
- package/dist/rooms-tasks/types.js +1 -4
- package/dist/sensitive-config.d.ts +2 -0
- package/dist/sensitive-config.js +4 -0
- package/dist/spawn.d.ts +8 -33
- package/dist/spawn.js +52 -211
- package/dist/watchdog/config.d.ts +10 -7
- package/dist/watchdog/config.js +29 -19
- package/dist/watchdog/run.js +4 -13
- package/dist/web/fleet-config-service.d.ts +11 -8
- package/dist/web/fleet-config-service.js +383 -183
- package/dist/web/topology-promote.js +25 -15
- package/dist/web/topology.js +2 -2
- package/dist/web/yaml-document-edit.js +2 -0
- package/dist/web-app/assets/index-BbTc5KtZ.js +10 -0
- package/dist/web-app/index.html +1 -1
- package/examples/fleet/agents/Alice.yaml +11 -0
- package/examples/fleet/agents/FleetCoordinator.yaml +7 -0
- package/examples/fleet/brains/claude-default.yaml +5 -0
- package/examples/fleet/roles/coordinator.yaml +5 -0
- package/examples/fleet/roles/developer.yaml +3 -0
- package/examples/fleet.yaml +74 -0
- package/package.json +2 -1
- package/dist/web-app/assets/index-DhMDVRU1.js +0 -10
package/dist/cli.js
CHANGED
|
@@ -6,11 +6,12 @@ import { join as joinPath, resolve as resolvePath } from 'node:path';
|
|
|
6
6
|
import { createInterface } from 'node:readline';
|
|
7
7
|
import { Command } from 'commander';
|
|
8
8
|
import { VERSION } from './version.js';
|
|
9
|
+
import { INIT_COMPLETION_GUIDANCE } from './init-guidance.js';
|
|
9
10
|
import { analyzeInstalls, buildInfo, buildLabel, discoverInstalls, runningLabel, } from './provenance.js';
|
|
10
11
|
import { agentDir, agentsRoot, tmpRoot, logsRoot, deriveXdgRuntimeDir } from './paths.js';
|
|
11
|
-
import { findRole, loadConfig } from './config.js';
|
|
12
|
+
import { findRole, loadConfig, ROLE_NAME_RE } from './config.js';
|
|
12
13
|
import { formatDuration } from './duration.js';
|
|
13
|
-
import { resolvedPlan } from './resolved-plan.js';
|
|
14
|
+
import { redactSensitive, resolvedPlan } from './resolved-plan.js';
|
|
14
15
|
import { pickBackend } from './supervisor/index.js';
|
|
15
16
|
import { up, down } from './ops.js';
|
|
16
17
|
import { readRestartLedger, runSupervised, runTemp } from './runner.js';
|
|
@@ -73,10 +74,10 @@ const passthrough = (cmd, args) => new Promise(resolve => {
|
|
|
73
74
|
});
|
|
74
75
|
const program = new Command()
|
|
75
76
|
.name('ours-fleet')
|
|
76
|
-
.description('Fleet of persistent, identity-bound AI agents —
|
|
77
|
+
.description('Fleet of persistent, identity-bound AI agents — canonical Brain + Role definitions over ACP sessions.')
|
|
77
78
|
.enablePositionalOptions()
|
|
78
79
|
.version(VERSION);
|
|
79
|
-
const cOpt = (cmd) => cmd.option('-c, --configuration <file>', '
|
|
80
|
+
const cOpt = (cmd) => cmd.option('-c, --configuration <file>', 'manifest (default: ~/fleet.yaml; documents under ~/fleet/)');
|
|
80
81
|
const collect = (value, previous) => [...previous, value];
|
|
81
82
|
program.command('docs')
|
|
82
83
|
.alias('man')
|
|
@@ -217,6 +218,24 @@ function parseCodexConfig(values) {
|
|
|
217
218
|
}
|
|
218
219
|
return out;
|
|
219
220
|
}
|
|
221
|
+
function parseAgentSelection(raw, kind) {
|
|
222
|
+
if (raw === undefined)
|
|
223
|
+
return undefined;
|
|
224
|
+
if (ROLE_NAME_RE.test(raw))
|
|
225
|
+
return { ref: raw };
|
|
226
|
+
if (!raw.startsWith('inline:'))
|
|
227
|
+
throw new Error(`invalid --${kind}; use a declared ID or inline:{...}`);
|
|
228
|
+
let value;
|
|
229
|
+
try {
|
|
230
|
+
value = JSON.parse(raw.slice('inline:'.length));
|
|
231
|
+
}
|
|
232
|
+
catch {
|
|
233
|
+
throw new Error(`invalid --${kind} inline mapping`);
|
|
234
|
+
}
|
|
235
|
+
if (!value || typeof value !== 'object' || Array.isArray(value))
|
|
236
|
+
throw new Error(`invalid --${kind} inline mapping`);
|
|
237
|
+
return { inline: value };
|
|
238
|
+
}
|
|
220
239
|
cOpt(program.command('config').description('validate + print the merged plan (no side effects)'))
|
|
221
240
|
.option('--json', 'emit the stable, versioned, secret-safe resolved plan')
|
|
222
241
|
.option('--yaml-mode <mode>', 'non-plain YAML policy: compat|strict', 'compat')
|
|
@@ -260,14 +279,16 @@ cOpt(program.command('config').description('validate + print the merged plan (no
|
|
|
260
279
|
console.log(` cwd: ${r.cwd}`);
|
|
261
280
|
if (r.model)
|
|
262
281
|
console.log(` model: ${r.model}`);
|
|
282
|
+
if (r.effort)
|
|
283
|
+
console.log(` effort: ${r.effort}`);
|
|
263
284
|
if (r.harness_options && Object.keys(r.harness_options).length)
|
|
264
|
-
console.log(` options: ${JSON.stringify(r.harness_options)}`);
|
|
285
|
+
console.log(` options: ${JSON.stringify(redactSensitive(r.harness_options))}`);
|
|
265
286
|
if (r.coordinator)
|
|
266
287
|
console.log(` coordinator: ${r.coordinator}`);
|
|
267
288
|
if (r.mission)
|
|
268
289
|
console.log(` mission: ${r.mission.split('\n')[0]}`);
|
|
269
290
|
if (r.oversee?.length)
|
|
270
|
-
console.log(` oversees: ${r.oversee.map(o => `${o.
|
|
291
|
+
console.log(` oversees: ${r.oversee.map(o => `${o.agent}@${o.interval}`).join(', ')}`);
|
|
271
292
|
if (r.isolation) {
|
|
272
293
|
const iso = r.isolation;
|
|
273
294
|
const caps = [
|
|
@@ -1109,50 +1130,32 @@ cOpt(program.command('rm <name>').description('stop + remove a role (temporary e
|
|
|
1109
1130
|
}
|
|
1110
1131
|
});
|
|
1111
1132
|
cOpt(program.command('spawn [name]').description('spawn a new agent (permanent by default)'))
|
|
1112
|
-
.option('--
|
|
1133
|
+
.option('--name <name>', 'agent name (alternative to the positional name)')
|
|
1134
|
+
.option('--brain <selection>', 'Brain ID or inline:{...} definition')
|
|
1135
|
+
.option('--role <selection>', 'Role ID or inline:{...} definition')
|
|
1113
1136
|
.option('--temp', 'temporary: independent transient supervisor, archived on retirement, gone on reboot')
|
|
1114
|
-
.option('--
|
|
1115
|
-
.option('--session <backend>', 'session backend: acp (default: acp)')
|
|
1116
|
-
.option('--mission <text>', 'one-line mission')
|
|
1117
|
-
.option('--mission-file <path>', 'UTF-8 mission text (mutually exclusive with --mission)')
|
|
1118
|
-
.option('--identity <name>', 'ours identity to bind (default: role name)')
|
|
1137
|
+
.option('--identity <name>', 'ours identity to bind (default: Agent name)')
|
|
1119
1138
|
.option('--cwd <dir>', 'working directory')
|
|
1120
1139
|
.option('--coordinator <name>', 'announce target')
|
|
1121
|
-
.option('--model <id>', 'model id to launch on (e.g. claude-fable-5); default: launcher default')
|
|
1122
|
-
.option('--permission-mode <mode>', 'harness permission mode (Codex: untrusted|on-request|never; Claude: native values)')
|
|
1123
1140
|
.option('--approval <mode>', 'fleet permission mode: ask|auto|allow (Codex ACP allow selects agent-full-access; deny is deprecated)')
|
|
1124
1141
|
.option('--filesystem <mode>', 'common filesystem intent: read-only|workspace|unrestricted')
|
|
1125
1142
|
.option('--unattended <mode>', 'permission behavior without a console: deny|wait')
|
|
1126
|
-
.option('--sandbox <mode>', 'Codex sandbox: read-only|workspace-write|danger-full-access')
|
|
1127
|
-
.option('--profile <name>', 'Codex profile file name ($CODEX_HOME/<name>.config.toml)')
|
|
1128
|
-
.option('--launcher <mode>', 'Codex launcher: auto|ours-codex|codex (default: auto)')
|
|
1129
|
-
.option('--search', 'enable Codex live web search')
|
|
1130
|
-
.option('--codex-config <key=value>', 'Codex config override (repeatable)', collect, [])
|
|
1131
|
-
.option('--add-dir <dir>', 'additional Codex writable directory (repeatable)', collect, [])
|
|
1132
|
-
.option('--monitor', 'legacy: consent to arm Codex\'s native monitor (wake owner is monitor.mode in YAML)')
|
|
1133
|
-
.option('--bio-file <file>', 'public bio (file)')
|
|
1134
|
-
.option('--persona-file <file>', 'persona / operating contract (file)')
|
|
1135
1143
|
.option('--isolation-file <path>', 'file holding an isolation: mapping (same schema as fleet.yaml)')
|
|
1136
1144
|
.option('--dry-run', 'validate and print without reserving or creating anything')
|
|
1137
1145
|
.option('--json', 'with --dry-run, emit a stable secret-safe JSON result')
|
|
1138
1146
|
.action(async (name, opts) => {
|
|
1139
1147
|
try {
|
|
1140
|
-
const roleName = String(name ?? opts.
|
|
1148
|
+
const roleName = String(name ?? opts.name ?? '');
|
|
1141
1149
|
if (!roleName)
|
|
1142
|
-
throw new Error('
|
|
1143
|
-
if (name && opts.
|
|
1144
|
-
throw new Error(`positional
|
|
1150
|
+
throw new Error('agent name is required (positional or --name)');
|
|
1151
|
+
if (name && opts.name && name !== opts.name)
|
|
1152
|
+
throw new Error(`positional agent name conflicts with --name`);
|
|
1145
1153
|
const o = {
|
|
1146
|
-
name: roleName, temp: opts.temp,
|
|
1147
|
-
|
|
1154
|
+
name: roleName, temp: opts.temp,
|
|
1155
|
+
brain: parseAgentSelection(opts.brain, 'brain'), role: parseAgentSelection(opts.role, 'role'),
|
|
1148
1156
|
identity: opts.identity, cwd: opts.cwd, coordinator: opts.coordinator,
|
|
1149
|
-
|
|
1150
|
-
permissionMode: opts.permissionMode, approval: opts.approval,
|
|
1157
|
+
approval: opts.approval,
|
|
1151
1158
|
filesystem: opts.filesystem, unattended: opts.unattended,
|
|
1152
|
-
sandbox: opts.sandbox, profile: opts.profile,
|
|
1153
|
-
launcher: opts.launcher, search: opts.search,
|
|
1154
|
-
codexConfig: parseCodexConfig(opts.codexConfig), addDirs: opts.addDir, monitor: opts.monitor,
|
|
1155
|
-
bioFile: opts.bioFile, personaFile: opts.personaFile,
|
|
1156
1159
|
isolationFile: opts.isolationFile, configPath: opts.configuration,
|
|
1157
1160
|
dryRun: opts.dryRun, json: opts.json,
|
|
1158
1161
|
};
|
|
@@ -1181,7 +1184,7 @@ cOpt(program.command('spawn [name]').description('spawn a new agent (permanent b
|
|
|
1181
1184
|
if (proxyStateDir) {
|
|
1182
1185
|
// Paths entered in the agent shell belong to that shell's cwd, not the
|
|
1183
1186
|
// supervisor process. Normalize before crossing the control boundary.
|
|
1184
|
-
for (const key of ['
|
|
1187
|
+
for (const key of ['isolationFile']) {
|
|
1185
1188
|
if (o[key])
|
|
1186
1189
|
o[key] = resolvePath(o[key]);
|
|
1187
1190
|
}
|
|
@@ -1253,7 +1256,7 @@ program.command('init').description('one-time host setup (units, dirs, linger)')
|
|
|
1253
1256
|
mkdirSync(d, { recursive: true });
|
|
1254
1257
|
for (const m of await pickBackend().init(binPath))
|
|
1255
1258
|
console.log(m);
|
|
1256
|
-
console.log(
|
|
1259
|
+
console.log(INIT_COMPLETION_GUIDANCE);
|
|
1257
1260
|
});
|
|
1258
1261
|
const webCommand = cOpt(program.command('web').description('start or open the secure localhost fleet web console'))
|
|
1259
1262
|
.enablePositionalOptions()
|
|
@@ -1494,4 +1497,11 @@ cOpt(program.command('_run-watchdogs', { hidden: true }))
|
|
|
1494
1497
|
die(e);
|
|
1495
1498
|
}
|
|
1496
1499
|
});
|
|
1497
|
-
|
|
1500
|
+
const spawnIndex = process.argv.indexOf('spawn');
|
|
1501
|
+
if (spawnIndex >= 0 && process.argv.slice(spawnIndex + 1).some(arg => arg === '--harness' || arg.startsWith('--harness=') || arg === '--model' || arg.startsWith('--model='))) {
|
|
1502
|
+
console.error('error: --harness and --model were removed; select a Brain with --brain');
|
|
1503
|
+
process.exitCode = 1;
|
|
1504
|
+
}
|
|
1505
|
+
else {
|
|
1506
|
+
program.parseAsync(process.argv);
|
|
1507
|
+
}
|
package/dist/config.d.ts
CHANGED
|
@@ -3,7 +3,7 @@ import type { IsolationConfig, WrapContext } from './isolation/types.js';
|
|
|
3
3
|
import type { ResolvedWatchdog } from './watchdog/config.js';
|
|
4
4
|
import type { ResolvedLoop, ResolvedRoleLoop } from './loops/config.js';
|
|
5
5
|
export interface OverseeEntry {
|
|
6
|
-
|
|
6
|
+
agent: string;
|
|
7
7
|
interval: string;
|
|
8
8
|
}
|
|
9
9
|
export interface WorklogPolicy {
|
|
@@ -123,6 +123,8 @@ export interface RoleConfig {
|
|
|
123
123
|
briefing_file?: string;
|
|
124
124
|
/** Explicit null means use the selected harness's own default, bypassing fleet defaults. */
|
|
125
125
|
model?: string | null;
|
|
126
|
+
/** Neutral Brain reasoning effort, retained for inspection after adapter translation. */
|
|
127
|
+
effort?: string;
|
|
126
128
|
model_chain?: string[];
|
|
127
129
|
max_tokens?: number;
|
|
128
130
|
autocompact_pct?: number;
|
|
@@ -135,6 +137,27 @@ export interface RoleConfig {
|
|
|
135
137
|
worklog?: WorklogPolicyInput;
|
|
136
138
|
auth_proxy?: Partial<AuthProxyConfig>;
|
|
137
139
|
}
|
|
140
|
+
export type AgentSelection<T extends Record<string, unknown> = Record<string, unknown>> = {
|
|
141
|
+
ref: string;
|
|
142
|
+
} | {
|
|
143
|
+
inline: T;
|
|
144
|
+
};
|
|
145
|
+
/** Canonical authoring contract shared by configured, spawned, and room agents. */
|
|
146
|
+
export interface AgentDefinition {
|
|
147
|
+
role: AgentSelection;
|
|
148
|
+
brain: AgentSelection;
|
|
149
|
+
permissions?: Partial<CommonPermissions>;
|
|
150
|
+
identity?: string;
|
|
151
|
+
cwd?: string;
|
|
152
|
+
coordinator?: string;
|
|
153
|
+
env?: Record<string, string>;
|
|
154
|
+
oversee?: OverseeEntry[];
|
|
155
|
+
isolation?: IsolationConfig;
|
|
156
|
+
monitor?: Partial<MonitorConfig>;
|
|
157
|
+
owner_channel?: OwnerChannelConfigInput;
|
|
158
|
+
worklog?: WorklogPolicyInput;
|
|
159
|
+
auth_proxy?: Partial<AuthProxyConfig>;
|
|
160
|
+
}
|
|
138
161
|
/** Internal first-boot payload for a Fleet-provisioned Cowork room member. */
|
|
139
162
|
export interface RoomMemberStartup {
|
|
140
163
|
room_id: string;
|
|
@@ -166,14 +189,41 @@ export interface ResolvedRole extends Omit<RoleConfig, 'model' | 'owner_channel'
|
|
|
166
189
|
worklog?: WorklogPolicy;
|
|
167
190
|
auth_proxy?: AuthProxyConfig;
|
|
168
191
|
loops?: ResolvedRoleLoop[];
|
|
192
|
+
provenance?: Record<string, FieldProvenance>;
|
|
169
193
|
/** Internal/transient: never accepted as a user-authored RoleConfig key. */
|
|
170
194
|
roomMemberStartup?: RoomMemberStartup;
|
|
195
|
+
/** Original unresolved selections only; denied operational fields never enter inheritance state. */
|
|
196
|
+
agentSelections?: Pick<AgentDefinition, 'role' | 'brain'>;
|
|
197
|
+
}
|
|
198
|
+
export interface FieldProvenance {
|
|
199
|
+
sourceFile: string;
|
|
200
|
+
sourcePointer: string;
|
|
201
|
+
sourceKind: 'Agent' | 'Role' | 'Brain' | 'Manifest' | 'built-in';
|
|
202
|
+
sourceId?: string;
|
|
203
|
+
origin: 'explicit' | 'typed-default' | 'built-in';
|
|
204
|
+
viaReference?: {
|
|
205
|
+
sourcePointer: string;
|
|
206
|
+
kind: 'Role' | 'Brain';
|
|
207
|
+
id: string;
|
|
208
|
+
};
|
|
209
|
+
transforms: Array<{
|
|
210
|
+
kind: 'substitution' | 'adapter-normalization' | 'validation-default';
|
|
211
|
+
detail: string;
|
|
212
|
+
}>;
|
|
171
213
|
}
|
|
172
214
|
export interface FleetConfig {
|
|
173
215
|
roles: ResolvedRole[];
|
|
216
|
+
/** Canonical, variable-resolved Agent authoring documents keyed by stable Agent ID. */
|
|
217
|
+
agentDefinitions?: Record<string, AgentDefinition>;
|
|
174
218
|
vars: Record<string, string>;
|
|
175
219
|
defaults: Record<string, unknown>;
|
|
176
220
|
files: string[];
|
|
221
|
+
configMode?: 'split-v2';
|
|
222
|
+
sourceDocuments?: Array<{
|
|
223
|
+
kind: 'Manifest' | 'Agent' | 'Role' | 'Brain';
|
|
224
|
+
id?: string;
|
|
225
|
+
path: string;
|
|
226
|
+
}>;
|
|
177
227
|
/** Fleet-wide delay (ms) enforced between agent launches to avoid boot bursts (0 = none). */
|
|
178
228
|
startStaggerMs: number;
|
|
179
229
|
/** Warning-first non-plain YAML migration diagnostics, in source order. */
|
|
@@ -204,9 +254,22 @@ export declare function resolveRoleModel(model: string | null | undefined, harne
|
|
|
204
254
|
*/
|
|
205
255
|
export declare function isolationContextFor(role: ResolvedRole): WrapContext;
|
|
206
256
|
export declare const ROLE_NAME_RE: RegExp;
|
|
207
|
-
|
|
257
|
+
export declare const ROLE_PRESET_KEYS: string[];
|
|
258
|
+
export declare const BRAIN_PRESET_KEYS: string[];
|
|
259
|
+
export declare const AGENT_KEYS: string[];
|
|
260
|
+
type BarePreset = Record<string, unknown>;
|
|
261
|
+
export declare function validateRoleValue(value: BarePreset, file: string, pointer: string): void;
|
|
262
|
+
export declare function validateBrainValue(value: BarePreset, file: string, pointer: string): void;
|
|
263
|
+
export declare function assertBareKeys(value: unknown, allowed: string[], label: string): BarePreset;
|
|
264
|
+
export declare function splitRootFor(base: string): string;
|
|
265
|
+
/** Load a v2 manifest and bare Agent/Role/Brain documents from its stem directory. */
|
|
208
266
|
export declare function loadConfig(configPath?: string, options?: {
|
|
209
267
|
yamlMode?: YamlMode;
|
|
268
|
+
additionalAgent?: {
|
|
269
|
+
id: string;
|
|
270
|
+
definition: AgentDefinition;
|
|
271
|
+
};
|
|
272
|
+
skipWatchdogs?: boolean;
|
|
210
273
|
}): FleetConfig;
|
|
211
274
|
/**
|
|
212
275
|
* Canonical form of a 64-hex container ID for authorization decisions. Hex
|