@ours.network/fleet 1.1.0-nightly.2 → 1.1.0-nightly.20
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 +169 -54
- package/dist/agent-recovery-gate.d.ts +17 -0
- package/dist/agent-recovery-gate.js +135 -0
- package/dist/application/capabilities.js +18 -6
- package/dist/application/fleet-query-service.js +20 -5
- package/dist/application/role-command-service.js +9 -0
- package/dist/application/role-creation-service.d.ts +6 -25
- package/dist/application/role-creation-service.js +34 -72
- package/dist/application/role-repository.d.ts +4 -2
- package/dist/application/role-repository.js +6 -3
- package/dist/application/session-control.d.ts +3 -1
- package/dist/application/session-control.js +4 -2
- package/dist/application/task-room-service.d.ts +58 -6
- package/dist/application/task-room-service.js +426 -78
- package/dist/briefing.js +74 -24
- package/dist/build-info.json +4 -4
- package/dist/canonical-json.d.ts +2 -0
- package/dist/canonical-json.js +10 -0
- package/dist/cli.js +227 -73
- package/dist/config-yaml.d.ts +1 -1
- package/dist/config.d.ts +67 -2
- package/dist/config.js +260 -30
- package/dist/daemon-recovery.d.ts +93 -0
- package/dist/daemon-recovery.js +328 -0
- package/dist/docs.d.ts +1 -1
- package/dist/docs.js +171 -66
- package/dist/doctor.d.ts +2 -0
- package/dist/doctor.js +54 -4
- package/dist/fleet-command-audit.d.ts +165 -0
- package/dist/fleet-command-audit.js +543 -0
- package/dist/fleet-proxy.d.ts +7 -2
- package/dist/fleet-proxy.js +30 -8
- package/dist/harness/agent-session.d.ts +5 -0
- package/dist/harness/claude-code-session.d.ts +2 -0
- package/dist/harness/claude-code-session.js +6 -1
- package/dist/harness/claude-code.js +2 -0
- package/dist/harness/codex-app-server-proxy.d.ts +40 -0
- package/dist/harness/codex-app-server-proxy.js +348 -14
- package/dist/harness/codex-session.d.ts +11 -2
- package/dist/harness/codex-session.js +22 -2
- package/dist/harness/codex.d.ts +5 -1
- package/dist/harness/codex.js +110 -10
- package/dist/harness/types.d.ts +1 -1
- package/dist/index.d.ts +5 -4
- package/dist/index.js +4 -3
- package/dist/init-guidance.d.ts +1 -1
- package/dist/init-guidance.js +4 -3
- package/dist/init-wizard.d.ts +98 -0
- package/dist/init-wizard.js +629 -0
- package/dist/lifecycle-summary.d.ts +118 -0
- package/dist/lifecycle-summary.js +161 -0
- package/dist/loops/config.js +3 -2
- package/dist/model-env.d.ts +2 -2
- package/dist/model-env.js +1 -1
- package/dist/model-recovery.d.ts +1 -1
- package/dist/ops.js +2 -17
- package/dist/owner-channel/channel.d.ts +58 -0
- package/dist/owner-channel/channel.js +321 -42
- package/dist/owner-channel/commands.d.ts +6 -1
- package/dist/owner-channel/commands.js +34 -19
- package/dist/owner-channel/state.d.ts +2 -0
- package/dist/owner-channel/state.js +8 -2
- package/dist/permissions.js +1 -1
- package/dist/preset-bootstrap.d.ts +10 -0
- package/dist/preset-bootstrap.js +85 -0
- package/dist/preset-migration.d.ts +42 -0
- package/dist/preset-migration.js +414 -0
- package/dist/reports/artifact.d.ts +10 -0
- package/dist/reports/artifact.js +32 -0
- package/dist/reports/index.d.ts +5 -0
- package/dist/reports/index.js +5 -0
- package/dist/reports/render.d.ts +6 -0
- package/dist/reports/render.js +240 -0
- package/dist/reports/service.d.ts +42 -0
- package/dist/reports/service.js +57 -0
- package/dist/reports/tasks.d.ts +52 -0
- package/dist/reports/tasks.js +177 -0
- package/dist/reports/types.d.ts +315 -0
- package/dist/reports/types.js +6 -0
- package/dist/resolved-plan.js +4 -0
- package/dist/rooms-tasks/cli.d.ts +2 -0
- package/dist/rooms-tasks/cli.js +503 -75
- package/dist/rooms-tasks/close.d.ts +9 -1
- package/dist/rooms-tasks/close.js +20 -4
- package/dist/rooms-tasks/config.js +16 -14
- package/dist/rooms-tasks/cowork-adapter.d.ts +1 -0
- package/dist/rooms-tasks/cowork-adapter.js +6 -0
- package/dist/rooms-tasks/deletion.d.ts +51 -0
- package/dist/rooms-tasks/deletion.js +217 -0
- package/dist/rooms-tasks/external-worker.d.ts +1 -0
- package/dist/rooms-tasks/external-worker.js +14 -9
- package/dist/rooms-tasks/launch-snapshot.d.ts +19 -0
- package/dist/rooms-tasks/launch-snapshot.js +176 -0
- package/dist/rooms-tasks/member-overrides.d.ts +27 -0
- package/dist/rooms-tasks/member-overrides.js +170 -0
- package/dist/rooms-tasks/provision.js +179 -49
- package/dist/rooms-tasks/room-state.d.ts +1 -0
- package/dist/rooms-tasks/room-state.js +12 -1
- package/dist/rooms-tasks/task-state.d.ts +115 -3
- package/dist/rooms-tasks/task-state.js +361 -11
- package/dist/rooms-tasks/templates.d.ts +4 -2
- package/dist/rooms-tasks/templates.js +42 -78
- package/dist/rooms-tasks/terminal.d.ts +3 -0
- package/dist/rooms-tasks/terminal.js +7 -3
- package/dist/rooms-tasks/types.d.ts +94 -17
- package/dist/rooms-tasks/types.js +14 -4
- package/dist/runner.d.ts +9 -2
- package/dist/runner.js +107 -40
- package/dist/session/acp.d.ts +9 -1
- package/dist/session/acp.js +35 -9
- package/dist/session/arbiter.d.ts +2 -1
- package/dist/session/arbiter.js +2 -0
- package/dist/session/codex-app-server-transport.d.ts +53 -0
- package/dist/session/codex-app-server-transport.js +184 -0
- package/dist/session/codex-app-server.d.ts +122 -0
- package/dist/session/codex-app-server.js +1031 -0
- package/dist/session/control.d.ts +14 -1
- package/dist/session/control.js +38 -0
- package/dist/session/conversation-types.d.ts +4 -4
- package/dist/session/types.d.ts +24 -6
- package/dist/session/types.js +28 -0
- package/dist/spawn.d.ts +6 -31
- package/dist/spawn.js +57 -234
- package/dist/temp-lifecycle.d.ts +1 -1
- 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/fleet-config-service.d.ts +1 -0
- package/dist/web/fleet-config-service.js +27 -8
- package/dist/web/runtime.js +11 -6
- package/dist/web/server.js +28 -1
- package/dist/web/topology-promote.js +8 -1
- package/dist/web-app/assets/index-C0h3ALvs.js +10 -0
- package/dist/web-app/index.html +1 -1
- package/package.json +3 -2
- package/presets/brain-catalog.json +16 -0
- package/presets/fleet/agent_templates/Critic.yaml +4 -0
- package/presets/fleet/agent_templates/Developer.yaml +4 -0
- package/presets/fleet/agent_templates/LocalCoordinator.yaml +4 -0
- package/presets/fleet/agents/FleetCoordinator.yaml +3 -0
- package/presets/fleet/brains/claude-default.yaml +5 -0
- package/presets/fleet/brains/claude-fable-5-high.yaml +5 -0
- package/presets/fleet/brains/claude-fable-5-low.yaml +5 -0
- package/presets/fleet/brains/claude-fable-5-max.yaml +5 -0
- package/presets/fleet/brains/claude-fable-5-medium.yaml +5 -0
- package/presets/fleet/brains/claude-fable-5-xhigh.yaml +5 -0
- package/presets/fleet/brains/claude-opus-5-high.yaml +5 -0
- package/presets/fleet/brains/claude-opus-5-low.yaml +5 -0
- package/presets/fleet/brains/claude-opus-5-max.yaml +5 -0
- package/presets/fleet/brains/claude-opus-5-medium.yaml +5 -0
- package/presets/fleet/brains/claude-opus-5-xhigh.yaml +5 -0
- package/presets/fleet/brains/claude-sonnet-5-high.yaml +5 -0
- package/presets/fleet/brains/claude-sonnet-5-low.yaml +5 -0
- package/presets/fleet/brains/claude-sonnet-5-max.yaml +5 -0
- package/presets/fleet/brains/claude-sonnet-5-medium.yaml +5 -0
- package/presets/fleet/brains/claude-sonnet-5-xhigh.yaml +5 -0
- package/presets/fleet/brains/codex-gpt-5-3-codex-spark-high.yaml +5 -0
- package/presets/fleet/brains/codex-gpt-5-3-codex-spark-low.yaml +5 -0
- package/presets/fleet/brains/codex-gpt-5-3-codex-spark-medium.yaml +5 -0
- package/presets/fleet/brains/codex-gpt-5-3-codex-spark-xhigh.yaml +5 -0
- package/presets/fleet/brains/codex-gpt-5-4-high.yaml +5 -0
- package/presets/fleet/brains/codex-gpt-5-4-low.yaml +5 -0
- package/presets/fleet/brains/codex-gpt-5-4-medium.yaml +5 -0
- package/presets/fleet/brains/codex-gpt-5-4-mini-high.yaml +5 -0
- package/presets/fleet/brains/codex-gpt-5-4-mini-low.yaml +5 -0
- package/presets/fleet/brains/codex-gpt-5-4-mini-medium.yaml +5 -0
- package/presets/fleet/brains/codex-gpt-5-4-mini-xhigh.yaml +5 -0
- package/presets/fleet/brains/codex-gpt-5-4-xhigh.yaml +5 -0
- package/presets/fleet/brains/codex-gpt-5-5-high.yaml +5 -0
- package/presets/fleet/brains/codex-gpt-5-5-low.yaml +5 -0
- package/presets/fleet/brains/codex-gpt-5-5-medium.yaml +5 -0
- package/presets/fleet/brains/codex-gpt-5-5-xhigh.yaml +5 -0
- package/presets/fleet/brains/codex-gpt-5-6-luna-high.yaml +5 -0
- package/presets/fleet/brains/codex-gpt-5-6-luna-low.yaml +5 -0
- package/presets/fleet/brains/codex-gpt-5-6-luna-max.yaml +5 -0
- package/presets/fleet/brains/codex-gpt-5-6-luna-medium.yaml +5 -0
- package/presets/fleet/brains/codex-gpt-5-6-luna-xhigh.yaml +5 -0
- package/presets/fleet/brains/codex-gpt-5-6-sol-high.yaml +5 -0
- package/presets/fleet/brains/codex-gpt-5-6-sol-low.yaml +5 -0
- package/presets/fleet/brains/codex-gpt-5-6-sol-max.yaml +5 -0
- package/presets/fleet/brains/codex-gpt-5-6-sol-medium.yaml +5 -0
- package/presets/fleet/brains/codex-gpt-5-6-sol-ultra.yaml +5 -0
- package/presets/fleet/brains/codex-gpt-5-6-sol-xhigh.yaml +5 -0
- package/presets/fleet/brains/codex-gpt-5-6-terra-high.yaml +5 -0
- package/presets/fleet/brains/codex-gpt-5-6-terra-low.yaml +5 -0
- package/presets/fleet/brains/codex-gpt-5-6-terra-max.yaml +5 -0
- package/presets/fleet/brains/codex-gpt-5-6-terra-medium.yaml +5 -0
- package/presets/fleet/brains/codex-gpt-5-6-terra-ultra.yaml +5 -0
- package/presets/fleet/brains/codex-gpt-5-6-terra-xhigh.yaml +5 -0
- package/presets/fleet/roles/Coordinator.yaml +30 -0
- package/presets/fleet/roles/Critic.yaml +19 -0
- package/presets/fleet/roles/Developer.yaml +19 -0
- package/presets/fleet/roles/LocalCoordinator.yaml +25 -0
- package/presets/fleet/room_templates/pair.yaml +10 -0
- package/presets/fleet/room_templates/single.yaml +7 -0
- package/presets/fleet/room_templates/team.yaml +12 -0
- package/presets/fleet.yaml +7 -0
- package/presets/manifest.json +6 -0
- package/dist/web-app/assets/index-BbE9EX6n.js +0 -10
|
@@ -1,25 +1,18 @@
|
|
|
1
|
-
import { type CommonPermissions, type MonitorConfig, type MonitorInterrupt, type NotifyEventType } from '../config.js';
|
|
1
|
+
import { type CommonPermissions, type MonitorConfig, type MonitorInterrupt, type NotifyEventType, type SessionBackendId } from '../config.js';
|
|
2
2
|
import { type IdentityProvisioner } from '../creation.js';
|
|
3
3
|
import { spawnDryRun, type SpawnOpts, type SupervisorLauncher } from '../spawn.js';
|
|
4
4
|
import type { OpsDeps } from '../ops.js';
|
|
5
5
|
import type { ResolvedRole } from '../config.js';
|
|
6
6
|
import { FleetError } from './errors.js';
|
|
7
7
|
import { type ManagedFleetSpawnResult } from '../fleet-proxy.js';
|
|
8
|
-
import { type HarnessModelCatalog, type HarnessModelOption } from './model-catalog.js';
|
|
9
8
|
export interface CreateRoleSessionRequest {
|
|
10
9
|
name: string;
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
model?: string | null;
|
|
14
|
-
reasoningEffort?: string | null;
|
|
15
|
-
session: 'acp';
|
|
10
|
+
brain: import('../config.js').AgentSelection;
|
|
11
|
+
role: import('../config.js').AgentSelection;
|
|
16
12
|
cwd?: string;
|
|
17
13
|
lifetime: 'permanent' | 'temporary';
|
|
18
|
-
mission?: string;
|
|
19
14
|
coordinator?: string;
|
|
20
15
|
permissions: CommonPermissions;
|
|
21
|
-
bio?: string;
|
|
22
|
-
persona?: string;
|
|
23
16
|
monitor?: WebCreationMonitor;
|
|
24
17
|
openAfterCreate: boolean;
|
|
25
18
|
highRiskAcknowledged?: boolean;
|
|
@@ -38,17 +31,6 @@ export type WebCreationMonitor = {
|
|
|
38
31
|
export interface CreationCapabilities {
|
|
39
32
|
available: boolean;
|
|
40
33
|
reasons: string[];
|
|
41
|
-
harnesses: Array<{
|
|
42
|
-
id: 'codex' | 'claude-code';
|
|
43
|
-
available: boolean;
|
|
44
|
-
sessions: Array<'acp'>;
|
|
45
|
-
defaultModel?: string;
|
|
46
|
-
models: string[];
|
|
47
|
-
modelOptions: HarnessModelOption[];
|
|
48
|
-
catalogSource: string;
|
|
49
|
-
customModelAllowed: true;
|
|
50
|
-
warnings: string[];
|
|
51
|
-
}>;
|
|
52
34
|
lifetimes: Array<'permanent' | 'temporary'>;
|
|
53
35
|
identityBootstrap: {
|
|
54
36
|
mode: 'current-fleet-first-boot';
|
|
@@ -71,7 +53,7 @@ export interface CreationPreview {
|
|
|
71
53
|
name: string;
|
|
72
54
|
identity: string;
|
|
73
55
|
harness: string;
|
|
74
|
-
session:
|
|
56
|
+
session: SessionBackendId;
|
|
75
57
|
model?: string;
|
|
76
58
|
reasoningEffort?: string;
|
|
77
59
|
cwd?: string;
|
|
@@ -95,7 +77,7 @@ export interface CreationAction {
|
|
|
95
77
|
actionId: string;
|
|
96
78
|
requestHash: string;
|
|
97
79
|
roleId: string;
|
|
98
|
-
session:
|
|
80
|
+
session: SessionBackendId;
|
|
99
81
|
lifetime: 'permanent' | 'temporary';
|
|
100
82
|
state: CreationStage;
|
|
101
83
|
stages: Array<{
|
|
@@ -121,9 +103,8 @@ export interface RoleCreationServiceOptions {
|
|
|
121
103
|
tempLauncher?: SupervisorLauncher;
|
|
122
104
|
allowedCwdRoots?: string[];
|
|
123
105
|
journalDir?: string;
|
|
124
|
-
probeReady?: (name: string, session:
|
|
106
|
+
probeReady?: (name: string, session: SessionBackendId) => Promise<'ready' | 'attention' | 'unknown'>;
|
|
125
107
|
onProgress?: (action: CreationAction) => void;
|
|
126
|
-
modelCatalogs?: Partial<Record<'codex' | 'claude-code', () => HarnessModelCatalog>>;
|
|
127
108
|
/** Direct/managed callers must not create or restore the web action journal. */
|
|
128
109
|
journal?: boolean;
|
|
129
110
|
}
|
|
@@ -1,17 +1,16 @@
|
|
|
1
1
|
import { createHash, randomUUID } from 'node:crypto';
|
|
2
2
|
import { mkdirSync, readFileSync, readdirSync, realpathSync, statSync } from 'node:fs';
|
|
3
3
|
import { isAbsolute, relative } from 'node:path';
|
|
4
|
-
import { loadConfig, NOTIFY_EVENT_TYPES, resolveMonitorConfig,
|
|
4
|
+
import { loadConfig, NOTIFY_EVENT_TYPES, resolveMonitorConfig, resolvePermissions, ROLE_NAME_RE, validateMonitorConfig, } from '../config.js';
|
|
5
5
|
import { daemonIdentityProvisioner, } from '../creation.js';
|
|
6
6
|
import { replaceFileAtomically } from '../atomic-file.js';
|
|
7
7
|
import { stateRoot } from '../paths.js';
|
|
8
|
-
import {
|
|
8
|
+
import { spawnDryRun, spawnPermanent, spawnTemp, validateSpawnOpts, } from '../spawn.js';
|
|
9
9
|
import { FleetError, normalizeError } from './errors.js';
|
|
10
10
|
import { inheritCallerSpawnDefaults } from '../fleet-proxy.js';
|
|
11
11
|
import { effectivePermissionMode } from '../permissions.js';
|
|
12
12
|
import { effectiveRoleModel } from '../model-env.js';
|
|
13
|
-
import {
|
|
14
|
-
import { claudeModelCatalog, codexModelCatalog, } from './model-catalog.js';
|
|
13
|
+
import { selectionOrigin, summarizeResolvedLaunch } from '../lifecycle-summary.js';
|
|
15
14
|
const canonical = (value) => {
|
|
16
15
|
if (Array.isArray(value))
|
|
17
16
|
return `[${value.map(canonical).join(',')}]`;
|
|
@@ -63,14 +62,31 @@ export class RoleCreationService {
|
|
|
63
62
|
const creationActionId = randomUUID();
|
|
64
63
|
plan.options.creationActionId = creationActionId;
|
|
65
64
|
const statePath = await this.launchSync(plan.options);
|
|
65
|
+
const selectionSummary = (kind) => {
|
|
66
|
+
const value = plan.options[kind];
|
|
67
|
+
const provenance = plan.inherited.includes(kind) ? 'inherited' : 'explicit';
|
|
68
|
+
if (!value)
|
|
69
|
+
return `unresolved (${provenance})`;
|
|
70
|
+
if ('ref' in value)
|
|
71
|
+
return `ref:${value.ref} (${provenance})`;
|
|
72
|
+
const fingerprint = hash(value.inline).slice(0, 16);
|
|
73
|
+
return `inline:sha256:${fingerprint} (${provenance})`;
|
|
74
|
+
};
|
|
75
|
+
const permissionMode = effectivePermissionMode(plan.preview.resolvedRole);
|
|
66
76
|
return {
|
|
67
77
|
caller: plan.caller, role: plan.options.name,
|
|
68
78
|
lifetime: plan.options.temp ? 'temporary' : 'permanent', statePath,
|
|
69
79
|
harness: plan.preview.resolvedRole.harness, session: plan.preview.resolvedRole.session,
|
|
70
80
|
...(effectiveRoleModel(plan.preview.resolvedRole) ? { model: effectiveRoleModel(plan.preview.resolvedRole) } : {}),
|
|
71
81
|
monitor: { mode: plan.preview.resolvedRole.monitor.mode, interrupt: plan.preview.resolvedRole.monitor.interrupt },
|
|
72
|
-
permissionMode
|
|
82
|
+
permissionMode, inherited: plan.inherited,
|
|
73
83
|
creationActionId,
|
|
84
|
+
brainSummary: selectionSummary('brain'), roleSummary: selectionSummary('role'),
|
|
85
|
+
configuration: summarizeResolvedLaunch(plan.preview.resolvedRole, {
|
|
86
|
+
role: selectionOrigin(plan.options.role ?? plan.options.agentDefinition?.role),
|
|
87
|
+
brain: selectionOrigin(plan.options.brain ?? plan.options.agentDefinition?.brain),
|
|
88
|
+
permissionMode,
|
|
89
|
+
}),
|
|
74
90
|
};
|
|
75
91
|
}
|
|
76
92
|
launchSync(options, creation) {
|
|
@@ -81,47 +97,16 @@ export class RoleCreationService {
|
|
|
81
97
|
async capabilities() {
|
|
82
98
|
const reasons = [];
|
|
83
99
|
let defaults = {};
|
|
84
|
-
let roles = [];
|
|
85
100
|
try {
|
|
86
101
|
const config = loadConfig(this.options.configPath);
|
|
87
102
|
defaults = config.defaults;
|
|
88
|
-
roles = config.roles;
|
|
89
103
|
}
|
|
90
104
|
catch (error) {
|
|
91
105
|
reasons.push(`configuration is invalid: ${error.message}`);
|
|
92
106
|
}
|
|
93
|
-
const modelsFor = (harness, catalog) => {
|
|
94
|
-
const configured = roles.filter(role => role.harness === harness)
|
|
95
|
-
.flatMap(role => [role.model, ...(role.model_chain ?? [])])
|
|
96
|
-
.filter((model) => Boolean(model));
|
|
97
|
-
const inherited = resolveRoleModel(undefined, harness, defaults);
|
|
98
|
-
const configuredOptions = [...new Set([...(inherited ? [inherited] : []), ...configured])]
|
|
99
|
-
.filter(id => !catalog.models.some(model => model.id === id))
|
|
100
|
-
.map(id => ({ id, label: `${id} (configured)`, reasoningEfforts: [], source: 'fleet-config' }));
|
|
101
|
-
const modelOptions = [...configuredOptions, ...catalog.models];
|
|
102
|
-
return { modelOptions, models: modelOptions.map(model => model.id) };
|
|
103
|
-
};
|
|
104
|
-
const codexCatalog = this.options.modelCatalogs?.codex?.() ?? codexModelCatalog();
|
|
105
|
-
const claudeCatalog = this.options.modelCatalogs?.['claude-code']?.() ?? claudeModelCatalog();
|
|
106
|
-
const codexModels = modelsFor('codex', codexCatalog);
|
|
107
|
-
const claudeModels = modelsFor('claude-code', claudeCatalog);
|
|
108
107
|
return {
|
|
109
108
|
available: reasons.length === 0,
|
|
110
109
|
reasons,
|
|
111
|
-
harnesses: [
|
|
112
|
-
{
|
|
113
|
-
id: 'codex', available: true, sessions: ['acp'],
|
|
114
|
-
defaultModel: resolveRoleModel(undefined, 'codex', defaults),
|
|
115
|
-
...codexModels, catalogSource: 'codex-runtime-catalog', customModelAllowed: true,
|
|
116
|
-
warnings: codexCatalog.warnings,
|
|
117
|
-
},
|
|
118
|
-
{
|
|
119
|
-
id: 'claude-code', available: true, sessions: ['acp'],
|
|
120
|
-
defaultModel: resolveRoleModel(undefined, 'claude-code', defaults),
|
|
121
|
-
...claudeModels, catalogSource: 'claude-adapter-2.1', customModelAllowed: true,
|
|
122
|
-
warnings: claudeCatalog.warnings,
|
|
123
|
-
},
|
|
124
|
-
],
|
|
125
110
|
lifetimes: ['permanent', 'temporary'],
|
|
126
111
|
identityBootstrap: {
|
|
127
112
|
mode: 'current-fleet-first-boot',
|
|
@@ -145,14 +130,12 @@ export class RoleCreationService {
|
|
|
145
130
|
const defaults = cfg.defaults;
|
|
146
131
|
const opts = this.spawnOptions(request);
|
|
147
132
|
validateSpawnOpts(opts);
|
|
148
|
-
|
|
133
|
+
const resolved = spawnDryRun(opts).resolvedRole;
|
|
149
134
|
const cwd = request.cwd ? this.resolveCwd(request.cwd) : undefined;
|
|
150
135
|
const effective = {
|
|
151
136
|
name: request.name, identity: request.name,
|
|
152
|
-
harness:
|
|
153
|
-
|
|
154
|
-
model: resolveRoleModel(request.model, request.harness, defaults),
|
|
155
|
-
reasoningEffort: request.reasoningEffort ?? undefined,
|
|
137
|
+
harness: resolved.harness, session: resolved.session, model: resolved.model,
|
|
138
|
+
reasoningEffort: resolved.effort,
|
|
156
139
|
cwd, lifetime: request.lifetime,
|
|
157
140
|
permissions: resolvePermissions(defaults.permissions, request.permissions),
|
|
158
141
|
monitor: resolveMonitorConfig(defaults.monitor, request.monitor),
|
|
@@ -184,9 +167,7 @@ export class RoleCreationService {
|
|
|
184
167
|
if (existingIdentity === 'unknown' && !request.unverifiedIdentityAcknowledged)
|
|
185
168
|
prerequisites.push('confirm creation with an unverified identity preflight');
|
|
186
169
|
const provenance = {
|
|
187
|
-
|
|
188
|
-
model: request.model !== undefined ? 'request'
|
|
189
|
-
: resolveRoleModel(undefined, request.harness, defaults) ? 'fleet-default' : 'built-in',
|
|
170
|
+
brain: 'request', role: 'request', identity: 'built-in',
|
|
190
171
|
cwd: request.cwd ? 'request' : 'built-in', permissions: 'request',
|
|
191
172
|
monitor: request.monitor ? 'request' : defaults.monitor ? 'fleet-default' : 'built-in',
|
|
192
173
|
};
|
|
@@ -297,8 +278,8 @@ export class RoleCreationService {
|
|
|
297
278
|
}
|
|
298
279
|
validate(input) {
|
|
299
280
|
const allowed = new Set([
|
|
300
|
-
'name', '
|
|
301
|
-
'coordinator', 'permissions', '
|
|
281
|
+
'name', 'brain', 'role', 'cwd', 'lifetime',
|
|
282
|
+
'coordinator', 'permissions', 'monitor', 'openAfterCreate',
|
|
302
283
|
'highRiskAcknowledged', 'reuseExistingIdentityAcknowledged',
|
|
303
284
|
'unverifiedIdentityAcknowledged',
|
|
304
285
|
]);
|
|
@@ -308,26 +289,11 @@ export class RoleCreationService {
|
|
|
308
289
|
throw new FleetError('invalid_request', `unsupported web creation field: ${unsupported[0]}`);
|
|
309
290
|
if (!ROLE_NAME_RE.test(input.name))
|
|
310
291
|
throw new FleetError('invalid_request', 'invalid role name');
|
|
311
|
-
if (!
|
|
312
|
-
throw new FleetError('invalid_request', '
|
|
313
|
-
if (input.session !== 'acp')
|
|
314
|
-
throw new FleetError('invalid_request', 'unsupported session backend');
|
|
292
|
+
if (!input.brain || !input.role)
|
|
293
|
+
throw new FleetError('invalid_request', 'brain and role selections are required');
|
|
315
294
|
if (!['permanent', 'temporary'].includes(input.lifetime))
|
|
316
295
|
throw new FleetError('invalid_request', 'unsupported lifetime');
|
|
317
|
-
bounded(input.model ?? undefined, 'model', 128);
|
|
318
|
-
bounded(input.reasoningEffort ?? undefined, 'reasoning effort', 16);
|
|
319
|
-
if (input.reasoningEffort != null) {
|
|
320
|
-
try {
|
|
321
|
-
getAdapter(input.harness).agentSession.resolveBrain({ effort: input.reasoningEffort });
|
|
322
|
-
}
|
|
323
|
-
catch (error) {
|
|
324
|
-
throw new FleetError('invalid_request', error.message);
|
|
325
|
-
}
|
|
326
|
-
}
|
|
327
|
-
bounded(input.mission, 'mission', 4_096);
|
|
328
296
|
bounded(input.coordinator, 'coordinator', 128);
|
|
329
|
-
bounded(input.bio, 'bio', 8_192);
|
|
330
|
-
bounded(input.persona, 'persona', 16_384);
|
|
331
297
|
resolvePermissions(undefined, input.permissions);
|
|
332
298
|
if (input.monitor) {
|
|
333
299
|
const problems = validateMonitorConfig(input.monitor);
|
|
@@ -337,10 +303,8 @@ export class RoleCreationService {
|
|
|
337
303
|
throw new FleetError('invalid_request', 'web creation supports monitor.inject=notification only');
|
|
338
304
|
}
|
|
339
305
|
return {
|
|
340
|
-
...input,
|
|
341
|
-
|
|
342
|
-
mission: input.mission?.trim() || undefined, coordinator: input.coordinator?.trim() || undefined,
|
|
343
|
-
bio: input.bio?.trim() || undefined, persona: input.persona?.trim() || undefined,
|
|
306
|
+
...input, brain: structuredClone(input.brain), role: structuredClone(input.role),
|
|
307
|
+
coordinator: input.coordinator?.trim() || undefined,
|
|
344
308
|
monitor: input.monitor ? structuredClone(input.monitor) : undefined,
|
|
345
309
|
};
|
|
346
310
|
}
|
|
@@ -367,12 +331,10 @@ export class RoleCreationService {
|
|
|
367
331
|
spawnOptions(request, creationActionId) {
|
|
368
332
|
return {
|
|
369
333
|
name: request.name, temp: request.lifetime === 'temporary',
|
|
370
|
-
identity: request.name,
|
|
371
|
-
|
|
372
|
-
reasoningEffort: request.reasoningEffort,
|
|
373
|
-
mission: request.mission, coordinator: request.coordinator,
|
|
334
|
+
identity: request.name, brain: request.brain, role: request.role, cwd: request.cwd,
|
|
335
|
+
coordinator: request.coordinator,
|
|
374
336
|
approval: request.permissions.approval, filesystem: request.permissions.filesystem,
|
|
375
|
-
unattended: request.permissions.unattended,
|
|
337
|
+
unattended: request.permissions.unattended,
|
|
376
338
|
monitorConfig: request.monitor,
|
|
377
339
|
configPath: this.options.configPath,
|
|
378
340
|
surface: creationActionId ? 'web' : undefined, creationActionId,
|
|
@@ -1,10 +1,12 @@
|
|
|
1
|
+
import { type SessionBackendId } from '../config.js';
|
|
1
2
|
import type { RoleRecord } from './types.js';
|
|
2
3
|
export interface RoleRepositoryOptions {
|
|
3
4
|
configPath?: string;
|
|
4
5
|
permanentRoot?: string;
|
|
5
6
|
temporaryRoot?: string;
|
|
6
|
-
probeBackend?: (name: string, intended?:
|
|
7
|
-
acp
|
|
7
|
+
probeBackend?: (name: string, intended?: SessionBackendId) => Promise<{
|
|
8
|
+
acp?: boolean;
|
|
9
|
+
backend?: SessionBackendId;
|
|
8
10
|
}>;
|
|
9
11
|
concurrency?: number;
|
|
10
12
|
timeoutMs?: number;
|
|
@@ -44,9 +44,10 @@ function snapshot(path, name) {
|
|
|
44
44
|
throw new Error('snapshot must be a mapping');
|
|
45
45
|
if (raw.session === 'tmux')
|
|
46
46
|
throw new Error('session: tmux is no longer supported; use session: acp with the Codex or Claude Code adapter');
|
|
47
|
-
if (raw.session !== undefined && raw.session !== 'acp'
|
|
48
|
-
|
|
49
|
-
|
|
47
|
+
if (raw.session !== undefined && raw.session !== 'acp'
|
|
48
|
+
&& raw.session !== 'codex-app-server')
|
|
49
|
+
throw new Error(`unsupported session '${String(raw.session)}'; expected session: acp or codex-app-server`);
|
|
50
|
+
const session = raw.session ?? 'acp';
|
|
50
51
|
return {
|
|
51
52
|
role: {
|
|
52
53
|
...raw, name, harness: typeof raw.harness === 'string' ? raw.harness : 'claude-code',
|
|
@@ -173,6 +174,8 @@ export class RoleRepository {
|
|
|
173
174
|
this.options.probeBackend(name, intended),
|
|
174
175
|
new Promise(resolve => setTimeout(() => resolve({ acp: false }), timeoutMs)),
|
|
175
176
|
]).catch(() => ({ acp: false }));
|
|
177
|
+
if (result.backend)
|
|
178
|
+
return result.backend;
|
|
176
179
|
if (result.acp)
|
|
177
180
|
return 'acp';
|
|
178
181
|
return 'none';
|
|
@@ -71,7 +71,7 @@ export interface RoleSessionControl {
|
|
|
71
71
|
onClose(reason?: string): void;
|
|
72
72
|
}): Promise<ConversationFollowHandle>;
|
|
73
73
|
}
|
|
74
|
-
export declare class
|
|
74
|
+
export declare class RoleSessionControlAdapter implements RoleSessionControl {
|
|
75
75
|
private readonly stateDir;
|
|
76
76
|
private readonly request;
|
|
77
77
|
constructor(stateDir: string, request?: typeof controlRequest);
|
|
@@ -119,3 +119,5 @@ export declare class AcpRoleSessionAdapter implements RoleSessionControl {
|
|
|
119
119
|
}>;
|
|
120
120
|
private call;
|
|
121
121
|
}
|
|
122
|
+
/** @deprecated Compatibility name; control is provider-neutral. */
|
|
123
|
+
export { RoleSessionControlAdapter as AcpRoleSessionAdapter };
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { controlRequest, followConversation } from '../session/control.js';
|
|
2
2
|
import { FleetError, normalizeError } from './errors.js';
|
|
3
3
|
const visibleEvents = (events) => events.filter(event => event.kind !== 'thought');
|
|
4
|
-
export class
|
|
4
|
+
export class RoleSessionControlAdapter {
|
|
5
5
|
stateDir;
|
|
6
6
|
request;
|
|
7
7
|
constructor(stateDir, request = controlRequest) {
|
|
@@ -12,7 +12,7 @@ export class AcpRoleSessionAdapter {
|
|
|
12
12
|
const response = await this.call('snapshot');
|
|
13
13
|
const result = response;
|
|
14
14
|
return {
|
|
15
|
-
backend:
|
|
15
|
+
backend: result.backend, protocolVersion: result.protocolVersion ?? 1,
|
|
16
16
|
features: result.features ?? [], snapshot: result,
|
|
17
17
|
};
|
|
18
18
|
}
|
|
@@ -147,3 +147,5 @@ export class AcpRoleSessionAdapter {
|
|
|
147
147
|
}
|
|
148
148
|
}
|
|
149
149
|
}
|
|
150
|
+
/** @deprecated Compatibility name; control is provider-neutral. */
|
|
151
|
+
export { RoleSessionControlAdapter as AcpRoleSessionAdapter };
|
|
@@ -2,7 +2,10 @@ import { type FleetConfig } from '../config.js';
|
|
|
2
2
|
import { type CoworkAdapter } from '../rooms-tasks/cowork-adapter.js';
|
|
3
3
|
import { provisionMembers } from '../rooms-tasks/provision.js';
|
|
4
4
|
import { moveTaskToList } from '../rooms-tasks/task-state.js';
|
|
5
|
-
import
|
|
5
|
+
import { type MemberOverrides } from '../rooms-tasks/member-overrides.js';
|
|
6
|
+
import { type TaskDeletionSettleResult } from '../rooms-tasks/deletion.js';
|
|
7
|
+
import type { RoomLaunchPolicy, RoomOrchestrationRecord, TaskListRecord, TaskOrigin, TaskOutcome, TaskRecord, TaskState, TemplateSnapshot } from '../rooms-tasks/types.js';
|
|
8
|
+
import type { TaskDeletionAcceptance } from '../rooms-tasks/task-state.js';
|
|
6
9
|
export type TaskRoomActor = {
|
|
7
10
|
kind: 'local_control';
|
|
8
11
|
surface: 'cli' | 'web';
|
|
@@ -37,14 +40,17 @@ export interface TaskRecoveryResult {
|
|
|
37
40
|
export type TaskRecoveryBegin = {
|
|
38
41
|
kind: 'terminal_worker_required';
|
|
39
42
|
taskId: string;
|
|
43
|
+
} | {
|
|
44
|
+
kind: 'deletion_worker_required';
|
|
45
|
+
taskId: string;
|
|
40
46
|
} | {
|
|
41
47
|
kind: 'final';
|
|
42
48
|
result: TaskRecoveryResult;
|
|
43
49
|
};
|
|
44
50
|
export declare class TaskRoomApplicationError extends Error {
|
|
45
|
-
readonly code: 'template_not_found' | 'task_template_drift' | 'template_mismatch' | 'task_terminal' | 'task_terminal_already' | 'task_non_resumable' | 'room_not_found' | 'room_record_not_found';
|
|
51
|
+
readonly code: 'template_not_found' | 'task_template_drift' | 'template_mismatch' | 'task_terminal' | 'task_terminal_already' | 'task_non_resumable' | 'task_deleting' | 'room_not_found' | 'room_record_not_found';
|
|
46
52
|
readonly fields: Readonly<Record<string, string>>;
|
|
47
|
-
constructor(code: 'template_not_found' | 'task_template_drift' | 'template_mismatch' | 'task_terminal' | 'task_terminal_already' | 'task_non_resumable' | 'room_not_found' | 'room_record_not_found', message: string, fields?: Readonly<Record<string, string>>);
|
|
53
|
+
constructor(code: 'template_not_found' | 'task_template_drift' | 'template_mismatch' | 'task_terminal' | 'task_terminal_already' | 'task_non_resumable' | 'task_deleting' | 'room_not_found' | 'room_record_not_found', message: string, fields?: Readonly<Record<string, string>>);
|
|
48
54
|
}
|
|
49
55
|
export interface CreateTaskRequest {
|
|
50
56
|
actor: TaskRoomActor;
|
|
@@ -57,6 +63,8 @@ export interface CreateTaskRequest {
|
|
|
57
63
|
idempotencyKey?: string;
|
|
58
64
|
origin: TaskOrigin;
|
|
59
65
|
list?: string;
|
|
66
|
+
members?: MemberOverrides;
|
|
67
|
+
anonymous?: boolean;
|
|
60
68
|
}
|
|
61
69
|
export interface CreateRoomRequest {
|
|
62
70
|
actor: TaskRoomActor;
|
|
@@ -65,13 +73,19 @@ export interface CreateRoomRequest {
|
|
|
65
73
|
goal?: string;
|
|
66
74
|
brief?: string;
|
|
67
75
|
briefFile?: string;
|
|
76
|
+
members?: MemberOverrides;
|
|
77
|
+
anonymous?: boolean;
|
|
68
78
|
}
|
|
79
|
+
export declare function resolveRoomLaunchPolicy(template: TemplateSnapshot | undefined, override: boolean | undefined): RoomLaunchPolicy;
|
|
69
80
|
export interface TaskRoomServiceDeps {
|
|
70
81
|
loadConfiguration?(path?: string): FleetConfig;
|
|
71
82
|
cowork?(config: FleetConfig): CoworkAdapter;
|
|
72
83
|
binPath?(): string;
|
|
73
84
|
provisionMembers?: typeof provisionMembers;
|
|
74
85
|
moveTaskToList?: typeof moveTaskToList;
|
|
86
|
+
launchDeletionWorker?(taskId: string): Promise<void>;
|
|
87
|
+
sleep?(ms: number): Promise<void>;
|
|
88
|
+
now?(): number;
|
|
75
89
|
}
|
|
76
90
|
/** Exact extraction of the previously CLI-owned task create/start behavior. */
|
|
77
91
|
export declare class TaskRoomApplicationService {
|
|
@@ -84,15 +98,20 @@ export declare class TaskRoomApplicationService {
|
|
|
84
98
|
startTask(input: {
|
|
85
99
|
actor: TaskRoomActor;
|
|
86
100
|
taskId: string;
|
|
101
|
+
template?: string;
|
|
102
|
+
members?: MemberOverrides;
|
|
103
|
+
anonymous?: boolean;
|
|
87
104
|
}): Promise<TaskRecord>;
|
|
88
105
|
listTasks(filter?: {
|
|
89
106
|
state?: TaskState | TaskState[];
|
|
90
107
|
list?: string;
|
|
108
|
+
includeDeleting?: boolean;
|
|
91
109
|
}): TaskRecord[];
|
|
92
110
|
listTaskLists(): TaskListRecord[];
|
|
93
111
|
groupedTasks(filter?: {
|
|
94
112
|
state?: TaskState | TaskState[];
|
|
95
113
|
list?: string;
|
|
114
|
+
includeDeleting?: boolean;
|
|
96
115
|
}): Array<{
|
|
97
116
|
list: TaskListRecord;
|
|
98
117
|
tasks: TaskRecord[];
|
|
@@ -137,10 +156,40 @@ export declare class TaskRoomApplicationService {
|
|
|
137
156
|
actor: TaskRoomActor;
|
|
138
157
|
taskId: string;
|
|
139
158
|
}): TaskRecord;
|
|
140
|
-
|
|
159
|
+
private deletionActor;
|
|
160
|
+
/** Accept a permanent deletion in any lifecycle state; audit at acceptance. */
|
|
161
|
+
requestTaskDeletion(input: {
|
|
162
|
+
actor: TaskRoomActor;
|
|
163
|
+
taskId: string;
|
|
164
|
+
}): Promise<TaskDeletionAcceptance>;
|
|
165
|
+
/** Worker entry: converge an accepted deletion; Cowork is resolved lazily. */
|
|
166
|
+
settleTaskDeletion(input: {
|
|
167
|
+
actor: {
|
|
168
|
+
kind: 'internal_worker';
|
|
169
|
+
surface: 'cli';
|
|
170
|
+
};
|
|
171
|
+
taskId: string;
|
|
172
|
+
}): Promise<TaskDeletionSettleResult>;
|
|
173
|
+
/**
|
|
174
|
+
* Launch the external deletion worker outside the caller's lifecycle and
|
|
175
|
+
* wait boundedly for physical absence. Timeouts and launch failures report
|
|
176
|
+
* a pending, recoverable state — never success. A concurrent worker that
|
|
177
|
+
* already removed the record reads as settled.
|
|
178
|
+
*/
|
|
179
|
+
launchTaskDeletionWorker(input: {
|
|
180
|
+
taskId: string;
|
|
181
|
+
waitMs?: number;
|
|
182
|
+
}): Promise<{
|
|
183
|
+
deleted: boolean;
|
|
184
|
+
pending: boolean;
|
|
185
|
+
error?: string;
|
|
186
|
+
}>;
|
|
187
|
+
recordDeletionError(input: {
|
|
141
188
|
actor: TaskRoomActor;
|
|
142
189
|
taskId: string;
|
|
143
|
-
|
|
190
|
+
error: string;
|
|
191
|
+
recoveryHint: string;
|
|
192
|
+
}): Promise<TaskRecord>;
|
|
144
193
|
completeTask(input: {
|
|
145
194
|
actor: TaskRoomActor;
|
|
146
195
|
taskId: string;
|
|
@@ -179,7 +228,7 @@ export declare class TaskRoomApplicationService {
|
|
|
179
228
|
name: string;
|
|
180
229
|
version: number;
|
|
181
230
|
description: string;
|
|
182
|
-
|
|
231
|
+
sourceFile?: string;
|
|
183
232
|
room?: import("../rooms-tasks/types.js").TemplateRoomConfig;
|
|
184
233
|
contract?: string;
|
|
185
234
|
members: import("../rooms-tasks/types.js").TemplateMemberSlot[];
|
|
@@ -197,6 +246,7 @@ export declare class TaskRoomApplicationService {
|
|
|
197
246
|
identity_cid: string;
|
|
198
247
|
room_name: string;
|
|
199
248
|
state: "provisioning" | "active" | "closing" | "closed";
|
|
249
|
+
anonymous: boolean;
|
|
200
250
|
seats: import("../rooms-tasks/cowork-adapter.js").CoworkSeatInfo[];
|
|
201
251
|
goal?: string;
|
|
202
252
|
briefing?: string;
|
|
@@ -252,6 +302,8 @@ export declare class TaskRoomApplicationService {
|
|
|
252
302
|
actor: TaskRoomActor;
|
|
253
303
|
taskId: string;
|
|
254
304
|
template?: string;
|
|
305
|
+
members?: MemberOverrides;
|
|
306
|
+
anonymous?: boolean;
|
|
255
307
|
}): Promise<{
|
|
256
308
|
task: TaskRecord;
|
|
257
309
|
status: 'ready' | 'already_active';
|