cortex-agents 2.2.0 → 2.3.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.
@@ -0,0 +1,53 @@
1
+ export interface ExecResult {
2
+ stdout: string;
3
+ stderr: string;
4
+ exitCode: number;
5
+ }
6
+ export interface ExecOptions {
7
+ cwd?: string;
8
+ env?: NodeJS.ProcessEnv;
9
+ timeout?: number;
10
+ /** If true, resolve even on non-zero exit codes instead of rejecting. */
11
+ nothrow?: boolean;
12
+ }
13
+ /**
14
+ * Execute a command with array-based arguments (no shell invocation).
15
+ * Uses child_process.execFile which never spawns a shell, preventing injection.
16
+ *
17
+ * By default, rejects on non-zero exit codes. Pass `nothrow: true` to always resolve.
18
+ */
19
+ export declare function exec(cmd: string, args: string[], opts?: ExecOptions): Promise<ExecResult>;
20
+ /**
21
+ * Fire-and-forget spawn. Returns the ChildProcess for PID tracking.
22
+ * Uses child_process.spawn with shell: false (default).
23
+ */
24
+ export declare function spawn(cmd: string, args: string[], opts?: ExecOptions & {
25
+ stdio?: "ignore" | "pipe";
26
+ }): import("child_process").ChildProcess;
27
+ /**
28
+ * Shorthand for running a git command.
29
+ */
30
+ export declare function git(cwd: string, ...args: string[]): Promise<ExecResult>;
31
+ /**
32
+ * Shorthand for running a gh (GitHub CLI) command.
33
+ */
34
+ export declare function gh(cwd: string, ...args: string[]): Promise<ExecResult>;
35
+ /**
36
+ * Check if a binary exists in PATH.
37
+ */
38
+ export declare function which(bin: string): Promise<string | null>;
39
+ /**
40
+ * Send a signal to a process. Returns true if signal was sent, false if
41
+ * the process doesn't exist or we lack permissions.
42
+ */
43
+ export declare function kill(pid: number, signal?: NodeJS.Signals): boolean;
44
+ /**
45
+ * Check if a process is alive (sends signal 0 — no actual signal).
46
+ */
47
+ export declare function isAlive(pid: number): boolean;
48
+ /**
49
+ * Escape a string for safe inclusion in a shell command.
50
+ * Use only when array-based argument passing is impossible (e.g., osascript).
51
+ */
52
+ export declare function shellEscape(str: string): string;
53
+ //# sourceMappingURL=shell.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"shell.d.ts","sourceRoot":"","sources":["../../src/utils/shell.ts"],"names":[],"mappings":"AAEA,MAAM,WAAW,UAAU;IACzB,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,WAAW;IAC1B,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,GAAG,CAAC,EAAE,MAAM,CAAC,UAAU,CAAC;IACxB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,yEAAyE;IACzE,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AAED;;;;;GAKG;AACH,wBAAgB,IAAI,CAClB,GAAG,EAAE,MAAM,EACX,IAAI,EAAE,MAAM,EAAE,EACd,IAAI,GAAE,WAAgB,GACrB,OAAO,CAAC,UAAU,CAAC,CAqCrB;AAED;;;GAGG;AACH,wBAAgB,KAAK,CACnB,GAAG,EAAE,MAAM,EACX,IAAI,EAAE,MAAM,EAAE,EACd,IAAI,GAAE,WAAW,GAAG;IAAE,KAAK,CAAC,EAAE,QAAQ,GAAG,MAAM,CAAA;CAAO,wCAYvD;AAED;;GAEG;AACH,wBAAsB,GAAG,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,UAAU,CAAC,CAE7E;AAED;;GAEG;AACH,wBAAsB,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,UAAU,CAAC,CAE5E;AAED;;GAEG;AACH,wBAAsB,KAAK,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAQ/D;AAED;;;GAGG;AACH,wBAAgB,IAAI,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,GAAE,MAAM,CAAC,OAAmB,GAAG,OAAO,CAO7E;AAED;;GAEG;AACH,wBAAgB,OAAO,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAO5C;AAED;;;GAGG;AACH,wBAAgB,WAAW,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAS/C"}
@@ -0,0 +1,118 @@
1
+ import { execFile, spawn as cpSpawn } from "child_process";
2
+ /**
3
+ * Execute a command with array-based arguments (no shell invocation).
4
+ * Uses child_process.execFile which never spawns a shell, preventing injection.
5
+ *
6
+ * By default, rejects on non-zero exit codes. Pass `nothrow: true` to always resolve.
7
+ */
8
+ export function exec(cmd, args, opts = {}) {
9
+ return new Promise((resolve, reject) => {
10
+ execFile(cmd, args, {
11
+ cwd: opts.cwd,
12
+ env: opts.env ?? process.env,
13
+ timeout: opts.timeout ?? 30_000,
14
+ maxBuffer: 10 * 1024 * 1024,
15
+ }, (error, stdout, stderr) => {
16
+ const result = {
17
+ stdout: String(stdout ?? ""),
18
+ stderr: String(stderr ?? ""),
19
+ exitCode: error ? error.code ?? 1 : 0,
20
+ };
21
+ if (error) {
22
+ if (error.code === "ENOENT") {
23
+ reject(new Error(`Command not found: ${cmd}`));
24
+ return;
25
+ }
26
+ if (!opts.nothrow) {
27
+ const err = new Error(result.stderr || error.message);
28
+ err.exitCode = result.exitCode;
29
+ err.stdout = result.stdout;
30
+ err.stderr = result.stderr;
31
+ reject(err);
32
+ return;
33
+ }
34
+ }
35
+ resolve(result);
36
+ });
37
+ });
38
+ }
39
+ /**
40
+ * Fire-and-forget spawn. Returns the ChildProcess for PID tracking.
41
+ * Uses child_process.spawn with shell: false (default).
42
+ */
43
+ export function spawn(cmd, args, opts = {}) {
44
+ const stdio = opts.stdio ?? "ignore";
45
+ const child = cpSpawn(cmd, args, {
46
+ cwd: opts.cwd,
47
+ env: opts.env ?? process.env,
48
+ stdio: stdio === "pipe" ? ["ignore", "pipe", "pipe"] : "ignore",
49
+ detached: false,
50
+ });
51
+ // Prevent unhandled error crashes on spawn failure
52
+ child.on("error", () => { });
53
+ return child;
54
+ }
55
+ /**
56
+ * Shorthand for running a git command.
57
+ */
58
+ export async function git(cwd, ...args) {
59
+ return exec("git", ["-C", cwd, ...args]);
60
+ }
61
+ /**
62
+ * Shorthand for running a gh (GitHub CLI) command.
63
+ */
64
+ export async function gh(cwd, ...args) {
65
+ return exec("gh", args, { cwd });
66
+ }
67
+ /**
68
+ * Check if a binary exists in PATH.
69
+ */
70
+ export async function which(bin) {
71
+ try {
72
+ const result = await exec(process.platform === "win32" ? "where" : "which", [bin]);
73
+ const p = result.stdout.trim().split("\n")[0];
74
+ return p || null;
75
+ }
76
+ catch {
77
+ return null;
78
+ }
79
+ }
80
+ /**
81
+ * Send a signal to a process. Returns true if signal was sent, false if
82
+ * the process doesn't exist or we lack permissions.
83
+ */
84
+ export function kill(pid, signal = "SIGTERM") {
85
+ try {
86
+ process.kill(pid, signal);
87
+ return true;
88
+ }
89
+ catch {
90
+ return false;
91
+ }
92
+ }
93
+ /**
94
+ * Check if a process is alive (sends signal 0 — no actual signal).
95
+ */
96
+ export function isAlive(pid) {
97
+ try {
98
+ process.kill(pid, 0);
99
+ return true;
100
+ }
101
+ catch {
102
+ return false;
103
+ }
104
+ }
105
+ /**
106
+ * Escape a string for safe inclusion in a shell command.
107
+ * Use only when array-based argument passing is impossible (e.g., osascript).
108
+ */
109
+ export function shellEscape(str) {
110
+ // Replace backslashes first, then other dangerous characters
111
+ return str
112
+ .replace(/\\/g, "\\\\")
113
+ .replace(/"/g, '\\"')
114
+ .replace(/'/g, "'\\''")
115
+ .replace(/`/g, "\\`")
116
+ .replace(/\$/g, "\\$")
117
+ .replace(/!/g, "\\!");
118
+ }
@@ -0,0 +1,66 @@
1
+ /**
2
+ * Terminal Driver System — Strategy pattern for cross-platform terminal tab management.
3
+ *
4
+ * Each supported terminal emulator implements the TerminalDriver interface for:
5
+ * - detect() — check if this is the active terminal
6
+ * - openTab() — open a new tab and return identifiers
7
+ * - closeTab() — close a tab by its identifiers (idempotent, never throws)
8
+ *
9
+ * Session data is persisted to `.cortex/.terminal-session` inside each worktree
10
+ * so tabs can be closed when the worktree is removed.
11
+ */
12
+ /** Persisted session data for an opened terminal tab. */
13
+ export interface TerminalSession {
14
+ /** Driver name (e.g., "iterm2", "kitty", "tmux", "pty") */
15
+ terminal: string;
16
+ platform: NodeJS.Platform;
17
+ sessionId?: string;
18
+ windowId?: string;
19
+ tabId?: string;
20
+ paneId?: string;
21
+ dbusPath?: string;
22
+ pid?: number;
23
+ ptyId?: string;
24
+ mode: "terminal" | "pty" | "background";
25
+ branch: string;
26
+ agent: string;
27
+ worktreePath: string;
28
+ startedAt: string;
29
+ }
30
+ /** Options passed to a driver's openTab() method. */
31
+ export interface TabOpenOptions {
32
+ worktreePath: string;
33
+ opencodeBin: string;
34
+ agent: string;
35
+ prompt: string;
36
+ branchName: string;
37
+ }
38
+ /** Common interface for all terminal drivers. */
39
+ export interface TerminalDriver {
40
+ readonly name: string;
41
+ detect(): boolean;
42
+ openTab(opts: TabOpenOptions): Promise<Partial<TerminalSession>>;
43
+ closeTab(session: TerminalSession): Promise<boolean>;
44
+ }
45
+ /** Persist terminal session data to the worktree's .cortex directory. */
46
+ export declare function writeSession(worktreePath: string, session: TerminalSession): void;
47
+ /** Read terminal session data from the worktree's .cortex directory. */
48
+ export declare function readSession(worktreePath: string): TerminalSession | null;
49
+ /**
50
+ * Detect the active terminal emulator and return the matching driver.
51
+ * Falls back to FallbackDriver if no specific terminal is detected.
52
+ */
53
+ export declare function detectDriver(): TerminalDriver;
54
+ /**
55
+ * Get a driver by name (used when closing a tab from a persisted session).
56
+ * Returns null if the driver name is unknown.
57
+ */
58
+ export declare function getDriverByName(name: string): TerminalDriver | null;
59
+ /**
60
+ * Close a terminal session using the appropriate driver.
61
+ * Handles all modes (terminal, pty, background) with PID fallback.
62
+ *
63
+ * This is the main entry point for worktree_remove cleanup.
64
+ */
65
+ export declare function closeSession(session: TerminalSession): Promise<boolean>;
66
+ //# sourceMappingURL=terminal.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"terminal.d.ts","sourceRoot":"","sources":["../../src/utils/terminal.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAQH,yDAAyD;AACzD,MAAM,WAAW,eAAe;IAC9B,2DAA2D;IAC3D,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC,QAAQ,CAAC;IAG1B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,KAAK,CAAC,EAAE,MAAM,CAAC;IAGf,IAAI,EAAE,UAAU,GAAG,KAAK,GAAG,YAAY,CAAC;IACxC,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;IACd,YAAY,EAAE,MAAM,CAAC;IACrB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,qDAAqD;AACrD,MAAM,WAAW,cAAc;IAC7B,YAAY,EAAE,MAAM,CAAC;IACrB,WAAW,EAAE,MAAM,CAAC;IACpB,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,iDAAiD;AACjD,MAAM,WAAW,cAAc;IAC7B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,MAAM,IAAI,OAAO,CAAC;IAClB,OAAO,CAAC,IAAI,EAAE,cAAc,GAAG,OAAO,CAAC,OAAO,CAAC,eAAe,CAAC,CAAC,CAAC;IACjE,QAAQ,CAAC,OAAO,EAAE,eAAe,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;CACtD;AAMD,yEAAyE;AACzE,wBAAgB,YAAY,CAC1B,YAAY,EAAE,MAAM,EACpB,OAAO,EAAE,eAAe,GACvB,IAAI,CASN;AAED,wEAAwE;AACxE,wBAAgB,WAAW,CACzB,YAAY,EAAE,MAAM,GACnB,eAAe,GAAG,IAAI,CAQxB;AA6kBD;;;GAGG;AACH,wBAAgB,YAAY,IAAI,cAAc,CAM7C;AAED;;;GAGG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,cAAc,GAAG,IAAI,CAEnE;AAED;;;;;GAKG;AACH,wBAAsB,YAAY,CAAC,OAAO,EAAE,eAAe,GAAG,OAAO,CAAC,OAAO,CAAC,CAY7E"}