crewly 1.5.21 → 1.6.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.
Files changed (113) hide show
  1. package/config/roles/orchestrator/prompt.md +182 -25
  2. package/config/skills/agent/core/cancel-followup/SKILL.md +38 -0
  3. package/config/skills/agent/core/cancel-followup/execute.sh +111 -0
  4. package/config/skills/agent/core/cancel-followup/execute.test.sh +42 -0
  5. package/config/skills/agent/core/list-my-followups/SKILL.md +36 -0
  6. package/config/skills/agent/core/list-my-followups/execute.sh +93 -0
  7. package/config/skills/agent/core/list-my-followups/execute.test.sh +41 -0
  8. package/config/skills/agent/core/schedule-followup/SKILL.md +53 -0
  9. package/config/skills/agent/core/schedule-followup/execute.sh +195 -0
  10. package/config/skills/agent/core/schedule-followup/execute.test.sh +48 -0
  11. package/config/skills/agent/core/watch-for-event/SKILL.md +60 -0
  12. package/config/skills/agent/core/watch-for-event/execute.sh +177 -0
  13. package/config/skills/agent/core/watch-for-event/execute.test.sh +43 -0
  14. package/config/skills/orchestrator/credential-manager/SKILL.md +218 -0
  15. package/config/skills/orchestrator/credential-manager/execute.sh +166 -0
  16. package/dist/backend/backend/src/controllers/credentials/credentials.controller.d.ts +80 -0
  17. package/dist/backend/backend/src/controllers/credentials/credentials.controller.d.ts.map +1 -0
  18. package/dist/backend/backend/src/controllers/credentials/credentials.controller.js +365 -0
  19. package/dist/backend/backend/src/controllers/credentials/credentials.controller.js.map +1 -0
  20. package/dist/backend/backend/src/controllers/credentials/credentials.routes.d.ts +26 -0
  21. package/dist/backend/backend/src/controllers/credentials/credentials.routes.d.ts.map +1 -0
  22. package/dist/backend/backend/src/controllers/credentials/credentials.routes.js +40 -0
  23. package/dist/backend/backend/src/controllers/credentials/credentials.routes.js.map +1 -0
  24. package/dist/backend/backend/src/controllers/task-pool/task-pool.controller.js +23 -14
  25. package/dist/backend/backend/src/controllers/task-pool/task-pool.controller.js.map +1 -1
  26. package/dist/backend/backend/src/scripts/backfill-mission-priority.d.ts +3 -1
  27. package/dist/backend/backend/src/scripts/backfill-mission-priority.d.ts.map +1 -1
  28. package/dist/backend/backend/src/scripts/backfill-mission-priority.js +16 -4
  29. package/dist/backend/backend/src/scripts/backfill-mission-priority.js.map +1 -1
  30. package/dist/backend/backend/src/services/browser/browser-proxy.service.d.ts.map +1 -1
  31. package/dist/backend/backend/src/services/browser/browser-proxy.service.js +22 -2
  32. package/dist/backend/backend/src/services/browser/browser-proxy.service.js.map +1 -1
  33. package/dist/backend/backend/src/services/credential/credential-store.service.d.ts +161 -0
  34. package/dist/backend/backend/src/services/credential/credential-store.service.d.ts.map +1 -0
  35. package/dist/backend/backend/src/services/credential/credential-store.service.js +298 -0
  36. package/dist/backend/backend/src/services/credential/credential-store.service.js.map +1 -0
  37. package/dist/backend/backend/src/services/credential/helpers/gemini-cli-workspace.helper.d.ts +117 -0
  38. package/dist/backend/backend/src/services/credential/helpers/gemini-cli-workspace.helper.d.ts.map +1 -0
  39. package/dist/backend/backend/src/services/credential/helpers/gemini-cli-workspace.helper.js +293 -0
  40. package/dist/backend/backend/src/services/credential/helpers/gemini-cli-workspace.helper.js.map +1 -0
  41. package/dist/backend/backend/src/services/project/task.service.d.ts +18 -2
  42. package/dist/backend/backend/src/services/project/task.service.d.ts.map +1 -1
  43. package/dist/backend/backend/src/services/project/task.service.js +69 -53
  44. package/dist/backend/backend/src/services/project/task.service.js.map +1 -1
  45. package/dist/backend/backend/src/services/v3/contract-matcher.d.ts +20 -0
  46. package/dist/backend/backend/src/services/v3/contract-matcher.d.ts.map +1 -0
  47. package/dist/backend/backend/src/services/v3/contract-matcher.js +33 -0
  48. package/dist/backend/backend/src/services/v3/contract-matcher.js.map +1 -0
  49. package/dist/backend/backend/src/services/v3/escalation.service.d.ts +20 -1
  50. package/dist/backend/backend/src/services/v3/escalation.service.d.ts.map +1 -1
  51. package/dist/backend/backend/src/services/v3/escalation.service.js +97 -28
  52. package/dist/backend/backend/src/services/v3/escalation.service.js.map +1 -1
  53. package/dist/backend/backend/src/services/v3/service-contract-gate.service.d.ts +6 -4
  54. package/dist/backend/backend/src/services/v3/service-contract-gate.service.d.ts.map +1 -1
  55. package/dist/backend/backend/src/services/v3/service-contract-gate.service.js +18 -28
  56. package/dist/backend/backend/src/services/v3/service-contract-gate.service.js.map +1 -1
  57. package/dist/backend/backend/src/services/v3/team-trigger-reconciler.service.d.ts.map +1 -1
  58. package/dist/backend/backend/src/services/v3/team-trigger-reconciler.service.js +14 -9
  59. package/dist/backend/backend/src/services/v3/team-trigger-reconciler.service.js.map +1 -1
  60. package/dist/backend/backend/src/services/v3/trigger-engine.service.d.ts +34 -1
  61. package/dist/backend/backend/src/services/v3/trigger-engine.service.d.ts.map +1 -1
  62. package/dist/backend/backend/src/services/v3/trigger-engine.service.js +115 -5
  63. package/dist/backend/backend/src/services/v3/trigger-engine.service.js.map +1 -1
  64. package/dist/backend/backend/src/types/credential.types.d.ts +185 -0
  65. package/dist/backend/backend/src/types/credential.types.d.ts.map +1 -0
  66. package/dist/backend/backend/src/types/credential.types.js +76 -0
  67. package/dist/backend/backend/src/types/credential.types.js.map +1 -0
  68. package/dist/backend/backend/src/utils/encryption.utils.d.ts +57 -0
  69. package/dist/backend/backend/src/utils/encryption.utils.d.ts.map +1 -0
  70. package/dist/backend/backend/src/utils/encryption.utils.js +162 -0
  71. package/dist/backend/backend/src/utils/encryption.utils.js.map +1 -0
  72. package/dist/cli/backend/src/services/credential/credential-store.service.d.ts +161 -0
  73. package/dist/cli/backend/src/services/credential/credential-store.service.d.ts.map +1 -0
  74. package/dist/cli/backend/src/services/credential/credential-store.service.js +298 -0
  75. package/dist/cli/backend/src/services/credential/credential-store.service.js.map +1 -0
  76. package/dist/cli/backend/src/services/credential/helpers/gemini-cli-workspace.helper.d.ts +117 -0
  77. package/dist/cli/backend/src/services/credential/helpers/gemini-cli-workspace.helper.d.ts.map +1 -0
  78. package/dist/cli/backend/src/services/credential/helpers/gemini-cli-workspace.helper.js +293 -0
  79. package/dist/cli/backend/src/services/credential/helpers/gemini-cli-workspace.helper.js.map +1 -0
  80. package/dist/cli/backend/src/services/settings/settings.service.d.ts +168 -0
  81. package/dist/cli/backend/src/services/settings/settings.service.d.ts.map +1 -0
  82. package/dist/cli/backend/src/services/settings/settings.service.js +312 -0
  83. package/dist/cli/backend/src/services/settings/settings.service.js.map +1 -0
  84. package/dist/cli/backend/src/services/skill/skill-executor.service.d.ts +159 -0
  85. package/dist/cli/backend/src/services/skill/skill-executor.service.d.ts.map +1 -0
  86. package/dist/cli/backend/src/services/skill/skill-executor.service.js +626 -0
  87. package/dist/cli/backend/src/services/skill/skill-executor.service.js.map +1 -0
  88. package/dist/cli/backend/src/services/skill/skill.service.d.ts +273 -0
  89. package/dist/cli/backend/src/services/skill/skill.service.d.ts.map +1 -0
  90. package/dist/cli/backend/src/services/skill/skill.service.js +655 -0
  91. package/dist/cli/backend/src/services/skill/skill.service.js.map +1 -0
  92. package/dist/cli/backend/src/types/credential.types.d.ts +185 -0
  93. package/dist/cli/backend/src/types/credential.types.d.ts.map +1 -0
  94. package/dist/cli/backend/src/types/credential.types.js +76 -0
  95. package/dist/cli/backend/src/types/credential.types.js.map +1 -0
  96. package/dist/cli/backend/src/utils/encryption.utils.d.ts +57 -0
  97. package/dist/cli/backend/src/utils/encryption.utils.d.ts.map +1 -0
  98. package/dist/cli/backend/src/utils/encryption.utils.js +162 -0
  99. package/dist/cli/backend/src/utils/encryption.utils.js.map +1 -0
  100. package/dist/cli/backend/src/utils/skill-md-parser.d.ts +38 -0
  101. package/dist/cli/backend/src/utils/skill-md-parser.d.ts.map +1 -0
  102. package/dist/cli/backend/src/utils/skill-md-parser.js +47 -0
  103. package/dist/cli/backend/src/utils/skill-md-parser.js.map +1 -0
  104. package/frontend/dist/assets/{index-dc92ab64.css → index-6aaa0630.css} +1 -1
  105. package/frontend/dist/assets/{index-76d76633.js → index-9e6d97d1.js} +334 -328
  106. package/frontend/dist/index.html +2 -2
  107. package/package.json +1 -1
  108. package/config/experts/empathetic-resolver/expert.json +0 -11
  109. package/config/experts/empathetic-resolver.md +0 -32
  110. package/config/experts/pragmatic-architect/expert.json +0 -11
  111. package/config/experts/pragmatic-architect.md +0 -32
  112. package/config/experts/viral-alchemist/expert.json +0 -11
  113. package/config/experts/viral-alchemist.md +0 -32
