@ours.network/fleet 1.1.3 → 1.1.4
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
CHANGED
|
@@ -599,6 +599,19 @@ tasks:
|
|
|
599
599
|
close_room_on_done: true
|
|
600
600
|
```
|
|
601
601
|
|
|
602
|
+
Owner-attached rooms require **ours-cowork 1.3.0 or newer**. Fleet sets the
|
|
603
|
+
configured Owner role's command policy to `["*"]` before accepting the Owner
|
|
604
|
+
invite, and reapplies it during Owner-seat recovery. Cowork stores the wildcard
|
|
605
|
+
verbatim, authorizing current and future room runtime commands (including command
|
|
606
|
+
grants and room close/delete) for active seats with that exact role. Other roles'
|
|
607
|
+
grants are unchanged; host/global APIs remain outside this authorization.
|
|
608
|
+
|
|
609
|
+
Older Cowork versions reject the wildcard. Fleet leaves provisioning at
|
|
610
|
+
`waiting_owner_authorization` with upgrade guidance, without accepting the Owner
|
|
611
|
+
invite or falling back to an enumerated grant list. Upgrade Cowork and retry the
|
|
612
|
+
originating task. Existing active rooms are not retroactively migrated, and rooms
|
|
613
|
+
with Owner attachment disabled receive no Owner grant.
|
|
614
|
+
|
|
602
615
|
Fleet launches each template member with a dedicated one-time Cowork invite.
|
|
603
616
|
The generated temporary-agent briefing contains the exact identity name, invite,
|
|
604
617
|
Cowork role, and task. The agent creates that identity itself with ours MCP
|
|
@@ -233,6 +233,7 @@ export declare class TaskRoomApplicationService {
|
|
|
233
233
|
};
|
|
234
234
|
taskId: string;
|
|
235
235
|
}): Promise<TaskProvisioningContinuationResult>;
|
|
236
|
+
private setOwnerRoomCommands;
|
|
236
237
|
private reconcileProvisioningOwner;
|
|
237
238
|
private acceptTerminal;
|
|
238
239
|
listTemplates(): import("../rooms-tasks/types.js").TemplateDefinition[];
|
|
@@ -16,7 +16,8 @@ import { withFileLock } from '../atomic-file.js';
|
|
|
16
16
|
import { launchFleetWorker } from '../rooms-tasks/external-worker.js';
|
|
17
17
|
import { storedRoomLaunchPolicy, TASK_CANCELLABLE_STATES, TASK_TERMINAL_STATES } from '../rooms-tasks/types.js';
|
|
18
18
|
import { deriveTaskRoomName } from '../rooms-tasks/task-room-name.js';
|
|
19
|
-
|
|
19
|
+
// Cowork 1.3.0+ stores this selector verbatim and matches future room commands.
|
|
20
|
+
const OWNER_ROOM_COMMANDS = ['*'];
|
|
20
21
|
/** Repairable terminal observation derived entirely from durable Task/Room state. */
|
|
21
22
|
export function recordTaskProvisioningOutcome(outcome) {
|
|
22
23
|
const room = outcome.room;
|
|
@@ -234,7 +235,7 @@ export class TaskRoomApplicationService {
|
|
|
234
235
|
&& active === expected && launched === expected;
|
|
235
236
|
const blocker = task.outcome?.summary ?? task.blocked?.reason ?? room?.saga.error;
|
|
236
237
|
const nextAction = room?.provisioning_detail === 'waiting_owner_authorization'
|
|
237
|
-
? `
|
|
238
|
+
? `Ensure ours-cowork 1.3.0 or newer is running and available, then run ours-fleet task start ${task.task_id}.`
|
|
238
239
|
: room?.provisioning_detail === 'waiting_owner_invite'
|
|
239
240
|
? `Rotate rooms.owner.public_invite, then run ours-fleet task start ${task.task_id}.`
|
|
240
241
|
: room?.provisioning_detail === 'owner_cid_mismatch'
|
|
@@ -497,6 +498,15 @@ export class TaskRoomApplicationService {
|
|
|
497
498
|
return { kind: 'provisioning_resume_failed', task, room, issues };
|
|
498
499
|
}
|
|
499
500
|
}
|
|
501
|
+
async setOwnerRoomCommands(cowork, roomId, role) {
|
|
502
|
+
try {
|
|
503
|
+
await cowork.setRoleCommands(roomId, { role, commands: [...OWNER_ROOM_COMMANDS] });
|
|
504
|
+
}
|
|
505
|
+
catch (error) {
|
|
506
|
+
setSagaError(roomId, error instanceof Error ? error.message : String(error), 'Ensure ours-cowork 1.3.0 or newer is running and available, then retry the originating task or room create command.', 'waiting_owner_authorization');
|
|
507
|
+
throw error;
|
|
508
|
+
}
|
|
509
|
+
}
|
|
500
510
|
async reconcileProvisioningOwner(cfg, roomId) {
|
|
501
511
|
if (!cfg.rooms)
|
|
502
512
|
throw new ConfigError('rooms: configuration is required before creating or querying rooms');
|
|
@@ -518,9 +528,7 @@ export class TaskRoomApplicationService {
|
|
|
518
528
|
const ownerCid = room.owner_seat_cid.toLowerCase();
|
|
519
529
|
const ownerSeat = remote.seats.find(seat => seat.identity_cid.toLowerCase() === ownerCid && seat.seat_state !== 'removed');
|
|
520
530
|
if (ownerSeat)
|
|
521
|
-
await
|
|
522
|
-
role: ownerSeat.role, commands: [...OWNER_ROOM_COMMANDS],
|
|
523
|
-
});
|
|
531
|
+
await this.setOwnerRoomCommands(cowork, roomId, ownerSeat.role);
|
|
524
532
|
if (room.saga.phase === 'attach_owner')
|
|
525
533
|
advanceSaga(roomId, 'create_members', 3);
|
|
526
534
|
return;
|
|
@@ -532,9 +540,7 @@ export class TaskRoomApplicationService {
|
|
|
532
540
|
.find(seat => seat.identity_cid.toLowerCase() === expected && seat.seat_state !== 'removed');
|
|
533
541
|
if (!existing && !cfg.ownerInvite)
|
|
534
542
|
throw new ConfigError('rooms.owner: configure public_invite or public_invite_file before continuing task provisioning');
|
|
535
|
-
await
|
|
536
|
-
role: existing?.role ?? cfg.rooms.owner.role, commands: [...OWNER_ROOM_COMMANDS],
|
|
537
|
-
});
|
|
543
|
+
await this.setOwnerRoomCommands(cowork, roomId, existing?.role ?? cfg.rooms.owner.role);
|
|
538
544
|
const acceptedCid = existing?.identity_cid ?? (await cowork.acceptInvite(roomId, cfg.ownerInvite, {
|
|
539
545
|
role: cfg.rooms.owner.role, expected_cid: cfg.rooms.owner.expected_cid,
|
|
540
546
|
})).seat_cid;
|
|
@@ -899,15 +905,7 @@ export class TaskRoomApplicationService {
|
|
|
899
905
|
room = advanceSaga(room.room_id, 'create_room', 1);
|
|
900
906
|
if (attachOwner) {
|
|
901
907
|
room = advanceSaga(room.room_id, 'attach_owner', 2);
|
|
902
|
-
|
|
903
|
-
await cowork.setRoleCommands(room.room_id, {
|
|
904
|
-
role: rooms.owner.role, commands: [...OWNER_ROOM_COMMANDS],
|
|
905
|
-
});
|
|
906
|
-
}
|
|
907
|
-
catch (error) {
|
|
908
|
-
setSagaError(room.room_id, error instanceof Error ? error.message : String(error), 'Restore Cowork availability, then retry the originating task or room create command.', 'waiting_owner_authorization');
|
|
909
|
-
throw error;
|
|
910
|
-
}
|
|
908
|
+
await this.setOwnerRoomCommands(cowork, room.room_id, rooms.owner.role);
|
|
911
909
|
try {
|
|
912
910
|
const accepted = await cowork.acceptInvite(room.room_id, cfg.ownerInvite, {
|
|
913
911
|
role: rooms.owner.role, expected_cid: rooms.owner.expected_cid,
|
package/dist/build-info.json
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
{
|
|
2
|
-
"version": "1.1.
|
|
3
|
-
"buildId": "
|
|
4
|
-
"commit": "
|
|
2
|
+
"version": "1.1.4",
|
|
3
|
+
"buildId": "a288595a172d",
|
|
4
|
+
"commit": "72d6d26ea49eaf1941885e721eab76e177f974af",
|
|
5
5
|
"dirty": false,
|
|
6
|
-
"builtAt": "2026-09-
|
|
6
|
+
"builtAt": "2026-09-11T09:05:53.118Z",
|
|
7
7
|
"capabilities": [
|
|
8
8
|
"monitor.interrupt.after_tool"
|
|
9
9
|
]
|
|
@@ -75,7 +75,7 @@ export interface CoworkAdapter {
|
|
|
75
75
|
}): Promise<CoworkRoleBriefingInfo>;
|
|
76
76
|
setRoleCommands(roomId: string, opts: {
|
|
77
77
|
role: string;
|
|
78
|
-
commands: Array<'list-members' | 'remove-member'>;
|
|
78
|
+
commands: Array<'*' | 'list-members' | 'remove-member'>;
|
|
79
79
|
}): Promise<void>;
|
|
80
80
|
getHistory(roomId: string, opts?: {
|
|
81
81
|
after?: number;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ours.network/fleet",
|
|
3
|
-
"version": "1.1.
|
|
3
|
+
"version": "1.1.4",
|
|
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",
|