@ours.network/fleet 1.1.0-nightly.27 → 1.1.0-nightly.28
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/application/task-room-service.d.ts +1 -1
- package/dist/application/task-room-service.js +43 -12
- package/dist/build-info.json +4 -4
- package/dist/owner-channel/channel.js +7 -6
- package/dist/rooms-tasks/cli.js +2 -0
- package/dist/rooms-tasks/cowork-adapter.d.ts +4 -0
- package/dist/rooms-tasks/cowork-adapter.js +7 -0
- package/dist/rooms-tasks/types.d.ts +1 -1
- package/package.json +1 -1
|
@@ -22,7 +22,7 @@ export interface TaskSettlementPlan {
|
|
|
22
22
|
settlementRequired: boolean;
|
|
23
23
|
}
|
|
24
24
|
export type TaskRecoveryIssue = {
|
|
25
|
-
code: 'terminal_pending' | 'waiting_cowork' | 'waiting_owner_invite' | 'owner_cid_mismatch' | 'waiting_seats' | 'provisioning_resumed';
|
|
25
|
+
code: 'terminal_pending' | 'waiting_cowork' | 'waiting_owner_authorization' | 'waiting_owner_invite' | 'owner_cid_mismatch' | 'waiting_seats' | 'provisioning_resumed';
|
|
26
26
|
} | {
|
|
27
27
|
code: 'member_failed';
|
|
28
28
|
stepIndex: number;
|
|
@@ -16,6 +16,7 @@ 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
20
|
function recordCanonicalRoomCreated(room) {
|
|
20
21
|
recordFleetAuditPresentation({ kind: 'room', operation: 'create',
|
|
21
22
|
eventId: `room-created:${room.created_at}`, id: room.room_id,
|
|
@@ -235,15 +236,17 @@ export class TaskRoomApplicationService {
|
|
|
235
236
|
const ready = task.state === 'active' && room?.state === 'active'
|
|
236
237
|
&& active === expected && launched === expected;
|
|
237
238
|
const blocker = task.outcome?.summary ?? task.blocked?.reason ?? room?.saga.error;
|
|
238
|
-
const nextAction = room?.provisioning_detail === '
|
|
239
|
-
? '
|
|
240
|
-
: room?.provisioning_detail === '
|
|
241
|
-
? '
|
|
242
|
-
: room?.provisioning_detail === '
|
|
243
|
-
? '
|
|
244
|
-
:
|
|
245
|
-
?
|
|
246
|
-
:
|
|
239
|
+
const nextAction = room?.provisioning_detail === 'waiting_owner_authorization'
|
|
240
|
+
? 'Restore ours-cowork, then await the same task to retry Owner command authorization.'
|
|
241
|
+
: room?.provisioning_detail === 'waiting_owner_invite'
|
|
242
|
+
? 'Rotate rooms.owner.public_invite, then await the same task.'
|
|
243
|
+
: room?.provisioning_detail === 'owner_cid_mismatch'
|
|
244
|
+
? 'Verify rooms.owner.expected_cid, rotate the Owner invite, then await the same task.'
|
|
245
|
+
: room?.provisioning_detail === 'waiting_cowork'
|
|
246
|
+
? 'Restore ours-cowork, then await the same task.'
|
|
247
|
+
: failed
|
|
248
|
+
? `Correct the blocker, then run ours-fleet task recover ${task.task_id}.`
|
|
249
|
+
: undefined;
|
|
247
250
|
return {
|
|
248
251
|
kind: failed ? 'failed' : ready ? 'ready' : 'in_progress', task, room,
|
|
249
252
|
handle: { command: `ours-fleet task await ${task.task_id}`, task_id: task.task_id },
|
|
@@ -462,7 +465,9 @@ export class TaskRoomApplicationService {
|
|
|
462
465
|
return { kind: 'provisioning_resume_failed', task, room, issues };
|
|
463
466
|
}
|
|
464
467
|
}
|
|
465
|
-
if (room.
|
|
468
|
+
if (room.saga.phase === 'attach_owner'
|
|
469
|
+
|| room.provisioning_detail === 'waiting_owner_authorization'
|
|
470
|
+
|| room.provisioning_detail === 'waiting_owner_invite'
|
|
466
471
|
|| room.provisioning_detail === 'owner_cid_mismatch') {
|
|
467
472
|
try {
|
|
468
473
|
await this.recoverRoom({ actor: input.actor, roomId: room.room_id });
|
|
@@ -484,6 +489,8 @@ export class TaskRoomApplicationService {
|
|
|
484
489
|
};
|
|
485
490
|
if (room.provisioning_detail === 'waiting_cowork')
|
|
486
491
|
issues.push({ code: 'waiting_cowork' });
|
|
492
|
+
if (room.provisioning_detail === 'waiting_owner_authorization')
|
|
493
|
+
issues.push({ code: 'waiting_owner_authorization' });
|
|
487
494
|
if (room.provisioning_detail === 'waiting_owner_invite')
|
|
488
495
|
issues.push({ code: 'waiting_owner_invite' });
|
|
489
496
|
if (room.provisioning_detail === 'owner_cid_mismatch')
|
|
@@ -631,14 +638,27 @@ export class TaskRoomApplicationService {
|
|
|
631
638
|
throw new Error(error);
|
|
632
639
|
}
|
|
633
640
|
}
|
|
641
|
+
if (orchestration?.owner_seat_cid) {
|
|
642
|
+
const ownerCid = orchestration.owner_seat_cid.toLowerCase();
|
|
643
|
+
const ownerSeat = room.seats.find(seat => seat.identity_cid.toLowerCase() === ownerCid && seat.seat_state !== 'removed');
|
|
644
|
+
if (ownerSeat)
|
|
645
|
+
await adapter.setRoleCommands(input.roomId, {
|
|
646
|
+
role: ownerSeat.role, commands: [...OWNER_ROOM_COMMANDS],
|
|
647
|
+
});
|
|
648
|
+
}
|
|
634
649
|
if (orchestration && !orchestration.owner_seat_cid
|
|
635
|
-
&& (orchestration.
|
|
650
|
+
&& (orchestration.saga.phase === 'attach_owner'
|
|
651
|
+
|| orchestration.provisioning_detail === 'waiting_owner_authorization'
|
|
652
|
+
|| orchestration.provisioning_detail === 'waiting_owner_invite'
|
|
636
653
|
|| orchestration.provisioning_detail === 'owner_cid_mismatch')) {
|
|
637
654
|
const expected = cfg.rooms.owner.expected_cid.toLowerCase();
|
|
638
655
|
const existing = (await adapter.getSeats(input.roomId))
|
|
639
656
|
.find(seat => seat.identity_cid.toLowerCase() === expected && seat.seat_state !== 'removed');
|
|
640
657
|
if (!existing && !cfg.ownerInvite)
|
|
641
658
|
throw new ConfigError('rooms.owner: configure public_invite or public_invite_file before recovery');
|
|
659
|
+
await adapter.setRoleCommands(input.roomId, {
|
|
660
|
+
role: existing?.role ?? cfg.rooms.owner.role, commands: [...OWNER_ROOM_COMMANDS],
|
|
661
|
+
});
|
|
642
662
|
let acceptedCid = existing?.identity_cid;
|
|
643
663
|
if (!acceptedCid)
|
|
644
664
|
acceptedCid = (await adapter.acceptInvite(input.roomId, cfg.ownerInvite, {
|
|
@@ -654,6 +674,8 @@ export class TaskRoomApplicationService {
|
|
|
654
674
|
issues.push('Recovery guidance is recorded; inspect role logs for diagnostics.');
|
|
655
675
|
if (orchestration?.provisioning_detail === 'waiting_cowork')
|
|
656
676
|
issues.push('Check ours-cowork service status');
|
|
677
|
+
if (orchestration?.provisioning_detail === 'waiting_owner_authorization')
|
|
678
|
+
issues.push('Restore Cowork availability, then re-run recover');
|
|
657
679
|
if (orchestration?.provisioning_detail === 'waiting_owner_invite')
|
|
658
680
|
issues.push('Rotate rooms.owner.public_invite in config, then re-run recover');
|
|
659
681
|
if (orchestration?.provisioning_detail === 'waiting_seats')
|
|
@@ -951,8 +973,17 @@ export class TaskRoomApplicationService {
|
|
|
951
973
|
await checkpointFleetAuditPresentations();
|
|
952
974
|
room = advanceSaga(room.room_id, 'create_room', 1);
|
|
953
975
|
if (attachOwner) {
|
|
976
|
+
room = advanceSaga(room.room_id, 'attach_owner', 2);
|
|
977
|
+
try {
|
|
978
|
+
await cowork.setRoleCommands(room.room_id, {
|
|
979
|
+
role: rooms.owner.role, commands: [...OWNER_ROOM_COMMANDS],
|
|
980
|
+
});
|
|
981
|
+
}
|
|
982
|
+
catch (error) {
|
|
983
|
+
setSagaError(room.room_id, error instanceof Error ? error.message : String(error), 'Restore Cowork availability, then run room recover to configure Owner command authorization.', 'waiting_owner_authorization');
|
|
984
|
+
throw error;
|
|
985
|
+
}
|
|
954
986
|
try {
|
|
955
|
-
room = advanceSaga(room.room_id, 'attach_owner', 2);
|
|
956
987
|
const accepted = await cowork.acceptInvite(room.room_id, cfg.ownerInvite, {
|
|
957
988
|
role: rooms.owner.role, expected_cid: rooms.owner.expected_cid,
|
|
958
989
|
});
|
package/dist/build-info.json
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
{
|
|
2
|
-
"version": "1.1.0-nightly.
|
|
3
|
-
"buildId": "
|
|
4
|
-
"commit": "
|
|
2
|
+
"version": "1.1.0-nightly.28",
|
|
3
|
+
"buildId": "761c569df66f",
|
|
4
|
+
"commit": "c03ee4d380feb9e12fcc503785f3d81203026c2a",
|
|
5
5
|
"dirty": true,
|
|
6
|
-
"builtAt": "2026-09-
|
|
6
|
+
"builtAt": "2026-09-04T14:31:02.540Z",
|
|
7
7
|
"capabilities": [
|
|
8
8
|
"monitor.interrupt.after_tool"
|
|
9
9
|
]
|
|
@@ -1648,12 +1648,13 @@ export class OwnerChannel {
|
|
|
1648
1648
|
}
|
|
1649
1649
|
const { task, room, issues } = begin.result;
|
|
1650
1650
|
const hints = issues.map(issue => issue.code === 'waiting_cowork' ? 'Cowork socket unreachable'
|
|
1651
|
-
: issue.code === '
|
|
1652
|
-
: issue.code === '
|
|
1653
|
-
: issue.code === '
|
|
1654
|
-
: issue.code === '
|
|
1655
|
-
: issue.code === '
|
|
1656
|
-
: issue.code
|
|
1651
|
+
: issue.code === 'waiting_owner_authorization' ? 'Owner command authorization is not configured'
|
|
1652
|
+
: issue.code === 'waiting_owner_invite' ? 'Owner invite missing or invalid'
|
|
1653
|
+
: issue.code === 'owner_cid_mismatch' ? 'Owner CID mismatch'
|
|
1654
|
+
: issue.code === 'member_failed' ? `Member failed at step ${issue.stepIndex}`
|
|
1655
|
+
: issue.code === 'resume_failed' ? `Resume failed: ${issue.error}`
|
|
1656
|
+
: issue.code === 'provisioning_resumed' ? 'Provisioning resumed successfully'
|
|
1657
|
+
: issue.code);
|
|
1657
1658
|
await this.send(sender.id, renderMarkdownResult({
|
|
1658
1659
|
icon: '🛟', title: 'Task recovery',
|
|
1659
1660
|
fields: [{ label: 'Task', value: task.task_id, kind: 'code' },
|
package/dist/rooms-tasks/cli.js
CHANGED
|
@@ -1196,6 +1196,8 @@ export function registerTaskCommands(parent, cOpt) {
|
|
|
1196
1196
|
return 'Cowork management socket unreachable — check ours-cowork service';
|
|
1197
1197
|
if (issue.code === 'waiting_owner_invite')
|
|
1198
1198
|
return 'Owner invite invalid or expired — rotate rooms.owner.public_invite in config';
|
|
1199
|
+
if (issue.code === 'waiting_owner_authorization')
|
|
1200
|
+
return 'Owner command authorization is not configured — restore ours-cowork and retry';
|
|
1199
1201
|
if (issue.code === 'owner_cid_mismatch')
|
|
1200
1202
|
return 'Owner CID mismatch — verify rooms.owner.expected_cid matches Messenger identity';
|
|
1201
1203
|
if (issue.code === 'member_failed')
|
|
@@ -73,6 +73,10 @@ export interface CoworkAdapter {
|
|
|
73
73
|
role: string;
|
|
74
74
|
text: string;
|
|
75
75
|
}): Promise<CoworkRoleBriefingInfo>;
|
|
76
|
+
setRoleCommands(roomId: string, opts: {
|
|
77
|
+
role: string;
|
|
78
|
+
commands: Array<'list-members' | 'remove-member'>;
|
|
79
|
+
}): Promise<void>;
|
|
76
80
|
getHistory(roomId: string, opts?: {
|
|
77
81
|
after?: number;
|
|
78
82
|
limit?: number;
|
|
@@ -390,6 +390,13 @@ export function createCoworkAdapter(options = {}) {
|
|
|
390
390
|
throw new CoworkProtocolError('room.participants', 'result must be an array');
|
|
391
391
|
return result.map((seat) => projectSeat(seat, 'room.participants'));
|
|
392
392
|
},
|
|
393
|
+
async setRoleCommands(roomId, opts) {
|
|
394
|
+
const result = await call('room.command.role.set', {
|
|
395
|
+
room_id: roomId, role: opts.role, commands: opts.commands,
|
|
396
|
+
});
|
|
397
|
+
if (!Array.isArray(result))
|
|
398
|
+
throw new CoworkProtocolError('room.command.role.set', 'result must be an array');
|
|
399
|
+
},
|
|
393
400
|
async recoverRoom(roomId) {
|
|
394
401
|
// Cowork performs packet/state reconciliation during daemon recovery.
|
|
395
402
|
// Its `room.recover` RPC is specifically invite-receipt recovery, so a
|
|
@@ -133,7 +133,7 @@ export interface SagaCursor {
|
|
|
133
133
|
error?: string;
|
|
134
134
|
recovery_hint?: string;
|
|
135
135
|
}
|
|
136
|
-
export type ProvisioningDetail = 'waiting_cowork' | 'waiting_owner_invite' | 'owner_cid_mismatch' | 'member_failed' | 'waiting_seats' | 'uncertain';
|
|
136
|
+
export type ProvisioningDetail = 'waiting_cowork' | 'waiting_owner_authorization' | 'waiting_owner_invite' | 'owner_cid_mismatch' | 'member_failed' | 'waiting_seats' | 'uncertain';
|
|
137
137
|
export interface RoomRoleBriefingDefinition {
|
|
138
138
|
role: string;
|
|
139
139
|
text: string;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ours.network/fleet",
|
|
3
|
-
"version": "1.1.0-nightly.
|
|
3
|
+
"version": "1.1.0-nightly.28",
|
|
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",
|