@elhu/pit 0.1.1

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.
Files changed (192) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +380 -0
  3. package/dist/adapters/claude-code.d.ts +70 -0
  4. package/dist/adapters/claude-code.d.ts.map +1 -0
  5. package/dist/adapters/claude-code.js +166 -0
  6. package/dist/adapters/claude-code.js.map +1 -0
  7. package/dist/adapters/index.d.ts +16 -0
  8. package/dist/adapters/index.d.ts.map +1 -0
  9. package/dist/adapters/index.js +49 -0
  10. package/dist/adapters/index.js.map +1 -0
  11. package/dist/adapters/opencode.d.ts +53 -0
  12. package/dist/adapters/opencode.d.ts.map +1 -0
  13. package/dist/adapters/opencode.js +120 -0
  14. package/dist/adapters/opencode.js.map +1 -0
  15. package/dist/adapters/process-utils.d.ts +29 -0
  16. package/dist/adapters/process-utils.d.ts.map +1 -0
  17. package/dist/adapters/process-utils.js +96 -0
  18. package/dist/adapters/process-utils.js.map +1 -0
  19. package/dist/adapters/types.d.ts +41 -0
  20. package/dist/adapters/types.d.ts.map +1 -0
  21. package/dist/adapters/types.js +6 -0
  22. package/dist/adapters/types.js.map +1 -0
  23. package/dist/assets.generated.d.ts +13 -0
  24. package/dist/assets.generated.d.ts.map +1 -0
  25. package/dist/assets.generated.js +162 -0
  26. package/dist/assets.generated.js.map +1 -0
  27. package/dist/beads.d.ts +85 -0
  28. package/dist/beads.d.ts.map +1 -0
  29. package/dist/beads.js +120 -0
  30. package/dist/beads.js.map +1 -0
  31. package/dist/cli.d.ts +3 -0
  32. package/dist/cli.d.ts.map +1 -0
  33. package/dist/cli.js +39 -0
  34. package/dist/cli.js.map +1 -0
  35. package/dist/commands/add.d.ts +10 -0
  36. package/dist/commands/add.d.ts.map +1 -0
  37. package/dist/commands/add.js +58 -0
  38. package/dist/commands/add.js.map +1 -0
  39. package/dist/commands/cleanup.d.ts +13 -0
  40. package/dist/commands/cleanup.d.ts.map +1 -0
  41. package/dist/commands/cleanup.js +174 -0
  42. package/dist/commands/cleanup.js.map +1 -0
  43. package/dist/commands/daemon.d.ts +3 -0
  44. package/dist/commands/daemon.d.ts.map +1 -0
  45. package/dist/commands/daemon.js +162 -0
  46. package/dist/commands/daemon.js.map +1 -0
  47. package/dist/commands/init.d.ts +20 -0
  48. package/dist/commands/init.d.ts.map +1 -0
  49. package/dist/commands/init.js +125 -0
  50. package/dist/commands/init.js.map +1 -0
  51. package/dist/commands/install-keybinding.d.ts +61 -0
  52. package/dist/commands/install-keybinding.d.ts.map +1 -0
  53. package/dist/commands/install-keybinding.js +138 -0
  54. package/dist/commands/install-keybinding.js.map +1 -0
  55. package/dist/commands/install-status.d.ts +35 -0
  56. package/dist/commands/install-status.d.ts.map +1 -0
  57. package/dist/commands/install-status.js +115 -0
  58. package/dist/commands/install-status.js.map +1 -0
  59. package/dist/commands/log.d.ts +7 -0
  60. package/dist/commands/log.d.ts.map +1 -0
  61. package/dist/commands/log.js +60 -0
  62. package/dist/commands/log.js.map +1 -0
  63. package/dist/commands/pause.d.ts +12 -0
  64. package/dist/commands/pause.d.ts.map +1 -0
  65. package/dist/commands/pause.js +47 -0
  66. package/dist/commands/pause.js.map +1 -0
  67. package/dist/commands/resume.d.ts +12 -0
  68. package/dist/commands/resume.d.ts.map +1 -0
  69. package/dist/commands/resume.js +59 -0
  70. package/dist/commands/resume.js.map +1 -0
  71. package/dist/commands/shared.d.ts +7 -0
  72. package/dist/commands/shared.d.ts.map +1 -0
  73. package/dist/commands/shared.js +56 -0
  74. package/dist/commands/shared.js.map +1 -0
  75. package/dist/commands/start.d.ts +12 -0
  76. package/dist/commands/start.d.ts.map +1 -0
  77. package/dist/commands/start.js +274 -0
  78. package/dist/commands/start.js.map +1 -0
  79. package/dist/commands/status.d.ts +24 -0
  80. package/dist/commands/status.d.ts.map +1 -0
  81. package/dist/commands/status.js +101 -0
  82. package/dist/commands/status.js.map +1 -0
  83. package/dist/commands/stop.d.ts +11 -0
  84. package/dist/commands/stop.d.ts.map +1 -0
  85. package/dist/commands/stop.js +52 -0
  86. package/dist/commands/stop.js.map +1 -0
  87. package/dist/commands/teardown.d.ts +15 -0
  88. package/dist/commands/teardown.d.ts.map +1 -0
  89. package/dist/commands/teardown.js +72 -0
  90. package/dist/commands/teardown.js.map +1 -0
  91. package/dist/config.d.ts +58 -0
  92. package/dist/config.d.ts.map +1 -0
  93. package/dist/config.js +129 -0
  94. package/dist/config.js.map +1 -0
  95. package/dist/daemon/client.d.ts +38 -0
  96. package/dist/daemon/client.d.ts.map +1 -0
  97. package/dist/daemon/client.js +254 -0
  98. package/dist/daemon/client.js.map +1 -0
  99. package/dist/daemon/context.d.ts +63 -0
  100. package/dist/daemon/context.d.ts.map +1 -0
  101. package/dist/daemon/context.js +14 -0
  102. package/dist/daemon/context.js.map +1 -0
  103. package/dist/daemon/handlers.d.ts +79 -0
  104. package/dist/daemon/handlers.d.ts.map +1 -0
  105. package/dist/daemon/handlers.js +1260 -0
  106. package/dist/daemon/handlers.js.map +1 -0
  107. package/dist/daemon/index.d.ts +6 -0
  108. package/dist/daemon/index.d.ts.map +1 -0
  109. package/dist/daemon/index.js +7 -0
  110. package/dist/daemon/index.js.map +1 -0
  111. package/dist/daemon/lifecycle.d.ts +56 -0
  112. package/dist/daemon/lifecycle.d.ts.map +1 -0
  113. package/dist/daemon/lifecycle.js +341 -0
  114. package/dist/daemon/lifecycle.js.map +1 -0
  115. package/dist/daemon/protocol.d.ts +174 -0
  116. package/dist/daemon/protocol.d.ts.map +1 -0
  117. package/dist/daemon/protocol.js +3 -0
  118. package/dist/daemon/protocol.js.map +1 -0
  119. package/dist/daemon/recovery.d.ts +37 -0
  120. package/dist/daemon/recovery.d.ts.map +1 -0
  121. package/dist/daemon/recovery.js +197 -0
  122. package/dist/daemon/recovery.js.map +1 -0
  123. package/dist/daemon/server.d.ts +31 -0
  124. package/dist/daemon/server.d.ts.map +1 -0
  125. package/dist/daemon/server.js +294 -0
  126. package/dist/daemon/server.js.map +1 -0
  127. package/dist/daemon/socket.d.ts +18 -0
  128. package/dist/daemon/socket.d.ts.map +1 -0
  129. package/dist/daemon/socket.js +36 -0
  130. package/dist/daemon/socket.js.map +1 -0
  131. package/dist/daemon/state.d.ts +60 -0
  132. package/dist/daemon/state.d.ts.map +1 -0
  133. package/dist/daemon/state.js +156 -0
  134. package/dist/daemon/state.js.map +1 -0
  135. package/dist/daemon/systemd.d.ts +19 -0
  136. package/dist/daemon/systemd.d.ts.map +1 -0
  137. package/dist/daemon/systemd.js +131 -0
  138. package/dist/daemon/systemd.js.map +1 -0
  139. package/dist/hooks/claude-code-hook.d.ts +32 -0
  140. package/dist/hooks/claude-code-hook.d.ts.map +1 -0
  141. package/dist/hooks/claude-code-hook.js +112 -0
  142. package/dist/hooks/claude-code-hook.js.map +1 -0
  143. package/dist/instructions-template.d.ts +9 -0
  144. package/dist/instructions-template.d.ts.map +1 -0
  145. package/dist/instructions-template.js +123 -0
  146. package/dist/instructions-template.js.map +1 -0
  147. package/dist/logger.d.ts +25 -0
  148. package/dist/logger.d.ts.map +1 -0
  149. package/dist/logger.js +44 -0
  150. package/dist/logger.js.map +1 -0
  151. package/dist/loop.d.ts +88 -0
  152. package/dist/loop.d.ts.map +1 -0
  153. package/dist/loop.js +161 -0
  154. package/dist/loop.js.map +1 -0
  155. package/dist/orchestrator-instructions-template.d.ts +13 -0
  156. package/dist/orchestrator-instructions-template.d.ts.map +1 -0
  157. package/dist/orchestrator-instructions-template.js +147 -0
  158. package/dist/orchestrator-instructions-template.js.map +1 -0
  159. package/dist/output.d.ts +12 -0
  160. package/dist/output.d.ts.map +1 -0
  161. package/dist/output.js +25 -0
  162. package/dist/output.js.map +1 -0
  163. package/dist/plugin/pit.js +57 -0
  164. package/dist/session.d.ts +55 -0
  165. package/dist/session.d.ts.map +1 -0
  166. package/dist/session.js +135 -0
  167. package/dist/session.js.map +1 -0
  168. package/dist/setup.d.ts +92 -0
  169. package/dist/setup.d.ts.map +1 -0
  170. package/dist/setup.js +382 -0
  171. package/dist/setup.js.map +1 -0
  172. package/dist/shell-quote.d.ts +16 -0
  173. package/dist/shell-quote.d.ts.map +1 -0
  174. package/dist/shell-quote.js +18 -0
  175. package/dist/shell-quote.js.map +1 -0
  176. package/dist/signals.d.ts +17 -0
  177. package/dist/signals.d.ts.map +1 -0
  178. package/dist/signals.js +26 -0
  179. package/dist/signals.js.map +1 -0
  180. package/dist/state-machine.d.ts +74 -0
  181. package/dist/state-machine.d.ts.map +1 -0
  182. package/dist/state-machine.js +153 -0
  183. package/dist/state-machine.js.map +1 -0
  184. package/dist/tmux.d.ts +101 -0
  185. package/dist/tmux.d.ts.map +1 -0
  186. package/dist/tmux.js +208 -0
  187. package/dist/tmux.js.map +1 -0
  188. package/dist/worktree.d.ts +33 -0
  189. package/dist/worktree.d.ts.map +1 -0
  190. package/dist/worktree.js +116 -0
  191. package/dist/worktree.js.map +1 -0
  192. package/package.json +66 -0
