crewly 1.6.3 → 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.
- package/config/slack-app-manifest.json +1 -2
- package/dist/backend/backend/src/index.d.ts.map +1 -1
- package/dist/backend/backend/src/index.js +16 -0
- package/dist/backend/backend/src/index.js.map +1 -1
- package/dist/backend/backend/src/services/agent/agent-registration.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/agent/agent-registration.service.js +30 -8
- package/dist/backend/backend/src/services/agent/agent-registration.service.js.map +1 -1
- package/dist/backend/backend/src/services/agent/crewly-agent/in-process-runtime-registry.d.ts +91 -0
- package/dist/backend/backend/src/services/agent/crewly-agent/in-process-runtime-registry.d.ts.map +1 -0
- package/dist/backend/backend/src/services/agent/crewly-agent/in-process-runtime-registry.js +120 -0
- package/dist/backend/backend/src/services/agent/crewly-agent/in-process-runtime-registry.js.map +1 -0
- package/dist/backend/backend/src/services/orchestrator/index.d.ts +1 -0
- package/dist/backend/backend/src/services/orchestrator/index.d.ts.map +1 -1
- package/dist/backend/backend/src/services/orchestrator/index.js +1 -0
- package/dist/backend/backend/src/services/orchestrator/index.js.map +1 -1
- package/dist/backend/backend/src/services/orchestrator/orchestrator-setup.service.d.ts +114 -0
- package/dist/backend/backend/src/services/orchestrator/orchestrator-setup.service.d.ts.map +1 -0
- package/dist/backend/backend/src/services/orchestrator/orchestrator-setup.service.js +195 -0
- package/dist/backend/backend/src/services/orchestrator/orchestrator-setup.service.js.map +1 -0
- package/dist/backend/backend/src/services/orchestrator/orchestrator-status.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/orchestrator/orchestrator-status.service.js +18 -6
- package/dist/backend/backend/src/services/orchestrator/orchestrator-status.service.js.map +1 -1
- package/dist/backend/backend/src/services/slack/slack-orchestrator-bridge.d.ts +23 -0
- package/dist/backend/backend/src/services/slack/slack-orchestrator-bridge.d.ts.map +1 -1
- package/dist/backend/backend/src/services/slack/slack-orchestrator-bridge.js +79 -2
- package/dist/backend/backend/src/services/slack/slack-orchestrator-bridge.js.map +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* In-Process Runtime Registry
|
|
3
|
+
*
|
|
4
|
+
* Module-level registry that tracks active in-process Crewly Agent runtimes
|
|
5
|
+
* by session name. Provides a lightweight lookup mechanism for callers (such
|
|
6
|
+
* as `orchestrator-status.service.ts`) that need to determine whether an
|
|
7
|
+
* in-process runtime is alive without holding a reference to the
|
|
8
|
+
* `AgentRegistrationService` instance.
|
|
9
|
+
*
|
|
10
|
+
* Why this exists (B0 hot-fix):
|
|
11
|
+
* The PTY-based `sessionExists()` check returns `false` for in-process
|
|
12
|
+
* Crewly Agent runtimes because they have no PTY session. Before this
|
|
13
|
+
* registry, the orchestrator-status service had no runtime-aware fallback,
|
|
14
|
+
* so `isActive` would report `false` for healthy in-process orchestrators
|
|
15
|
+
* — causing SlackBridge to incorrectly route messages to the offline path.
|
|
16
|
+
*
|
|
17
|
+
* The `AgentRegistrationService` already maintains an internal
|
|
18
|
+
* `inProcessRuntimes` map for in-process runtime routing. This module
|
|
19
|
+
* mirrors that knowledge at module scope so any caller can probe runtime
|
|
20
|
+
* health without a service-locator dance.
|
|
21
|
+
*
|
|
22
|
+
* @module services/agent/crewly-agent/in-process-runtime-registry
|
|
23
|
+
*/
|
|
24
|
+
import type { CrewlyAgentRuntimeService } from './crewly-agent-runtime.service.js';
|
|
25
|
+
/**
|
|
26
|
+
* Register an in-process Crewly Agent runtime.
|
|
27
|
+
*
|
|
28
|
+
* Called by `AgentRegistrationService` after `initializeInProcess()`
|
|
29
|
+
* succeeds. If a runtime is already registered for the same session, it is
|
|
30
|
+
* replaced — the old reference is discarded but not shut down (the caller
|
|
31
|
+
* is responsible for the lifecycle).
|
|
32
|
+
*
|
|
33
|
+
* @param sessionName - Session name owning the runtime (e.g. 'crewly-orc')
|
|
34
|
+
* @param runtime - The initialized CrewlyAgentRuntimeService instance
|
|
35
|
+
*
|
|
36
|
+
* @example
|
|
37
|
+
* ```typescript
|
|
38
|
+
* registerInProcessRuntime('crewly-orc', crewlyRuntime);
|
|
39
|
+
* ```
|
|
40
|
+
*/
|
|
41
|
+
export declare function registerInProcessRuntime(sessionName: string, runtime: CrewlyAgentRuntimeService): void;
|
|
42
|
+
/**
|
|
43
|
+
* Unregister an in-process runtime by session name.
|
|
44
|
+
*
|
|
45
|
+
* Called when a runtime is shut down or the session is destroyed.
|
|
46
|
+
* Idempotent — safe to call when the session is not registered.
|
|
47
|
+
*
|
|
48
|
+
* @param sessionName - Session name to remove
|
|
49
|
+
* @returns True if a runtime was removed, false if none was registered
|
|
50
|
+
*/
|
|
51
|
+
export declare function unregisterInProcessRuntime(sessionName: string): boolean;
|
|
52
|
+
/**
|
|
53
|
+
* Look up an in-process runtime by session name.
|
|
54
|
+
*
|
|
55
|
+
* @param sessionName - Session name to look up
|
|
56
|
+
* @returns The CrewlyAgentRuntimeService if registered, undefined otherwise
|
|
57
|
+
*/
|
|
58
|
+
export declare function getInProcessRuntime(sessionName: string): CrewlyAgentRuntimeService | undefined;
|
|
59
|
+
/**
|
|
60
|
+
* Check whether an in-process runtime exists and is ready to handle
|
|
61
|
+
* messages for the given session.
|
|
62
|
+
*
|
|
63
|
+
* Returns `true` only when both:
|
|
64
|
+
* - A runtime is registered for the session
|
|
65
|
+
* - The runtime's `isReady()` returns `true`
|
|
66
|
+
*
|
|
67
|
+
* This is the function callers should use when answering "is this
|
|
68
|
+
* session alive?" — it correctly handles both the worker-process and
|
|
69
|
+
* direct in-process modes of `CrewlyAgentRuntimeService`.
|
|
70
|
+
*
|
|
71
|
+
* @param sessionName - Session name to check
|
|
72
|
+
* @returns True when the runtime exists and is ready
|
|
73
|
+
*/
|
|
74
|
+
export declare function isInProcessRuntimeActive(sessionName: string): boolean;
|
|
75
|
+
/**
|
|
76
|
+
* Reset the registry. Test-only helper.
|
|
77
|
+
*
|
|
78
|
+
* Leaves any actually-running runtimes untouched — only clears the
|
|
79
|
+
* registry's bookkeeping. Production code must never call this.
|
|
80
|
+
*
|
|
81
|
+
* @internal
|
|
82
|
+
*/
|
|
83
|
+
export declare function _resetInProcessRuntimeRegistryForTesting(): void;
|
|
84
|
+
/**
|
|
85
|
+
* Get the current registry size. Test-only helper.
|
|
86
|
+
*
|
|
87
|
+
* @returns Number of registered runtimes
|
|
88
|
+
* @internal
|
|
89
|
+
*/
|
|
90
|
+
export declare function _getInProcessRuntimeRegistrySize(): number;
|
|
91
|
+
//# sourceMappingURL=in-process-runtime-registry.d.ts.map
|
package/dist/backend/backend/src/services/agent/crewly-agent/in-process-runtime-registry.d.ts.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"in-process-runtime-registry.d.ts","sourceRoot":"","sources":["../../../../../../../backend/src/services/agent/crewly-agent/in-process-runtime-registry.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AAEH,OAAO,KAAK,EAAE,yBAAyB,EAAE,MAAM,mCAAmC,CAAC;AAWnF;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,wBAAwB,CACtC,WAAW,EAAE,MAAM,EACnB,OAAO,EAAE,yBAAyB,GACjC,IAAI,CAEN;AAED;;;;;;;;GAQG;AACH,wBAAgB,0BAA0B,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAEvE;AAED;;;;;GAKG;AACH,wBAAgB,mBAAmB,CACjC,WAAW,EAAE,MAAM,GAClB,yBAAyB,GAAG,SAAS,CAEvC;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,wBAAwB,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAWrE;AAED;;;;;;;GAOG;AACH,wBAAgB,wCAAwC,IAAI,IAAI,CAE/D;AAED;;;;;GAKG;AACH,wBAAgB,gCAAgC,IAAI,MAAM,CAEzD"}
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* In-Process Runtime Registry
|
|
3
|
+
*
|
|
4
|
+
* Module-level registry that tracks active in-process Crewly Agent runtimes
|
|
5
|
+
* by session name. Provides a lightweight lookup mechanism for callers (such
|
|
6
|
+
* as `orchestrator-status.service.ts`) that need to determine whether an
|
|
7
|
+
* in-process runtime is alive without holding a reference to the
|
|
8
|
+
* `AgentRegistrationService` instance.
|
|
9
|
+
*
|
|
10
|
+
* Why this exists (B0 hot-fix):
|
|
11
|
+
* The PTY-based `sessionExists()` check returns `false` for in-process
|
|
12
|
+
* Crewly Agent runtimes because they have no PTY session. Before this
|
|
13
|
+
* registry, the orchestrator-status service had no runtime-aware fallback,
|
|
14
|
+
* so `isActive` would report `false` for healthy in-process orchestrators
|
|
15
|
+
* — causing SlackBridge to incorrectly route messages to the offline path.
|
|
16
|
+
*
|
|
17
|
+
* The `AgentRegistrationService` already maintains an internal
|
|
18
|
+
* `inProcessRuntimes` map for in-process runtime routing. This module
|
|
19
|
+
* mirrors that knowledge at module scope so any caller can probe runtime
|
|
20
|
+
* health without a service-locator dance.
|
|
21
|
+
*
|
|
22
|
+
* @module services/agent/crewly-agent/in-process-runtime-registry
|
|
23
|
+
*/
|
|
24
|
+
/**
|
|
25
|
+
* Module-level registry of active in-process runtimes keyed by session name.
|
|
26
|
+
*
|
|
27
|
+
* Mirrors `AgentRegistrationService.inProcessRuntimes`. Both maps must stay
|
|
28
|
+
* in sync — `AgentRegistrationService` writes to this registry whenever it
|
|
29
|
+
* registers/unregisters a runtime.
|
|
30
|
+
*/
|
|
31
|
+
const registry = new Map();
|
|
32
|
+
/**
|
|
33
|
+
* Register an in-process Crewly Agent runtime.
|
|
34
|
+
*
|
|
35
|
+
* Called by `AgentRegistrationService` after `initializeInProcess()`
|
|
36
|
+
* succeeds. If a runtime is already registered for the same session, it is
|
|
37
|
+
* replaced — the old reference is discarded but not shut down (the caller
|
|
38
|
+
* is responsible for the lifecycle).
|
|
39
|
+
*
|
|
40
|
+
* @param sessionName - Session name owning the runtime (e.g. 'crewly-orc')
|
|
41
|
+
* @param runtime - The initialized CrewlyAgentRuntimeService instance
|
|
42
|
+
*
|
|
43
|
+
* @example
|
|
44
|
+
* ```typescript
|
|
45
|
+
* registerInProcessRuntime('crewly-orc', crewlyRuntime);
|
|
46
|
+
* ```
|
|
47
|
+
*/
|
|
48
|
+
export function registerInProcessRuntime(sessionName, runtime) {
|
|
49
|
+
registry.set(sessionName, runtime);
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Unregister an in-process runtime by session name.
|
|
53
|
+
*
|
|
54
|
+
* Called when a runtime is shut down or the session is destroyed.
|
|
55
|
+
* Idempotent — safe to call when the session is not registered.
|
|
56
|
+
*
|
|
57
|
+
* @param sessionName - Session name to remove
|
|
58
|
+
* @returns True if a runtime was removed, false if none was registered
|
|
59
|
+
*/
|
|
60
|
+
export function unregisterInProcessRuntime(sessionName) {
|
|
61
|
+
return registry.delete(sessionName);
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* Look up an in-process runtime by session name.
|
|
65
|
+
*
|
|
66
|
+
* @param sessionName - Session name to look up
|
|
67
|
+
* @returns The CrewlyAgentRuntimeService if registered, undefined otherwise
|
|
68
|
+
*/
|
|
69
|
+
export function getInProcessRuntime(sessionName) {
|
|
70
|
+
return registry.get(sessionName);
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* Check whether an in-process runtime exists and is ready to handle
|
|
74
|
+
* messages for the given session.
|
|
75
|
+
*
|
|
76
|
+
* Returns `true` only when both:
|
|
77
|
+
* - A runtime is registered for the session
|
|
78
|
+
* - The runtime's `isReady()` returns `true`
|
|
79
|
+
*
|
|
80
|
+
* This is the function callers should use when answering "is this
|
|
81
|
+
* session alive?" — it correctly handles both the worker-process and
|
|
82
|
+
* direct in-process modes of `CrewlyAgentRuntimeService`.
|
|
83
|
+
*
|
|
84
|
+
* @param sessionName - Session name to check
|
|
85
|
+
* @returns True when the runtime exists and is ready
|
|
86
|
+
*/
|
|
87
|
+
export function isInProcessRuntimeActive(sessionName) {
|
|
88
|
+
const runtime = registry.get(sessionName);
|
|
89
|
+
if (!runtime) {
|
|
90
|
+
return false;
|
|
91
|
+
}
|
|
92
|
+
try {
|
|
93
|
+
return runtime.isReady();
|
|
94
|
+
}
|
|
95
|
+
catch {
|
|
96
|
+
// Defensive: a misbehaving isReady() must not break callers.
|
|
97
|
+
return false;
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
/**
|
|
101
|
+
* Reset the registry. Test-only helper.
|
|
102
|
+
*
|
|
103
|
+
* Leaves any actually-running runtimes untouched — only clears the
|
|
104
|
+
* registry's bookkeeping. Production code must never call this.
|
|
105
|
+
*
|
|
106
|
+
* @internal
|
|
107
|
+
*/
|
|
108
|
+
export function _resetInProcessRuntimeRegistryForTesting() {
|
|
109
|
+
registry.clear();
|
|
110
|
+
}
|
|
111
|
+
/**
|
|
112
|
+
* Get the current registry size. Test-only helper.
|
|
113
|
+
*
|
|
114
|
+
* @returns Number of registered runtimes
|
|
115
|
+
* @internal
|
|
116
|
+
*/
|
|
117
|
+
export function _getInProcessRuntimeRegistrySize() {
|
|
118
|
+
return registry.size;
|
|
119
|
+
}
|
|
120
|
+
//# sourceMappingURL=in-process-runtime-registry.js.map
|
package/dist/backend/backend/src/services/agent/crewly-agent/in-process-runtime-registry.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"in-process-runtime-registry.js","sourceRoot":"","sources":["../../../../../../../backend/src/services/agent/crewly-agent/in-process-runtime-registry.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AAIH;;;;;;GAMG;AACH,MAAM,QAAQ,GAA2C,IAAI,GAAG,EAAE,CAAC;AAEnE;;;;;;;;;;;;;;;GAeG;AACH,MAAM,UAAU,wBAAwB,CACtC,WAAmB,EACnB,OAAkC;IAElC,QAAQ,CAAC,GAAG,CAAC,WAAW,EAAE,OAAO,CAAC,CAAC;AACrC,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,UAAU,0BAA0B,CAAC,WAAmB;IAC5D,OAAO,QAAQ,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC;AACtC,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,mBAAmB,CACjC,WAAmB;IAEnB,OAAO,QAAQ,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC;AACnC,CAAC;AAED;;;;;;;;;;;;;;GAcG;AACH,MAAM,UAAU,wBAAwB,CAAC,WAAmB;IAC1D,MAAM,OAAO,GAAG,QAAQ,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC;IAC1C,IAAI,CAAC,OAAO,EAAE,CAAC;QACb,OAAO,KAAK,CAAC;IACf,CAAC;IACD,IAAI,CAAC;QACH,OAAO,OAAO,CAAC,OAAO,EAAE,CAAC;IAC3B,CAAC;IAAC,MAAM,CAAC;QACP,6DAA6D;QAC7D,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,UAAU,wCAAwC;IACtD,QAAQ,CAAC,KAAK,EAAE,CAAC;AACnB,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,gCAAgC;IAC9C,OAAO,QAAQ,CAAC,IAAI,CAAC;AACvB,CAAC"}
|
|
@@ -12,4 +12,5 @@ export { ImprovementMarkerService, getImprovementMarkerService, resetImprovement
|
|
|
12
12
|
export { ImprovementStartupService, getImprovementStartupService, resetImprovementStartupService, type StartupResult, } from './improvement-startup.service.js';
|
|
13
13
|
export { isOrchestratorActive, isAgentActive, getOrchestratorStatus, getOrchestratorOfflineMessage, type OrchestratorStatusResult, } from './orchestrator-status.service.js';
|
|
14
14
|
export { OrchestratorRestartService, type RestartStats, } from './orchestrator-restart.service.js';
|
|
15
|
+
export { triggerOrchestratorSetup, setOrchestratorSetupDependencies, type OrchestratorSetupResult, type AgentRegistrationServiceLike, } from './orchestrator-setup.service.js';
|
|
15
16
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../../backend/src/services/orchestrator/index.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EACL,uBAAuB,EACvB,0BAA0B,EAC1B,4BAA4B,GAC7B,MAAM,gCAAgC,CAAC;AAExC,OAAO,EACL,kBAAkB,EAClB,qBAAqB,EACrB,uBAAuB,EACvB,KAAK,aAAa,EAClB,KAAK,aAAa,GACnB,MAAM,2BAA2B,CAAC;AAEnC,OAAO,EACL,sBAAsB,EACtB,yBAAyB,EACzB,2BAA2B,EAC3B,KAAK,kBAAkB,EACvB,KAAK,iBAAiB,EACtB,KAAK,eAAe,GACrB,MAAM,+BAA+B,CAAC;AAEvC,OAAO,EACL,wBAAwB,EACxB,2BAA2B,EAC3B,6BAA6B,EAC7B,KAAK,iBAAiB,EACtB,KAAK,gBAAgB,EACrB,KAAK,gBAAgB,EACrB,KAAK,gBAAgB,GACtB,MAAM,iCAAiC,CAAC;AAEzC,OAAO,EACL,yBAAyB,EACzB,4BAA4B,EAC5B,8BAA8B,EAC9B,KAAK,aAAa,GACnB,MAAM,kCAAkC,CAAC;AAE1C,OAAO,EACL,oBAAoB,EACpB,aAAa,EACb,qBAAqB,EACrB,6BAA6B,EAC7B,KAAK,wBAAwB,GAC9B,MAAM,kCAAkC,CAAC;AAE1C,OAAO,EACL,0BAA0B,EAC1B,KAAK,YAAY,GAClB,MAAM,mCAAmC,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../../backend/src/services/orchestrator/index.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EACL,uBAAuB,EACvB,0BAA0B,EAC1B,4BAA4B,GAC7B,MAAM,gCAAgC,CAAC;AAExC,OAAO,EACL,kBAAkB,EAClB,qBAAqB,EACrB,uBAAuB,EACvB,KAAK,aAAa,EAClB,KAAK,aAAa,GACnB,MAAM,2BAA2B,CAAC;AAEnC,OAAO,EACL,sBAAsB,EACtB,yBAAyB,EACzB,2BAA2B,EAC3B,KAAK,kBAAkB,EACvB,KAAK,iBAAiB,EACtB,KAAK,eAAe,GACrB,MAAM,+BAA+B,CAAC;AAEvC,OAAO,EACL,wBAAwB,EACxB,2BAA2B,EAC3B,6BAA6B,EAC7B,KAAK,iBAAiB,EACtB,KAAK,gBAAgB,EACrB,KAAK,gBAAgB,EACrB,KAAK,gBAAgB,GACtB,MAAM,iCAAiC,CAAC;AAEzC,OAAO,EACL,yBAAyB,EACzB,4BAA4B,EAC5B,8BAA8B,EAC9B,KAAK,aAAa,GACnB,MAAM,kCAAkC,CAAC;AAE1C,OAAO,EACL,oBAAoB,EACpB,aAAa,EACb,qBAAqB,EACrB,6BAA6B,EAC7B,KAAK,wBAAwB,GAC9B,MAAM,kCAAkC,CAAC;AAE1C,OAAO,EACL,0BAA0B,EAC1B,KAAK,YAAY,GAClB,MAAM,mCAAmC,CAAC;AAE3C,OAAO,EACL,wBAAwB,EACxB,gCAAgC,EAChC,KAAK,uBAAuB,EAC5B,KAAK,4BAA4B,GAClC,MAAM,iCAAiC,CAAC"}
|
|
@@ -12,4 +12,5 @@ export { ImprovementMarkerService, getImprovementMarkerService, resetImprovement
|
|
|
12
12
|
export { ImprovementStartupService, getImprovementStartupService, resetImprovementStartupService, } from './improvement-startup.service.js';
|
|
13
13
|
export { isOrchestratorActive, isAgentActive, getOrchestratorStatus, getOrchestratorOfflineMessage, } from './orchestrator-status.service.js';
|
|
14
14
|
export { OrchestratorRestartService, } from './orchestrator-restart.service.js';
|
|
15
|
+
export { triggerOrchestratorSetup, setOrchestratorSetupDependencies, } from './orchestrator-setup.service.js';
|
|
15
16
|
//# sourceMappingURL=index.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../../../backend/src/services/orchestrator/index.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EACL,uBAAuB,EACvB,0BAA0B,EAC1B,4BAA4B,GAC7B,MAAM,gCAAgC,CAAC;AAExC,OAAO,EACL,kBAAkB,EAClB,qBAAqB,EACrB,uBAAuB,GAGxB,MAAM,2BAA2B,CAAC;AAEnC,OAAO,EACL,sBAAsB,EACtB,yBAAyB,EACzB,2BAA2B,GAI5B,MAAM,+BAA+B,CAAC;AAEvC,OAAO,EACL,wBAAwB,EACxB,2BAA2B,EAC3B,6BAA6B,GAK9B,MAAM,iCAAiC,CAAC;AAEzC,OAAO,EACL,yBAAyB,EACzB,4BAA4B,EAC5B,8BAA8B,GAE/B,MAAM,kCAAkC,CAAC;AAE1C,OAAO,EACL,oBAAoB,EACpB,aAAa,EACb,qBAAqB,EACrB,6BAA6B,GAE9B,MAAM,kCAAkC,CAAC;AAE1C,OAAO,EACL,0BAA0B,GAE3B,MAAM,mCAAmC,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../../../backend/src/services/orchestrator/index.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EACL,uBAAuB,EACvB,0BAA0B,EAC1B,4BAA4B,GAC7B,MAAM,gCAAgC,CAAC;AAExC,OAAO,EACL,kBAAkB,EAClB,qBAAqB,EACrB,uBAAuB,GAGxB,MAAM,2BAA2B,CAAC;AAEnC,OAAO,EACL,sBAAsB,EACtB,yBAAyB,EACzB,2BAA2B,GAI5B,MAAM,+BAA+B,CAAC;AAEvC,OAAO,EACL,wBAAwB,EACxB,2BAA2B,EAC3B,6BAA6B,GAK9B,MAAM,iCAAiC,CAAC;AAEzC,OAAO,EACL,yBAAyB,EACzB,4BAA4B,EAC5B,8BAA8B,GAE/B,MAAM,kCAAkC,CAAC;AAE1C,OAAO,EACL,oBAAoB,EACpB,aAAa,EACb,qBAAqB,EACrB,6BAA6B,GAE9B,MAAM,kCAAkC,CAAC;AAE1C,OAAO,EACL,0BAA0B,GAE3B,MAAM,mCAAmC,CAAC;AAE3C,OAAO,EACL,wBAAwB,EACxB,gCAAgC,GAGjC,MAAM,iCAAiC,CAAC"}
|
|
@@ -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;
|
|
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
|
-
|
|
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
|
-
|
|
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
|