@@ -0,0 +1,626 @@
1
+ /**
2
+ * Skill Executor Service
3
+ *
4
+ * Responsible for executing skills including script execution with
5
+ * environment variable injection, browser automation coordination,
6
+ * and MCP tool invocation.
7
+ *
8
+ * @module services/skill/skill-executor.service
9
+ */
10
+ import { spawn } from 'child_process';
11
+ import { promises as fs } from 'fs';
12
+ import * as path from 'path';
13
+ import { SKILL_CONSTANTS, } from '../../types/skill.types.js';
14
+ import { getSkillService } from './skill.service.js';
15
+ import { getSettingsService } from '../settings/settings.service.js';
16
+ import { LoggerService } from '../core/logger.service.js';
17
+ import { getCredentialStoreService } from '../credential/credential-store.service.js';
18
+ import { GeminiCliWorkspaceHelper } from '../credential/helpers/gemini-cli-workspace.helper.js';
19
+ import { MissingCredentialError, InsufficientScopeError, } from '../../types/credential.types.js';
20
+ /**
21
+ * Replace all occurrences of any live secret value in `text` with a
22
+ * `<redacted:{label}>` placeholder.
23
+ */
24
+ function redactSecrets(text, secrets) {
25
+ if (!text || secrets.length === 0)
26
+ return text;
27
+ let out = text;
28
+ for (const { value, label } of secrets) {
29
+ if (value && out.includes(value)) {
30
+ // String.prototype.split+join is safe for all characters (no regex escaping).
31
+ out = out.split(value).join(`<redacted:${label}>`);
32
+ }
33
+ }
34
+ return out;
35
+ }
36
+ /**
37
+ * Service for executing skills
38
+ *
39
+ * Handles:
40
+ * - Script execution with environment variable injection
41
+ * - Browser automation via Claude's Chrome MCP
42
+ * - MCP tool invocation
43
+ * - Composite skill orchestration
44
+ */
45
+ export class SkillExecutorService {
46
+ defaultTimeoutMs = SKILL_CONSTANTS.DEFAULTS.SCRIPT_TIMEOUT_MS;
47
+ logger = LoggerService.getInstance().createComponentLogger('SkillExecutorService');
48
+ /** Lazy-instantiated helpers for credential refresh. */
49
+ geminiCliHelper = null;
50
+ getGeminiCliHelper() {
51
+ if (!this.geminiCliHelper) {
52
+ this.geminiCliHelper = new GeminiCliWorkspaceHelper(getCredentialStoreService());
53
+ }
54
+ return this.geminiCliHelper;
55
+ }
56
+ /**
57
+ * Execute a skill by ID
58
+ *
59
+ * @param skillId - ID of the skill to execute
60
+ * @param context - Execution context with agent and task information
61
+ * @returns Execution result with success status and output
62
+ */
63
+ async executeSkill(skillId, context) {
64
+ const startTime = Date.now();
65
+ try {
66
+ const skillService = getSkillService();
67
+ const skill = await skillService.getSkill(skillId);
68
+ if (!skill) {
69
+ return {
70
+ success: false,
71
+ error: `Skill not found: ${skillId}`,
72
+ durationMs: Date.now() - startTime,
73
+ };
74
+ }
75
+ if (!skill.isEnabled) {
76
+ return {
77
+ success: false,
78
+ error: `Skill is disabled: ${skill.name}`,
79
+ durationMs: Date.now() - startTime,
80
+ };
81
+ }
82
+ return await this.executeSkillInternal(skill, context);
83
+ }
84
+ catch (error) {
85
+ return {
86
+ success: false,
87
+ error: error instanceof Error ? error.message : 'Unknown error',
88
+ durationMs: Date.now() - startTime,
89
+ };
90
+ }
91
+ }
92
+ /**
93
+ * Execute a skill with the full skill object
94
+ *
95
+ * @param skill - Full skill object with prompt content
96
+ * @param context - Execution context
97
+ * @returns Execution result
98
+ */
99
+ async executeSkillInternal(skill, context) {
100
+ const startTime = Date.now();
101
+ // Check if skill is enabled
102
+ if (!skill.isEnabled) {
103
+ return {
104
+ success: false,
105
+ error: `Skill is disabled: ${skill.name}`,
106
+ durationMs: Date.now() - startTime,
107
+ };
108
+ }
109
+ // Check settings for execution type restrictions
110
+ try {
111
+ const settings = await getSettingsService().getSettings();
112
+ if (!settings.skills.enableScriptExecution && skill.execution?.type === 'script') {
113
+ return {
114
+ success: false,
115
+ error: 'Script execution is disabled in settings',
116
+ durationMs: Date.now() - startTime,
117
+ };
118
+ }
119
+ if (!settings.skills.enableBrowserAutomation && skill.execution?.type === 'browser') {
120
+ return {
121
+ success: false,
122
+ error: 'Browser automation is disabled in settings',
123
+ durationMs: Date.now() - startTime,
124
+ };
125
+ }
126
+ }
127
+ catch (error) {
128
+ // If settings can't be loaded, continue with defaults (allow execution)
129
+ this.logger.warn('Failed to load settings, continuing with defaults', { error: error instanceof Error ? error.message : String(error) });
130
+ }
131
+ const executionType = skill.execution?.type ?? 'prompt-only';
132
+ switch (executionType) {
133
+ case 'script':
134
+ return this.executeScript(skill, context);
135
+ case 'browser':
136
+ return this.executeBrowserAutomation(skill, context);
137
+ case 'mcp-tool':
138
+ return this.executeMcpTool(skill, context);
139
+ case 'composite':
140
+ return this.executeComposite(skill, context);
141
+ case 'prompt-only':
142
+ return {
143
+ success: true,
144
+ output: skill.promptContent,
145
+ durationMs: Date.now() - startTime,
146
+ data: { type: 'prompt-only' },
147
+ };
148
+ default:
149
+ return {
150
+ success: false,
151
+ error: `Unknown execution type: ${executionType}`,
152
+ durationMs: Date.now() - startTime,
153
+ };
154
+ }
155
+ }
156
+ /**
157
+ * Execute a script-based skill
158
+ *
159
+ * @param skill - Skill with script configuration
160
+ * @param context - Execution context
161
+ * @returns Execution result
162
+ */
163
+ async executeScript(skill, context) {
164
+ const startTime = Date.now();
165
+ const scriptConfig = skill.execution?.script;
166
+ if (!scriptConfig) {
167
+ return {
168
+ success: false,
169
+ error: 'Script configuration missing',
170
+ durationMs: Date.now() - startTime,
171
+ };
172
+ }
173
+ try {
174
+ // Load environment variables + any live secrets for output redaction
175
+ const { env, liveSecrets } = await this.buildEnvironmentWithSecrets(skill, context);
176
+ // Determine script path
177
+ const skillDir = path.dirname(skill.promptFile);
178
+ const scriptPath = path.isAbsolute(scriptConfig.file)
179
+ ? scriptConfig.file
180
+ : path.join(skillDir, scriptConfig.file);
181
+ // Verify script exists
182
+ await fs.access(scriptPath);
183
+ // Build command based on interpreter
184
+ const { command, args } = this.getInterpreterCommand(scriptConfig.interpreter, scriptPath);
185
+ // Execute script (spawnProcess applies redaction to stdout/stderr using liveSecrets)
186
+ const result = await this.spawnProcess(command, args, {
187
+ cwd: scriptConfig.workingDir || skillDir,
188
+ env,
189
+ timeout: scriptConfig.timeoutMs || this.defaultTimeoutMs,
190
+ liveSecrets,
191
+ });
192
+ return {
193
+ success: result.exitCode === 0,
194
+ output: result.stdout,
195
+ error: result.exitCode !== 0 ? result.stderr : undefined,
196
+ durationMs: Date.now() - startTime,
197
+ data: {
198
+ exitCode: result.exitCode,
199
+ stderr: result.stderr,
200
+ },
201
+ };
202
+ }
203
+ catch (error) {
204
+ return {
205
+ success: false,
206
+ error: error instanceof Error ? error.message : 'Script execution failed',
207
+ durationMs: Date.now() - startTime,
208
+ };
209
+ }
210
+ }
211
+ /**
212
+ * Execute browser automation skill
213
+ *
214
+ * This returns instructions for Claude to use with the Chrome MCP.
215
+ * The actual browser automation is performed by Claude using the
216
+ * mcp__claude-in-chrome__* tools.
217
+ *
218
+ * @param skill - Skill with browser configuration
219
+ * @param context - Execution context
220
+ * @returns Execution result with browser automation prompt
221
+ */
222
+ async executeBrowserAutomation(skill, context) {
223
+ const startTime = Date.now();
224
+ const browserConfig = skill.execution?.browser;
225
+ if (!browserConfig) {
226
+ return {
227
+ success: false,
228
+ error: 'Browser configuration missing',
229
+ durationMs: Date.now() - startTime,
230
+ };
231
+ }
232
+ // Build browser automation prompt for Claude
233
+ const browserPrompt = this.buildBrowserAutomationPrompt(browserConfig, context);
234
+ return {
235
+ success: true,
236
+ output: browserPrompt,
237
+ durationMs: Date.now() - startTime,
238
+ data: {
239
+ type: 'browser-automation',
240
+ url: browserConfig.url,
241
+ requiresChromeMcp: true,
242
+ },
243
+ };
244
+ }
245
+ /**
246
+ * Execute MCP tool skill
247
+ *
248
+ * Returns instructions for invoking the specified MCP tool.
249
+ *
250
+ * @param skill - Skill with MCP tool configuration
251
+ * @param context - Execution context
252
+ * @returns Execution result with MCP tool invocation prompt
253
+ */
254
+ async executeMcpTool(skill, context) {
255
+ const startTime = Date.now();
256
+ const mcpConfig = skill.execution?.mcpTool;
257
+ if (!mcpConfig) {
258
+ return {
259
+ success: false,
260
+ error: 'MCP tool configuration missing',
261
+ durationMs: Date.now() - startTime,
262
+ };
263
+ }
264
+ // Build MCP tool invocation instructions
265
+ const mcpPrompt = this.buildMcpToolPrompt(mcpConfig, context);
266
+ return {
267
+ success: true,
268
+ output: mcpPrompt,
269
+ durationMs: Date.now() - startTime,
270
+ data: {
271
+ type: 'mcp-tool',
272
+ toolName: mcpConfig.toolName,
273
+ defaultParams: mcpConfig.defaultParams,
274
+ },
275
+ };
276
+ }
277
+ /**
278
+ * Execute composite skill (sequence of other skills)
279
+ *
280
+ * @param skill - Skill with composite configuration
281
+ * @param context - Execution context
282
+ * @returns Combined execution result
283
+ */
284
+ async executeComposite(skill, context) {
285
+ const startTime = Date.now();
286
+ const compositeConfig = skill.execution?.composite;
287
+ if (!compositeConfig || !compositeConfig.skillSequence.length) {
288
+ return {
289
+ success: false,
290
+ error: 'Composite configuration missing or empty',
291
+ durationMs: Date.now() - startTime,
292
+ };
293
+ }
294
+ const results = [];
295
+ const outputs = [];
296
+ for (const skillId of compositeConfig.skillSequence) {
297
+ const result = await this.executeSkill(skillId, context);
298
+ results.push(result);
299
+ if (result.output) {
300
+ outputs.push(result.output);
301
+ }
302
+ if (!result.success && !compositeConfig.continueOnError) {
303
+ return {
304
+ success: false,
305
+ error: `Skill ${skillId} failed: ${result.error}`,
306
+ output: outputs.join('\n\n---\n\n'),
307
+ durationMs: Date.now() - startTime,
308
+ data: { results },
309
+ };
310
+ }
311
+ }
312
+ const allSucceeded = results.every((r) => r.success);
313
+ return {
314
+ success: allSucceeded,
315
+ output: outputs.join('\n\n---\n\n'),
316
+ durationMs: Date.now() - startTime,
317
+ data: { results },
318
+ };
319
+ }
320
+ /**
321
+ * Build environment variables for script execution
322
+ *
323
+ * @param skill - Skill with environment configuration
324
+ * @param context - Execution context
325
+ * @returns Environment variables object
326
+ */
327
+ async buildEnvironment(skill, context) {
328
+ // Preserved for callers (tests etc.) that don't need the liveSecrets list.
329
+ const { env } = await this.buildEnvironmentWithSecrets(skill, context);
330
+ return env;
331
+ }
332
+ /**
333
+ * Build environment variables and collect the list of live secret values
334
+ * that need to be redacted from the child process's output. Used by
335
+ * `executeScript` to wire up per-execution output redaction.
336
+ */
337
+ async buildEnvironmentWithSecrets(skill, context) {
338
+ const env = { ...process.env };
339
+ const liveSecrets = [];
340
+ // Add context variables
341
+ env.CREWLY_AGENT_ID = context.agentId;
342
+ env.CREWLY_ROLE_ID = context.roleId;
343
+ if (context.projectId)
344
+ env.CREWLY_PROJECT_ID = context.projectId;
345
+ if (context.taskId)
346
+ env.CREWLY_TASK_ID = context.taskId;
347
+ if (context.userInput)
348
+ env.CREWLY_USER_INPUT = context.userInput;
349
+ // Resolve credential slots declared in the skill frontmatter.
350
+ // Runs BEFORE .env-file loading so that a credential-injected var can
351
+ // be overridden by an explicit .env entry if desired.
352
+ if (skill.credentials && skill.credentials.length > 0) {
353
+ await this.resolveAndInjectCredentials(skill.credentials, context, env, liveSecrets);
354
+ }
355
+ const envConfig = skill.environment;
356
+ if (!envConfig)
357
+ return { env, liveSecrets };
358
+ // Load from .env file if specified
359
+ if (envConfig.file) {
360
+ const skillDir = path.dirname(skill.promptFile);
361
+ const envFilePath = path.join(skillDir, envConfig.file);
362
+ try {
363
+ const envContent = await fs.readFile(envFilePath, 'utf-8');
364
+ const parsed = this.parseEnvFile(envContent);
365
+ Object.assign(env, parsed);
366
+ }
367
+ catch (error) {
368
+ this.logger.warn('Failed to load env file', { envFilePath });
369
+ }
370
+ }
371
+ // Add inline variables (override file values)
372
+ if (envConfig.variables) {
373
+ Object.assign(env, envConfig.variables);
374
+ }
375
+ // Check required variables
376
+ if (envConfig.required) {
377
+ for (const varName of envConfig.required) {
378
+ if (!env[varName]) {
379
+ throw new Error(`Required environment variable missing: ${varName}`);
380
+ }
381
+ }
382
+ }
383
+ return { env, liveSecrets };
384
+ }
385
+ /**
386
+ * For each credential requirement declared on the skill:
387
+ * - Resolve it to a credential UUID (agent binding → skill default)
388
+ * - Look up the credential, decrypt the payload
389
+ * - Verify scopes (OAuth)
390
+ * - Refresh tokens if near expiry
391
+ * - Inject values into env vars named `CREWLY_CRED_<SLOT>_*`
392
+ * - Register secret values for output redaction
393
+ */
394
+ async resolveAndInjectCredentials(requirements, context, env, liveSecrets) {
395
+ const store = getCredentialStoreService();
396
+ for (const req of requirements) {
397
+ const bindingId = context.credentialBindings?.[req.slot] ?? req.default;
398
+ if (!bindingId) {
399
+ if (req.required) {
400
+ throw new MissingCredentialError(req.slot, req.provider);
401
+ }
402
+ continue;
403
+ }
404
+ const entry = await store.getCredential(bindingId);
405
+ if (entry.status === 'revoked') {
406
+ throw new Error(`Credential '${entry.name}' (slot '${req.slot}') is revoked. Re-authorize before using this skill.`);
407
+ }
408
+ const payload = await store.getPayload(bindingId);
409
+ // Verify scopes for OAuth
410
+ if (req.requiredScopes && req.requiredScopes.length > 0) {
411
+ if (payload.type !== 'google-oauth') {
412
+ throw new Error(`Slot '${req.slot}' declared requiredScopes but credential is type '${payload.type}'.`);
413
+ }
414
+ const granted = new Set(payload.scopes);
415
+ const missing = req.requiredScopes.filter((s) => !granted.has(s));
416
+ if (missing.length > 0) {
417
+ throw new InsufficientScopeError(req.slot, req.requiredScopes, payload.scopes);
418
+ }
419
+ }
420
+ const slotEnv = this.credentialEnvPrefix(req.slot);
421
+ if (payload.type === 'google-oauth') {
422
+ // Refresh if near expiry
423
+ let finalPayload = payload;
424
+ if (entry.helper === 'gemini-cli-workspace') {
425
+ try {
426
+ finalPayload = await this.getGeminiCliHelper().getAccessToken(entry, payload);
427
+ }
428
+ catch (err) {
429
+ // Bubble up — includes CredentialRevokedError with remediation
430
+ throw err;
431
+ }
432
+ }
433
+ env[`${slotEnv}_ACCESS_TOKEN`] = finalPayload.accessToken;
434
+ env[`${slotEnv}_REFRESH_TOKEN`] = finalPayload.refreshToken;
435
+ env[`${slotEnv}_TOKEN_TYPE`] = finalPayload.tokenType;
436
+ env[`${slotEnv}_EXPIRES_AT`] = String(finalPayload.expiresAt);
437
+ env[`${slotEnv}_SCOPES`] = finalPayload.scopes.join(' ');
438
+ if (finalPayload.accountEmail) {
439
+ env[`${slotEnv}_EMAIL`] = finalPayload.accountEmail;
440
+ }
441
+ // Redact both tokens from output
442
+ liveSecrets.push({ value: finalPayload.accessToken, label: `${req.slot}:access_token` });
443
+ liveSecrets.push({ value: finalPayload.refreshToken, label: `${req.slot}:refresh_token` });
444
+ }
445
+ else {
446
+ // api-key
447
+ const apiPayload = payload;
448
+ env[slotEnv] = apiPayload.value;
449
+ liveSecrets.push({ value: apiPayload.value, label: req.slot });
450
+ }
451
+ // Record usage (best-effort — don't block execution if this fails)
452
+ try {
453
+ await store.updateCredential(bindingId, {
454
+ lastUsedAt: new Date().toISOString(),
455
+ });
456
+ }
457
+ catch (err) {
458
+ this.logger.warn('Failed to update lastUsedAt for credential', {
459
+ credentialId: bindingId,
460
+ });
461
+ }
462
+ }
463
+ }
464
+ /**
465
+ * Slot name to env var prefix. `gmail-drive` → `CREWLY_CRED_GMAIL_DRIVE`.
466
+ */
467
+ credentialEnvPrefix(slot) {
468
+ return `CREWLY_CRED_${slot.toUpperCase().replace(/-/g, '_')}`;
469
+ }
470
+ /**
471
+ * Parse .env file content into key-value pairs
472
+ *
473
+ * @param content - Content of .env file
474
+ * @returns Parsed environment variables
475
+ */
476
+ parseEnvFile(content) {
477
+ const result = {};
478
+ const lines = content.split('\n');
479
+ for (const line of lines) {
480
+ const trimmed = line.trim();
481
+ if (!trimmed || trimmed.startsWith('#'))
482
+ continue;
483
+ const match = trimmed.match(/^([^=]+)=(.*)$/);
484
+ if (match) {
485
+ const key = match[1].trim();
486
+ let value = match[2].trim();
487
+ // Remove quotes
488
+ if ((value.startsWith('"') && value.endsWith('"')) ||
489
+ (value.startsWith("'") && value.endsWith("'"))) {
490
+ value = value.slice(1, -1);
491
+ }
492
+ result[key] = value;
493
+ }
494
+ }
495
+ return result;
496
+ }
497
+ /**
498
+ * Get interpreter command and arguments for script execution
499
+ *
500
+ * @param interpreter - Script interpreter type
501
+ * @param scriptPath - Path to the script file
502
+ * @returns Command and arguments
503
+ */
504
+ getInterpreterCommand(interpreter, scriptPath) {
505
+ switch (interpreter) {
506
+ case 'bash':
507
+ return { command: 'bash', args: [scriptPath] };
508
+ case 'python':
509
+ return { command: 'python3', args: [scriptPath] };
510
+ case 'node':
511
+ return { command: 'node', args: [scriptPath] };
512
+ default:
513
+ return { command: interpreter, args: [scriptPath] };
514
+ }
515
+ }
516
+ /**
517
+ * Spawn a process and capture output
518
+ *
519
+ * @param command - Command to execute
520
+ * @param args - Command arguments
521
+ * @param options - Execution options
522
+ * @returns Process result with stdout, stderr, and exit code
523
+ */
524
+ spawnProcess(command, args, options) {
525
+ return new Promise((resolve, reject) => {
526
+ const child = spawn(command, args, {
527
+ cwd: options.cwd,
528
+ env: options.env,
529
+ shell: false,
530
+ });
531
+ let stdout = '';
532
+ let stderr = '';
533
+ child.stdout.on('data', (data) => {
534
+ stdout += data.toString();
535
+ });
536
+ child.stderr.on('data', (data) => {
537
+ stderr += data.toString();
538
+ });
539
+ const timeoutMs = options.timeout || this.defaultTimeoutMs;
540
+ const timeoutId = setTimeout(() => {
541
+ child.kill('SIGTERM');
542
+ reject(new Error(`Process timed out after ${timeoutMs}ms`));
543
+ }, timeoutMs);
544
+ child.on('close', (exitCode) => {
545
+ clearTimeout(timeoutId);
546
+ const secrets = options.liveSecrets ?? [];
547
+ resolve({
548
+ stdout: redactSecrets(stdout, secrets),
549
+ stderr: redactSecrets(stderr, secrets),
550
+ exitCode: exitCode ?? 1,
551
+ });
552
+ });
553
+ child.on('error', (error) => {
554
+ clearTimeout(timeoutId);
555
+ reject(error);
556
+ });
557
+ });
558
+ }
559
+ /**
560
+ * Build browser automation prompt for Claude
561
+ *
562
+ * @param config - Browser configuration
563
+ * @param context - Execution context
564
+ * @returns Formatted prompt for browser automation
565
+ */
566
+ buildBrowserAutomationPrompt(config, context) {
567
+ let prompt = `## Browser Automation Task\n\n`;
568
+ prompt += `Navigate to: ${config.url}\n\n`;
569
+ prompt += `### Instructions\n${config.instructions}\n\n`;
570
+ if (config.actions?.length) {
571
+ prompt += `### Specific Actions\n`;
572
+ config.actions.forEach((action, i) => {
573
+ prompt += `${i + 1}. ${action}\n`;
574
+ });
575
+ prompt += '\n';
576
+ }
577
+ if (context.userInput) {
578
+ prompt += `### User Context\n${context.userInput}\n\n`;
579
+ }
580
+ prompt += `*Use the Claude Chrome MCP tools (mcp__claude-in-chrome__*) to complete this task.*`;
581
+ return prompt;
582
+ }
583
+ /**
584
+ * Build MCP tool invocation prompt
585
+ *
586
+ * @param config - MCP tool configuration
587
+ * @param context - Execution context
588
+ * @returns Formatted prompt for MCP tool invocation
589
+ */
590
+ buildMcpToolPrompt(config, context) {
591
+ let prompt = `## MCP Tool Invocation\n\n`;
592
+ prompt += `Tool: ${config.toolName}\n\n`;
593
+ if (config.defaultParams) {
594
+ prompt += `### Default Parameters\n`;
595
+ prompt += '```json\n';
596
+ prompt += JSON.stringify(config.defaultParams, null, 2);
597
+ prompt += '\n```\n\n';
598
+ }
599
+ if (context.userInput) {
600
+ prompt += `### User Context\n${context.userInput}\n`;
601
+ }
602
+ return prompt;
603
+ }
604
+ }
605
+ // =============================================================================
606
+ // Singleton Instance
607
+ // =============================================================================
608
+ let executorInstance = null;
609
+ /**
610
+ * Get the singleton SkillExecutorService instance
611
+ *
612
+ * @returns The SkillExecutorService instance
613
+ */
614
+ export function getSkillExecutorService() {
615
+ if (!executorInstance) {
616
+ executorInstance = new SkillExecutorService();
617
+ }
618
+ return executorInstance;
619
+ }
620
+ /**
621
+ * Reset the singleton instance (for testing)
622
+ */
623
+ export function resetSkillExecutorService() {
624
+ executorInstance = null;
625
+ }
626
+ //# sourceMappingURL=skill-executor.service.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"skill-executor.service.js","sourceRoot":"","sources":["../../../../../../backend/src/services/skill/skill-executor.service.ts"],"names":[],"mappings":"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"}