@@ -0,0 +1,58 @@
1
+ /**
2
+ * Configuration module for pit.
3
+ *
4
+ * Reads .pit.json from the project root and merges with CLI flags and defaults.
5
+ * Exported for use by the daemon and CLI commands.
6
+ */
7
+ /**
8
+ * User-facing configuration loaded from .pit.json.
9
+ * All fields are optional — missing fields fall back to DEFAULT_CONFIG.
10
+ */
11
+ export interface PitConfig {
12
+ agent?: "auto" | "opencode" | "claude-code";
13
+ worktreeDir?: string;
14
+ baseBranch?: string;
15
+ tmuxSession?: string;
16
+ /** Inline prompt template string (NOT a file path). */
17
+ promptTemplate?: string;
18
+ /** Delay in ms before clearing agent context after ticket completion. */
19
+ clearDelay?: number;
20
+ /** Delay in ms before starting the agent after setup. */
21
+ initDelay?: number;
22
+ /** Ticket timeout in minutes, or null to disable. */
23
+ ticketTimeout?: number | null;
24
+ /** Model to use for the agent, or null to use agent default. */
25
+ model?: string | null;
26
+ }
27
+ /**
28
+ * Fully resolved configuration — every field is required (no optionals).
29
+ * Produced by resolveConfig() after merging CLI flags > file > defaults.
30
+ */
31
+ export interface ResolvedConfig {
32
+ agent: "auto" | "opencode" | "claude-code";
33
+ worktreeDir: string;
34
+ baseBranch: string;
35
+ tmuxSession: string;
36
+ promptTemplate: string;
37
+ clearDelay: number;
38
+ initDelay: number;
39
+ ticketTimeout: number | null;
40
+ model: string | null;
41
+ }
42
+ export declare const DEFAULT_CONFIG: ResolvedConfig;
43
+ /**
44
+ * Load configuration from `<projectRoot>/.pit.json`.
45
+ *
46
+ * - Returns `{}` when the file is missing or unparseable (logs a warning).
47
+ * - Warns on unknown fields (typo detection).
48
+ * - Warns and drops fields with invalid types (uses default instead).
49
+ */
50
+ export declare function loadPitConfig(projectRoot: string): PitConfig;
51
+ /**
52
+ * Three-tier merge: CLI flags > .pit.json values > DEFAULT_CONFIG.
53
+ *
54
+ * `cliFlags` should contain ONLY fields the user explicitly set on the CLI
55
+ * (use Commander's `command.getOptionValueSource(name) === 'cli'` to filter).
56
+ */
57
+ export declare function resolveConfig(cliFlags: Partial<PitConfig>, fileConfig: PitConfig): ResolvedConfig;
58
+ //# sourceMappingURL=config.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAYH;;;GAGG;AACH,MAAM,WAAW,SAAS;IACxB,KAAK,CAAC,EAAE,MAAM,GAAG,UAAU,GAAG,aAAa,CAAC;IAC5C,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,uDAAuD;IACvD,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,yEAAyE;IACzE,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,yDAAyD;IACzD,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,qDAAqD;IACrD,aAAa,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B,gEAAgE;IAChE,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CACvB;AAED;;;GAGG;AACH,MAAM,WAAW,cAAc;IAC7B,KAAK,EAAE,MAAM,GAAG,UAAU,GAAG,aAAa,CAAC;IAC3C,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,EAAE,MAAM,CAAC;IACnB,WAAW,EAAE,MAAM,CAAC;IACpB,cAAc,EAAE,MAAM,CAAC;IACvB,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;IAClB,aAAa,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;CACtB;AAMD,eAAO,MAAM,cAAc,EAAE,cAU5B,CAAC;AAyBF;;;;;;GAMG;AACH,wBAAgB,aAAa,CAAC,WAAW,EAAE,MAAM,GAAG,SAAS,CAsD5D;AAMD;;;;;GAKG;AACH,wBAAgB,aAAa,CAAC,QAAQ,EAAE,OAAO,CAAC,SAAS,CAAC,EAAE,UAAU,EAAE,SAAS,GAAG,cAAc,CAoBjG"}
package/dist/config.js ADDED
@@ -0,0 +1,129 @@
1
+ /**
2
+ * Configuration module for pit.
3
+ *
4
+ * Reads .pit.json from the project root and merges with CLI flags and defaults.
5
+ * Exported for use by the daemon and CLI commands.
6
+ */
7
+ import * as fs from "node:fs";
8
+ import * as path from "node:path";
9
+ import { createLogger } from "./logger.js";
10
+ const logger = createLogger();
11
+ // ---------------------------------------------------------------------------
12
+ // Defaults
13
+ // ---------------------------------------------------------------------------
14
+ export const DEFAULT_CONFIG = {
15
+ agent: "auto",
16
+ worktreeDir: ".worktrees",
17
+ baseBranch: "main",
18
+ tmuxSession: "pit",
19
+ promptTemplate: "",
20
+ clearDelay: 2000,
21
+ initDelay: 5000,
22
+ ticketTimeout: null,
23
+ model: null,
24
+ };
25
+ // ---------------------------------------------------------------------------
26
+ // Field validators
27
+ // ---------------------------------------------------------------------------
28
+ const VALID_AGENTS = new Set(["auto", "opencode", "claude-code"]);
29
+ /** Map of field name → runtime type-check predicate. */
30
+ const FIELD_VALIDATORS = {
31
+ agent: (v) => typeof v === "string" && VALID_AGENTS.has(v),
32
+ worktreeDir: (v) => typeof v === "string",
33
+ baseBranch: (v) => typeof v === "string",
34
+ tmuxSession: (v) => typeof v === "string",
35
+ promptTemplate: (v) => typeof v === "string",
36
+ clearDelay: (v) => typeof v === "number" && Number.isFinite(v),
37
+ initDelay: (v) => typeof v === "number" && Number.isFinite(v),
38
+ ticketTimeout: (v) => v === null || (typeof v === "number" && Number.isFinite(v)),
39
+ model: (v) => v === null || typeof v === "string",
40
+ };
41
+ // ---------------------------------------------------------------------------
42
+ // loadPitConfig
43
+ // ---------------------------------------------------------------------------
44
+ /**
45
+ * Load configuration from `<projectRoot>/.pit.json`.
46
+ *
47
+ * - Returns `{}` when the file is missing or unparseable (logs a warning).
48
+ * - Warns on unknown fields (typo detection).
49
+ * - Warns and drops fields with invalid types (uses default instead).
50
+ */
51
+ export function loadPitConfig(projectRoot) {
52
+ const configPath = path.join(projectRoot, ".pit.json");
53
+ let raw;
54
+ try {
55
+ raw = fs.readFileSync(configPath, "utf8");
56
+ }
57
+ catch {
58
+ // File missing — perfectly fine, return empty config.
59
+ return {};
60
+ }
61
+ let parsed;
62
+ try {
63
+ parsed = JSON.parse(raw);
64
+ }
65
+ catch (error) {
66
+ logger.warn("Failed to parse .pit.json", {
67
+ error: String(error),
68
+ configPath,
69
+ });
70
+ return {};
71
+ }
72
+ if (typeof parsed !== "object" || parsed === null || Array.isArray(parsed)) {
73
+ logger.warn(".pit.json must be a JSON object", { configPath });
74
+ return {};
75
+ }
76
+ const obj = parsed;
77
+ const knownKeys = new Set(Object.keys(FIELD_VALIDATORS));
78
+ const result = {};
79
+ // Warn on unknown fields
80
+ for (const key of Object.keys(obj)) {
81
+ if (!knownKeys.has(key)) {
82
+ logger.warn(`Unknown field in .pit.json: "${key}"`, { configPath });
83
+ }
84
+ }
85
+ // Validate and pick known fields
86
+ for (const [key, validator] of Object.entries(FIELD_VALIDATORS)) {
87
+ const typedKey = key;
88
+ if (typedKey in obj) {
89
+ const value = obj[typedKey];
90
+ if (validator(value)) {
91
+ // Type assertion is safe — validator just confirmed the type.
92
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
93
+ result[typedKey] = value;
94
+ }
95
+ else {
96
+ logger.warn(`Invalid type for "${typedKey}" in .pit.json, ignoring`, { value, configPath });
97
+ }
98
+ }
99
+ }
100
+ return result;
101
+ }
102
+ // ---------------------------------------------------------------------------
103
+ // resolveConfig
104
+ // ---------------------------------------------------------------------------
105
+ /**
106
+ * Three-tier merge: CLI flags > .pit.json values > DEFAULT_CONFIG.
107
+ *
108
+ * `cliFlags` should contain ONLY fields the user explicitly set on the CLI
109
+ * (use Commander's `command.getOptionValueSource(name) === 'cli'` to filter).
110
+ */
111
+ export function resolveConfig(cliFlags, fileConfig) {
112
+ const resolved = { ...DEFAULT_CONFIG };
113
+ // Layer 1: file config overrides defaults
114
+ for (const key of Object.keys(FIELD_VALIDATORS)) {
115
+ if (key in fileConfig && fileConfig[key] !== undefined) {
116
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
117
+ resolved[key] = fileConfig[key];
118
+ }
119
+ }
120
+ // Layer 2: CLI flags override file config
121
+ for (const key of Object.keys(FIELD_VALIDATORS)) {
122
+ if (key in cliFlags && cliFlags[key] !== undefined) {
123
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
124
+ resolved[key] = cliFlags[key];
125
+ }
126
+ }
127
+ return resolved;
128
+ }
129
+ //# sourceMappingURL=config.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,38 @@
1
+ import type { DaemonRequest, DaemonResponse } from "./protocol.js";
2
+ /** Error classes for daemon connection failures */
3
+ export declare class DaemonConnectionError extends Error {
4
+ readonly code: "NO_SOCKET" | "CONNECTION_REFUSED" | "TIMEOUT";
5
+ constructor(message: string, code: "NO_SOCKET" | "CONNECTION_REFUSED" | "TIMEOUT");
6
+ }
7
+ export declare class DaemonVersionError extends Error {
8
+ readonly daemonVersion: string;
9
+ readonly clientVersion: string;
10
+ constructor(message: string, daemonVersion: string, clientVersion: string);
11
+ }
12
+ /** Result of daemon discovery */
13
+ export interface DaemonInfo {
14
+ socketPath: string;
15
+ running: boolean;
16
+ }
17
+ /** Connected client that can send requests */
18
+ export interface DaemonClientConnection {
19
+ send<T extends DaemonResponse>(request: DaemonRequest): Promise<T>;
20
+ close(): void;
21
+ }
22
+ /**
23
+ * Discover daemon for given project and session
24
+ */
25
+ export declare function discoverDaemon(projectRoot: string, tmuxSession?: string): Promise<DaemonInfo>;
26
+ /**
27
+ * Ensure daemon is running, start if needed
28
+ */
29
+ export declare function ensureDaemon(projectRoot: string, tmuxSession?: string): Promise<string>;
30
+ /**
31
+ * Connect to daemon socket
32
+ */
33
+ export declare function connectToDaemon(socketPath: string): Promise<DaemonClientConnection>;
34
+ /** Connect with protocol version check */
35
+ export declare function connectWithVersionCheck(socketPath: string): Promise<DaemonClientConnection>;
36
+ /** Connect with retry logic */
37
+ export declare function connectWithRetry(socketPath: string, maxRetries?: number): Promise<DaemonClientConnection>;
38
+ //# sourceMappingURL=client.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../src/daemon/client.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,aAAa,EAAE,cAAc,EAAgB,MAAM,eAAe,CAAC;AAIjF,mDAAmD;AACnD,qBAAa,qBAAsB,SAAQ,KAAK;aAG5B,IAAI,EAAE,WAAW,GAAG,oBAAoB,GAAG,SAAS;gBADpE,OAAO,EAAE,MAAM,EACC,IAAI,EAAE,WAAW,GAAG,oBAAoB,GAAG,SAAS;CAKvE;AAED,qBAAa,kBAAmB,SAAQ,KAAK;aAGzB,aAAa,EAAE,MAAM;aACrB,aAAa,EAAE,MAAM;gBAFrC,OAAO,EAAE,MAAM,EACC,aAAa,EAAE,MAAM,EACrB,aAAa,EAAE,MAAM;CAKxC;AAED,iCAAiC;AACjC,MAAM,WAAW,UAAU;IACzB,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,EAAE,OAAO,CAAC;CAClB;AAED,8CAA8C;AAC9C,MAAM,WAAW,sBAAsB;IACrC,IAAI,CAAC,CAAC,SAAS,cAAc,EAAE,OAAO,EAAE,aAAa,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC;IACnE,KAAK,IAAI,IAAI,CAAC;CACf;AAKD;;GAEG;AACH,wBAAsB,cAAc,CAClC,WAAW,EAAE,MAAM,EACnB,WAAW,SAAQ,GAClB,OAAO,CAAC,UAAU,CAAC,CASrB;AAeD;;GAEG;AACH,wBAAsB,YAAY,CAAC,WAAW,EAAE,MAAM,EAAE,WAAW,SAAQ,GAAG,OAAO,CAAC,MAAM,CAAC,CA2B5F;AAiCD;;GAEG;AACH,wBAAsB,eAAe,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,sBAAsB,CAAC,CA6BzF;AAkDD,0CAA0C;AAC1C,wBAAsB,uBAAuB,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,sBAAsB,CAAC,CA8BjG;AAED,+BAA+B;AAC/B,wBAAsB,gBAAgB,CACpC,UAAU,EAAE,MAAM,EAClB,UAAU,SAAI,GACb,OAAO,CAAC,sBAAsB,CAAC,CA+BjC"}
@@ -0,0 +1,254 @@
1
+ import * as fs from "node:fs/promises";
2
+ import * as net from "node:net";
3
+ import * as path from "node:path";
4
+ import { spawn } from "node:child_process";
5
+ import { PROTOCOL_VERSION } from "./protocol.js";
6
+ import { generateSessionId } from "../session.js";
7
+ /** Error classes for daemon connection failures */
8
+ export class DaemonConnectionError extends Error {
9
+ code;
10
+ constructor(message, code) {
11
+ super(message);
12
+ this.code = code;
13
+ this.name = "DaemonConnectionError";
14
+ }
15
+ }
16
+ export class DaemonVersionError extends Error {
17
+ daemonVersion;
18
+ clientVersion;
19
+ constructor(message, daemonVersion, clientVersion) {
20
+ super(message);
21
+ this.daemonVersion = daemonVersion;
22
+ this.clientVersion = clientVersion;
23
+ this.name = "DaemonVersionError";
24
+ }
25
+ }
26
+ const STARTUP_TIMEOUT_MS = 5000;
27
+ const STARTUP_POLL_MS = 100;
28
+ /**
29
+ * Discover daemon for given project and session
30
+ */
31
+ export async function discoverDaemon(projectRoot, tmuxSession = "pit") {
32
+ // Derive session ID (same logic as src/session.ts:generateSessionId)
33
+ const sessionId = generateSessionId(projectRoot, tmuxSession);
34
+ const socketPath = path.join("/tmp/pit", sessionId, "daemon.sock");
35
+ // Test if socket is connectable
36
+ const running = await testConnection(socketPath);
37
+ return { socketPath, running };
38
+ }
39
+ async function testConnection(socketPath) {
40
+ return new Promise((resolve) => {
41
+ const socket = net.createConnection(socketPath);
42
+ socket.on("connect", () => {
43
+ socket.destroy();
44
+ resolve(true);
45
+ });
46
+ socket.on("error", () => {
47
+ resolve(false);
48
+ });
49
+ });
50
+ }
51
+ /**
52
+ * Ensure daemon is running, start if needed
53
+ */
54
+ export async function ensureDaemon(projectRoot, tmuxSession = "pit") {
55
+ const info = await discoverDaemon(projectRoot, tmuxSession);
56
+ if (info.running) {
57
+ return info.socketPath;
58
+ }
59
+ // Acquire startup lock to prevent race with other clients
60
+ const lockPath = path.join(path.dirname(info.socketPath), "daemon.lock");
61
+ await acquireLock(lockPath);
62
+ try {
63
+ // Double-check after acquiring lock (another client may have started it)
64
+ if (await testConnection(info.socketPath)) {
65
+ return info.socketPath;
66
+ }
67
+ // Spawn daemon process (detached, stdio ignored)
68
+ await spawnDaemon(projectRoot, tmuxSession);
69
+ // Wait for socket to become ready
70
+ await waitForSocket(info.socketPath, STARTUP_TIMEOUT_MS);
71
+ return info.socketPath;
72
+ }
73
+ finally {
74
+ await releaseLock(lockPath);
75
+ }
76
+ }
77
+ async function spawnDaemon(projectRoot, _tmuxSession) {
78
+ // Spawn daemon __run directly (not daemon start) because the caller
79
+ // (ensureDaemon) already holds daemon.lock. Going through daemon start
80
+ // would deadlock since it tries to acquire the same lock.
81
+ const child = spawn(process.execPath, // node
82
+ [
83
+ path.resolve(process.argv[1]), // Use resolved path to CLI
84
+ "daemon",
85
+ "__run",
86
+ ], {
87
+ detached: true,
88
+ stdio: "ignore",
89
+ cwd: projectRoot,
90
+ });
91
+ child.unref();
92
+ }
93
+ async function waitForSocket(socketPath, timeoutMs) {
94
+ const deadline = Date.now() + timeoutMs;
95
+ while (Date.now() < deadline) {
96
+ if (await testConnection(socketPath)) {
97
+ return;
98
+ }
99
+ await new Promise((r) => setTimeout(r, STARTUP_POLL_MS));
100
+ }
101
+ throw new Error(`Daemon failed to start within ${timeoutMs}ms`);
102
+ }
103
+ /**
104
+ * Connect to daemon socket
105
+ */
106
+ export async function connectToDaemon(socketPath) {
107
+ return new Promise((resolve, reject) => {
108
+ const socket = net.createConnection(socketPath);
109
+ const timeout = setTimeout(() => {
110
+ socket.destroy();
111
+ reject(new DaemonConnectionError("Connection timeout", "TIMEOUT"));
112
+ }, 5000);
113
+ socket.on("connect", () => {
114
+ clearTimeout(timeout);
115
+ resolve(createClient(socket));
116
+ });
117
+ socket.on("error", (err) => {
118
+ clearTimeout(timeout);
119
+ if (err.code === "ENOENT") {
120
+ reject(new DaemonConnectionError("Daemon socket not found", "NO_SOCKET"));
121
+ }
122
+ else if (err.code === "ECONNREFUSED") {
123
+ reject(new DaemonConnectionError("Daemon not responding (may have crashed)", "CONNECTION_REFUSED"));
124
+ }
125
+ else {
126
+ reject(err);
127
+ }
128
+ });
129
+ });
130
+ }
131
+ /** Create client with proper error handling */
132
+ function createClient(socket) {
133
+ let buffer = "";
134
+ return {
135
+ async send(request) {
136
+ const REQUEST_TIMEOUT_MS = 30000;
137
+ return new Promise((resolve, reject) => {
138
+ const timeout = setTimeout(() => {
139
+ socket.off("data", onData);
140
+ reject(new Error(`Request timeout after ${REQUEST_TIMEOUT_MS}ms`));
141
+ }, REQUEST_TIMEOUT_MS);
142
+ const onData = (chunk) => {
143
+ buffer += chunk.toString();
144
+ const newlineIdx = buffer.indexOf("\n");
145
+ if (newlineIdx !== -1) {
146
+ const line = buffer.slice(0, newlineIdx);
147
+ buffer = buffer.slice(newlineIdx + 1);
148
+ socket.off("data", onData);
149
+ clearTimeout(timeout);
150
+ try {
151
+ resolve(JSON.parse(line));
152
+ }
153
+ catch {
154
+ reject(new Error("Invalid JSON response from daemon"));
155
+ }
156
+ }
157
+ };
158
+ socket.on("data", onData);
159
+ socket.write(JSON.stringify(request) + "\n");
160
+ });
161
+ },
162
+ close() {
163
+ socket.destroy();
164
+ },
165
+ };
166
+ }
167
+ /** Check if daemon protocol version is compatible */
168
+ function isVersionCompatible(daemon, client) {
169
+ // Same major version = compatible (semver-like)
170
+ const daemonMajor = daemon.split(".")[0];
171
+ const clientMajor = client.split(".")[0];
172
+ return daemonMajor === clientMajor;
173
+ }
174
+ /** Connect with protocol version check */
175
+ export async function connectWithVersionCheck(socketPath) {
176
+ const client = await connectToDaemon(socketPath);
177
+ try {
178
+ // Send status request to check version
179
+ const status = await client.send({
180
+ id: "version-check",
181
+ method: "status",
182
+ params: {},
183
+ });
184
+ if (!status.success || !status.result || !status.result.protocolVersion) {
185
+ client.close();
186
+ throw new Error("Daemon status response missing protocol version");
187
+ }
188
+ if (!isVersionCompatible(status.result.protocolVersion, PROTOCOL_VERSION)) {
189
+ client.close();
190
+ throw new DaemonVersionError(`Daemon version ${status.result.protocolVersion} incompatible with client ${PROTOCOL_VERSION}`, status.result.protocolVersion, PROTOCOL_VERSION);
191
+ }
192
+ return client;
193
+ }
194
+ catch (err) {
195
+ client.close();
196
+ throw err;
197
+ }
198
+ }
199
+ /** Connect with retry logic */
200
+ export async function connectWithRetry(socketPath, maxRetries = 1) {
201
+ let lastError = null;
202
+ for (let attempt = 0; attempt <= maxRetries; attempt++) {
203
+ try {
204
+ return await connectWithVersionCheck(socketPath);
205
+ }
206
+ catch (err) {
207
+ lastError = err;
208
+ // Retry only for transient failures
209
+ if (err instanceof DaemonConnectionError) {
210
+ if (err.code === "CONNECTION_REFUSED" && attempt < maxRetries) {
211
+ // Wait briefly before retry
212
+ await new Promise((r) => setTimeout(r, 500));
213
+ continue;
214
+ }
215
+ }
216
+ // Don't retry version mismatch or other permanent failures
217
+ if (err instanceof DaemonVersionError) {
218
+ throw err;
219
+ }
220
+ // Don't retry socket not found (daemon not running)
221
+ if (err instanceof DaemonConnectionError && err.code === "NO_SOCKET") {
222
+ throw err;
223
+ }
224
+ }
225
+ }
226
+ throw lastError;
227
+ }
228
+ async function acquireLock(lockPath) {
229
+ const dir = path.dirname(lockPath);
230
+ await fs.mkdir(dir, { recursive: true });
231
+ // Simple spinlock with exponential backoff
232
+ let attempts = 0;
233
+ while (attempts < 50) {
234
+ try {
235
+ // O_EXCL ensures atomic creation
236
+ await fs.writeFile(lockPath, String(process.pid), { flag: "wx" });
237
+ return;
238
+ }
239
+ catch (err) {
240
+ if (err.code !== "EEXIST")
241
+ throw err;
242
+ // Lock held by another process
243
+ await new Promise((r) => setTimeout(r, Math.min(100, 10 * Math.pow(1.5, attempts))));
244
+ attempts++;
245
+ }
246
+ }
247
+ throw new Error("Failed to acquire daemon startup lock");
248
+ }
249
+ async function releaseLock(lockPath) {
250
+ await fs.unlink(lockPath).catch(() => {
251
+ // Ignore if file doesn't exist
252
+ });
253
+ }
254
+ //# sourceMappingURL=client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.js","sourceRoot":"","sources":["../../src/daemon/client.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,63 @@
1
+ /**
2
+ * Shared context type for the pit daemon.
3
+ *
4
+ * DaemonContext encapsulates all mutable runtime state that daemon handlers
5
+ * need to close over. It is a plain mutable object — not a class — so that
6
+ * state updates are straightforward assignments.
7
+ *
8
+ * The module-level let variables in commands/daemon.ts (daemonState,
9
+ * debouncedSaver, loopHandles, agentInstance) will be migrated to this
10
+ * context in a later task (.7/.8). For now this module only defines the
11
+ * shared types.
12
+ */
13
+ import type { AgentAdapter } from "../adapters/types.js";
14
+ import type { DaemonState, PersistedEpicState } from "./state.js";
15
+ import type { LoopHandle } from "../loop.js";
16
+ import type { PitConfig } from "../config.js";
17
+ import type * as beads from "../beads.js";
18
+ /**
19
+ * All runtime state for a running daemon instance.
20
+ *
21
+ * daemonState, debouncedSaver, and agentInstance start as null and are
22
+ * populated on the first `start` call or during state recovery.
23
+ */
24
+ export interface DaemonContext {
25
+ daemonState: DaemonState | null;
26
+ debouncedSaver: ((state: DaemonState) => void) | null;
27
+ loopHandles: Map<string, LoopHandle>;
28
+ agentInstance: AgentAdapter | null;
29
+ daemonStartTime: number;
30
+ projectRoot: string;
31
+ sessionId: string;
32
+ tmuxSession: string;
33
+ fileConfig: PitConfig;
34
+ healthCheckInterval: ReturnType<typeof setInterval> | null;
35
+ }
36
+ /**
37
+ * Narrowed version of DaemonContext for handlers that require the daemon to
38
+ * have been started at least once. Guarantees that daemonState, debouncedSaver,
39
+ * and agentInstance are non-null.
40
+ */
41
+ export type InitializedDaemonContext = DaemonContext & {
42
+ daemonState: DaemonState;
43
+ debouncedSaver: (state: DaemonState) => void;
44
+ agentInstance: AgentAdapter;
45
+ };
46
+ /**
47
+ * Signature of the clearAndReprompt helper used by daemon handlers and the
48
+ * recovery pipeline.
49
+ *
50
+ * Moved here (from commands/daemon.ts) to avoid future import cycles between
51
+ * the handler modules and the recovery module.
52
+ */
53
+ export type ClearAndRepromptFn = (options: {
54
+ epicId: string;
55
+ machine: LoopHandle["machine"];
56
+ windowName: string;
57
+ adapter: AgentAdapter;
58
+ transitionReason: "TICKET_COMPLETE" | "RESUME_NO_MESSAGE";
59
+ epicState: PersistedEpicState;
60
+ }) => Promise<{
61
+ nextTicket: beads.BeadTicket | null;
62
+ }>;
63
+ //# sourceMappingURL=context.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"context.d.ts","sourceRoot":"","sources":["../../src/daemon/context.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AACzD,OAAO,KAAK,EAAE,WAAW,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC;AAClE,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAC7C,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAC9C,OAAO,KAAK,KAAK,KAAK,MAAM,aAAa,CAAC;AAM1C;;;;;GAKG;AACH,MAAM,WAAW,aAAa;IAC5B,WAAW,EAAE,WAAW,GAAG,IAAI,CAAC;IAChC,cAAc,EAAE,CAAC,CAAC,KAAK,EAAE,WAAW,KAAK,IAAI,CAAC,GAAG,IAAI,CAAC;IACtD,WAAW,EAAE,GAAG,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC;IACrC,aAAa,EAAE,YAAY,GAAG,IAAI,CAAC;IACnC,eAAe,EAAE,MAAM,CAAC;IACxB,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,EAAE,SAAS,CAAC;IACtB,mBAAmB,EAAE,UAAU,CAAC,OAAO,WAAW,CAAC,GAAG,IAAI,CAAC;CAC5D;AAMD;;;;GAIG;AACH,MAAM,MAAM,wBAAwB,GAAG,aAAa,GAAG;IACrD,WAAW,EAAE,WAAW,CAAC;IACzB,cAAc,EAAE,CAAC,KAAK,EAAE,WAAW,KAAK,IAAI,CAAC;IAC7C,aAAa,EAAE,YAAY,CAAC;CAC7B,CAAC;AAMF;;;;;;GAMG;AACH,MAAM,MAAM,kBAAkB,GAAG,CAAC,OAAO,EAAE;IACzC,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,UAAU,CAAC,SAAS,CAAC,CAAC;IAC/B,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,EAAE,YAAY,CAAC;IACtB,gBAAgB,EAAE,iBAAiB,GAAG,mBAAmB,CAAC;IAC1D,SAAS,EAAE,kBAAkB,CAAC;CAC/B,KAAK,OAAO,CAAC;IAAE,UAAU,EAAE,KAAK,CAAC,UAAU,GAAG,IAAI,CAAA;CAAE,CAAC,CAAC"}
@@ -0,0 +1,14 @@
1
+ /**
2
+ * Shared context type for the pit daemon.
3
+ *
4
+ * DaemonContext encapsulates all mutable runtime state that daemon handlers
5
+ * need to close over. It is a plain mutable object — not a class — so that
6
+ * state updates are straightforward assignments.
7
+ *
8
+ * The module-level let variables in commands/daemon.ts (daemonState,
9
+ * debouncedSaver, loopHandles, agentInstance) will be migrated to this
10
+ * context in a later task (.7/.8). For now this module only defines the
11
+ * shared types.
12
+ */
13
+ export {};
14
+ //# sourceMappingURL=context.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"context.js","sourceRoot":"","sources":["../../src/daemon/context.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG"}