@proletariat/cli 0.3.78 → 0.3.80

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,98 @@
1
+ /**
2
+ * Container Cleanup Lifecycle Hook
3
+ *
4
+ * Subscribes to agent lifecycle events on the global EventBus and
5
+ * automatically cleans up Docker containers when agents complete work.
6
+ *
7
+ * This is a triggered cleanup (not TTL-based): containers are removed
8
+ * when the agent:stopped event fires or when stale executions are detected.
9
+ */
10
+ import { getEventBus } from '../events/event-bus.js';
11
+ import { cleanupAgentContainer } from '../execution/container-cleanup.js';
12
+ /**
13
+ * ContainerCleanupHook listens for agent completion events and
14
+ * removes the associated Docker container.
15
+ *
16
+ * Cleanup is fire-and-forget: failures are logged but never block
17
+ * the event emission chain.
18
+ */
19
+ export class ContainerCleanupHook {
20
+ unsubscribers = [];
21
+ /**
22
+ * Start listening for agent lifecycle events.
23
+ */
24
+ start() {
25
+ const bus = getEventBus();
26
+ // Clean up container when an agent is stopped
27
+ this.unsubscribers.push(bus.on('agent:stopped', (payload) => {
28
+ this.handleAgentStopped(payload);
29
+ }));
30
+ }
31
+ /**
32
+ * Stop listening and clean up subscriptions.
33
+ */
34
+ stop() {
35
+ for (const unsub of this.unsubscribers) {
36
+ unsub();
37
+ }
38
+ this.unsubscribers = [];
39
+ }
40
+ /**
41
+ * Handle agent:stopped by cleaning up the agent's container.
42
+ * Extracts agent name from the session ID or event data.
43
+ */
44
+ handleAgentStopped(eventData) {
45
+ try {
46
+ // The sessionId format is: {ticketId}-{action}-{agentName}
47
+ // We need the agent name to find the container
48
+ const sessionId = eventData.sessionId;
49
+ if (!sessionId)
50
+ return;
51
+ // Extract agent name from session ID
52
+ // Format: TKT-123-implement-agent-name or similar
53
+ const agentName = extractAgentNameFromSessionId(sessionId);
54
+ if (!agentName)
55
+ return;
56
+ cleanupAgentContainer(agentName);
57
+ }
58
+ catch {
59
+ // Container cleanup errors are non-fatal
60
+ }
61
+ }
62
+ }
63
+ /**
64
+ * Extract agent name from a session ID.
65
+ * Session IDs follow the format: {ticketId}-{action}-{agentName}
66
+ * e.g., "TKT-100-implement-bold-turing" → "bold-turing"
67
+ */
68
+ function extractAgentNameFromSessionId(sessionId) {
69
+ // Match pattern: TKT-NNN-action-agentname or similar
70
+ // Agent names are typically two hyphenated words: adjective-noun
71
+ const match = sessionId.match(/^(?:TKT-\d+|[A-Z]+-\d+)-\w+-(.+)$/);
72
+ return match ? match[1] : null;
73
+ }
74
+ // =============================================================================
75
+ // Singleton
76
+ // =============================================================================
77
+ let _hook;
78
+ /**
79
+ * Initialize and start the container cleanup hook.
80
+ * Safe to call multiple times — subsequent calls are no-ops.
81
+ */
82
+ export function initContainerCleanupHook() {
83
+ if (!_hook) {
84
+ _hook = new ContainerCleanupHook();
85
+ _hook.start();
86
+ }
87
+ return _hook;
88
+ }
89
+ /**
90
+ * Stop the container cleanup hook (primarily for testing).
91
+ */
92
+ export function stopContainerCleanupHook() {
93
+ if (_hook) {
94
+ _hook.stop();
95
+ _hook = undefined;
96
+ }
97
+ }
98
+ //# sourceMappingURL=container-cleanup-hook.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"container-cleanup-hook.js","sourceRoot":"","sources":["../../../src/lib/work-lifecycle/container-cleanup-hook.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAA;AACpD,OAAO,EAAE,qBAAqB,EAAE,MAAM,mCAAmC,CAAA;AAEzE;;;;;;GAMG;AACH,MAAM,OAAO,oBAAoB;IACvB,aAAa,GAAsB,EAAE,CAAA;IAE7C;;OAEG;IACH,KAAK;QACH,MAAM,GAAG,GAAG,WAAW,EAAE,CAAA;QAEzB,8CAA8C;QAC9C,IAAI,CAAC,aAAa,CAAC,IAAI,CACrB,GAAG,CAAC,EAAE,CAAC,eAAe,EAAE,CAAC,OAAO,EAAE,EAAE;YAClC,IAAI,CAAC,kBAAkB,CAAC,OAA6C,CAAC,CAAA;QACxE,CAAC,CAAC,CACH,CAAA;IACH,CAAC;IAED;;OAEG;IACH,IAAI;QACF,KAAK,MAAM,KAAK,IAAI,IAAI,CAAC,aAAa,EAAE,CAAC;YACvC,KAAK,EAAE,CAAA;QACT,CAAC;QACD,IAAI,CAAC,aAAa,GAAG,EAAE,CAAA;IACzB,CAAC;IAED;;;OAGG;IACK,kBAAkB,CAAC,SAAkC;QAC3D,IAAI,CAAC;YACH,2DAA2D;YAC3D,+CAA+C;YAC/C,MAAM,SAAS,GAAG,SAAS,CAAC,SAA+B,CAAA;YAC3D,IAAI,CAAC,SAAS;gBAAE,OAAM;YAEtB,qCAAqC;YACrC,kDAAkD;YAClD,MAAM,SAAS,GAAG,6BAA6B,CAAC,SAAS,CAAC,CAAA;YAC1D,IAAI,CAAC,SAAS;gBAAE,OAAM;YAEtB,qBAAqB,CAAC,SAAS,CAAC,CAAA;QAClC,CAAC;QAAC,MAAM,CAAC;YACP,yCAAyC;QAC3C,CAAC;IACH,CAAC;CACF;AAED;;;;GAIG;AACH,SAAS,6BAA6B,CAAC,SAAiB;IACtD,qDAAqD;IACrD,iEAAiE;IACjE,MAAM,KAAK,GAAG,SAAS,CAAC,KAAK,CAAC,mCAAmC,CAAC,CAAA;IAClE,OAAO,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAA;AAChC,CAAC;AAED,gFAAgF;AAChF,YAAY;AACZ,gFAAgF;AAEhF,IAAI,KAAuC,CAAA;AAE3C;;;GAGG;AACH,MAAM,UAAU,wBAAwB;IACtC,IAAI,CAAC,KAAK,EAAE,CAAC;QACX,KAAK,GAAG,IAAI,oBAAoB,EAAE,CAAA;QAClC,KAAK,CAAC,KAAK,EAAE,CAAA;IACf,CAAC;IACD,OAAO,KAAK,CAAA;AACd,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,wBAAwB;IACtC,IAAI,KAAK,EAAE,CAAC;QACV,KAAK,CAAC,IAAI,EAAE,CAAA;QACZ,KAAK,GAAG,SAAS,CAAA;IACnB,CAAC;AACH,CAAC"}
@@ -12,3 +12,4 @@ export { handlePostExecutionTransition, type PostExecutionContext, type PostExec
12
12
  export { validateCommits, tryValidateCommits, type CommitValidationResult, } from '../execution/commit-validation.js';
13
13
  export { WorkflowRuleEvaluator, initWorkflowRuleEvaluator, stopWorkflowRuleEvaluator, } from './rule-evaluator.js';
14
14
  export { ActionChainingHandler, initActionChaining, stopActionChaining, } from './action-chaining.js';
15
+ export { ContainerCleanupHook, initContainerCleanupHook, stopContainerCleanupHook, } from './container-cleanup-hook.js';
@@ -11,4 +11,5 @@ export { handlePostExecutionTransition, } from './post-execution.js';
11
11
  export { validateCommits, tryValidateCommits, } from '../execution/commit-validation.js';
12
12
  export { WorkflowRuleEvaluator, initWorkflowRuleEvaluator, stopWorkflowRuleEvaluator, } from './rule-evaluator.js';
13
13
  export { ActionChainingHandler, initActionChaining, stopActionChaining, } from './action-chaining.js';
14
+ export { ContainerCleanupHook, initContainerCleanupHook, stopContainerCleanupHook, } from './container-cleanup-hook.js';
14
15
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/lib/work-lifecycle/index.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAUH,OAAO,EACL,oBAAoB,EACpB,wBAAwB,EACxB,wBAAwB,GACzB,MAAM,cAAc,CAAA;AAErB,OAAO,EACL,eAAe,EACf,eAAe,GAChB,MAAM,kBAAkB,CAAA;AAEzB,OAAO,EACL,6BAA6B,GAG9B,MAAM,qBAAqB,CAAA;AAE5B,OAAO,EACL,eAAe,EACf,kBAAkB,GAEnB,MAAM,mCAAmC,CAAA;AAE1C,OAAO,EACL,qBAAqB,EACrB,yBAAyB,EACzB,yBAAyB,GAC1B,MAAM,qBAAqB,CAAA;AAE5B,OAAO,EACL,qBAAqB,EACrB,kBAAkB,EAClB,kBAAkB,GACnB,MAAM,sBAAsB,CAAA"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/lib/work-lifecycle/index.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAUH,OAAO,EACL,oBAAoB,EACpB,wBAAwB,EACxB,wBAAwB,GACzB,MAAM,cAAc,CAAA;AAErB,OAAO,EACL,eAAe,EACf,eAAe,GAChB,MAAM,kBAAkB,CAAA;AAEzB,OAAO,EACL,6BAA6B,GAG9B,MAAM,qBAAqB,CAAA;AAE5B,OAAO,EACL,eAAe,EACf,kBAAkB,GAEnB,MAAM,mCAAmC,CAAA;AAE1C,OAAO,EACL,qBAAqB,EACrB,yBAAyB,EACzB,yBAAyB,GAC1B,MAAM,qBAAqB,CAAA;AAE5B,OAAO,EACL,qBAAqB,EACrB,kBAAkB,EAClB,kBAAkB,GACnB,MAAM,sBAAsB,CAAA;AAE7B,OAAO,EACL,oBAAoB,EACpB,wBAAwB,EACxB,wBAAwB,GACzB,MAAM,6BAA6B,CAAA"}