@ours.network/fleet 1.1.0-nightly.8 → 1.1.0
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 +231 -46
- package/dist/application/capabilities.js +18 -6
- package/dist/application/fleet-query-service.js +7 -4
- package/dist/application/role-command-service.js +9 -0
- package/dist/application/role-creation-service.d.ts +4 -4
- package/dist/application/role-creation-service.js +9 -2
- 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 +92 -39
- package/dist/application/task-room-service.js +579 -173
- package/dist/briefing.js +85 -28
- package/dist/build-info.json +5 -5
- package/dist/canonical-json.d.ts +2 -0
- package/dist/canonical-json.js +10 -0
- package/dist/cli.js +130 -55
- package/dist/config.d.ts +38 -3
- package/dist/config.js +193 -28
- package/dist/creation.d.ts +1 -1
- package/dist/creation.js +7 -4
- package/dist/docs.d.ts +1 -1
- package/dist/docs.js +193 -55
- package/dist/doctor.d.ts +2 -0
- package/dist/doctor.js +40 -4
- package/dist/fleet-command-audit.d.ts +59 -9
- package/dist/fleet-command-audit.js +426 -63
- package/dist/fleet-proxy.d.ts +5 -2
- package/dist/harness/claude-code-session.js +2 -1
- 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 +9 -2
- package/dist/harness/codex-session.js +18 -2
- package/dist/harness/codex.d.ts +5 -1
- package/dist/harness/codex.js +104 -10
- package/dist/harness/types.d.ts +1 -1
- package/dist/index.d.ts +4 -3
- package/dist/index.js +3 -2
- package/dist/init-guidance.d.ts +1 -1
- package/dist/init-guidance.js +1 -1
- package/dist/init-wizard.d.ts +98 -0
- package/dist/init-wizard.js +631 -0
- package/dist/lifecycle-summary.d.ts +134 -0
- package/dist/lifecycle-summary.js +179 -0
- package/dist/loops/config.d.ts +10 -1
- package/dist/loops/config.js +38 -5
- package/dist/model-recovery.d.ts +1 -1
- package/dist/ops.js +2 -17
- package/dist/owner-channel/channel.d.ts +21 -5
- package/dist/owner-channel/channel.js +312 -138
- package/dist/owner-channel/commands.d.ts +28 -6
- package/dist/owner-channel/commands.js +109 -27
- package/dist/owner-channel/lifecycle-outbox.d.ts +24 -0
- package/dist/owner-channel/lifecycle-outbox.js +87 -0
- package/dist/owner-channel/ours-client.d.ts +19 -0
- package/dist/owner-channel/ours-client.js +3 -0
- 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-migration.d.ts +42 -0
- package/dist/preset-migration.js +450 -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 +13 -1
- package/dist/rooms-tasks/cli.d.ts +2 -0
- package/dist/rooms-tasks/cli.js +434 -279
- package/dist/rooms-tasks/close.d.ts +9 -1
- package/dist/rooms-tasks/close.js +23 -7
- package/dist/rooms-tasks/config.js +16 -25
- package/dist/rooms-tasks/cowork-adapter.d.ts +5 -0
- package/dist/rooms-tasks/cowork-adapter.js +13 -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 +8 -0
- package/dist/rooms-tasks/external-worker.js +38 -0
- package/dist/rooms-tasks/launch-snapshot.d.ts +19 -0
- package/dist/rooms-tasks/launch-snapshot.js +181 -0
- package/dist/rooms-tasks/member-overrides.d.ts +30 -0
- package/dist/rooms-tasks/member-overrides.js +204 -0
- package/dist/rooms-tasks/member-startup.d.ts +1 -0
- package/dist/rooms-tasks/member-startup.js +9 -2
- package/dist/rooms-tasks/provision.js +146 -56
- package/dist/rooms-tasks/room-state.d.ts +1 -0
- package/dist/rooms-tasks/room-state.js +12 -1
- package/dist/rooms-tasks/task-room-name.d.ts +12 -0
- package/dist/rooms-tasks/task-room-name.js +61 -0
- 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 -1
- package/dist/rooms-tasks/templates.js +34 -3
- package/dist/rooms-tasks/terminal.d.ts +3 -0
- package/dist/rooms-tasks/terminal.js +10 -4
- package/dist/rooms-tasks/types.d.ts +92 -7
- package/dist/rooms-tasks/types.js +14 -1
- package/dist/runner.d.ts +3 -0
- package/dist/runner.js +92 -33
- package/dist/session/acp.d.ts +4 -1
- package/dist/session/acp.js +29 -13
- 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 +2 -2
- package/dist/session/control.js +18 -2
- 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 +9 -0
- package/dist/spawn.js +77 -9
- package/dist/web/fleet-config-service.d.ts +1 -0
- package/dist/web/fleet-config-service.js +25 -7
- package/dist/web/runtime.js +11 -6
- package/dist/web/server.js +28 -1
- package/dist/web-app/assets/{index-BbTc5KtZ.js → index-C0h3ALvs.js} +8 -8
- package/dist/web-app/index.html +1 -1
- package/package.json +4 -4
- package/presets/brain-catalog.json +17 -0
- package/presets/fleet/{agents → agent_templates}/Critic.yaml +2 -0
- package/presets/fleet/{agents/Agent.yaml → agent_templates/Developer.yaml} +3 -1
- package/presets/fleet/agent_templates/LocalCoordinator.yaml +50 -0
- package/presets/fleet/agents/{Developer.yaml → FleetCoordinator.yaml} +1 -1
- 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/brains/codex-gpt-6-astra-high.yaml +5 -0
- package/presets/fleet/brains/codex-gpt-6-astra-low.yaml +5 -0
- package/presets/fleet/brains/codex-gpt-6-astra-max.yaml +5 -0
- package/presets/fleet/brains/codex-gpt-6-astra-medium.yaml +5 -0
- package/presets/fleet/brains/codex-gpt-6-astra-ultra.yaml +5 -0
- package/presets/fleet/brains/codex-gpt-6-astra-xhigh.yaml +5 -0
- package/presets/fleet/roles/Coordinator.yaml +37 -0
- package/presets/fleet/roles/Critic.yaml +23 -1
- package/presets/fleet/roles/Developer.yaml +27 -5
- package/presets/fleet/roles/LocalCoordinator.yaml +35 -0
- package/presets/fleet/room_templates/pair.yaml +9 -7
- package/presets/fleet/room_templates/single.yaml +5 -4
- package/presets/fleet/room_templates/team.yaml +12 -8
- package/presets/manifest.json +2 -1
- package/presets/fleet/agents/Architect.yaml +0 -3
- package/presets/fleet/agents/Secretary.yaml +0 -3
- package/presets/fleet/agents/Tester.yaml +0 -3
- package/presets/fleet/roles/Agent.yaml +0 -6
- package/presets/fleet/roles/Architect.yaml +0 -6
- package/presets/fleet/roles/Secretary.yaml +0 -6
- package/presets/fleet/roles/Tester.yaml +0 -6
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
import type { AgentSelection, ApprovalMode, FilesystemMode, FleetPermissionMode, MonitorInterrupt, MonitorMode, ResolvedRole, SessionBackendId, UnattendedMode } from './config.js';
|
|
2
|
+
import type { IsolationBackendId, NetworkMode, OnUnavailable } from './isolation/types.js';
|
|
3
|
+
/**
|
|
4
|
+
* Operator-facing launch configuration captured at the launch boundary from
|
|
5
|
+
* the exact ResolvedRole that was spawned. It is the single source for every
|
|
6
|
+
* Fleet lifecycle/report surface (CLI and owner-channel/Messenger).
|
|
7
|
+
*
|
|
8
|
+
* Security boundary: this object is a strict whitelist. It must never carry
|
|
9
|
+
* env, cwd or any local path, harness_options, session_options, owner_channel,
|
|
10
|
+
* or auth_proxy content. Hashes are secondary provenance only, never the
|
|
11
|
+
* primary description.
|
|
12
|
+
*/
|
|
13
|
+
export interface AgentLaunchConfiguration {
|
|
14
|
+
version: 1;
|
|
15
|
+
/** Agent template / launch definition label when one was selected. */
|
|
16
|
+
template?: string;
|
|
17
|
+
role: SelectionOrigin;
|
|
18
|
+
brain: SelectionOrigin;
|
|
19
|
+
harness: string;
|
|
20
|
+
session: SessionBackendId;
|
|
21
|
+
/**
|
|
22
|
+
* Model observed effective at launch. `null` reports runtime behavior — the
|
|
23
|
+
* harness ran its own default — not whether the author wrote `model: null`
|
|
24
|
+
* or omitted the field; effectiveRoleModel cannot distinguish those.
|
|
25
|
+
*/
|
|
26
|
+
model: string | null;
|
|
27
|
+
effort?: string;
|
|
28
|
+
/** Concise first-line mission label (or Cowork-role fallback), never the full mission. */
|
|
29
|
+
mission?: string;
|
|
30
|
+
approval: ApprovalMode;
|
|
31
|
+
filesystem: FilesystemMode;
|
|
32
|
+
unattended: UnattendedMode;
|
|
33
|
+
/** Portable policy plus the exact native runtime mode after harness_options. */
|
|
34
|
+
permissionMode: {
|
|
35
|
+
fleetMode: FleetPermissionMode;
|
|
36
|
+
nativeMode: string;
|
|
37
|
+
};
|
|
38
|
+
monitor: {
|
|
39
|
+
mode: MonitorMode;
|
|
40
|
+
interrupt: MonitorInterrupt;
|
|
41
|
+
};
|
|
42
|
+
/** Requested isolation policy only — never resolved runtime facts or host paths. */
|
|
43
|
+
isolation?: {
|
|
44
|
+
requested: IsolationBackendId;
|
|
45
|
+
on_unavailable?: OnUnavailable;
|
|
46
|
+
network?: NetworkMode;
|
|
47
|
+
read_mounts?: number;
|
|
48
|
+
write_mounts?: number;
|
|
49
|
+
};
|
|
50
|
+
/** Present only for temporary agents; prompt bodies are never presented. */
|
|
51
|
+
loops?: {
|
|
52
|
+
source: 'agent-template' | 'cli' | 'omitted';
|
|
53
|
+
policy: 'skip-if-busy';
|
|
54
|
+
entries: Array<{
|
|
55
|
+
name: string;
|
|
56
|
+
enabled: boolean;
|
|
57
|
+
intervalMs: number;
|
|
58
|
+
initialDelayMs: number;
|
|
59
|
+
jitterMs: number;
|
|
60
|
+
prompt: {
|
|
61
|
+
bytes: number;
|
|
62
|
+
sha256: string;
|
|
63
|
+
};
|
|
64
|
+
}>;
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
/** Where a Brain/Role selection came from; labels are human, hashes secondary. */
|
|
68
|
+
export type SelectionOrigin = {
|
|
69
|
+
kind: 'named';
|
|
70
|
+
ref: string;
|
|
71
|
+
} | {
|
|
72
|
+
kind: 'inline';
|
|
73
|
+
fingerprint?: string;
|
|
74
|
+
} | {
|
|
75
|
+
kind: 'unknown';
|
|
76
|
+
};
|
|
77
|
+
export declare const MISSION_LABEL_MAX = 80;
|
|
78
|
+
/**
|
|
79
|
+
* The inline fingerprint is always computed here from the canonical inline
|
|
80
|
+
* body; provenance can never be an arbitrary caller string.
|
|
81
|
+
*/
|
|
82
|
+
export declare function selectionOrigin(selection: AgentSelection | undefined): SelectionOrigin;
|
|
83
|
+
export declare function missionLabel(mission: string | undefined): string | undefined;
|
|
84
|
+
/**
|
|
85
|
+
* Build the presentation from the exact resolved launch state. `origins`
|
|
86
|
+
* carries the authoring-time selections and template label because a merged
|
|
87
|
+
* ResolvedRole no longer distinguishes preset references from inline bodies.
|
|
88
|
+
* `permissionMode` is required at capture time: every supported harness
|
|
89
|
+
* adapter reports it, and the managed-spawn receiver gets it over the wire
|
|
90
|
+
* and must never re-resolve mutable configuration.
|
|
91
|
+
*/
|
|
92
|
+
export declare function summarizeResolvedLaunch(role: ResolvedRole, origins: {
|
|
93
|
+
role: SelectionOrigin;
|
|
94
|
+
brain: SelectionOrigin;
|
|
95
|
+
template?: string;
|
|
96
|
+
permissionMode: {
|
|
97
|
+
fleetMode: FleetPermissionMode;
|
|
98
|
+
nativeMode: string;
|
|
99
|
+
};
|
|
100
|
+
/** Shown when the resolved role has no mission text (e.g. Cowork role name). */
|
|
101
|
+
missionFallback?: string;
|
|
102
|
+
}): AgentLaunchConfiguration;
|
|
103
|
+
/**
|
|
104
|
+
* Component budget for one rendered agent line. The complete mandatory
|
|
105
|
+
* rendering must always fit — that is a validity condition of a current-v1
|
|
106
|
+
* configuration, enforced by mandatoryConfigurationFits at the builder AND
|
|
107
|
+
* the wire boundary — while optional components (monitor, isolation) are
|
|
108
|
+
* dropped whole with a visible `…` marker past this budget.
|
|
109
|
+
*/
|
|
110
|
+
export declare const AGENT_LINE_MAX_CODE_POINTS = 1500;
|
|
111
|
+
export declare const AGENT_LINE_MAX_BYTES = 5000;
|
|
112
|
+
/**
|
|
113
|
+
* Validity condition of a current-v1 configuration: its complete mandatory
|
|
114
|
+
* rendering fits the per-line budget with the optional-omission suffix
|
|
115
|
+
* reserved. Escaping and code-fence growth (a value made of backticks can
|
|
116
|
+
* more than triple its code span) make this depend on rendered size, not raw
|
|
117
|
+
* field lengths, so both summarizeResolvedLaunch and the wire validator call
|
|
118
|
+
* this instead of trusting per-field caps.
|
|
119
|
+
*/
|
|
120
|
+
export declare function mandatoryConfigurationFits(configuration: AgentLaunchConfiguration): boolean;
|
|
121
|
+
/**
|
|
122
|
+
* Render one agent's configuration as a single escaped Markdown line segment.
|
|
123
|
+
* This is the only escaping boundary: callers pass raw values and must not
|
|
124
|
+
* escape the result again (it is safe as a markdownItems entry and inside
|
|
125
|
+
* owner-channel lifecycle messages). Every mandatory component always
|
|
126
|
+
* renders — mandatoryConfigurationFits guarantees the fit for every produced
|
|
127
|
+
* or wire-accepted configuration; only optional components may be dropped,
|
|
128
|
+
* whole (never splitting a Markdown span), with a visible `…`.
|
|
129
|
+
*/
|
|
130
|
+
export declare function renderAgentConfiguration(configuration: AgentLaunchConfiguration | undefined, fallback?: {
|
|
131
|
+
role?: string;
|
|
132
|
+
brain?: string;
|
|
133
|
+
permissions?: string;
|
|
134
|
+
}): string;
|
|
@@ -0,0 +1,179 @@
|
|
|
1
|
+
import { createHash } from 'node:crypto';
|
|
2
|
+
import { Buffer } from 'node:buffer';
|
|
3
|
+
import { canonicalJson } from './canonical-json.js';
|
|
4
|
+
import { effectiveRoleModel } from './model-env.js';
|
|
5
|
+
import { markdownCode, markdownProse } from './rooms-tasks/markdown.js';
|
|
6
|
+
const FINGERPRINT_HEX = 12;
|
|
7
|
+
export const MISSION_LABEL_MAX = 80;
|
|
8
|
+
/**
|
|
9
|
+
* The inline fingerprint is always computed here from the canonical inline
|
|
10
|
+
* body; provenance can never be an arbitrary caller string.
|
|
11
|
+
*/
|
|
12
|
+
export function selectionOrigin(selection) {
|
|
13
|
+
if (!selection)
|
|
14
|
+
return { kind: 'unknown' };
|
|
15
|
+
if ('ref' in selection)
|
|
16
|
+
return { kind: 'named', ref: selection.ref };
|
|
17
|
+
const fingerprint = createHash('sha256').update(canonicalJson(selection.inline)).digest('hex');
|
|
18
|
+
return { kind: 'inline', fingerprint: fingerprint.slice(0, FINGERPRINT_HEX) };
|
|
19
|
+
}
|
|
20
|
+
export function missionLabel(mission) {
|
|
21
|
+
const line = mission?.trim().split('\n', 1)[0]?.trim();
|
|
22
|
+
if (!line)
|
|
23
|
+
return undefined;
|
|
24
|
+
const points = Array.from(line);
|
|
25
|
+
return points.length > MISSION_LABEL_MAX
|
|
26
|
+
? `${points.slice(0, MISSION_LABEL_MAX - 1).join('')}…` : line;
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Build the presentation from the exact resolved launch state. `origins`
|
|
30
|
+
* carries the authoring-time selections and template label because a merged
|
|
31
|
+
* ResolvedRole no longer distinguishes preset references from inline bodies.
|
|
32
|
+
* `permissionMode` is required at capture time: every supported harness
|
|
33
|
+
* adapter reports it, and the managed-spawn receiver gets it over the wire
|
|
34
|
+
* and must never re-resolve mutable configuration.
|
|
35
|
+
*/
|
|
36
|
+
export function summarizeResolvedLaunch(role, origins) {
|
|
37
|
+
const mission = missionLabel(role.mission) ?? missionLabel(origins.missionFallback);
|
|
38
|
+
const fs = role.isolation?.fs;
|
|
39
|
+
const configuration = {
|
|
40
|
+
version: 1,
|
|
41
|
+
...(origins.template ? { template: origins.template } : {}),
|
|
42
|
+
role: origins.role,
|
|
43
|
+
brain: origins.brain,
|
|
44
|
+
harness: role.harness,
|
|
45
|
+
session: role.session,
|
|
46
|
+
model: effectiveRoleModel(role) ?? null,
|
|
47
|
+
...(role.effort ? { effort: role.effort } : {}),
|
|
48
|
+
...(mission ? { mission } : {}),
|
|
49
|
+
approval: role.permissions.approval,
|
|
50
|
+
filesystem: role.permissions.filesystem,
|
|
51
|
+
unattended: role.permissions.unattended,
|
|
52
|
+
permissionMode: origins.permissionMode,
|
|
53
|
+
monitor: { mode: role.monitor.mode, interrupt: role.monitor.interrupt },
|
|
54
|
+
...(role.isolation?.backend ? { isolation: {
|
|
55
|
+
requested: role.isolation.backend,
|
|
56
|
+
...(role.isolation.on_unavailable ? { on_unavailable: role.isolation.on_unavailable } : {}),
|
|
57
|
+
...(role.isolation.network ? { network: role.isolation.network } : {}),
|
|
58
|
+
...(fs?.read?.length ? { read_mounts: fs.read.length } : {}),
|
|
59
|
+
...(fs?.write?.length ? { write_mounts: fs.write.length } : {}),
|
|
60
|
+
} } : {}),
|
|
61
|
+
...(role.temporaryLoopSource ? { loops: {
|
|
62
|
+
source: role.temporaryLoopSource,
|
|
63
|
+
policy: 'skip-if-busy',
|
|
64
|
+
entries: (role.temporaryLoops ?? role.loops ?? []).map(loop => ({
|
|
65
|
+
name: loop.name, enabled: loop.enabled, intervalMs: loop.intervalMs,
|
|
66
|
+
initialDelayMs: loop.initialDelayMs, jitterMs: loop.jitterMs,
|
|
67
|
+
prompt: { bytes: loop.promptBytes, sha256: loop.promptHash },
|
|
68
|
+
})),
|
|
69
|
+
} } : {}),
|
|
70
|
+
};
|
|
71
|
+
// A configuration whose complete mandatory rendering cannot fit must never
|
|
72
|
+
// be produced; real resolved values sit far below the budget, so this is a
|
|
73
|
+
// capture defect, not an expected path.
|
|
74
|
+
if (!mandatoryConfigurationFits(configuration))
|
|
75
|
+
throw new Error('agent launch presentation exceeds the mandatory rendering budget');
|
|
76
|
+
return configuration;
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* Component budget for one rendered agent line. The complete mandatory
|
|
80
|
+
* rendering must always fit — that is a validity condition of a current-v1
|
|
81
|
+
* configuration, enforced by mandatoryConfigurationFits at the builder AND
|
|
82
|
+
* the wire boundary — while optional components (monitor, isolation) are
|
|
83
|
+
* dropped whole with a visible `…` marker past this budget.
|
|
84
|
+
*/
|
|
85
|
+
export const AGENT_LINE_MAX_CODE_POINTS = 1_500;
|
|
86
|
+
export const AGENT_LINE_MAX_BYTES = 5_000;
|
|
87
|
+
const codePoints = (value) => Array.from(value).length;
|
|
88
|
+
const utf8 = (value) => Buffer.byteLength(value, 'utf8');
|
|
89
|
+
const OPTIONAL_OMISSION_SUFFIX = '; …';
|
|
90
|
+
function selectionComponent(kind, value) {
|
|
91
|
+
if (value.kind === 'named')
|
|
92
|
+
return `${kind} preset ${markdownCode(value.ref)}`;
|
|
93
|
+
if (value.kind === 'inline')
|
|
94
|
+
return `inline ${kind}${value.fingerprint ? ` (def ${markdownCode(value.fingerprint)})` : ''}`;
|
|
95
|
+
return `${kind} unknown`;
|
|
96
|
+
}
|
|
97
|
+
/**
|
|
98
|
+
* The complete mandatory rendering: template, origins, mission, harness,
|
|
99
|
+
* model, effort, portable policy triple, and fleet/native permission mode.
|
|
100
|
+
* These must never be omitted from an operator-facing line.
|
|
101
|
+
*/
|
|
102
|
+
function mandatoryComponents(configuration) {
|
|
103
|
+
return [
|
|
104
|
+
configuration.template ? `template ${markdownCode(configuration.template)}` : undefined,
|
|
105
|
+
selectionComponent('Role', configuration.role),
|
|
106
|
+
configuration.mission ? `mission “${markdownProse(configuration.mission)}”` : undefined,
|
|
107
|
+
selectionComponent('Brain', configuration.brain),
|
|
108
|
+
`harness ${markdownCode(configuration.harness)}`,
|
|
109
|
+
`model ${configuration.model === null ? 'harness-default' : markdownCode(configuration.model)}`,
|
|
110
|
+
configuration.effort ? `effort ${markdownProse(configuration.effort)}` : undefined,
|
|
111
|
+
`approval=${configuration.approval}, filesystem=${configuration.filesystem}, `
|
|
112
|
+
+ `unattended=${configuration.unattended}`,
|
|
113
|
+
`mode ${configuration.permissionMode.fleetMode}/${markdownProse(configuration.permissionMode.nativeMode)}`,
|
|
114
|
+
].filter((part) => Boolean(part));
|
|
115
|
+
}
|
|
116
|
+
function optionalComponents(configuration) {
|
|
117
|
+
return [
|
|
118
|
+
`monitor ${configuration.monitor.mode}/${String(configuration.monitor.interrupt)}`,
|
|
119
|
+
configuration.isolation
|
|
120
|
+
? `isolation requested ${configuration.isolation.requested}`
|
|
121
|
+
+ `${configuration.isolation.network ? `, net ${configuration.isolation.network}` : ''}`
|
|
122
|
+
+ `${configuration.isolation.on_unavailable ? `, on-unavailable ${configuration.isolation.on_unavailable}` : ''}`
|
|
123
|
+
+ `${configuration.isolation.read_mounts || configuration.isolation.write_mounts
|
|
124
|
+
? `, mounts +${configuration.isolation.read_mounts ?? 0}ro/+${configuration.isolation.write_mounts ?? 0}rw` : ''}`
|
|
125
|
+
: undefined,
|
|
126
|
+
configuration.loops
|
|
127
|
+
? configuration.loops.source === 'omitted'
|
|
128
|
+
? 'temporary loops omitted (legacy behavior)'
|
|
129
|
+
: configuration.loops.entries.length === 0
|
|
130
|
+
? `temporary loops disabled (source ${configuration.loops.source})`
|
|
131
|
+
: `temporary loops ${configuration.loops.entries.map(loop => `${loop.name}:${loop.enabled ? 'enabled' : 'disabled'}`
|
|
132
|
+
+ ` interval=${loop.intervalMs}ms delay=${loop.initialDelayMs}ms jitter=${loop.jitterMs}ms`
|
|
133
|
+
+ ` prompt=${loop.prompt.bytes}B/${loop.prompt.sha256.slice(0, 12)}`).join(', ')}; policy skip-if-busy; source ${configuration.loops.source}`
|
|
134
|
+
: undefined,
|
|
135
|
+
].filter((part) => Boolean(part));
|
|
136
|
+
}
|
|
137
|
+
/**
|
|
138
|
+
* Validity condition of a current-v1 configuration: its complete mandatory
|
|
139
|
+
* rendering fits the per-line budget with the optional-omission suffix
|
|
140
|
+
* reserved. Escaping and code-fence growth (a value made of backticks can
|
|
141
|
+
* more than triple its code span) make this depend on rendered size, not raw
|
|
142
|
+
* field lengths, so both summarizeResolvedLaunch and the wire validator call
|
|
143
|
+
* this instead of trusting per-field caps.
|
|
144
|
+
*/
|
|
145
|
+
export function mandatoryConfigurationFits(configuration) {
|
|
146
|
+
const reserved = `${mandatoryComponents(configuration).join('; ')}${OPTIONAL_OMISSION_SUFFIX}`;
|
|
147
|
+
return codePoints(reserved) <= AGENT_LINE_MAX_CODE_POINTS && utf8(reserved) <= AGENT_LINE_MAX_BYTES;
|
|
148
|
+
}
|
|
149
|
+
/**
|
|
150
|
+
* Render one agent's configuration as a single escaped Markdown line segment.
|
|
151
|
+
* This is the only escaping boundary: callers pass raw values and must not
|
|
152
|
+
* escape the result again (it is safe as a markdownItems entry and inside
|
|
153
|
+
* owner-channel lifecycle messages). Every mandatory component always
|
|
154
|
+
* renders — mandatoryConfigurationFits guarantees the fit for every produced
|
|
155
|
+
* or wire-accepted configuration; only optional components may be dropped,
|
|
156
|
+
* whole (never splitting a Markdown span), with a visible `…`.
|
|
157
|
+
*/
|
|
158
|
+
export function renderAgentConfiguration(configuration, fallback) {
|
|
159
|
+
if (!configuration) {
|
|
160
|
+
const labels = [
|
|
161
|
+
fallback?.role ? `Role ${markdownProse(fallback.role)}` : undefined,
|
|
162
|
+
fallback?.brain ? `Brain ${markdownProse(fallback.brain)}` : undefined,
|
|
163
|
+
fallback?.permissions ? `permissions ${markdownProse(fallback.permissions)}` : undefined,
|
|
164
|
+
].filter(Boolean).join('; ');
|
|
165
|
+
return `legacy launch; resolved details unavailable${labels ? ` (${labels})` : ''}`;
|
|
166
|
+
}
|
|
167
|
+
let line = mandatoryComponents(configuration).join('; ');
|
|
168
|
+
let omitted = false;
|
|
169
|
+
for (const part of optionalComponents(configuration)) {
|
|
170
|
+
const next = `${line}; ${part}`;
|
|
171
|
+
if (codePoints(`${next}${OPTIONAL_OMISSION_SUFFIX}`) > AGENT_LINE_MAX_CODE_POINTS
|
|
172
|
+
|| utf8(`${next}${OPTIONAL_OMISSION_SUFFIX}`) > AGENT_LINE_MAX_BYTES) {
|
|
173
|
+
omitted = true;
|
|
174
|
+
continue;
|
|
175
|
+
}
|
|
176
|
+
line = next;
|
|
177
|
+
}
|
|
178
|
+
return omitted ? `${line}${OPTIONAL_OMISSION_SUFFIX}` : line;
|
|
179
|
+
}
|
package/dist/loops/config.d.ts
CHANGED
|
@@ -7,6 +7,9 @@ export interface LoopConfig {
|
|
|
7
7
|
initial_delay?: string;
|
|
8
8
|
jitter?: string;
|
|
9
9
|
}
|
|
10
|
+
/** Agent Template-local loops are implicitly scoped to the temporary agent. */
|
|
11
|
+
export type AgentLoopConfig = Omit<LoopConfig, 'roles'>;
|
|
12
|
+
export type AgentLoopsConfig = Record<string, AgentLoopConfig>;
|
|
10
13
|
export interface ResolvedLoop {
|
|
11
14
|
name: string;
|
|
12
15
|
selectors: string[];
|
|
@@ -24,7 +27,13 @@ export interface ResolvedRoleLoop extends Omit<ResolvedLoop, 'selectors' | 'role
|
|
|
24
27
|
role: string;
|
|
25
28
|
definitionHash: string;
|
|
26
29
|
}
|
|
27
|
-
export declare function resolveLoops(block: unknown, baseFile: string, roles: ResolvedRole[], vars: Record<string, string
|
|
30
|
+
export declare function resolveLoops(block: unknown, baseFile: string, roles: ResolvedRole[], vars: Record<string, string>, options?: {
|
|
31
|
+
assertTrustedSource?: boolean;
|
|
32
|
+
}): {
|
|
28
33
|
loops: ResolvedLoop[];
|
|
29
34
|
byRole: Map<string, ResolvedRoleLoop[]>;
|
|
30
35
|
};
|
|
36
|
+
/** Resolve the canonical Agent Template schema without inventing a second loop language. */
|
|
37
|
+
export declare function resolveAgentLoops(block: unknown, role: ResolvedRole, sourceFile?: string): ResolvedRoleLoop[];
|
|
38
|
+
/** Fully explicit private snapshot form; prompt text is retained for deterministic recovery. */
|
|
39
|
+
export declare function canonicalAgentLoops(loops: ResolvedRoleLoop[]): AgentLoopsConfig;
|
package/dist/loops/config.js
CHANGED
|
@@ -1,13 +1,15 @@
|
|
|
1
1
|
import { createHash } from 'node:crypto';
|
|
2
2
|
import { lstatSync } from 'node:fs';
|
|
3
3
|
import { ConfigError, ROLE_NAME_RE } from '../config.js';
|
|
4
|
-
import {
|
|
4
|
+
import { sessionBackendCapabilities } from '../session/types.js';
|
|
5
|
+
import { formatDuration, parseDuration } from '../duration.js';
|
|
5
6
|
const LOOP_KEYS = ['roles', 'interval', 'prompt', 'enabled', 'initial_delay', 'jitter'];
|
|
6
7
|
const MIN_INTERVAL_MS = 60_000;
|
|
7
8
|
const MAX_DURATION_MS = 30 * 24 * 60 * 60 * 1_000;
|
|
8
9
|
const MAX_JITTER_MS = 60 * 60 * 1_000;
|
|
9
10
|
const MAX_PROMPT_BYTES = 16 * 1024;
|
|
10
11
|
const MAX_PROMPT_SCALARS = 12_000;
|
|
12
|
+
const MAX_AGENT_LOOPS = 64;
|
|
11
13
|
function substitute(value, vars) {
|
|
12
14
|
if (typeof value === 'string')
|
|
13
15
|
return value.replace(/\$\{(\w+)\}/g, (match, key) => key in vars ? String(vars[key]) : match);
|
|
@@ -47,7 +49,7 @@ function normalizePrompt(raw, where) {
|
|
|
47
49
|
function digest(value) {
|
|
48
50
|
return createHash('sha256').update(JSON.stringify(value)).digest('hex');
|
|
49
51
|
}
|
|
50
|
-
export function resolveLoops(block, baseFile, roles, vars) {
|
|
52
|
+
export function resolveLoops(block, baseFile, roles, vars, options = {}) {
|
|
51
53
|
const byRole = new Map(roles.map(role => [role.name, []]));
|
|
52
54
|
if (block === undefined || block === null)
|
|
53
55
|
return { loops: [], byRole };
|
|
@@ -90,8 +92,8 @@ export function resolveLoops(block, baseFile, roles, vars) {
|
|
|
90
92
|
const prompt = normalizePrompt(value.prompt, `${where}: prompt`);
|
|
91
93
|
if (enabled)
|
|
92
94
|
for (const role of selected) {
|
|
93
|
-
if (role.session
|
|
94
|
-
throw new ConfigError(`${where} selects role '${role.name}' with session '${role.session}'; scheduled loops require
|
|
95
|
+
if (!sessionBackendCapabilities(role.session, role.harness).promptInput)
|
|
96
|
+
throw new ConfigError(`${where} selects role '${role.name}' with session '${role.session}'; scheduled loops require managed prompt input`);
|
|
95
97
|
}
|
|
96
98
|
const promptHash = digest(prompt);
|
|
97
99
|
const resolved = {
|
|
@@ -113,10 +115,41 @@ export function resolveLoops(block, baseFile, roles, vars) {
|
|
|
113
115
|
for (const values of byRole.values())
|
|
114
116
|
values.sort((a, b) => a.name.localeCompare(b.name));
|
|
115
117
|
out.sort((a, b) => a.name.localeCompare(b.name));
|
|
116
|
-
if (out.some(loop => loop.enabled))
|
|
118
|
+
if (out.some(loop => loop.enabled) && options.assertTrustedSource !== false)
|
|
117
119
|
assertSafeLoopConfig(baseFile);
|
|
118
120
|
return { loops: out, byRole };
|
|
119
121
|
}
|
|
122
|
+
/** Resolve the canonical Agent Template schema without inventing a second loop language. */
|
|
123
|
+
export function resolveAgentLoops(block, role, sourceFile = '(temporary Agent loop)') {
|
|
124
|
+
if (block === undefined)
|
|
125
|
+
return [];
|
|
126
|
+
if (!block || typeof block !== 'object' || Array.isArray(block))
|
|
127
|
+
throw new ConfigError(`${sourceFile}: Agent loops must be a non-empty map`);
|
|
128
|
+
if (!Object.keys(block).length)
|
|
129
|
+
throw new ConfigError(`${sourceFile}: Agent loops must be non-empty; use an explicit no-loops override to disable template loops`);
|
|
130
|
+
if (Object.keys(block).length > MAX_AGENT_LOOPS)
|
|
131
|
+
throw new ConfigError(`${sourceFile}: Agent loops may contain at most ${MAX_AGENT_LOOPS} entries`);
|
|
132
|
+
const scoped = Object.fromEntries(Object.entries(block).map(([name, raw]) => {
|
|
133
|
+
if (!raw || typeof raw !== 'object' || Array.isArray(raw))
|
|
134
|
+
return [name, raw];
|
|
135
|
+
const value = raw;
|
|
136
|
+
if (Object.hasOwn(value, 'roles'))
|
|
137
|
+
throw new ConfigError(`${sourceFile}: Agent loop '${name}' has unknown key roles; Agent loops are implicitly scoped`);
|
|
138
|
+
return [name, { ...value, roles: [role.name] }];
|
|
139
|
+
}));
|
|
140
|
+
return resolveLoops(scoped, sourceFile, [role], {}, { assertTrustedSource: false })
|
|
141
|
+
.byRole.get(role.name) ?? [];
|
|
142
|
+
}
|
|
143
|
+
/** Fully explicit private snapshot form; prompt text is retained for deterministic recovery. */
|
|
144
|
+
export function canonicalAgentLoops(loops) {
|
|
145
|
+
return Object.fromEntries(loops.map(loop => [loop.name, {
|
|
146
|
+
enabled: loop.enabled,
|
|
147
|
+
interval: formatDuration(loop.intervalMs),
|
|
148
|
+
initial_delay: formatDuration(loop.initialDelayMs),
|
|
149
|
+
jitter: formatDuration(loop.jitterMs),
|
|
150
|
+
prompt: loop.prompt,
|
|
151
|
+
}]));
|
|
152
|
+
}
|
|
120
153
|
function assertSafeLoopConfig(path) {
|
|
121
154
|
let stat;
|
|
122
155
|
try {
|
package/dist/model-recovery.d.ts
CHANGED
|
@@ -5,7 +5,7 @@ export interface FailureEvidence {
|
|
|
5
5
|
httpStatus?: number;
|
|
6
6
|
model?: string;
|
|
7
7
|
confidence: 'low' | 'medium' | 'high';
|
|
8
|
-
source: 'claude-pane' | 'acp' | 'auth-proxy';
|
|
8
|
+
source: 'claude-pane' | 'acp' | 'codex-app-server' | 'auth-proxy';
|
|
9
9
|
observedAt: string;
|
|
10
10
|
}
|
|
11
11
|
export interface ModelRecoveryLedger {
|
package/dist/ops.js
CHANGED
|
@@ -179,23 +179,8 @@ async function reconcileWatchdogScheduler(cfg, deps, configPath) {
|
|
|
179
179
|
}
|
|
180
180
|
}
|
|
181
181
|
export async function down(cfg, names, deps) {
|
|
182
|
-
const roles =
|
|
183
|
-
for (
|
|
184
|
-
const role = roles[index];
|
|
185
|
-
const requested = names[index];
|
|
186
|
-
if (!role && requested && /^[A-Za-z0-9_-]+$/.test(requested)
|
|
187
|
-
&& existsSync(agentDir(requested, true))) {
|
|
188
|
-
try {
|
|
189
|
-
const outcome = await stopTempSupervisor(requested, { exec: deps.exec ?? realExec });
|
|
190
|
-
deps.log(`■ ${outcome === 'stopped' ? 'stopping' : 'stopped'} temporary role ${requested}`);
|
|
191
|
-
}
|
|
192
|
-
catch (e) {
|
|
193
|
-
deps.log(` ! could not stop temporary role ${requested}: ${e instanceof Error ? e.message : String(e)}`);
|
|
194
|
-
}
|
|
195
|
-
continue;
|
|
196
|
-
}
|
|
197
|
-
if (!role)
|
|
198
|
-
throw new Error(`no such role '${requested}'`);
|
|
182
|
+
const roles = selectRoles(cfg, names);
|
|
183
|
+
for (const role of roles) {
|
|
199
184
|
// Never swallow the backend's reason. "maybe not running" hid real stop
|
|
200
185
|
// failures — a wedged unit, an unreachable user bus — behind a guess.
|
|
201
186
|
try {
|
|
@@ -46,6 +46,7 @@ export interface OwnerChannelHandle {
|
|
|
46
46
|
manage(request: OwnerChannelManagementRequest): Promise<OwnerChannelManagementResult>;
|
|
47
47
|
/** Fleet-owned deterministic lifecycle notice; absent on legacy test doubles. */
|
|
48
48
|
notifyFleetSpawn?(event: ManagedFleetSpawnResult): Promise<void>;
|
|
49
|
+
notifyFleetLifecycle?(presentations: FleetAuditPresentation[]): Promise<void>;
|
|
49
50
|
beginFleetCommandAudit?(requestId: string, argv: string[]): Promise<FleetAuditAttempt>;
|
|
50
51
|
finishFleetCommandAudit?(input: {
|
|
51
52
|
correlationId: string;
|
|
@@ -53,7 +54,7 @@ export interface OwnerChannelHandle {
|
|
|
53
54
|
exitCode?: number;
|
|
54
55
|
effect: 'not_started' | 'completed' | 'unknown';
|
|
55
56
|
resourceIds?: Record<string, string>;
|
|
56
|
-
|
|
57
|
+
presentations?: FleetAuditPresentation[];
|
|
57
58
|
}): Promise<FleetAuditAttempt>;
|
|
58
59
|
}
|
|
59
60
|
export declare const OWNER_RECOVERY_QUEUE_CAPACITY = 32;
|
|
@@ -175,6 +176,8 @@ export declare class OwnerChannel implements OwnerChannelHandle {
|
|
|
175
176
|
* (a crash must replay them) but must not be queued twice while live.
|
|
176
177
|
*/
|
|
177
178
|
private readonly inFlight;
|
|
179
|
+
/** SDK handlers entered during the current getMessages call. */
|
|
180
|
+
private readonly typedHandlersEntered;
|
|
178
181
|
/** Wires already NACKed to the managed agent, so a history replay stays quiet. */
|
|
179
182
|
private readonly relayNacks;
|
|
180
183
|
/**
|
|
@@ -209,6 +212,7 @@ export declare class OwnerChannel implements OwnerChannelHandle {
|
|
|
209
212
|
private readonly fleetOps;
|
|
210
213
|
private readonly prepareRestart;
|
|
211
214
|
private readonly commandAudits;
|
|
215
|
+
private readonly lifecycleOutbox;
|
|
212
216
|
constructor(options: OwnerChannelOptions);
|
|
213
217
|
start(): Promise<void>;
|
|
214
218
|
drain(): Promise<void>;
|
|
@@ -216,6 +220,8 @@ export declare class OwnerChannel implements OwnerChannelHandle {
|
|
|
216
220
|
binderReleaseSafe(): boolean;
|
|
217
221
|
manage(request: OwnerChannelManagementRequest): Promise<OwnerChannelManagementResult>;
|
|
218
222
|
notifyFleetSpawn(event: ManagedFleetSpawnResult): Promise<void>;
|
|
223
|
+
notifyFleetLifecycle(presentations: FleetAuditPresentation[]): Promise<void>;
|
|
224
|
+
private flushPendingFleetLifecycle;
|
|
219
225
|
beginFleetCommandAudit(requestId: string, argv: string[]): Promise<FleetAuditAttempt>;
|
|
220
226
|
finishFleetCommandAudit(input: {
|
|
221
227
|
correlationId: string;
|
|
@@ -223,8 +229,10 @@ export declare class OwnerChannel implements OwnerChannelHandle {
|
|
|
223
229
|
exitCode?: number;
|
|
224
230
|
effect: 'not_started' | 'completed' | 'unknown';
|
|
225
231
|
resourceIds?: Record<string, string>;
|
|
226
|
-
|
|
232
|
+
presentations?: FleetAuditPresentation[];
|
|
227
233
|
}): Promise<FleetAuditAttempt>;
|
|
234
|
+
private flushPendingFleetCommandAudits;
|
|
235
|
+
private deliverFleetCommandOutcome;
|
|
228
236
|
recover(epoch: string): Promise<void>;
|
|
229
237
|
private recoveryStage;
|
|
230
238
|
private writeShutdownState;
|
|
@@ -269,6 +277,15 @@ export declare class OwnerChannel implements OwnerChannelHandle {
|
|
|
269
277
|
* agent itself can execute /force-restart, /model, or any other command.
|
|
270
278
|
*/
|
|
271
279
|
private handleCommand;
|
|
280
|
+
/**
|
|
281
|
+
* Register one typed adapter per primary slash command. The adapter performs
|
|
282
|
+
* the live CID check before constructing the same slash text and entering the
|
|
283
|
+
* existing dispatcher; its null SDK result avoids duplicating the ordinary
|
|
284
|
+
* owner-channel replies that remain the command's result contract.
|
|
285
|
+
*/
|
|
286
|
+
private registerTypedCommands;
|
|
287
|
+
private handleRecoveredTypedCommand;
|
|
288
|
+
private handleTypedCommand;
|
|
272
289
|
/** Queue raw slash text to the harness and report the turn's outcome. */
|
|
273
290
|
private runHarnessCommand;
|
|
274
291
|
/**
|
|
@@ -281,9 +298,8 @@ export declare class OwnerChannel implements OwnerChannelHandle {
|
|
|
281
298
|
* before an external worker starts a saga that can retire this process.
|
|
282
299
|
*/
|
|
283
300
|
private closeRoomFromOwner;
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
private recoverTaskFromOwner;
|
|
301
|
+
/** Accept a permanent any-state deletion, acknowledge it, then hand cleanup to a durable worker. */
|
|
302
|
+
private deleteTaskFromOwner;
|
|
287
303
|
private terminalTaskFromOwner;
|
|
288
304
|
/** Code-point-safe tail of the worklog, or undefined when there is none. */
|
|
289
305
|
private readWorklogTail;
|