praxis-agent 0.35.0 → 0.37.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 +20 -2
- package/dist/application/background-agent-manager.d.ts +16 -6
- package/dist/application/background-agent-manager.js +139 -97
- package/dist/application/context-engine.d.ts +56 -0
- package/dist/application/context-engine.js +129 -0
- package/dist/application/durable-follow-up.d.ts +14 -0
- package/dist/application/durable-follow-up.js +52 -0
- package/dist/application/native-session-transcript.d.ts +72 -0
- package/dist/application/native-session-transcript.js +351 -0
- package/dist/application/native-sidechain-transcript.d.ts +34 -0
- package/dist/application/native-sidechain-transcript.js +156 -0
- package/dist/application/session-service.d.ts +23 -4
- package/dist/application/session-service.js +1130 -494
- package/dist/application/subagent-service.d.ts +5 -1
- package/dist/application/subagent-service.js +749 -320
- package/dist/application/team-agent-runtime.d.ts +29 -0
- package/dist/application/team-agent-runtime.js +169 -0
- package/dist/application/team-capability.d.ts +27 -0
- package/dist/application/team-capability.js +41 -0
- package/dist/application/team-lead-operations.d.ts +38 -0
- package/dist/application/team-lead-operations.js +155 -0
- package/dist/application/team-mailbox.d.ts +54 -0
- package/dist/application/team-mailbox.js +196 -0
- package/dist/application/team-manager.d.ts +113 -0
- package/dist/application/team-manager.js +681 -0
- package/dist/application/team-workspace.d.ts +29 -0
- package/dist/application/team-workspace.js +197 -0
- package/dist/application/top-level-agent-manager.d.ts +1 -0
- package/dist/application/top-level-agent-manager.js +1025 -403
- package/dist/application/transcript-projection.d.ts +35 -0
- package/dist/application/transcript-projection.js +139 -0
- package/dist/application/turn-lifecycle.d.ts +2 -0
- package/dist/application/turn-memory-coordinator.d.ts +43 -0
- package/dist/application/turn-memory-coordinator.js +98 -0
- package/dist/cli/agents-dashboard.js +10 -5
- package/dist/cli/interactive.d.ts +7 -0
- package/dist/cli/interactive.js +645 -334
- package/dist/cli/tui/claude-style.d.ts +8 -25
- package/dist/cli/tui/claude-style.js +299 -277
- package/dist/cli/tui/decision-surface-model.d.ts +71 -0
- package/dist/cli/tui/decision-surface-model.js +131 -0
- package/dist/cli/tui/decision-surface.d.ts +7 -0
- package/dist/cli/tui/decision-surface.js +41 -0
- package/dist/cli/tui/help-surface-model.d.ts +68 -0
- package/dist/cli/tui/help-surface-model.js +131 -0
- package/dist/cli/tui/mcp-panel.js +1 -2
- package/dist/cli/tui/permission-surface-model.d.ts +195 -0
- package/dist/cli/tui/permission-surface-model.js +360 -0
- package/dist/cli/tui/permission-surface.d.ts +7 -0
- package/dist/cli/tui/permission-surface.js +69 -0
- package/dist/cli/tui/presentation-environment.d.ts +32 -0
- package/dist/cli/tui/presentation-environment.js +149 -0
- package/dist/cli/tui/task-panel.js +10 -1
- package/dist/cli/tui/theme.d.ts +46 -3
- package/dist/cli/tui/theme.js +414 -56
- package/dist/cli/tui/tool-permission.js +16 -8
- package/dist/cli/tui/transcript-presentation.d.ts +19 -1
- package/dist/cli/tui/transcript-presentation.js +26 -6
- package/dist/cli/tui/transcript-viewport.d.ts +18 -0
- package/dist/cli/tui/transcript-viewport.js +517 -111
- package/dist/cli/tui/transcript-window-model.d.ts +108 -0
- package/dist/cli/tui/transcript-window-model.js +772 -0
- package/dist/cli/tui/tui-interaction-router.d.ts +78 -0
- package/dist/cli/tui/tui-interaction-router.js +127 -0
- package/dist/cli/tui/tui-screen-model.d.ts +114 -0
- package/dist/cli/tui/tui-screen-model.js +210 -0
- package/dist/cli/tui/tui-view-model.d.ts +2 -49
- package/dist/cli/tui/tui-view-model.js +1 -68
- package/dist/cli-runtime.d.ts +4 -2
- package/dist/cli-runtime.js +397 -32
- package/dist/compatibility/claude/transcript-codec.js +6 -0
- package/dist/core/agent-orchestration.d.ts +31 -0
- package/dist/core/agent-orchestration.js +235 -0
- package/dist/core/permission-policy.d.ts +4 -0
- package/dist/core/permission-policy.js +21 -0
- package/dist/core/runtime.d.ts +6 -0
- package/dist/core/runtime.js +20 -2
- package/dist/core/team-mailbox.d.ts +54 -0
- package/dist/core/team-mailbox.js +212 -0
- package/dist/core/team-ownership.d.ts +84 -0
- package/dist/core/team-ownership.js +505 -0
- package/dist/core/tool-execution-scheduler.js +6 -1
- package/dist/core/transcript-event.d.ts +5 -1
- package/dist/core/transcript-event.js +12 -0
- package/dist/persistence/claude-job-store.d.ts +58 -0
- package/dist/persistence/claude-job-store.js +483 -1
- package/dist/persistence/claude-transcript-store.d.ts +2 -1
- package/dist/persistence/claude-transcript-store.js +2 -10
- package/dist/persistence/native-team-mailbox.d.ts +68 -0
- package/dist/persistence/native-team-mailbox.js +542 -0
- package/dist/persistence/native-team-store.d.ts +34 -0
- package/dist/persistence/native-team-store.js +257 -0
- package/dist/persistence/native-transcript-reader.d.ts +53 -0
- package/dist/persistence/native-transcript-reader.js +283 -0
- package/dist/persistence/native-transcript-store.d.ts +69 -0
- package/dist/persistence/native-transcript-store.js +321 -0
- package/dist/persistence/subagent-lifecycle-store.d.ts +41 -8
- package/dist/persistence/subagent-lifecycle-store.js +373 -146
- package/dist/persistence/transcript-file-append.d.ts +2 -0
- package/dist/persistence/transcript-file-append.js +10 -0
- package/dist/platform/exclusive-file-lease.d.ts +3 -0
- package/dist/platform/exclusive-file-lease.js +3 -0
- package/dist/tools/claude-capabilities.d.ts +4 -0
- package/dist/tools/claude-capabilities.js +18 -2
- package/dist/tools/team-lead-tools.d.ts +19 -0
- package/dist/tools/team-lead-tools.js +479 -0
- package/dist/tools/team-member-tools.d.ts +21 -0
- package/dist/tools/team-member-tools.js +259 -0
- package/package.json +1 -1
- package/dist/cli/tui/fullscreen-renderer.d.ts +0 -14
- package/dist/cli/tui/fullscreen-renderer.js +0 -13
|
@@ -0,0 +1,321 @@
|
|
|
1
|
+
import { createHash } from 'node:crypto';
|
|
2
|
+
import { mkdir, open, readFile } from 'node:fs/promises';
|
|
3
|
+
import { dirname } from 'node:path';
|
|
4
|
+
import { ExclusiveFileLease } from '../platform/exclusive-file-lease.js';
|
|
5
|
+
import { createNativeTranscriptCodec } from './native-transcript-codec.js';
|
|
6
|
+
import { classifyTranscriptAppend } from './transcript-file-append.js';
|
|
7
|
+
const hashLine = (line) => createHash('sha256').update(line).digest('hex');
|
|
8
|
+
const emptyTail = () => ({
|
|
9
|
+
byteLength: 0,
|
|
10
|
+
lastLineHash: null,
|
|
11
|
+
lastEventId: null,
|
|
12
|
+
newlineTerminated: true,
|
|
13
|
+
});
|
|
14
|
+
function splitLines(source) {
|
|
15
|
+
const end = source.at(-1) === 0x0a ? source.length - 1 : source.length;
|
|
16
|
+
if (!end)
|
|
17
|
+
return [];
|
|
18
|
+
const result = [];
|
|
19
|
+
let start = 0;
|
|
20
|
+
for (let i = 0; i < end; i++) {
|
|
21
|
+
if (source[i] === 0x0a) {
|
|
22
|
+
result.push(source.subarray(start, i));
|
|
23
|
+
start = i + 1;
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
result.push(source.subarray(start, end));
|
|
27
|
+
return result;
|
|
28
|
+
}
|
|
29
|
+
function tailFrom(source, records) {
|
|
30
|
+
const lines = splitLines(source);
|
|
31
|
+
const line = lines.at(-1);
|
|
32
|
+
return {
|
|
33
|
+
byteLength: source.length,
|
|
34
|
+
lastLineHash: line ? hashLine(line) : null,
|
|
35
|
+
lastEventId: records.at(-1)?.event.id ?? null,
|
|
36
|
+
newlineTerminated: source.length === 0 || source.at(-1) === 0x0a,
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
function equalTail(a, b) {
|
|
40
|
+
return (a.byteLength === b.byteLength &&
|
|
41
|
+
a.lastLineHash === b.lastLineHash &&
|
|
42
|
+
a.lastEventId === b.lastEventId &&
|
|
43
|
+
a.newlineTerminated === b.newlineTerminated);
|
|
44
|
+
}
|
|
45
|
+
function logicalTail(tail) {
|
|
46
|
+
return tail.branchParentId === undefined
|
|
47
|
+
? tail.lastEventId
|
|
48
|
+
: (tail.branchParentId ?? null);
|
|
49
|
+
}
|
|
50
|
+
function effectiveParentId(event) {
|
|
51
|
+
return event.kind === 'context-boundary'
|
|
52
|
+
? event.logicalParentId
|
|
53
|
+
: event.parentId;
|
|
54
|
+
}
|
|
55
|
+
function validateHistory(events) {
|
|
56
|
+
const ids = new Set();
|
|
57
|
+
const sessions = new Set();
|
|
58
|
+
const calls = new Set();
|
|
59
|
+
const children = new Map();
|
|
60
|
+
for (const [index, event] of events.entries()) {
|
|
61
|
+
if (ids.has(event.id))
|
|
62
|
+
throw new Error('Invalid native transcript invariant: event IDs must be unique');
|
|
63
|
+
if (sessions.size && !sessions.has(event.sessionId))
|
|
64
|
+
throw new Error('Invalid native transcript invariant: sessionId must match history');
|
|
65
|
+
if (event.kind === 'context-boundary') {
|
|
66
|
+
if (event.parentId !== null || !ids.has(event.logicalParentId))
|
|
67
|
+
throw new Error('Invalid native transcript invariant: context boundary logicalParentId must reference history');
|
|
68
|
+
}
|
|
69
|
+
else if (event.parentId === null) {
|
|
70
|
+
if (index !== 0)
|
|
71
|
+
throw new Error('Invalid native transcript invariant: only the first logical root may have a null parentId');
|
|
72
|
+
}
|
|
73
|
+
else if (!ids.has(event.parentId)) {
|
|
74
|
+
throw new Error('Invalid native transcript invariant: event parentId must reference an earlier event');
|
|
75
|
+
}
|
|
76
|
+
const parentId = effectiveParentId(event);
|
|
77
|
+
if (parentId !== null) {
|
|
78
|
+
const siblings = children.get(parentId) ?? [];
|
|
79
|
+
siblings.push(event);
|
|
80
|
+
children.set(parentId, siblings);
|
|
81
|
+
}
|
|
82
|
+
ids.add(event.id);
|
|
83
|
+
sessions.add(event.sessionId);
|
|
84
|
+
if (event.kind !== 'messages')
|
|
85
|
+
continue;
|
|
86
|
+
for (const message of event.messages) {
|
|
87
|
+
if (message.role !== 'assistant')
|
|
88
|
+
continue;
|
|
89
|
+
for (const call of message.toolCalls ?? []) {
|
|
90
|
+
if (calls.has(call.id))
|
|
91
|
+
throw new Error('Invalid native transcript invariant: assistant tool-call IDs must be unique');
|
|
92
|
+
calls.add(call.id);
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
const root = events[0];
|
|
97
|
+
if (!root)
|
|
98
|
+
return;
|
|
99
|
+
const activeCalls = new Set();
|
|
100
|
+
const activeResults = new Set();
|
|
101
|
+
const stack = [{ event: root, leaving: false }];
|
|
102
|
+
while (stack.length > 0) {
|
|
103
|
+
const frame = stack.pop();
|
|
104
|
+
if (!frame)
|
|
105
|
+
break;
|
|
106
|
+
if (frame.leaving) {
|
|
107
|
+
for (const id of frame.addedCalls)
|
|
108
|
+
activeCalls.delete(id);
|
|
109
|
+
for (const id of frame.addedResults)
|
|
110
|
+
activeResults.delete(id);
|
|
111
|
+
continue;
|
|
112
|
+
}
|
|
113
|
+
const addedCalls = [];
|
|
114
|
+
const addedResults = [];
|
|
115
|
+
if (frame.event.kind === 'messages') {
|
|
116
|
+
for (const message of frame.event.messages) {
|
|
117
|
+
if (message.role === 'assistant') {
|
|
118
|
+
for (const call of message.toolCalls ?? []) {
|
|
119
|
+
activeCalls.add(call.id);
|
|
120
|
+
addedCalls.push(call.id);
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
else if (message.role === 'tool') {
|
|
124
|
+
if (!activeCalls.has(message.toolCallId))
|
|
125
|
+
throw new Error('Invalid native transcript invariant: tool result references unknown tool call on active ancestry');
|
|
126
|
+
if (activeResults.has(message.toolCallId))
|
|
127
|
+
throw new Error('Invalid native transcript invariant: tool call has multiple results on active ancestry');
|
|
128
|
+
activeResults.add(message.toolCallId);
|
|
129
|
+
addedResults.push(message.toolCallId);
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
stack.push({
|
|
134
|
+
event: frame.event,
|
|
135
|
+
leaving: true,
|
|
136
|
+
addedCalls,
|
|
137
|
+
addedResults,
|
|
138
|
+
});
|
|
139
|
+
const descendants = children.get(frame.event.id) ?? [];
|
|
140
|
+
for (let index = descendants.length - 1; index >= 0; index -= 1) {
|
|
141
|
+
const descendant = descendants[index];
|
|
142
|
+
if (descendant)
|
|
143
|
+
stack.push({ event: descendant, leaving: false });
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
export class NativeTranscriptStore {
|
|
148
|
+
options;
|
|
149
|
+
lease;
|
|
150
|
+
constructor(options) {
|
|
151
|
+
this.options = options;
|
|
152
|
+
this.lease = new ExclusiveFileLease(options.lockFile);
|
|
153
|
+
}
|
|
154
|
+
async source() {
|
|
155
|
+
try {
|
|
156
|
+
return await readFile(this.options.transcriptFile);
|
|
157
|
+
}
|
|
158
|
+
catch (e) {
|
|
159
|
+
if (e.code === 'ENOENT')
|
|
160
|
+
return Buffer.alloc(0);
|
|
161
|
+
throw e;
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
decode(source, recover) {
|
|
165
|
+
if (!source.length)
|
|
166
|
+
return { records: [], tail: emptyTail(), issue: null };
|
|
167
|
+
const decoded = createNativeTranscriptCodec().decodeDocument(source);
|
|
168
|
+
if (decoded.issue && !recover)
|
|
169
|
+
throw new Error(`Invalid native transcript: ${decoded.issue.message}`);
|
|
170
|
+
if (!recover)
|
|
171
|
+
validateHistory(decoded.records.map((record) => record.event));
|
|
172
|
+
return {
|
|
173
|
+
records: decoded.records,
|
|
174
|
+
tail: tailFrom(source, decoded.records),
|
|
175
|
+
issue: decoded.issue,
|
|
176
|
+
};
|
|
177
|
+
}
|
|
178
|
+
async load() {
|
|
179
|
+
const { records, tail } = this.decode(await this.source(), false);
|
|
180
|
+
return { records, tail };
|
|
181
|
+
}
|
|
182
|
+
async loadReadOnly() {
|
|
183
|
+
return this.decode(await this.source(), true);
|
|
184
|
+
}
|
|
185
|
+
async exportReadOnly() {
|
|
186
|
+
return this.source();
|
|
187
|
+
}
|
|
188
|
+
prepare(history, events, expected) {
|
|
189
|
+
if (!events.length)
|
|
190
|
+
throw new Error('Cannot append an empty native transcript batch');
|
|
191
|
+
const all = history.map((r) => r.event);
|
|
192
|
+
const historicalIds = new Set(all.map((event) => event.id));
|
|
193
|
+
if (expected.branchParentId !== undefined &&
|
|
194
|
+
expected.branchParentId !== null &&
|
|
195
|
+
!historicalIds.has(expected.branchParentId))
|
|
196
|
+
throw new Error('Invalid native transcript invariant: branchParentId must reference an earlier event');
|
|
197
|
+
validateHistory([...history.map((record) => record.event), ...events]);
|
|
198
|
+
const ids = new Set();
|
|
199
|
+
const sessions = new Set();
|
|
200
|
+
for (const e of all) {
|
|
201
|
+
if (ids.has(e.id))
|
|
202
|
+
throw new Error('Invalid native transcript invariant: event IDs must be unique');
|
|
203
|
+
if (sessions.size && !sessions.has(e.sessionId))
|
|
204
|
+
throw new Error('Invalid native transcript invariant: sessionId must match history');
|
|
205
|
+
ids.add(e.id);
|
|
206
|
+
sessions.add(e.sessionId);
|
|
207
|
+
}
|
|
208
|
+
let parent = logicalTail(expected);
|
|
209
|
+
const lines = [];
|
|
210
|
+
for (const event of events) {
|
|
211
|
+
const codec = createNativeTranscriptCodec();
|
|
212
|
+
const encoded = codec.encodeLine(event);
|
|
213
|
+
if (!encoded.ok)
|
|
214
|
+
throw new Error(`Invalid native transcript event: ${encoded.issue.message}`);
|
|
215
|
+
if (ids.has(event.id))
|
|
216
|
+
throw new Error('Invalid native transcript invariant: event IDs must be unique');
|
|
217
|
+
if (sessions.size && !sessions.has(event.sessionId))
|
|
218
|
+
throw new Error('Invalid native transcript invariant: sessionId must match history');
|
|
219
|
+
sessions.add(event.sessionId);
|
|
220
|
+
if (event.kind === 'context-boundary') {
|
|
221
|
+
if (event.parentId !== null || !ids.has(event.logicalParentId))
|
|
222
|
+
throw new Error('Invalid native transcript invariant: context boundary logicalParentId must reference history');
|
|
223
|
+
parent = event.id;
|
|
224
|
+
}
|
|
225
|
+
else if (event.parentId !== parent)
|
|
226
|
+
throw new Error('Invalid native transcript invariant: event parentId does not match logical tail');
|
|
227
|
+
lines.push(Buffer.from(`${encoded.line}\n`));
|
|
228
|
+
ids.add(event.id);
|
|
229
|
+
parent = event.id;
|
|
230
|
+
}
|
|
231
|
+
return Buffer.concat(lines);
|
|
232
|
+
}
|
|
233
|
+
async create(events) {
|
|
234
|
+
const bytes = this.prepare([], events, emptyTail());
|
|
235
|
+
await mkdir(dirname(this.options.transcriptFile), { recursive: true });
|
|
236
|
+
let handle;
|
|
237
|
+
try {
|
|
238
|
+
handle = await open(this.options.transcriptFile, 'wx', 0o600);
|
|
239
|
+
}
|
|
240
|
+
catch (e) {
|
|
241
|
+
if (e.code === 'EEXIST')
|
|
242
|
+
return { status: 'conflict', reason: 'already-exists' };
|
|
243
|
+
throw e;
|
|
244
|
+
}
|
|
245
|
+
try {
|
|
246
|
+
await handle.writeFile(bytes);
|
|
247
|
+
await handle.sync();
|
|
248
|
+
}
|
|
249
|
+
finally {
|
|
250
|
+
await handle.close();
|
|
251
|
+
}
|
|
252
|
+
return { status: 'created', tail: (await this.load()).tail };
|
|
253
|
+
}
|
|
254
|
+
async reserveUnderLease() {
|
|
255
|
+
await mkdir(dirname(this.options.transcriptFile), { recursive: true });
|
|
256
|
+
let handle;
|
|
257
|
+
try {
|
|
258
|
+
handle = await open(this.options.transcriptFile, 'wx', 0o600);
|
|
259
|
+
}
|
|
260
|
+
catch (e) {
|
|
261
|
+
if (e.code === 'EEXIST')
|
|
262
|
+
return { status: 'conflict', reason: 'already-exists' };
|
|
263
|
+
throw e;
|
|
264
|
+
}
|
|
265
|
+
try {
|
|
266
|
+
await handle.sync();
|
|
267
|
+
}
|
|
268
|
+
finally {
|
|
269
|
+
await handle.close();
|
|
270
|
+
}
|
|
271
|
+
return { status: 'reserved' };
|
|
272
|
+
}
|
|
273
|
+
async withLease(operation) {
|
|
274
|
+
const lock = await this.lease.tryAcquire();
|
|
275
|
+
if (!lock)
|
|
276
|
+
return { status: 'conflict', reason: 'locked' };
|
|
277
|
+
try {
|
|
278
|
+
const value = await operation({
|
|
279
|
+
reserve: () => this.reserveUnderLease(),
|
|
280
|
+
load: () => this.load(),
|
|
281
|
+
append: (tail, event) => this.appendUnderLease(tail, [event]),
|
|
282
|
+
appendMany: (tail, events) => this.appendUnderLease(tail, events),
|
|
283
|
+
});
|
|
284
|
+
return { status: 'completed', value };
|
|
285
|
+
}
|
|
286
|
+
finally {
|
|
287
|
+
await lock.release();
|
|
288
|
+
}
|
|
289
|
+
}
|
|
290
|
+
async appendUnderLease(expected, events) {
|
|
291
|
+
const current = await this.load();
|
|
292
|
+
if (!equalTail(current.tail, expected))
|
|
293
|
+
return { status: 'conflict', reason: 'tail-changed' };
|
|
294
|
+
if (!current.tail.newlineTerminated)
|
|
295
|
+
throw new Error('Invalid native transcript: file is not newline-terminated');
|
|
296
|
+
const bytes = this.prepare(current.records, events, expected);
|
|
297
|
+
await mkdir(dirname(this.options.transcriptFile), { recursive: true });
|
|
298
|
+
const handle = await open(this.options.transcriptFile, 'a');
|
|
299
|
+
try {
|
|
300
|
+
const stat = await handle.stat();
|
|
301
|
+
if (stat.size !== expected.byteLength)
|
|
302
|
+
return { status: 'conflict', reason: 'tail-changed' };
|
|
303
|
+
await handle.writeFile(bytes);
|
|
304
|
+
await handle.sync();
|
|
305
|
+
}
|
|
306
|
+
finally {
|
|
307
|
+
await handle.close();
|
|
308
|
+
}
|
|
309
|
+
const written = await readFile(this.options.transcriptFile);
|
|
310
|
+
if (classifyTranscriptAppend(written, expected.byteLength, bytes) ===
|
|
311
|
+
'interleaved-write')
|
|
312
|
+
return { status: 'conflict', reason: 'interleaved-write' };
|
|
313
|
+
const tail = (await this.load()).tail;
|
|
314
|
+
return { status: 'appended', tail };
|
|
315
|
+
}
|
|
316
|
+
async append(expectedTail, event) {
|
|
317
|
+
const result = await this.withLease((lease) => lease.append(expectedTail, event));
|
|
318
|
+
return result.status === 'completed' ? result.value : result;
|
|
319
|
+
}
|
|
320
|
+
}
|
|
321
|
+
//# sourceMappingURL=native-transcript-store.js.map
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { type AgentLifecycleSnapshot, type LifecycleState } from '../core/agent-orchestration.js';
|
|
2
|
+
import { type ExclusiveFileLeaseHandle } from '../platform/exclusive-file-lease.js';
|
|
1
3
|
export type PersistedSubagentStatus = 'running' | 'completed' | 'failed' | 'killed';
|
|
2
4
|
export interface PersistedSubagentRunResult {
|
|
3
5
|
text: string;
|
|
@@ -32,35 +34,66 @@ export interface PersistedSubagentNotification {
|
|
|
32
34
|
delivered: boolean;
|
|
33
35
|
};
|
|
34
36
|
}
|
|
37
|
+
/** `status` is a read-only compatibility projection and is never persisted. */
|
|
35
38
|
export interface PersistedSubagentLifecycle {
|
|
36
|
-
version:
|
|
39
|
+
version: 2;
|
|
37
40
|
sessionId: string;
|
|
38
41
|
agentId: string;
|
|
39
|
-
|
|
42
|
+
lifecycle: AgentLifecycleSnapshot;
|
|
40
43
|
updatedAt: string;
|
|
41
44
|
transcriptBytes?: number;
|
|
42
45
|
detail?: string;
|
|
43
46
|
result?: PersistedSubagentRunResult;
|
|
44
47
|
notifications?: PersistedSubagentNotification[];
|
|
48
|
+
readonly status?: PersistedSubagentStatus;
|
|
49
|
+
}
|
|
50
|
+
type StoredLifecycle = Omit<PersistedSubagentLifecycle, 'status'>;
|
|
51
|
+
export declare class SubagentExecution {
|
|
52
|
+
private readonly store;
|
|
53
|
+
private readonly lease;
|
|
54
|
+
readonly token: string;
|
|
55
|
+
readonly generation: number;
|
|
56
|
+
private current;
|
|
57
|
+
private released;
|
|
58
|
+
constructor(store: SubagentLifecycleStore, lease: ExclusiveFileLeaseHandle, token: string, generation: number, current: AgentLifecycleSnapshot);
|
|
59
|
+
get snapshot(): AgentLifecycleSnapshot;
|
|
60
|
+
transition(state: LifecycleState): Promise<AgentLifecycleSnapshot>;
|
|
61
|
+
running(): Promise<AgentLifecycleSnapshot>;
|
|
62
|
+
beginCancellation(): Promise<AgentLifecycleSnapshot>;
|
|
63
|
+
finish(state: 'completed' | 'failed' | 'cancelled', result?: PersistedSubagentRunResult, detail?: string, notification?: Omit<PersistedSubagentNotification, 'result' | 'consumed'>): Promise<AgentLifecycleSnapshot>;
|
|
64
|
+
release(): Promise<void>;
|
|
65
|
+
private ensureActive;
|
|
45
66
|
}
|
|
46
|
-
/** Praxis-private state for a retained Claude-compatible sidechain. */
|
|
47
67
|
export declare class SubagentLifecycleStore {
|
|
48
68
|
private readonly sessionId;
|
|
49
69
|
private readonly agentId;
|
|
50
70
|
private readonly transcriptPath?;
|
|
51
71
|
private readonly path;
|
|
72
|
+
private readonly ownerLock;
|
|
73
|
+
private readonly mutationLock;
|
|
52
74
|
private mutation;
|
|
53
75
|
constructor(praxisRoot: string, sessionId: string, agentId: string, transcriptPath?: string | undefined);
|
|
54
76
|
read(): Promise<PersistedSubagentLifecycle | null>;
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
77
|
+
acquire(mode?: 'start' | 'continue' | 'recover'): Promise<SubagentExecution>;
|
|
78
|
+
start(): Promise<SubagentExecution>;
|
|
79
|
+
continue(): Promise<SubagentExecution>;
|
|
80
|
+
recover(): Promise<SubagentExecution>;
|
|
81
|
+
reconcileOwnerLoss(): Promise<{
|
|
82
|
+
owned: boolean;
|
|
83
|
+
snapshot: AgentLifecycleSnapshot | null;
|
|
84
|
+
}>;
|
|
59
85
|
acknowledgeNotification(id: string): Promise<void>;
|
|
60
86
|
prepareNotificationDetached(id: string, model: string): Promise<void>;
|
|
61
87
|
confirmNotificationDetached(id: string): Promise<void>;
|
|
62
88
|
matchesTranscript(record: PersistedSubagentLifecycle): Promise<boolean>;
|
|
63
|
-
private
|
|
89
|
+
private baseRecord;
|
|
90
|
+
withLifecycle(current: StoredLifecycle, lifecycle: AgentLifecycleSnapshot, extra?: Partial<Pick<StoredLifecycle, 'detail' | 'result' | 'notifications'>>): StoredLifecycle;
|
|
91
|
+
mutateOwned(lease: ExclusiveFileLeaseHandle, generation: number, operation: (current: StoredLifecycle) => StoredLifecycle, refreshTranscript?: boolean): Promise<AgentLifecycleSnapshot>;
|
|
64
92
|
private mutate;
|
|
93
|
+
private acquireMutationLock;
|
|
94
|
+
private readStored;
|
|
95
|
+
private normalizeLegacy;
|
|
96
|
+
private writeStored;
|
|
65
97
|
}
|
|
98
|
+
export {};
|
|
66
99
|
//# sourceMappingURL=subagent-lifecycle-store.d.ts.map
|