crewly 1.11.2 → 1.11.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/skills/agent/core/accept-task/SKILL.md +35 -7
- package/config/skills/agent/core/poll-tasks/execute.sh +44 -9
- package/config/skills/agent/core/poll-tasks/execute.test.sh +98 -0
- package/config/skills/agent/core/record-learning/execute.sh +92 -3
- package/config/skills/agent/core/register-self/SKILL.md +51 -8
- package/config/skills/agent/transcribe-audio/SKILL.md +110 -0
- package/config/skills/agent/transcribe-audio/execute.sh +223 -0
- package/config/skills/agent/transcribe-audio/instructions.md +92 -0
- package/config/skills/agent/transcribe-audio/skill.json +22 -0
- package/config/skills/orchestrator/assign-task/SKILL.md +40 -6
- package/config/skills/orchestrator/broadcast/SKILL.md +45 -8
- package/dist/backend/backend/src/constants.d.ts +0 -16
- package/dist/backend/backend/src/constants.d.ts.map +1 -1
- package/dist/backend/backend/src/constants.js +0 -16
- package/dist/backend/backend/src/constants.js.map +1 -1
- package/dist/backend/backend/src/controllers/memory/memory.controller.d.ts.map +1 -1
- package/dist/backend/backend/src/controllers/memory/memory.controller.js +3 -10
- package/dist/backend/backend/src/controllers/memory/memory.controller.js.map +1 -1
- package/dist/backend/backend/src/controllers/system/system.controller.d.ts.map +1 -1
- package/dist/backend/backend/src/controllers/system/system.controller.js +24 -5
- package/dist/backend/backend/src/controllers/system/system.controller.js.map +1 -1
- package/dist/backend/backend/src/controllers/team/team.controller.d.ts.map +1 -1
- package/dist/backend/backend/src/controllers/team/team.controller.js +57 -2
- package/dist/backend/backend/src/controllers/team/team.controller.js.map +1 -1
- package/dist/backend/backend/src/index.d.ts +2 -0
- package/dist/backend/backend/src/index.d.ts.map +1 -1
- package/dist/backend/backend/src/index.js +124 -1
- package/dist/backend/backend/src/index.js.map +1 -1
- package/dist/backend/backend/src/routes/api.routes.d.ts.map +1 -1
- package/dist/backend/backend/src/routes/api.routes.js +0 -3
- package/dist/backend/backend/src/routes/api.routes.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 +56 -20
- package/dist/backend/backend/src/services/agent/agent-registration.service.js.map +1 -1
- package/dist/backend/backend/src/services/ai/prompt-modules/index.d.ts +1 -0
- package/dist/backend/backend/src/services/ai/prompt-modules/index.d.ts.map +1 -1
- package/dist/backend/backend/src/services/ai/prompt-modules/index.js +1 -0
- package/dist/backend/backend/src/services/ai/prompt-modules/index.js.map +1 -1
- package/dist/backend/backend/src/services/ai/prompt-modules/prompt-assembly.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/ai/prompt-modules/prompt-assembly.service.js +2 -0
- package/dist/backend/backend/src/services/ai/prompt-modules/prompt-assembly.service.js.map +1 -1
- package/dist/backend/backend/src/services/ai/prompt-modules/sop-norm-distinction.module.d.ts +79 -0
- package/dist/backend/backend/src/services/ai/prompt-modules/sop-norm-distinction.module.d.ts.map +1 -0
- package/dist/backend/backend/src/services/ai/prompt-modules/sop-norm-distinction.module.js +118 -0
- package/dist/backend/backend/src/services/ai/prompt-modules/sop-norm-distinction.module.js.map +1 -0
- package/dist/backend/backend/src/services/boot/boot-announce.service.d.ts +88 -0
- package/dist/backend/backend/src/services/boot/boot-announce.service.d.ts.map +1 -0
- package/dist/backend/backend/src/services/boot/boot-announce.service.js +119 -0
- package/dist/backend/backend/src/services/boot/boot-announce.service.js.map +1 -0
- package/dist/backend/backend/src/services/event-bus/event-to-workitem-bridge.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/event-bus/event-to-workitem-bridge.service.js +14 -0
- package/dist/backend/backend/src/services/event-bus/event-to-workitem-bridge.service.js.map +1 -1
- package/dist/backend/backend/src/services/mcp-server.d.ts.map +1 -1
- package/dist/backend/backend/src/services/mcp-server.js +0 -6
- package/dist/backend/backend/src/services/mcp-server.js.map +1 -1
- package/dist/backend/backend/src/services/memory/learning-format.validator.d.ts +97 -0
- package/dist/backend/backend/src/services/memory/learning-format.validator.d.ts.map +1 -0
- package/dist/backend/backend/src/services/memory/learning-format.validator.js +209 -0
- package/dist/backend/backend/src/services/memory/learning-format.validator.js.map +1 -0
- package/dist/backend/backend/src/services/memory/memory.service.d.ts +78 -41
- package/dist/backend/backend/src/services/memory/memory.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/memory/memory.service.js +209 -127
- package/dist/backend/backend/src/services/memory/memory.service.js.map +1 -1
- package/dist/backend/backend/src/services/memory/project-memory.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/memory/project-memory.service.js +37 -9
- package/dist/backend/backend/src/services/memory/project-memory.service.js.map +1 -1
- package/dist/backend/backend/src/services/orchestrator/commitment-approval-guard.d.ts +46 -0
- package/dist/backend/backend/src/services/orchestrator/commitment-approval-guard.d.ts.map +1 -1
- package/dist/backend/backend/src/services/orchestrator/commitment-approval-guard.js +51 -0
- package/dist/backend/backend/src/services/orchestrator/commitment-approval-guard.js.map +1 -1
- package/dist/backend/backend/src/services/orchestrator/orchestrator-heartbeat-monitor.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/orchestrator/orchestrator-heartbeat-monitor.service.js +29 -0
- package/dist/backend/backend/src/services/orchestrator/orchestrator-heartbeat-monitor.service.js.map +1 -1
- package/dist/backend/backend/src/services/session/pty/pty-session-backend.d.ts.map +1 -1
- package/dist/backend/backend/src/services/session/pty/pty-session-backend.js +9 -0
- package/dist/backend/backend/src/services/session/pty/pty-session-backend.js.map +1 -1
- package/dist/backend/backend/src/services/session/runtime-pid-registry.service.d.ts +86 -0
- package/dist/backend/backend/src/services/session/runtime-pid-registry.service.d.ts.map +1 -0
- package/dist/backend/backend/src/services/session/runtime-pid-registry.service.js +214 -0
- package/dist/backend/backend/src/services/session/runtime-pid-registry.service.js.map +1 -0
- package/dist/backend/backend/src/services/sop/sop.service.d.ts +70 -2
- package/dist/backend/backend/src/services/sop/sop.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/sop/sop.service.js +93 -3
- package/dist/backend/backend/src/services/sop/sop.service.js.map +1 -1
- package/dist/backend/backend/src/services/task-pool/claim.service.d.ts +41 -0
- package/dist/backend/backend/src/services/task-pool/claim.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/task-pool/claim.service.js +72 -0
- package/dist/backend/backend/src/services/task-pool/claim.service.js.map +1 -1
- package/dist/backend/backend/src/services/task-pool/task-pool.service.d.ts +16 -0
- package/dist/backend/backend/src/services/task-pool/task-pool.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/task-pool/task-pool.service.js +20 -0
- package/dist/backend/backend/src/services/task-pool/task-pool.service.js.map +1 -1
- package/dist/backend/backend/src/services/telegram/telegram-orchestrator-bridge.d.ts.map +1 -1
- package/dist/backend/backend/src/services/telegram/telegram-orchestrator-bridge.js +11 -0
- package/dist/backend/backend/src/services/telegram/telegram-orchestrator-bridge.js.map +1 -1
- package/dist/backend/backend/src/services/telegram/telegram.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/telegram/telegram.service.js +24 -2
- package/dist/backend/backend/src/services/telegram/telegram.service.js.map +1 -1
- package/dist/backend/backend/src/services/v3/mission-reminder.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/v3/mission-reminder.service.js +18 -18
- package/dist/backend/backend/src/services/v3/mission-reminder.service.js.map +1 -1
- package/dist/backend/backend/src/services/v3/request-sla.subscriber.d.ts +10 -0
- package/dist/backend/backend/src/services/v3/request-sla.subscriber.d.ts.map +1 -1
- package/dist/backend/backend/src/services/v3/request-sla.subscriber.js +20 -12
- package/dist/backend/backend/src/services/v3/request-sla.subscriber.js.map +1 -1
- package/dist/backend/backend/src/services/wiki/wiki-migrate.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/wiki/wiki-migrate.service.js +12 -3
- package/dist/backend/backend/src/services/wiki/wiki-migrate.service.js.map +1 -1
- package/dist/backend/backend/src/services/wiki/wiki-query.service.d.ts +15 -5
- package/dist/backend/backend/src/services/wiki/wiki-query.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/wiki/wiki-query.service.js +31 -50
- package/dist/backend/backend/src/services/wiki/wiki-query.service.js.map +1 -1
- package/dist/backend/backend/src/services/wiki/wiki-search.service.d.ts +16 -0
- package/dist/backend/backend/src/services/wiki/wiki-search.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/wiki/wiki-search.service.js +20 -0
- package/dist/backend/backend/src/services/wiki/wiki-search.service.js.map +1 -1
- package/dist/backend/backend/src/types/settings.types.d.ts +8 -0
- package/dist/backend/backend/src/types/settings.types.d.ts.map +1 -1
- package/dist/backend/backend/src/types/settings.types.js +2 -0
- package/dist/backend/backend/src/types/settings.types.js.map +1 -1
- package/dist/backend/backend/src/types/v2/work-item.types.d.ts +23 -0
- package/dist/backend/backend/src/types/v2/work-item.types.d.ts.map +1 -1
- package/dist/backend/backend/src/types/v2/work-item.types.js +29 -0
- package/dist/backend/backend/src/types/v2/work-item.types.js.map +1 -1
- package/dist/cli/backend/src/constants.d.ts +0 -16
- package/dist/cli/backend/src/constants.d.ts.map +1 -1
- package/dist/cli/backend/src/constants.js +0 -16
- package/dist/cli/backend/src/constants.js.map +1 -1
- package/dist/cli/backend/src/services/mcp-server.d.ts.map +1 -1
- package/dist/cli/backend/src/services/mcp-server.js +0 -6
- package/dist/cli/backend/src/services/mcp-server.js.map +1 -1
- package/dist/cli/backend/src/services/memory/memory.service.d.ts +78 -41
- package/dist/cli/backend/src/services/memory/memory.service.d.ts.map +1 -1
- package/dist/cli/backend/src/services/memory/memory.service.js +209 -127
- package/dist/cli/backend/src/services/memory/memory.service.js.map +1 -1
- package/dist/cli/backend/src/services/memory/project-memory.service.d.ts.map +1 -1
- package/dist/cli/backend/src/services/memory/project-memory.service.js +37 -9
- package/dist/cli/backend/src/services/memory/project-memory.service.js.map +1 -1
- package/dist/cli/backend/src/services/task-pool/claim.service.d.ts +41 -0
- package/dist/cli/backend/src/services/task-pool/claim.service.d.ts.map +1 -1
- package/dist/cli/backend/src/services/task-pool/claim.service.js +72 -0
- package/dist/cli/backend/src/services/task-pool/claim.service.js.map +1 -1
- package/dist/cli/backend/src/services/task-pool/task-pool.service.d.ts +16 -0
- package/dist/cli/backend/src/services/task-pool/task-pool.service.d.ts.map +1 -1
- package/dist/cli/backend/src/services/task-pool/task-pool.service.js +20 -0
- package/dist/cli/backend/src/services/task-pool/task-pool.service.js.map +1 -1
- package/dist/cli/backend/src/services/wiki/schema-loader.service.d.ts +57 -0
- package/dist/cli/backend/src/services/wiki/schema-loader.service.d.ts.map +1 -0
- package/dist/cli/backend/src/services/wiki/schema-loader.service.js +183 -0
- package/dist/cli/backend/src/services/wiki/schema-loader.service.js.map +1 -0
- package/dist/cli/backend/src/services/wiki/wiki-ingest.service.d.ts +100 -0
- package/dist/cli/backend/src/services/wiki/wiki-ingest.service.d.ts.map +1 -0
- package/dist/cli/backend/src/services/wiki/wiki-ingest.service.js +212 -0
- package/dist/cli/backend/src/services/wiki/wiki-ingest.service.js.map +1 -0
- package/dist/cli/backend/src/services/wiki/wiki-overlay.resolver.d.ts +43 -0
- package/dist/cli/backend/src/services/wiki/wiki-overlay.resolver.d.ts.map +1 -0
- package/dist/cli/backend/src/services/wiki/wiki-overlay.resolver.js +67 -0
- package/dist/cli/backend/src/services/wiki/wiki-overlay.resolver.js.map +1 -0
- package/dist/cli/backend/src/services/wiki/wiki-search.service.d.ts +166 -0
- package/dist/cli/backend/src/services/wiki/wiki-search.service.d.ts.map +1 -0
- package/dist/cli/backend/src/services/wiki/wiki-search.service.js +379 -0
- package/dist/cli/backend/src/services/wiki/wiki-search.service.js.map +1 -0
- package/dist/cli/backend/src/services/wiki/wiki.types.d.ts +84 -0
- package/dist/cli/backend/src/services/wiki/wiki.types.d.ts.map +1 -0
- package/dist/cli/backend/src/services/wiki/wiki.types.js +10 -0
- package/dist/cli/backend/src/services/wiki/wiki.types.js.map +1 -0
- package/dist/cli/backend/src/types/settings.types.d.ts +8 -0
- package/dist/cli/backend/src/types/settings.types.d.ts.map +1 -1
- package/dist/cli/backend/src/types/settings.types.js +2 -0
- package/dist/cli/backend/src/types/settings.types.js.map +1 -1
- package/dist/cli/backend/src/types/v2/work-item.types.d.ts +23 -0
- package/dist/cli/backend/src/types/v2/work-item.types.d.ts.map +1 -1
- package/dist/cli/backend/src/types/v2/work-item.types.js +29 -0
- package/dist/cli/backend/src/types/v2/work-item.types.js.map +1 -1
- package/frontend/dist/assets/{index-44266b5d.css → index-8205ea5e.css} +1 -1
- package/frontend/dist/assets/{index-4099a91c.js → index-890d3f9d.js} +289 -289
- package/frontend/dist/index.html +2 -2
- package/package.json +1 -1
|
@@ -15,6 +15,7 @@ import os from 'os';
|
|
|
15
15
|
import { fileURLToPath } from 'url';
|
|
16
16
|
import { StorageService, TmuxService, SchedulerService, MessageSchedulerService, ActivityMonitorService, TeamActivityWebSocketService, TeamsJsonWatcherService, } from './services/index.js';
|
|
17
17
|
import { getSessionBackend, getSessionBackendSync, getSessionStatePersistence, destroySessionBackend, PtySessionBackend, } from './services/session/index.js';
|
|
18
|
+
import { RuntimePidRegistry } from './services/session/runtime-pid-registry.service.js';
|
|
18
19
|
import { ApiController } from './controllers/api.controller.js';
|
|
19
20
|
import { createApiRoutes } from './routes/api.routes.js';
|
|
20
21
|
import { TerminalGateway, setTerminalGateway } from './websocket/terminal.gateway.js';
|
|
@@ -36,12 +37,13 @@ import { EventBusService } from './services/event-bus/index.js';
|
|
|
36
37
|
import { EventToWorkItemBridge } from './services/event-bus/event-to-workitem-bridge.service.js';
|
|
37
38
|
import { AutoLearningSubscriber } from './services/memory/auto-learning.subscriber.js';
|
|
38
39
|
import { MilestoneNotificationSubscriber } from './services/notification/milestone-notification.subscriber.js';
|
|
39
|
-
import { RequestSlaSubscriber, setRequestSlaSubscriber, } from './services/v3/request-sla.subscriber.js';
|
|
40
|
+
import { RequestSlaSubscriber, setRequestSlaSubscriber, getRequestSlaSubscriber, } from './services/v3/request-sla.subscriber.js';
|
|
40
41
|
import { RequestDecomposeSubscriber, setRequestDecomposeSubscriber, } from './services/v3/request-decompose.subscriber.js';
|
|
41
42
|
import { RequestStatusUpdateSubscriber } from './services/v3/request-status-update.subscriber.js';
|
|
42
43
|
import { RequestCascadeSubscriber } from './services/v3/request-cascade.subscriber.js';
|
|
43
44
|
import { setRequestServiceEventBus, RequestService } from './services/v3/request.service.js';
|
|
44
45
|
import { getSlackService } from './services/slack/slack.service.js';
|
|
46
|
+
import { sendBootAnnouncement, isFirstBoot, markBooted } from './services/boot/boot-announce.service.js';
|
|
45
47
|
import { SlackThreadStoreService, setSlackThreadStore, getSlackThreadStore } from './services/slack/slack-thread-store.service.js';
|
|
46
48
|
import { GoogleChatThreadStoreService, setGchatThreadStore } from './services/messaging/gchat-thread-store.service.js';
|
|
47
49
|
import { SlackImageService, setSlackImageService } from './services/slack/slack-image.service.js';
|
|
@@ -125,6 +127,8 @@ export class CrewlyServer {
|
|
|
125
127
|
io;
|
|
126
128
|
config;
|
|
127
129
|
logger = LoggerService.getInstance().createComponentLogger('CrewlyServer');
|
|
130
|
+
/** Offline-replay summary from this boot, surfaced in the boot announcement. */
|
|
131
|
+
lastOfflineReplay;
|
|
128
132
|
storageService;
|
|
129
133
|
tmuxService;
|
|
130
134
|
schedulerService;
|
|
@@ -903,6 +907,41 @@ export class CrewlyServer {
|
|
|
903
907
|
shadowMode: watchdog.getLastSweep()?.shadowMode ?? null,
|
|
904
908
|
}
|
|
905
909
|
: { status: 'warming', last_sweep_age_ms: -1, shadowMode: null };
|
|
910
|
+
// Orchestrator-liveness signal (issue #686). The silent 假死 symptom is
|
|
911
|
+
// "inbound user messages queue but nobody answers": no active agent AND
|
|
912
|
+
// outstanding `respond_to_user` SLA trackers. Surface it as a body block
|
|
913
|
+
// — we deliberately keep top-level status:"healthy" / HTTP 200 so a load
|
|
914
|
+
// balancer doesn't drop the node on this (the LB keys on the status code;
|
|
915
|
+
// this signal is for dashboards/monitoring to read from the body).
|
|
916
|
+
const slaSub = getRequestSlaSubscriber();
|
|
917
|
+
const pendingUserRequests = slaSub ? slaSub.getPendingUserRequestCount() : 0;
|
|
918
|
+
// "Down" — no active agent while user work is queued (issue #686).
|
|
919
|
+
const orchestratorDown = agentCount === 0 && pendingUserRequests > 0;
|
|
920
|
+
// "Up but hung" — the orchestrator process is alive yet its session keeps
|
|
921
|
+
// claiming work and never heartbeats (claims get grace-revoked in a loop).
|
|
922
|
+
// agentCount>0 hides this from the "down" check, so detect it explicitly
|
|
923
|
+
// via the claim-service hung signal (the Irissair 假死).
|
|
924
|
+
let orchestratorHung = false;
|
|
925
|
+
try {
|
|
926
|
+
orchestratorHung = TaskPoolService.getInstance()
|
|
927
|
+
.getHungAgents()
|
|
928
|
+
.includes(ORCHESTRATOR_SESSION_NAME);
|
|
929
|
+
}
|
|
930
|
+
catch {
|
|
931
|
+
// Task pool not ready yet — treat as not-hung.
|
|
932
|
+
}
|
|
933
|
+
const orchestratorStalled = orchestratorDown || orchestratorHung;
|
|
934
|
+
const orchestratorBlock = {
|
|
935
|
+
status: orchestratorStalled ? 'degraded' : 'ok',
|
|
936
|
+
activeAgents: agentCount,
|
|
937
|
+
pendingUserRequests,
|
|
938
|
+
hung: orchestratorHung,
|
|
939
|
+
reason: orchestratorHung
|
|
940
|
+
? 'orchestrator session is hung — claiming work but not heartbeating (repeated grace-revokes)'
|
|
941
|
+
: orchestratorDown
|
|
942
|
+
? `no active agent with ${pendingUserRequests} pending user request(s) — orchestrator may be down`
|
|
943
|
+
: null,
|
|
944
|
+
};
|
|
906
945
|
res.json({
|
|
907
946
|
status: 'healthy',
|
|
908
947
|
timestamp: new Date().toISOString(),
|
|
@@ -916,6 +955,7 @@ export class CrewlyServer {
|
|
|
916
955
|
total: agentCount,
|
|
917
956
|
},
|
|
918
957
|
team_health: teamHealthBlock,
|
|
958
|
+
orchestrator: orchestratorBlock,
|
|
919
959
|
});
|
|
920
960
|
});
|
|
921
961
|
// H5 quick entry static page (served regardless of headless mode)
|
|
@@ -1515,6 +1555,11 @@ export class CrewlyServer {
|
|
|
1515
1555
|
const { MessageReplayService } = await import('./services/messaging/message-replay.service.js');
|
|
1516
1556
|
const replayService = new MessageReplayService(this.messageQueueService, this.config.crewlyHome);
|
|
1517
1557
|
const replayResult = await replayService.replayPendingMessages();
|
|
1558
|
+
// Stash for the boot announcement (surfaced after the orchestrator starts).
|
|
1559
|
+
this.lastOfflineReplay = {
|
|
1560
|
+
offlineDurationMs: replayResult.offlineDurationMs,
|
|
1561
|
+
replayedCount: replayResult.replayedCount,
|
|
1562
|
+
};
|
|
1518
1563
|
if (replayResult.replayedCount > 0) {
|
|
1519
1564
|
this.logger.info('Replayed pending messages from offline period (#247)', {
|
|
1520
1565
|
replayed: replayResult.replayedCount,
|
|
@@ -1799,6 +1844,23 @@ export class CrewlyServer {
|
|
|
1799
1844
|
error: dispatchErr instanceof Error ? dispatchErr.message : String(dispatchErr),
|
|
1800
1845
|
});
|
|
1801
1846
|
}
|
|
1847
|
+
// Bootstrap SOPService at boot (F8 — fix/f8-get-sops-graceful-fallback).
|
|
1848
|
+
// This materialises `~/.crewly/sops/{system,custom}/` and seeds the
|
|
1849
|
+
// `index.json` so the get-sops skill — which sits on every agent's
|
|
1850
|
+
// session-startup hot path — never hits a missing-file 500.
|
|
1851
|
+
// SOPService.initialize is internally idempotent and the service has
|
|
1852
|
+
// graceful in-memory fallbacks, so this is non-critical: failures here
|
|
1853
|
+
// will be tolerated by the API layer at request time.
|
|
1854
|
+
try {
|
|
1855
|
+
const { SOPService } = await import('./services/sop/sop.service.js');
|
|
1856
|
+
await SOPService.getInstance().initialize();
|
|
1857
|
+
this.logger.info('SOPService bootstrapped — get-sops endpoint ready');
|
|
1858
|
+
}
|
|
1859
|
+
catch (sopErr) {
|
|
1860
|
+
this.logger.warn('SOPService bootstrap failed (non-critical, runtime fallback active)', {
|
|
1861
|
+
error: sopErr instanceof Error ? sopErr.message : String(sopErr),
|
|
1862
|
+
});
|
|
1863
|
+
}
|
|
1802
1864
|
// Start AgentAutoClaimService — auto-assign work to idle agents
|
|
1803
1865
|
try {
|
|
1804
1866
|
const { AgentAutoClaimService } = await import('./services/v3/agent-auto-claim.service.js');
|
|
@@ -1957,6 +2019,23 @@ export class CrewlyServer {
|
|
|
1957
2019
|
this.registerSignalHandlers();
|
|
1958
2020
|
// Start health monitoring
|
|
1959
2021
|
this.startHealthMonitoring();
|
|
2022
|
+
// Reap orphaned runtime processes left by a previous, non-graceful
|
|
2023
|
+
// backend death (crash / OOM / force-exit) BEFORE we spawn any new
|
|
2024
|
+
// sessions below — otherwise stray `gemini --yolo` / `claude` runtimes
|
|
2025
|
+
// accumulate across restarts and inflate the process table (#715).
|
|
2026
|
+
// Identity-verified: only kills recorded PIDs whose live cmdline still
|
|
2027
|
+
// matches, so it never touches an unrelated reused PID.
|
|
2028
|
+
try {
|
|
2029
|
+
const reaped = RuntimePidRegistry.getInstance().reapOrphans();
|
|
2030
|
+
if (reaped > 0) {
|
|
2031
|
+
this.logger.warn('Reaped orphaned runtime processes at startup', { reaped });
|
|
2032
|
+
}
|
|
2033
|
+
}
|
|
2034
|
+
catch (err) {
|
|
2035
|
+
this.logger.warn('Orphan runtime reap failed (non-fatal)', {
|
|
2036
|
+
error: err instanceof Error ? err.message : String(err),
|
|
2037
|
+
});
|
|
2038
|
+
}
|
|
1960
2039
|
// Auto-start orchestrator if enabled in settings
|
|
1961
2040
|
await this.autoStartOrchestratorIfEnabled();
|
|
1962
2041
|
// Auto-restore agent sessions that were running before the last shutdown
|
|
@@ -2302,6 +2381,50 @@ export class CrewlyServer {
|
|
|
2302
2381
|
this.terminalGateway.startOrchestratorChatMonitoring(ORCHESTRATOR_SESSION_NAME);
|
|
2303
2382
|
}
|
|
2304
2383
|
this.logger.info('Orchestrator auto-started successfully');
|
|
2384
|
+
// Announce "back online" to the owner's channel (best-effort, never
|
|
2385
|
+
// blocks boot). Deterministic system message — reports startup + the
|
|
2386
|
+
// running version, enriched with offline duration + replayed count.
|
|
2387
|
+
try {
|
|
2388
|
+
const settings = await getSettingsService().getSettings();
|
|
2389
|
+
if (settings.general.announceOnBoot) {
|
|
2390
|
+
let version = 'unknown';
|
|
2391
|
+
try {
|
|
2392
|
+
version = VersionCheckService.getInstance().getLocalVersion();
|
|
2393
|
+
}
|
|
2394
|
+
catch {
|
|
2395
|
+
version = process.env.npm_package_version || 'unknown';
|
|
2396
|
+
}
|
|
2397
|
+
// First-ever boot → welcome; subsequent boots → "back online".
|
|
2398
|
+
const bootMarker = path.join(this.config.crewlyHome, '.boot-announced');
|
|
2399
|
+
const firstBoot = isFirstBoot(bootMarker);
|
|
2400
|
+
if (firstBoot)
|
|
2401
|
+
markBooted(bootMarker);
|
|
2402
|
+
await sendBootAnnouncement({
|
|
2403
|
+
version,
|
|
2404
|
+
firstBoot,
|
|
2405
|
+
offlineDurationMs: this.lastOfflineReplay?.offlineDurationMs,
|
|
2406
|
+
replayedCount: this.lastOfflineReplay?.replayedCount,
|
|
2407
|
+
}, {
|
|
2408
|
+
isSlackConnected: () => getSlackService().isConnected(),
|
|
2409
|
+
sendSlack: (msg) => getSlackService().sendNotification({
|
|
2410
|
+
type: 'project_update',
|
|
2411
|
+
title: msg.title,
|
|
2412
|
+
message: msg.message,
|
|
2413
|
+
urgency: 'normal',
|
|
2414
|
+
timestamp: new Date().toISOString(),
|
|
2415
|
+
}),
|
|
2416
|
+
logger: {
|
|
2417
|
+
info: (m, meta) => this.logger.info(m, meta),
|
|
2418
|
+
warn: (m, meta) => this.logger.warn(m, meta),
|
|
2419
|
+
},
|
|
2420
|
+
});
|
|
2421
|
+
}
|
|
2422
|
+
}
|
|
2423
|
+
catch (announceErr) {
|
|
2424
|
+
this.logger.warn('Boot announce skipped (non-critical)', {
|
|
2425
|
+
error: announceErr instanceof Error ? announceErr.message : String(announceErr),
|
|
2426
|
+
});
|
|
2427
|
+
}
|
|
2305
2428
|
}
|
|
2306
2429
|
catch (error) {
|
|
2307
2430
|
this.logger.error('Failed to auto-start orchestrator', {
|