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,29 @@
|
|
|
1
|
+
export interface TeamWorkspace {
|
|
2
|
+
readonly cwd: string;
|
|
3
|
+
readonly branch: string | null;
|
|
4
|
+
}
|
|
5
|
+
export interface TeamWorkspaceInput {
|
|
6
|
+
readonly teamId: string;
|
|
7
|
+
readonly taskId: string;
|
|
8
|
+
readonly generation: number;
|
|
9
|
+
readonly access: 'read-only' | 'write';
|
|
10
|
+
}
|
|
11
|
+
export interface TeamWorkspaceProvider {
|
|
12
|
+
acquire(input: TeamWorkspaceInput): Promise<TeamWorkspace>;
|
|
13
|
+
}
|
|
14
|
+
export declare class NativeTeamWorkspaceProvider implements TeamWorkspaceProvider {
|
|
15
|
+
private readonly nativeRoot;
|
|
16
|
+
private readonly cwd;
|
|
17
|
+
private readonly projectIdentity;
|
|
18
|
+
private readonly gitRoot;
|
|
19
|
+
private readonly initialHead;
|
|
20
|
+
private constructor();
|
|
21
|
+
static open(options: {
|
|
22
|
+
nativeRoot: string;
|
|
23
|
+
cwd: string;
|
|
24
|
+
projectIdentity: string;
|
|
25
|
+
}): Promise<NativeTeamWorkspaceProvider>;
|
|
26
|
+
acquire(input: TeamWorkspaceInput): Promise<TeamWorkspace>;
|
|
27
|
+
private hasBranch;
|
|
28
|
+
}
|
|
29
|
+
//# sourceMappingURL=team-workspace.d.ts.map
|
|
@@ -0,0 +1,197 @@
|
|
|
1
|
+
import { execFile } from 'node:child_process';
|
|
2
|
+
import { lstat, mkdir, realpath } from 'node:fs/promises';
|
|
3
|
+
import { createHash } from 'node:crypto';
|
|
4
|
+
import { isAbsolute, relative, resolve } from 'node:path';
|
|
5
|
+
import { promisify } from 'node:util';
|
|
6
|
+
import { resolveProjectIdentity } from '../platform/project-identity.js';
|
|
7
|
+
import { sanitizeProjectPath } from '../platform/project-path-key.js';
|
|
8
|
+
import { parseTeamId } from '../core/team-ownership.js';
|
|
9
|
+
const execFileAsync = promisify(execFile);
|
|
10
|
+
async function git(cwd, args) {
|
|
11
|
+
return (await execFileAsync('git', ['-C', cwd, ...args], { encoding: 'utf8' })).stdout.trim();
|
|
12
|
+
}
|
|
13
|
+
async function canonical(path) {
|
|
14
|
+
try {
|
|
15
|
+
return await realpath(path);
|
|
16
|
+
}
|
|
17
|
+
catch (error) {
|
|
18
|
+
if (error.code === 'ENOENT')
|
|
19
|
+
return resolve(path);
|
|
20
|
+
throw error;
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
function assertInput(input) {
|
|
24
|
+
parseTeamId(input.teamId);
|
|
25
|
+
if (typeof input.taskId !== 'string' || input.taskId.trim() === '')
|
|
26
|
+
throw new Error('Invalid Team task ID');
|
|
27
|
+
if (!Number.isSafeInteger(input.generation) || input.generation <= 0)
|
|
28
|
+
throw new Error('Invalid Team generation');
|
|
29
|
+
if (input.access !== 'read-only' && input.access !== 'write')
|
|
30
|
+
throw new Error('Invalid Team workspace access');
|
|
31
|
+
}
|
|
32
|
+
async function registeredWorktrees(root) {
|
|
33
|
+
const output = await git(root, ['worktree', 'list', '--porcelain']);
|
|
34
|
+
const result = new Map();
|
|
35
|
+
let path;
|
|
36
|
+
for (const line of output.split('\n')) {
|
|
37
|
+
if (line.startsWith('worktree '))
|
|
38
|
+
path = resolve(line.slice('worktree '.length));
|
|
39
|
+
else if (line.startsWith('branch ') && path) {
|
|
40
|
+
result.set(await canonical(path), line.slice('branch '.length));
|
|
41
|
+
path = undefined;
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
if (path)
|
|
45
|
+
result.set(await canonical(path), '');
|
|
46
|
+
return result;
|
|
47
|
+
}
|
|
48
|
+
export class NativeTeamWorkspaceProvider {
|
|
49
|
+
nativeRoot;
|
|
50
|
+
cwd;
|
|
51
|
+
projectIdentity;
|
|
52
|
+
gitRoot;
|
|
53
|
+
initialHead;
|
|
54
|
+
constructor(nativeRoot, cwd, projectIdentity, gitRoot, initialHead) {
|
|
55
|
+
this.nativeRoot = nativeRoot;
|
|
56
|
+
this.cwd = cwd;
|
|
57
|
+
this.projectIdentity = projectIdentity;
|
|
58
|
+
this.gitRoot = gitRoot;
|
|
59
|
+
this.initialHead = initialHead;
|
|
60
|
+
}
|
|
61
|
+
static async open(options) {
|
|
62
|
+
if (typeof options.nativeRoot !== 'string' ||
|
|
63
|
+
options.nativeRoot.trim() === '')
|
|
64
|
+
throw new Error('Invalid native Team root');
|
|
65
|
+
const canonicalCwd = await canonical(options.cwd);
|
|
66
|
+
const identity = await resolveProjectIdentity(canonicalCwd);
|
|
67
|
+
if (identity !== options.projectIdentity)
|
|
68
|
+
throw new Error('Team workspace project identity mismatch');
|
|
69
|
+
let gitRoot = null;
|
|
70
|
+
let initialHead = null;
|
|
71
|
+
try {
|
|
72
|
+
gitRoot = await canonical(await git(canonicalCwd, ['rev-parse', '--show-toplevel']));
|
|
73
|
+
initialHead = await git(gitRoot, ['rev-parse', 'HEAD']);
|
|
74
|
+
}
|
|
75
|
+
catch {
|
|
76
|
+
// A read-only member can safely use a non-Git project root.
|
|
77
|
+
}
|
|
78
|
+
return new NativeTeamWorkspaceProvider(await canonical(options.nativeRoot), canonicalCwd, options.projectIdentity, gitRoot, initialHead);
|
|
79
|
+
}
|
|
80
|
+
async acquire(input) {
|
|
81
|
+
assertInput(input);
|
|
82
|
+
if (input.access === 'read-only') {
|
|
83
|
+
return { cwd: this.cwd, branch: null };
|
|
84
|
+
}
|
|
85
|
+
if (this.gitRoot === null || this.initialHead === null)
|
|
86
|
+
throw new Error('Team write workspace requires a Git repository');
|
|
87
|
+
const hash = createHash('sha256')
|
|
88
|
+
.update(`${this.projectIdentity}\0${input.teamId}\0${input.taskId}\0${input.generation}`)
|
|
89
|
+
.digest('hex')
|
|
90
|
+
.slice(0, 24);
|
|
91
|
+
const branch = `praxis/team/${input.teamId}/${hash}`;
|
|
92
|
+
const path = resolve(this.nativeRoot, 'state', 'team-worktrees', sanitizeProjectPath(this.projectIdentity), input.teamId, hash);
|
|
93
|
+
if (!isAbsolute(path) ||
|
|
94
|
+
!isAbsolute(this.nativeRoot) ||
|
|
95
|
+
!isPathWithin(this.nativeRoot, path))
|
|
96
|
+
throw new Error('Invalid Team workspace path');
|
|
97
|
+
await assertSafeParents(this.nativeRoot, path);
|
|
98
|
+
let pathExists = false;
|
|
99
|
+
try {
|
|
100
|
+
const entry = await lstat(path);
|
|
101
|
+
if (entry.isSymbolicLink())
|
|
102
|
+
throw new Error('Team worktree path must not be a symlink');
|
|
103
|
+
if (!entry.isDirectory())
|
|
104
|
+
throw new Error(`Team worktree path is not a directory: ${path}`);
|
|
105
|
+
pathExists = true;
|
|
106
|
+
}
|
|
107
|
+
catch (error) {
|
|
108
|
+
if (error.code !== 'ENOENT')
|
|
109
|
+
throw error;
|
|
110
|
+
}
|
|
111
|
+
const currentHead = await git(this.gitRoot, ['rev-parse', 'HEAD']);
|
|
112
|
+
const registered = await registeredWorktrees(this.gitRoot);
|
|
113
|
+
const registeredBranch = registered.get(path);
|
|
114
|
+
const branchExists = await this.hasBranch(branch);
|
|
115
|
+
if (!pathExists && !branchExists) {
|
|
116
|
+
await mkdir(resolve(path, '..'), { recursive: true });
|
|
117
|
+
try {
|
|
118
|
+
await git(this.gitRoot, [
|
|
119
|
+
'worktree',
|
|
120
|
+
'add',
|
|
121
|
+
'-b',
|
|
122
|
+
branch,
|
|
123
|
+
path,
|
|
124
|
+
currentHead,
|
|
125
|
+
]);
|
|
126
|
+
}
|
|
127
|
+
catch (error) {
|
|
128
|
+
throw new Error(`Could not create Team worktree: ${error.message}`);
|
|
129
|
+
}
|
|
130
|
+
return { cwd: path, branch };
|
|
131
|
+
}
|
|
132
|
+
if (!pathExists || !branchExists)
|
|
133
|
+
throw new Error(`Team workspace collision at ${path}`);
|
|
134
|
+
if (registeredBranch !== `refs/heads/${branch}`)
|
|
135
|
+
throw new Error(`Team worktree registration mismatch at ${path}`);
|
|
136
|
+
if ((await canonical(path)) !== path)
|
|
137
|
+
throw new Error(`Team worktree path must be canonical: ${path}`);
|
|
138
|
+
const worktreeRoot = await canonical(await git(path, ['rev-parse', '--show-toplevel']));
|
|
139
|
+
if (worktreeRoot !== path ||
|
|
140
|
+
(await resolveProjectIdentity(path)) !== this.projectIdentity)
|
|
141
|
+
throw new Error(`Team worktree repository mismatch at ${path}`);
|
|
142
|
+
const currentBranch = await git(path, [
|
|
143
|
+
'symbolic-ref',
|
|
144
|
+
'--quiet',
|
|
145
|
+
'--short',
|
|
146
|
+
'HEAD',
|
|
147
|
+
]);
|
|
148
|
+
if (currentBranch !== branch)
|
|
149
|
+
throw new Error(`Team worktree branch mismatch at ${path}`);
|
|
150
|
+
return { cwd: path, branch };
|
|
151
|
+
}
|
|
152
|
+
async hasBranch(branch) {
|
|
153
|
+
try {
|
|
154
|
+
await git(this.gitRoot, [
|
|
155
|
+
'show-ref',
|
|
156
|
+
'--verify',
|
|
157
|
+
'--quiet',
|
|
158
|
+
`refs/heads/${branch}`,
|
|
159
|
+
]);
|
|
160
|
+
return true;
|
|
161
|
+
}
|
|
162
|
+
catch (error) {
|
|
163
|
+
const code = error.code;
|
|
164
|
+
if (code === 1)
|
|
165
|
+
return false;
|
|
166
|
+
throw error;
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
function isPathWithin(root, candidate) {
|
|
171
|
+
const path = relative(resolve(root), resolve(candidate));
|
|
172
|
+
return path === '' || (!path.startsWith('..') && !isAbsolute(path));
|
|
173
|
+
}
|
|
174
|
+
async function assertSafeParents(root, path) {
|
|
175
|
+
let current = resolve(path, '..');
|
|
176
|
+
const nativeRoot = resolve(root);
|
|
177
|
+
for (;;) {
|
|
178
|
+
try {
|
|
179
|
+
const entry = await lstat(current);
|
|
180
|
+
if (entry.isSymbolicLink())
|
|
181
|
+
throw new Error(`Team worktree parent must not be a symlink: ${current}`);
|
|
182
|
+
if (!entry.isDirectory())
|
|
183
|
+
throw new Error(`Team worktree parent is not a directory: ${current}`);
|
|
184
|
+
}
|
|
185
|
+
catch (error) {
|
|
186
|
+
if (error.code !== 'ENOENT')
|
|
187
|
+
throw error;
|
|
188
|
+
}
|
|
189
|
+
if (current === nativeRoot || !isPathWithin(nativeRoot, current))
|
|
190
|
+
return;
|
|
191
|
+
const parent = resolve(current, '..');
|
|
192
|
+
if (parent === current)
|
|
193
|
+
return;
|
|
194
|
+
current = parent;
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
//# sourceMappingURL=team-workspace.js.map
|
|
@@ -59,6 +59,7 @@ export declare class TopLevelAgentManager {
|
|
|
59
59
|
cwd?: string;
|
|
60
60
|
all: boolean;
|
|
61
61
|
}): Promise<TopLevelAgentSummary[]>;
|
|
62
|
+
private readLifecycleView;
|
|
62
63
|
private nativeSessions;
|
|
63
64
|
logs(id: string): Promise<string>;
|
|
64
65
|
review(agent: Pick<TopLevelAgentSummary, 'id' | 'cwd' | 'sessionId'>): Promise<string>;
|