mirror of
https://github.com/Ark0N/Codeman.git
synced 2026-10-04 22:49:41 +02:00
fix: address code review findings for OpenCode integration
- Add _isStopped guard to OpenCode 3s readiness timeout (session.ts) - Block respawn for opencode sessions on interactive-respawn and respawn/enable routes (server.ts) - Fail fast in direct PTY fallback for OpenCode mode (session.ts) - Validate configContent as JSON at schema level (schemas.ts) - Update JSDoc example for createSession options API (tmux-manager.ts) - Un-hide Context tab for OpenCode sessions (index.html) - Add OpenCode UI tests (opencode-resize.test.ts) Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -989,6 +989,7 @@ export class Session extends EventEmitter {
|
||||
// Emit needsRefresh so the client fetches the full buffer once the TUI has rendered.
|
||||
this._promptCheckTimeout = setTimeout(() => {
|
||||
this._promptCheckTimeout = null;
|
||||
if (this._isStopped) return;
|
||||
this._status = 'idle';
|
||||
this.emit('needsRefresh');
|
||||
}, 3000);
|
||||
@@ -1035,6 +1036,10 @@ export class Session extends EventEmitter {
|
||||
|
||||
// Fallback to direct PTY if mux is not used
|
||||
if (!this.ptyProcess) {
|
||||
// OpenCode sessions require tmux for env var injection (API keys via setenv)
|
||||
if (this.mode === 'opencode') {
|
||||
throw new Error('OpenCode sessions require tmux. Direct PTY fallback is not supported.');
|
||||
}
|
||||
try {
|
||||
// Pass --session-id to use the SAME ID as the Claudeman session
|
||||
// This ensures subagents can be directly matched to the correct tab
|
||||
|
||||
+1
-1
@@ -258,7 +258,7 @@ function setOpenCodeConfigContent(muxName: string, config?: OpenCodeConfig): voi
|
||||
* const manager = new TmuxManager();
|
||||
*
|
||||
* // Create a tmux session for Claude
|
||||
* const session = await manager.createSession(sessionId, '/project', 'claude');
|
||||
* const session = await manager.createSession({ sessionId, workingDir: '/project', mode: 'claude' });
|
||||
*
|
||||
* // Send input (single command, no delay!)
|
||||
* manager.sendInput(sessionId, '/clear\r');
|
||||
|
||||
@@ -510,7 +510,7 @@
|
||||
<!-- Modal Tabs -->
|
||||
<div class="modal-tabs">
|
||||
<button class="modal-tab-btn active" data-tab="respawn" data-claude-only onclick="app.switchOptionsTab('respawn')">Respawn</button>
|
||||
<button class="modal-tab-btn" data-tab="context" data-claude-only onclick="app.switchOptionsTab('context')">Context</button>
|
||||
<button class="modal-tab-btn" data-tab="context" onclick="app.switchOptionsTab('context')">Context</button>
|
||||
<button class="modal-tab-btn" data-tab="ralph" data-claude-only onclick="app.switchOptionsTab('ralph')">Ralph / Todo</button>
|
||||
<button class="modal-tab-btn" data-tab="summary" onclick="app.switchOptionsTab('summary')">Summary</button>
|
||||
</div>
|
||||
|
||||
+4
-1
@@ -70,7 +70,10 @@ const OpenCodeConfigSchema = z.object({
|
||||
autoAllowTools: z.boolean().optional(),
|
||||
continueSession: z.string().max(100).regex(/^[a-zA-Z0-9_-]+$/).optional(),
|
||||
forkSession: z.boolean().optional(),
|
||||
configContent: z.string().max(10000).optional(),
|
||||
configContent: z.string().max(10000).refine(
|
||||
(val) => { try { JSON.parse(val); return true; } catch { return false; } },
|
||||
{ message: 'configContent must be valid JSON' },
|
||||
).optional(),
|
||||
}).optional();
|
||||
|
||||
export const CreateSessionSchema = z.object({
|
||||
|
||||
+11
-2
@@ -2026,10 +2026,14 @@ export class WebServer extends EventEmitter {
|
||||
return createErrorResponse(ApiErrorCode.SESSION_BUSY, 'Session is busy');
|
||||
}
|
||||
|
||||
// Respawn is not supported for opencode sessions
|
||||
if (session.mode === 'opencode') {
|
||||
return createErrorResponse(ApiErrorCode.INVALID_INPUT, 'Respawn is not supported for opencode sessions');
|
||||
}
|
||||
|
||||
try {
|
||||
// Auto-detect completion phrase from CLAUDE.md BEFORE starting (only if globally enabled and not explicitly disabled by user)
|
||||
// Ralph tracker is not supported for opencode sessions
|
||||
if (session.mode !== 'opencode' && this.store.getConfig().ralphEnabled && !session.ralphTracker.autoEnableDisabled) {
|
||||
if (this.store.getConfig().ralphEnabled && !session.ralphTracker.autoEnableDisabled) {
|
||||
autoConfigureRalph(session, session.workingDir, () => {});
|
||||
if (!session.ralphTracker.enabled) {
|
||||
session.ralphTracker.enable();
|
||||
@@ -2084,6 +2088,11 @@ export class WebServer extends EventEmitter {
|
||||
return createErrorResponse(ApiErrorCode.NOT_FOUND, 'Session not found');
|
||||
}
|
||||
|
||||
// Respawn is not supported for opencode sessions
|
||||
if (session.mode === 'opencode') {
|
||||
return createErrorResponse(ApiErrorCode.INVALID_INPUT, 'Respawn is not supported for opencode sessions');
|
||||
}
|
||||
|
||||
// Check if session is running (has a PID)
|
||||
if (!session.pid) {
|
||||
return createErrorResponse(ApiErrorCode.OPERATION_FAILED, 'Session is not running. Start it first.');
|
||||
|
||||
Reference in New Issue
Block a user