praxis-agent 0.10.0 → 0.11.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 +15 -2
- package/dist/application/session-service.d.ts +5 -2
- package/dist/application/session-service.js +23 -0
- package/dist/application/subagent-service.d.ts +4 -2
- package/dist/application/subagent-service.js +4 -0
- package/dist/cli/interactive.d.ts +4 -3
- package/dist/cli/interactive.js +517 -58
- package/dist/cli/tui/claude-command-inventory.d.ts +368 -0
- package/dist/cli/tui/claude-command-inventory.js +220 -0
- package/dist/cli/tui/mcp-elicitation.d.ts +75 -0
- package/dist/cli/tui/mcp-elicitation.js +497 -0
- package/dist/cli/tui/open-url.d.ts +2 -0
- package/dist/cli/tui/open-url.js +13 -0
- package/dist/cli/tui/permission-settings.d.ts +6 -0
- package/dist/cli/tui/permission-settings.js +84 -0
- package/dist/cli/tui/slash-commands.js +3 -28
- package/dist/cli/tui/tool-permission.d.ts +36 -0
- package/dist/cli/tui/tool-permission.js +386 -0
- package/dist/cli.d.ts +2 -2
- package/dist/cli.js +28 -13
- package/dist/core/runtime.d.ts +50 -2
- package/dist/core/runtime.js +30 -3
- package/dist/extensions/claude-extension-tools.d.ts +3 -2
- package/dist/extensions/claude-extension-tools.js +15 -5
- package/dist/extensions/claude-extensions.d.ts +1 -0
- package/dist/extensions/claude-extensions.js +10 -0
- package/dist/hooks/claude-hook-tools.js +1 -1
- package/dist/mcp/claude-mcp-tools.js +12 -6
- package/dist/permissions/bash-ast.d.ts +39 -0
- package/dist/permissions/bash-ast.js +1046 -0
- package/dist/permissions/bash-normalization.d.ts +5 -0
- package/dist/permissions/bash-normalization.js +241 -0
- package/dist/permissions/bash-path-safety.d.ts +28 -0
- package/dist/permissions/bash-path-safety.js +575 -0
- package/dist/permissions/claude-permission-resolver.d.ts +7 -0
- package/dist/permissions/claude-permission-resolver.js +351 -40
- package/dist/permissions/claude-shell-permission.d.ts +4 -0
- package/dist/permissions/claude-shell-permission.js +108 -0
- package/dist/permissions/permission-updates.d.ts +16 -0
- package/dist/permissions/permission-updates.js +320 -0
- package/dist/permissions/sed-safety.d.ts +9 -0
- package/dist/permissions/sed-safety.js +172 -0
- package/dist/permissions/shell-rule-matching.d.ts +14 -0
- package/dist/permissions/shell-rule-matching.js +76 -0
- package/dist/tools/claude-interactive-tools.d.ts +10 -1
- package/dist/tools/claude-interactive-tools.js +10 -4
- package/dist/tools/local-tools.js +22 -2
- package/package.json +3 -1
package/README.md
CHANGED
|
@@ -109,8 +109,21 @@ troubleshooting. Run `praxis --help` for the authoritative command surface.
|
|
|
109
109
|
image, web, scheduled prompts, workflows, and worktrees.
|
|
110
110
|
- **Permission boundary** — local allow/ask/deny rules, safe and bare modes,
|
|
111
111
|
searchable scoped-rule creation/removal, local/project/user atomic settings
|
|
112
|
-
writes,
|
|
113
|
-
|
|
112
|
+
writes, tool-specific Bash/PowerShell/file/notebook/WebFetch/Skill approval
|
|
113
|
+
dialogs, editable reusable shell and Skill rules, source-root-aware Claude
|
|
114
|
+
file-rule matching, atomic session permission updates, compound-shell rule
|
|
115
|
+
suggestions backed by a bounded Bash AST, source-shaped exact/prefix/wildcard
|
|
116
|
+
matching, wrapper and environment normalization, fail-closed Bash semantic
|
|
117
|
+
checks with control-flow-aware variable scopes, declaration and literal-only
|
|
118
|
+
arithmetic analysis, exact `cat` heredoc handling, argv-based
|
|
119
|
+
command/redirection path validation, full symlink-chain checks, dangerous-removal,
|
|
120
|
+
sensitive-file, and suspicious Windows-path gates, source-ordered strict sed
|
|
121
|
+
constraints, internal auto-memory/session/task path handling, compound `cd` +
|
|
122
|
+
Git protection, mode-ordered `acceptEdits` handling, live raw/resolved-path
|
|
123
|
+
grants for external directories,
|
|
124
|
+
safe-property Skill auto-allow, interactive
|
|
125
|
+
workspace-directory add/remove controls, path confinement, credential
|
|
126
|
+
redaction, and sanitized child processes.
|
|
114
127
|
- **Durable local work** — resumable sessions, full-history forks, file
|
|
115
128
|
checkpoints, tasks, foreground/background subagents, and top-level agents.
|
|
116
129
|
- **Claude-compatible ecosystem** — shared instructions with recursive `@`
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { ClaudeConditionalRuleResolver } from '../compatibility/claude/context.js';
|
|
2
2
|
import { type ClaudeFileResource, type ClaudeFileResourceConfig } from '../compatibility/claude/file-resources.js';
|
|
3
3
|
import { type ClaudeDisplayTranscriptItem } from '../compatibility/claude/projection.js';
|
|
4
|
-
import { type ModelDocument, type ModelImage, type ModelToolCall, type ModelProvider, type ModelUsage, type PermissionApproval, type PermissionResolver, type RuntimeEventSink, type ToolRegistry } from '../core/runtime.js';
|
|
4
|
+
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';
|
|
5
5
|
import { type BackgroundTaskSnapshot } from './background-task-runtime.js';
|
|
6
6
|
import type { ModelPricingRegistry } from '../core/usage.js';
|
|
7
7
|
import type { Compactor } from '../core/compaction.js';
|
|
@@ -24,7 +24,8 @@ export interface ClaudeSessionServiceOptions {
|
|
|
24
24
|
tools?: ToolRegistry;
|
|
25
25
|
permissions?: PermissionResolver;
|
|
26
26
|
permissionResolverForMode?: (mode: AgentPermissionMode) => PermissionResolver;
|
|
27
|
-
|
|
27
|
+
persistPermissionUpdates?: (updates: readonly PermissionUpdate[]) => void | Promise<void>;
|
|
28
|
+
approveTool?: (call: ModelToolCall, originalCall?: ModelToolCall, decision?: PermissionDecision) => PermissionApproval | Promise<PermissionApproval>;
|
|
28
29
|
approveRecovery?: (call: ModelToolCall) => boolean | Promise<boolean>;
|
|
29
30
|
contextAssembler?: ContextAssembler;
|
|
30
31
|
conditionalRuleResolver?: Pick<ClaudeConditionalRuleResolver, 'resolve'>;
|
|
@@ -143,6 +144,7 @@ export declare class ClaudeSessionService {
|
|
|
143
144
|
private readonly backgroundTasks;
|
|
144
145
|
private readonly worktreeManager;
|
|
145
146
|
private readonly sessionCwds;
|
|
147
|
+
private readonly sessionPermissionUpdates;
|
|
146
148
|
private readonly hostedSubagents;
|
|
147
149
|
private readonly hostedSubagentsByRegistry;
|
|
148
150
|
private readonly backgroundNotificationWrites;
|
|
@@ -160,6 +162,7 @@ export declare class ClaudeSessionService {
|
|
|
160
162
|
private requireMcp;
|
|
161
163
|
taskSnapshots(sessionId: string): Promise<BackgroundTaskSnapshot>;
|
|
162
164
|
stopTask(sessionId: string, taskId: string): Promise<void>;
|
|
165
|
+
private applyPermissionUpdates;
|
|
163
166
|
close(): Promise<void>;
|
|
164
167
|
createHostedToolRegistry(sessionId: string): ToolRegistry;
|
|
165
168
|
run(prompt: string, signal?: AbortSignal, sessionId?: string, name?: string, images?: readonly ModelImage[], documents?: readonly ModelDocument[]): Promise<SessionRunResult>;
|
|
@@ -92,6 +92,7 @@ export class ClaudeSessionService {
|
|
|
92
92
|
backgroundTasks;
|
|
93
93
|
worktreeManager;
|
|
94
94
|
sessionCwds = new Map();
|
|
95
|
+
sessionPermissionUpdates = new Map();
|
|
95
96
|
hostedSubagents = new Set();
|
|
96
97
|
hostedSubagentsByRegistry = new WeakMap();
|
|
97
98
|
backgroundNotificationWrites = new Map();
|
|
@@ -159,6 +160,18 @@ export class ClaudeSessionService {
|
|
|
159
160
|
stopTask(sessionId, taskId) {
|
|
160
161
|
return this.backgroundTasks.stop(sessionId, taskId);
|
|
161
162
|
}
|
|
163
|
+
async applyPermissionUpdates(sessionId, updates) {
|
|
164
|
+
if (updates.length === 0)
|
|
165
|
+
return;
|
|
166
|
+
await this.options.persistPermissionUpdates?.(updates);
|
|
167
|
+
const current = this.sessionPermissionUpdates.get(sessionId) ?? [];
|
|
168
|
+
current.push(...updates);
|
|
169
|
+
this.sessionPermissionUpdates.set(sessionId, current);
|
|
170
|
+
const mode = updates.findLast((update) => update.type === 'setMode')?.mode;
|
|
171
|
+
if (mode && this.options.interactiveTools) {
|
|
172
|
+
await this.options.interactiveTools.setMode(sessionId, mode);
|
|
173
|
+
}
|
|
174
|
+
}
|
|
162
175
|
async close() {
|
|
163
176
|
this.scheduledPrompts?.close();
|
|
164
177
|
await Promise.all([...this.hostedSubagents].map((executor) => executor.close()));
|
|
@@ -247,6 +260,8 @@ export class ClaudeSessionService {
|
|
|
247
260
|
...(this.options.approveTool
|
|
248
261
|
? { approveTool: this.options.approveTool }
|
|
249
262
|
: {}),
|
|
263
|
+
permissionUpdates: () => this.sessionPermissionUpdates.get(sessionId) ?? [],
|
|
264
|
+
onPermissionUpdates: (updates) => this.applyPermissionUpdates(sessionId, updates),
|
|
250
265
|
...(this.options.eventSink
|
|
251
266
|
? { eventSink: this.options.eventSink }
|
|
252
267
|
: {}),
|
|
@@ -1455,6 +1470,8 @@ export class ClaudeSessionService {
|
|
|
1455
1470
|
...(this.options.approveTool
|
|
1456
1471
|
? { approveTool: this.options.approveTool }
|
|
1457
1472
|
: {}),
|
|
1473
|
+
permissionUpdates: () => this.sessionPermissionUpdates.get(sessionId) ?? [],
|
|
1474
|
+
onPermissionUpdates: (updates) => this.applyPermissionUpdates(sessionId, updates),
|
|
1458
1475
|
...(this.options.eventSink
|
|
1459
1476
|
? { eventSink: this.options.eventSink }
|
|
1460
1477
|
: {}),
|
|
@@ -1723,6 +1740,8 @@ export class ClaudeSessionService {
|
|
|
1723
1740
|
toolResultDirectory,
|
|
1724
1741
|
messages: projectClaudeModelMessages(snapshot.entries),
|
|
1725
1742
|
observer,
|
|
1743
|
+
permissionUpdates: this.sessionPermissionUpdates.get(sessionId) ?? [],
|
|
1744
|
+
onPermissionUpdates: (updates) => this.applyPermissionUpdates(sessionId, updates),
|
|
1726
1745
|
...(signal ? { signal } : {}),
|
|
1727
1746
|
...(approveRecovery
|
|
1728
1747
|
? {
|
|
@@ -2087,6 +2106,8 @@ export class ClaudeSessionService {
|
|
|
2087
2106
|
...(this.options.approveTool
|
|
2088
2107
|
? { approveTool: this.options.approveTool }
|
|
2089
2108
|
: {}),
|
|
2109
|
+
permissionUpdates: this.sessionPermissionUpdates.get(sessionId) ?? [],
|
|
2110
|
+
onPermissionUpdates: (updates) => this.applyPermissionUpdates(sessionId, updates),
|
|
2090
2111
|
...(signal ? { signal } : {}),
|
|
2091
2112
|
});
|
|
2092
2113
|
}
|
|
@@ -2215,6 +2236,8 @@ export class ClaudeSessionService {
|
|
|
2215
2236
|
...(this.options.approveTool
|
|
2216
2237
|
? { approveTool: this.options.approveTool }
|
|
2217
2238
|
: {}),
|
|
2239
|
+
permissionUpdates: this.sessionPermissionUpdates.get(sessionId) ?? [],
|
|
2240
|
+
onPermissionUpdates: (updates) => this.applyPermissionUpdates(sessionId, updates),
|
|
2218
2241
|
};
|
|
2219
2242
|
const result = signal
|
|
2220
2243
|
? await runtime.run({ ...runtimeRequest, signal })
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { type ClaudeSidechainPermissionMode } from '../compatibility/claude/sidechain.js';
|
|
2
2
|
import { type ContextAssembler } from '../core/context.js';
|
|
3
|
-
import { type ModelProvider, type ModelToolCall, type ModelToolDefinition, type ModelUsage, type PermissionResolver, type PermissionApproval, type RuntimeEventSink, type ToolExecutionContext, type ToolExecutionResult, type ToolRegistry } from '../core/runtime.js';
|
|
3
|
+
import { type ModelProvider, type ModelToolCall, type ModelToolDefinition, type ModelUsage, type PermissionResolver, type PermissionApproval, type PermissionDecision, type PermissionUpdate, type RuntimeEventSink, type ToolExecutionContext, type ToolExecutionResult, type ToolRegistry } from '../core/runtime.js';
|
|
4
4
|
import type { ClaudeExtensionCatalog } from '../extensions/claude-extensions.js';
|
|
5
5
|
import type { ClaudeHookRunner } from '../hooks/claude-hooks.js';
|
|
6
6
|
import { type BackgroundAgentSnapshot } from './background-agent-manager.js';
|
|
@@ -56,7 +56,9 @@ export interface ClaudeSubagentExecutorOptions {
|
|
|
56
56
|
hooks?: ClaudeHookRunner;
|
|
57
57
|
contextAssembler?: ContextAssembler;
|
|
58
58
|
contextReserveTokens?: number;
|
|
59
|
-
approveTool?: (call: ModelToolCall, originalCall?: ModelToolCall) => PermissionApproval | Promise<PermissionApproval>;
|
|
59
|
+
approveTool?: (call: ModelToolCall, originalCall?: ModelToolCall, decision?: PermissionDecision) => PermissionApproval | Promise<PermissionApproval>;
|
|
60
|
+
permissionUpdates?: () => readonly PermissionUpdate[];
|
|
61
|
+
onPermissionUpdates?: (updates: readonly PermissionUpdate[]) => void | Promise<void>;
|
|
60
62
|
eventSink?: RuntimeEventSink;
|
|
61
63
|
maxDepth?: number;
|
|
62
64
|
maxCalls?: number;
|
|
@@ -1139,6 +1139,10 @@ export class ClaudeSubagentExecutor {
|
|
|
1139
1139
|
...(this.options.approveTool
|
|
1140
1140
|
? { approveTool: this.options.approveTool }
|
|
1141
1141
|
: {}),
|
|
1142
|
+
permissionUpdates: this.options.permissionUpdates?.() ?? [],
|
|
1143
|
+
...(this.options.onPermissionUpdates
|
|
1144
|
+
? { onPermissionUpdates: this.options.onPermissionUpdates }
|
|
1145
|
+
: {}),
|
|
1142
1146
|
...(this.options.hooks || this.options.backgroundTaskNotifications
|
|
1143
1147
|
? {
|
|
1144
1148
|
onStop: async (text) => {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { ForkResult, ManualCompactResult, ManualCompactSelection, RewindPoint, SessionForkCheckpoint, SessionRunResult, SessionSummary, SideQuestionForkResult, SideQuestionResult } from '../application/session-service.js';
|
|
2
|
-
import type { ModelImage, ModelToolCall, RuntimeEventSink } from '../core/runtime.js';
|
|
2
|
+
import type { ModelImage, ModelToolCall, PermissionApproval, PermissionDecision, RuntimeEventSink } from '../core/runtime.js';
|
|
3
3
|
import type { CliElicitationRequest, CliElicitationResult, CliRuntimeInfo } from './protocol.js';
|
|
4
4
|
import type { ClaudeInteractiveToolCallbacks } from '../tools/claude-interactive-tools.js';
|
|
5
5
|
import { type ClaudePermissionMode } from '../permissions/claude-permission-resolver.js';
|
|
@@ -71,7 +71,7 @@ export interface InteractiveServiceFactory {
|
|
|
71
71
|
requireProvider: boolean;
|
|
72
72
|
hooksOnly?: boolean;
|
|
73
73
|
approveRecovery?: (call: ModelToolCall) => boolean | Promise<boolean>;
|
|
74
|
-
approveTool?: (call: ModelToolCall) =>
|
|
74
|
+
approveTool?: (call: ModelToolCall, originalCall?: ModelToolCall, decision?: PermissionDecision) => PermissionApproval | Promise<PermissionApproval>;
|
|
75
75
|
onElicitation?: (request: CliElicitationRequest) => Promise<CliElicitationResult>;
|
|
76
76
|
askUser?: ClaudeInteractiveToolCallbacks['askUser'];
|
|
77
77
|
approvePlan?: ClaudeInteractiveToolCallbacks['approvePlan'];
|
|
@@ -172,8 +172,9 @@ interface InteractiveAppProps {
|
|
|
172
172
|
runtimeSettings?: PraxisRuntimeSettings;
|
|
173
173
|
runtimeSettingsTarget?: ConfigSettingsTarget;
|
|
174
174
|
notificationWriter?: TuiNotificationWriter;
|
|
175
|
+
elicitationUrlOpener?: (url: string) => void | Promise<void>;
|
|
175
176
|
}
|
|
176
|
-
export declare function InteractiveApp({ factory, initialSessions, initialPrompt, initialHistory, signal, onCancel, onTurnChange, onCleanup, onRendererChange, onBackground, axScreenReader, allowNewSession, resume, display, terminalWidth, slashCommands, agents, allowDangerouslySkipPermissions, additionalDirectories, diffLoader, fileLoader, externalEditor, keybindingsConfigRoot, keybindingsFile, keybindingsLoader, keybindingsEditor, memoryFilesLoader, memoryEditor, memoryFolderOpener, suspendProcess, clipboardReader, clipboardWriter, sideQuestionClipboardWriter, exportWriter, permissionRuleStore, recentlyDeniedStore: suppliedRecentlyDeniedStore, terminalSetup: terminalSetupOverride, themeStore, initialThemeSettings, initialThemeLoadError, workspaceDirectoryResolver, workspaceDirectoryCompleter, runtimeSettings: suppliedRuntimeSettings, runtimeSettingsTarget, notificationWriter, }: InteractiveAppProps): import("react").JSX.Element;
|
|
177
|
+
export declare function InteractiveApp({ factory, initialSessions, initialPrompt, initialHistory, signal, onCancel, onTurnChange, onCleanup, onRendererChange, onBackground, axScreenReader, allowNewSession, resume, display, terminalWidth, slashCommands, agents, allowDangerouslySkipPermissions, additionalDirectories, diffLoader, fileLoader, externalEditor, keybindingsConfigRoot, keybindingsFile, keybindingsLoader, keybindingsEditor, memoryFilesLoader, memoryEditor, memoryFolderOpener, suspendProcess, clipboardReader, clipboardWriter, sideQuestionClipboardWriter, exportWriter, permissionRuleStore, recentlyDeniedStore: suppliedRecentlyDeniedStore, terminalSetup: terminalSetupOverride, themeStore, initialThemeSettings, initialThemeLoadError, workspaceDirectoryResolver, workspaceDirectoryCompleter, runtimeSettings: suppliedRuntimeSettings, runtimeSettingsTarget, notificationWriter, elicitationUrlOpener, }: InteractiveAppProps): import("react").JSX.Element;
|
|
177
178
|
export declare function runInteractive(options: {
|
|
178
179
|
factory: InteractiveServiceFactory;
|
|
179
180
|
initialPrompt?: string;
|