@proletariat/cli 0.3.96 → 0.3.97
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.
- package/dist/commands/gc.d.ts +1 -0
- package/dist/commands/gc.js +31 -1
- package/dist/commands/gc.js.map +1 -1
- package/dist/commands/linear/connect.d.ts +5 -0
- package/dist/commands/linear/connect.js +84 -0
- package/dist/commands/linear/connect.js.map +1 -1
- package/dist/commands/session/watch.d.ts +1 -0
- package/dist/commands/session/watch.js +46 -2
- package/dist/commands/session/watch.js.map +1 -1
- package/dist/commands/work/complete.d.ts +1 -0
- package/dist/commands/work/complete.js +27 -25
- package/dist/commands/work/complete.js.map +1 -1
- package/dist/commands/work/drop.d.ts +14 -0
- package/dist/commands/work/drop.js +215 -0
- package/dist/commands/work/drop.js.map +1 -0
- package/dist/commands/work/ready.d.ts +1 -0
- package/dist/commands/work/ready.js +26 -25
- package/dist/commands/work/ready.js.map +1 -1
- package/dist/commands/work/ship.d.ts +1 -0
- package/dist/commands/work/ship.js +33 -32
- package/dist/commands/work/ship.js.map +1 -1
- package/dist/commands/work/start.d.ts +2 -0
- package/dist/commands/work/start.js +160 -42
- package/dist/commands/work/start.js.map +1 -1
- package/dist/commands/work/stop.d.ts +1 -0
- package/dist/commands/work/stop.js +40 -0
- package/dist/commands/work/stop.js.map +1 -1
- package/dist/lib/agents/commands.js +7 -5
- package/dist/lib/agents/commands.js.map +1 -1
- package/dist/lib/database/drizzle-schema.d.ts +17 -0
- package/dist/lib/database/drizzle-schema.js +1 -0
- package/dist/lib/database/drizzle-schema.js.map +1 -1
- package/dist/lib/database/migrations/0019_gc_artifact_cleanup.d.ts +9 -0
- package/dist/lib/database/migrations/0019_gc_artifact_cleanup.js +23 -0
- package/dist/lib/database/migrations/0019_gc_artifact_cleanup.js.map +1 -0
- package/dist/lib/database/migrations/0020_transition_map.d.ts +2 -0
- package/dist/lib/database/migrations/0020_transition_map.js +27 -0
- package/dist/lib/database/migrations/0020_transition_map.js.map +1 -0
- package/dist/lib/database/migrations/index.js +4 -0
- package/dist/lib/database/migrations/index.js.map +1 -1
- package/dist/lib/execution/config.d.ts +10 -0
- package/dist/lib/execution/config.js +24 -0
- package/dist/lib/execution/config.js.map +1 -1
- package/dist/lib/execution/preflight.d.ts +51 -0
- package/dist/lib/execution/preflight.js +278 -0
- package/dist/lib/execution/preflight.js.map +1 -0
- package/dist/lib/execution/runners/prompt-builder.d.ts +6 -0
- package/dist/lib/execution/runners/prompt-builder.js +38 -7
- package/dist/lib/execution/runners/prompt-builder.js.map +1 -1
- package/dist/lib/execution/session-utils.d.ts +23 -0
- package/dist/lib/execution/session-utils.js +69 -0
- package/dist/lib/execution/session-utils.js.map +1 -1
- package/dist/lib/execution/spawner.d.ts +11 -1
- package/dist/lib/execution/spawner.js +44 -16
- package/dist/lib/execution/spawner.js.map +1 -1
- package/dist/lib/execution/ticket-refs.d.ts +71 -0
- package/dist/lib/execution/ticket-refs.js +125 -0
- package/dist/lib/execution/ticket-refs.js.map +1 -0
- package/dist/lib/execution/types.d.ts +7 -2
- package/dist/lib/execution/types.js +5 -3
- package/dist/lib/execution/types.js.map +1 -1
- package/dist/lib/gc/index.d.ts +59 -6
- package/dist/lib/gc/index.js +258 -13
- package/dist/lib/gc/index.js.map +1 -1
- package/dist/lib/prompt-json.d.ts +31 -0
- package/dist/lib/prompt-json.js.map +1 -1
- package/dist/lib/providers/auto-mapper.d.ts +45 -0
- package/dist/lib/providers/auto-mapper.js +115 -0
- package/dist/lib/providers/auto-mapper.js.map +1 -0
- package/dist/lib/providers/state-intents.d.ts +20 -0
- package/dist/lib/providers/state-intents.js +61 -7
- package/dist/lib/providers/state-intents.js.map +1 -1
- package/dist/lib/providers/state-resolution.d.ts +15 -11
- package/dist/lib/providers/state-resolution.js +54 -48
- package/dist/lib/providers/state-resolution.js.map +1 -1
- package/dist/lib/providers/transition-map.d.ts +59 -0
- package/dist/lib/providers/transition-map.js +113 -0
- package/dist/lib/providers/transition-map.js.map +1 -0
- package/dist/lib/session/index.d.ts +3 -1
- package/dist/lib/session/index.js +3 -1
- package/dist/lib/session/index.js.map +1 -1
- package/dist/lib/session/tmux-watchdog.d.ts +157 -0
- package/dist/lib/session/tmux-watchdog.js +424 -0
- package/dist/lib/session/tmux-watchdog.js.map +1 -0
- package/dist/lib/session/watcher.d.ts +22 -4
- package/dist/lib/session/watcher.js +66 -8
- package/dist/lib/session/watcher.js.map +1 -1
- package/dist/lib/work-lifecycle/transition.d.ts +73 -0
- package/dist/lib/work-lifecycle/transition.js +124 -0
- package/dist/lib/work-lifecycle/transition.js.map +1 -0
- package/oclif.manifest.json +438 -332
- package/package.json +1 -1
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Transition Map Store
|
|
3
|
+
*
|
|
4
|
+
* Manages the pmo_transition_map table, which stores intent-to-provider-state
|
|
5
|
+
* mappings. Each work primitive (start, ready, ship, stop, drop) has a
|
|
6
|
+
* canonical intent, and this store resolves that intent to whatever state
|
|
7
|
+
* name exists on the connected board.
|
|
8
|
+
*
|
|
9
|
+
* Resolution order (in state-resolution.ts):
|
|
10
|
+
* 1. pmo_transition_map (this store) — explicit user-confirmed mappings
|
|
11
|
+
* 2. state-map.{intent} config override
|
|
12
|
+
* 3. Built-in semantic intent aliases
|
|
13
|
+
* 4. LLM fallback
|
|
14
|
+
* 5. Skip (no match)
|
|
15
|
+
*/
|
|
16
|
+
import type Database from 'better-sqlite3';
|
|
17
|
+
import type { TransitionIntent } from './state-intents.js';
|
|
18
|
+
export interface TransitionMapping {
|
|
19
|
+
provider: string;
|
|
20
|
+
intent: TransitionIntent;
|
|
21
|
+
providerStateName: string;
|
|
22
|
+
providerStateId?: string | null;
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* CRUD operations for the pmo_transition_map table.
|
|
26
|
+
*/
|
|
27
|
+
export declare class TransitionMapStore {
|
|
28
|
+
private db;
|
|
29
|
+
constructor(db: Database.Database);
|
|
30
|
+
/**
|
|
31
|
+
* Get the provider state name mapped to a transition intent.
|
|
32
|
+
* Returns null if no mapping exists.
|
|
33
|
+
*/
|
|
34
|
+
getMapping(provider: string, intent: string): TransitionMapping | null;
|
|
35
|
+
/**
|
|
36
|
+
* Add or update a transition mapping.
|
|
37
|
+
*/
|
|
38
|
+
upsertMapping(mapping: TransitionMapping): void;
|
|
39
|
+
/**
|
|
40
|
+
* List all transition mappings for a provider.
|
|
41
|
+
*/
|
|
42
|
+
listMappings(provider: string): TransitionMapping[];
|
|
43
|
+
/**
|
|
44
|
+
* Remove a specific transition mapping.
|
|
45
|
+
*/
|
|
46
|
+
removeMapping(provider: string, intent: string): void;
|
|
47
|
+
/**
|
|
48
|
+
* Remove all transition mappings for a provider.
|
|
49
|
+
*/
|
|
50
|
+
clearMappings(provider: string): void;
|
|
51
|
+
/**
|
|
52
|
+
* Resolve a transition intent to a provider state name.
|
|
53
|
+
* Returns the mapped state name, or null if no mapping exists.
|
|
54
|
+
*
|
|
55
|
+
* This is the primary resolution method called by work commands.
|
|
56
|
+
* If this returns null, the caller should fall through to alias/LLM resolution.
|
|
57
|
+
*/
|
|
58
|
+
resolveIntent(provider: string, intent: string): string | null;
|
|
59
|
+
}
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Transition Map Store
|
|
3
|
+
*
|
|
4
|
+
* Manages the pmo_transition_map table, which stores intent-to-provider-state
|
|
5
|
+
* mappings. Each work primitive (start, ready, ship, stop, drop) has a
|
|
6
|
+
* canonical intent, and this store resolves that intent to whatever state
|
|
7
|
+
* name exists on the connected board.
|
|
8
|
+
*
|
|
9
|
+
* Resolution order (in state-resolution.ts):
|
|
10
|
+
* 1. pmo_transition_map (this store) — explicit user-confirmed mappings
|
|
11
|
+
* 2. state-map.{intent} config override
|
|
12
|
+
* 3. Built-in semantic intent aliases
|
|
13
|
+
* 4. LLM fallback
|
|
14
|
+
* 5. Skip (no match)
|
|
15
|
+
*/
|
|
16
|
+
/**
|
|
17
|
+
* CRUD operations for the pmo_transition_map table.
|
|
18
|
+
*/
|
|
19
|
+
export class TransitionMapStore {
|
|
20
|
+
db;
|
|
21
|
+
constructor(db) {
|
|
22
|
+
this.db = db;
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Get the provider state name mapped to a transition intent.
|
|
26
|
+
* Returns null if no mapping exists.
|
|
27
|
+
*/
|
|
28
|
+
getMapping(provider, intent) {
|
|
29
|
+
try {
|
|
30
|
+
const row = this.db.prepare(`
|
|
31
|
+
SELECT provider, intent, provider_state_name, provider_state_id
|
|
32
|
+
FROM pmo_transition_map
|
|
33
|
+
WHERE provider = ? AND intent = ?
|
|
34
|
+
`).get(provider, intent);
|
|
35
|
+
if (!row)
|
|
36
|
+
return null;
|
|
37
|
+
return {
|
|
38
|
+
provider: row.provider,
|
|
39
|
+
intent: row.intent,
|
|
40
|
+
providerStateName: row.provider_state_name,
|
|
41
|
+
providerStateId: row.provider_state_id,
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
catch {
|
|
45
|
+
return null;
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Add or update a transition mapping.
|
|
50
|
+
*/
|
|
51
|
+
upsertMapping(mapping) {
|
|
52
|
+
this.db.prepare(`
|
|
53
|
+
INSERT INTO pmo_transition_map (provider, intent, provider_state_name, provider_state_id, updated_at)
|
|
54
|
+
VALUES (?, ?, ?, ?, CURRENT_TIMESTAMP)
|
|
55
|
+
ON CONFLICT(provider, intent) DO UPDATE SET
|
|
56
|
+
provider_state_name = excluded.provider_state_name,
|
|
57
|
+
provider_state_id = excluded.provider_state_id,
|
|
58
|
+
updated_at = CURRENT_TIMESTAMP
|
|
59
|
+
`).run(mapping.provider, mapping.intent, mapping.providerStateName, mapping.providerStateId ?? null);
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* List all transition mappings for a provider.
|
|
63
|
+
*/
|
|
64
|
+
listMappings(provider) {
|
|
65
|
+
try {
|
|
66
|
+
const rows = this.db.prepare(`
|
|
67
|
+
SELECT provider, intent, provider_state_name, provider_state_id
|
|
68
|
+
FROM pmo_transition_map
|
|
69
|
+
WHERE provider = ?
|
|
70
|
+
ORDER BY intent
|
|
71
|
+
`).all(provider);
|
|
72
|
+
return rows.map(row => ({
|
|
73
|
+
provider: row.provider,
|
|
74
|
+
intent: row.intent,
|
|
75
|
+
providerStateName: row.provider_state_name,
|
|
76
|
+
providerStateId: row.provider_state_id,
|
|
77
|
+
}));
|
|
78
|
+
}
|
|
79
|
+
catch {
|
|
80
|
+
return [];
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* Remove a specific transition mapping.
|
|
85
|
+
*/
|
|
86
|
+
removeMapping(provider, intent) {
|
|
87
|
+
this.db.prepare(`
|
|
88
|
+
DELETE FROM pmo_transition_map
|
|
89
|
+
WHERE provider = ? AND intent = ?
|
|
90
|
+
`).run(provider, intent);
|
|
91
|
+
}
|
|
92
|
+
/**
|
|
93
|
+
* Remove all transition mappings for a provider.
|
|
94
|
+
*/
|
|
95
|
+
clearMappings(provider) {
|
|
96
|
+
this.db.prepare(`
|
|
97
|
+
DELETE FROM pmo_transition_map
|
|
98
|
+
WHERE provider = ?
|
|
99
|
+
`).run(provider);
|
|
100
|
+
}
|
|
101
|
+
/**
|
|
102
|
+
* Resolve a transition intent to a provider state name.
|
|
103
|
+
* Returns the mapped state name, or null if no mapping exists.
|
|
104
|
+
*
|
|
105
|
+
* This is the primary resolution method called by work commands.
|
|
106
|
+
* If this returns null, the caller should fall through to alias/LLM resolution.
|
|
107
|
+
*/
|
|
108
|
+
resolveIntent(provider, intent) {
|
|
109
|
+
const mapping = this.getMapping(provider, intent);
|
|
110
|
+
return mapping?.providerStateName ?? null;
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
//# sourceMappingURL=transition-map.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"transition-map.js","sourceRoot":"","sources":["../../../src/lib/providers/transition-map.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAYH;;GAEG;AACH,MAAM,OAAO,kBAAkB;IACT;IAApB,YAAoB,EAAqB;QAArB,OAAE,GAAF,EAAE,CAAmB;IAAG,CAAC;IAE7C;;;OAGG;IACH,UAAU,CAAC,QAAgB,EAAE,MAAc;QACzC,IAAI,CAAC;YACH,MAAM,GAAG,GAAG,IAAI,CAAC,EAAE,CAAC,OAAO,CAAC;;;;OAI3B,CAAC,CAAC,GAAG,CAAC,QAAQ,EAAE,MAAM,CAKV,CAAA;YAEb,IAAI,CAAC,GAAG;gBAAE,OAAO,IAAI,CAAA;YAErB,OAAO;gBACL,QAAQ,EAAE,GAAG,CAAC,QAAQ;gBACtB,MAAM,EAAE,GAAG,CAAC,MAA0B;gBACtC,iBAAiB,EAAE,GAAG,CAAC,mBAAmB;gBAC1C,eAAe,EAAE,GAAG,CAAC,iBAAiB;aACvC,CAAA;QACH,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,IAAI,CAAA;QACb,CAAC;IACH,CAAC;IAED;;OAEG;IACH,aAAa,CAAC,OAA0B;QACtC,IAAI,CAAC,EAAE,CAAC,OAAO,CAAC;;;;;;;KAOf,CAAC,CAAC,GAAG,CACJ,OAAO,CAAC,QAAQ,EAChB,OAAO,CAAC,MAAM,EACd,OAAO,CAAC,iBAAiB,EACzB,OAAO,CAAC,eAAe,IAAI,IAAI,CAChC,CAAA;IACH,CAAC;IAED;;OAEG;IACH,YAAY,CAAC,QAAgB;QAC3B,IAAI,CAAC;YACH,MAAM,IAAI,GAAG,IAAI,CAAC,EAAE,CAAC,OAAO,CAAC;;;;;OAK5B,CAAC,CAAC,GAAG,CAAC,QAAQ,CAKb,CAAA;YAEF,OAAO,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;gBACtB,QAAQ,EAAE,GAAG,CAAC,QAAQ;gBACtB,MAAM,EAAE,GAAG,CAAC,MAA0B;gBACtC,iBAAiB,EAAE,GAAG,CAAC,mBAAmB;gBAC1C,eAAe,EAAE,GAAG,CAAC,iBAAiB;aACvC,CAAC,CAAC,CAAA;QACL,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,EAAE,CAAA;QACX,CAAC;IACH,CAAC;IAED;;OAEG;IACH,aAAa,CAAC,QAAgB,EAAE,MAAc;QAC5C,IAAI,CAAC,EAAE,CAAC,OAAO,CAAC;;;KAGf,CAAC,CAAC,GAAG,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAA;IAC1B,CAAC;IAED;;OAEG;IACH,aAAa,CAAC,QAAgB;QAC5B,IAAI,CAAC,EAAE,CAAC,OAAO,CAAC;;;KAGf,CAAC,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAA;IAClB,CAAC;IAED;;;;;;OAMG;IACH,aAAa,CAAC,QAAgB,EAAE,MAAc;QAC5C,MAAM,OAAO,GAAG,IAAI,CAAC,UAAU,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAA;QACjD,OAAO,OAAO,EAAE,iBAAiB,IAAI,IAAI,CAAA;IAC3C,CAAC;CACF"}
|
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Session Module
|
|
3
3
|
*
|
|
4
|
-
* Agent session monitoring, heartbeat tracking,
|
|
4
|
+
* Agent session monitoring, heartbeat tracking, stale detection,
|
|
5
|
+
* and tmux server crash recovery.
|
|
5
6
|
*/
|
|
6
7
|
export * from './heartbeat.js';
|
|
7
8
|
export * from './watcher.js';
|
|
9
|
+
export * from './tmux-watchdog.js';
|
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Session Module
|
|
3
3
|
*
|
|
4
|
-
* Agent session monitoring, heartbeat tracking,
|
|
4
|
+
* Agent session monitoring, heartbeat tracking, stale detection,
|
|
5
|
+
* and tmux server crash recovery.
|
|
5
6
|
*/
|
|
6
7
|
export * from './heartbeat.js';
|
|
7
8
|
export * from './watcher.js';
|
|
9
|
+
export * from './tmux-watchdog.js';
|
|
8
10
|
//# sourceMappingURL=index.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/lib/session/index.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/lib/session/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,cAAc,gBAAgB,CAAA;AAC9B,cAAc,cAAc,CAAA;AAC5B,cAAc,oBAAoB,CAAA"}
|
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tmux Watchdog
|
|
3
|
+
*
|
|
4
|
+
* Detects tmux server crashes and attempts automatic recovery of agent sessions.
|
|
5
|
+
*
|
|
6
|
+
* Problem: When the tmux server crashes (macOS sleep, resource pressure, OOM),
|
|
7
|
+
* ALL agent sessions are silently lost. The existing heartbeat system treats
|
|
8
|
+
* each agent as individually stale, missing the root cause. There is no
|
|
9
|
+
* recovery or user notification.
|
|
10
|
+
*
|
|
11
|
+
* Solution: This watchdog monitors the tmux server process itself. When a
|
|
12
|
+
* crash is detected (server transitions from alive→dead while agents were
|
|
13
|
+
* active), it:
|
|
14
|
+
*
|
|
15
|
+
* 1. Marks all affected executions with a crash-specific error
|
|
16
|
+
* 2. Attempts to re-create tmux sessions and restart agents
|
|
17
|
+
* 3. Logs crash events for user notification
|
|
18
|
+
*
|
|
19
|
+
* Architecture:
|
|
20
|
+
* - Runs as Phase 0 in SessionWatcher.runCycle(), before heartbeat checks
|
|
21
|
+
* - Maintains last-known server state per environment (host + each container)
|
|
22
|
+
* - Uses session-utils.ts for server status checks
|
|
23
|
+
* - Uses session restart logic to re-launch agents in recovered sessions
|
|
24
|
+
*/
|
|
25
|
+
import { ExecutionStorage } from '../execution/storage.js';
|
|
26
|
+
import type { AgentWork } from '../execution/types.js';
|
|
27
|
+
/**
|
|
28
|
+
* Record of a tmux server crash event.
|
|
29
|
+
*/
|
|
30
|
+
export interface TmuxCrashEvent {
|
|
31
|
+
/** When the crash was detected */
|
|
32
|
+
timestamp: Date;
|
|
33
|
+
/** Where the crash occurred */
|
|
34
|
+
environment: 'host' | 'container';
|
|
35
|
+
/** Container ID (only for container crashes) */
|
|
36
|
+
containerId?: string;
|
|
37
|
+
/** Executions that were active when the crash occurred */
|
|
38
|
+
affectedExecutions: AgentWork[];
|
|
39
|
+
/** Whether recovery was attempted */
|
|
40
|
+
recoveryAttempted: boolean;
|
|
41
|
+
/** Sessions that were successfully recovered */
|
|
42
|
+
recoveredSessions: string[];
|
|
43
|
+
/** Sessions that failed to recover */
|
|
44
|
+
failedRecoveries: string[];
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Result of a watchdog check cycle.
|
|
48
|
+
*/
|
|
49
|
+
export interface WatchdogCycleResult {
|
|
50
|
+
/** Whether the host tmux server is alive */
|
|
51
|
+
hostServerAlive: boolean;
|
|
52
|
+
/** Map of container ID → server alive status */
|
|
53
|
+
containerServersAlive: Map<string, boolean>;
|
|
54
|
+
/** Crash events detected in this cycle */
|
|
55
|
+
crashEvents: TmuxCrashEvent[];
|
|
56
|
+
/** Total executions affected by crashes */
|
|
57
|
+
totalAffected: number;
|
|
58
|
+
/** Total sessions recovered */
|
|
59
|
+
totalRecovered: number;
|
|
60
|
+
}
|
|
61
|
+
export interface TmuxWatchdogOptions {
|
|
62
|
+
/** Execution storage for DB operations */
|
|
63
|
+
storage: ExecutionStorage;
|
|
64
|
+
/** Whether to attempt auto-recovery (default: true) */
|
|
65
|
+
autoRecover?: boolean;
|
|
66
|
+
/** Logger function */
|
|
67
|
+
log?: (msg: string) => void;
|
|
68
|
+
/** Callback when a crash is detected */
|
|
69
|
+
onCrashDetected?: (event: TmuxCrashEvent) => void | Promise<void>;
|
|
70
|
+
}
|
|
71
|
+
export declare class TmuxWatchdog {
|
|
72
|
+
private storage;
|
|
73
|
+
private autoRecover;
|
|
74
|
+
private log;
|
|
75
|
+
private onCrashDetected?;
|
|
76
|
+
/**
|
|
77
|
+
* Tracks last known tmux server state.
|
|
78
|
+
* Key: 'host' for host server, containerId for container servers.
|
|
79
|
+
* Value: true = server was alive, false = server was down.
|
|
80
|
+
*/
|
|
81
|
+
private lastServerState;
|
|
82
|
+
/**
|
|
83
|
+
* Tracks which executions were active when we last saw the server alive.
|
|
84
|
+
* Key: 'host' or containerId.
|
|
85
|
+
* Value: array of execution IDs that were active in that environment.
|
|
86
|
+
*/
|
|
87
|
+
private activeExecutionsSnapshot;
|
|
88
|
+
/**
|
|
89
|
+
* Tracks crash events we've already handled to avoid duplicate recovery.
|
|
90
|
+
* Key: 'host' or containerId.
|
|
91
|
+
* Value: timestamp of when we detected the crash.
|
|
92
|
+
*/
|
|
93
|
+
private handledCrashes;
|
|
94
|
+
constructor(options: TmuxWatchdogOptions);
|
|
95
|
+
/**
|
|
96
|
+
* Run a single watchdog check cycle.
|
|
97
|
+
*
|
|
98
|
+
* Checks tmux server health for host and all containers with active executions.
|
|
99
|
+
* Detects crashes (server alive→dead transition) and attempts recovery.
|
|
100
|
+
*/
|
|
101
|
+
checkAndRecover(): Promise<WatchdogCycleResult>;
|
|
102
|
+
/**
|
|
103
|
+
* Handle a detected tmux server crash.
|
|
104
|
+
* Marks affected executions and attempts recovery.
|
|
105
|
+
*/
|
|
106
|
+
private handleCrash;
|
|
107
|
+
/**
|
|
108
|
+
* Attempt to recover agent sessions after a tmux server crash.
|
|
109
|
+
*
|
|
110
|
+
* Recovery steps:
|
|
111
|
+
* 1. Wait briefly for tmux server to come back (macOS wake, Docker resume)
|
|
112
|
+
* 2. Create new tmux sessions with the original session names
|
|
113
|
+
* 3. Navigate to the working directory
|
|
114
|
+
* 4. Re-launch Claude Code with --resume flag
|
|
115
|
+
*/
|
|
116
|
+
private attemptRecovery;
|
|
117
|
+
/**
|
|
118
|
+
* Wait for the tmux server to come back online.
|
|
119
|
+
* Returns true if the server recovered within the timeout.
|
|
120
|
+
*/
|
|
121
|
+
private waitForServerRecovery;
|
|
122
|
+
/**
|
|
123
|
+
* Restart an agent session by creating a new tmux session and re-launching Claude Code.
|
|
124
|
+
*/
|
|
125
|
+
private restartSession;
|
|
126
|
+
/**
|
|
127
|
+
* Restart a host tmux session.
|
|
128
|
+
*/
|
|
129
|
+
private restartHostSession;
|
|
130
|
+
/**
|
|
131
|
+
* Restart a tmux session inside a Docker container.
|
|
132
|
+
*/
|
|
133
|
+
private restartContainerSession;
|
|
134
|
+
/**
|
|
135
|
+
* Get the current known state of servers.
|
|
136
|
+
* Useful for diagnostics and testing.
|
|
137
|
+
*/
|
|
138
|
+
getServerStates(): Map<string, boolean>;
|
|
139
|
+
/**
|
|
140
|
+
* Reset internal state. Useful for testing.
|
|
141
|
+
*/
|
|
142
|
+
reset(): void;
|
|
143
|
+
/**
|
|
144
|
+
* Seed the initial server state without triggering crash detection.
|
|
145
|
+
* Call this once during watcher startup to establish baseline.
|
|
146
|
+
*/
|
|
147
|
+
seedServerState(activeExecs: AgentWork[]): void;
|
|
148
|
+
}
|
|
149
|
+
/**
|
|
150
|
+
* Format a crash event into a human-readable notification string.
|
|
151
|
+
*/
|
|
152
|
+
export declare function formatCrashNotification(event: TmuxCrashEvent): string;
|
|
153
|
+
/**
|
|
154
|
+
* Send a desktop notification about a tmux crash (best effort).
|
|
155
|
+
* Uses osascript on macOS, notify-send on Linux.
|
|
156
|
+
*/
|
|
157
|
+
export declare function sendDesktopNotification(title: string, message: string): void;
|