crewly 1.1.2 → 1.2.0
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/README.md +6 -6
- package/config/roles/ops/prompt.md +140 -0
- package/config/roles/ops/role.json +13 -0
- package/config/skills/agent/browse-stealth/execute.sh +84 -0
- package/config/skills/agent/browse-stealth/instructions.md +108 -0
- package/config/skills/agent/browse-stealth/launch-chrome-cdp.sh +141 -0
- package/config/skills/agent/browse-stealth/skill.json +20 -0
- package/config/skills/agent/browse-stealth/stealth-browse.py +330 -0
- package/config/skills/agent/competitor-content-tracker/execute.sh +232 -0
- package/config/skills/agent/competitor-content-tracker/instructions.md +210 -0
- package/config/skills/agent/competitor-content-tracker/skill.json +22 -0
- package/config/skills/agent/content-calendar/execute.sh +294 -0
- package/config/skills/agent/content-calendar/instructions.md +122 -0
- package/config/skills/agent/content-calendar/skill.json +22 -0
- package/config/skills/agent/content-repurposer/execute.sh +194 -0
- package/config/skills/agent/content-repurposer/instructions.md +69 -0
- package/config/skills/agent/content-repurposer/skill.json +22 -0
- package/config/skills/agent/content-writer/execute.sh +311 -0
- package/config/skills/agent/content-writer/instructions.md +124 -0
- package/config/skills/agent/content-writer/skill.json +22 -0
- package/config/skills/agent/core/generate-pdf/execute.sh +88 -0
- package/config/skills/agent/core/generate-pdf/instructions.md +46 -0
- package/config/skills/agent/core/generate-pdf/skill.json +20 -0
- package/config/skills/agent/core/report-status/execute.sh +6 -0
- package/config/skills/agent/trend-monitor/execute.sh +211 -0
- package/config/skills/agent/trend-monitor/instructions.md +207 -0
- package/config/skills/agent/trend-monitor/skill.json +22 -0
- package/config/skills/agent/vnc-browser/execute.sh +261 -0
- package/config/skills/agent/vnc-browser/instructions.md +102 -0
- package/config/skills/agent/vnc-browser/skill.json +20 -0
- package/config/skills/orchestrator/delegate-task/execute.sh +63 -4
- package/config/skills/orchestrator/delegate-task/instructions.md +60 -0
- package/config/skills/orchestrator/delegate-task/skill.json +4 -4
- package/config/skills/orchestrator/reply-slack/execute.sh +2 -0
- package/config/skills/orchestrator/send-key/execute.sh +19 -6
- package/config/skills/orchestrator/send-key/instructions.md +44 -0
- package/config/skills/orchestrator/send-key/skill.json +20 -0
- package/config/skills/orchestrator/send-message/execute.sh +9 -1
- package/config/skills/registry.json +256 -0
- package/config/templates/code-review-team/README.md +176 -0
- package/config/templates/code-review-team/team-config.json +16 -0
- package/config/templates/code-review-team.json +62 -0
- package/config/templates/content-generation-team/README.md +128 -0
- package/config/templates/content-generation-team/team-config.json +21 -0
- package/config/templates/content-generation-team.json +67 -0
- package/config/templates/demo-team.json +22 -0
- package/config/templates/social-media-ops-team/README.md +145 -0
- package/config/templates/social-media-ops-team/team-config.json +21 -0
- package/config/templates/social-media-ops-team.json +67 -0
- package/dist/backend/backend/src/constants.d.ts +69 -6
- package/dist/backend/backend/src/constants.d.ts.map +1 -1
- package/dist/backend/backend/src/constants.js +75 -6
- package/dist/backend/backend/src/constants.js.map +1 -1
- package/dist/backend/backend/src/controllers/index.d.ts.map +1 -1
- package/dist/backend/backend/src/controllers/index.js +2 -0
- package/dist/backend/backend/src/controllers/index.js.map +1 -1
- package/dist/backend/backend/src/controllers/messaging/messenger.routes.d.ts +8 -0
- package/dist/backend/backend/src/controllers/messaging/messenger.routes.d.ts.map +1 -1
- package/dist/backend/backend/src/controllers/messaging/messenger.routes.js +110 -63
- package/dist/backend/backend/src/controllers/messaging/messenger.routes.js.map +1 -1
- package/dist/backend/backend/src/controllers/monitoring/terminal.controller.d.ts.map +1 -1
- package/dist/backend/backend/src/controllers/monitoring/terminal.controller.js +31 -4
- package/dist/backend/backend/src/controllers/monitoring/terminal.controller.js.map +1 -1
- package/dist/backend/backend/src/controllers/oauth/oauth.routes.d.ts +8 -0
- package/dist/backend/backend/src/controllers/oauth/oauth.routes.d.ts.map +1 -1
- package/dist/backend/backend/src/controllers/oauth/oauth.routes.js +127 -111
- package/dist/backend/backend/src/controllers/oauth/oauth.routes.js.map +1 -1
- package/dist/backend/backend/src/controllers/task-management/task-management.controller.d.ts +34 -0
- package/dist/backend/backend/src/controllers/task-management/task-management.controller.d.ts.map +1 -1
- package/dist/backend/backend/src/controllers/task-management/task-management.controller.js +219 -2
- package/dist/backend/backend/src/controllers/task-management/task-management.controller.js.map +1 -1
- package/dist/backend/backend/src/controllers/user/user.routes.d.ts +7 -0
- package/dist/backend/backend/src/controllers/user/user.routes.d.ts.map +1 -1
- package/dist/backend/backend/src/controllers/user/user.routes.js +45 -38
- package/dist/backend/backend/src/controllers/user/user.routes.js.map +1 -1
- package/dist/backend/backend/src/controllers/whatsapp/index.d.ts +17 -0
- package/dist/backend/backend/src/controllers/whatsapp/index.d.ts.map +1 -0
- package/dist/backend/backend/src/controllers/whatsapp/index.js +18 -0
- package/dist/backend/backend/src/controllers/whatsapp/index.js.map +1 -0
- package/dist/backend/backend/src/controllers/whatsapp/whatsapp.controller.d.ts +12 -0
- package/dist/backend/backend/src/controllers/whatsapp/whatsapp.controller.d.ts.map +1 -0
- package/dist/backend/backend/src/controllers/whatsapp/whatsapp.controller.js +185 -0
- package/dist/backend/backend/src/controllers/whatsapp/whatsapp.controller.js.map +1 -0
- package/dist/backend/backend/src/index.d.ts +5 -0
- package/dist/backend/backend/src/index.d.ts.map +1 -1
- package/dist/backend/backend/src/index.js +35 -0
- package/dist/backend/backend/src/index.js.map +1 -1
- package/dist/backend/backend/src/routes/modules/task-management.routes.d.ts.map +1 -1
- package/dist/backend/backend/src/routes/modules/task-management.routes.js +4 -0
- package/dist/backend/backend/src/routes/modules/task-management.routes.js.map +1 -1
- package/dist/backend/backend/src/services/agent/agent-heartbeat.service.js +1 -1
- package/dist/backend/backend/src/services/agent/agent-heartbeat.service.js.map +1 -1
- package/dist/backend/backend/src/services/agent/agent-registration.service.d.ts +14 -3
- 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 +160 -29
- package/dist/backend/backend/src/services/agent/agent-registration.service.js.map +1 -1
- package/dist/backend/backend/src/services/agent/claude-runtime.service.d.ts +4 -3
- package/dist/backend/backend/src/services/agent/claude-runtime.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/agent/claude-runtime.service.js +29 -4
- package/dist/backend/backend/src/services/agent/claude-runtime.service.js.map +1 -1
- package/dist/backend/backend/src/services/agent/context-window-monitor.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/agent/context-window-monitor.service.js +11 -0
- package/dist/backend/backend/src/services/agent/context-window-monitor.service.js.map +1 -1
- package/dist/backend/backend/src/services/agent/runtime-agent.service.abstract.d.ts +32 -2
- package/dist/backend/backend/src/services/agent/runtime-agent.service.abstract.d.ts.map +1 -1
- package/dist/backend/backend/src/services/agent/runtime-agent.service.abstract.js +69 -8
- package/dist/backend/backend/src/services/agent/runtime-agent.service.abstract.js.map +1 -1
- package/dist/backend/backend/src/services/knowledge/knowledge-search.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/knowledge/knowledge-search.service.js +14 -2
- package/dist/backend/backend/src/services/knowledge/knowledge-search.service.js.map +1 -1
- package/dist/backend/backend/src/services/marketplace/marketplace-installer.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/marketplace/marketplace-installer.service.js +11 -2
- package/dist/backend/backend/src/services/marketplace/marketplace-installer.service.js.map +1 -1
- package/dist/backend/backend/src/services/messaging/adapters/discord-messenger.adapter.d.ts +18 -0
- package/dist/backend/backend/src/services/messaging/adapters/discord-messenger.adapter.d.ts.map +1 -1
- package/dist/backend/backend/src/services/messaging/adapters/discord-messenger.adapter.js +28 -4
- package/dist/backend/backend/src/services/messaging/adapters/discord-messenger.adapter.js.map +1 -1
- package/dist/backend/backend/src/services/messaging/adapters/slack-messenger.adapter.js +2 -2
- package/dist/backend/backend/src/services/messaging/adapters/slack-messenger.adapter.js.map +1 -1
- package/dist/backend/backend/src/services/messaging/adapters/telegram-messenger.adapter.d.ts +18 -0
- package/dist/backend/backend/src/services/messaging/adapters/telegram-messenger.adapter.d.ts.map +1 -1
- package/dist/backend/backend/src/services/messaging/adapters/telegram-messenger.adapter.js +26 -4
- package/dist/backend/backend/src/services/messaging/adapters/telegram-messenger.adapter.js.map +1 -1
- package/dist/backend/backend/src/services/messaging/messenger-adapter.interface.d.ts +28 -2
- package/dist/backend/backend/src/services/messaging/messenger-adapter.interface.d.ts.map +1 -1
- package/dist/backend/backend/src/services/messaging/messenger-registry.service.d.ts +33 -2
- package/dist/backend/backend/src/services/messaging/messenger-registry.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/messaging/messenger-registry.service.js +33 -0
- package/dist/backend/backend/src/services/messaging/messenger-registry.service.js.map +1 -1
- package/dist/backend/backend/src/services/monitoring/activity-monitor.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/monitoring/activity-monitor.service.js +4 -2
- package/dist/backend/backend/src/services/monitoring/activity-monitor.service.js.map +1 -1
- package/dist/backend/backend/src/services/orchestrator/orchestrator-restart.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/orchestrator/orchestrator-restart.service.js +4 -3
- package/dist/backend/backend/src/services/orchestrator/orchestrator-restart.service.js.map +1 -1
- package/dist/backend/backend/src/services/project/task-tracking.service.d.ts +27 -0
- package/dist/backend/backend/src/services/project/task-tracking.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/project/task-tracking.service.js +54 -0
- package/dist/backend/backend/src/services/project/task-tracking.service.js.map +1 -1
- package/dist/backend/backend/src/services/slack/slack-orchestrator-bridge.d.ts +36 -6
- 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 +238 -36
- package/dist/backend/backend/src/services/slack/slack-orchestrator-bridge.js.map +1 -1
- package/dist/backend/backend/src/services/slack/slack.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/slack/slack.service.js +6 -4
- package/dist/backend/backend/src/services/slack/slack.service.js.map +1 -1
- package/dist/backend/backend/src/services/user/user-identity.service.d.ts +44 -0
- package/dist/backend/backend/src/services/user/user-identity.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/user/user-identity.service.js +75 -8
- package/dist/backend/backend/src/services/user/user-identity.service.js.map +1 -1
- package/dist/backend/backend/src/services/whatsapp/index.d.ts +11 -0
- package/dist/backend/backend/src/services/whatsapp/index.d.ts.map +1 -0
- package/dist/backend/backend/src/services/whatsapp/index.js +11 -0
- package/dist/backend/backend/src/services/whatsapp/index.js.map +1 -0
- package/dist/backend/backend/src/services/whatsapp/whatsapp-initializer.d.ts +66 -0
- package/dist/backend/backend/src/services/whatsapp/whatsapp-initializer.d.ts.map +1 -0
- package/dist/backend/backend/src/services/whatsapp/whatsapp-initializer.js +96 -0
- package/dist/backend/backend/src/services/whatsapp/whatsapp-initializer.js.map +1 -0
- package/dist/backend/backend/src/services/whatsapp/whatsapp-orchestrator-bridge.d.ts +109 -0
- package/dist/backend/backend/src/services/whatsapp/whatsapp-orchestrator-bridge.d.ts.map +1 -0
- package/dist/backend/backend/src/services/whatsapp/whatsapp-orchestrator-bridge.js +234 -0
- package/dist/backend/backend/src/services/whatsapp/whatsapp-orchestrator-bridge.js.map +1 -0
- package/dist/backend/backend/src/services/whatsapp/whatsapp.service.d.ts +127 -0
- package/dist/backend/backend/src/services/whatsapp/whatsapp.service.d.ts.map +1 -0
- package/dist/backend/backend/src/services/whatsapp/whatsapp.service.js +347 -0
- package/dist/backend/backend/src/services/whatsapp/whatsapp.service.js.map +1 -0
- package/dist/backend/backend/src/services/workflow/scheduler.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/workflow/scheduler.service.js +4 -0
- package/dist/backend/backend/src/services/workflow/scheduler.service.js.map +1 -1
- package/dist/backend/backend/src/types/index.d.ts +1 -0
- package/dist/backend/backend/src/types/index.d.ts.map +1 -1
- package/dist/backend/backend/src/types/index.js.map +1 -1
- package/dist/backend/backend/src/types/slack.types.d.ts +24 -0
- package/dist/backend/backend/src/types/slack.types.d.ts.map +1 -1
- package/dist/backend/backend/src/types/slack.types.js.map +1 -1
- package/dist/backend/backend/src/types/task-tracking.types.d.ts +4 -0
- package/dist/backend/backend/src/types/task-tracking.types.d.ts.map +1 -1
- package/dist/backend/backend/src/types/task-tracking.types.js.map +1 -1
- package/dist/backend/backend/src/types/whatsapp.types.d.ts +84 -0
- package/dist/backend/backend/src/types/whatsapp.types.d.ts.map +1 -0
- package/dist/backend/backend/src/types/whatsapp.types.js +33 -0
- package/dist/backend/backend/src/types/whatsapp.types.js.map +1 -0
- package/dist/backend/backend/src/websocket/terminal.gateway.d.ts +11 -0
- package/dist/backend/backend/src/websocket/terminal.gateway.d.ts.map +1 -1
- package/dist/backend/backend/src/websocket/terminal.gateway.js +35 -1
- package/dist/backend/backend/src/websocket/terminal.gateway.js.map +1 -1
- package/dist/cli/backend/src/constants.d.ts +69 -6
- package/dist/cli/backend/src/constants.d.ts.map +1 -1
- package/dist/cli/backend/src/constants.js +75 -6
- package/dist/cli/backend/src/constants.js.map +1 -1
- package/dist/cli/backend/src/services/knowledge/knowledge-search.service.d.ts.map +1 -1
- package/dist/cli/backend/src/services/knowledge/knowledge-search.service.js +14 -2
- package/dist/cli/backend/src/services/knowledge/knowledge-search.service.js.map +1 -1
- package/dist/cli/backend/src/types/index.d.ts +1 -0
- package/dist/cli/backend/src/types/index.d.ts.map +1 -1
- package/dist/cli/backend/src/types/index.js.map +1 -1
- package/dist/cli/cli/src/commands/publish.d.ts.map +1 -1
- package/dist/cli/cli/src/commands/publish.js +17 -15
- package/dist/cli/cli/src/commands/publish.js.map +1 -1
- package/dist/cli/cli/src/index.js +2 -2
- package/dist/cli/cli/src/index.js.map +1 -1
- package/dist/cli/cli/src/utils/gh-submit.d.ts +46 -0
- package/dist/cli/cli/src/utils/gh-submit.d.ts.map +1 -0
- package/dist/cli/cli/src/utils/gh-submit.js +167 -0
- package/dist/cli/cli/src/utils/gh-submit.js.map +1 -0
- package/dist/cli/cli/src/utils/marketplace.d.ts.map +1 -1
- package/dist/cli/cli/src/utils/marketplace.js +13 -5
- package/dist/cli/cli/src/utils/marketplace.js.map +1 -1
- package/dist/cli/cli/src/utils/templates.d.ts +3 -2
- package/dist/cli/cli/src/utils/templates.d.ts.map +1 -1
- package/dist/cli/cli/src/utils/templates.js +5 -4
- package/dist/cli/cli/src/utils/templates.js.map +1 -1
- package/frontend/dist/assets/{index-45eeea99.js → index-a23214ae.js} +241 -241
- package/frontend/dist/assets/{index-6972eeee.css → index-c407fe13.css} +1 -1
- package/frontend/dist/index.html +2 -2
- package/package.json +3 -1
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import * as path from 'path';
|
|
2
2
|
import * as os from 'os';
|
|
3
|
-
import { readFile, readdir, stat, mkdir, writeFile } from 'fs/promises';
|
|
3
|
+
import { readFile, readdir, stat, mkdir, writeFile, access } from 'fs/promises';
|
|
4
4
|
import { LoggerService } from '../core/logger.service.js';
|
|
5
5
|
import { createSessionCommandHelper, getSessionBackendSync, createSessionBackend, getSessionStatePersistence, } from '../session/index.js';
|
|
6
6
|
import { RuntimeServiceFactory } from './runtime-service.factory.js';
|
|
@@ -13,6 +13,7 @@ import { RuntimeExitMonitorService } from './runtime-exit-monitor.service.js';
|
|
|
13
13
|
import { ContextWindowMonitorService } from './context-window-monitor.service.js';
|
|
14
14
|
import { SubAgentMessageQueue } from '../messaging/sub-agent-message-queue.service.js';
|
|
15
15
|
import { AgentSuspendService } from './agent-suspend.service.js';
|
|
16
|
+
import { stripAnsiCodes } from '../../utils/terminal-output.utils.js';
|
|
16
17
|
/**
|
|
17
18
|
* Service responsible for the complex, multi-step process of agent initialization and registration.
|
|
18
19
|
* Isolates the complex state management of agent startup with progressive escalation.
|
|
@@ -187,11 +188,17 @@ export class AgentRegistrationService {
|
|
|
187
188
|
for (const excluded of (excludedRoleSkills || [])) {
|
|
188
189
|
effectiveSkills.delete(excluded);
|
|
189
190
|
}
|
|
190
|
-
// 3. For each skill, read skill.json and collect flags matching runtime
|
|
191
|
+
// 3. For each skill, read skill.json and collect flags matching runtime.
|
|
192
|
+
// Skills live under agent/core/ or agent/marketplace/ subdirectories,
|
|
193
|
+
// so search both paths when looking up skill.json.
|
|
191
194
|
for (const skillId of effectiveSkills) {
|
|
192
195
|
try {
|
|
193
|
-
const
|
|
194
|
-
|
|
196
|
+
const skillJsonPath = await this.findSkillJsonPath(skillId);
|
|
197
|
+
if (!skillJsonPath) {
|
|
198
|
+
this.logger.warn('Skill config not found in any known directory', { skillId });
|
|
199
|
+
continue;
|
|
200
|
+
}
|
|
201
|
+
const skillContent = await readFile(skillJsonPath, 'utf8');
|
|
195
202
|
const skillConfig = JSON.parse(skillContent);
|
|
196
203
|
if (skillConfig.runtime?.runtime === runtimeType && Array.isArray(skillConfig.runtime?.flags)) {
|
|
197
204
|
for (const flag of skillConfig.runtime.flags) {
|
|
@@ -199,8 +206,11 @@ export class AgentRegistrationService {
|
|
|
199
206
|
}
|
|
200
207
|
}
|
|
201
208
|
}
|
|
202
|
-
catch {
|
|
203
|
-
|
|
209
|
+
catch (skillErr) {
|
|
210
|
+
this.logger.warn('Failed to read skill config', {
|
|
211
|
+
skillId,
|
|
212
|
+
error: skillErr instanceof Error ? skillErr.message : String(skillErr),
|
|
213
|
+
});
|
|
204
214
|
}
|
|
205
215
|
}
|
|
206
216
|
if (flags.size > 0) {
|
|
@@ -216,6 +226,29 @@ export class AgentRegistrationService {
|
|
|
216
226
|
}
|
|
217
227
|
return Array.from(flags);
|
|
218
228
|
}
|
|
229
|
+
/**
|
|
230
|
+
* Search known skill directories for a skill's skill.json file.
|
|
231
|
+
* Skills live under `config/skills/agent/core/` or `config/skills/agent/marketplace/`.
|
|
232
|
+
*
|
|
233
|
+
* @param skillId - The skill identifier (directory name)
|
|
234
|
+
* @returns Absolute path to skill.json, or null if not found
|
|
235
|
+
*/
|
|
236
|
+
async findSkillJsonPath(skillId) {
|
|
237
|
+
const searchDirs = [
|
|
238
|
+
path.join(this.projectRoot, 'config', 'skills', 'agent', 'core', skillId, 'skill.json'),
|
|
239
|
+
path.join(this.projectRoot, 'config', 'skills', 'agent', 'marketplace', skillId, 'skill.json'),
|
|
240
|
+
];
|
|
241
|
+
for (const candidate of searchDirs) {
|
|
242
|
+
try {
|
|
243
|
+
await access(candidate);
|
|
244
|
+
return candidate;
|
|
245
|
+
}
|
|
246
|
+
catch {
|
|
247
|
+
// Not found in this directory, try next
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
return null;
|
|
251
|
+
}
|
|
219
252
|
/**
|
|
220
253
|
* Create a runtime service instance for the given runtime type.
|
|
221
254
|
* Centralizes RuntimeServiceFactory creation to reduce code duplication.
|
|
@@ -422,9 +455,26 @@ export class AgentRegistrationService {
|
|
|
422
455
|
// Must be before postInitialize and sendRegistrationPromptAsync so exits
|
|
423
456
|
// during those phases are detected and the abort signal fires in time.
|
|
424
457
|
RuntimeExitMonitorService.getInstance().startMonitoring(sessionName, runtimeType, role);
|
|
458
|
+
// Look up per-agent browser automation override from member config
|
|
459
|
+
let browserAutomationOverride;
|
|
460
|
+
if (memberId) {
|
|
461
|
+
try {
|
|
462
|
+
const teams = await this.storageService.getTeams();
|
|
463
|
+
for (const team of teams) {
|
|
464
|
+
const member = team.members?.find((m) => m.id === memberId || m.sessionName === sessionName);
|
|
465
|
+
if (member?.enableBrowserAutomation !== undefined) {
|
|
466
|
+
browserAutomationOverride = member.enableBrowserAutomation;
|
|
467
|
+
break;
|
|
468
|
+
}
|
|
469
|
+
}
|
|
470
|
+
}
|
|
471
|
+
catch {
|
|
472
|
+
// Non-fatal — will use global setting
|
|
473
|
+
}
|
|
474
|
+
}
|
|
425
475
|
// Run post-initialization hook (e.g., Gemini CLI directory allowlist)
|
|
426
476
|
try {
|
|
427
|
-
await runtimeService2.postInitialize(sessionName, projectPath, additionalAllowlistPaths);
|
|
477
|
+
await runtimeService2.postInitialize(sessionName, projectPath, additionalAllowlistPaths, browserAutomationOverride);
|
|
428
478
|
// Drain stale terminal escape sequences (e.g. DA1 [?1;2c) that may have
|
|
429
479
|
// arrived during postInitialize commands, so they don't leak into the prompt input
|
|
430
480
|
await delay(500);
|
|
@@ -684,10 +734,27 @@ export class AgentRegistrationService {
|
|
|
684
734
|
// Start runtime exit monitoring immediately after runtime is ready
|
|
685
735
|
RuntimeExitMonitorService.getInstance().startMonitoring(sessionName, runtimeType, role);
|
|
686
736
|
}
|
|
737
|
+
// Look up per-agent browser automation override from member config
|
|
738
|
+
let browserOverrideForRecreation;
|
|
739
|
+
if (memberId) {
|
|
740
|
+
try {
|
|
741
|
+
const teams = await this.storageService.getTeams();
|
|
742
|
+
for (const team of teams) {
|
|
743
|
+
const member = team.members?.find((m) => m.id === memberId || m.sessionName === sessionName);
|
|
744
|
+
if (member?.enableBrowserAutomation !== undefined) {
|
|
745
|
+
browserOverrideForRecreation = member.enableBrowserAutomation;
|
|
746
|
+
break;
|
|
747
|
+
}
|
|
748
|
+
}
|
|
749
|
+
}
|
|
750
|
+
catch {
|
|
751
|
+
// Non-fatal — will use global setting
|
|
752
|
+
}
|
|
753
|
+
}
|
|
687
754
|
// Run post-initialization hook (e.g., Gemini CLI directory allowlist)
|
|
688
755
|
try {
|
|
689
756
|
const postInitService = this.createRuntimeService(runtimeType);
|
|
690
|
-
await postInitService.postInitialize(sessionName, projectPath);
|
|
757
|
+
await postInitService.postInitialize(sessionName, projectPath, undefined, browserOverrideForRecreation);
|
|
691
758
|
// Drain stale terminal escape sequences (e.g. DA1 [?1;2c) that may have
|
|
692
759
|
// arrived during postInitialize commands, so they don't leak into the prompt input
|
|
693
760
|
await delay(500);
|
|
@@ -1742,7 +1809,10 @@ After checking in, just say "Ready for tasks" and wait for me to send you work.`
|
|
|
1742
1809
|
const unsubscribe = session.onData((data) => {
|
|
1743
1810
|
if (resolved)
|
|
1744
1811
|
return;
|
|
1745
|
-
|
|
1812
|
+
// Strip ANSI escape sequences before testing — raw PTY data contains
|
|
1813
|
+
// cursor positioning, color codes, etc. that break regex matching (#106)
|
|
1814
|
+
const cleanData = stripAnsiCodes(data);
|
|
1815
|
+
if (streamPattern.test(cleanData)) {
|
|
1746
1816
|
// Double-check with capturePane to avoid false positives from partial data
|
|
1747
1817
|
const output = sessionHelper.capturePane(sessionName);
|
|
1748
1818
|
if (this.isClaudeAtPrompt(output, runtimeType)) {
|
|
@@ -2035,11 +2105,25 @@ After checking in, just say "Ready for tasks" and wait for me to send you work.`
|
|
|
2035
2105
|
// Verify agent is at prompt before sending
|
|
2036
2106
|
const output = sessionHelper.capturePane(sessionName);
|
|
2037
2107
|
if (!this.isClaudeAtPrompt(output, runtimeType)) {
|
|
2038
|
-
// On the final attempt, fall back to direct delivery rather than
|
|
2039
|
-
// returning a 502 error. The agent may be at a prompt that doesn't
|
|
2040
|
-
// match our detection patterns, or the terminal buffer may be stale.
|
|
2041
|
-
// This mirrors what the /write endpoint does successfully.
|
|
2042
2108
|
if (attempt === maxAttempts) {
|
|
2109
|
+
// On the final attempt, check if the agent is DEFINITELY busy
|
|
2110
|
+
// before force-delivering. If we see "esc to interrupt" or
|
|
2111
|
+
// processing indicators, the agent is actively working and
|
|
2112
|
+
// force-delivery risks corrupting its current task.
|
|
2113
|
+
const tailForBusyCheck = output.slice(-2000);
|
|
2114
|
+
const isBusy = TERMINAL_PATTERNS.BUSY_STATUS_BAR.test(tailForBusyCheck) ||
|
|
2115
|
+
TERMINAL_PATTERNS.PROCESSING_WITH_TEXT.test(tailForBusyCheck);
|
|
2116
|
+
if (isBusy) {
|
|
2117
|
+
this.logger.warn('Agent is busy (processing indicators detected), skipping force delivery', {
|
|
2118
|
+
sessionName,
|
|
2119
|
+
attempt,
|
|
2120
|
+
runtimeType,
|
|
2121
|
+
});
|
|
2122
|
+
return false;
|
|
2123
|
+
}
|
|
2124
|
+
// Not clearly busy — fall back to direct delivery. The agent
|
|
2125
|
+
// may be at a prompt that doesn't match our detection patterns,
|
|
2126
|
+
// or the terminal buffer may be stale.
|
|
2043
2127
|
this.logger.warn('Prompt detection failed on final attempt, delivering message directly', {
|
|
2044
2128
|
sessionName,
|
|
2045
2129
|
attempt,
|
|
@@ -2096,9 +2180,18 @@ After checking in, just say "Ready for tasks" and wait for me to send you work.`
|
|
|
2096
2180
|
}
|
|
2097
2181
|
}
|
|
2098
2182
|
else {
|
|
2099
|
-
//
|
|
2100
|
-
//
|
|
2101
|
-
|
|
2183
|
+
// Detect recent /compress — Ink TUI loses internal focus after
|
|
2184
|
+
// /compress re-renders, causing subsequent messages to be silently
|
|
2185
|
+
// dropped even though the prompt `>` is visible (#114).
|
|
2186
|
+
// Always force PTY resize on attempt 1 if /compress detected.
|
|
2187
|
+
const recentOutput = sessionHelper.capturePane(sessionName, 40);
|
|
2188
|
+
const compressDetected = recentOutput.includes('/compress') ||
|
|
2189
|
+
recentOutput.includes('Context compressed') ||
|
|
2190
|
+
recentOutput.includes('Compressing context');
|
|
2191
|
+
const needsResize = attempt > 1 || compressDetected;
|
|
2192
|
+
// Force a PTY resize to trigger SIGWINCH, making Ink
|
|
2193
|
+
// re-render the TUI and potentially restore focus state.
|
|
2194
|
+
if (needsResize) {
|
|
2102
2195
|
try {
|
|
2103
2196
|
const session = sessionHelper.getSession(sessionName);
|
|
2104
2197
|
if (session) {
|
|
@@ -2110,6 +2203,7 @@ After checking in, just say "Ready for tasks" and wait for me to send you work.`
|
|
|
2110
2203
|
this.logger.debug('PTY resize sent to trigger TUI re-render', {
|
|
2111
2204
|
sessionName,
|
|
2112
2205
|
attempt,
|
|
2206
|
+
compressDetected,
|
|
2113
2207
|
});
|
|
2114
2208
|
}
|
|
2115
2209
|
}
|
|
@@ -2131,7 +2225,8 @@ After checking in, just say "Ready for tasks" and wait for me to send you work.`
|
|
|
2131
2225
|
// the input is engaged. Enter on an empty `> ` prompt is a
|
|
2132
2226
|
// safe no-op (just shows a new blank prompt line).
|
|
2133
2227
|
await sessionHelper.sendEnter(sessionName);
|
|
2134
|
-
|
|
2228
|
+
// Extra settling time after /compress to let Ink TUI stabilize
|
|
2229
|
+
await delay(compressDetected ? 1000 : 500);
|
|
2135
2230
|
}
|
|
2136
2231
|
// For Gemini CLI: detect and gently escape interactive modes before
|
|
2137
2232
|
// sending the message. Avoid Ctrl-C here — Gemini interprets it as
|
|
@@ -2400,7 +2495,12 @@ After checking in, just say "Ready for tasks" and wait for me to send you work.`
|
|
|
2400
2495
|
|| hasProcessingIndicators
|
|
2401
2496
|
|| hasGeminiIndicators;
|
|
2402
2497
|
if (delivered) {
|
|
2403
|
-
|
|
2498
|
+
// Log at warn level when verification passed on weak signals
|
|
2499
|
+
// (output length change only, no explicit processing indicators)
|
|
2500
|
+
// so future false positives are traceable in logs.
|
|
2501
|
+
const hasStrongSignal = hasProcessingIndicators || hasGeminiIndicators;
|
|
2502
|
+
const logLevel = hasStrongSignal ? 'debug' : 'warn';
|
|
2503
|
+
this.logger[logLevel](`Message delivery verified (${hasStrongSignal ? 'strong' : 'weak'} signal)`, {
|
|
2404
2504
|
sessionName,
|
|
2405
2505
|
attempt,
|
|
2406
2506
|
lengthDiff,
|
|
@@ -2408,6 +2508,7 @@ After checking in, just say "Ready for tasks" and wait for me to send you work.`
|
|
|
2408
2508
|
hasProcessingIndicators,
|
|
2409
2509
|
hasGeminiIndicators,
|
|
2410
2510
|
newContentLength: newContent.length,
|
|
2511
|
+
signal: hasStrongSignal ? 'processing-indicators' : 'output-length-change-only',
|
|
2411
2512
|
});
|
|
2412
2513
|
return true;
|
|
2413
2514
|
}
|
|
@@ -2460,6 +2561,19 @@ After checking in, just say "Ready for tasks" and wait for me to send you work.`
|
|
|
2460
2561
|
}
|
|
2461
2562
|
}
|
|
2462
2563
|
}
|
|
2564
|
+
// Verification failed, but the message was physically written to the PTY.
|
|
2565
|
+
// If the session is still alive, the agent will likely process it — return
|
|
2566
|
+
// true to avoid false "Failed to deliver" errors shown to users (#99).
|
|
2567
|
+
const backend = getSessionBackendSync();
|
|
2568
|
+
const childAlive = backend?.isChildProcessAlive?.(sessionName);
|
|
2569
|
+
if (childAlive !== false) {
|
|
2570
|
+
this.logger.warn('Message delivery verification inconclusive but session alive — assuming success', {
|
|
2571
|
+
sessionName,
|
|
2572
|
+
maxAttempts,
|
|
2573
|
+
messageLength: message.length,
|
|
2574
|
+
});
|
|
2575
|
+
return true;
|
|
2576
|
+
}
|
|
2463
2577
|
this.logger.error('Message delivery failed after all retry attempts', {
|
|
2464
2578
|
sessionName,
|
|
2465
2579
|
maxAttempts,
|
|
@@ -2822,11 +2936,14 @@ After checking in, just say "Ready for tasks" and wait for me to send you work.`
|
|
|
2822
2936
|
return TERMINAL_PATTERNS.PROMPT_STREAM;
|
|
2823
2937
|
}
|
|
2824
2938
|
/**
|
|
2825
|
-
* Check if
|
|
2826
|
-
* Looks for
|
|
2939
|
+
* Check if the agent appears to be at an input prompt.
|
|
2940
|
+
* Looks for prompt indicators (❯, ⏵, $, ❯❯, ⏵⏵) in terminal output.
|
|
2941
|
+
* Also checks for busy indicators (esc to interrupt, spinners, ⏺)
|
|
2942
|
+
* to avoid false negatives when the agent is processing.
|
|
2827
2943
|
*
|
|
2828
2944
|
* @param terminalOutput - The terminal output to check
|
|
2829
|
-
* @
|
|
2945
|
+
* @param runtimeType - The runtime type for pattern selection
|
|
2946
|
+
* @returns true if the agent appears to be at a prompt
|
|
2830
2947
|
*/
|
|
2831
2948
|
isClaudeAtPrompt(terminalOutput, runtimeType) {
|
|
2832
2949
|
// Handle null/undefined/empty input — return false since an empty buffer
|
|
@@ -2835,8 +2952,10 @@ After checking in, just say "Ready for tasks" and wait for me to send you work.`
|
|
|
2835
2952
|
this.logger.debug('Terminal output is empty or invalid, cannot detect prompt', { runtimeType });
|
|
2836
2953
|
return false;
|
|
2837
2954
|
}
|
|
2838
|
-
// Only analyze the tail of the buffer to avoid matching historical prompts
|
|
2839
|
-
|
|
2955
|
+
// Only analyze the tail of the buffer to avoid matching historical prompts.
|
|
2956
|
+
// Use 5000 chars to accommodate large tool outputs that push the prompt
|
|
2957
|
+
// further back in the buffer (#106).
|
|
2958
|
+
const tailSection = terminalOutput.slice(-5000);
|
|
2840
2959
|
const isGemini = runtimeType === RUNTIME_TYPES.GEMINI_CLI;
|
|
2841
2960
|
const isClaudeCode = runtimeType === RUNTIME_TYPES.CLAUDE_CODE;
|
|
2842
2961
|
const isCodex = runtimeType === RUNTIME_TYPES.CODEX_CLI;
|
|
@@ -2854,8 +2973,11 @@ After checking in, just say "Ready for tasks" and wait for me to send you work.`
|
|
|
2854
2973
|
const linesToCheck = lines.slice(-10);
|
|
2855
2974
|
const hasPrompt = linesToCheck.some((line) => {
|
|
2856
2975
|
const trimmed = line.trim();
|
|
2857
|
-
// Strip TUI box-drawing borders
|
|
2858
|
-
|
|
2976
|
+
// Strip TUI box-drawing borders that Gemini CLI and other TUI frameworks
|
|
2977
|
+
// wrap around prompts. Covers full Unicode box-drawing range (#106).
|
|
2978
|
+
const stripped = trimmed
|
|
2979
|
+
.replace(/^[\u2500-\u257F|+\-═║╭╮╰╯]+\s*/, '')
|
|
2980
|
+
.replace(/\s*[\u2500-\u257F|+\-═║╭╮╰╯]+$/, '');
|
|
2859
2981
|
// Claude Code prompts: ❯, ⏵, $ alone on a line
|
|
2860
2982
|
if (!isGemini && !isCodex) {
|
|
2861
2983
|
if (['❯', '⏵', '$'].some(ch => trimmed === ch || stripped === ch)) {
|
|
@@ -2863,7 +2985,8 @@ After checking in, just say "Ready for tasks" and wait for me to send you work.`
|
|
|
2863
2985
|
}
|
|
2864
2986
|
// ❯❯ = bypass permissions prompt (idle).
|
|
2865
2987
|
// Matches "❯❯", "❯❯ ", and "❯❯ bypass permissions on (shift+tab to cycle)".
|
|
2866
|
-
//
|
|
2988
|
+
// Note: ⏵⏵ appears in the status bar but is visible both when idle AND
|
|
2989
|
+
// busy, so it cannot be used as a reliable prompt indicator.
|
|
2867
2990
|
if (trimmed.startsWith('❯❯')) {
|
|
2868
2991
|
return true;
|
|
2869
2992
|
}
|
|
@@ -2887,13 +3010,21 @@ After checking in, just say "Ready for tasks" and wait for me to send you work.`
|
|
|
2887
3010
|
if (hasPrompt) {
|
|
2888
3011
|
return true;
|
|
2889
3012
|
}
|
|
2890
|
-
// No prompt found — check if still processing.
|
|
2891
|
-
// lines
|
|
2892
|
-
|
|
3013
|
+
// No prompt found — check if still processing.
|
|
3014
|
+
// Check last 10 lines (not just 5) because tool output can push processing
|
|
3015
|
+
// indicators further up while the status bar stays at the bottom.
|
|
3016
|
+
const recentLines = linesToCheck.join('\n');
|
|
2893
3017
|
if (TERMINAL_PATTERNS.PROCESSING_WITH_TEXT.test(recentLines)) {
|
|
2894
3018
|
this.logger.debug('Processing indicators present near bottom of output');
|
|
2895
3019
|
return false;
|
|
2896
3020
|
}
|
|
3021
|
+
// Check for "esc to interrupt" in the status bar — this is a definitive
|
|
3022
|
+
// busy signal. Claude Code only shows this text while actively processing.
|
|
3023
|
+
// It disappears when the agent returns to idle at the prompt.
|
|
3024
|
+
if (TERMINAL_PATTERNS.BUSY_STATUS_BAR.test(recentLines)) {
|
|
3025
|
+
this.logger.debug('Busy status bar detected (esc to interrupt)');
|
|
3026
|
+
return false;
|
|
3027
|
+
}
|
|
2897
3028
|
this.logger.debug('No prompt detected in terminal output', {
|
|
2898
3029
|
tailLength: tailSection.length,
|
|
2899
3030
|
lastLines: linesToCheck.slice(-3).map(l => l.substring(0, 80)),
|