@coralai/sps-cli 0.22.0 → 0.23.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.
@@ -16,7 +16,7 @@ export interface ProjectConfig {
16
16
  MR_MODE: 'none' | 'create';
17
17
  WORKER_TOOL: 'claude' | 'codex';
18
18
  WORKER_MODE: 'print' | 'interactive';
19
- WORKER_TRANSPORT: 'proc' | 'acp';
19
+ WORKER_TRANSPORT: 'proc' | 'acp' | 'pty';
20
20
  MAX_CONCURRENT_WORKERS: number;
21
21
  WORKER_RESTART_LIMIT: number;
22
22
  AUTOFIX_ATTEMPTS: number;
@@ -1 +1 @@
1
- {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/core/config.ts"],"names":[],"mappings":"AAOA,MAAM,WAAW,SAAS;IACxB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAAC;CACvB;AAgFD,MAAM,WAAW,aAAa;IAE5B,YAAY,EAAE,MAAM,CAAC;IACrB,eAAe,EAAE,MAAM,CAAC;IACxB,WAAW,CAAC,EAAE,MAAM,CAAC;IAGrB,cAAc,EAAE,MAAM,CAAC;IACvB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,mBAAmB,EAAE,MAAM,CAAC;IAC5B,qBAAqB,EAAE,MAAM,CAAC;IAG9B,OAAO,EAAE,QAAQ,GAAG,OAAO,GAAG,UAAU,CAAC;IAGzC,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B,OAAO,EAAE,QAAQ,GAAG,OAAO,GAAG,MAAM,CAAC;IACrC,OAAO,EAAE,MAAM,GAAG,QAAQ,CAAC;IAG3B,WAAW,EAAE,QAAQ,GAAG,OAAO,CAAC;IAChC,WAAW,EAAE,OAAO,GAAG,aAAa,CAAC;IACrC,gBAAgB,EAAE,MAAM,GAAG,KAAK,CAAC;IACjC,sBAAsB,EAAE,MAAM,CAAC;IAC/B,oBAAoB,EAAE,MAAM,CAAC;IAC7B,gBAAgB,EAAE,MAAM,CAAC;IACzB,oBAAoB,EAAE,OAAO,CAAC;IAC9B,oBAAoB,EAAE,MAAM,CAAC;IAC7B,gBAAgB,EAAE,OAAO,CAAC;IAC1B,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,SAAS,CAAC,EAAE,QAAQ,GAAG,OAAO,CAAC;IAC/B,oBAAoB,EAAE,UAAU,CAAC;IAGjC,uBAAuB,EAAE,MAAM,CAAC;IAChC,qBAAqB,EAAE,MAAM,CAAC;IAG9B,wBAAwB,EAAE,MAAM,CAAC;IACjC,eAAe,EAAE,OAAO,CAAC;IACzB,gBAAgB,EAAE,QAAQ,GAAG,UAAU,CAAC;IACxC,yBAAyB,EAAE,MAAM,CAAC;IAClC,qBAAqB,EAAE,MAAM,CAAC;IAC9B,qBAAqB,EAAE,MAAM,CAAC;IAG9B,YAAY,CAAC,EAAE,MAAM,CAAC;IAGtB,cAAc,EAAE,OAAO,CAAC;IACxB,aAAa,CAAC,EAAE,MAAM,CAAC;IAGvB,GAAG,EAAE,SAAS,CAAC;CAChB;AAQD,wBAAgB,aAAa,IAAI,SAAS,CAIzC;AAED,wBAAgB,eAAe,CAAC,WAAW,EAAE,MAAM,GAAG,aAAa,CAwElE;AAED,wBAAgB,cAAc,CAAC,MAAM,EAAE,aAAa,GAAG;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,EAAE,CAQ1F;AAED;;;;GAIG;AACH,wBAAgB,sBAAsB,CAAC,MAAM,EAAE,aAAa,GAAG,MAAM,CAiCpE"}
1
+ {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/core/config.ts"],"names":[],"mappings":"AAOA,MAAM,WAAW,SAAS;IACxB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAAC;CACvB;AAgFD,MAAM,WAAW,aAAa;IAE5B,YAAY,EAAE,MAAM,CAAC;IACrB,eAAe,EAAE,MAAM,CAAC;IACxB,WAAW,CAAC,EAAE,MAAM,CAAC;IAGrB,cAAc,EAAE,MAAM,CAAC;IACvB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,mBAAmB,EAAE,MAAM,CAAC;IAC5B,qBAAqB,EAAE,MAAM,CAAC;IAG9B,OAAO,EAAE,QAAQ,GAAG,OAAO,GAAG,UAAU,CAAC;IAGzC,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B,OAAO,EAAE,QAAQ,GAAG,OAAO,GAAG,MAAM,CAAC;IACrC,OAAO,EAAE,MAAM,GAAG,QAAQ,CAAC;IAG3B,WAAW,EAAE,QAAQ,GAAG,OAAO,CAAC;IAChC,WAAW,EAAE,OAAO,GAAG,aAAa,CAAC;IACrC,gBAAgB,EAAE,MAAM,GAAG,KAAK,GAAG,KAAK,CAAC;IACzC,sBAAsB,EAAE,MAAM,CAAC;IAC/B,oBAAoB,EAAE,MAAM,CAAC;IAC7B,gBAAgB,EAAE,MAAM,CAAC;IACzB,oBAAoB,EAAE,OAAO,CAAC;IAC9B,oBAAoB,EAAE,MAAM,CAAC;IAC7B,gBAAgB,EAAE,OAAO,CAAC;IAC1B,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,SAAS,CAAC,EAAE,QAAQ,GAAG,OAAO,CAAC;IAC/B,oBAAoB,EAAE,UAAU,CAAC;IAGjC,uBAAuB,EAAE,MAAM,CAAC;IAChC,qBAAqB,EAAE,MAAM,CAAC;IAG9B,wBAAwB,EAAE,MAAM,CAAC;IACjC,eAAe,EAAE,OAAO,CAAC;IACzB,gBAAgB,EAAE,QAAQ,GAAG,UAAU,CAAC;IACxC,yBAAyB,EAAE,MAAM,CAAC;IAClC,qBAAqB,EAAE,MAAM,CAAC;IAC9B,qBAAqB,EAAE,MAAM,CAAC;IAG9B,YAAY,CAAC,EAAE,MAAM,CAAC;IAGtB,cAAc,EAAE,OAAO,CAAC;IACxB,aAAa,CAAC,EAAE,MAAM,CAAC;IAGvB,GAAG,EAAE,SAAS,CAAC;CAChB;AAQD,wBAAgB,aAAa,IAAI,SAAS,CAIzC;AAED,wBAAgB,eAAe,CAAC,WAAW,EAAE,MAAM,GAAG,aAAa,CAwElE;AAED,wBAAgB,cAAc,CAAC,MAAM,EAAE,aAAa,GAAG;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,EAAE,CAQ1F;AAED;;;;GAIG;AACH,wBAAgB,sBAAsB,CAAC,MAAM,EAAE,aAAa,GAAG,MAAM,CAiCpE"}
@@ -9,7 +9,7 @@ export interface WorkerSlotState {
9
9
  /** Worker execution mode — null for legacy state files */
10
10
  mode?: 'print' | 'interactive' | 'acp' | null;
11
11
  /** Underlying worker transport */
12
- transport?: 'proc' | 'acp' | null;
12
+ transport?: 'proc' | 'acp' | 'pty' | null;
13
13
  /** Worker tool currently bound to the slot */
14
14
  agent?: 'claude' | 'codex' | null;
15
15
  /** Claude/Codex session ID for resume chains (print mode) */
@@ -1 +1 @@
1
- {"version":3,"file":"state.d.ts","sourceRoot":"","sources":["../../src/core/state.ts"],"names":[],"mappings":"AAGA,MAAM,WAAW,eAAe;IAC9B,MAAM,EAAE,MAAM,GAAG,QAAQ,GAAG,SAAS,GAAG,WAAW,GAAG,WAAW,CAAC;IAClE,GAAG,EAAE,MAAM,GAAG,IAAI,CAAC;IACnB,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,aAAa,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,0DAA0D;IAC1D,IAAI,CAAC,EAAE,OAAO,GAAG,aAAa,GAAG,KAAK,GAAG,IAAI,CAAC;IAC9C,kCAAkC;IAClC,SAAS,CAAC,EAAE,MAAM,GAAG,KAAK,GAAG,IAAI,CAAC;IAClC,8CAA8C;IAC9C,KAAK,CAAC,EAAE,QAAQ,GAAG,OAAO,GAAG,IAAI,CAAC;IAClC,6DAA6D;IAC7D,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,qCAAqC;IACrC,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,mCAAmC;IACnC,YAAY,CAAC,EAAE,SAAS,GAAG,OAAO,GAAG,MAAM,GAAG,UAAU,GAAG,SAAS,GAAG,IAAI,CAAC;IAC5E,+BAA+B;IAC/B,YAAY,CAAC,EAAE,WAAW,GAAG,SAAS,GAAG,eAAe,GAAG,WAAW,GAAG,QAAQ,GAAG,WAAW,GAAG,MAAM,GAAG,IAAI,CAAC;IAChH,+CAA+C;IAC/C,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,+CAA+C;IAC/C,GAAG,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACpB,iDAAiD;IACjD,UAAU,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,0DAA0D;IAC1D,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,sDAAsD;IACtD,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,8EAA8E;IAC9E,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CAC7B;AAED,MAAM,WAAW,eAAe;IAC9B,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,eAAe,EAAE,MAAM,EAAE,CAAC;IAC1B,SAAS,EAAE,MAAM,CAAC;IAClB,sDAAsD;IACtD,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,oBAAoB;IACnC,MAAM,EAAE,MAAM,CAAC;IACf,YAAY,EAAE,MAAM,CAAC;IACrB,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,YAAY;IAC3B,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,eAAe,CAAC,CAAC;IACzC,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,eAAe,CAAC,CAAC;IAC7C,eAAe,EAAE,oBAAoB,EAAE,CAAC;CACzC;AAwED,wBAAgB,SAAS,CAAC,SAAS,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,YAAY,CAU7E;AAED;;;GAGG;AACH,wBAAgB,UAAU,CAAC,SAAS,EAAE,MAAM,EAAE,KAAK,EAAE,YAAY,EAAE,SAAS,EAAE,MAAM,GAAG,IAAI,CAW1F"}
1
+ {"version":3,"file":"state.d.ts","sourceRoot":"","sources":["../../src/core/state.ts"],"names":[],"mappings":"AAGA,MAAM,WAAW,eAAe;IAC9B,MAAM,EAAE,MAAM,GAAG,QAAQ,GAAG,SAAS,GAAG,WAAW,GAAG,WAAW,CAAC;IAClE,GAAG,EAAE,MAAM,GAAG,IAAI,CAAC;IACnB,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,aAAa,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,0DAA0D;IAC1D,IAAI,CAAC,EAAE,OAAO,GAAG,aAAa,GAAG,KAAK,GAAG,IAAI,CAAC;IAC9C,kCAAkC;IAClC,SAAS,CAAC,EAAE,MAAM,GAAG,KAAK,GAAG,KAAK,GAAG,IAAI,CAAC;IAC1C,8CAA8C;IAC9C,KAAK,CAAC,EAAE,QAAQ,GAAG,OAAO,GAAG,IAAI,CAAC;IAClC,6DAA6D;IAC7D,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,qCAAqC;IACrC,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,mCAAmC;IACnC,YAAY,CAAC,EAAE,SAAS,GAAG,OAAO,GAAG,MAAM,GAAG,UAAU,GAAG,SAAS,GAAG,IAAI,CAAC;IAC5E,+BAA+B;IAC/B,YAAY,CAAC,EAAE,WAAW,GAAG,SAAS,GAAG,eAAe,GAAG,WAAW,GAAG,QAAQ,GAAG,WAAW,GAAG,MAAM,GAAG,IAAI,CAAC;IAChH,+CAA+C;IAC/C,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,+CAA+C;IAC/C,GAAG,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACpB,iDAAiD;IACjD,UAAU,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,0DAA0D;IAC1D,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,sDAAsD;IACtD,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,8EAA8E;IAC9E,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CAC7B;AAED,MAAM,WAAW,eAAe;IAC9B,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,eAAe,EAAE,MAAM,EAAE,CAAC;IAC1B,SAAS,EAAE,MAAM,CAAC;IAClB,sDAAsD;IACtD,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,oBAAoB;IACnC,MAAM,EAAE,MAAM,CAAC;IACf,YAAY,EAAE,MAAM,CAAC;IACrB,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,YAAY;IAC3B,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,eAAe,CAAC,CAAC;IACzC,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,eAAe,CAAC,CAAC;IAC7C,eAAe,EAAE,oBAAoB,EAAE,CAAC;CACzC;AAwED,wBAAgB,SAAS,CAAC,SAAS,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,YAAY,CAU7E;AAED;;;GAGG;AACH,wBAAgB,UAAU,CAAC,SAAS,EAAE,MAAM,EAAE,KAAK,EAAE,YAAY,EAAE,SAAS,EAAE,MAAM,GAAG,IAAI,CAW1F"}
@@ -0,0 +1,64 @@
1
+ import { PTYSession, type SessionState } from './pty-session.js';
2
+ export interface EnsureSessionOpts {
3
+ project: string;
4
+ slot: string;
5
+ tool: 'claude' | 'codex';
6
+ cwd: string;
7
+ logsDir: string;
8
+ /** Timeout for waiting for ready state (ms). Default: 60000 */
9
+ readyTimeoutMs?: number;
10
+ /** Auto-confirm trust prompts. Default: true */
11
+ autoTrust?: boolean;
12
+ }
13
+ export interface SessionInfo {
14
+ sessionId: string;
15
+ state: SessionState;
16
+ pid: number;
17
+ tool: 'claude' | 'codex';
18
+ cwd: string;
19
+ runId: string | null;
20
+ buffer: string;
21
+ alive: boolean;
22
+ }
23
+ export declare class PTYSessionManager {
24
+ private sessions;
25
+ private static makeKey;
26
+ /**
27
+ * Ensure a ready PTY session exists for the given slot.
28
+ * Reuses existing live session or creates a new one.
29
+ */
30
+ ensureSession(opts: EnsureSessionOpts): Promise<PTYSession>;
31
+ /**
32
+ * Start a new run (send prompt) on an existing session.
33
+ */
34
+ startRun(project: string, slot: string, prompt: string): {
35
+ runId: string;
36
+ };
37
+ /**
38
+ * Resume a run on the same session (for conflict resolution, retries, etc.)
39
+ */
40
+ resumeRun(project: string, slot: string, instruction: string): {
41
+ runId: string;
42
+ };
43
+ /**
44
+ * Wait for the current run to complete (prompt reappears).
45
+ */
46
+ waitForRunComplete(project: string, slot: string, timeoutMs?: number): Promise<{
47
+ status: 'completed' | 'failed' | 'timeout';
48
+ runId: string | null;
49
+ }>;
50
+ /**
51
+ * Send a response to a waiting-input prompt.
52
+ */
53
+ respond(project: string, slot: string, response: string): void;
54
+ getSession(project: string, slot: string): PTYSession | null;
55
+ inspect(project: string, slot: string): SessionInfo | null;
56
+ listSessions(): SessionInfo[];
57
+ killSession(project: string, slot: string): void;
58
+ killAll(): void;
59
+ get size(): number;
60
+ private requireSession;
61
+ private waitForState;
62
+ private log;
63
+ }
64
+ //# sourceMappingURL=pty-session-manager.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pty-session-manager.d.ts","sourceRoot":"","sources":["../../src/manager/pty-session-manager.ts"],"names":[],"mappings":"AAUA,OAAO,EAAE,UAAU,EAAE,KAAK,YAAY,EAAqB,MAAM,kBAAkB,CAAC;AAMpF,MAAM,WAAW,iBAAiB;IAChC,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,QAAQ,GAAG,OAAO,CAAC;IACzB,GAAG,EAAE,MAAM,CAAC;IACZ,OAAO,EAAE,MAAM,CAAC;IAChB,+DAA+D;IAC/D,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,gDAAgD;IAChD,SAAS,CAAC,EAAE,OAAO,CAAC;CACrB;AAED,MAAM,WAAW,WAAW;IAC1B,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,YAAY,CAAC;IACpB,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,QAAQ,GAAG,OAAO,CAAC;IACzB,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,OAAO,CAAC;CAChB;AAID,qBAAa,iBAAiB;IAC5B,OAAO,CAAC,QAAQ,CAAiC;IAEjD,OAAO,CAAC,MAAM,CAAC,OAAO;IAMtB;;;OAGG;IACG,aAAa,CAAC,IAAI,EAAE,iBAAiB,GAAG,OAAO,CAAC,UAAU,CAAC;IAqEjE;;OAEG;IACH,QAAQ,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG;QAAE,KAAK,EAAE,MAAM,CAAA;KAAE;IAc1E;;OAEG;IACH,SAAS,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,GAAG;QAAE,KAAK,EAAE,MAAM,CAAA;KAAE;IAchF;;OAEG;IACG,kBAAkB,CACtB,OAAO,EAAE,MAAM,EACf,IAAI,EAAE,MAAM,EACZ,SAAS,GAAE,MAAkB,GAC5B,OAAO,CAAC;QAAE,MAAM,EAAE,WAAW,GAAG,QAAQ,GAAG,SAAS,CAAC;QAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAAA;KAAE,CAAC;IAyChF;;OAEG;IACH,OAAO,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,IAAI;IAQ9D,UAAU,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,UAAU,GAAG,IAAI;IAI5D,OAAO,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,WAAW,GAAG,IAAI;IAe1D,YAAY,IAAI,WAAW,EAAE;IAmB7B,WAAW,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,IAAI;IAShD,OAAO,IAAI,IAAI;IAOf,IAAI,IAAI,IAAI,MAAM,CAEjB;IAID,OAAO,CAAC,cAAc;IAQtB,OAAO,CAAC,YAAY;IA2BpB,OAAO,CAAC,GAAG;CAGZ"}
@@ -0,0 +1,241 @@
1
+ /**
2
+ * PTYSessionManager — manages multiple PTY sessions across projects and slots.
3
+ *
4
+ * Each worker slot gets one persistent PTYSession. Sessions are reused across
5
+ * task cards within the same slot.
6
+ *
7
+ * Replaces LocalACPClient + acpTmux.ts for the PTY transport.
8
+ */
9
+ import { resolve } from 'node:path';
10
+ import { mkdirSync } from 'node:fs';
11
+ import { PTYSession } from './pty-session.js';
12
+ import { ClaudeOutputParser } from '../providers/parsers/claude-parser.js';
13
+ import { CodexOutputParser } from '../providers/parsers/codex-parser.js';
14
+ // ─── Manager ────────────────────────────────────────────────────
15
+ export class PTYSessionManager {
16
+ sessions = new Map();
17
+ static makeKey(project, slot) {
18
+ return `${project}:${slot}`;
19
+ }
20
+ // ─── Session Lifecycle ──────────────────────────────────────
21
+ /**
22
+ * Ensure a ready PTY session exists for the given slot.
23
+ * Reuses existing live session or creates a new one.
24
+ */
25
+ async ensureSession(opts) {
26
+ const key = PTYSessionManager.makeKey(opts.project, opts.slot);
27
+ // Reuse existing live session
28
+ const existing = this.sessions.get(key);
29
+ if (existing?.isAlive()) {
30
+ // If session was left in a worktree from a previous card, we can't change cwd
31
+ // of a running PTY. But the run prompt will include explicit cwd instructions.
32
+ return existing;
33
+ }
34
+ // Clean up dead session
35
+ if (existing) {
36
+ this.sessions.delete(key);
37
+ }
38
+ // Create output log directory
39
+ mkdirSync(opts.logsDir, { recursive: true });
40
+ const outputPath = resolve(opts.logsDir, `${opts.slot}-pty-${Date.now()}.log`);
41
+ // Create parser for the tool
42
+ const parser = opts.tool === 'claude'
43
+ ? new ClaudeOutputParser()
44
+ : new CodexOutputParser();
45
+ // Spawn PTY
46
+ const session = new PTYSession(opts.tool, opts.cwd, outputPath, parser);
47
+ // Auto-handle trust prompts
48
+ if (opts.autoTrust !== false) {
49
+ session.on('waiting-input', (event) => {
50
+ if (event.type === 'trust') {
51
+ this.log(`[${key}] Auto-confirming trust prompt`);
52
+ session.confirm();
53
+ }
54
+ });
55
+ }
56
+ // Clean up on exit
57
+ session.on('exit', (code) => {
58
+ this.log(`[${key}] PTY exited (code=${code})`);
59
+ this.sessions.delete(key);
60
+ });
61
+ this.sessions.set(key, session);
62
+ // Wait for ready
63
+ const timeout = opts.readyTimeoutMs ?? 60_000;
64
+ try {
65
+ await this.waitForState(session, 'ready', timeout);
66
+ this.log(`[${key}] Session ready (pid=${session.pid})`);
67
+ }
68
+ catch (err) {
69
+ const state = session.getState();
70
+ // If stuck in waiting_input (trust prompt not auto-handled), still return session
71
+ if (state === 'waiting_input') {
72
+ this.log(`[${key}] Session waiting for input (pid=${session.pid})`);
73
+ }
74
+ else {
75
+ this.log(`[${key}] Session failed to reach ready state: ${state}`);
76
+ session.kill();
77
+ this.sessions.delete(key);
78
+ throw err;
79
+ }
80
+ }
81
+ return session;
82
+ }
83
+ // ─── Run Management ─────────────────────────────────────────
84
+ /**
85
+ * Start a new run (send prompt) on an existing session.
86
+ */
87
+ startRun(project, slot, prompt) {
88
+ const session = this.requireSession(project, slot);
89
+ if (session.getState() !== 'ready') {
90
+ throw new Error(`Session not ready (state=${session.getState()})`);
91
+ }
92
+ const runId = String(Date.now());
93
+ session.setRunId(runId);
94
+ session.sendPrompt(prompt);
95
+ this.log(`[${project}:${slot}] Run started: ${runId}`);
96
+ return { runId };
97
+ }
98
+ /**
99
+ * Resume a run on the same session (for conflict resolution, retries, etc.)
100
+ */
101
+ resumeRun(project, slot, instruction) {
102
+ const session = this.requireSession(project, slot);
103
+ if (session.getState() !== 'ready') {
104
+ throw new Error(`Session not ready for resume (state=${session.getState()})`);
105
+ }
106
+ const runId = String(Date.now());
107
+ session.setRunId(runId);
108
+ session.sendPrompt(instruction);
109
+ this.log(`[${project}:${slot}] Resume run started: ${runId}`);
110
+ return { runId };
111
+ }
112
+ /**
113
+ * Wait for the current run to complete (prompt reappears).
114
+ */
115
+ async waitForRunComplete(project, slot, timeoutMs = 3_600_000) {
116
+ const session = this.requireSession(project, slot);
117
+ const runId = session.getRunId();
118
+ return new Promise((resolve) => {
119
+ const timer = setTimeout(() => {
120
+ resolve({ status: 'timeout', runId });
121
+ }, timeoutMs);
122
+ const onCompleted = (completedRunId) => {
123
+ clearTimeout(timer);
124
+ cleanup();
125
+ resolve({ status: 'completed', runId: completedRunId });
126
+ };
127
+ const onFailed = (failedRunId) => {
128
+ clearTimeout(timer);
129
+ cleanup();
130
+ resolve({ status: 'failed', runId: failedRunId });
131
+ };
132
+ const onExit = () => {
133
+ clearTimeout(timer);
134
+ cleanup();
135
+ resolve({ status: 'failed', runId });
136
+ };
137
+ const cleanup = () => {
138
+ session.off('run-completed', onCompleted);
139
+ session.off('run-failed', onFailed);
140
+ session.off('exit', onExit);
141
+ };
142
+ session.on('run-completed', onCompleted);
143
+ session.on('run-failed', onFailed);
144
+ session.on('exit', onExit);
145
+ });
146
+ }
147
+ // ─── Human Interaction ──────────────────────────────────────
148
+ /**
149
+ * Send a response to a waiting-input prompt.
150
+ */
151
+ respond(project, slot, response) {
152
+ const session = this.requireSession(project, slot);
153
+ session.write(response + '\r');
154
+ this.log(`[${project}:${slot}] Sent response: ${response}`);
155
+ }
156
+ // ─── Inspection ─────────────────────────────────────────────
157
+ getSession(project, slot) {
158
+ return this.sessions.get(PTYSessionManager.makeKey(project, slot)) || null;
159
+ }
160
+ inspect(project, slot) {
161
+ const session = this.getSession(project, slot);
162
+ if (!session)
163
+ return null;
164
+ return {
165
+ sessionId: session.sessionId,
166
+ state: session.getState(),
167
+ pid: session.pid,
168
+ tool: session.tool,
169
+ cwd: session.cwd,
170
+ runId: session.getRunId(),
171
+ buffer: session.getBuffer(30),
172
+ alive: session.isAlive(),
173
+ };
174
+ }
175
+ listSessions() {
176
+ const result = [];
177
+ for (const session of this.sessions.values()) {
178
+ result.push({
179
+ sessionId: session.sessionId,
180
+ state: session.getState(),
181
+ pid: session.pid,
182
+ tool: session.tool,
183
+ cwd: session.cwd,
184
+ runId: session.getRunId(),
185
+ buffer: session.getBuffer(5),
186
+ alive: session.isAlive(),
187
+ });
188
+ }
189
+ return result;
190
+ }
191
+ // ─── Cleanup ────────────────────────────────────────────────
192
+ killSession(project, slot) {
193
+ const key = PTYSessionManager.makeKey(project, slot);
194
+ const session = this.sessions.get(key);
195
+ if (session) {
196
+ session.kill();
197
+ this.sessions.delete(key);
198
+ }
199
+ }
200
+ killAll() {
201
+ for (const session of this.sessions.values()) {
202
+ session.kill();
203
+ }
204
+ this.sessions.clear();
205
+ }
206
+ get size() {
207
+ return this.sessions.size;
208
+ }
209
+ // ─── Internal ─────────────────────────────────────────────
210
+ requireSession(project, slot) {
211
+ const session = this.getSession(project, slot);
212
+ if (!session || !session.isAlive()) {
213
+ throw new Error(`No live session for ${project}:${slot}`);
214
+ }
215
+ return session;
216
+ }
217
+ waitForState(session, target, timeoutMs) {
218
+ if (session.getState() === target)
219
+ return Promise.resolve();
220
+ return new Promise((resolve, reject) => {
221
+ const timer = setTimeout(() => reject(new Error(`Timeout (${timeoutMs}ms) waiting for ${target}, current: ${session.getState()}`)), timeoutMs);
222
+ const handler = (state) => {
223
+ if (state === target) {
224
+ clearTimeout(timer);
225
+ session.off('state-change', handler);
226
+ resolve();
227
+ }
228
+ };
229
+ session.on('state-change', handler);
230
+ session.on('exit', () => {
231
+ clearTimeout(timer);
232
+ session.off('state-change', handler);
233
+ reject(new Error('Session exited before reaching target state'));
234
+ });
235
+ });
236
+ }
237
+ log(msg) {
238
+ process.stderr.write(`[pty-manager] ${msg}\n`);
239
+ }
240
+ }
241
+ //# sourceMappingURL=pty-session-manager.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pty-session-manager.js","sourceRoot":"","sources":["../../src/manager/pty-session-manager.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,62 @@
1
+ import { EventEmitter } from 'node:events';
2
+ export type SessionState = 'booting' | 'ready' | 'busy' | 'waiting_input' | 'offline';
3
+ export interface WaitingInputEvent {
4
+ type: 'trust' | 'permission' | 'confirmation' | 'unknown';
5
+ prompt: string;
6
+ options?: string[];
7
+ dangerous?: boolean;
8
+ timestamp: string;
9
+ }
10
+ export interface PTYSessionEvents {
11
+ 'state-change': (state: SessionState, prev: SessionState) => void;
12
+ 'waiting-input': (event: WaitingInputEvent) => void;
13
+ 'run-completed': (runId: string) => void;
14
+ 'run-failed': (runId: string, error: string) => void;
15
+ 'output': (chunk: string) => void;
16
+ 'exit': (code: number) => void;
17
+ }
18
+ /**
19
+ * OutputParser — tool-specific stream parser. Fed every chunk from PTY stdout.
20
+ * Responsible for detecting state transitions by analyzing the output stream.
21
+ */
22
+ export interface OutputParser {
23
+ feed(chunk: string, session: PTYSession): void;
24
+ reset(): void;
25
+ }
26
+ export declare class PTYSession extends EventEmitter {
27
+ private readonly parser;
28
+ private terminal;
29
+ private state;
30
+ private buffer;
31
+ private outputStream;
32
+ private currentRunId;
33
+ private _alive;
34
+ readonly pid: number;
35
+ readonly sessionId: string;
36
+ readonly tool: 'claude' | 'codex';
37
+ readonly cwd: string;
38
+ constructor(tool: 'claude' | 'codex', cwd: string, outputPath: string | null, parser: OutputParser);
39
+ /** Write raw bytes to PTY stdin */
40
+ write(data: string): void;
41
+ /** Send a prompt followed by Enter */
42
+ sendPrompt(prompt: string): void;
43
+ /** Send Enter key (confirm) */
44
+ confirm(): void;
45
+ /** Send Escape key (cancel/reject) */
46
+ reject(): void;
47
+ /** Send Ctrl+C */
48
+ interrupt(): void;
49
+ getState(): SessionState;
50
+ setState(state: SessionState): void;
51
+ getRunId(): string | null;
52
+ setRunId(runId: string | null): void;
53
+ isAlive(): boolean;
54
+ /** Get recent buffer content (optionally limited to last N lines) */
55
+ getBuffer(lines?: number): string;
56
+ /** Get raw buffer including ANSI sequences */
57
+ getRawBuffer(): string;
58
+ resize(cols: number, rows: number): void;
59
+ kill(): void;
60
+ private trimBuffer;
61
+ }
62
+ //# sourceMappingURL=pty-session.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pty-session.d.ts","sourceRoot":"","sources":["../../src/manager/pty-session.ts"],"names":[],"mappings":"AAQA,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAK3C,MAAM,MAAM,YAAY,GAAG,SAAS,GAAG,OAAO,GAAG,MAAM,GAAG,eAAe,GAAG,SAAS,CAAC;AAEtF,MAAM,WAAW,iBAAiB;IAChC,IAAI,EAAE,OAAO,GAAG,YAAY,GAAG,cAAc,GAAG,SAAS,CAAC;IAC1D,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;IACnB,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,gBAAgB;IAC/B,cAAc,EAAE,CAAC,KAAK,EAAE,YAAY,EAAE,IAAI,EAAE,YAAY,KAAK,IAAI,CAAC;IAClE,eAAe,EAAE,CAAC,KAAK,EAAE,iBAAiB,KAAK,IAAI,CAAC;IACpD,eAAe,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IACzC,YAAY,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IACrD,QAAQ,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IAClC,MAAM,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;CAChC;AAED;;;GAGG;AACH,MAAM,WAAW,YAAY;IAC3B,IAAI,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,UAAU,GAAG,IAAI,CAAC;IAC/C,KAAK,IAAI,IAAI,CAAC;CACf;AAaD,qBAAa,UAAW,SAAQ,YAAY;IAiBxC,OAAO,CAAC,QAAQ,CAAC,MAAM;IAhBzB,OAAO,CAAC,QAAQ,CAAW;IAC3B,OAAO,CAAC,KAAK,CAA2B;IACxC,OAAO,CAAC,MAAM,CAAc;IAC5B,OAAO,CAAC,YAAY,CAA4B;IAChD,OAAO,CAAC,YAAY,CAAuB;IAC3C,OAAO,CAAC,MAAM,CAAQ;IAEtB,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,IAAI,EAAE,QAAQ,GAAG,OAAO,CAAC;IAClC,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;gBAGnB,IAAI,EAAE,QAAQ,GAAG,OAAO,EACxB,GAAG,EAAE,MAAM,EACX,UAAU,EAAE,MAAM,GAAG,IAAI,EACR,MAAM,EAAE,YAAY;IAgDvC,mCAAmC;IACnC,KAAK,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI;IAKzB,sCAAsC;IACtC,UAAU,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI;IAIhC,+BAA+B;IAC/B,OAAO,IAAI,IAAI;IAIf,sCAAsC;IACtC,MAAM,IAAI,IAAI;IAId,kBAAkB;IAClB,SAAS,IAAI,IAAI;IAMjB,QAAQ,IAAI,YAAY;IAIxB,QAAQ,CAAC,KAAK,EAAE,YAAY,GAAG,IAAI;IAOnC,QAAQ,IAAI,MAAM,GAAG,IAAI;IAIzB,QAAQ,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,GAAG,IAAI;IAIpC,OAAO,IAAI,OAAO;IAMlB,qEAAqE;IACrE,SAAS,CAAC,KAAK,CAAC,EAAE,MAAM,GAAG,MAAM;IAOjC,8CAA8C;IAC9C,YAAY,IAAI,MAAM;IAMtB,MAAM,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,IAAI;IAIxC,IAAI,IAAI,IAAI;IAQZ,OAAO,CAAC,UAAU;CAMnB"}
@@ -0,0 +1,148 @@
1
+ /**
2
+ * PTYSession — wraps a single persistent Worker process (Claude/Codex) in a
3
+ * pseudoterminal. Provides real-time streaming output, direct stdin injection,
4
+ * and event-driven state detection.
5
+ *
6
+ * Replaces tmux send-keys/capture-pane with direct PTY read/write.
7
+ */
8
+ import * as pty from 'node-pty';
9
+ import { EventEmitter } from 'node:events';
10
+ import { createWriteStream } from 'node:fs';
11
+ // ─── Constants ──────────────────────────────────────────────────
12
+ const MAX_BUFFER_LINES = 500;
13
+ const STRIP_ANSI_RE = /\x1b\[[0-9;]*[a-zA-Z]|\x1b\][^\x07]*\x07|\x1b[()][AB012]|\x1b\[[\?]?[0-9;]*[hlm]/g;
14
+ function stripAnsi(text) {
15
+ return text.replace(STRIP_ANSI_RE, '');
16
+ }
17
+ // ─── PTYSession ─────────────────────────────────────────────────
18
+ export class PTYSession extends EventEmitter {
19
+ parser;
20
+ terminal;
21
+ state = 'booting';
22
+ buffer = '';
23
+ outputStream = null;
24
+ currentRunId = null;
25
+ _alive = true;
26
+ pid;
27
+ sessionId;
28
+ tool;
29
+ cwd;
30
+ constructor(tool, cwd, outputPath, parser) {
31
+ super();
32
+ this.parser = parser;
33
+ this.tool = tool;
34
+ this.cwd = cwd;
35
+ const cmd = tool === 'claude' ? 'claude' : 'codex';
36
+ const args = tool === 'claude'
37
+ ? ['--dangerously-skip-permissions']
38
+ : ['--full-auto'];
39
+ this.terminal = pty.spawn(cmd, args, {
40
+ name: 'xterm-256color',
41
+ cols: 200,
42
+ rows: 50,
43
+ cwd,
44
+ env: { ...process.env },
45
+ });
46
+ this.pid = this.terminal.pid;
47
+ this.sessionId = `pty-${tool}-${this.pid}-${Date.now()}`;
48
+ if (outputPath) {
49
+ this.outputStream = createWriteStream(outputPath, { flags: 'a' });
50
+ }
51
+ // ── Real-time stream processing ──
52
+ this.terminal.onData((chunk) => {
53
+ this.buffer += chunk;
54
+ this.trimBuffer();
55
+ if (this.outputStream)
56
+ this.outputStream.write(chunk);
57
+ this.emit('output', chunk);
58
+ // Feed clean text to parser
59
+ const clean = stripAnsi(chunk);
60
+ this.parser.feed(clean, this);
61
+ });
62
+ this.terminal.onExit(({ exitCode }) => {
63
+ this._alive = false;
64
+ this.setState('offline');
65
+ if (this.outputStream)
66
+ this.outputStream.end();
67
+ this.emit('exit', exitCode);
68
+ });
69
+ }
70
+ // ─── Write ────────────────────────────────────────────────────
71
+ /** Write raw bytes to PTY stdin */
72
+ write(data) {
73
+ if (!this._alive)
74
+ return;
75
+ this.terminal.write(data);
76
+ }
77
+ /** Send a prompt followed by Enter */
78
+ sendPrompt(prompt) {
79
+ this.write(prompt + '\r');
80
+ }
81
+ /** Send Enter key (confirm) */
82
+ confirm() {
83
+ this.write('\r');
84
+ }
85
+ /** Send Escape key (cancel/reject) */
86
+ reject() {
87
+ this.write('\x1b');
88
+ }
89
+ /** Send Ctrl+C */
90
+ interrupt() {
91
+ this.write('\x03');
92
+ }
93
+ // ─── State ────────────────────────────────────────────────────
94
+ getState() {
95
+ return this.state;
96
+ }
97
+ setState(state) {
98
+ const prev = this.state;
99
+ if (prev === state)
100
+ return;
101
+ this.state = state;
102
+ this.emit('state-change', state, prev);
103
+ }
104
+ getRunId() {
105
+ return this.currentRunId;
106
+ }
107
+ setRunId(runId) {
108
+ this.currentRunId = runId;
109
+ }
110
+ isAlive() {
111
+ return this._alive;
112
+ }
113
+ // ─── Buffer ───────────────────────────────────────────────────
114
+ /** Get recent buffer content (optionally limited to last N lines) */
115
+ getBuffer(lines) {
116
+ const clean = stripAnsi(this.buffer);
117
+ if (!lines)
118
+ return clean;
119
+ const all = clean.split('\n');
120
+ return all.slice(-lines).join('\n');
121
+ }
122
+ /** Get raw buffer including ANSI sequences */
123
+ getRawBuffer() {
124
+ return this.buffer;
125
+ }
126
+ // ─── Lifecycle ────────────────────────────────────────────────
127
+ resize(cols, rows) {
128
+ if (this._alive)
129
+ this.terminal.resize(cols, rows);
130
+ }
131
+ kill() {
132
+ this._alive = false;
133
+ try {
134
+ this.terminal.kill();
135
+ }
136
+ catch { /* already dead */ }
137
+ if (this.outputStream)
138
+ this.outputStream.end();
139
+ }
140
+ // ─── Internal ─────────────────────────────────────────────────
141
+ trimBuffer() {
142
+ const lines = this.buffer.split('\n');
143
+ if (lines.length > MAX_BUFFER_LINES) {
144
+ this.buffer = lines.slice(-MAX_BUFFER_LINES).join('\n');
145
+ }
146
+ }
147
+ }
148
+ //# sourceMappingURL=pty-session.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pty-session.js","sourceRoot":"","sources":["../../src/manager/pty-session.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,43 @@
1
+ /**
2
+ * PTYAgentRuntime — implements AgentRuntime using PTY sessions instead of tmux.
3
+ *
4
+ * Uses PTYSessionManager for direct pseudoterminal control, providing:
5
+ * - Real-time stream output (no polling)
6
+ * - Direct stdin injection (no tmux send-keys indirection)
7
+ * - Event-driven state detection (no pane text parsing)
8
+ */
9
+ import type { ProjectContext } from '../core/context.js';
10
+ import type { AgentRuntime } from '../interfaces/AgentRuntime.js';
11
+ import type { ACPState, ACPSessionRecord, ACPTool } from '../models/acp.js';
12
+ import { PTYSessionManager } from '../manager/pty-session-manager.js';
13
+ export declare function getSharedPTYManager(): PTYSessionManager;
14
+ export declare class PTYAgentRuntime implements AgentRuntime {
15
+ private readonly ctx;
16
+ private readonly manager;
17
+ constructor(ctx: ProjectContext, manager?: PTYSessionManager);
18
+ ensureSession(slot: string, tool?: ACPTool, cwdOverride?: string): Promise<ACPSessionRecord>;
19
+ startRun(slot: string, prompt: string, tool?: ACPTool, cwdOverride?: string): Promise<ACPSessionRecord>;
20
+ resumeRun(slot: string, prompt: string): Promise<ACPSessionRecord>;
21
+ inspect(slot?: string): Promise<ACPState>;
22
+ stopSession(slot: string): Promise<void>;
23
+ /**
24
+ * Wait for the current run on a slot to complete.
25
+ */
26
+ waitForRunComplete(slot: string, timeoutMs?: number): Promise<{
27
+ status: string;
28
+ runId: string | null;
29
+ }>;
30
+ /**
31
+ * Send a response to a waiting_input prompt.
32
+ */
33
+ respond(slot: string, response: string): void;
34
+ /**
35
+ * Get the underlying PTYSessionManager (for direct access if needed).
36
+ */
37
+ getManager(): PTYSessionManager;
38
+ private normalizeSlot;
39
+ private defaultTool;
40
+ private buildSessionRecord;
41
+ private syncSessionRecord;
42
+ }
43
+ //# sourceMappingURL=PTYAgentRuntime.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"PTYAgentRuntime.d.ts","sourceRoot":"","sources":["../../src/providers/PTYAgentRuntime.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AAEzD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,+BAA+B,CAAC;AAClE,OAAO,KAAK,EACV,QAAQ,EACR,gBAAgB,EAChB,OAAO,EACR,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EAAE,iBAAiB,EAAoB,MAAM,mCAAmC,CAAC;AAcxF,wBAAgB,mBAAmB,IAAI,iBAAiB,CAKvD;AAED,qBAAa,eAAgB,YAAW,YAAY;IAIhD,OAAO,CAAC,QAAQ,CAAC,GAAG;IAHtB,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAoB;gBAGzB,GAAG,EAAE,cAAc,EACpC,OAAO,CAAC,EAAE,iBAAiB;IAKvB,aAAa,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,OAAO,EAAE,WAAW,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,gBAAgB,CAAC;IAyB5F,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,OAAO,EAAE,WAAW,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,gBAAgB,CAAC;IAkCvG,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,gBAAgB,CAAC;IA2BlE,OAAO,CAAC,IAAI,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,QAAQ,CAAC;IA+BzC,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAe9C;;OAEG;IACG,kBAAkB,CAAC,IAAI,EAAE,MAAM,EAAE,SAAS,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAAA;KAAE,CAAC;IAK7G;;OAEG;IACH,OAAO,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,IAAI;IAK7C;;OAEG;IACH,UAAU,IAAI,iBAAiB;IAM/B,OAAO,CAAC,aAAa;IAIrB,OAAO,CAAC,WAAW;IAInB,OAAO,CAAC,kBAAkB;IAgD1B,OAAO,CAAC,iBAAiB;CAmB1B"}
@@ -0,0 +1,219 @@
1
+ import { readACPState, writeACPState } from '../core/acpState.js';
2
+ import { PTYSessionManager } from '../manager/pty-session-manager.js';
3
+ function now() {
4
+ return new Date().toISOString();
5
+ }
6
+ function previewPrompt(prompt) {
7
+ const oneLine = prompt.replace(/\s+/g, ' ').trim();
8
+ return oneLine.length > 120 ? `${oneLine.slice(0, 117)}...` : oneLine;
9
+ }
10
+ // Shared singleton per tick process
11
+ let sharedManager = null;
12
+ export function getSharedPTYManager() {
13
+ if (!sharedManager) {
14
+ sharedManager = new PTYSessionManager();
15
+ }
16
+ return sharedManager;
17
+ }
18
+ export class PTYAgentRuntime {
19
+ ctx;
20
+ manager;
21
+ constructor(ctx, manager) {
22
+ this.ctx = ctx;
23
+ this.manager = manager || getSharedPTYManager();
24
+ }
25
+ async ensureSession(slot, tool, cwdOverride) {
26
+ const normalizedSlot = this.normalizeSlot(slot);
27
+ const selectedTool = tool || this.defaultTool();
28
+ const cwd = cwdOverride || this.ctx.paths.repoDir;
29
+ const session = await this.manager.ensureSession({
30
+ project: this.ctx.projectName,
31
+ slot: normalizedSlot,
32
+ tool: selectedTool,
33
+ cwd,
34
+ logsDir: this.ctx.paths.logsDir,
35
+ });
36
+ const record = this.buildSessionRecord(normalizedSlot, session, selectedTool, cwd);
37
+ // Persist to acp-state.json
38
+ const state = readACPState(this.ctx.paths.acpStateFile);
39
+ state.sessions[normalizedSlot] = record;
40
+ state.updatedAt = now();
41
+ state.updatedBy = 'pty-ensure';
42
+ writeACPState(this.ctx.paths.acpStateFile, state, state.updatedBy);
43
+ return record;
44
+ }
45
+ async startRun(slot, prompt, tool, cwdOverride) {
46
+ const normalizedSlot = this.normalizeSlot(slot);
47
+ const selectedTool = tool || this.defaultTool();
48
+ const cwd = cwdOverride || this.ctx.paths.repoDir;
49
+ // Ensure session exists first
50
+ let session = this.manager.getSession(this.ctx.projectName, normalizedSlot);
51
+ if (!session || !session.isAlive()) {
52
+ await this.ensureSession(slot, selectedTool, cwd);
53
+ session = this.manager.getSession(this.ctx.projectName, normalizedSlot);
54
+ }
55
+ if (!session)
56
+ throw new Error(`Failed to create session for ${normalizedSlot}`);
57
+ const { runId } = this.manager.startRun(this.ctx.projectName, normalizedSlot, prompt);
58
+ const info = this.manager.inspect(this.ctx.projectName, normalizedSlot);
59
+ const record = this.buildSessionRecord(normalizedSlot, info, selectedTool, cwd, {
60
+ runId,
61
+ status: 'running',
62
+ promptPreview: previewPrompt(prompt),
63
+ startedAt: now(),
64
+ });
65
+ // Persist
66
+ const state = readACPState(this.ctx.paths.acpStateFile);
67
+ state.sessions[normalizedSlot] = record;
68
+ state.updatedAt = now();
69
+ state.updatedBy = 'pty-start-run';
70
+ writeACPState(this.ctx.paths.acpStateFile, state, state.updatedBy);
71
+ return record;
72
+ }
73
+ async resumeRun(slot, prompt) {
74
+ const normalizedSlot = this.normalizeSlot(slot);
75
+ const session = this.manager.getSession(this.ctx.projectName, normalizedSlot);
76
+ if (!session || !session.isAlive()) {
77
+ throw new Error(`No live PTY session for ${normalizedSlot}`);
78
+ }
79
+ const { runId } = this.manager.resumeRun(this.ctx.projectName, normalizedSlot, prompt);
80
+ const info = this.manager.inspect(this.ctx.projectName, normalizedSlot);
81
+ const tool = session.tool;
82
+ const record = this.buildSessionRecord(normalizedSlot, info, tool, session.cwd, {
83
+ runId,
84
+ status: 'running',
85
+ promptPreview: previewPrompt(prompt),
86
+ startedAt: now(),
87
+ });
88
+ const state = readACPState(this.ctx.paths.acpStateFile);
89
+ state.sessions[normalizedSlot] = record;
90
+ state.updatedAt = now();
91
+ state.updatedBy = 'pty-resume-run';
92
+ writeACPState(this.ctx.paths.acpStateFile, state, state.updatedBy);
93
+ return record;
94
+ }
95
+ async inspect(slot) {
96
+ const state = readACPState(this.ctx.paths.acpStateFile);
97
+ if (slot) {
98
+ const normalizedSlot = this.normalizeSlot(slot);
99
+ const info = this.manager.inspect(this.ctx.projectName, normalizedSlot);
100
+ if (info) {
101
+ this.syncSessionRecord(state, normalizedSlot, info);
102
+ }
103
+ }
104
+ else {
105
+ // Inspect all slots
106
+ for (const [slotName, record] of Object.entries(state.sessions)) {
107
+ const info = this.manager.inspect(this.ctx.projectName, slotName);
108
+ if (info) {
109
+ this.syncSessionRecord(state, slotName, info);
110
+ }
111
+ else {
112
+ // Session gone — mark offline
113
+ record.sessionState = 'offline';
114
+ record.status = 'idle';
115
+ record.updatedAt = now();
116
+ }
117
+ }
118
+ }
119
+ state.updatedAt = now();
120
+ state.updatedBy = 'pty-inspect';
121
+ writeACPState(this.ctx.paths.acpStateFile, state, state.updatedBy);
122
+ return state;
123
+ }
124
+ async stopSession(slot) {
125
+ const normalizedSlot = this.normalizeSlot(slot);
126
+ this.manager.killSession(this.ctx.projectName, normalizedSlot);
127
+ const state = readACPState(this.ctx.paths.acpStateFile);
128
+ if (state.sessions[normalizedSlot]) {
129
+ state.sessions[normalizedSlot].sessionState = 'offline';
130
+ state.sessions[normalizedSlot].status = 'idle';
131
+ state.sessions[normalizedSlot].updatedAt = now();
132
+ }
133
+ state.updatedAt = now();
134
+ state.updatedBy = 'pty-stop';
135
+ writeACPState(this.ctx.paths.acpStateFile, state, state.updatedBy);
136
+ }
137
+ /**
138
+ * Wait for the current run on a slot to complete.
139
+ */
140
+ async waitForRunComplete(slot, timeoutMs) {
141
+ const normalizedSlot = this.normalizeSlot(slot);
142
+ return this.manager.waitForRunComplete(this.ctx.projectName, normalizedSlot, timeoutMs);
143
+ }
144
+ /**
145
+ * Send a response to a waiting_input prompt.
146
+ */
147
+ respond(slot, response) {
148
+ const normalizedSlot = this.normalizeSlot(slot);
149
+ this.manager.respond(this.ctx.projectName, normalizedSlot, response);
150
+ }
151
+ /**
152
+ * Get the underlying PTYSessionManager (for direct access if needed).
153
+ */
154
+ getManager() {
155
+ return this.manager;
156
+ }
157
+ // ─── Internal ─────────────────────────────────────────────
158
+ normalizeSlot(slot) {
159
+ return slot.startsWith('worker-') ? slot : `worker-${slot}`;
160
+ }
161
+ defaultTool() {
162
+ return (this.ctx.config.raw.ACP_AGENT || this.ctx.config.WORKER_TOOL || 'claude');
163
+ }
164
+ buildSessionRecord(slot, info, tool, cwd, run) {
165
+ const isSessionInfo = 'state' in info;
166
+ const state = isSessionInfo ? info.state : info.getState();
167
+ const pid = isSessionInfo ? info.pid : info.pid;
168
+ const sessionId = isSessionInfo ? info.sessionId : info.sessionId;
169
+ const alive = isSessionInfo ? info.alive : info.isAlive();
170
+ const buffer = isSessionInfo ? info.buffer : info.getBuffer(30);
171
+ const sessionState = !alive ? 'offline' :
172
+ state === 'busy' || state === 'waiting_input' ? 'busy' :
173
+ state === 'ready' ? 'ready' :
174
+ 'booting';
175
+ const slotStatus = state === 'busy' ? 'active' :
176
+ state === 'waiting_input' ? 'active' :
177
+ 'idle';
178
+ return {
179
+ slot,
180
+ tool,
181
+ sessionId,
182
+ sessionName: sessionId,
183
+ cwd,
184
+ status: slotStatus,
185
+ sessionState,
186
+ currentRun: run ? {
187
+ runId: run.runId,
188
+ status: run.status,
189
+ promptPreview: run.promptPreview,
190
+ startedAt: run.startedAt,
191
+ updatedAt: now(),
192
+ completedAt: null,
193
+ } : null,
194
+ createdAt: now(),
195
+ updatedAt: now(),
196
+ lastSeenAt: now(),
197
+ lastPaneText: buffer,
198
+ };
199
+ }
200
+ syncSessionRecord(state, slotName, info) {
201
+ const existing = state.sessions[slotName];
202
+ if (!existing)
203
+ return;
204
+ existing.sessionState = info.alive
205
+ ? (info.state === 'busy' || info.state === 'waiting_input' ? 'busy' : info.state === 'ready' ? 'ready' : 'booting')
206
+ : 'offline';
207
+ existing.status = info.state === 'busy' || info.state === 'waiting_input' ? 'active' : 'idle';
208
+ existing.lastSeenAt = now();
209
+ existing.lastPaneText = info.buffer;
210
+ existing.updatedAt = now();
211
+ // Update run status if run completed
212
+ if (existing.currentRun && info.state === 'ready' && existing.status === 'idle') {
213
+ existing.currentRun.status = 'completed';
214
+ existing.currentRun.completedAt = now();
215
+ existing.currentRun.updatedAt = now();
216
+ }
217
+ }
218
+ }
219
+ //# sourceMappingURL=PTYAgentRuntime.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"PTYAgentRuntime.js","sourceRoot":"","sources":["../../src/providers/PTYAgentRuntime.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,17 @@
1
+ /**
2
+ * ClaudeOutputParser — real-time stream parser for Claude Code interactive output.
3
+ *
4
+ * Detects state transitions by matching patterns in the stripped-ANSI text stream.
5
+ * Fed by PTYSession.onData → stripAnsi → parser.feed()
6
+ */
7
+ import type { PTYSession, OutputParser } from '../../manager/pty-session.js';
8
+ export declare class ClaudeOutputParser implements OutputParser {
9
+ private accumulated;
10
+ private lastPromptAt;
11
+ reset(): void;
12
+ feed(chunk: string, session: PTYSession): void;
13
+ private hasPrompt;
14
+ private hasPromptInChunk;
15
+ private hasBusyIndicator;
16
+ }
17
+ //# sourceMappingURL=claude-parser.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"claude-parser.d.ts","sourceRoot":"","sources":["../../../src/providers/parsers/claude-parser.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,OAAO,KAAK,EAAE,UAAU,EAAE,YAAY,EAAqB,MAAM,8BAA8B,CAAC;AAIhG,qBAAa,kBAAmB,YAAW,YAAY;IACrD,OAAO,CAAC,WAAW,CAAM;IACzB,OAAO,CAAC,YAAY,CAAK;IAEzB,KAAK,IAAI,IAAI;IAKb,IAAI,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,UAAU,GAAG,IAAI;IAqG9C,OAAO,CAAC,SAAS;IAKjB,OAAO,CAAC,gBAAgB;IAKxB,OAAO,CAAC,gBAAgB;CAIzB"}
@@ -0,0 +1,112 @@
1
+ const DANGEROUS_RE = /rm\s+-rf|git\s+push\s+--force|DROP\s+TABLE|DELETE\s+FROM|TRUNCATE|format\s+c:|dd\s+if=/i;
2
+ export class ClaudeOutputParser {
3
+ accumulated = '';
4
+ lastPromptAt = 0;
5
+ reset() {
6
+ this.accumulated = '';
7
+ this.lastPromptAt = 0;
8
+ }
9
+ feed(chunk, session) {
10
+ this.accumulated += chunk;
11
+ const state = session.getState();
12
+ // ── booting → ready (prompt appears for the first time) ──
13
+ if (state === 'booting') {
14
+ // Check both accumulated and current chunk for prompt
15
+ if (this.hasPrompt() || this.hasPromptInChunk(chunk)) {
16
+ session.setState('ready');
17
+ this.lastPromptAt = Date.now();
18
+ this.accumulated = '';
19
+ return;
20
+ }
21
+ // Also detect "bypass permissions" as ready indicator
22
+ if (/bypass permissions/i.test(this.accumulated)) {
23
+ session.setState('ready');
24
+ this.lastPromptAt = Date.now();
25
+ this.accumulated = '';
26
+ return;
27
+ }
28
+ // Trust prompt during boot
29
+ if (this.accumulated.includes('Yes, I trust this folder') ||
30
+ this.accumulated.includes('trust this folder')) {
31
+ session.setState('waiting_input');
32
+ session.emit('waiting-input', {
33
+ type: 'trust',
34
+ prompt: 'Trust this folder?',
35
+ options: ['Yes', 'No'],
36
+ dangerous: false,
37
+ timestamp: new Date().toISOString(),
38
+ });
39
+ this.accumulated = '';
40
+ return;
41
+ }
42
+ return;
43
+ }
44
+ // ── Permission / confirmation prompts (any state) ──
45
+ const permMatch = this.accumulated.match(/\? Allow[:\s]+(.+?)(?:\n|$)/);
46
+ if (permMatch) {
47
+ const promptText = permMatch[1].trim();
48
+ session.setState('waiting_input');
49
+ session.emit('waiting-input', {
50
+ type: 'permission',
51
+ prompt: promptText,
52
+ dangerous: DANGEROUS_RE.test(promptText),
53
+ timestamp: new Date().toISOString(),
54
+ });
55
+ this.accumulated = '';
56
+ return;
57
+ }
58
+ if (/Enter to confirm|Esc to cancel|y\/n\]?\s*$/i.test(this.accumulated)) {
59
+ const lines = this.accumulated.split('\n').filter(Boolean);
60
+ const promptText = lines[lines.length - 1]?.trim() || 'Confirmation required';
61
+ session.setState('waiting_input');
62
+ session.emit('waiting-input', {
63
+ type: 'confirmation',
64
+ prompt: promptText,
65
+ dangerous: DANGEROUS_RE.test(this.accumulated),
66
+ timestamp: new Date().toISOString(),
67
+ });
68
+ this.accumulated = '';
69
+ return;
70
+ }
71
+ // ── waiting_input → ready (user responded, prompt came back) ──
72
+ if (state === 'waiting_input' && this.hasPrompt()) {
73
+ session.setState('ready');
74
+ this.lastPromptAt = Date.now();
75
+ this.accumulated = '';
76
+ return;
77
+ }
78
+ // ── ready → busy (content appearing after prompt = Worker started working) ──
79
+ if (state === 'ready' && this.hasBusyIndicator(chunk)) {
80
+ session.setState('busy');
81
+ }
82
+ // ── busy → ready (prompt reappeared = run completed) ──
83
+ if (state === 'busy' && (this.hasPrompt() || this.hasPromptInChunk(chunk))) {
84
+ const runId = session.getRunId();
85
+ if (runId) {
86
+ session.emit('run-completed', runId);
87
+ }
88
+ session.setState('ready');
89
+ this.lastPromptAt = Date.now();
90
+ this.accumulated = '';
91
+ return;
92
+ }
93
+ // Prevent memory leak
94
+ if (this.accumulated.length > 50_000) {
95
+ this.accumulated = this.accumulated.slice(-10_000);
96
+ }
97
+ }
98
+ // ── Pattern matchers ──
99
+ hasPrompt() {
100
+ // Claude Code prompt: ❯ or > at end of a line, or bypass permissions indicator
101
+ return /[❯>]\s*$/m.test(this.accumulated) || /bypass permissions/i.test(this.accumulated);
102
+ }
103
+ hasPromptInChunk(chunk) {
104
+ // Check raw chunk for prompt characters (may have ANSI around them)
105
+ return chunk.includes('❯') || chunk.includes('bypass permissions');
106
+ }
107
+ hasBusyIndicator(chunk) {
108
+ // Spinner, tool calls, or working indicators
109
+ return /[●◐◑◒◓]|Working|Thinking|Read|Write|Bash|Edit|Search|Glob|Agent/.test(chunk);
110
+ }
111
+ }
112
+ //# sourceMappingURL=claude-parser.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"claude-parser.js","sourceRoot":"","sources":["../../../src/providers/parsers/claude-parser.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,12 @@
1
+ /**
2
+ * CodexOutputParser — real-time stream parser for Codex CLI interactive output.
3
+ */
4
+ import type { PTYSession, OutputParser } from '../../manager/pty-session.js';
5
+ export declare class CodexOutputParser implements OutputParser {
6
+ private accumulated;
7
+ reset(): void;
8
+ feed(chunk: string, session: PTYSession): void;
9
+ private hasPrompt;
10
+ private hasBusyIndicator;
11
+ }
12
+ //# sourceMappingURL=codex-parser.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"codex-parser.d.ts","sourceRoot":"","sources":["../../../src/providers/parsers/codex-parser.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,OAAO,KAAK,EAAE,UAAU,EAAE,YAAY,EAAqB,MAAM,8BAA8B,CAAC;AAIhG,qBAAa,iBAAkB,YAAW,YAAY;IACpD,OAAO,CAAC,WAAW,CAAM;IAEzB,KAAK,IAAI,IAAI;IAIb,IAAI,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,UAAU,GAAG,IAAI;IAsE9C,OAAO,CAAC,SAAS;IAKjB,OAAO,CAAC,gBAAgB;CAGzB"}
@@ -0,0 +1,77 @@
1
+ const DANGEROUS_RE = /rm\s+-rf|git\s+push\s+--force|DROP\s+TABLE|DELETE\s+FROM|TRUNCATE/i;
2
+ export class CodexOutputParser {
3
+ accumulated = '';
4
+ reset() {
5
+ this.accumulated = '';
6
+ }
7
+ feed(chunk, session) {
8
+ this.accumulated += chunk;
9
+ const state = session.getState();
10
+ // ── booting → ready ──
11
+ if (state === 'booting') {
12
+ if (this.hasPrompt()) {
13
+ session.setState('ready');
14
+ this.accumulated = '';
15
+ return;
16
+ }
17
+ // Trust/sandbox prompt during boot
18
+ if (/trust|sandbox|approve/i.test(this.accumulated) && /\[y\/n\]|Enter/i.test(this.accumulated)) {
19
+ session.setState('waiting_input');
20
+ session.emit('waiting-input', {
21
+ type: 'trust',
22
+ prompt: 'Codex trust/sandbox prompt',
23
+ dangerous: false,
24
+ timestamp: new Date().toISOString(),
25
+ });
26
+ this.accumulated = '';
27
+ return;
28
+ }
29
+ return;
30
+ }
31
+ // ── Permission prompts ──
32
+ const permMatch = this.accumulated.match(/\? (Allow|Approve|Execute)[:\s]+(.+?)(?:\n|$)/);
33
+ if (permMatch) {
34
+ const promptText = permMatch[2].trim();
35
+ session.setState('waiting_input');
36
+ session.emit('waiting-input', {
37
+ type: 'permission',
38
+ prompt: promptText,
39
+ dangerous: DANGEROUS_RE.test(promptText),
40
+ timestamp: new Date().toISOString(),
41
+ });
42
+ this.accumulated = '';
43
+ return;
44
+ }
45
+ // ── waiting_input → ready ──
46
+ if (state === 'waiting_input' && this.hasPrompt()) {
47
+ session.setState('ready');
48
+ this.accumulated = '';
49
+ return;
50
+ }
51
+ // ── ready → busy ──
52
+ if (state === 'ready' && this.hasBusyIndicator(chunk)) {
53
+ session.setState('busy');
54
+ }
55
+ // ── busy → ready (run completed) ──
56
+ if (state === 'busy' && this.hasPrompt()) {
57
+ const runId = session.getRunId();
58
+ if (runId) {
59
+ session.emit('run-completed', runId);
60
+ }
61
+ session.setState('ready');
62
+ this.accumulated = '';
63
+ return;
64
+ }
65
+ if (this.accumulated.length > 50_000) {
66
+ this.accumulated = this.accumulated.slice(-10_000);
67
+ }
68
+ }
69
+ hasPrompt() {
70
+ // Codex prompt: $ or ❯ at end of line
71
+ return /[$❯>]\s*$/.test(this.accumulated.trimEnd());
72
+ }
73
+ hasBusyIndicator(chunk) {
74
+ return /Running|Thinking|Executing|apply_patch|Searching|Reading/.test(chunk);
75
+ }
76
+ }
77
+ //# sourceMappingURL=codex-parser.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"codex-parser.js","sourceRoot":"","sources":["../../../src/providers/parsers/codex-parser.ts"],"names":[],"mappings":"AAKA,MAAM,YAAY,GAAG,oEAAoE,CAAC;AAE1F,MAAM,OAAO,iBAAiB;IACpB,WAAW,GAAG,EAAE,CAAC;IAEzB,KAAK;QACH,IAAI,CAAC,WAAW,GAAG,EAAE,CAAC;IACxB,CAAC;IAED,IAAI,CAAC,KAAa,EAAE,OAAmB;QACrC,IAAI,CAAC,WAAW,IAAI,KAAK,CAAC;QAE1B,MAAM,KAAK,GAAG,OAAO,CAAC,QAAQ,EAAE,CAAC;QAEjC,wBAAwB;QACxB,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;YACxB,IAAI,IAAI,CAAC,SAAS,EAAE,EAAE,CAAC;gBACrB,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC;gBAC1B,IAAI,CAAC,WAAW,GAAG,EAAE,CAAC;gBACtB,OAAO;YACT,CAAC;YACD,mCAAmC;YACnC,IAAI,wBAAwB,CAAC,IAAI,CAAC,IAAI,CAAC,WAAW,CAAC,IAAI,iBAAiB,CAAC,IAAI,CAAC,IAAI,CAAC,WAAW,CAAC,EAAE,CAAC;gBAChG,OAAO,CAAC,QAAQ,CAAC,eAAe,CAAC,CAAC;gBAClC,OAAO,CAAC,IAAI,CAAC,eAAe,EAAE;oBAC5B,IAAI,EAAE,OAAO;oBACb,MAAM,EAAE,4BAA4B;oBACpC,SAAS,EAAE,KAAK;oBAChB,SAAS,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;iBACR,CAAC,CAAC;gBAC/B,IAAI,CAAC,WAAW,GAAG,EAAE,CAAC;gBACtB,OAAO;YACT,CAAC;YACD,OAAO;QACT,CAAC;QAED,2BAA2B;QAC3B,MAAM,SAAS,GAAG,IAAI,CAAC,WAAW,CAAC,KAAK,CAAC,+CAA+C,CAAC,CAAC;QAC1F,IAAI,SAAS,EAAE,CAAC;YACd,MAAM,UAAU,GAAG,SAAS,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;YACvC,OAAO,CAAC,QAAQ,CAAC,eAAe,CAAC,CAAC;YAClC,OAAO,CAAC,IAAI,CAAC,eAAe,EAAE;gBAC5B,IAAI,EAAE,YAAY;gBAClB,MAAM,EAAE,UAAU;gBAClB,SAAS,EAAE,YAAY,CAAC,IAAI,CAAC,UAAU,CAAC;gBACxC,SAAS,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;aACR,CAAC,CAAC;YAC/B,IAAI,CAAC,WAAW,GAAG,EAAE,CAAC;YACtB,OAAO;QACT,CAAC;QAED,8BAA8B;QAC9B,IAAI,KAAK,KAAK,eAAe,IAAI,IAAI,CAAC,SAAS,EAAE,EAAE,CAAC;YAClD,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC;YAC1B,IAAI,CAAC,WAAW,GAAG,EAAE,CAAC;YACtB,OAAO;QACT,CAAC;QAED,qBAAqB;QACrB,IAAI,KAAK,KAAK,OAAO,IAAI,IAAI,CAAC,gBAAgB,CAAC,KAAK,CAAC,EAAE,CAAC;YACtD,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;QAC3B,CAAC;QAED,qCAAqC;QACrC,IAAI,KAAK,KAAK,MAAM,IAAI,IAAI,CAAC,SAAS,EAAE,EAAE,CAAC;YACzC,MAAM,KAAK,GAAG,OAAO,CAAC,QAAQ,EAAE,CAAC;YACjC,IAAI,KAAK,EAAE,CAAC;gBACV,OAAO,CAAC,IAAI,CAAC,eAAe,EAAE,KAAK,CAAC,CAAC;YACvC,CAAC;YACD,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC;YAC1B,IAAI,CAAC,WAAW,GAAG,EAAE,CAAC;YACtB,OAAO;QACT,CAAC;QAED,IAAI,IAAI,CAAC,WAAW,CAAC,MAAM,GAAG,MAAM,EAAE,CAAC;YACrC,IAAI,CAAC,WAAW,GAAG,IAAI,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,CAAC;QACrD,CAAC;IACH,CAAC;IAEO,SAAS;QACf,sCAAsC;QACtC,OAAO,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC,WAAW,CAAC,OAAO,EAAE,CAAC,CAAC;IACtD,CAAC;IAEO,gBAAgB,CAAC,KAAa;QACpC,OAAO,0DAA0D,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IAChF,CAAC;CACF"}
@@ -1 +1 @@
1
- {"version":3,"file":"registry.d.ts","sourceRoot":"","sources":["../../src/providers/registry.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AACvD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,8BAA8B,CAAC;AAChE,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,iCAAiC,CAAC;AACtE,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,8BAA8B,CAAC;AAChE,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,2BAA2B,CAAC;AAC1D,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,+BAA+B,CAAC;AAUlE,OAAO,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AAGpD,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,aAAa,GAAG,WAAW,CAOpE;AAED,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,aAAa,GAAG,cAAc,CAkB1E;AAED,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,aAAa,GAAG,WAAW,CAEpE;AAED,wBAAgB,cAAc,CAAC,MAAM,EAAE,aAAa,GAAG,QAAQ,CAE9D;AAED,wBAAgB,kBAAkB,CAAC,GAAG,EAAE,cAAc,GAAG,YAAY,CAEpE"}
1
+ {"version":3,"file":"registry.d.ts","sourceRoot":"","sources":["../../src/providers/registry.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AACvD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,8BAA8B,CAAC;AAChE,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,iCAAiC,CAAC;AACtE,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,8BAA8B,CAAC;AAChE,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,2BAA2B,CAAC;AAC1D,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,+BAA+B,CAAC;AAUlE,OAAO,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AAIpD,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,aAAa,GAAG,WAAW,CAOpE;AAED,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,aAAa,GAAG,cAAc,CAkB1E;AAED,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,aAAa,GAAG,WAAW,CAEpE;AAED,wBAAgB,cAAc,CAAC,MAAM,EAAE,aAAa,GAAG,QAAQ,CAE9D;AAED,wBAAgB,kBAAkB,CAAC,GAAG,EAAE,cAAc,GAAG,YAAY,CAMpE"}
@@ -8,6 +8,7 @@ import { CodexTmuxProvider } from './CodexTmuxProvider.js';
8
8
  import { GitLabRepoBackend } from './GitLabRepoBackend.js';
9
9
  import { MatrixNotifier } from './MatrixNotifier.js';
10
10
  import { ACPWorkerRuntime } from './ACPWorkerRuntime.js';
11
+ import { PTYAgentRuntime } from './PTYAgentRuntime.js';
11
12
  export function createTaskBackend(config) {
12
13
  switch (config.PM_TOOL) {
13
14
  case 'plane': return new PlaneTaskBackend(config);
@@ -40,6 +41,10 @@ export function createNotifier(config) {
40
41
  return new MatrixNotifier(config);
41
42
  }
42
43
  export function createAgentRuntime(ctx) {
44
+ const transport = ctx.config.raw.WORKER_TRANSPORT || 'acp';
45
+ if (transport === 'pty') {
46
+ return new PTYAgentRuntime(ctx);
47
+ }
43
48
  return new ACPWorkerRuntime(ctx);
44
49
  }
45
50
  //# sourceMappingURL=registry.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"registry.js","sourceRoot":"","sources":["../../src/providers/registry.ts"],"names":[],"mappings":"AAMA,OAAO,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AACzD,OAAO,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;AAC3D,OAAO,EAAE,mBAAmB,EAAE,MAAM,0BAA0B,CAAC;AAC/D,OAAO,EAAE,mBAAmB,EAAE,MAAM,0BAA0B,CAAC;AAC/D,OAAO,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;AAC3D,OAAO,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAC;AAC7D,OAAO,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;AAC3D,OAAO,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;AAC3D,OAAO,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAErD,OAAO,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AAEzD,MAAM,UAAU,iBAAiB,CAAC,MAAqB;IACrD,QAAQ,MAAM,CAAC,OAAO,EAAE,CAAC;QACvB,KAAK,OAAO,CAAC,CAAC,OAAO,IAAI,gBAAgB,CAAC,MAAM,CAAC,CAAC;QAClD,KAAK,QAAQ,CAAC,CAAC,OAAO,IAAI,iBAAiB,CAAC,MAAM,CAAC,CAAC;QACpD,KAAK,UAAU,CAAC,CAAC,OAAO,IAAI,mBAAmB,CAAC,MAAM,CAAC,CAAC;QACxD,OAAO,CAAC,CAAC,MAAM,IAAI,KAAK,CAAC,oBAAoB,MAAM,CAAC,OAAO,EAAE,CAAC,CAAC;IACjE,CAAC;AACH,CAAC;AAED,MAAM,UAAU,oBAAoB,CAAC,MAAqB;IACxD,MAAM,IAAI,GAAG,MAAM,CAAC,WAAW,IAAI,OAAO,CAAC;IAC3C,MAAM,IAAI,GAAG,MAAM,CAAC,WAAW,IAAI,QAAQ,CAAC;IAE5C,IAAI,IAAI,KAAK,OAAO,EAAE,CAAC;QACrB,QAAQ,IAAI,EAAE,CAAC;YACb,KAAK,QAAQ,CAAC,CAAC,OAAO,IAAI,mBAAmB,CAAC,MAAM,CAAC,CAAC;YACtD,KAAK,OAAO,CAAC,CAAC,OAAO,IAAI,iBAAiB,CAAC,MAAM,CAAC,CAAC;YACnD,OAAO,CAAC,CAAC,MAAM,IAAI,KAAK,CAAC,wBAAwB,IAAI,EAAE,CAAC,CAAC;QAC3D,CAAC;IACH,CAAC;IAED,4CAA4C;IAC5C,QAAQ,IAAI,EAAE,CAAC;QACb,KAAK,QAAQ,CAAC,CAAC,OAAO,IAAI,kBAAkB,CAAC,MAAM,CAAC,CAAC;QACrD,KAAK,OAAO,CAAC,CAAC,OAAO,IAAI,iBAAiB,CAAC,MAAM,CAAC,CAAC;QACnD,OAAO,CAAC,CAAC,MAAM,IAAI,KAAK,CAAC,wBAAwB,IAAI,EAAE,CAAC,CAAC;IAC3D,CAAC;AACH,CAAC;AAED,MAAM,UAAU,iBAAiB,CAAC,MAAqB;IACrD,OAAO,IAAI,iBAAiB,CAAC,MAAM,CAAC,CAAC;AACvC,CAAC;AAED,MAAM,UAAU,cAAc,CAAC,MAAqB;IAClD,OAAO,IAAI,cAAc,CAAC,MAAM,CAAC,CAAC;AACpC,CAAC;AAED,MAAM,UAAU,kBAAkB,CAAC,GAAmB;IACpD,OAAO,IAAI,gBAAgB,CAAC,GAAG,CAAC,CAAC;AACnC,CAAC"}
1
+ {"version":3,"file":"registry.js","sourceRoot":"","sources":["../../src/providers/registry.ts"],"names":[],"mappings":"AAMA,OAAO,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AACzD,OAAO,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;AAC3D,OAAO,EAAE,mBAAmB,EAAE,MAAM,0BAA0B,CAAC;AAC/D,OAAO,EAAE,mBAAmB,EAAE,MAAM,0BAA0B,CAAC;AAC/D,OAAO,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;AAC3D,OAAO,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAC;AAC7D,OAAO,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;AAC3D,OAAO,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;AAC3D,OAAO,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAErD,OAAO,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AACzD,OAAO,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AAEvD,MAAM,UAAU,iBAAiB,CAAC,MAAqB;IACrD,QAAQ,MAAM,CAAC,OAAO,EAAE,CAAC;QACvB,KAAK,OAAO,CAAC,CAAC,OAAO,IAAI,gBAAgB,CAAC,MAAM,CAAC,CAAC;QAClD,KAAK,QAAQ,CAAC,CAAC,OAAO,IAAI,iBAAiB,CAAC,MAAM,CAAC,CAAC;QACpD,KAAK,UAAU,CAAC,CAAC,OAAO,IAAI,mBAAmB,CAAC,MAAM,CAAC,CAAC;QACxD,OAAO,CAAC,CAAC,MAAM,IAAI,KAAK,CAAC,oBAAoB,MAAM,CAAC,OAAO,EAAE,CAAC,CAAC;IACjE,CAAC;AACH,CAAC;AAED,MAAM,UAAU,oBAAoB,CAAC,MAAqB;IACxD,MAAM,IAAI,GAAG,MAAM,CAAC,WAAW,IAAI,OAAO,CAAC;IAC3C,MAAM,IAAI,GAAG,MAAM,CAAC,WAAW,IAAI,QAAQ,CAAC;IAE5C,IAAI,IAAI,KAAK,OAAO,EAAE,CAAC;QACrB,QAAQ,IAAI,EAAE,CAAC;YACb,KAAK,QAAQ,CAAC,CAAC,OAAO,IAAI,mBAAmB,CAAC,MAAM,CAAC,CAAC;YACtD,KAAK,OAAO,CAAC,CAAC,OAAO,IAAI,iBAAiB,CAAC,MAAM,CAAC,CAAC;YACnD,OAAO,CAAC,CAAC,MAAM,IAAI,KAAK,CAAC,wBAAwB,IAAI,EAAE,CAAC,CAAC;QAC3D,CAAC;IACH,CAAC;IAED,4CAA4C;IAC5C,QAAQ,IAAI,EAAE,CAAC;QACb,KAAK,QAAQ,CAAC,CAAC,OAAO,IAAI,kBAAkB,CAAC,MAAM,CAAC,CAAC;QACrD,KAAK,OAAO,CAAC,CAAC,OAAO,IAAI,iBAAiB,CAAC,MAAM,CAAC,CAAC;QACnD,OAAO,CAAC,CAAC,MAAM,IAAI,KAAK,CAAC,wBAAwB,IAAI,EAAE,CAAC,CAAC;IAC3D,CAAC;AACH,CAAC;AAED,MAAM,UAAU,iBAAiB,CAAC,MAAqB;IACrD,OAAO,IAAI,iBAAiB,CAAC,MAAM,CAAC,CAAC;AACvC,CAAC;AAED,MAAM,UAAU,cAAc,CAAC,MAAqB;IAClD,OAAO,IAAI,cAAc,CAAC,MAAM,CAAC,CAAC;AACpC,CAAC;AAED,MAAM,UAAU,kBAAkB,CAAC,GAAmB;IACpD,MAAM,SAAS,GAAG,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,gBAAgB,IAAI,KAAK,CAAC;IAC3D,IAAI,SAAS,KAAK,KAAK,EAAE,CAAC;QACxB,OAAO,IAAI,eAAe,CAAC,GAAG,CAAC,CAAC;IAClC,CAAC;IACD,OAAO,IAAI,gBAAgB,CAAC,GAAG,CAAC,CAAC;AACnC,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@coralai/sps-cli",
3
- "version": "0.22.0",
3
+ "version": "0.23.0",
4
4
  "description": "SPS CLI — AI-driven development pipeline orchestrator",
5
5
  "type": "module",
6
6
  "main": "dist/main.js",
@@ -35,5 +35,9 @@
35
35
  "@types/node": "^25.5.0",
36
36
  "tsx": "^4.21.0",
37
37
  "typescript": "^5.9.3"
38
+ },
39
+ "dependencies": {
40
+ "node-pty": "^1.1.0",
41
+ "strip-ansi": "^7.2.0"
38
42
  }
39
43
  }