crewly 1.6.2 → 1.6.4

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 (40) hide show
  1. package/dist/backend/backend/src/controllers/orchestrator/orchestrator.controller.d.ts.map +1 -1
  2. package/dist/backend/backend/src/controllers/orchestrator/orchestrator.controller.js +76 -15
  3. package/dist/backend/backend/src/controllers/orchestrator/orchestrator.controller.js.map +1 -1
  4. package/dist/backend/backend/src/controllers/team/team.controller.d.ts.map +1 -1
  5. package/dist/backend/backend/src/controllers/team/team.controller.js +3 -0
  6. package/dist/backend/backend/src/controllers/team/team.controller.js.map +1 -1
  7. package/dist/backend/backend/src/index.d.ts.map +1 -1
  8. package/dist/backend/backend/src/index.js +16 -0
  9. package/dist/backend/backend/src/index.js.map +1 -1
  10. package/dist/backend/backend/src/services/agent/agent-registration.service.d.ts.map +1 -1
  11. package/dist/backend/backend/src/services/agent/agent-registration.service.js +58 -9
  12. package/dist/backend/backend/src/services/agent/agent-registration.service.js.map +1 -1
  13. package/dist/backend/backend/src/services/agent/crewly-agent/in-process-runtime-registry.d.ts +91 -0
  14. package/dist/backend/backend/src/services/agent/crewly-agent/in-process-runtime-registry.d.ts.map +1 -0
  15. package/dist/backend/backend/src/services/agent/crewly-agent/in-process-runtime-registry.js +120 -0
  16. package/dist/backend/backend/src/services/agent/crewly-agent/in-process-runtime-registry.js.map +1 -0
  17. package/dist/backend/backend/src/services/core/storage.service.d.ts +15 -0
  18. package/dist/backend/backend/src/services/core/storage.service.d.ts.map +1 -1
  19. package/dist/backend/backend/src/services/core/storage.service.js +42 -0
  20. package/dist/backend/backend/src/services/core/storage.service.js.map +1 -1
  21. package/dist/backend/backend/src/services/orchestrator/index.d.ts +1 -0
  22. package/dist/backend/backend/src/services/orchestrator/index.d.ts.map +1 -1
  23. package/dist/backend/backend/src/services/orchestrator/index.js +1 -0
  24. package/dist/backend/backend/src/services/orchestrator/index.js.map +1 -1
  25. package/dist/backend/backend/src/services/orchestrator/orchestrator-setup.service.d.ts +114 -0
  26. package/dist/backend/backend/src/services/orchestrator/orchestrator-setup.service.d.ts.map +1 -0
  27. package/dist/backend/backend/src/services/orchestrator/orchestrator-setup.service.js +195 -0
  28. package/dist/backend/backend/src/services/orchestrator/orchestrator-setup.service.js.map +1 -0
  29. package/dist/backend/backend/src/services/orchestrator/orchestrator-status.service.d.ts.map +1 -1
  30. package/dist/backend/backend/src/services/orchestrator/orchestrator-status.service.js +18 -6
  31. package/dist/backend/backend/src/services/orchestrator/orchestrator-status.service.js.map +1 -1
  32. package/dist/backend/backend/src/services/slack/slack-orchestrator-bridge.d.ts +23 -0
  33. package/dist/backend/backend/src/services/slack/slack-orchestrator-bridge.d.ts.map +1 -1
  34. package/dist/backend/backend/src/services/slack/slack-orchestrator-bridge.js +79 -2
  35. package/dist/backend/backend/src/services/slack/slack-orchestrator-bridge.js.map +1 -1
  36. package/dist/cli/backend/src/services/core/storage.service.d.ts +15 -0
  37. package/dist/cli/backend/src/services/core/storage.service.d.ts.map +1 -1
  38. package/dist/cli/backend/src/services/core/storage.service.js +42 -0
  39. package/dist/cli/backend/src/services/core/storage.service.js.map +1 -1
  40. package/package.json +1 -1
