crewly 1.20.59 → 1.20.60
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/backend/backend/src/constants.d.ts +19 -0
- package/dist/backend/backend/src/constants.d.ts.map +1 -1
- package/dist/backend/backend/src/constants.js +19 -0
- package/dist/backend/backend/src/constants.js.map +1 -1
- package/dist/backend/backend/src/controllers/slack/slack.controller.d.ts.map +1 -1
- package/dist/backend/backend/src/controllers/slack/slack.controller.js +4 -0
- package/dist/backend/backend/src/controllers/slack/slack.controller.js.map +1 -1
- package/dist/backend/backend/src/services/agent/agent-registration.service.d.ts +36 -0
- 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 +93 -15
- package/dist/backend/backend/src/services/agent/agent-registration.service.js.map +1 -1
- package/dist/backend/backend/src/services/cloud/cloud-sync.service.d.ts +35 -21
- package/dist/backend/backend/src/services/cloud/cloud-sync.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/cloud/cloud-sync.service.js +105 -5
- package/dist/backend/backend/src/services/cloud/cloud-sync.service.js.map +1 -1
- package/dist/backend/backend/src/services/slack/slack-instance-registry.service.d.ts +15 -0
- package/dist/backend/backend/src/services/slack/slack-instance-registry.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/slack/slack-instance-registry.service.js +15 -0
- package/dist/backend/backend/src/services/slack/slack-instance-registry.service.js.map +1 -1
- package/dist/backend/build-info.json +2 -2
- package/dist/cli/backend/src/constants.d.ts +19 -0
- package/dist/cli/backend/src/constants.d.ts.map +1 -1
- package/dist/cli/backend/src/constants.js +19 -0
- package/dist/cli/backend/src/constants.js.map +1 -1
- package/dist/cli/backend/src/services/agent/agent-registration.service.d.ts +36 -0
- package/dist/cli/backend/src/services/agent/agent-registration.service.d.ts.map +1 -1
- package/dist/cli/backend/src/services/agent/agent-registration.service.js +93 -15
- package/dist/cli/backend/src/services/agent/agent-registration.service.js.map +1 -1
- package/dist/cli/backend/src/services/cloud/cloud-sync.service.d.ts +35 -21
- package/dist/cli/backend/src/services/cloud/cloud-sync.service.d.ts.map +1 -1
- package/dist/cli/backend/src/services/cloud/cloud-sync.service.js +105 -5
- package/dist/cli/backend/src/services/cloud/cloud-sync.service.js.map +1 -1
- package/package.json +1 -1
|
@@ -7,7 +7,7 @@ import { createSessionCommandHelper, getSessionBackendSync, createSessionBackend
|
|
|
7
7
|
import { RuntimeServiceFactory } from './runtime-service.factory.js';
|
|
8
8
|
import { registerInProcessRuntime, unregisterInProcessRuntime, } from './crewly-agent/in-process-runtime-registry.js';
|
|
9
9
|
import { getCrewlyHomePath } from '../core/crewly-home.utils.js';
|
|
10
|
-
import { CREWLY_CONSTANTS, ENV_CONSTANTS, AGENT_TIMEOUTS, ORCHESTRATOR_SESSION_NAME, ORCHESTRATOR_ROLE, RUNTIME_TYPES, SESSION_COMMAND_DELAYS, EVENT_DELIVERY_CONSTANTS, TERMINAL_PATTERNS, GEMINI_SHELL_MODE_CONSTANTS, GEMINI_STUCK_CONNECTIVITY_PATTERN, GEMINI_ERROR_STATE_CONSTANTS, REGISTRATION_DELIVERY_CONSTANTS, } from '../../constants.js';
|
|
10
|
+
import { CREWLY_CONSTANTS, ENV_CONSTANTS, AGENT_TIMEOUTS, ORCHESTRATOR_SESSION_NAME, ORCHESTRATOR_ROLE, RUNTIME_TYPES, SESSION_COMMAND_DELAYS, SESSION_RECREATION_CONSTANTS, EVENT_DELIVERY_CONSTANTS, TERMINAL_PATTERNS, GEMINI_SHELL_MODE_CONSTANTS, GEMINI_STUCK_CONNECTIVITY_PATTERN, GEMINI_ERROR_STATE_CONSTANTS, REGISTRATION_DELIVERY_CONSTANTS, } from '../../constants.js';
|
|
11
11
|
import { WEB_CONSTANTS } from '../../../../config/constants.js';
|
|
12
12
|
import { delay } from '../../utils/async.utils.js';
|
|
13
13
|
import { buildRuntimeModelFlags } from '../../utils/runtime-model-flags.utils.js';
|
|
@@ -1474,7 +1474,10 @@ export class AgentRegistrationService {
|
|
|
1474
1474
|
* Most aggressive approach - completely recreates the session from scratch
|
|
1475
1475
|
*/
|
|
1476
1476
|
async tryFullRecreation(sessionName, role, timeout, projectPath, memberId, runtimeType = RUNTIME_TYPES.CLAUDE_CODE, runtimeFlags) {
|
|
1477
|
-
// Kill existing session
|
|
1477
|
+
// Kill existing session. Same D2(a) rule as forceRecreate: a monitor entry
|
|
1478
|
+
// for the old incarnation must not outlive it, or it false-declares the
|
|
1479
|
+
// replacement PTY dead before startMonitoring() below replaces it.
|
|
1480
|
+
RuntimeExitMonitorService.getInstance().stopMonitoring(sessionName);
|
|
1478
1481
|
await (await this.getSessionHelper()).killSession(sessionName);
|
|
1479
1482
|
// Wait for cleanup
|
|
1480
1483
|
await delay(1000);
|
|
@@ -1511,6 +1514,8 @@ export class AgentRegistrationService {
|
|
|
1511
1514
|
sessionName,
|
|
1512
1515
|
projectPath: orchestratorCwd,
|
|
1513
1516
|
});
|
|
1517
|
+
// D3: let the shell print its prompt before the init sequence's Ctrl-C.
|
|
1518
|
+
await this.waitForShellReady(sessionName);
|
|
1514
1519
|
// Initialize runtime for orchestrator using script (always fresh start)
|
|
1515
1520
|
const runtimeService = this.createRuntimeService(runtimeType);
|
|
1516
1521
|
const launchedAtMs = Date.now();
|
|
@@ -1559,8 +1564,17 @@ export class AgentRegistrationService {
|
|
|
1559
1564
|
this.logger.debug('Runtime confirmed ready for orchestrator in Step 3', { sessionName, runtimeType });
|
|
1560
1565
|
}
|
|
1561
1566
|
else {
|
|
1562
|
-
// For other roles, create basic session and initialize Claude (always fresh start)
|
|
1563
|
-
|
|
1567
|
+
// For other roles, create basic session and initialize Claude (always fresh start).
|
|
1568
|
+
// D1 (2026-09-21): spawn with the identity env exactly like the primary
|
|
1569
|
+
// path — this branch used to spawn env-less, so every agent that came
|
|
1570
|
+
// through Step 2 ran without CREWLY_SESSION_NAME (unattributed heartbeats
|
|
1571
|
+
// and channel replies).
|
|
1572
|
+
const recreationCwd = projectPath || process.cwd();
|
|
1573
|
+
await (await this.getSessionHelper()).createSession(sessionName, recreationCwd, {
|
|
1574
|
+
env: this.buildAgentIdentityEnv(sessionName, role, recreationCwd),
|
|
1575
|
+
});
|
|
1576
|
+
// D3: let the shell print its prompt before the init sequence's Ctrl-C.
|
|
1577
|
+
await this.waitForShellReady(sessionName);
|
|
1564
1578
|
const runtimeService = this.createRuntimeService(runtimeType);
|
|
1565
1579
|
const launchedAtMs = Date.now();
|
|
1566
1580
|
await runtimeService.executeRuntimeInitScript(sessionName, projectPath, effectiveFlags, promptFilePath, agentName, sessionPlan.resumeSessionId ?? undefined);
|
|
@@ -2496,14 +2510,77 @@ Loop until done, blocked, or explicitly reassigned:
|
|
|
2496
2510
|
});
|
|
2497
2511
|
return;
|
|
2498
2512
|
}
|
|
2499
|
-
// Create new session for orchestrator
|
|
2500
|
-
|
|
2501
|
-
|
|
2502
|
-
|
|
2513
|
+
// Create new session for orchestrator — with the identity env (D1), the
|
|
2514
|
+
// same object the primary path spawns with. windowName not used in PTY backend.
|
|
2515
|
+
await (await this.getSessionHelper()).createSession(config.sessionName, config.projectPath, {
|
|
2516
|
+
env: this.buildAgentIdentityEnv(config.sessionName, ORCHESTRATOR_ROLE, config.projectPath),
|
|
2517
|
+
});
|
|
2503
2518
|
this.logger.info('Orchestrator session created successfully', {
|
|
2504
2519
|
sessionName: config.sessionName,
|
|
2505
2520
|
});
|
|
2506
2521
|
}
|
|
2522
|
+
/**
|
|
2523
|
+
* The identity environment every agent PTY is spawned with.
|
|
2524
|
+
*
|
|
2525
|
+
* One source of truth for the primary spawn path, the Step-2 full
|
|
2526
|
+
* recreation path and the orchestrator session: `CREWLY_SESSION_NAME`
|
|
2527
|
+
* is what every skill sends as `X-Agent-Session`, so a session spawned
|
|
2528
|
+
* without it produces unattributed heartbeats and channel replies. Passing
|
|
2529
|
+
* the env at spawn (rather than only typing `export`s afterwards) is what
|
|
2530
|
+
* makes it survive a shell that is still initialising.
|
|
2531
|
+
*
|
|
2532
|
+
* @param sessionName - PTY session name (also the agent's identity)
|
|
2533
|
+
* @param role - Agent role (orchestrator, developer, …)
|
|
2534
|
+
* @param cwd - Working directory the PTY is spawned in (exposed as CREWLY_PROJECT_PATH)
|
|
2535
|
+
* @returns Env map to pass as `createSession(..., { env })`
|
|
2536
|
+
*/
|
|
2537
|
+
buildAgentIdentityEnv(sessionName, role, cwd) {
|
|
2538
|
+
return {
|
|
2539
|
+
[ENV_CONSTANTS.CREWLY_SESSION_NAME]: sessionName,
|
|
2540
|
+
[ENV_CONSTANTS.CREWLY_ROLE]: role,
|
|
2541
|
+
[ENV_CONSTANTS.CREWLY_API_URL]: `http://localhost:${WEB_CONSTANTS.PORTS.BACKEND}`,
|
|
2542
|
+
[ENV_CONSTANTS.CREWLY_PROJECT_PATH]: cwd,
|
|
2543
|
+
[ENV_CONSTANTS.CREWLY_INSTALL_DIR]: this.projectRoot,
|
|
2544
|
+
};
|
|
2545
|
+
}
|
|
2546
|
+
/**
|
|
2547
|
+
* Wait — bounded — for a freshly spawned shell to print its prompt before
|
|
2548
|
+
* anything is written to it.
|
|
2549
|
+
*
|
|
2550
|
+
* D3 (2026-09-21): Step 2 full recreation used to write the runtime init
|
|
2551
|
+
* sequence ~8 ms after spawn. That sequence leads with Ctrl-C, and a zsh that
|
|
2552
|
+
* young has not installed its interactive SIGINT handling, so the TTY-delivered
|
|
2553
|
+
* SIGINT ends the shell (exit 0, 11 ms after spawn). The primary path never
|
|
2554
|
+
* hits this only because it types five `export`s first (~0.5 s).
|
|
2555
|
+
*
|
|
2556
|
+
* Checks the buffer first (the prompt may have landed before we subscribe),
|
|
2557
|
+
* then waits for the first non-whitespace output up to
|
|
2558
|
+
* `SESSION_RECREATION_CONSTANTS.SHELL_READY_TIMEOUT_MS`. Never throws: on
|
|
2559
|
+
* timeout it logs a warning and lets the caller proceed, so a silent shell
|
|
2560
|
+
* degrades to today's behaviour rather than blocking recreation.
|
|
2561
|
+
*
|
|
2562
|
+
* @param sessionName - The just-created PTY session
|
|
2563
|
+
* @returns True when a prompt was seen, false when the window elapsed
|
|
2564
|
+
*/
|
|
2565
|
+
async waitForShellReady(sessionName) {
|
|
2566
|
+
const { SHELL_READY_PATTERN, SHELL_READY_TIMEOUT_MS, SHELL_READY_CAPTURE_LINES } = SESSION_RECREATION_CONSTANTS;
|
|
2567
|
+
const helper = await this.getSessionHelper();
|
|
2568
|
+
try {
|
|
2569
|
+
if (SHELL_READY_PATTERN.test(helper.capturePane(sessionName, SHELL_READY_CAPTURE_LINES))) {
|
|
2570
|
+
return true;
|
|
2571
|
+
}
|
|
2572
|
+
await helper.waitForPattern(sessionName, SHELL_READY_PATTERN, SHELL_READY_TIMEOUT_MS);
|
|
2573
|
+
return true;
|
|
2574
|
+
}
|
|
2575
|
+
catch (error) {
|
|
2576
|
+
this.logger.warn('Fresh shell printed nothing within the readiness window — proceeding with runtime init anyway', {
|
|
2577
|
+
sessionName,
|
|
2578
|
+
timeoutMs: SHELL_READY_TIMEOUT_MS,
|
|
2579
|
+
error: error instanceof Error ? error.message : String(error),
|
|
2580
|
+
});
|
|
2581
|
+
return false;
|
|
2582
|
+
}
|
|
2583
|
+
}
|
|
2507
2584
|
/**
|
|
2508
2585
|
* Unified session creation that handles both orchestrator and team members
|
|
2509
2586
|
* @param config Session configuration
|
|
@@ -2677,6 +2754,12 @@ Loop until done, blocked, or explicitly reassigned:
|
|
|
2677
2754
|
// Skip recovery, kill immediately (used during server startup for stale sessions)
|
|
2678
2755
|
this.logger.info('Session exists but forceRecreate is set, killing for clean restart', { sessionName });
|
|
2679
2756
|
try {
|
|
2757
|
+
// D2(a) (2026-09-21): the previous incarnation's RuntimeExitMonitor
|
|
2758
|
+
// entry must go BEFORE the kill. It resolves the child by session
|
|
2759
|
+
// NAME and its 30s poll grace is long expired, so left alive it
|
|
2760
|
+
// judges the seconds-old replacement PTY (no runtime child yet)
|
|
2761
|
+
// dead and force-kills it — Step 1 then fails and Step 2 runs.
|
|
2762
|
+
RuntimeExitMonitorService.getInstance().stopMonitoring(sessionName);
|
|
2680
2763
|
const runtimeService = this.createRuntimeService(runtimeType);
|
|
2681
2764
|
runtimeService.clearDetectionCache(sessionName);
|
|
2682
2765
|
await (await this.getSessionHelper()).killSession(sessionName);
|
|
@@ -2908,14 +2991,9 @@ Loop until done, blocked, or explicitly reassigned:
|
|
|
2908
2991
|
// can be lost, and every skill then runs without
|
|
2909
2992
|
// CREWLY_SESSION_NAME — no X-Agent-Session header, and
|
|
2910
2993
|
// reply-channel fails with a misleading 404 (Think Tank, 2026-09-18).
|
|
2994
|
+
// Same env object as the Step-2 recreation path (buildAgentIdentityEnv).
|
|
2911
2995
|
const createdSession = await sessionHelper.createSession(sessionName, cwdToUse, {
|
|
2912
|
-
env:
|
|
2913
|
-
[ENV_CONSTANTS.CREWLY_SESSION_NAME]: sessionName,
|
|
2914
|
-
[ENV_CONSTANTS.CREWLY_ROLE]: role,
|
|
2915
|
-
[ENV_CONSTANTS.CREWLY_API_URL]: `http://localhost:${WEB_CONSTANTS.PORTS.BACKEND}`,
|
|
2916
|
-
[ENV_CONSTANTS.CREWLY_PROJECT_PATH]: cwdToUse,
|
|
2917
|
-
[ENV_CONSTANTS.CREWLY_INSTALL_DIR]: this.projectRoot,
|
|
2918
|
-
},
|
|
2996
|
+
env: this.buildAgentIdentityEnv(sessionName, role, cwdToUse),
|
|
2919
2997
|
});
|
|
2920
2998
|
this.logger.info('PTY session created successfully', {
|
|
2921
2999
|
sessionName,
|