praxis-agent 0.60.0 → 0.61.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 +6 -1
- package/dist/application/managed-worktree.d.ts +28 -0
- package/dist/application/managed-worktree.js +606 -6
- package/dist/application/subagent-service.js +11 -0
- package/dist/application/workflow-worktree.d.ts +9 -0
- package/dist/application/workflow-worktree.js +31 -4
- package/dist/cli/protocol.d.ts +1 -0
- package/dist/cli/protocol.js +37 -7
- package/dist/cli-runtime.d.ts +1 -0
- package/dist/cli-runtime.js +48 -7
- package/dist/hooks/claude-hooks.js +16 -2
- package/dist/persistence/managed-worktree-store.d.ts +41 -0
- package/dist/persistence/managed-worktree-store.js +341 -0
- package/package.json +1 -1
|
@@ -1,9 +1,18 @@
|
|
|
1
1
|
import { type ManagedWorktree } from './managed-worktree.js';
|
|
2
|
+
import type { ClaudeHookRunner } from '../hooks/claude-hooks.js';
|
|
2
3
|
export type WorkflowWorktree = ManagedWorktree;
|
|
4
|
+
export interface WorkflowWorktreeHookContext {
|
|
5
|
+
runner: ClaudeHookRunner;
|
|
6
|
+
sessionId: string;
|
|
7
|
+
transcriptPath: string;
|
|
8
|
+
permissionMode: string;
|
|
9
|
+
signal?: AbortSignal;
|
|
10
|
+
}
|
|
3
11
|
export declare function createWorkflowWorktree(options: {
|
|
4
12
|
cwd: string;
|
|
5
13
|
praxisRoot: string;
|
|
6
14
|
runId: string;
|
|
7
15
|
agentId: string;
|
|
16
|
+
hookContext?: WorkflowWorktreeHookContext;
|
|
8
17
|
}): Promise<WorkflowWorktree>;
|
|
9
18
|
//# sourceMappingURL=workflow-worktree.d.ts.map
|
|
@@ -1,11 +1,38 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
1
|
+
import { createOwnedManagedWorktree, } from './managed-worktree.js';
|
|
2
|
+
function lifecycleHookInput(input, context, event) {
|
|
3
|
+
const reason = 'reason' in input ? input.reason : undefined;
|
|
4
|
+
return {
|
|
5
|
+
session_id: context.sessionId,
|
|
6
|
+
transcript_path: context.transcriptPath,
|
|
7
|
+
cwd: input.worktreePath,
|
|
8
|
+
permission_mode: context.permissionMode,
|
|
9
|
+
hook_event_name: event,
|
|
10
|
+
worktree_path: input.worktreePath,
|
|
11
|
+
worktree_kind: input.worktreeKind,
|
|
12
|
+
worktree_id: input.worktreeId,
|
|
13
|
+
owner_id: input.ownerId,
|
|
14
|
+
base_commit: input.baseCommit,
|
|
15
|
+
...(event === 'WorktreeRemove' && reason !== undefined ? { reason } : {}),
|
|
16
|
+
};
|
|
17
|
+
}
|
|
18
|
+
function lifecycleHooks(context) {
|
|
19
|
+
return {
|
|
20
|
+
afterCreate: async (input) => context.runner.run(lifecycleHookInput(input, context, 'WorktreeCreate'), input.worktreeKind, context.signal),
|
|
21
|
+
beforeRemove: async (input) => context.runner.run(lifecycleHookInput(input, context, 'WorktreeRemove'), input.worktreeKind, context.signal),
|
|
22
|
+
};
|
|
23
|
+
}
|
|
3
24
|
export async function createWorkflowWorktree(options) {
|
|
4
|
-
return
|
|
25
|
+
return createOwnedManagedWorktree({
|
|
5
26
|
cwd: options.cwd,
|
|
6
|
-
|
|
27
|
+
stateRoot: options.praxisRoot,
|
|
7
28
|
directoryName: `${options.runId}-${options.agentId}`,
|
|
29
|
+
ownerId: `workflow:${options.runId}:${options.agentId}`,
|
|
8
30
|
label: 'Workflow',
|
|
31
|
+
kind: 'workflow',
|
|
32
|
+
policy: 'ephemeral',
|
|
33
|
+
...(options.hookContext
|
|
34
|
+
? { hooks: lifecycleHooks(options.hookContext) }
|
|
35
|
+
: {}),
|
|
9
36
|
});
|
|
10
37
|
}
|
|
11
38
|
//# sourceMappingURL=workflow-worktree.js.map
|
package/dist/cli/protocol.d.ts
CHANGED
|
@@ -243,6 +243,7 @@ export interface ProtocolTimingProjection {
|
|
|
243
243
|
}
|
|
244
244
|
export declare function projectProtocolTimings(startedAt: number, requestAt?: number, outputAt?: number): ProtocolTimingProjection;
|
|
245
245
|
export declare function createSuccessResult(result: ProtocolResult, info: CliRuntimeInfo, startedAt: number, modelTurns: number, context?: ProtocolSuccessProjectionContext): Record<string, unknown>;
|
|
246
|
+
export declare function formatPrintTextError(message: string, context?: ProtocolErrorProjectionContext): string;
|
|
246
247
|
export declare function createErrorResult(message: string, sessionId: string, startedAt: number, modelTurns: number, context?: ProtocolErrorProjectionContext): Record<string, unknown>;
|
|
247
248
|
/**
|
|
248
249
|
* Returns the argument text of a headless `/color` prompt, or undefined when
|
package/dist/cli/protocol.js
CHANGED
|
@@ -94,14 +94,44 @@ export function createSuccessResult(result, info, startedAt, modelTurns, context
|
|
|
94
94
|
uuid: randomUUID(),
|
|
95
95
|
};
|
|
96
96
|
}
|
|
97
|
+
function classifyErrorResult(message) {
|
|
98
|
+
const maxBudget = /Maximum budget of \$([0-9]+(?:\.[0-9]+)?) exceeded/iu.exec(message);
|
|
99
|
+
if (maxBudget || /maximum budget|budget .* exceeded/iu.test(message)) {
|
|
100
|
+
return {
|
|
101
|
+
subtype: 'error_max_budget_usd',
|
|
102
|
+
...(maxBudget?.[1] === undefined ? {} : { maxBudgetUsd: maxBudget[1] }),
|
|
103
|
+
};
|
|
104
|
+
}
|
|
105
|
+
const maxTurns = /Maximum model turns of (\d+) exceeded/iu.exec(message);
|
|
106
|
+
if (maxTurns || /maximum model turns|model turn limit/iu.test(message)) {
|
|
107
|
+
return {
|
|
108
|
+
subtype: 'error_max_turns',
|
|
109
|
+
...(maxTurns?.[1] === undefined ? {} : { maxTurns: maxTurns[1] }),
|
|
110
|
+
};
|
|
111
|
+
}
|
|
112
|
+
if (/StructuredOutput/iu.test(message)) {
|
|
113
|
+
return { subtype: 'error_max_structured_output_retries' };
|
|
114
|
+
}
|
|
115
|
+
return { subtype: 'error_during_execution' };
|
|
116
|
+
}
|
|
97
117
|
function errorResultSubtype(message) {
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
118
|
+
return classifyErrorResult(message).subtype;
|
|
119
|
+
}
|
|
120
|
+
export function formatPrintTextError(message, context = {}) {
|
|
121
|
+
if (context.providerApiError === true) {
|
|
122
|
+
const normalized = typeof context.apiErrorStatus === 'number'
|
|
123
|
+
? normalizeApiError(message, context.apiErrorStatus)
|
|
124
|
+
: message;
|
|
125
|
+
return `${normalized}\n`;
|
|
126
|
+
}
|
|
127
|
+
const classification = classifyErrorResult(message);
|
|
128
|
+
if (classification.maxTurns !== undefined)
|
|
129
|
+
return `Error: Reached max turns (${classification.maxTurns})`;
|
|
130
|
+
if (classification.maxBudgetUsd !== undefined)
|
|
131
|
+
return `Error: Exceeded USD budget (${classification.maxBudgetUsd})`;
|
|
132
|
+
if (classification.subtype === 'error_max_structured_output_retries')
|
|
133
|
+
return 'Error: Failed to provide valid structured output after maximum retries';
|
|
134
|
+
return 'Execution error';
|
|
105
135
|
}
|
|
106
136
|
export function createErrorResult(message, sessionId, startedAt, modelTurns, context = {}) {
|
|
107
137
|
const duration = Date.now() - startedAt;
|
package/dist/cli-runtime.d.ts
CHANGED
|
@@ -34,6 +34,7 @@ export interface CliIO {
|
|
|
34
34
|
stdout(message: string | Uint8Array): void;
|
|
35
35
|
stderr(message: string): void;
|
|
36
36
|
isTTY?: boolean;
|
|
37
|
+
stdinIsTTY?: boolean;
|
|
37
38
|
readStdinLines?: () => AsyncIterable<string | Uint8Array>;
|
|
38
39
|
readSecret?: (prompt: string, signal?: AbortSignal) => Promise<string>;
|
|
39
40
|
}
|
package/dist/cli-runtime.js
CHANGED
|
@@ -65,7 +65,7 @@ import { WorkspaceContext } from './application/session-worktree.js';
|
|
|
65
65
|
import { launchTmuxWorktree } from './platform/tmux-worktree.js';
|
|
66
66
|
import { claudeSandboxRuntime } from './sandbox/claude-sandbox-runtime.js';
|
|
67
67
|
import { nativeSandboxTempDirectory, loadClaudeSandboxSettings, } from './sandbox/claude-sandbox-settings.js';
|
|
68
|
-
import { createErrorResult, createSuccessResult, isHeadlessCostCommand, matchHeadlessColorCommand, parseCliInvocation, projectProtocolTimings, readStreamJsonMessages, StreamJsonOutput, } from './cli/protocol.js';
|
|
68
|
+
import { createErrorResult, createSuccessResult, isHeadlessCostCommand, matchHeadlessColorCommand, formatPrintTextError, parseCliInvocation, projectProtocolTimings, readStreamJsonMessages, StreamJsonOutput, } from './cli/protocol.js';
|
|
69
69
|
import { isDirectProcessSigint } from './cli/process-signal.js';
|
|
70
70
|
import { executeProviderAuthCommand } from './cli/provider-auth-command.js';
|
|
71
71
|
import { describeClaudePlugin, initClaudePlugin, installClaudePlugin, loadClaudePlugins, readPluginRegistry, setClaudePluginEnabled, uninstallClaudePlugin, updateClaudePlugin, validateClaudePlugin, } from './plugins/claude-plugin-runtime.js';
|
|
@@ -893,6 +893,7 @@ const consoleIO = {
|
|
|
893
893
|
stdout: (message) => process.stdout.write(message),
|
|
894
894
|
stderr: (message) => process.stderr.write(message),
|
|
895
895
|
isTTY: Boolean(process.stdin.isTTY && process.stdout.isTTY),
|
|
896
|
+
stdinIsTTY: Boolean(process.stdin.isTTY),
|
|
896
897
|
readStdinLines: () => process.stdin,
|
|
897
898
|
readSecret: readConsoleSecret,
|
|
898
899
|
};
|
|
@@ -4243,7 +4244,7 @@ async function executeMcpCommand(args, invocation, io, dependencies, signal) {
|
|
|
4243
4244
|
}
|
|
4244
4245
|
throw new Error(`Unknown mcp command: ${action}`);
|
|
4245
4246
|
}
|
|
4246
|
-
function eventSink(io, outputFormat, legacyJson = false) {
|
|
4247
|
+
function eventSink(io, outputFormat, legacyJson = false, printText = false) {
|
|
4247
4248
|
const sensitiveValues = sensitiveEnvironmentValues(process.env);
|
|
4248
4249
|
if (legacyJson) {
|
|
4249
4250
|
return (event) => {
|
|
@@ -4261,6 +4262,12 @@ function eventSink(io, outputFormat, legacyJson = false) {
|
|
|
4261
4262
|
}
|
|
4262
4263
|
if (outputFormat !== 'text')
|
|
4263
4264
|
return () => undefined;
|
|
4265
|
+
if (printText)
|
|
4266
|
+
return (event) => {
|
|
4267
|
+
if (event.type === 'warning') {
|
|
4268
|
+
io.stderr(`Warning: ${redactSensitiveText(event.message, sensitiveValues)}\n`);
|
|
4269
|
+
}
|
|
4270
|
+
};
|
|
4264
4271
|
let turnBuffered = false;
|
|
4265
4272
|
let bufferedText = '';
|
|
4266
4273
|
const flushBufferedText = () => {
|
|
@@ -4313,6 +4320,29 @@ function promptFrom(values) {
|
|
|
4313
4320
|
throw new Error('Prompt is required');
|
|
4314
4321
|
return prompt;
|
|
4315
4322
|
}
|
|
4323
|
+
async function resolvePrintTextPrompt(io, argvPrompt) {
|
|
4324
|
+
const missingInput = () => new Error('Error: Input must be provided either through stdin or as a prompt argument when using --print');
|
|
4325
|
+
if (io.stdinIsTTY !== false) {
|
|
4326
|
+
if (argvPrompt !== undefined)
|
|
4327
|
+
return argvPrompt;
|
|
4328
|
+
throw missingInput();
|
|
4329
|
+
}
|
|
4330
|
+
const input = io.readStdinLines?.();
|
|
4331
|
+
if (!input)
|
|
4332
|
+
throw new Error('print text input requires stdin support');
|
|
4333
|
+
const chunks = [];
|
|
4334
|
+
for await (const chunk of input) {
|
|
4335
|
+
chunks.push(Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk));
|
|
4336
|
+
}
|
|
4337
|
+
const stdinText = Buffer.concat(chunks).toString('utf8');
|
|
4338
|
+
if (argvPrompt !== undefined && stdinText.length > 0)
|
|
4339
|
+
return `${argvPrompt}\n${stdinText}`;
|
|
4340
|
+
if (argvPrompt !== undefined)
|
|
4341
|
+
return argvPrompt;
|
|
4342
|
+
if (stdinText.length > 0)
|
|
4343
|
+
return stdinText;
|
|
4344
|
+
throw missingInput();
|
|
4345
|
+
}
|
|
4316
4346
|
function backgroundWorkerArgv(argv) {
|
|
4317
4347
|
const filtered = [];
|
|
4318
4348
|
let optionsEnded = false;
|
|
@@ -5578,9 +5608,14 @@ async function execute(argv, io, dependencies, signal) {
|
|
|
5578
5608
|
};
|
|
5579
5609
|
};
|
|
5580
5610
|
const headlessPromptArgs = command === 'resume' ? args.slice(2) : knownCommand ? args.slice(1) : args;
|
|
5581
|
-
const
|
|
5611
|
+
const headlessTurnReached = invocation.rewindFiles === undefined &&
|
|
5612
|
+
!['sessions', 'fork', 'inspect', 'export'].includes(command ?? 'run');
|
|
5613
|
+
const argvHeadlessPrompt = inputFormat === 'text' && headlessPromptArgs.length > 0
|
|
5582
5614
|
? promptFrom(headlessPromptArgs)
|
|
5583
5615
|
: undefined;
|
|
5616
|
+
const headlessPrompt = inputFormat === 'text' && headlessTurnReached && invocation.print
|
|
5617
|
+
? await resolvePrintTextPrompt(io, argvHeadlessPrompt)
|
|
5618
|
+
: argvHeadlessPrompt;
|
|
5584
5619
|
if (headlessPrompt === '/release-notes' && !invocation.disableSlashCommands) {
|
|
5585
5620
|
const startedAt = Date.now();
|
|
5586
5621
|
const sessionId = invocation.sessionId ?? randomUUID();
|
|
@@ -5629,8 +5664,6 @@ async function execute(argv, io, dependencies, signal) {
|
|
|
5629
5664
|
}
|
|
5630
5665
|
return 0;
|
|
5631
5666
|
}
|
|
5632
|
-
const headlessTurnReached = invocation.rewindFiles === undefined &&
|
|
5633
|
-
!['sessions', 'fork', 'inspect', 'export'].includes(command ?? 'run');
|
|
5634
5667
|
if (streamIterator && headlessTurnReached) {
|
|
5635
5668
|
const first = await nextStreamUser();
|
|
5636
5669
|
if (first)
|
|
@@ -5686,7 +5719,7 @@ async function execute(argv, io, dependencies, signal) {
|
|
|
5686
5719
|
io.stderr(`Warning: ${redactSensitiveText(event.message, sensitiveEnvironmentValues(process.env))}\n`);
|
|
5687
5720
|
}
|
|
5688
5721
|
}
|
|
5689
|
-
: eventSink(io, outputFormat, invocation.legacyJson),
|
|
5722
|
+
: eventSink(io, outputFormat, invocation.legacyJson, invocation.print && inputFormat === 'text'),
|
|
5690
5723
|
requireProvider: !streamInputExhausted &&
|
|
5691
5724
|
!firstTurnIsLocalColor &&
|
|
5692
5725
|
!firstTurnIsLocalCost &&
|
|
@@ -5818,6 +5851,7 @@ async function execute(argv, io, dependencies, signal) {
|
|
|
5818
5851
|
if (streamInputExhausted)
|
|
5819
5852
|
return 0;
|
|
5820
5853
|
const initialPrompt = firstStreamMessage?.prompt ??
|
|
5854
|
+
headlessPrompt ??
|
|
5821
5855
|
promptFrom(command === 'resume'
|
|
5822
5856
|
? args.slice(2)
|
|
5823
5857
|
: knownCommand
|
|
@@ -5833,7 +5867,6 @@ async function execute(argv, io, dependencies, signal) {
|
|
|
5833
5867
|
signal?.addEventListener('abort', forwardAbort, { once: true });
|
|
5834
5868
|
currentTurnAbort = streamIterator ? turnAbort : undefined;
|
|
5835
5869
|
const runSignal = streamIterator ? turnAbort.signal : signal;
|
|
5836
|
-
await ensureCostBaseline(activeSessionId);
|
|
5837
5870
|
jsonModelTurns = 0;
|
|
5838
5871
|
jsonRequestAt = undefined;
|
|
5839
5872
|
jsonOutputAt = undefined;
|
|
@@ -5851,6 +5884,7 @@ async function execute(argv, io, dependencies, signal) {
|
|
|
5851
5884
|
let colorArgs;
|
|
5852
5885
|
let costTurn = false;
|
|
5853
5886
|
try {
|
|
5887
|
+
await ensureCostBaseline(activeSessionId);
|
|
5854
5888
|
costTurn =
|
|
5855
5889
|
!invocation.disableSlashCommands && isHeadlessCostCommand(prompt);
|
|
5856
5890
|
colorArgs = invocation.disableSlashCommands
|
|
@@ -5939,6 +5973,11 @@ async function execute(argv, io, dependencies, signal) {
|
|
|
5939
5973
|
else if (outputFormat === 'json') {
|
|
5940
5974
|
writeJson(io, createErrorResult(message, activeSessionId, startedAt, jsonModelTurns, errorContext));
|
|
5941
5975
|
}
|
|
5976
|
+
else if (invocation.print &&
|
|
5977
|
+
inputFormat === 'text' &&
|
|
5978
|
+
outputFormat === 'text') {
|
|
5979
|
+
io.stdout(formatPrintTextError(message, errorContext));
|
|
5980
|
+
}
|
|
5942
5981
|
else {
|
|
5943
5982
|
if (currentTurnAbort === turnAbort)
|
|
5944
5983
|
currentTurnAbort = undefined;
|
|
@@ -5971,6 +6010,8 @@ async function execute(argv, io, dependencies, signal) {
|
|
|
5971
6010
|
}
|
|
5972
6011
|
else if (outputFormat !== 'text')
|
|
5973
6012
|
writeJson(io, { type: 'result', ...result });
|
|
6013
|
+
else if (invocation.print && inputFormat === 'text')
|
|
6014
|
+
io.stdout(`${result.text}\n`);
|
|
5974
6015
|
else
|
|
5975
6016
|
io.stdout(localCommand ? `${result.text}\n` : '\n');
|
|
5976
6017
|
if (streamOutput && invocation.promptSuggestions) {
|
|
@@ -28,7 +28,14 @@ export const HOOK_EVENTS = [
|
|
|
28
28
|
'FileChanged',
|
|
29
29
|
'SessionEnd',
|
|
30
30
|
];
|
|
31
|
-
const
|
|
31
|
+
const LIFECYCLE_HOOK_EVENTS = [
|
|
32
|
+
'WorktreeCreate',
|
|
33
|
+
'WorktreeRemove',
|
|
34
|
+
];
|
|
35
|
+
const EXECUTABLE_HOOK_EVENTS = new Set([
|
|
36
|
+
...HOOK_EVENTS,
|
|
37
|
+
...LIFECYCLE_HOOK_EVENTS,
|
|
38
|
+
]);
|
|
32
39
|
function isRecord(value) {
|
|
33
40
|
return typeof value === 'object' && value !== null && !Array.isArray(value);
|
|
34
41
|
}
|
|
@@ -91,6 +98,9 @@ function eventSettings(settings, event, maxTimeoutMs) {
|
|
|
91
98
|
if (hook.async !== undefined && typeof hook.async !== 'boolean') {
|
|
92
99
|
throw new Error(`Invalid Claude ${event} hook async: ${resource.path}`);
|
|
93
100
|
}
|
|
101
|
+
if (LIFECYCLE_HOOK_EVENTS.includes(event) && hook.async === true) {
|
|
102
|
+
throw new Error(`Invalid Claude ${event} hook async: ${resource.path}`);
|
|
103
|
+
}
|
|
94
104
|
return [
|
|
95
105
|
{
|
|
96
106
|
command,
|
|
@@ -145,8 +155,9 @@ export function validateClaudeHooks(settings, maxTimeoutMs = DEFAULT_TIMEOUT_MS)
|
|
|
145
155
|
!Number.isInteger(maxTimeoutMs)) {
|
|
146
156
|
throw new Error('Hook max timeout must be a positive integer');
|
|
147
157
|
}
|
|
148
|
-
for (const event of HOOK_EVENTS)
|
|
158
|
+
for (const event of [...HOOK_EVENTS, ...LIFECYCLE_HOOK_EVENTS]) {
|
|
149
159
|
eventSettings(settings, event, maxTimeoutMs);
|
|
160
|
+
}
|
|
150
161
|
}
|
|
151
162
|
function outputRecord(stdout) {
|
|
152
163
|
const trimmed = stdout.trim();
|
|
@@ -204,6 +215,9 @@ function hookMatcherValue(input) {
|
|
|
204
215
|
return basename(optionalString(input.file_path) ?? '');
|
|
205
216
|
case 'SessionEnd':
|
|
206
217
|
return optionalString(input.reason) ?? '';
|
|
218
|
+
case 'WorktreeCreate':
|
|
219
|
+
case 'WorktreeRemove':
|
|
220
|
+
return optionalString(input.worktree_kind) ?? '';
|
|
207
221
|
default:
|
|
208
222
|
return '';
|
|
209
223
|
}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { type ExclusiveFileLeaseHandle } from '../platform/exclusive-file-lease.js';
|
|
2
|
+
type ManagedWorktreeKind = 'workflow' | 'agent' | 'team';
|
|
3
|
+
type ManagedWorktreePolicy = 'ephemeral' | 'durable';
|
|
4
|
+
type ManagedWorktreeState = 'creating' | 'active' | 'releasing' | 'retained' | 'released';
|
|
5
|
+
export interface ManagedWorktreeRecord {
|
|
6
|
+
version: 1;
|
|
7
|
+
worktreeId: string;
|
|
8
|
+
kind: ManagedWorktreeKind;
|
|
9
|
+
policy: ManagedWorktreePolicy;
|
|
10
|
+
ownerId: string;
|
|
11
|
+
repositoryRoot: string;
|
|
12
|
+
worktreePath: string;
|
|
13
|
+
branch: string | null;
|
|
14
|
+
baseCommit: string;
|
|
15
|
+
state: ManagedWorktreeState;
|
|
16
|
+
createdAt: string;
|
|
17
|
+
updatedAt: string;
|
|
18
|
+
retentionReason?: string;
|
|
19
|
+
}
|
|
20
|
+
export declare class ManagedWorktreeStore {
|
|
21
|
+
readonly path: string;
|
|
22
|
+
readonly lockPath: string;
|
|
23
|
+
readonly projectLockPath: string;
|
|
24
|
+
private readonly directory;
|
|
25
|
+
private readonly stateRoot;
|
|
26
|
+
private readonly repositoryRoot;
|
|
27
|
+
private readonly worktreeId;
|
|
28
|
+
private readonly worktreeLease;
|
|
29
|
+
private readonly projectLease;
|
|
30
|
+
constructor(stateRoot: string, repositoryRoot: string, worktreeId: string);
|
|
31
|
+
acquireLease(): Promise<ExclusiveFileLeaseHandle | null>;
|
|
32
|
+
read(): Promise<ManagedWorktreeRecord>;
|
|
33
|
+
create(record: ManagedWorktreeRecord): Promise<void>;
|
|
34
|
+
update(record: ManagedWorktreeRecord): Promise<void>;
|
|
35
|
+
private withProjectLease;
|
|
36
|
+
private assertUnreservedPath;
|
|
37
|
+
private assertStoreIdentity;
|
|
38
|
+
private assertSameIdentity;
|
|
39
|
+
}
|
|
40
|
+
export {};
|
|
41
|
+
//# sourceMappingURL=managed-worktree-store.d.ts.map
|