@proletariat/cli 0.3.43 → 0.3.45
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/commands/agent/list.js +2 -3
- package/dist/commands/agent/login.js +2 -2
- package/dist/commands/agent/rebuild.js +2 -3
- package/dist/commands/agent/shell.js +2 -2
- package/dist/commands/agent/status.js +3 -3
- package/dist/commands/agent/visit.js +2 -2
- package/dist/commands/orchestrator/attach.d.ts +13 -0
- package/dist/commands/orchestrator/attach.js +140 -0
- package/dist/commands/orchestrator/index.d.ts +14 -0
- package/dist/commands/orchestrator/index.js +51 -0
- package/dist/commands/orchestrator/start.d.ts +17 -0
- package/dist/commands/orchestrator/start.js +287 -0
- package/dist/commands/orchestrator/status.d.ts +12 -0
- package/dist/commands/orchestrator/status.js +63 -0
- package/dist/commands/orchestrator/stop.d.ts +11 -0
- package/dist/commands/orchestrator/stop.js +104 -0
- package/dist/commands/staff/list.js +2 -3
- package/dist/commands/work/revise.js +3 -3
- package/dist/commands/work/start.js +4 -4
- package/dist/commands/work/watch.js +2 -2
- package/dist/lib/agents/commands.d.ts +11 -0
- package/dist/lib/agents/commands.js +40 -10
- package/dist/lib/execution/runners.js +4 -0
- package/dist/lib/execution/spawner.js +3 -2
- package/dist/lib/themes.js +32 -16
- package/oclif.manifest.json +3268 -2971
- package/package.json +1 -1
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import { Flags } from '@oclif/core';
|
|
2
|
+
import { PromptCommand } from '../../lib/prompt-command.js';
|
|
3
|
+
import { machineOutputFlags } from '../../lib/pmo/index.js';
|
|
4
|
+
import { shouldOutputJson, outputSuccessAsJson, createMetadata, } from '../../lib/prompt-json.js';
|
|
5
|
+
import { styles } from '../../lib/styles.js';
|
|
6
|
+
import { getHostTmuxSessionNames, captureTmuxPane } from '../../lib/execution/session-utils.js';
|
|
7
|
+
import { ORCHESTRATOR_SESSION_NAME } from './start.js';
|
|
8
|
+
export default class OrchestratorStatus extends PromptCommand {
|
|
9
|
+
static description = 'Check if the orchestrator is running';
|
|
10
|
+
static examples = [
|
|
11
|
+
'<%= config.bin %> <%= command.id %>',
|
|
12
|
+
'<%= config.bin %> <%= command.id %> --peek',
|
|
13
|
+
'<%= config.bin %> <%= command.id %> --peek --lines 50',
|
|
14
|
+
];
|
|
15
|
+
static flags = {
|
|
16
|
+
...machineOutputFlags,
|
|
17
|
+
peek: Flags.boolean({
|
|
18
|
+
description: 'Show recent output from the orchestrator',
|
|
19
|
+
default: false,
|
|
20
|
+
}),
|
|
21
|
+
lines: Flags.integer({
|
|
22
|
+
description: 'Number of lines to show when peeking',
|
|
23
|
+
default: 20,
|
|
24
|
+
}),
|
|
25
|
+
};
|
|
26
|
+
async run() {
|
|
27
|
+
const { flags } = await this.parse(OrchestratorStatus);
|
|
28
|
+
const jsonMode = shouldOutputJson(flags);
|
|
29
|
+
const hostSessions = getHostTmuxSessionNames();
|
|
30
|
+
const isRunning = hostSessions.includes(ORCHESTRATOR_SESSION_NAME);
|
|
31
|
+
let recentOutput = null;
|
|
32
|
+
if (isRunning && flags.peek) {
|
|
33
|
+
recentOutput = captureTmuxPane(ORCHESTRATOR_SESSION_NAME, flags.lines);
|
|
34
|
+
}
|
|
35
|
+
if (jsonMode) {
|
|
36
|
+
outputSuccessAsJson({
|
|
37
|
+
running: isRunning,
|
|
38
|
+
sessionId: isRunning ? ORCHESTRATOR_SESSION_NAME : null,
|
|
39
|
+
...(recentOutput !== null && { recentOutput }),
|
|
40
|
+
}, createMetadata('orchestrator status', flags));
|
|
41
|
+
return;
|
|
42
|
+
}
|
|
43
|
+
this.log('');
|
|
44
|
+
if (isRunning) {
|
|
45
|
+
this.log(styles.success(`Orchestrator is running`));
|
|
46
|
+
this.log(styles.muted(` Session: ${ORCHESTRATOR_SESSION_NAME}`));
|
|
47
|
+
this.log(styles.muted(` Attach: prlt orchestrator attach`));
|
|
48
|
+
this.log(styles.muted(` Poke: prlt session poke orchestrator "message"`));
|
|
49
|
+
if (recentOutput) {
|
|
50
|
+
this.log('');
|
|
51
|
+
this.log(styles.header('Recent output:'));
|
|
52
|
+
this.log(styles.muted('─'.repeat(60)));
|
|
53
|
+
this.log(recentOutput);
|
|
54
|
+
this.log(styles.muted('─'.repeat(60)));
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
else {
|
|
58
|
+
this.log(styles.muted('Orchestrator is not running.'));
|
|
59
|
+
this.log(styles.muted('Start it with: prlt orchestrator start'));
|
|
60
|
+
}
|
|
61
|
+
this.log('');
|
|
62
|
+
}
|
|
63
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { PromptCommand } from '../../lib/prompt-command.js';
|
|
2
|
+
export default class OrchestratorStop extends PromptCommand {
|
|
3
|
+
static description: string;
|
|
4
|
+
static examples: string[];
|
|
5
|
+
static flags: {
|
|
6
|
+
force: import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
7
|
+
json: import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
8
|
+
machine: import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
9
|
+
};
|
|
10
|
+
run(): Promise<void>;
|
|
11
|
+
}
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
import { Flags } from '@oclif/core';
|
|
2
|
+
import { execSync } from 'node:child_process';
|
|
3
|
+
import * as path from 'node:path';
|
|
4
|
+
import * as fs from 'node:fs';
|
|
5
|
+
import Database from 'better-sqlite3';
|
|
6
|
+
import { PromptCommand } from '../../lib/prompt-command.js';
|
|
7
|
+
import { machineOutputFlags } from '../../lib/pmo/index.js';
|
|
8
|
+
import { findHQRoot } from '../../lib/workspace.js';
|
|
9
|
+
import { shouldOutputJson, outputErrorAsJson, outputSuccessAsJson, createMetadata, } from '../../lib/prompt-json.js';
|
|
10
|
+
import { styles } from '../../lib/styles.js';
|
|
11
|
+
import { getHostTmuxSessionNames } from '../../lib/execution/session-utils.js';
|
|
12
|
+
import { ExecutionStorage } from '../../lib/execution/storage.js';
|
|
13
|
+
import { ORCHESTRATOR_SESSION_NAME } from './start.js';
|
|
14
|
+
export default class OrchestratorStop extends PromptCommand {
|
|
15
|
+
static description = 'Stop the running orchestrator';
|
|
16
|
+
static examples = [
|
|
17
|
+
'<%= config.bin %> <%= command.id %>',
|
|
18
|
+
'<%= config.bin %> <%= command.id %> --force',
|
|
19
|
+
];
|
|
20
|
+
static flags = {
|
|
21
|
+
...machineOutputFlags,
|
|
22
|
+
force: Flags.boolean({
|
|
23
|
+
char: 'f',
|
|
24
|
+
description: 'Skip confirmation',
|
|
25
|
+
default: false,
|
|
26
|
+
}),
|
|
27
|
+
};
|
|
28
|
+
async run() {
|
|
29
|
+
const { flags } = await this.parse(OrchestratorStop);
|
|
30
|
+
const jsonMode = shouldOutputJson(flags);
|
|
31
|
+
// Check if orchestrator session exists
|
|
32
|
+
const hostSessions = getHostTmuxSessionNames();
|
|
33
|
+
if (!hostSessions.includes(ORCHESTRATOR_SESSION_NAME)) {
|
|
34
|
+
if (jsonMode) {
|
|
35
|
+
outputErrorAsJson('NOT_RUNNING', 'Orchestrator is not running.', createMetadata('orchestrator stop', flags));
|
|
36
|
+
return;
|
|
37
|
+
}
|
|
38
|
+
this.log('');
|
|
39
|
+
this.log(styles.muted('Orchestrator is not running.'));
|
|
40
|
+
this.log('');
|
|
41
|
+
return;
|
|
42
|
+
}
|
|
43
|
+
// Confirm unless --force
|
|
44
|
+
if (!flags.force && !jsonMode) {
|
|
45
|
+
const { confirmed } = await this.prompt([{
|
|
46
|
+
type: 'list',
|
|
47
|
+
name: 'confirmed',
|
|
48
|
+
message: 'Stop the orchestrator?',
|
|
49
|
+
choices: [
|
|
50
|
+
{ name: 'Yes', value: true },
|
|
51
|
+
{ name: 'No', value: false },
|
|
52
|
+
],
|
|
53
|
+
}]);
|
|
54
|
+
if (!confirmed) {
|
|
55
|
+
this.log(styles.muted('Cancelled.'));
|
|
56
|
+
return;
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
// Kill the tmux session
|
|
60
|
+
try {
|
|
61
|
+
execSync(`tmux kill-session -t "${ORCHESTRATOR_SESSION_NAME}"`, { stdio: 'pipe' });
|
|
62
|
+
}
|
|
63
|
+
catch (error) {
|
|
64
|
+
if (jsonMode) {
|
|
65
|
+
outputErrorAsJson('KILL_FAILED', `Failed to stop orchestrator: ${error instanceof Error ? error.message : error}`, createMetadata('orchestrator stop', flags));
|
|
66
|
+
return;
|
|
67
|
+
}
|
|
68
|
+
this.error(`Failed to stop orchestrator: ${error instanceof Error ? error.message : error}`);
|
|
69
|
+
}
|
|
70
|
+
// Update execution record to stopped
|
|
71
|
+
const hqPath = findHQRoot(process.cwd());
|
|
72
|
+
if (hqPath) {
|
|
73
|
+
const dbPath = path.join(hqPath, '.proletariat', 'workspace.db');
|
|
74
|
+
if (fs.existsSync(dbPath)) {
|
|
75
|
+
let db = null;
|
|
76
|
+
try {
|
|
77
|
+
db = new Database(dbPath);
|
|
78
|
+
const executionStorage = new ExecutionStorage(db);
|
|
79
|
+
const running = executionStorage.listExecutions({ agentName: 'orchestrator', status: 'running' });
|
|
80
|
+
const starting = executionStorage.listExecutions({ agentName: 'orchestrator', status: 'starting' });
|
|
81
|
+
for (const exec of [...running, ...starting]) {
|
|
82
|
+
executionStorage.updateStatus(exec.id, 'stopped');
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
catch {
|
|
86
|
+
// Non-fatal
|
|
87
|
+
}
|
|
88
|
+
finally {
|
|
89
|
+
db?.close();
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
if (jsonMode) {
|
|
94
|
+
outputSuccessAsJson({
|
|
95
|
+
sessionId: ORCHESTRATOR_SESSION_NAME,
|
|
96
|
+
status: 'stopped',
|
|
97
|
+
}, createMetadata('orchestrator stop', flags));
|
|
98
|
+
return;
|
|
99
|
+
}
|
|
100
|
+
this.log('');
|
|
101
|
+
this.log(styles.success('Orchestrator stopped.'));
|
|
102
|
+
this.log('');
|
|
103
|
+
}
|
|
104
|
+
}
|
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
import { Command } from '@oclif/core';
|
|
2
2
|
import chalk from 'chalk';
|
|
3
|
-
import * as path from 'node:path';
|
|
4
3
|
import * as fs from 'node:fs';
|
|
5
|
-
import { getWorkspaceInfo, getAllAgentsStatus } from '../../lib/agents/commands.js';
|
|
4
|
+
import { getWorkspaceInfo, getAllAgentsStatus, resolveAgentDir } from '../../lib/agents/commands.js';
|
|
6
5
|
import { shouldOutputJson } from '../../lib/prompt-json.js';
|
|
7
6
|
import { machineOutputFlags } from '../../lib/pmo/index.js';
|
|
8
7
|
export default class List extends Command {
|
|
@@ -73,7 +72,7 @@ export default class List extends Command {
|
|
|
73
72
|
}
|
|
74
73
|
}
|
|
75
74
|
else {
|
|
76
|
-
const agentDir =
|
|
75
|
+
const agentDir = resolveAgentDir(workspaceInfo, agentStatus.name);
|
|
77
76
|
const dirExists = fs.existsSync(agentDir);
|
|
78
77
|
if (dirExists) {
|
|
79
78
|
this.log(chalk.red(` Invalid or broken worktrees`));
|
|
@@ -6,7 +6,7 @@ import Database from 'better-sqlite3';
|
|
|
6
6
|
import { PMOCommand, pmoBaseFlags, autoExportToBoard } from '../../lib/pmo/index.js';
|
|
7
7
|
import { getWorkColumnSetting, findColumnByName } from '../../lib/pmo/utils.js';
|
|
8
8
|
import { styles } from '../../lib/styles.js';
|
|
9
|
-
import { getWorkspaceInfo } from '../../lib/agents/commands.js';
|
|
9
|
+
import { getWorkspaceInfo, resolveAgentDir } from '../../lib/agents/commands.js';
|
|
10
10
|
import { DEFAULT_EXECUTION_CONFIG, } from '../../lib/execution/types.js';
|
|
11
11
|
import { runExecution, isDockerRunning, isDevcontainerCliInstalled } from '../../lib/execution/runners.js';
|
|
12
12
|
import { ExecutionStorage } from '../../lib/execution/storage.js';
|
|
@@ -179,8 +179,8 @@ export default class WorkRevise extends PMOCommand {
|
|
|
179
179
|
this.error(`Ticket "${ticketId}" already has work in progress: ${runningExecution.id}\n` +
|
|
180
180
|
`Stop it first with "prlt work stop ${runningExecution.id}"`);
|
|
181
181
|
}
|
|
182
|
-
// Find worktree path
|
|
183
|
-
const agentDir =
|
|
182
|
+
// Find worktree path (handles staff and temp agents)
|
|
183
|
+
const agentDir = resolveAgentDir(workspaceInfo, agentName);
|
|
184
184
|
if (!fs.existsSync(agentDir)) {
|
|
185
185
|
db.close();
|
|
186
186
|
this.error(`Agent directory not found at ${agentDir}.`);
|
|
@@ -9,7 +9,7 @@ import { shouldOutputJson, outputErrorAsJson, createMetadata, outputConfirmation
|
|
|
9
9
|
import { FlagResolver } from '../../lib/flags/index.js';
|
|
10
10
|
import { getWorkColumnSetting, findColumnByName } from '../../lib/pmo/utils.js';
|
|
11
11
|
import { styles } from '../../lib/styles.js';
|
|
12
|
-
import { getWorkspaceInfo, createEphemeralAgent, getTicketTmuxSession, killTmuxSession, findWorktreeForBranch, } from '../../lib/agents/commands.js';
|
|
12
|
+
import { getWorkspaceInfo, createEphemeralAgent, getTicketTmuxSession, killTmuxSession, findWorktreeForBranch, resolveAgentDir, } from '../../lib/agents/commands.js';
|
|
13
13
|
import { generateBranchName, DEFAULT_EXECUTION_CONFIG, } from '../../lib/execution/types.js';
|
|
14
14
|
import { runExecution, isDockerRunning, isGitHubTokenAvailable, isDevcontainerCliInstalled, dockerCredentialsExist, getDockerCredentialInfo } from '../../lib/execution/runners.js';
|
|
15
15
|
import { ExecutionStorage, ContainerStorage } from '../../lib/execution/storage.js';
|
|
@@ -1712,7 +1712,7 @@ export default class WorkStart extends PMOCommand {
|
|
|
1712
1712
|
}
|
|
1713
1713
|
// Check Docker credentials if any agents use devcontainers
|
|
1714
1714
|
const anyUseDevcontainer = availableAgents.some(agent => {
|
|
1715
|
-
const agentDir =
|
|
1715
|
+
const agentDir = resolveAgentDir(workspaceInfo, agent.name);
|
|
1716
1716
|
return hasDevcontainerConfig(agentDir) && !flags['run-on-host'];
|
|
1717
1717
|
});
|
|
1718
1718
|
// Track whether user explicitly chose to use API key instead of OAuth
|
|
@@ -1858,8 +1858,8 @@ export default class WorkStart extends PMOCommand {
|
|
|
1858
1858
|
async spawnSingleTicket(ticket, agent, workspaceInfo, executionStorage, db, flags) {
|
|
1859
1859
|
const agentName = agent.name;
|
|
1860
1860
|
// Note: Ticket assignee update moved to after successful spawn
|
|
1861
|
-
// Find agent directory and worktree
|
|
1862
|
-
const agentDir =
|
|
1861
|
+
// Find agent directory and worktree (handles staff and temp agents)
|
|
1862
|
+
const agentDir = resolveAgentDir(workspaceInfo, agentName);
|
|
1863
1863
|
if (!fs.existsSync(agentDir)) {
|
|
1864
1864
|
throw new Error(`Agent directory not found: ${agentDir}`);
|
|
1865
1865
|
}
|
|
@@ -3,7 +3,7 @@ import * as path from 'node:path';
|
|
|
3
3
|
import Database from 'better-sqlite3';
|
|
4
4
|
import { PMOCommand, pmoBaseFlags } from '../../lib/pmo/index.js';
|
|
5
5
|
import { styles } from '../../lib/styles.js';
|
|
6
|
-
import { getWorkspaceInfo } from '../../lib/agents/commands.js';
|
|
6
|
+
import { getWorkspaceInfo, resolveAgentDir } from '../../lib/agents/commands.js';
|
|
7
7
|
import { ExecutionStorage } from '../../lib/execution/storage.js';
|
|
8
8
|
import { hasDevcontainerConfig } from '../../lib/execution/devcontainer.js';
|
|
9
9
|
import { spawnForColumn, getAvailableAgents, isDockerRunning, isDevcontainerCliInstalled, } from '../../lib/execution/spawner.js';
|
|
@@ -152,7 +152,7 @@ export default class WorkWatch extends PMOCommand {
|
|
|
152
152
|
}
|
|
153
153
|
// Check if any agent has devcontainer
|
|
154
154
|
const hasDevcontainer = workspaceInfo.agents.some(agent => {
|
|
155
|
-
const agentDir =
|
|
155
|
+
const agentDir = resolveAgentDir(workspaceInfo, agent.name);
|
|
156
156
|
return hasDevcontainerConfig(agentDir);
|
|
157
157
|
});
|
|
158
158
|
// Prompt for environment and display mode if not provided
|
|
@@ -1,4 +1,15 @@
|
|
|
1
1
|
import { Agent, Repository, MountMode as DBMountMode } from '../database/index.js';
|
|
2
|
+
/**
|
|
3
|
+
* Resolve the directory for an agent, cascading through resolution strategies.
|
|
4
|
+
* Handles both staff (persistent) and temp (ephemeral) agents.
|
|
5
|
+
*
|
|
6
|
+
* Resolution order:
|
|
7
|
+
* 1. Check agent's worktree_path from DB (most reliable)
|
|
8
|
+
* 2. Check ephemeral directory if agent type is ephemeral
|
|
9
|
+
* 3. Check both directories on disk as fallback
|
|
10
|
+
* 4. Fall back to staff path (caller handles missing dir error)
|
|
11
|
+
*/
|
|
12
|
+
export declare function resolveAgentDir(workspaceInfo: WorkspaceInfo, agentName: string): string;
|
|
2
13
|
/**
|
|
3
14
|
* Format a list of agents for display in error messages.
|
|
4
15
|
* Truncates long lists to avoid overwhelming output.
|
|
@@ -10,6 +10,43 @@ import { isValidAgentName, getSuggestedAgentNames, generateEphemeralAgentName, g
|
|
|
10
10
|
import { createDevcontainerConfig } from '../execution/devcontainer.js';
|
|
11
11
|
import { getGitIdentity } from '../pr/index.js';
|
|
12
12
|
import { getPMOContext } from '../pmo/index.js';
|
|
13
|
+
/**
|
|
14
|
+
* Resolve the directory for an agent, cascading through resolution strategies.
|
|
15
|
+
* Handles both staff (persistent) and temp (ephemeral) agents.
|
|
16
|
+
*
|
|
17
|
+
* Resolution order:
|
|
18
|
+
* 1. Check agent's worktree_path from DB (most reliable)
|
|
19
|
+
* 2. Check ephemeral directory if agent type is ephemeral
|
|
20
|
+
* 3. Check both directories on disk as fallback
|
|
21
|
+
* 4. Fall back to staff path (caller handles missing dir error)
|
|
22
|
+
*/
|
|
23
|
+
export function resolveAgentDir(workspaceInfo, agentName) {
|
|
24
|
+
const agent = workspaceInfo.agents.find(a => a.name === agentName);
|
|
25
|
+
// 1. Check DB worktree_path (most reliable - set during agent creation)
|
|
26
|
+
if (agent?.worktree_path) {
|
|
27
|
+
const fullWorktreePath = path.join(workspaceInfo.path, agent.worktree_path);
|
|
28
|
+
// worktree_path may point to repo subdir (e.g. agents/staff/altman/proletariat)
|
|
29
|
+
// Go up to the agent dir level
|
|
30
|
+
const agentDir = path.dirname(fullWorktreePath);
|
|
31
|
+
if (fs.existsSync(agentDir))
|
|
32
|
+
return agentDir;
|
|
33
|
+
}
|
|
34
|
+
// 2. Check ephemeral directory if agent type is ephemeral
|
|
35
|
+
if (agent?.type === 'ephemeral') {
|
|
36
|
+
const ephemeralDir = path.join(workspaceInfo.path, 'agents', workspaceInfo.ephemeralAgentsDir, agentName);
|
|
37
|
+
if (fs.existsSync(ephemeralDir))
|
|
38
|
+
return ephemeralDir;
|
|
39
|
+
}
|
|
40
|
+
// 3. Check both directories on disk (handles DB inconsistencies)
|
|
41
|
+
const tempDir = path.join(workspaceInfo.path, 'agents', workspaceInfo.ephemeralAgentsDir, agentName);
|
|
42
|
+
if (fs.existsSync(tempDir))
|
|
43
|
+
return tempDir;
|
|
44
|
+
const staffDir = path.join(workspaceInfo.agentsPath, agentName);
|
|
45
|
+
if (fs.existsSync(staffDir))
|
|
46
|
+
return staffDir;
|
|
47
|
+
// 4. Fall back to staff path - caller will handle the missing dir error
|
|
48
|
+
return staffDir;
|
|
49
|
+
}
|
|
13
50
|
/**
|
|
14
51
|
* Format a list of agents for display in error messages.
|
|
15
52
|
* Truncates long lists to avoid overwhelming output.
|
|
@@ -169,15 +206,8 @@ export function getAgentStatus(workspaceInfo, agentName) {
|
|
|
169
206
|
const exists = !!agentRecord;
|
|
170
207
|
// Get worktrees from database to find actual agent location
|
|
171
208
|
const worktrees = getAgentWorktrees(workspaceInfo.path, agentName);
|
|
172
|
-
//
|
|
173
|
-
|
|
174
|
-
if (worktrees.length > 0) {
|
|
175
|
-
// worktree_path is like "agents/staff/altman/proletariat-altman"
|
|
176
|
-
// Agent dir is the parent: "agents/staff/altman"
|
|
177
|
-
const worktreePath = worktrees[0].worktree_path;
|
|
178
|
-
const agentDirRelative = path.dirname(worktreePath);
|
|
179
|
-
agentDir = path.join(workspaceInfo.path, agentDirRelative);
|
|
180
|
-
}
|
|
209
|
+
// Resolve agent directory (handles both staff and temp agents)
|
|
210
|
+
const agentDir = resolveAgentDir(workspaceInfo, agentName);
|
|
181
211
|
const dirExists = fs.existsSync(agentDir);
|
|
182
212
|
const status = {
|
|
183
213
|
name: agentName,
|
|
@@ -314,7 +344,7 @@ export async function removeAgentsFromWorkspace(workspaceInfo, agentNames) {
|
|
|
314
344
|
const failed = [];
|
|
315
345
|
for (const agentName of agentNames) {
|
|
316
346
|
try {
|
|
317
|
-
const agentDir =
|
|
347
|
+
const agentDir = resolveAgentDir(workspaceInfo, agentName);
|
|
318
348
|
// Stop and remove Docker container if it exists
|
|
319
349
|
try {
|
|
320
350
|
const containerId = execSync(`docker ps -aq --filter "label=devcontainer.local_folder=${agentDir}"`, { encoding: 'utf-8', stdio: ['pipe', 'pipe', 'pipe'] }).trim();
|
|
@@ -100,6 +100,7 @@ export function buildTmuxScript(sessionName, claudeCmd, displayMode) {
|
|
|
100
100
|
export TERM=xterm-256color
|
|
101
101
|
export COLORTERM=truecolor
|
|
102
102
|
unset CI
|
|
103
|
+
unset CLAUDECODE
|
|
103
104
|
echo "🚀 Starting: ${sessionName}"
|
|
104
105
|
echo ""
|
|
105
106
|
${claudeCmd}
|
|
@@ -112,6 +113,7 @@ kill 1
|
|
|
112
113
|
export TERM=xterm-256color
|
|
113
114
|
export COLORTERM=truecolor
|
|
114
115
|
unset CI
|
|
116
|
+
unset CLAUDECODE
|
|
115
117
|
echo "🚀 Starting: ${sessionName}"
|
|
116
118
|
echo ""
|
|
117
119
|
${claudeCmd}
|
|
@@ -470,6 +472,8 @@ export async function runHost(context, executor, config, displayMode = 'terminal
|
|
|
470
472
|
const setTitleCmds = getSetTitleCommands(windowTitle);
|
|
471
473
|
const scriptContent = `#!/bin/bash
|
|
472
474
|
# Auto-generated script for ticket ${context.ticketId}
|
|
475
|
+
unset CI
|
|
476
|
+
unset CLAUDECODE
|
|
473
477
|
SCRIPT_PATH="${scriptPath}"
|
|
474
478
|
PROMPT_PATH="${promptPath}"
|
|
475
479
|
${setTitleCmds}
|
|
@@ -9,6 +9,7 @@ import * as path from 'node:path';
|
|
|
9
9
|
import { execSync } from 'node:child_process';
|
|
10
10
|
import { autoExportToBoard } from '../pmo/index.js';
|
|
11
11
|
import { getWorkColumnSetting, findColumnByName } from '../pmo/utils.js';
|
|
12
|
+
import { resolveAgentDir } from '../agents/commands.js';
|
|
12
13
|
import { findHQRoot } from '../repos/index.js';
|
|
13
14
|
import { hasGitHubRemote } from '../repos/git.js';
|
|
14
15
|
import { hasDevcontainerConfig } from './devcontainer.js';
|
|
@@ -182,8 +183,8 @@ export function selectAgent(strategy, availableAgents, executionStorage, roundRo
|
|
|
182
183
|
export async function spawnAgentForTicket(ticket, agentName, storage, executionStorage, workspaceInfo, db, pmoPath, options = {}) {
|
|
183
184
|
const log = options.log || (() => { });
|
|
184
185
|
const executor = options.executor || DEFAULT_EXECUTION_CONFIG.defaultExecutor;
|
|
185
|
-
// Determine agent directory and worktree path
|
|
186
|
-
const agentDir =
|
|
186
|
+
// Determine agent directory and worktree path (handles staff and temp agents)
|
|
187
|
+
const agentDir = resolveAgentDir(workspaceInfo, agentName);
|
|
187
188
|
if (!fs.existsSync(agentDir)) {
|
|
188
189
|
return {
|
|
189
190
|
success: false,
|
package/dist/lib/themes.js
CHANGED
|
@@ -80,26 +80,42 @@ export const BUILTIN_THEMES = [
|
|
|
80
80
|
{
|
|
81
81
|
id: 'billionaires',
|
|
82
82
|
name: 'billionaires',
|
|
83
|
-
displayName: 'Billionaires
|
|
83
|
+
displayName: 'Billionaires',
|
|
84
84
|
description: 'The ultra-wealthy work for you',
|
|
85
85
|
persistentDir: 'staff',
|
|
86
86
|
ephemeralDir: 'temp',
|
|
87
87
|
names: [
|
|
88
|
-
|
|
89
|
-
'
|
|
90
|
-
'
|
|
91
|
-
'
|
|
92
|
-
'
|
|
93
|
-
'
|
|
94
|
-
|
|
95
|
-
'
|
|
96
|
-
'
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
88
|
+
'altman', 'andreesen', 'ballmer', 'benioff', 'bezos', 'branson',
|
|
89
|
+
'brin', 'buffett', 'chesky', 'collison', 'cook', 'dalio',
|
|
90
|
+
'dario', 'dell', 'dorsey', 'durov', 'ellison', 'fink',
|
|
91
|
+
'gates', 'hastings', 'hoffman', 'horowitz', 'huang', 'jobs',
|
|
92
|
+
'kalanick', 'khosla', 'knight', 'levinson', 'ma', 'mcnealy',
|
|
93
|
+
'musk', 'nadella', 'neumann', 'omidyar', 'page', 'parker',
|
|
94
|
+
'pichai', 'sandberg', 'schmidt', 'schultz', 'siebel',
|
|
95
|
+
'silbermann', 'spiegel', 'sweeney', 'systrom', 'thiel',
|
|
96
|
+
'wozniak', 'yang', 'zuck'
|
|
97
|
+
]
|
|
98
|
+
},
|
|
99
|
+
{
|
|
100
|
+
id: 'cracked-engineers',
|
|
101
|
+
name: 'cracked-engineers',
|
|
102
|
+
displayName: 'Cracked Engineers',
|
|
103
|
+
description: 'AI researchers, engineers, and tech legends',
|
|
104
|
+
persistentDir: 'staff',
|
|
105
|
+
ephemeralDir: 'temp',
|
|
106
|
+
names: [
|
|
107
|
+
// AI researchers
|
|
108
|
+
'karpathy', 'lecun', 'sutskever',
|
|
109
|
+
// Engineers & creators
|
|
110
|
+
'sinofsky', 'spolsky', 'torvalds', 'yegge',
|
|
111
|
+
// Investors & operators (non-billionaire)
|
|
112
|
+
'grove', 'kutcher', 'rabois', 'ross',
|
|
113
|
+
// Podcasters & educators
|
|
114
|
+
'fridman',
|
|
115
|
+
// Other tech figures
|
|
116
|
+
'hurd', 'iger', 'ive', 'levie', 'lynch', 'marcus', 'mayer',
|
|
117
|
+
'morin', 'powell', 'rometty', 'wales', 'wojcicki', 'zhang',
|
|
118
|
+
'zhong'
|
|
103
119
|
]
|
|
104
120
|
},
|
|
105
121
|
{
|