praxis-agent 0.32.0 → 0.34.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/dist/application/background-agent-manager.d.ts +48 -3
- package/dist/application/background-agent-manager.js +249 -73
- package/dist/application/background-task-runtime.d.ts +20 -1
- package/dist/application/background-task-runtime.js +45 -6
- package/dist/application/managed-worktree.d.ts +8 -0
- package/dist/application/managed-worktree.js +54 -2
- package/dist/application/session-service.d.ts +38 -0
- package/dist/application/session-service.js +590 -70
- package/dist/application/subagent-service.d.ts +34 -7
- package/dist/application/subagent-service.js +694 -135
- package/dist/cli/interactive.d.ts +1 -0
- package/dist/cli/interactive.js +26 -1
- package/dist/cli/tui/task-panel.d.ts +1 -1
- package/dist/cli/tui/task-panel.js +2 -1
- package/dist/cli-runtime.d.ts +1 -0
- package/dist/cli-runtime.js +111 -31
- package/dist/compatibility/claude/history.d.ts +8 -0
- package/dist/compatibility/claude/history.js +54 -0
- package/dist/compatibility/claude/interruption.d.ts +16 -0
- package/dist/compatibility/claude/interruption.js +147 -0
- package/dist/compatibility/claude/projection.d.ts +4 -0
- package/dist/compatibility/claude/projection.js +82 -0
- package/dist/compatibility/claude/schema.js +22 -0
- package/dist/compatibility/claude/session-metadata.d.ts +44 -0
- package/dist/compatibility/claude/session-metadata.js +180 -0
- package/dist/compatibility/claude/sidechain.d.ts +5 -0
- package/dist/compatibility/claude/sidechain.js +13 -4
- package/dist/persistence/claude-session-index.d.ts +39 -0
- package/dist/persistence/claude-session-index.js +175 -0
- package/dist/persistence/claude-sidechain-store.js +19 -3
- package/dist/persistence/claude-transcript-store.d.ts +6 -2
- package/dist/persistence/claude-transcript-store.js +78 -3
- package/dist/persistence/in-memory-transcript-store.js +1 -0
- package/dist/persistence/subagent-lifecycle-store.d.ts +66 -0
- package/dist/persistence/subagent-lifecycle-store.js +299 -0
- package/package.json +2 -1
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { execFile } from 'node:child_process';
|
|
2
|
-
import { lstat, mkdir } from 'node:fs/promises';
|
|
3
|
-
import { join, resolve } from 'node:path';
|
|
2
|
+
import { lstat, mkdir, realpath } from 'node:fs/promises';
|
|
3
|
+
import { isAbsolute, join, resolve } from 'node:path';
|
|
4
4
|
import { promisify } from 'node:util';
|
|
5
5
|
const execFileAsync = promisify(execFile);
|
|
6
6
|
async function git(cwd, args) {
|
|
@@ -124,4 +124,56 @@ export async function createManagedWorktree(options) {
|
|
|
124
124
|
},
|
|
125
125
|
};
|
|
126
126
|
}
|
|
127
|
+
/** Reattaches only to a real, registered Git worktree. Persisted metadata is
|
|
128
|
+
* untrusted input, so an arbitrary directory can never become an execution
|
|
129
|
+
* cwd merely because it exists. Restored worktrees are retained for audit. */
|
|
130
|
+
export async function restoreManagedWorktree(options) {
|
|
131
|
+
if (!isAbsolute(options.path) || options.path.includes('\0')) {
|
|
132
|
+
throw new Error(`Invalid retained ${options.label.toLowerCase()} worktree path`);
|
|
133
|
+
}
|
|
134
|
+
const path = resolve(options.path);
|
|
135
|
+
let entry;
|
|
136
|
+
try {
|
|
137
|
+
entry = await lstat(path);
|
|
138
|
+
}
|
|
139
|
+
catch (error) {
|
|
140
|
+
if (error.code === 'ENOENT') {
|
|
141
|
+
throw new Error(`Retained ${options.label.toLowerCase()} worktree is missing: ${path}`);
|
|
142
|
+
}
|
|
143
|
+
throw error;
|
|
144
|
+
}
|
|
145
|
+
if (entry.isSymbolicLink() || !entry.isDirectory()) {
|
|
146
|
+
throw new Error(`Retained ${options.label.toLowerCase()} worktree must be a real directory: ${path}`);
|
|
147
|
+
}
|
|
148
|
+
let root;
|
|
149
|
+
let registered;
|
|
150
|
+
let canonicalPath;
|
|
151
|
+
try {
|
|
152
|
+
;
|
|
153
|
+
[root, canonicalPath] = await Promise.all([
|
|
154
|
+
git(options.cwd, ['rev-parse', '--show-toplevel']),
|
|
155
|
+
realpath(path),
|
|
156
|
+
]);
|
|
157
|
+
registered = await registeredWorktrees(root);
|
|
158
|
+
}
|
|
159
|
+
catch (error) {
|
|
160
|
+
throw new Error(`Could not inspect retained ${options.label.toLowerCase()} worktree ${path}: ${error.message}`);
|
|
161
|
+
}
|
|
162
|
+
if (!registered.has(path) && !registered.has(canonicalPath)) {
|
|
163
|
+
throw new Error(`Retained ${options.label.toLowerCase()} worktree is not registered: ${path}`);
|
|
164
|
+
}
|
|
165
|
+
const worktreeRoot = await realpath(resolve(await git(path, ['rev-parse', '--show-toplevel'])));
|
|
166
|
+
if (worktreeRoot !== canonicalPath) {
|
|
167
|
+
throw new Error(`Retained ${options.label.toLowerCase()} worktree path is not its root: ${path}`);
|
|
168
|
+
}
|
|
169
|
+
return {
|
|
170
|
+
cwd: path,
|
|
171
|
+
async cleanup() {
|
|
172
|
+
return {
|
|
173
|
+
retained: true,
|
|
174
|
+
reason: `${options.label} worktree was restored and retained at ${path}`,
|
|
175
|
+
};
|
|
176
|
+
},
|
|
177
|
+
};
|
|
178
|
+
}
|
|
127
179
|
//# sourceMappingURL=managed-worktree.js.map
|
|
@@ -4,6 +4,8 @@ import { type DataPlane } from '../persistence/data-plane.js';
|
|
|
4
4
|
import { type ClaudeFileResource, type ClaudeFileResourceConfig } from '../compatibility/claude/file-resources.js';
|
|
5
5
|
import { type ClaudeDisplayTranscriptItem } from '../compatibility/claude/projection.js';
|
|
6
6
|
import { type ClaudeTranscriptEntry } from '../compatibility/claude/schema.js';
|
|
7
|
+
import { type ClaudeSessionMetadata } from '../compatibility/claude/session-metadata.js';
|
|
8
|
+
import { type ClaudeInterruptionClassification } from '../compatibility/claude/interruption.js';
|
|
7
9
|
import { type ModelDocument, type ModelImage, type ModelToolCall, type ModelProvider, type ModelUsage, type PermissionApproval, type PermissionDecision, type PermissionResolver, type PermissionUpdate, type RuntimeEventSink, type ToolRegistry } from '../core/runtime.js';
|
|
8
10
|
import { type BackgroundTaskSnapshot } from './background-task-runtime.js';
|
|
9
11
|
import type { ModelPricingRegistry } from '../core/usage.js';
|
|
@@ -38,6 +40,8 @@ export interface ClaudeSessionServiceOptions {
|
|
|
38
40
|
persistPermissionUpdates?: (updates: readonly PermissionUpdate[]) => void | Promise<void>;
|
|
39
41
|
approveTool?: (call: ModelToolCall, originalCall?: ModelToolCall, decision?: PermissionDecision) => PermissionApproval | Promise<PermissionApproval>;
|
|
40
42
|
approveRecovery?: (call: ModelToolCall) => boolean | Promise<boolean>;
|
|
43
|
+
/** Explicit Claude-compatible opt-in for replaying an interrupted turn. */
|
|
44
|
+
resumeInterruptedTurn?: boolean;
|
|
41
45
|
contextAssembler?: ContextAssembler;
|
|
42
46
|
conditionalRuleResolver?: Pick<ClaudeConditionalRuleResolver, 'resolve'>;
|
|
43
47
|
extensions?: ClaudeExtensionCatalog;
|
|
@@ -125,6 +129,12 @@ export interface SideQuestionForkResult {
|
|
|
125
129
|
export interface SessionSummary {
|
|
126
130
|
sessionId: string;
|
|
127
131
|
name?: string;
|
|
132
|
+
tag?: string;
|
|
133
|
+
agentName?: string;
|
|
134
|
+
agentColor?: string;
|
|
135
|
+
agentSetting?: string;
|
|
136
|
+
permissionMode?: string;
|
|
137
|
+
mode?: string;
|
|
128
138
|
lastPrompt: string | null;
|
|
129
139
|
updatedAt: string;
|
|
130
140
|
status: SessionStatus;
|
|
@@ -183,10 +193,18 @@ export declare class ClaudeSessionService {
|
|
|
183
193
|
private readonly worktreeManager;
|
|
184
194
|
private readonly sessionCwds;
|
|
185
195
|
private readonly discoveredProjectRoots;
|
|
196
|
+
private readonly explicitSessionFiles;
|
|
197
|
+
private readonly explicitResumeLeafUuids;
|
|
186
198
|
private readonly sessionPermissionUpdates;
|
|
187
199
|
private readonly hostedSubagents;
|
|
200
|
+
private readonly subagentExecutors;
|
|
188
201
|
private readonly hostedSubagentsByRegistry;
|
|
202
|
+
private readonly subagentExecutorSessions;
|
|
203
|
+
private readonly hostedSubagentNotificationPumps;
|
|
204
|
+
private readonly hostedSubagentPumpPromises;
|
|
205
|
+
private readonly hostedSubagentNotificationReservations;
|
|
189
206
|
private readonly backgroundNotificationWrites;
|
|
207
|
+
private closing;
|
|
190
208
|
private readonly downloadedFileResourceSessions;
|
|
191
209
|
private readonly detachedHookRuns;
|
|
192
210
|
private activeProvider;
|
|
@@ -194,6 +212,9 @@ export declare class ClaudeSessionService {
|
|
|
194
212
|
private readonly sessionCostTrackers;
|
|
195
213
|
private activeCostSessionId;
|
|
196
214
|
private closeCostSavePromise;
|
|
215
|
+
private closeMetadataSavePromise;
|
|
216
|
+
private readonly durableMetadataSessions;
|
|
217
|
+
private readonly durableMetadataSnapshots;
|
|
197
218
|
private readonly sessionMemoryControllers;
|
|
198
219
|
private resolvedSessionMemoryProvider;
|
|
199
220
|
private readonly hookLifecycle;
|
|
@@ -212,6 +233,10 @@ export declare class ClaudeSessionService {
|
|
|
212
233
|
private requireMcp;
|
|
213
234
|
taskSnapshots(sessionId: string): Promise<BackgroundTaskSnapshot>;
|
|
214
235
|
stopTask(sessionId: string, taskId: string): Promise<void>;
|
|
236
|
+
backgroundForegroundTask(sessionId: string): import("./background-agent-manager.js").BackgroundAgentSnapshot;
|
|
237
|
+
private sendOwnedBackgroundAgent;
|
|
238
|
+
private sessionSubagentExecutors;
|
|
239
|
+
private collectSubagentNotifications;
|
|
215
240
|
private applyPermissionUpdates;
|
|
216
241
|
close(): Promise<void>;
|
|
217
242
|
transitionHookSession(sessionId: string, reason: Exclude<HookSessionEndReason, 'other'>): Promise<void>;
|
|
@@ -240,14 +265,19 @@ export declare class ClaudeSessionService {
|
|
|
240
265
|
resumeShell(sessionId: string, command: string, signal?: AbortSignal, name?: string, resumeSessionAt?: string): Promise<SessionRunResult>;
|
|
241
266
|
answerSideQuestion(sessionId: string | undefined, question: string, signal?: AbortSignal, onDelta?: (delta: string) => void, permissionMode?: ClaudePermissionMode): Promise<SideQuestionResult>;
|
|
242
267
|
forkSideQuestion(sessionId: string, question: string, signal?: AbortSignal): Promise<SideQuestionForkResult>;
|
|
268
|
+
private startHostedSubagentNotificationPump;
|
|
243
269
|
promptSuggestion(sessionId: string, signal?: AbortSignal): Promise<string | null>;
|
|
244
270
|
sessionNameSuggestion(sessionId: string, signal?: AbortSignal): Promise<string | null>;
|
|
245
271
|
sessions(): Promise<SessionSummary[]>;
|
|
246
272
|
inspect(sessionId: string): Promise<SessionInspection>;
|
|
247
273
|
readEffectiveAgentColor(sessionId: string): Promise<AgentColorName | undefined>;
|
|
248
274
|
export(sessionId: string): Promise<Buffer>;
|
|
275
|
+
registerResumePath(requestedPath: string): Promise<SessionSummary>;
|
|
249
276
|
transcript(sessionId: string, resumeSessionAt?: string): Promise<ClaudeDisplayTranscriptItem[]>;
|
|
277
|
+
interruption(sessionId: string): Promise<ClaudeInterruptionClassification>;
|
|
278
|
+
metadata(sessionId: string): Promise<ClaudeSessionMetadata>;
|
|
250
279
|
rename(sessionId: string, name: string): Promise<void>;
|
|
280
|
+
tag(sessionId: string, tag: string): Promise<void>;
|
|
251
281
|
changeCwd(sessionId: string | undefined, requestedCwd: string): Promise<string>;
|
|
252
282
|
recordCdUsage(sessionId: string): Promise<void>;
|
|
253
283
|
approveRecentlyDenied(sessionId: string, display: string): Promise<void>;
|
|
@@ -269,6 +299,7 @@ export declare class ClaudeSessionService {
|
|
|
269
299
|
private persistActiveSessionCost;
|
|
270
300
|
private recordAuxiliaryMetrics;
|
|
271
301
|
costSnapshot(sessionId: string): Promise<ClaudeSessionCostSnapshot>;
|
|
302
|
+
private withDetachedSubagentUsage;
|
|
272
303
|
private executeTurn;
|
|
273
304
|
private ensureFileResources;
|
|
274
305
|
private translationContext;
|
|
@@ -303,7 +334,14 @@ export declare class ClaudeSessionService {
|
|
|
303
334
|
private cdCommandEntries;
|
|
304
335
|
private localCommandEntries;
|
|
305
336
|
private store;
|
|
337
|
+
/**
|
|
338
|
+
* Refreshes metadata under the transcript lease before writing a compact
|
|
339
|
+
* tail snapshot. This prevents a long-lived process from overwriting a
|
|
340
|
+
* newer title or tag appended by another writer.
|
|
341
|
+
*/
|
|
342
|
+
private reappendDurableMetadata;
|
|
306
343
|
private turnStore;
|
|
344
|
+
private rememberDurableMetadata;
|
|
307
345
|
private assertSessionPersistence;
|
|
308
346
|
private assertWritable;
|
|
309
347
|
private sessionStatus;
|