@ours.network/fleet 0.19.0-nightly.1 → 0.19.0-nightly.2
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 +4 -4
- package/dist/cli.js +5 -0
- package/dist/config.d.ts +5 -0
- package/dist/config.js +32 -2
- package/dist/owner-channel/commands.js +89 -0
- package/dist/rooms-tasks/cli.d.ts +4 -0
- package/dist/rooms-tasks/cli.js +565 -0
- package/dist/rooms-tasks/config.d.ts +15 -0
- package/dist/rooms-tasks/config.js +171 -0
- package/dist/rooms-tasks/cowork-adapter.d.ts +80 -0
- package/dist/rooms-tasks/cowork-adapter.js +48 -0
- package/dist/rooms-tasks/index.d.ts +7 -0
- package/dist/rooms-tasks/index.js +7 -0
- package/dist/rooms-tasks/room-state.d.ts +22 -0
- package/dist/rooms-tasks/room-state.js +117 -0
- package/dist/rooms-tasks/task-state.d.ts +31 -0
- package/dist/rooms-tasks/task-state.js +173 -0
- package/dist/rooms-tasks/templates.d.ts +6 -0
- package/dist/rooms-tasks/templates.js +80 -0
- package/dist/rooms-tasks/types.d.ts +153 -0
- package/dist/rooms-tasks/types.js +20 -0
- package/package.json +1 -1
package/dist/build-info.json
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
{
|
|
2
|
-
"version": "0.19.0-nightly.
|
|
3
|
-
"buildId": "
|
|
4
|
-
"commit": "
|
|
2
|
+
"version": "0.19.0-nightly.2",
|
|
3
|
+
"buildId": "13880d55bd06",
|
|
4
|
+
"commit": "ccf83082de238e6dc8ddb1bc557d2b7ffc7e816f",
|
|
5
5
|
"dirty": true,
|
|
6
|
-
"builtAt": "2026-08-
|
|
6
|
+
"builtAt": "2026-08-23T08:33:08.792Z",
|
|
7
7
|
"capabilities": [
|
|
8
8
|
"monitor.interrupt.after_tool"
|
|
9
9
|
]
|
package/dist/cli.js
CHANGED
|
@@ -37,6 +37,7 @@ import { WebAccessStore, passwordAccess, validatePublicOrigin } from './web/acce
|
|
|
37
37
|
import { FLEET_PROXY_CALLER_ENV, FLEET_PROXY_STATE_DIR_ENV, } from './fleet-proxy.js';
|
|
38
38
|
import './harness/claude-code.js'; // registers the claude-code adapter
|
|
39
39
|
import './harness/codex.js'; // registers the codex adapter
|
|
40
|
+
import { registerTemplateCommands, registerTaskCommands, registerRoomCommands } from './rooms-tasks/cli.js';
|
|
40
41
|
// sudo/su shells lack XDG_RUNTIME_DIR, breaking every systemctl/journalctl
|
|
41
42
|
// --user child (supervisor commands, logs, doctor). Derive it before dispatch. (#9)
|
|
42
43
|
deriveXdgRuntimeDir();
|
|
@@ -1403,6 +1404,10 @@ function configureWebAccess(opts) {
|
|
|
1403
1404
|
+ 'or --pairing for protection, or --no-password only for intentional unprotected access');
|
|
1404
1405
|
return undefined;
|
|
1405
1406
|
}
|
|
1407
|
+
// ── rooms & tasks ──────────────────────────────────────────────────────────
|
|
1408
|
+
registerTemplateCommands(program, cOpt);
|
|
1409
|
+
registerTaskCommands(program, cOpt);
|
|
1410
|
+
registerRoomCommands(program, cOpt);
|
|
1406
1411
|
program.command('_run <name>', { hidden: true }).description('internal: supervisor entrypoint')
|
|
1407
1412
|
.option('-c, --configuration <file>')
|
|
1408
1413
|
.action(async (name, opts) => {
|
package/dist/config.d.ts
CHANGED
|
@@ -165,6 +165,11 @@ export interface FleetConfig {
|
|
|
165
165
|
diagnostics: ConfigDiagnostic[];
|
|
166
166
|
watchdogs: ResolvedWatchdog[];
|
|
167
167
|
loops: ResolvedLoop[];
|
|
168
|
+
rooms?: import('./rooms-tasks/types.js').RoomsConfig;
|
|
169
|
+
roomTemplates?: import('./rooms-tasks/types.js').RoomTemplatesConfig;
|
|
170
|
+
tasks?: import('./rooms-tasks/types.js').TasksConfig;
|
|
171
|
+
/** SHA-256 fingerprint of the resolved owner invite (never the invite itself). */
|
|
172
|
+
ownerInviteFingerprint?: string;
|
|
168
173
|
}
|
|
169
174
|
export declare class ConfigError extends Error {
|
|
170
175
|
}
|
package/dist/config.js
CHANGED
|
@@ -6,6 +6,7 @@ import { harnessRuntimeDir, resolveIsolation, validateIsolationConfig, } from '.
|
|
|
6
6
|
import { getAdapter } from './harness/registry.js';
|
|
7
7
|
import { resolveWatchdogs } from './watchdog/config.js';
|
|
8
8
|
import { resolveLoops } from './loops/config.js';
|
|
9
|
+
import { validateRoomsConfig, validateTasksConfig, validateRoomTemplatesConfig, } from './rooms-tasks/config.js';
|
|
9
10
|
import { CAPABILITIES, CAP_MONITOR_INTERRUPT_AFTER_TOOL } from './capabilities.js';
|
|
10
11
|
import { runningLabel } from './provenance.js';
|
|
11
12
|
/** The 8 content-free event types the ours daemon appends to notifications.log. */
|
|
@@ -164,9 +165,10 @@ export function loadConfig(configPath, options = {}) {
|
|
|
164
165
|
const parsed = parseFleetDocument(p, readFileSync(p, 'utf8'), options.yamlMode);
|
|
165
166
|
const doc = parsed.value;
|
|
166
167
|
diagnostics.push(...parsed.diagnostics);
|
|
167
|
-
const
|
|
168
|
+
const FLEET_D_ALLOWED = ['roles', 'rooms', 'room_templates', 'tasks'];
|
|
169
|
+
const extra = Object.keys(doc).filter(k => !FLEET_D_ALLOWED.includes(k));
|
|
168
170
|
if (extra.length)
|
|
169
|
-
throw new ConfigError(`${p}: fleet.d files may only define
|
|
171
|
+
throw new ConfigError(`${p}: fleet.d files may only define ${FLEET_D_ALLOWED.join(', ')}: (found: ${extra.join(', ')})`);
|
|
170
172
|
docs.push({ file: p, doc });
|
|
171
173
|
files.push(p);
|
|
172
174
|
}
|
|
@@ -268,9 +270,37 @@ export function loadConfig(configPath, options = {}) {
|
|
|
268
270
|
const resolvedLoops = resolveLoops(baseDoc.loops, base, roles, vars);
|
|
269
271
|
for (const role of roles)
|
|
270
272
|
role.loops = resolvedLoops.byRole.get(role.name) ?? [];
|
|
273
|
+
// ── Rooms, room_templates, tasks (split-config merge) ──────────────
|
|
274
|
+
// These sections may appear in the base fleet.yaml and/or in fleet.d files.
|
|
275
|
+
// Base provides defaults; fleet.d extends. Only one source may define rooms/tasks
|
|
276
|
+
// top-level (room_templates merge by name, last writer wins).
|
|
277
|
+
let rooms;
|
|
278
|
+
let ownerInviteFingerprint;
|
|
279
|
+
let roomTemplates;
|
|
280
|
+
let tasks;
|
|
281
|
+
for (const { file, doc } of docs) {
|
|
282
|
+
if (doc.rooms !== undefined) {
|
|
283
|
+
if (rooms)
|
|
284
|
+
throw new ConfigError(`rooms: defined in multiple files; last: ${file}`);
|
|
285
|
+
const validated = validateRoomsConfig(deepSub(doc.rooms, vars), vars, file);
|
|
286
|
+
ownerInviteFingerprint = validated._invite?.fingerprint;
|
|
287
|
+
const { _invite: _, ...clean } = validated;
|
|
288
|
+
rooms = clean;
|
|
289
|
+
}
|
|
290
|
+
if (doc.room_templates !== undefined) {
|
|
291
|
+
const validated = validateRoomTemplatesConfig(deepSub(doc.room_templates, vars), file);
|
|
292
|
+
roomTemplates = { ...(roomTemplates ?? {}), ...validated };
|
|
293
|
+
}
|
|
294
|
+
if (doc.tasks !== undefined) {
|
|
295
|
+
if (tasks)
|
|
296
|
+
throw new ConfigError(`tasks: defined in multiple files; last: ${file}`);
|
|
297
|
+
tasks = validateTasksConfig(deepSub(doc.tasks, vars), file);
|
|
298
|
+
}
|
|
299
|
+
}
|
|
271
300
|
return {
|
|
272
301
|
roles, vars, defaults, files, startStaggerMs, diagnostics, watchdogs,
|
|
273
302
|
loops: resolvedLoops.loops,
|
|
303
|
+
rooms, roomTemplates, tasks, ownerInviteFingerprint,
|
|
274
304
|
};
|
|
275
305
|
}
|
|
276
306
|
/**
|
|
@@ -142,6 +142,95 @@ export const ownerCommands = [
|
|
|
142
142
|
name: 'version', summary: 'report the fleet version',
|
|
143
143
|
execute: noArgs('/version', async (ctx) => ctx.reply(`ℹ️ ours-fleet ${ctx.version}`)),
|
|
144
144
|
},
|
|
145
|
+
{
|
|
146
|
+
name: 'tasks', usage: '/tasks [state]',
|
|
147
|
+
summary: 'list tasks (optionally filter by state)',
|
|
148
|
+
execute: async (ctx, args) => {
|
|
149
|
+
const { listTasks } = await import('../rooms-tasks/task-state.js');
|
|
150
|
+
const stateFilter = args?.trim() || undefined;
|
|
151
|
+
const tasks = listTasks(stateFilter && stateFilter !== 'all' ? { state: stateFilter } : undefined);
|
|
152
|
+
if (!tasks.length)
|
|
153
|
+
return ctx.reply('📋 No tasks.');
|
|
154
|
+
const lines = tasks.map(t => {
|
|
155
|
+
const blocked = t.blocked ? ` [BLOCKED: ${t.blocked.reason}]` : '';
|
|
156
|
+
return `${t.task_id} ${t.state}${blocked} ${t.title}`;
|
|
157
|
+
});
|
|
158
|
+
await ctx.reply(tail(`📋 Tasks:\n${lines.join('\n')}`, REPLY_MAX_CHARS));
|
|
159
|
+
},
|
|
160
|
+
},
|
|
161
|
+
{
|
|
162
|
+
name: 'task', usage: '/task <id>',
|
|
163
|
+
summary: 'show task details',
|
|
164
|
+
execute: async (ctx, args) => {
|
|
165
|
+
if (!args)
|
|
166
|
+
throw new OwnerCommandUsageError('usage: /task <id>');
|
|
167
|
+
const { getTask } = await import('../rooms-tasks/task-state.js');
|
|
168
|
+
try {
|
|
169
|
+
const t = getTask(args.trim());
|
|
170
|
+
const lines = [
|
|
171
|
+
`📋 Task: ${t.task_id}`,
|
|
172
|
+
`Title: ${t.title}`,
|
|
173
|
+
`State: ${t.state}${t.blocked ? ` [BLOCKED: ${t.blocked.reason}]` : ''}`,
|
|
174
|
+
...(t.template ? [`Template: ${t.template.name}@${t.template.version}`] : []),
|
|
175
|
+
...(t.room_id ? [`Room: ${t.room_id}`] : []),
|
|
176
|
+
`Origin: ${t.origin.type}`,
|
|
177
|
+
`Created: ${t.created_at}`,
|
|
178
|
+
];
|
|
179
|
+
await ctx.reply(lines.join('\n'));
|
|
180
|
+
}
|
|
181
|
+
catch (e) {
|
|
182
|
+
await ctx.reply(`⚠️ ${e instanceof Error ? e.message : String(e)}`);
|
|
183
|
+
}
|
|
184
|
+
},
|
|
185
|
+
},
|
|
186
|
+
{
|
|
187
|
+
name: 'rooms', summary: 'list rooms',
|
|
188
|
+
execute: noArgs('/rooms', async (ctx) => {
|
|
189
|
+
const { listRoomRecords } = await import('../rooms-tasks/room-state.js');
|
|
190
|
+
const rooms = listRoomRecords();
|
|
191
|
+
if (!rooms.length)
|
|
192
|
+
return ctx.reply('🏠 No rooms.');
|
|
193
|
+
const lines = rooms.map(r => `${r.room_id} ${r.state} ${r.room_name}${r.task_id ? ` (task: ${r.task_id})` : ''}`);
|
|
194
|
+
await ctx.reply(tail(`🏠 Rooms:\n${lines.join('\n')}`, REPLY_MAX_CHARS));
|
|
195
|
+
}),
|
|
196
|
+
},
|
|
197
|
+
{
|
|
198
|
+
name: 'room', usage: '/room <id>',
|
|
199
|
+
summary: 'show room details',
|
|
200
|
+
execute: async (ctx, args) => {
|
|
201
|
+
if (!args)
|
|
202
|
+
throw new OwnerCommandUsageError('usage: /room <id>');
|
|
203
|
+
const { getRoomRecord } = await import('../rooms-tasks/room-state.js');
|
|
204
|
+
const r = getRoomRecord(args.trim());
|
|
205
|
+
if (!r)
|
|
206
|
+
return ctx.reply(`⚠️ room not found: ${args.trim()}`);
|
|
207
|
+
const lines = [
|
|
208
|
+
`🏠 Room: ${r.room_id}`,
|
|
209
|
+
`Name: ${r.room_name}`,
|
|
210
|
+
`State: ${r.state}`,
|
|
211
|
+
`Saga: ${r.saga.phase} (step ${r.saga.step_index})`,
|
|
212
|
+
...(r.task_id ? [`Task: ${r.task_id}`] : []),
|
|
213
|
+
...(r.provisioning_detail ? [`Detail: ${r.provisioning_detail}`] : []),
|
|
214
|
+
...(r.saga.error ? [`Error: ${r.saga.error}`] : []),
|
|
215
|
+
`Created: ${r.created_at}`,
|
|
216
|
+
];
|
|
217
|
+
await ctx.reply(lines.join('\n'));
|
|
218
|
+
},
|
|
219
|
+
},
|
|
220
|
+
{
|
|
221
|
+
name: 'templates', summary: 'list available room templates',
|
|
222
|
+
execute: noArgs('/templates', async (ctx) => {
|
|
223
|
+
const { listTemplates } = await import('../rooms-tasks/templates.js');
|
|
224
|
+
const templates = listTemplates({});
|
|
225
|
+
if (!templates.length)
|
|
226
|
+
return ctx.reply('📐 No templates.');
|
|
227
|
+
const lines = templates.map(t => {
|
|
228
|
+
const tag = t.builtin ? ' (built-in)' : '';
|
|
229
|
+
return `${t.name}@${t.version}${tag} ${t.description}`;
|
|
230
|
+
});
|
|
231
|
+
await ctx.reply(`📐 Templates:\n${lines.join('\n')}`);
|
|
232
|
+
}),
|
|
233
|
+
},
|
|
145
234
|
];
|
|
146
235
|
/** Trimmed slash-prefixed text is a command attempt and is never forwarded. */
|
|
147
236
|
export const isOwnerCommandText = (text) => text.trim().startsWith('/');
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import type { Command } from 'commander';
|
|
2
|
+
export declare function registerTemplateCommands(parent: Command, cOpt: (cmd: Command) => Command): void;
|
|
3
|
+
export declare function registerTaskCommands(parent: Command, cOpt: (cmd: Command) => Command): void;
|
|
4
|
+
export declare function registerRoomCommands(parent: Command, cOpt: (cmd: Command) => Command): void;
|