@ours.network/fleet 1.1.2 → 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
- const OWNER_ROOM_COMMANDS = ['list-members', 'remove-member'];
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
- ? `Restore ours-cowork, then run ours-fleet task start ${task.task_id}.`
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 cowork.setRoleCommands(roomId, {
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 cowork.setRoleCommands(roomId, {
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
- try {
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,
@@ -1,9 +1,9 @@
1
1
  {
2
- "version": "1.1.2",
3
- "buildId": "2713c17e322c",
4
- "commit": "2fe00e32e6115359694fc1f79484d6b12ffbb49c",
2
+ "version": "1.1.4",
3
+ "buildId": "a288595a172d",
4
+ "commit": "72d6d26ea49eaf1941885e721eab76e177f974af",
5
5
  "dirty": false,
6
- "builtAt": "2026-09-05T21:51:48.223Z",
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;
@@ -9,7 +9,7 @@ import { homedir } from 'node:os';
9
9
  import { join, resolve } from 'node:path';
10
10
  import { createConnection } from 'node:net';
11
11
  const RPC_VERSION = 1;
12
- const DEFAULT_TIMEOUT_MS = 10_000;
12
+ const DEFAULT_TIMEOUT_MS = 30_000;
13
13
  const MAX_RESPONSE_BYTES = 4 * 1024 * 1024;
14
14
  export class CoworkUnavailableError extends Error {
15
15
  constructor(message = 'Cowork management socket is not reachable', options) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ours.network/fleet",
3
- "version": "1.1.2",
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",