chore: bump version to 0.1394

This commit is contained in:
arkon
2026-01-27 02:38:37 +01:00
parent 2a89f2aa51
commit 2d8597a66f
15 changed files with 169 additions and 38 deletions
+1 -1
View File
@@ -38,7 +38,7 @@ Claudeman is a Claude Code session manager with a web interface and autonomous R
When adding new features, always ask: "Will this maintain responsiveness with 20 sessions and 50 agent windows?"
**Version**: 0.1393 (must match `package.json`)
**Version**: 0.1394 (must match `package.json`)
**Tech Stack**: TypeScript (ES2022/NodeNext, strict mode), Node.js, Fastify, Server-Sent Events, node-pty
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "claudeman",
"version": "0.1393",
"version": "0.1394",
"description": "The missing control plane for Claude Code - run 20 autonomous agents with real-time monitoring and session persistence",
"type": "module",
"main": "dist/index.js",
+18 -6
View File
@@ -1202,18 +1202,24 @@ export class Session extends EventEmitter {
* the response.
*
* @param prompt - The prompt text to send to Claude
* @param options - Optional configuration
* @param options.model - Model to use ('opus', 'sonnet', or full model name). Defaults to default model.
* @param options.onProgress - Callback for progress updates (token count, status)
* @returns Promise resolving to the result text and total cost in USD
* @throws {Error} If a process is already running in this session
*
* @example
* ```typescript
* const session = new Session({ workingDir: '/project' });
* const { result, cost } = await session.runPrompt('Explain this code');
* const { result, cost } = await session.runPrompt('Explain this code', { model: 'opus' });
* console.log(`Response: ${result}`);
* console.log(`Cost: $${cost.toFixed(4)}`);
* ```
*/
async runPrompt(prompt: string): Promise<{ result: string; cost: number }> {
async runPrompt(
prompt: string,
options?: { model?: string; onProgress?: (info: { tokens?: number; status?: string }) => void }
): Promise<{ result: string; cost: number }> {
return new Promise((resolve, reject) => {
if (this.ptyProcess) {
reject(new Error('Session already has a running process'));
@@ -1235,14 +1241,20 @@ export class Session extends EventEmitter {
try {
// Spawn claude in a real PTY
console.log('[Session] Spawning PTY for claude with prompt:', prompt.substring(0, 50));
const model = options?.model;
console.log('[Session] Spawning PTY for claude with prompt:', prompt.substring(0, 50), model ? `(model: ${model})` : '');
this.ptyProcess = pty.spawn('claude', [
const args = [
'-p',
'--dangerously-skip-permissions',
'--output-format', 'stream-json',
prompt
], {
];
if (model) {
args.push('--model', model);
}
args.push(prompt);
this.ptyProcess = pty.spawn('claude', args, {
name: 'xterm-256color',
cols: 120,
rows: 40,
+50 -8
View File
@@ -2635,34 +2635,67 @@ class ClaudemanApp {
async generatePlan() {
const config = this.ralphWizardConfig;
// Stop any existing timer
// Stop any existing timers
if (this.planLoadingTimer) {
clearInterval(this.planLoadingTimer);
this.planLoadingTimer = null;
}
if (this.planPhaseTimer) {
clearInterval(this.planPhaseTimer);
this.planPhaseTimer = null;
}
// Show loading state
document.getElementById('planGenerationError')?.classList.add('hidden');
document.getElementById('planEditor')?.classList.add('hidden');
document.getElementById('planGenerationLoading')?.classList.remove('hidden');
// Start elapsed time display
// Animated progress phases
const phases = [
{ time: 0, title: 'Starting Opus 4.5...', hint: 'Initializing deep reasoning model' },
{ time: 3, title: 'Analyzing task requirements...', hint: 'Understanding the scope and complexity' },
{ time: 8, title: 'Identifying components...', hint: 'Breaking down into modules and features' },
{ time: 15, title: 'Planning TDD approach...', hint: 'Designing test-first implementation strategy' },
{ time: 25, title: 'Generating implementation steps...', hint: 'Creating detailed action items with tests' },
{ time: 40, title: 'Adding verification checkpoints...', hint: 'Ensuring each phase has validation' },
{ time: 55, title: 'Reviewing for completeness...', hint: 'Checking all requirements are covered' },
{ time: 70, title: 'Finalizing plan...', hint: 'Organizing and prioritizing steps' },
{ time: 90, title: 'Still working...', hint: 'Complex tasks take longer - hang tight!' },
];
// Start elapsed time and phase display
this.planLoadingStartTime = Date.now();
const timeEl = document.getElementById('planLoadingTime');
if (timeEl) timeEl.textContent = '0s';
const titleEl = document.getElementById('planLoadingTitle');
const hintEl = document.getElementById('planLoadingHint');
if (timeEl) timeEl.textContent = '0s';
if (titleEl) titleEl.textContent = phases[0].title;
if (hintEl) hintEl.textContent = phases[0].hint;
let currentPhaseIndex = 0;
this.planLoadingTimer = setInterval(() => {
const elapsed = Math.floor((Date.now() - this.planLoadingStartTime) / 1000);
if (timeEl) timeEl.textContent = `${elapsed}s`;
// Update phase based on elapsed time
for (let i = phases.length - 1; i >= 0; i--) {
if (elapsed >= phases[i].time && i > currentPhaseIndex) {
currentPhaseIndex = i;
if (titleEl) titleEl.textContent = phases[i].title;
if (hintEl) hintEl.textContent = phases[i].hint;
break;
}
}
}, 1000);
// Determine max items based on detail level
const detailConfig = {
brief: { maxItems: 5, includeTests: false },
standard: { maxItems: 8, includeTests: true },
detailed: { maxItems: 12, includeTests: true },
brief: { maxItems: 10 },
standard: { maxItems: 15 },
detailed: { maxItems: 20 },
};
const { maxItems, includeTests } = detailConfig[config.planDetailLevel] || detailConfig.standard;
const { maxItems } = detailConfig[config.planDetailLevel] || detailConfig.standard;
try {
const res = await fetch('/api/generate-plan', {
@@ -2671,7 +2704,6 @@ class ClaudemanApp {
body: JSON.stringify({
taskDescription: config.taskDescription,
maxItems,
includeTests,
detailLevel: config.planDetailLevel,
}),
});
@@ -2838,6 +2870,16 @@ class ClaudemanApp {
}
skipPlanGeneration() {
// Stop any running timers
if (this.planLoadingTimer) {
clearInterval(this.planLoadingTimer);
this.planLoadingTimer = null;
}
if (this.planPhaseTimer) {
clearInterval(this.planPhaseTimer);
this.planPhaseTimer = null;
}
this.ralphWizardConfig.skipPlanGeneration = true;
this.ralphWizardConfig.planGenerated = false;
this.ralphWizardConfig.generatedPlan = null;
+3 -2
View File
@@ -1011,11 +1011,12 @@
<div class="plan-loading-content">
<div class="plan-spinner"></div>
<div class="plan-loading-text">
<span class="plan-loading-title">Generating implementation plan...</span>
<span class="plan-loading-title" id="planLoadingTitle">Starting Opus 4.5...</span>
<span class="plan-loading-time" id="planLoadingTime">0s</span>
</div>
</div>
<p class="plan-loading-hint">Claude is breaking down your task into actionable steps with tests</p>
<p class="plan-loading-hint" id="planLoadingHint">Initializing deep reasoning model</p>
<button class="btn-toolbar btn-sm plan-skip-btn" onclick="app.skipPlanGeneration()">Skip</button>
</div>
<!-- Error state -->
+12 -4
View File
@@ -5344,7 +5344,7 @@ kbd {
/* Wizard Pages */
.wizard-page {
min-height: 280px;
min-height: 180px;
}
.wizard-page.hidden {
@@ -5482,7 +5482,15 @@ kbd {
.plan-loading-hint {
color: var(--text-dim);
font-size: 0.85rem;
margin: 0;
margin: 0 0 1rem 0;
}
.plan-skip-btn {
opacity: 0.6;
}
.plan-skip-btn:hover {
opacity: 1;
}
.plan-error-msg {
@@ -5744,11 +5752,11 @@ kbd {
background: var(--bg-dark);
border: 1px solid var(--border);
border-radius: 4px;
padding: 0.75rem;
padding: 0.5rem 0.75rem;
font-family: 'SF Mono', Monaco, 'Courier New', monospace;
font-size: 0.75rem;
color: var(--text-dim);
max-height: 200px;
max-height: 120px;
overflow-y: auto;
white-space: pre-wrap;
word-break: break-word;
+84 -16
View File
@@ -2056,6 +2056,7 @@ export class WebServer extends EventEmitter {
interface GeneratePlanRequest {
taskDescription: string;
maxItems?: number;
detailLevel?: 'brief' | 'standard' | 'detailed';
}
interface PlanItem {
@@ -2064,7 +2065,11 @@ export class WebServer extends EventEmitter {
}
this.app.post('/api/generate-plan', async (req): Promise<ApiResponse> => {
const { taskDescription, maxItems = 8 } = req.body as GeneratePlanRequest;
const {
taskDescription,
maxItems = 12,
detailLevel = 'standard'
} = req.body as GeneratePlanRequest;
if (!taskDescription || typeof taskDescription !== 'string') {
return createErrorResponse(ApiErrorCode.INVALID_INPUT, 'Task description is required');
@@ -2074,26 +2079,86 @@ export class WebServer extends EventEmitter {
return createErrorResponse(ApiErrorCode.INVALID_INPUT, 'Task description too long (max 10000 chars)');
}
const prompt = `Break down this task into ${maxItems} or fewer actionable implementation steps.
// Build sophisticated prompt based on Ralph Wiggum methodology
const detailConfig = {
brief: { minSteps: 5, maxSteps: maxItems, testDepth: 'basic' },
standard: { minSteps: 8, maxSteps: maxItems, testDepth: 'thorough' },
detailed: { minSteps: 12, maxSteps: Math.max(maxItems, 15), testDepth: 'comprehensive' },
};
const config = detailConfig[detailLevel] || detailConfig.standard;
TASK:
const prompt = `You are an expert software architect breaking down a task into a thorough implementation plan.
## TASK TO IMPLEMENT
${taskDescription}
OUTPUT FORMAT:
Return ONLY a JSON array. Each item must have:
- content: specific, actionable step (verb phrase, 5-80 chars)
- priority: "P0" (critical path), "P1" (standard), "P2" (nice-to-have), or null
## YOUR MISSION
Create a detailed, actionable implementation plan following Test-Driven Development (TDD) methodology.
Think deeply about:
- What are all the components needed?
- What could go wrong? Add defensive steps.
- How will we verify each part works?
- What edge cases need handling?
Example output:
[{"content": "Create auth database schema", "priority": "P0"}, {"content": "Implement JWT token generation", "priority": "P1"}]
## PLAN STRUCTURE (${config.minSteps}-${config.maxSteps} steps)
RULES:
- Start each step with a verb (Create, Implement, Add, Write, Configure, etc.)
- Keep steps focused and achievable in one work session
- Order by logical dependency (do first things first)
- Use P0 sparingly for truly critical items`;
Your plan MUST include these phases in order:
// Create temporary session for the AI call
### Phase 1: Foundation & Setup
- Project structure, dependencies, configuration
- Database schemas, type definitions, interfaces
### Phase 2: Core Implementation (TDD Cycle)
For EACH feature:
1. Write failing tests first (unit tests)
2. Implement the feature
3. Run tests, debug until passing
4. Refactor if needed
### Phase 3: Integration & Edge Cases
- Integration tests for feature interactions
- Edge case handling (errors, boundaries, invalid input)
- Error messages and user feedback
### Phase 4: Verification & Hardening
- Run full test suite
- Fix any failing tests
- Add missing test coverage
- Final verification that ALL requirements are met
## OUTPUT FORMAT
Return ONLY a JSON array. Each item:
- content: specific action (verb phrase, 15-120 chars, be descriptive!)
- priority: "P0" (critical/blocking), "P1" (required), "P2" (enhancement)
## EXAMPLE OUTPUT
[
{"content": "Create project structure with src/, tests/, and config directories", "priority": "P0"},
{"content": "Define TypeScript interfaces for User, Session, and AuthToken types", "priority": "P0"},
{"content": "Write failing unit tests for password hashing (valid password, empty, too short)", "priority": "P0"},
{"content": "Implement password hashing with bcrypt, configurable salt rounds", "priority": "P0"},
{"content": "Run password tests and debug until all pass", "priority": "P0"},
{"content": "Write failing tests for JWT token generation and validation", "priority": "P0"},
{"content": "Implement JWT service with access/refresh token support", "priority": "P0"},
{"content": "Run JWT tests and verify token expiration handling works", "priority": "P0"},
{"content": "Write integration tests for login flow (valid creds, invalid, locked account)", "priority": "P1"},
{"content": "Implement login endpoint with rate limiting and audit logging", "priority": "P1"},
{"content": "Add error handling for network failures and database timeouts", "priority": "P1"},
{"content": "Run full test suite and fix any failures", "priority": "P1"},
{"content": "Verify all original requirements are implemented and tested", "priority": "P1"}
]
## CRITICAL RULES
1. EVERY implementation step should have a corresponding test step BEFORE it
2. Include "Run tests and debug/fix" steps after implementation blocks
3. Be SPECIFIC - not "Add tests" but "Write tests for X covering Y and Z"
4. Think about what could fail and add defensive steps
5. End with verification that ALL original requirements are met
6. Use P0 for foundation and core features, P1 for required work, P2 for nice-to-have
NOW: Generate the implementation plan for the task above. Think step by step.`;
// Create temporary session for the AI call using Opus 4.5 for deep reasoning
const session = new Session({
workingDir: process.cwd(),
screenManager: this.screenManager,
@@ -2101,8 +2166,11 @@ RULES:
mode: 'claude',
});
// Use Opus 4.5 for plan generation (better reasoning)
const modelToUse = 'opus';
try {
const { result, cost } = await session.runPrompt(prompt);
const { result, cost } = await session.runPrompt(prompt, { model: modelToUse });
// Parse JSON from result
const jsonMatch = result.match(/\[[\s\S]*\]/);
Binary file not shown.

After

Width:  |  Height:  |  Size: 207 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 206 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 201 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 201 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 202 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 216 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 166 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 188 KiB