praxis-agent 0.46.1 → 0.46.4
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 +28 -18
- package/dist/application/session-service.d.ts +7 -1
- package/dist/application/session-service.js +42 -9
- package/dist/cli/interactive.d.ts +3 -2
- package/dist/cli/interactive.js +126 -16
- package/dist/cli/tui/decision-surface-model.d.ts +18 -1
- package/dist/cli/tui/decision-surface-model.js +26 -0
- package/dist/cli/tui/decision-surface.js +4 -1
- package/dist/cli/tui/open-url.d.ts +11 -1
- package/dist/cli/tui/open-url.js +27 -7
- package/dist/cli/tui/quiet-choice-rows.js +14 -1
- package/dist/cli/tui/sandbox-settings.d.ts +10 -1
- package/dist/cli/tui/sandbox-settings.js +7 -7
- package/dist/cli/tui/tui-focus-stack.d.ts +1 -0
- package/dist/cli/tui/tui-focus-stack.js +6 -0
- package/dist/cli/tui/tui-interaction-router.d.ts +1 -1
- package/dist/cli-runtime.d.ts +3 -2
- package/dist/cli-runtime.js +2 -1
- package/dist/native/schema.d.ts +0 -4
- package/dist/native/schema.js +1 -23
- package/dist/platform/bounded-process-runner.d.ts +4 -0
- package/dist/platform/bounded-process-runner.js +59 -1
- package/dist/sandbox/claude-sandbox-runtime.d.ts +1 -0
- package/dist/sandbox/claude-sandbox-runtime.js +1 -1
- package/dist/tools/local-tools.d.ts +7 -0
- package/dist/tools/local-tools.js +303 -51
- package/dist/tools/team-lead-tools.js +24 -5
- package/package.json +8 -5
- package/dist/native/fork.d.ts +0 -9
- package/dist/native/fork.js +0 -260
|
@@ -19,6 +19,12 @@ export function projectTuiFocusStack(input) {
|
|
|
19
19
|
layer: { kind: 'cancelable', target: 'plan-approval' },
|
|
20
20
|
};
|
|
21
21
|
}
|
|
22
|
+
else if (input.cdTrust) {
|
|
23
|
+
higher = {
|
|
24
|
+
id: 'cd-trust',
|
|
25
|
+
layer: { kind: 'cancelable', target: 'cd-trust' },
|
|
26
|
+
};
|
|
27
|
+
}
|
|
22
28
|
else if (input.question) {
|
|
23
29
|
higher = {
|
|
24
30
|
id: 'question',
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { type ComposerKeyProjection } from './composer-key-router.js';
|
|
2
2
|
import type { ComposerEditorState } from './composer-editor.js';
|
|
3
3
|
export type TuiScrollIntent = 'page-older' | 'page-newer' | 'half-page-older' | 'half-page-newer' | 'line-older' | 'line-newer' | 'none';
|
|
4
|
-
export type TuiCancellationTarget = 'permission' | 'plan-approval' | 'question' | 'elicitation' | 'elicitation-url-waiting' | 'elicitation-options' | 'file-picker' | 'command-palette';
|
|
4
|
+
export type TuiCancellationTarget = 'permission' | 'plan-approval' | 'cd-trust' | 'question' | 'elicitation' | 'elicitation-url-waiting' | 'elicitation-options' | 'file-picker' | 'command-palette';
|
|
5
5
|
export type TuiInteractionLayer = {
|
|
6
6
|
readonly kind: 'none';
|
|
7
7
|
} | {
|
package/dist/cli-runtime.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import { type ForkResult, type ManualCompactResult, type ManualCompactSelection, type RewindPoint, type SessionForkCheckpoint, type SessionInspection, type SessionRunResult, type SessionSummary, type SideQuestionForkResult, type SideQuestionResult } from './application/session-service.js';
|
|
2
|
+
import { type CwdInspection, type ForkResult, type ManualCompactResult, type ManualCompactSelection, type RewindPoint, type SessionForkCheckpoint, type SessionInspection, type SessionRunResult, type SessionSummary, type SideQuestionForkResult, type SideQuestionResult } from './application/session-service.js';
|
|
3
3
|
import type { TeamLeadOperations } from './application/team-lead-operations.js';
|
|
4
4
|
import type { ClaudeSessionCostSnapshot } from './application/session-cost-tracker.js';
|
|
5
5
|
import { type AgentColorName, type AgentColorSelection } from './core/agent-color.js';
|
|
@@ -43,7 +43,8 @@ interface SessionCommands {
|
|
|
43
43
|
setPermissionMode?(sessionId: string, mode: ClaudePermissionMode): Promise<void>;
|
|
44
44
|
rewindFiles?(sessionId: string, userMessageId: string): Promise<void>;
|
|
45
45
|
rewindPoints?(sessionId: string): Promise<RewindPoint[]>;
|
|
46
|
-
changeCwd?(sessionId: string | undefined, cwd: string): Promise<string>;
|
|
46
|
+
changeCwd?(sessionId: string | undefined, cwd: string, expectedCanonicalTarget?: string): Promise<string>;
|
|
47
|
+
inspectCwd?(cwd: string): Promise<CwdInspection>;
|
|
47
48
|
notify?(sessionId: string | undefined, message: string, notificationType: string, title?: string): void;
|
|
48
49
|
recordCdUsage?(sessionId: string): Promise<void>;
|
|
49
50
|
approveRecentlyDenied?(sessionId: string, display: string): Promise<void>;
|
package/dist/cli-runtime.js
CHANGED
|
@@ -2049,7 +2049,8 @@ const createDefaultService = async ({ eventSink, requireProvider, hooksOnly = fa
|
|
|
2049
2049
|
setPermissionMode: (sessionId, permissionMode) => service.setPermissionMode(sessionId, permissionMode),
|
|
2050
2050
|
rewindFiles: (sessionId, userMessageId) => service.rewindFiles(sessionId, userMessageId),
|
|
2051
2051
|
rewindPoints: (sessionId) => service.rewindPoints(sessionId),
|
|
2052
|
-
changeCwd: (sessionId, cwd) => service.changeCwd(sessionId, cwd),
|
|
2052
|
+
changeCwd: (sessionId, cwd, expectedCanonicalTarget) => service.changeCwd(sessionId, cwd, expectedCanonicalTarget),
|
|
2053
|
+
inspectCwd: (cwd) => service.inspectCwd(cwd),
|
|
2053
2054
|
notify: (sessionId, message, notificationType, title) => service.notifyDetached(sessionId, message, notificationType, title),
|
|
2054
2055
|
recordCdUsage: (sessionId) => service.recordCdUsage(sessionId),
|
|
2055
2056
|
approveRecentlyDenied: (sessionId, display) => service.approveRecentlyDenied(sessionId, display),
|
package/dist/native/schema.d.ts
CHANGED
|
@@ -7,8 +7,4 @@
|
|
|
7
7
|
export type NativeTranscriptEntry = Record<string, unknown> & {
|
|
8
8
|
type: string;
|
|
9
9
|
};
|
|
10
|
-
export declare function isNativeForkableEntryType(type: string): boolean;
|
|
11
|
-
/** Copy only projection metadata; persisted native events are copied by
|
|
12
|
-
* NativeSessionTranscript.forkTo and retain their event identity semantics. */
|
|
13
|
-
export declare function copyNativeEntryWithSessionId(entry: NativeTranscriptEntry, sessionId: string): NativeTranscriptEntry;
|
|
14
10
|
//# sourceMappingURL=schema.d.ts.map
|
package/dist/native/schema.js
CHANGED
|
@@ -1,24 +1,2 @@
|
|
|
1
|
-
|
|
2
|
-
'agent-color',
|
|
3
|
-
'agent-name',
|
|
4
|
-
'agent-setting',
|
|
5
|
-
'ai-title',
|
|
6
|
-
'assistant',
|
|
7
|
-
'attachment',
|
|
8
|
-
'custom-title',
|
|
9
|
-
'last-prompt',
|
|
10
|
-
'mode',
|
|
11
|
-
'permission-mode',
|
|
12
|
-
'pr-link',
|
|
13
|
-
'system',
|
|
14
|
-
'user',
|
|
15
|
-
]);
|
|
16
|
-
export function isNativeForkableEntryType(type) {
|
|
17
|
-
return FORKABLE_ENTRY_TYPES.has(type);
|
|
18
|
-
}
|
|
19
|
-
/** Copy only projection metadata; persisted native events are copied by
|
|
20
|
-
* NativeSessionTranscript.forkTo and retain their event identity semantics. */
|
|
21
|
-
export function copyNativeEntryWithSessionId(entry, sessionId) {
|
|
22
|
-
return { ...entry, sessionId };
|
|
23
|
-
}
|
|
1
|
+
export {};
|
|
24
2
|
//# sourceMappingURL=schema.js.map
|
|
@@ -5,6 +5,7 @@ export interface ProcessResult {
|
|
|
5
5
|
code: number;
|
|
6
6
|
timedOut: boolean;
|
|
7
7
|
truncated: boolean;
|
|
8
|
+
controlOutput?: string;
|
|
8
9
|
}
|
|
9
10
|
export interface BoundedProcessRunnerOptions {
|
|
10
11
|
cwd: string;
|
|
@@ -18,6 +19,9 @@ export interface RunProcessOptions {
|
|
|
18
19
|
signal?: AbortSignal;
|
|
19
20
|
onOutput?: (output: string) => void | Promise<void>;
|
|
20
21
|
env?: Readonly<Record<string, string>>;
|
|
22
|
+
controlOutputBytes?: number;
|
|
23
|
+
controlOutputFd?: number;
|
|
24
|
+
scriptInput?: string;
|
|
21
25
|
}
|
|
22
26
|
export declare function joinedProcessOutput(result: ProcessResult): string;
|
|
23
27
|
export declare class BoundedProcessRunner {
|
|
@@ -87,15 +87,35 @@ export class BoundedProcessRunner {
|
|
|
87
87
|
const sensitiveValues = sensitiveEnvironmentValues(process.env);
|
|
88
88
|
const longestSensitiveValueBytes = sensitiveValues.reduce((longest, value) => Math.max(longest, Buffer.byteLength(value)), 0);
|
|
89
89
|
const rawOutputLimit = this.options.maxOutputBytes + Math.max(3, longestSensitiveValueBytes);
|
|
90
|
+
const controlOutputFd = options.controlOutputBytes === undefined
|
|
91
|
+
? undefined
|
|
92
|
+
: (options.controlOutputFd ?? 3);
|
|
93
|
+
const scriptInputFd = options.scriptInput === undefined ? undefined : 4;
|
|
94
|
+
if (controlOutputFd !== undefined &&
|
|
95
|
+
scriptInputFd !== undefined &&
|
|
96
|
+
controlOutputFd === scriptInputFd) {
|
|
97
|
+
reject(new Error('Process control output and script input FDs conflict'));
|
|
98
|
+
return;
|
|
99
|
+
}
|
|
100
|
+
const highestFd = Math.max(2, controlOutputFd ?? 2, scriptInputFd ?? 2);
|
|
101
|
+
const stdio = Array.from({ length: highestFd + 1 }, () => 'ignore');
|
|
102
|
+
stdio[1] = 'pipe';
|
|
103
|
+
stdio[2] = 'pipe';
|
|
104
|
+
if (controlOutputFd !== undefined)
|
|
105
|
+
stdio[controlOutputFd] = 'pipe';
|
|
106
|
+
if (scriptInputFd !== undefined)
|
|
107
|
+
stdio[scriptInputFd] = 'pipe';
|
|
90
108
|
const child = spawn(options.command, options.args, {
|
|
91
109
|
cwd: options.cwd ?? this.options.cwd,
|
|
92
110
|
detached: process.platform !== 'win32',
|
|
93
111
|
env: { ...sanitizeChildEnvironment(), ...options.env },
|
|
94
|
-
stdio
|
|
112
|
+
stdio,
|
|
95
113
|
});
|
|
96
114
|
const chunks = { stdout: [], stderr: [] };
|
|
97
115
|
const combined = [];
|
|
98
116
|
const retainedBytes = { stdout: 0, stderr: 0, combined: 0 };
|
|
117
|
+
const controlChunks = [];
|
|
118
|
+
let controlBytes = 0;
|
|
99
119
|
let outputBytes = 0;
|
|
100
120
|
let timedOut = false;
|
|
101
121
|
let settled = false;
|
|
@@ -136,8 +156,41 @@ export class BoundedProcessRunner {
|
|
|
136
156
|
}
|
|
137
157
|
updateLiveOutput();
|
|
138
158
|
};
|
|
159
|
+
if (!child.stdout || !child.stderr) {
|
|
160
|
+
reject(new Error('Process output streams were not created'));
|
|
161
|
+
return;
|
|
162
|
+
}
|
|
139
163
|
child.stdout.on('data', (chunk) => retain('stdout', chunk));
|
|
140
164
|
child.stderr.on('data', (chunk) => retain('stderr', chunk));
|
|
165
|
+
const controlStream = controlOutputFd === undefined ? undefined : child.stdio[controlOutputFd];
|
|
166
|
+
if (controlStream) {
|
|
167
|
+
controlStream.on('data', (chunk) => {
|
|
168
|
+
const remaining = Math.max(0, (options.controlOutputBytes ?? 0) - controlBytes);
|
|
169
|
+
if (remaining <= 0)
|
|
170
|
+
return;
|
|
171
|
+
const retained = chunk.subarray(0, remaining);
|
|
172
|
+
controlChunks.push(retained);
|
|
173
|
+
controlBytes += retained.length;
|
|
174
|
+
});
|
|
175
|
+
child.once('exit', () => {
|
|
176
|
+
setImmediate(() => controlStream.destroy());
|
|
177
|
+
});
|
|
178
|
+
}
|
|
179
|
+
const scriptStream = scriptInputFd === undefined ? undefined : child.stdio[scriptInputFd];
|
|
180
|
+
if (scriptStream) {
|
|
181
|
+
scriptStream.on('error', () => {
|
|
182
|
+
// The child process result remains authoritative if it exits before
|
|
183
|
+
// consuming the complete script.
|
|
184
|
+
});
|
|
185
|
+
if (!('end' in scriptStream)) {
|
|
186
|
+
reject(new Error('Process script input stream is not writable'));
|
|
187
|
+
return;
|
|
188
|
+
}
|
|
189
|
+
scriptStream.end(options.scriptInput);
|
|
190
|
+
child.once('exit', () => {
|
|
191
|
+
setImmediate(() => scriptStream.destroy());
|
|
192
|
+
});
|
|
193
|
+
}
|
|
141
194
|
const kill = () => {
|
|
142
195
|
if (child.pid === undefined)
|
|
143
196
|
return;
|
|
@@ -200,6 +253,11 @@ export class BoundedProcessRunner {
|
|
|
200
253
|
code: code ?? 1,
|
|
201
254
|
timedOut,
|
|
202
255
|
truncated,
|
|
256
|
+
...(options.controlOutputBytes === undefined
|
|
257
|
+
? {}
|
|
258
|
+
: {
|
|
259
|
+
controlOutput: Buffer.concat(controlChunks).toString('utf8'),
|
|
260
|
+
}),
|
|
203
261
|
});
|
|
204
262
|
}, reject);
|
|
205
263
|
});
|
|
@@ -136,7 +136,7 @@ export class ClaudeSandboxRuntime {
|
|
|
136
136
|
throw new Error('Sandbox has not been initialized');
|
|
137
137
|
if (!this.shouldUseSandbox(input))
|
|
138
138
|
return input.command;
|
|
139
|
-
return this.backend.wrapWithSandbox(input.command, options.shell, undefined, options.signal, {
|
|
139
|
+
return this.backend.wrapWithSandbox(input.executionCommand ?? input.command, options.shell, undefined, options.signal, {
|
|
140
140
|
...(options.commandId ? { commandId: options.commandId } : {}),
|
|
141
141
|
commandText: input.command,
|
|
142
142
|
});
|
|
@@ -26,6 +26,7 @@ export interface BashSandboxRuntime {
|
|
|
26
26
|
wrapCommand(input: {
|
|
27
27
|
command: string;
|
|
28
28
|
dangerouslyDisableSandbox?: boolean;
|
|
29
|
+
executionCommand?: string;
|
|
29
30
|
}, options?: {
|
|
30
31
|
shell?: string;
|
|
31
32
|
signal?: AbortSignal;
|
|
@@ -43,6 +44,7 @@ export declare class LocalToolRegistry implements ToolRegistry {
|
|
|
43
44
|
private readonly maxOutputBytes;
|
|
44
45
|
private readonly maxFileBytes;
|
|
45
46
|
private readonly maxShellTimeoutMs;
|
|
47
|
+
private readonly maxSearchTimeoutMs;
|
|
46
48
|
private readonly processRunner;
|
|
47
49
|
private readonly enableReportFindings;
|
|
48
50
|
private readonly environment;
|
|
@@ -50,11 +52,14 @@ export declare class LocalToolRegistry implements ToolRegistry {
|
|
|
50
52
|
private readonly sandbox;
|
|
51
53
|
private readonly homeDirectory;
|
|
52
54
|
private readonly configRoot;
|
|
55
|
+
private readonly sessionCwds;
|
|
53
56
|
private readonly protectedWriteReason;
|
|
57
|
+
private readonly mutationTargetExisted;
|
|
54
58
|
constructor(options: LocalToolRegistryOptions);
|
|
55
59
|
private assertProtectedWritePath;
|
|
56
60
|
private assertProtectedBashCommand;
|
|
57
61
|
private currentCwd;
|
|
62
|
+
private currentBashCwd;
|
|
58
63
|
definitions(): readonly ModelToolDefinition[];
|
|
59
64
|
schedulingPolicy(call: ModelToolCall): {
|
|
60
65
|
concurrency: "concurrent";
|
|
@@ -78,7 +83,9 @@ export declare class LocalToolRegistry implements ToolRegistry {
|
|
|
78
83
|
private workspacePath;
|
|
79
84
|
private filePath;
|
|
80
85
|
private resolvePath;
|
|
86
|
+
private pathExists;
|
|
81
87
|
private assertStablePath;
|
|
88
|
+
private assertStableCreationParent;
|
|
82
89
|
private globRoot;
|
|
83
90
|
private wasSuccessfullyRead;
|
|
84
91
|
private read;
|