@ours.network/fleet 1.1.0-nightly.2 → 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 +14 -22
- package/dist/application/role-creation-service.d.ts +2 -21
- package/dist/application/role-creation-service.js +15 -71
- package/dist/application/task-room-service.js +7 -2
- package/dist/briefing.js +3 -3
- package/dist/build-info.json +4 -4
- package/dist/cli.js +40 -33
- package/dist/config.d.ts +37 -0
- package/dist/config.js +40 -12
- package/dist/docs.d.ts +1 -1
- package/dist/docs.js +19 -30
- package/dist/doctor.js +3 -3
- package/dist/fleet-proxy.js +30 -8
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/dist/model-env.d.ts +2 -2
- package/dist/model-env.js +1 -1
- package/dist/owner-channel/commands.js +2 -1
- 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/spawn.d.ts +6 -31
- package/dist/spawn.js +45 -233
- 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/topology-promote.js +8 -1
- package/dist/web-app/assets/index-BbTc5KtZ.js +10 -0
- package/dist/web-app/index.html +1 -1
- package/package.json +1 -1
- package/dist/web-app/assets/index-BbE9EX6n.js +0 -10
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import { existsSync, readFileSync } from 'node:fs';
|
|
2
2
|
import { createHash } from 'node:crypto';
|
|
3
|
-
import { ROOMS_KEYS as RK, ROOMS_OWNER_KEYS as ROK, ROOMS_COWORK_KEYS as RCK, ROOMS_DEFAULTS_KEYS as RDK, TASKS_KEYS as TK, TEMPLATE_KEYS as TPK, TEMPLATE_MEMBER_KEYS as TMK,
|
|
3
|
+
import { ROOMS_KEYS as RK, ROOMS_OWNER_KEYS as ROK, ROOMS_COWORK_KEYS as RCK, ROOMS_DEFAULTS_KEYS as RDK, TASKS_KEYS as TK, TEMPLATE_KEYS as TPK, TEMPLATE_MEMBER_KEYS as TMK, } from './types.js';
|
|
4
4
|
import { BUILTIN_TEMPLATES } from './templates.js';
|
|
5
|
+
import { isSensitiveConfigKey } from '../sensitive-config.js';
|
|
5
6
|
const isPlainObject = (v) => v !== null && typeof v === 'object' && !Array.isArray(v);
|
|
6
7
|
const CID_RE = /^[0-9a-fA-F]{64}$/;
|
|
7
8
|
export class RoomsTasksConfigError extends Error {
|
|
@@ -136,19 +137,33 @@ export function validateRoomTemplatesConfig(raw, path) {
|
|
|
136
137
|
throw new RoomsTasksConfigError(path, `room_templates.${name}.members[${i}].role: required string`);
|
|
137
138
|
if (!Number.isInteger(m.count) || m.count < 1)
|
|
138
139
|
throw new RoomsTasksConfigError(path, `room_templates.${name}.members[${i}].count: required positive integer`);
|
|
139
|
-
if (!m.
|
|
140
|
-
throw new RoomsTasksConfigError(path, `room_templates.${name}.members[${i}].
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
140
|
+
if (!isPlainObject(m.agent))
|
|
141
|
+
throw new RoomsTasksConfigError(path, `room_templates.${name}.members[${i}].agent: required mapping`);
|
|
142
|
+
const agentKeys = Object.keys(m.agent);
|
|
143
|
+
const isRef = agentKeys.length === 1 && typeof m.agent.ref === 'string';
|
|
144
|
+
const isDefinition = agentKeys.includes('role') && agentKeys.includes('brain');
|
|
145
|
+
if (!isRef && !isDefinition)
|
|
146
|
+
throw new RoomsTasksConfigError(path, `room_templates.${name}.members[${i}].agent: must be {ref} or canonical {role, brain, ...}`);
|
|
147
|
+
const containsSensitive = (value) => Array.isArray(value)
|
|
148
|
+
? value.some(containsSensitive)
|
|
149
|
+
: Boolean(value && typeof value === 'object' && Object.entries(value)
|
|
150
|
+
.some(([key, child]) => isSensitiveConfigKey(key) || containsSensitive(child)));
|
|
151
|
+
if (isDefinition && containsSensitive(m.agent))
|
|
152
|
+
throw new RoomsTasksConfigError(path, `room_templates.${name}.members[${i}].agent: inline sensitive configuration cannot be persisted; use references`);
|
|
153
|
+
if (isDefinition) {
|
|
154
|
+
const definition = m.agent;
|
|
155
|
+
const brain = isPlainObject(definition.brain) && isPlainObject(definition.brain.inline)
|
|
156
|
+
? definition.brain.inline : undefined;
|
|
157
|
+
if (definition.env !== undefined || definition.owner_channel !== undefined
|
|
158
|
+
|| definition.auth_proxy !== undefined || brain?.harness_options !== undefined
|
|
159
|
+
|| brain?.session_options !== undefined)
|
|
160
|
+
throw new RoomsTasksConfigError(path, `room_templates.${name}.members[${i}].agent: secret-capable inline fields cannot be persisted; use references`);
|
|
145
161
|
}
|
|
146
162
|
return {
|
|
147
163
|
slot: m.slot,
|
|
148
164
|
role: m.role,
|
|
149
165
|
count: m.count,
|
|
150
|
-
|
|
151
|
-
overrides: m.overrides,
|
|
166
|
+
agent: structuredClone(m.agent),
|
|
152
167
|
};
|
|
153
168
|
});
|
|
154
169
|
let room;
|
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import { randomUUID } from 'node:crypto';
|
|
2
|
-
import { existsSync, readFileSync, realpathSync } from 'node:fs';
|
|
1
|
+
import { createHash, randomUUID } from 'node:crypto';
|
|
2
|
+
import { existsSync, readFileSync, realpathSync, statSync } from 'node:fs';
|
|
3
3
|
import { parse } from 'yaml';
|
|
4
4
|
import { advanceSaga, setSagaError, updateMemberSeats, updateMemberStartup, activateRoom, getRoomRecord, } from './room-state.js';
|
|
5
5
|
import { activateTask, updateTaskMembers, blockTask, unblockTask, getTask, } from './task-state.js';
|
|
6
6
|
import { spawnTemp } from '../spawn.js';
|
|
7
|
-
import { findRole } from '../config.js';
|
|
7
|
+
import { findRole, loadConfig } from '../config.js';
|
|
8
8
|
import { FLEET_PROXY_CALLER_ENV, FLEET_PROXY_STATE_DIR_ENV, } from '../fleet-proxy.js';
|
|
9
9
|
import { controlRequest } from '../session/control.js';
|
|
10
10
|
import { SessionControlError } from '../session/types.js';
|
|
@@ -21,6 +21,26 @@ export function getBinPath() {
|
|
|
21
21
|
return process.argv[1];
|
|
22
22
|
}
|
|
23
23
|
}
|
|
24
|
+
function canonicalJson(value) {
|
|
25
|
+
if (Array.isArray(value))
|
|
26
|
+
return `[${value.map(canonicalJson).join(',')}]`;
|
|
27
|
+
if (value && typeof value === 'object')
|
|
28
|
+
return `{${Object.entries(value)
|
|
29
|
+
.sort(([a], [b]) => a.localeCompare(b))
|
|
30
|
+
.map(([key, item]) => `${JSON.stringify(key)}:${canonicalJson(item)}`).join(',')}}`;
|
|
31
|
+
return JSON.stringify(value);
|
|
32
|
+
}
|
|
33
|
+
function launchDefinition(definition) {
|
|
34
|
+
const selectionEvidence = (selection) => 'ref' in selection ? { kind: 'ref', id: selection.ref } : { kind: 'inline' };
|
|
35
|
+
return {
|
|
36
|
+
projection: {
|
|
37
|
+
brain: selectionEvidence(definition.brain), role: selectionEvidence(definition.role),
|
|
38
|
+
operationalFields: Object.keys(definition)
|
|
39
|
+
.filter(key => key !== 'brain' && key !== 'role').sort(),
|
|
40
|
+
},
|
|
41
|
+
fingerprint: createHash('sha256').update(canonicalJson(definition)).digest('hex'),
|
|
42
|
+
};
|
|
43
|
+
}
|
|
24
44
|
async function spawnRoomMember(options, binPath) {
|
|
25
45
|
const stateDir = process.env[FLEET_PROXY_STATE_DIR_ENV];
|
|
26
46
|
if (!stateDir)
|
|
@@ -52,28 +72,31 @@ function expandMembers(template, prefix) {
|
|
|
52
72
|
name: `${prefix}-${slot.slot}-${i}`,
|
|
53
73
|
slot: slot.slot,
|
|
54
74
|
coworkRole: slot.role,
|
|
55
|
-
|
|
56
|
-
overrides: slot.overrides,
|
|
75
|
+
agent: structuredClone(slot.agent),
|
|
57
76
|
});
|
|
58
77
|
}
|
|
59
78
|
}
|
|
60
79
|
return result;
|
|
61
80
|
}
|
|
62
81
|
function settingsFor(member, cfg) {
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
82
|
+
if (!('ref' in member.agent)) {
|
|
83
|
+
const role = member.agent.role;
|
|
84
|
+
if (cfg.files[0] && existsSync(cfg.files[0]) && statSync(cfg.files[0]).isFile())
|
|
85
|
+
loadConfig(cfg.files[0], { additionalAgent: {
|
|
86
|
+
id: `RoomPreflight${member.name.replace(/[^A-Za-z0-9_-]/g, '')}`.slice(0, 64),
|
|
87
|
+
definition: member.agent,
|
|
88
|
+
} });
|
|
89
|
+
return { definition: structuredClone(member.agent),
|
|
90
|
+
...('inline' in role && typeof role.inline.persona === 'string'
|
|
91
|
+
? { persona: role.inline.persona } : {}) };
|
|
66
92
|
}
|
|
67
|
-
|
|
68
|
-
const
|
|
93
|
+
const refRole = findRole(cfg, member.agent.ref);
|
|
94
|
+
const definition = cfg.agentDefinitions?.[member.agent.ref];
|
|
95
|
+
if (!definition)
|
|
96
|
+
throw new Error(`Agent '${member.agent.ref}' has no canonical definition`);
|
|
69
97
|
return {
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
cwd: member.overrides?.cwd ?? refRole?.cwd,
|
|
73
|
-
persona: member.overrides?.persona ?? refRole?.persona,
|
|
74
|
-
approval: permissions?.approval,
|
|
75
|
-
filesystem: permissions?.filesystem,
|
|
76
|
-
unattended: permissions?.unattended,
|
|
98
|
+
definition: structuredClone(definition),
|
|
99
|
+
persona: refRole.persona,
|
|
77
100
|
};
|
|
78
101
|
}
|
|
79
102
|
function roomTask(input, member, settings, members, roomIdentityCid, ownerSeatCid) {
|
|
@@ -104,13 +127,11 @@ function launchMatches(dir, member, actionId, taskSha, roomId, roomIdentityCid,
|
|
|
104
127
|
const role = parse(readFileSync(`${dir}/role.yaml`, 'utf8'));
|
|
105
128
|
const startup = role.roomMemberStartup;
|
|
106
129
|
return role.identity === member.name
|
|
107
|
-
&& typeof role.mission === 'string'
|
|
108
|
-
&& sha256Text(role.mission) === taskSha
|
|
109
130
|
&& startup?.room_id === roomId
|
|
110
131
|
&& startup.room_identity_cid === roomIdentityCid
|
|
111
132
|
&& startup.identity_name === member.name
|
|
112
133
|
&& startup.role === member.coworkRole
|
|
113
|
-
&& startup.task ===
|
|
134
|
+
&& sha256Text(startup.task ?? '') === taskSha
|
|
114
135
|
&& (expectedInviteId === undefined || startup.invite_id === expectedInviteId)
|
|
115
136
|
&& typeof startup.invite === 'string'
|
|
116
137
|
&& startup.invite.length > 0;
|
|
@@ -199,10 +220,13 @@ async function launchMember(input) {
|
|
|
199
220
|
let effectiveActionId = actionId;
|
|
200
221
|
const attempt = (seat.launch?.attempt ?? 0) + 1;
|
|
201
222
|
const taskSha = sha256Text(startup.task);
|
|
223
|
+
const effectiveAgentDefinition = structuredClone(settings.definition);
|
|
224
|
+
const { projection: agentDefinition, fingerprint: agentFingerprint } = launchDefinition(effectiveAgentDefinition);
|
|
202
225
|
const proxyCaller = process.env[FLEET_PROXY_STATE_DIR_ENV]
|
|
203
226
|
? process.env[FLEET_PROXY_CALLER_ENV] : undefined;
|
|
204
227
|
updateMemberStartup(provision.roomId, member.name, { launch: {
|
|
205
228
|
state: 'intent', attempt, action_id: actionId, mission_sha256: taskSha,
|
|
229
|
+
agent_definition: agentDefinition, agent_fingerprint: agentFingerprint,
|
|
206
230
|
...(proxyCaller ? { caller_role: proxyCaller } : {}),
|
|
207
231
|
updated_at: new Date().toISOString(),
|
|
208
232
|
} });
|
|
@@ -211,13 +235,7 @@ async function launchMember(input) {
|
|
|
211
235
|
name: member.name,
|
|
212
236
|
temp: true,
|
|
213
237
|
identity: member.name,
|
|
214
|
-
|
|
215
|
-
model: settings.model,
|
|
216
|
-
harness: settings.harness,
|
|
217
|
-
cwd: settings.cwd,
|
|
218
|
-
approval: settings.approval,
|
|
219
|
-
filesystem: settings.filesystem,
|
|
220
|
-
unattended: settings.unattended,
|
|
238
|
+
agentDefinition: settings.definition,
|
|
221
239
|
surface: 'agent',
|
|
222
240
|
creationActionId: actionId,
|
|
223
241
|
roomMemberStartup: startup,
|
|
@@ -227,7 +245,8 @@ async function launchMember(input) {
|
|
|
227
245
|
if (launched.creationActionId !== actionId) {
|
|
228
246
|
updateMemberStartup(provision.roomId, member.name, { launch: {
|
|
229
247
|
state: 'intent', attempt, action_id: launched.creationActionId,
|
|
230
|
-
mission_sha256: taskSha,
|
|
248
|
+
mission_sha256: taskSha, agent_definition: agentDefinition,
|
|
249
|
+
agent_fingerprint: agentFingerprint, updated_at: new Date().toISOString(),
|
|
231
250
|
...(launched.callerRole ? { caller_role: launched.callerRole } : {}),
|
|
232
251
|
} });
|
|
233
252
|
}
|
|
@@ -237,6 +256,7 @@ async function launchMember(input) {
|
|
|
237
256
|
}
|
|
238
257
|
updateMemberStartup(provision.roomId, member.name, { launch: {
|
|
239
258
|
state: 'launched', attempt, action_id: launched.creationActionId, mission_sha256: taskSha,
|
|
259
|
+
agent_definition: agentDefinition, agent_fingerprint: agentFingerprint,
|
|
240
260
|
...(launched.callerRole ? { caller_role: launched.callerRole } : {}),
|
|
241
261
|
launch_id: supervisor.launchId, updated_at: new Date().toISOString(),
|
|
242
262
|
} });
|
|
@@ -244,6 +264,7 @@ async function launchMember(input) {
|
|
|
244
264
|
catch (error) {
|
|
245
265
|
updateMemberStartup(provision.roomId, member.name, { launch: {
|
|
246
266
|
state: 'failed', attempt, action_id: effectiveActionId, mission_sha256: taskSha,
|
|
267
|
+
agent_definition: agentDefinition, agent_fingerprint: agentFingerprint,
|
|
247
268
|
...(proxyCaller ? { caller_role: proxyCaller } : {}),
|
|
248
269
|
updated_at: new Date().toISOString(),
|
|
249
270
|
error: error instanceof Error ? error.message : String(error),
|
|
@@ -289,6 +310,8 @@ export async function provisionMembers(input) {
|
|
|
289
310
|
const { cfg, cowork, roomId, taskId, template } = input;
|
|
290
311
|
const prefix = taskId ? shortId(taskId) : `room-${shortId(roomId)}`;
|
|
291
312
|
const members = expandMembers(template, prefix);
|
|
313
|
+
// Resolve every Agent before persisting launch intent or touching Cowork membership.
|
|
314
|
+
const settings = new Map(members.map(member => [member.name, settingsFor(member, cfg)]));
|
|
292
315
|
const existing = getRoomRecord(roomId);
|
|
293
316
|
if (!existing?.room_identity_cid)
|
|
294
317
|
throw new Error(`room ${roomId} has no pinned room identity CID`);
|
|
@@ -299,15 +322,27 @@ export async function provisionMembers(input) {
|
|
|
299
322
|
&& members.every(member => persistedNames.has(member.name));
|
|
300
323
|
if (!resuming) {
|
|
301
324
|
advanceSaga(roomId, 'create_members', 3);
|
|
302
|
-
updateMemberSeats(roomId, members.map(member =>
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
325
|
+
updateMemberSeats(roomId, members.map(member => {
|
|
326
|
+
const evidence = launchDefinition(settings.get(member.name).definition);
|
|
327
|
+
return ({
|
|
328
|
+
role_name: member.name,
|
|
329
|
+
slot: member.slot,
|
|
330
|
+
cowork_role: member.coworkRole,
|
|
331
|
+
seat_state: 'pending',
|
|
332
|
+
launch: { state: 'pending', attempt: 0,
|
|
333
|
+
agent_definition: evidence.projection, agent_fingerprint: evidence.fingerprint,
|
|
334
|
+
updated_at: new Date().toISOString() },
|
|
335
|
+
});
|
|
336
|
+
}));
|
|
337
|
+
}
|
|
338
|
+
else {
|
|
339
|
+
for (const member of members) {
|
|
340
|
+
const seat = existing.member_seats.find(candidate => candidate.role_name === member.name);
|
|
341
|
+
const evidence = launchDefinition(settings.get(member.name).definition);
|
|
342
|
+
if (!seat.launch?.agent_fingerprint || seat.launch.agent_fingerprint !== evidence.fingerprint)
|
|
343
|
+
throw new Error(`Agent definition drift for ${member.name}; durable launch intent does not match current configuration`);
|
|
344
|
+
}
|
|
309
345
|
}
|
|
310
|
-
const settings = new Map(members.map(member => [member.name, settingsFor(member, cfg)]));
|
|
311
346
|
const tasks = new Map(members.map(member => [member.name, roomTask(input, member, settings.get(member.name), members, roomIdentityCid, ownerSeatCid)]));
|
|
312
347
|
const policy = {
|
|
313
348
|
timeoutMs: input.startupWait?.timeoutMs ?? 60_000,
|
|
@@ -12,9 +12,9 @@ const TEAM = {
|
|
|
12
12
|
'Completion requires tester sign-off.',
|
|
13
13
|
].join('\n'),
|
|
14
14
|
members: [
|
|
15
|
-
{ slot: 'architect', role: 'Architect', count: 1,
|
|
16
|
-
{ slot: 'developer', role: 'Developer', count: 1,
|
|
17
|
-
{ slot: 'tester', role: 'Tester', count: 1,
|
|
15
|
+
{ slot: 'architect', role: 'Architect', count: 1, agent: { ref: 'Architect' } },
|
|
16
|
+
{ slot: 'developer', role: 'Developer', count: 1, agent: { ref: 'Developer' } },
|
|
17
|
+
{ slot: 'tester', role: 'Tester', count: 1, agent: { ref: 'Tester' } },
|
|
18
18
|
],
|
|
19
19
|
};
|
|
20
20
|
const PAIR = {
|
|
@@ -30,8 +30,8 @@ const PAIR = {
|
|
|
30
30
|
'Completion requires joint sign-off.',
|
|
31
31
|
].join('\n'),
|
|
32
32
|
members: [
|
|
33
|
-
{ slot: 'secretary', role: 'Secretary', count: 1,
|
|
34
|
-
{ slot: 'critic', role: 'Critic', count: 1,
|
|
33
|
+
{ slot: 'secretary', role: 'Secretary', count: 1, agent: { ref: 'Secretary' } },
|
|
34
|
+
{ slot: 'critic', role: 'Critic', count: 1, agent: { ref: 'Critic' } },
|
|
35
35
|
],
|
|
36
36
|
};
|
|
37
37
|
const SINGLE = {
|
|
@@ -45,7 +45,7 @@ const SINGLE = {
|
|
|
45
45
|
'Owner reviews and approves completion.',
|
|
46
46
|
].join('\n'),
|
|
47
47
|
members: [
|
|
48
|
-
{ slot: 'agent', role: 'Agent', count: 1,
|
|
48
|
+
{ slot: 'agent', role: 'Agent', count: 1, agent: { ref: 'Agent' } },
|
|
49
49
|
],
|
|
50
50
|
};
|
|
51
51
|
export const BUILTIN_TEMPLATES = [TEAM, PAIR, SINGLE];
|
|
@@ -100,6 +100,9 @@ export interface RoomMemberLaunchState {
|
|
|
100
100
|
/** Expected authenticated proxy caller while adopting a post-spawn crash. */
|
|
101
101
|
caller_role?: string;
|
|
102
102
|
mission_sha256?: string;
|
|
103
|
+
/** Redacted, deterministic effective Agent launch definition retained for retry inspection. */
|
|
104
|
+
agent_definition?: Record<string, unknown>;
|
|
105
|
+
agent_fingerprint?: string;
|
|
103
106
|
launch_id?: string;
|
|
104
107
|
updated_at: string;
|
|
105
108
|
error?: string;
|
|
@@ -189,19 +192,10 @@ export interface TemplateMemberSlot {
|
|
|
189
192
|
slot: string;
|
|
190
193
|
role: string;
|
|
191
194
|
count: number;
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
harness?: string;
|
|
197
|
-
model?: string;
|
|
198
|
-
model_chain?: string[];
|
|
199
|
-
permissions?: Record<string, unknown>;
|
|
200
|
-
isolation?: Record<string, unknown>;
|
|
201
|
-
cwd?: string;
|
|
202
|
-
env?: Record<string, string>;
|
|
203
|
-
persona?: string;
|
|
204
|
-
mission?: string;
|
|
195
|
+
/** Canonical Agent definition, or stable reference to a declared Agent. */
|
|
196
|
+
agent: import('../config.js').AgentDefinition | {
|
|
197
|
+
ref: string;
|
|
198
|
+
};
|
|
205
199
|
}
|
|
206
200
|
export interface TemplateRoomConfig {
|
|
207
201
|
quiet_membership?: boolean;
|
|
@@ -252,5 +246,4 @@ export declare const ROOMS_COWORK_KEYS: readonly ["config"];
|
|
|
252
246
|
export declare const ROOMS_DEFAULTS_KEYS: readonly ["template", "attach_owner", "close_when_task_done"];
|
|
253
247
|
export declare const TASKS_KEYS: readonly ["default_room_template", "create_mode", "close_room_on_done", "retain_completed_for"];
|
|
254
248
|
export declare const TEMPLATE_KEYS: readonly ["version", "description", "room", "contract", "members", "override_builtin"];
|
|
255
|
-
export declare const TEMPLATE_MEMBER_KEYS: readonly ["slot", "role", "count", "
|
|
256
|
-
export declare const TEMPLATE_OVERRIDE_KEYS: readonly ["harness", "model", "model_chain", "permissions", "isolation", "cwd", "env", "persona", "mission"];
|
|
249
|
+
export declare const TEMPLATE_MEMBER_KEYS: readonly ["slot", "role", "count", "agent"];
|
|
@@ -14,7 +14,4 @@ export const ROOMS_COWORK_KEYS = ['config'];
|
|
|
14
14
|
export const ROOMS_DEFAULTS_KEYS = ['template', 'attach_owner', 'close_when_task_done'];
|
|
15
15
|
export const TASKS_KEYS = ['default_room_template', 'create_mode', 'close_room_on_done', 'retain_completed_for'];
|
|
16
16
|
export const TEMPLATE_KEYS = ['version', 'description', 'room', 'contract', 'members', 'override_builtin'];
|
|
17
|
-
export const TEMPLATE_MEMBER_KEYS = ['slot', 'role', 'count', '
|
|
18
|
-
export const TEMPLATE_OVERRIDE_KEYS = [
|
|
19
|
-
'harness', 'model', 'model_chain', 'permissions', 'isolation', 'cwd', 'env', 'persona', 'mission',
|
|
20
|
-
];
|
|
17
|
+
export const TEMPLATE_MEMBER_KEYS = ['slot', 'role', 'count', 'agent'];
|
package/dist/spawn.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { IsolationConfig } from './isolation/types.js';
|
|
2
|
-
import { type ApprovalMode, type FilesystemMode, type ResolvedRole, type
|
|
2
|
+
import { type ApprovalMode, type FilesystemMode, type ResolvedRole, type MonitorConfig, type UnattendedMode, type RoomMemberStartup, type AgentDefinition, type AgentSelection } from './config.js';
|
|
3
3
|
import { type OpsDeps } from './ops.js';
|
|
4
4
|
import { type CreationDeps, type CreationProvenance } from './creation.js';
|
|
5
5
|
import './harness/claude-code.js';
|
|
@@ -13,34 +13,18 @@ export declare let lastProvenance: CreationProvenance | undefined;
|
|
|
13
13
|
export interface SpawnOpts {
|
|
14
14
|
name: string;
|
|
15
15
|
temp?: boolean;
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
16
|
+
brain?: AgentSelection;
|
|
17
|
+
role?: AgentSelection;
|
|
18
|
+
/** Trusted canonical definition used by room provisioning; never a second schema. */
|
|
19
|
+
agentDefinition?: AgentDefinition;
|
|
20
20
|
identity?: string;
|
|
21
21
|
cwd?: string;
|
|
22
22
|
coordinator?: string;
|
|
23
|
-
/** null explicitly selects the harness default; undefined retains normal fleet inheritance. */
|
|
24
|
-
model?: string | null;
|
|
25
|
-
permissionMode?: string;
|
|
26
23
|
approval?: ApprovalMode;
|
|
27
24
|
filesystem?: FilesystemMode;
|
|
28
25
|
unattended?: UnattendedMode;
|
|
29
|
-
sandbox?: string;
|
|
30
|
-
profile?: string;
|
|
31
|
-
launcher?: string;
|
|
32
|
-
search?: boolean;
|
|
33
|
-
codexConfig?: Record<string, string | number | boolean>;
|
|
34
|
-
reasoningEffort?: string | null;
|
|
35
|
-
addDirs?: string[];
|
|
36
|
-
monitor?: boolean;
|
|
37
26
|
/** Typed external monitor configuration used by trusted creation surfaces. */
|
|
38
27
|
monitorConfig?: Partial<MonitorConfig>;
|
|
39
|
-
bioFile?: string;
|
|
40
|
-
personaFile?: string;
|
|
41
|
-
/** Inline profile values for trusted typed callers such as the local web service. */
|
|
42
|
-
bio?: string;
|
|
43
|
-
persona?: string;
|
|
44
28
|
/** Internal, non-sensitive provenance correlation for typed presentation layers. */
|
|
45
29
|
surface?: 'cli' | 'web' | 'agent';
|
|
46
30
|
creationActionId?: string;
|
|
@@ -61,12 +45,7 @@ export interface SpawnOpts {
|
|
|
61
45
|
dryRun?: boolean;
|
|
62
46
|
json?: boolean;
|
|
63
47
|
}
|
|
64
|
-
export declare function
|
|
65
|
-
bio?: string;
|
|
66
|
-
persona?: string;
|
|
67
|
-
};
|
|
68
|
-
/** Pure option-to-role mapping shared by CLI and application services. */
|
|
69
|
-
export declare function buildRoleConfig(o: SpawnOpts, defaultHarness?: string): RoleConfig;
|
|
48
|
+
export declare function agentDefinitionFromSpawn(o: SpawnOpts): AgentDefinition;
|
|
70
49
|
/**
|
|
71
50
|
* Read and validate an `--isolation-file`. The file is the existing
|
|
72
51
|
* `isolation:` mapping and nothing else — the same schema, the same validator
|
|
@@ -78,8 +57,6 @@ export declare function buildRoleConfig(o: SpawnOpts, defaultHarness?: string):
|
|
|
78
57
|
*/
|
|
79
58
|
export declare function readIsolationFile(path: string): IsolationConfig;
|
|
80
59
|
export declare function validateSpawnOpts(o: SpawnOpts): void;
|
|
81
|
-
/** Read mission text without trimming or newline rewriting. */
|
|
82
|
-
export declare function readMissionFile(path: string): string;
|
|
83
60
|
/** The ours identity a spawn will bind: explicit, else the role name. */
|
|
84
61
|
export declare const effectiveIdentity: (o: SpawnOpts) => string;
|
|
85
62
|
export interface SpawnDryRun {
|
|
@@ -88,8 +65,6 @@ export interface SpawnDryRun {
|
|
|
88
65
|
roleDocument: Record<string, unknown>;
|
|
89
66
|
resolvedRole: ResolvedRole;
|
|
90
67
|
}
|
|
91
|
-
/** Bare Agent document written by v2 spawn: inline Role × inline Brain + operations. */
|
|
92
|
-
export declare function buildAgentDocument(raw: RoleConfig): Record<string, unknown>;
|
|
93
68
|
/**
|
|
94
69
|
* Validate and resolve a spawn without reserving names, contacting the daemon,
|
|
95
70
|
* or writing state. Collision checks are necessarily a point-in-time snapshot.
|