@@ -0,0 +1,114 @@
1
+ /**
2
+ * Orchestrator Setup Service
3
+ *
4
+ * Provides a service-level entrypoint for triggering orchestrator setup,
5
+ * mirroring the logic behind `POST /api/orchestrator/setup`. Used by the
6
+ * SlackBridge auto-recovery path so it can reattempt setup without going
7
+ * through HTTP.
8
+ *
9
+ * Design notes:
10
+ * - Dependencies are injected via `setOrchestratorSetupDependencies()` from
11
+ * the bootstrap layer (`backend/src/index.ts`), keeping this service
12
+ * decoupled from the API context shape.
13
+ * - Concurrent calls are deduplicated via an in-flight promise — if a
14
+ * setup is already running, the second caller awaits the same result.
15
+ * - Callers should impose their own timeout on the returned promise; this
16
+ * service does not enforce a timeout because setup duration varies per
17
+ * runtime type.
18
+ *
19
+ * @module services/orchestrator/orchestrator-setup.service
20
+ */
21
+ import { type RuntimeType } from '../../constants.js';
22
+ import type { StorageService } from '../core/storage.service.js';
23
+ /**
24
+ * Minimal contract expected from the agent registration service.
25
+ *
26
+ * Defined as an inline structural type rather than imported to avoid a
27
+ * circular module graph (agent-registration → orchestrator → bridge →
28
+ * agent-registration). Matches `AgentRegistrationService.createAgentSession`.
29
+ */
30
+ export interface AgentRegistrationServiceLike {
31
+ createAgentSession(config: {
32
+ sessionName: string;
33
+ role: string;
34
+ projectPath: string;
35
+ windowName: string;
36
+ runtimeType: RuntimeType;
37
+ forceRecreate?: boolean;
38
+ additionalAllowlistPaths?: string[];
39
+ }): Promise<{
40
+ success: boolean;
41
+ sessionName?: string;
42
+ message?: string;
43
+ error?: string;
44
+ }>;
45
+ }
46
+ /**
47
+ * Result of `triggerOrchestratorSetup()`.
48
+ */
49
+ export interface OrchestratorSetupResult {
50
+ /** Whether the setup attempt succeeded (or the orchestrator was already healthy). */
51
+ success: boolean;
52
+ /** Session name if setup succeeded. */
53
+ sessionName?: string;
54
+ /** Human-readable status message. */
55
+ message?: string;
56
+ /** Error message if setup failed. */
57
+ error?: string;
58
+ /** True when setup was skipped because the orchestrator was already healthy. */
59
+ skipped?: boolean;
60
+ }
61
+ /**
62
+ * Injected dependencies wired by the bootstrap layer.
63
+ */
64
+ interface SetupDependencies {
65
+ agentRegistrationService: AgentRegistrationServiceLike;
66
+ storageService: StorageService;
67
+ }
68
+ /**
69
+ * Wire the dependencies needed to trigger setup from any caller.
70
+ *
71
+ * Must be called once during bootstrap, after the agent registration service
72
+ * is created. Passing the same dependencies twice is safe (last write wins).
73
+ *
74
+ * @param deps - Required service dependencies
75
+ *
76
+ * @example
77
+ * ```typescript
78
+ * setOrchestratorSetupDependencies({
79
+ * agentRegistrationService,
80
+ * storageService,
81
+ * });
82
+ * ```
83
+ */
84
+ export declare function setOrchestratorSetupDependencies(deps: SetupDependencies): void;
85
+ /**
86
+ * Reset injected dependencies. Test-only helper.
87
+ *
88
+ * @internal
89
+ */
90
+ export declare function _resetOrchestratorSetupDependenciesForTesting(): void;
91
+ /**
92
+ * Trigger orchestrator setup if it is not already healthy.
93
+ *
94
+ * Steps:
95
+ * 1. Health-check via `getOrchestratorStatus()` — if active, return early.
96
+ * 2. Resolve runtime type from persisted orchestrator status (default: claude-code).
97
+ * 3. Call `createAgentSession()` with `forceRecreate: true`.
98
+ * 4. Initialize memory and start chat monitoring (best-effort).
99
+ *
100
+ * Concurrent callers receive the same in-flight promise — at most one setup
101
+ * runs at a time across the process.
102
+ *
103
+ * The orchestrator's conversation history (`AgentRunner.state.messages`) is
104
+ * left empty after this call. The registration path skips the activation
105
+ * kickoff message for the orchestrator session — this preserves the B1
106
+ * `messageCount === 0` cold-start invariant.
107
+ *
108
+ * @returns Setup result. `skipped: true` if the orchestrator was already healthy.
109
+ *
110
+ * @throws Never — errors are returned in the result object instead.
111
+ */
112
+ export declare function triggerOrchestratorSetup(): Promise<OrchestratorSetupResult>;
113
+ export {};
114
+ //# sourceMappingURL=orchestrator-setup.service.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"orchestrator-setup.service.d.ts","sourceRoot":"","sources":["../../../../../../backend/src/services/orchestrator/orchestrator-setup.service.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAEH,OAAO,EAKN,KAAK,WAAW,EAChB,MAAM,oBAAoB,CAAC;AAG5B,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,4BAA4B,CAAC;AAKjE;;;;;;GAMG;AACH,MAAM,WAAW,4BAA4B;IAC5C,kBAAkB,CAAC,MAAM,EAAE;QAC1B,WAAW,EAAE,MAAM,CAAC;QACpB,IAAI,EAAE,MAAM,CAAC;QACb,WAAW,EAAE,MAAM,CAAC;QACpB,UAAU,EAAE,MAAM,CAAC;QACnB,WAAW,EAAE,WAAW,CAAC;QACzB,aAAa,CAAC,EAAE,OAAO,CAAC;QACxB,wBAAwB,CAAC,EAAE,MAAM,EAAE,CAAC;KACpC,GAAG,OAAO,CAAC;QAAE,OAAO,EAAE,OAAO,CAAC;QAAC,WAAW,CAAC,EAAE,MAAM,CAAC;QAAC,OAAO,CAAC,EAAE,MAAM,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;CAC1F;AAED;;GAEG;AACH,MAAM,WAAW,uBAAuB;IACvC,qFAAqF;IACrF,OAAO,EAAE,OAAO,CAAC;IACjB,uCAAuC;IACvC,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,qCAAqC;IACrC,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,qCAAqC;IACrC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,gFAAgF;IAChF,OAAO,CAAC,EAAE,OAAO,CAAC;CAClB;AAED;;GAEG;AACH,UAAU,iBAAiB;IAC1B,wBAAwB,EAAE,4BAA4B,CAAC;IACvD,cAAc,EAAE,cAAc,CAAC;CAC/B;AAQD;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,gCAAgC,CAAC,IAAI,EAAE,iBAAiB,GAAG,IAAI,CAE9E;AAED;;;;GAIG;AACH,wBAAgB,6CAA6C,IAAI,IAAI,CAGpE;AAED;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAsB,wBAAwB,IAAI,OAAO,CAAC,uBAAuB,CAAC,CAiBjF"}
@@ -0,0 +1,195 @@
1
+ /**
2
+ * Orchestrator Setup Service
3
+ *
4
+ * Provides a service-level entrypoint for triggering orchestrator setup,
5
+ * mirroring the logic behind `POST /api/orchestrator/setup`. Used by the
6
+ * SlackBridge auto-recovery path so it can reattempt setup without going
7
+ * through HTTP.
8
+ *
9
+ * Design notes:
10
+ * - Dependencies are injected via `setOrchestratorSetupDependencies()` from
11
+ * the bootstrap layer (`backend/src/index.ts`), keeping this service
12
+ * decoupled from the API context shape.
13
+ * - Concurrent calls are deduplicated via an in-flight promise — if a
14
+ * setup is already running, the second caller awaits the same result.
15
+ * - Callers should impose their own timeout on the returned promise; this
16
+ * service does not enforce a timeout because setup duration varies per
17
+ * runtime type.
18
+ *
19
+ * @module services/orchestrator/orchestrator-setup.service
20
+ */
21
+ import { ORCHESTRATOR_SESSION_NAME, ORCHESTRATOR_WINDOW_NAME, ORCHESTRATOR_ROLE, RUNTIME_TYPES, } from '../../constants.js';
22
+ import { LoggerService } from '../core/logger.service.js';
23
+ import { formatError } from '../../utils/format-error.js';
24
+ import { MemoryService } from '../memory/memory.service.js';
25
+ import { getTerminalGateway } from '../../websocket/terminal.gateway.js';
26
+ import { getOrchestratorStatus } from './orchestrator-status.service.js';
27
+ let dependencies = null;
28
+ let setupInFlight = null;
29
+ const getLogger = () => LoggerService.getInstance().createComponentLogger('OrchestratorSetup');
30
+ /**
31
+ * Wire the dependencies needed to trigger setup from any caller.
32
+ *
33
+ * Must be called once during bootstrap, after the agent registration service
34
+ * is created. Passing the same dependencies twice is safe (last write wins).
35
+ *
36
+ * @param deps - Required service dependencies
37
+ *
38
+ * @example
39
+ * ```typescript
40
+ * setOrchestratorSetupDependencies({
41
+ * agentRegistrationService,
42
+ * storageService,
43
+ * });
44
+ * ```
45
+ */
46
+ export function setOrchestratorSetupDependencies(deps) {
47
+ dependencies = deps;
48
+ }
49
+ /**
50
+ * Reset injected dependencies. Test-only helper.
51
+ *
52
+ * @internal
53
+ */
54
+ export function _resetOrchestratorSetupDependenciesForTesting() {
55
+ dependencies = null;
56
+ setupInFlight = null;
57
+ }
58
+ /**
59
+ * Trigger orchestrator setup if it is not already healthy.
60
+ *
61
+ * Steps:
62
+ * 1. Health-check via `getOrchestratorStatus()` — if active, return early.
63
+ * 2. Resolve runtime type from persisted orchestrator status (default: claude-code).
64
+ * 3. Call `createAgentSession()` with `forceRecreate: true`.
65
+ * 4. Initialize memory and start chat monitoring (best-effort).
66
+ *
67
+ * Concurrent callers receive the same in-flight promise — at most one setup
68
+ * runs at a time across the process.
69
+ *
70
+ * The orchestrator's conversation history (`AgentRunner.state.messages`) is
71
+ * left empty after this call. The registration path skips the activation
72
+ * kickoff message for the orchestrator session — this preserves the B1
73
+ * `messageCount === 0` cold-start invariant.
74
+ *
75
+ * @returns Setup result. `skipped: true` if the orchestrator was already healthy.
76
+ *
77
+ * @throws Never — errors are returned in the result object instead.
78
+ */
79
+ export async function triggerOrchestratorSetup() {
80
+ if (setupInFlight) {
81
+ // Concurrent call — caller waits on the existing setup.
82
+ return setupInFlight;
83
+ }
84
+ if (!dependencies) {
85
+ const error = 'Orchestrator setup dependencies not initialized';
86
+ getLogger().error(error);
87
+ return { success: false, error };
88
+ }
89
+ setupInFlight = _runSetup(dependencies).finally(() => {
90
+ setupInFlight = null;
91
+ });
92
+ return setupInFlight;
93
+ }
94
+ /**
95
+ * Internal setup runner. Extracted for clarity — `triggerOrchestratorSetup`
96
+ * just guards concurrency.
97
+ */
98
+ async function _runSetup(deps) {
99
+ const logger = getLogger();
100
+ try {
101
+ // 1. Skip when already healthy. Avoids hammering setup when SlackBridge's
102
+ // auto-recovery races with another caller.
103
+ try {
104
+ const currentStatus = await getOrchestratorStatus();
105
+ if (currentStatus.isActive) {
106
+ logger.info('Orchestrator is already healthy — skipping setup', {
107
+ agentStatus: currentStatus.agentStatus,
108
+ });
109
+ return {
110
+ success: true,
111
+ skipped: true,
112
+ message: 'Orchestrator is already running (setup skipped)',
113
+ sessionName: ORCHESTRATOR_SESSION_NAME,
114
+ };
115
+ }
116
+ }
117
+ catch (healthErr) {
118
+ logger.warn('Health check failed, proceeding with setup', {
119
+ error: formatError(healthErr),
120
+ });
121
+ }
122
+ // 2. Resolve runtime type. Falls back to claude-code if unknown.
123
+ let runtimeType = RUNTIME_TYPES.CLAUDE_CODE;
124
+ try {
125
+ const orchestratorStatus = await deps.storageService.getOrchestratorStatus();
126
+ const stored = orchestratorStatus?.runtimeType;
127
+ if (stored && Object.values(RUNTIME_TYPES).includes(stored)) {
128
+ runtimeType = stored;
129
+ }
130
+ }
131
+ catch (lookupErr) {
132
+ logger.warn('Failed to read runtime type from storage; defaulting to claude-code', {
133
+ error: formatError(lookupErr),
134
+ });
135
+ }
136
+ // 3. For Gemini CLI we'd normally collect project paths for the
137
+ // allowlist. The auto-recovery path is best-effort and the controller
138
+ // already does this on the explicit setup endpoint, so we keep it
139
+ // simple here. The createAgentSession contract treats the parameter
140
+ // as optional.
141
+ logger.info('Triggering createAgentSession from auto-recovery', {
142
+ sessionName: ORCHESTRATOR_SESSION_NAME,
143
+ runtimeType,
144
+ });
145
+ const result = await deps.agentRegistrationService.createAgentSession({
146
+ sessionName: ORCHESTRATOR_SESSION_NAME,
147
+ role: ORCHESTRATOR_ROLE,
148
+ projectPath: process.cwd(),
149
+ windowName: ORCHESTRATOR_WINDOW_NAME,
150
+ runtimeType,
151
+ forceRecreate: true,
152
+ });
153
+ if (!result.success) {
154
+ logger.error('createAgentSession returned failure', { error: result.error });
155
+ return {
156
+ success: false,
157
+ error: result.error || 'Failed to create orchestrator session',
158
+ };
159
+ }
160
+ // 4. Best-effort memory init + chat monitoring. Failures here do not
161
+ // block setup success — the session is created, these are auxiliary.
162
+ try {
163
+ await MemoryService.getInstance().initializeForSession(ORCHESTRATOR_SESSION_NAME, ORCHESTRATOR_ROLE, process.cwd());
164
+ }
165
+ catch (memErr) {
166
+ logger.warn('Memory initialization failed (non-fatal)', {
167
+ error: formatError(memErr),
168
+ });
169
+ }
170
+ try {
171
+ const terminalGateway = getTerminalGateway();
172
+ if (terminalGateway) {
173
+ terminalGateway.startOrchestratorChatMonitoring(ORCHESTRATOR_SESSION_NAME);
174
+ }
175
+ }
176
+ catch (monitorErr) {
177
+ logger.warn('Failed to start chat monitoring (non-fatal)', {
178
+ error: formatError(monitorErr),
179
+ });
180
+ }
181
+ return {
182
+ success: true,
183
+ sessionName: result.sessionName ?? ORCHESTRATOR_SESSION_NAME,
184
+ message: result.message ?? 'Orchestrator session created and registered',
185
+ };
186
+ }
187
+ catch (error) {
188
+ logger.error('Auto-recovery setup failed', { error: formatError(error) });
189
+ return {
190
+ success: false,
191
+ error: error instanceof Error ? error.message : 'Failed to setup orchestrator session',
192
+ };
193
+ }
194
+ }
195
+ //# sourceMappingURL=orchestrator-setup.service.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"orchestrator-setup.service.js","sourceRoot":"","sources":["../../../../../../backend/src/services/orchestrator/orchestrator-setup.service.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"orchestrator-status.service.d.ts","sourceRoot":"","sources":["../../../../../../backend/src/services/orchestrator/orchestrator-status.service.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AASH;;GAEG;AACH,MAAM,WAAW,wBAAwB;IACvC,uEAAuE;IACvE,QAAQ,EAAE,OAAO,CAAC;IAClB,mDAAmD;IACnD,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,oCAAoC;IACpC,OAAO,EAAE,MAAM,CAAC;CACjB;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAsB,oBAAoB,IAAI,OAAO,CAAC,OAAO,CAAC,CAG7D;AAED;;;;;;;;;;;;;;;GAeG;AACH,wBAAsB,qBAAqB,IAAI,OAAO,CAAC,wBAAwB,CAAC,CAyI/E;AAED;;;;;;GAMG;AACH,wBAAsB,aAAa,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAczE;AAED;;;;;;GAMG;AACH,wBAAgB,6BAA6B,CAAC,UAAU,UAAO,GAAG,MAAM,CAMvE"}
1
+ {"version":3,"file":"orchestrator-status.service.d.ts","sourceRoot":"","sources":["../../../../../../backend/src/services/orchestrator/orchestrator-status.service.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAWH;;GAEG;AACH,MAAM,WAAW,wBAAwB;IACvC,uEAAuE;IACvE,QAAQ,EAAE,OAAO,CAAC;IAClB,mDAAmD;IACnD,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,oCAAoC;IACpC,OAAO,EAAE,MAAM,CAAC;CACjB;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAsB,oBAAoB,IAAI,OAAO,CAAC,OAAO,CAAC,CAG7D;AAED;;;;;;;;;;;;;;;GAeG;AACH,wBAAsB,qBAAqB,IAAI,OAAO,CAAC,wBAAwB,CAAC,CAqJ/E;AAED;;;;;;GAMG;AACH,wBAAsB,aAAa,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAczE;AAED;;;;;;GAMG;AACH,wBAAgB,6BAA6B,CAAC,UAAU,UAAO,GAAG,MAAM,CAMvE"}
@@ -10,6 +10,8 @@
10
10
  import { StorageService } from '../core/storage.service.js';
11
11
  import { CREWLY_CONSTANTS, WEB_CONSTANTS } from '../../../../config/index.js';
12
12
  import { getSessionBackendSync } from '../session/index.js';
13
+ import { isInProcessRuntimeActive } from '../agent/crewly-agent/in-process-runtime-registry.js';
14
+ import { RUNTIME_TYPES } from '../../constants.js';
13
15
  /** Dashboard URL for user-facing messages */
14
16
  const DASHBOARD_URL = `http://localhost:${WEB_CONSTANTS.PORTS.FRONTEND}`;
15
17
  /**
@@ -58,9 +60,9 @@ export async function getOrchestratorStatus() {
58
60
  // aligning with how the teams controller checks session existence.
59
61
  let sessionExists = false;
60
62
  let sessionCheckPerformed = false;
63
+ const sessionName = orchestratorStatus?.sessionName || CREWLY_CONSTANTS.SESSIONS.ORCHESTRATOR_NAME;
61
64
  try {
62
65
  const sessionBackend = getSessionBackendSync();
63
- const sessionName = orchestratorStatus?.sessionName || CREWLY_CONSTANTS.SESSIONS.ORCHESTRATOR_NAME;
64
66
  if (sessionBackend && sessionName) {
65
67
  sessionExists = sessionBackend.sessionExists(sessionName);
66
68
  sessionCheckPerformed = true;
@@ -69,6 +71,19 @@ export async function getOrchestratorStatus() {
69
71
  catch {
70
72
  // Ignore session check errors - fall back to storage-based status
71
73
  }
74
+ // Runtime-aware fallback (B0 hot-fix):
75
+ // The PTY-based `sessionExists()` returns false for in-process Crewly
76
+ // Agent runtimes because they have no PTY session. Treat the session as
77
+ // alive when the runtime type is `crewly-agent` AND the in-process
78
+ // registry confirms a ready runtime is registered. The PTY path is
79
+ // untouched for `claude-code` / other runtimes.
80
+ if (!sessionExists
81
+ && orchestratorStatus?.runtimeType === RUNTIME_TYPES.CREWLY_AGENT
82
+ && sessionName
83
+ && isInProcessRuntimeActive(sessionName)) {
84
+ sessionExists = true;
85
+ sessionCheckPerformed = true;
86
+ }
72
87
  if (!orchestratorStatus) {
73
88
  return {
74
89
  isActive: false,
@@ -99,8 +114,7 @@ export async function getOrchestratorStatus() {
99
114
  if (sessionCheckPerformed && !sessionExists && agentStatus === CREWLY_CONSTANTS.AGENT_STATUSES.ACTIVE) {
100
115
  try {
101
116
  const storageServiceForCleanup = StorageService.getInstance();
102
- const cleanupSessionName = orchestratorStatus?.sessionName || CREWLY_CONSTANTS.SESSIONS.ORCHESTRATOR_NAME;
103
- await storageServiceForCleanup.updateAgentStatus(cleanupSessionName, CREWLY_CONSTANTS.AGENT_STATUSES.INACTIVE);
117
+ await storageServiceForCleanup.updateAgentStatus(sessionName, CREWLY_CONSTANTS.AGENT_STATUSES.INACTIVE);
104
118
  }
105
119
  catch {
106
120
  // Best-effort cleanup — don't let it break the status check
@@ -125,7 +139,6 @@ export async function getOrchestratorStatus() {
125
139
  let childProcessAlive = false;
126
140
  try {
127
141
  const sessionBackend = getSessionBackendSync();
128
- const sessionName = orchestratorStatus?.sessionName || CREWLY_CONSTANTS.SESSIONS.ORCHESTRATOR_NAME;
129
142
  childProcessAlive = !!sessionBackend?.isChildProcessAlive?.(sessionName);
130
143
  }
131
144
  catch {
@@ -135,8 +148,7 @@ export async function getOrchestratorStatus() {
135
148
  // Best-effort: persist the recovered status but return active regardless
136
149
  try {
137
150
  const storageServiceForRecovery = StorageService.getInstance();
138
- const recoverySessionName = orchestratorStatus?.sessionName || CREWLY_CONSTANTS.SESSIONS.ORCHESTRATOR_NAME;
139
- await storageServiceForRecovery.updateAgentStatus(recoverySessionName, CREWLY_CONSTANTS.AGENT_STATUSES.ACTIVE);
151
+ await storageServiceForRecovery.updateAgentStatus(sessionName, CREWLY_CONSTANTS.AGENT_STATUSES.ACTIVE);
140
152
  }
141
153
  catch {
142
154
  // Best-effort — don't let persist failure block recovery
@@ -1 +1 @@
1
- {"version":3,"file":"orchestrator-status.service.js","sourceRoot":"","sources":["../../../../../../backend/src/services/orchestrator/orchestrator-status.service.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"orchestrator-status.service.js","sourceRoot":"","sources":["../../../../../../backend/src/services/orchestrator/orchestrator-status.service.ts"],"names":[],"mappings":"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"}
@@ -173,6 +173,29 @@ export declare class SlackOrchestratorBridge extends EventEmitter {
173
173
  * @returns Control response
174
174
  */
175
175
  private handleControlCommand;
176
+ /**
177
+ * Attempt to auto-recover the orchestrator with a hard timeout.
178
+ *
179
+ * Calls `triggerOrchestratorSetup()` from the orchestrator service module
180
+ * directly (bypassing HTTP). Wraps the attempt in a 5-second deadline so
181
+ * a wedged setup cannot stall the Slack message ingress thread.
182
+ *
183
+ * Behavior:
184
+ * - Timeout: rejects with a TimeoutError-like message after 5s.
185
+ * - Setup error: rejects with the underlying error.
186
+ * - Setup returning `success: false`: rejects with the recorded error
187
+ * (the caller treats this the same as a thrown error and falls
188
+ * through to the offline path).
189
+ *
190
+ * Caller is expected to wrap the call in try/catch and continue down
191
+ * the offline path on rejection — auto-recovery is best-effort.
192
+ *
193
+ * @returns Resolves when setup completes successfully (or was skipped
194
+ * because the orc was already healthy)
195
+ * @throws Error on timeout or setup failure
196
+ * @internal Visible for tests via class member access.
197
+ */
198
+ private attemptAutoRecovery;
176
199
  /**
177
200
  * Send message to orchestrator via the message queue and wait for response.
178
201
  *
@@ -1 +1 @@
1
- {"version":3,"file":"slack-orchestrator-bridge.d.ts","sourceRoot":"","sources":["../../../../../../backend/src/services/slack/slack-orchestrator-bridge.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"slack-orchestrator-bridge.d.ts","sourceRoot":"","sources":["../../../../../../backend/src/services/slack/slack-orchestrator-bridge.ts"],"names":[],"mappings":"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"}
@@ -15,7 +15,7 @@ import { pipeline } from 'stream/promises';
15
15
  import { PDFParse } from 'pdf-parse';
16
16
  import { getSlackService } from './slack.service.js';
17
17
  import { getChatService } from '../chat/chat.service.js';
18
- import { isOrchestratorActive, isAgentActive, getOrchestratorOfflineMessage, } from '../orchestrator/index.js';
18
+ import { isOrchestratorActive, isAgentActive, getOrchestratorOfflineMessage, triggerOrchestratorSetup, } from '../orchestrator/index.js';
19
19
  import { parseCommandIntent, } from '../../types/slack.types.js';
20
20
  import { ContentApprovalService } from '../onboarding/content-approval.service.js';
21
21
  import { getSlackImageService } from './slack-image.service.js';
@@ -34,6 +34,12 @@ const DEFAULT_CONFIG = {
34
34
  responseTimeoutMs: (MESSAGE_QUEUE_CONSTANTS?.DEFAULT_MESSAGE_TIMEOUT ?? 120000) + 5000,
35
35
  skillDeliveryWaitMs: SLACK_BRIDGE_CONSTANTS?.SKILL_DELIVERY_WAIT_MS ?? 3000,
36
36
  };
37
+ /**
38
+ * Maximum time to wait for an auto-recovery setup attempt before giving
39
+ * up and falling through to the offline path. Capped tight to avoid
40
+ * blocking the message ingress thread when setup is wedged.
41
+ */
42
+ const AUTO_RECOVERY_TIMEOUT_MS = 5_000;
37
43
  /**
38
44
  * Slack-Orchestrator Bridge singleton
39
45
  */
@@ -521,6 +527,49 @@ Just type naturally to chat with the orchestrator!`;
521
527
  const target = command.parameters.target || command.parameters.mention || 'all agents';
522
528
  return await this.sendToOrchestrator(`${action} ${target}.`, context);
523
529
  }
530
+ /**
531
+ * Attempt to auto-recover the orchestrator with a hard timeout.
532
+ *
533
+ * Calls `triggerOrchestratorSetup()` from the orchestrator service module
534
+ * directly (bypassing HTTP). Wraps the attempt in a 5-second deadline so
535
+ * a wedged setup cannot stall the Slack message ingress thread.
536
+ *
537
+ * Behavior:
538
+ * - Timeout: rejects with a TimeoutError-like message after 5s.
539
+ * - Setup error: rejects with the underlying error.
540
+ * - Setup returning `success: false`: rejects with the recorded error
541
+ * (the caller treats this the same as a thrown error and falls
542
+ * through to the offline path).
543
+ *
544
+ * Caller is expected to wrap the call in try/catch and continue down
545
+ * the offline path on rejection — auto-recovery is best-effort.
546
+ *
547
+ * @returns Resolves when setup completes successfully (or was skipped
548
+ * because the orc was already healthy)
549
+ * @throws Error on timeout or setup failure
550
+ * @internal Visible for tests via class member access.
551
+ */
552
+ async attemptAutoRecovery() {
553
+ let timeoutHandle;
554
+ const timeoutPromise = new Promise((_, reject) => {
555
+ timeoutHandle = setTimeout(() => {
556
+ reject(new Error(`auto-recovery setup timed out after ${AUTO_RECOVERY_TIMEOUT_MS}ms`));
557
+ }, AUTO_RECOVERY_TIMEOUT_MS);
558
+ // Don't keep the process alive just for this timer
559
+ timeoutHandle.unref?.();
560
+ });
561
+ try {
562
+ const result = await Promise.race([triggerOrchestratorSetup(), timeoutPromise]);
563
+ if (!result.success) {
564
+ throw new Error(result.error || 'orchestrator setup returned success=false');
565
+ }
566
+ }
567
+ finally {
568
+ if (timeoutHandle) {
569
+ clearTimeout(timeoutHandle);
570
+ }
571
+ }
572
+ }
524
573
  /**
525
574
  * Send message to orchestrator via the message queue and wait for response.
526
575
  *
@@ -534,7 +583,35 @@ Just type naturally to chat with the orchestrator!`;
534
583
  async sendToOrchestrator(message, context) {
535
584
  try {
536
585
  // Check if orchestrator is active before attempting to send
537
- const isActive = await isOrchestratorActive();
586
+ let isActive = await isOrchestratorActive();
587
+ // Auto-recovery (B0 hot-fix, defense-in-depth):
588
+ // ESTestNode regression — `isActive` falsely reports offline when the
589
+ // orchestrator is an in-process Crewly Agent runtime that has lost its
590
+ // status registration but is otherwise healthy. Before falling
591
+ // through to the offline path, attempt one synchronous setup call.
592
+ // This is intentionally once-per-message (not retry-loop). On
593
+ // success we re-check isActive and proceed normally; on failure we
594
+ // continue down the existing offline branch (Auditor + queue).
595
+ if (!isActive) {
596
+ const recoveryStart = Date.now();
597
+ this.logger.info('Orchestrator offline — attempting auto-recovery via triggerOrchestratorSetup', {
598
+ timeoutMs: AUTO_RECOVERY_TIMEOUT_MS,
599
+ });
600
+ try {
601
+ await this.attemptAutoRecovery();
602
+ isActive = await isOrchestratorActive();
603
+ this.logger.info('Auto-recovery setup attempt complete', {
604
+ elapsedMs: Date.now() - recoveryStart,
605
+ isActiveAfter: isActive,
606
+ });
607
+ }
608
+ catch (err) {
609
+ this.logger.warn('Auto-recovery setup attempt failed (falling through to offline path)', {
610
+ elapsedMs: Date.now() - recoveryStart,
611
+ error: err instanceof Error ? err.message : String(err),
612
+ });
613
+ }
614
+ }
538
615
  if (!isActive) {
539
616
  // Fallback: route to Auditor agent if it's active
540
617
  const auditorSession = AUDITOR_SCHEDULER_CONSTANTS.AUDITOR_SESSION_NAME;