crewly 1.5.22 → 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 (112) 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.js +1 -1
  31. package/dist/backend/backend/src/services/browser/browser-proxy.service.js.map +1 -1
  32. package/dist/backend/backend/src/services/credential/credential-store.service.d.ts +161 -0
  33. package/dist/backend/backend/src/services/credential/credential-store.service.d.ts.map +1 -0
  34. package/dist/backend/backend/src/services/credential/credential-store.service.js +298 -0
  35. package/dist/backend/backend/src/services/credential/credential-store.service.js.map +1 -0
  36. package/dist/backend/backend/src/services/credential/helpers/gemini-cli-workspace.helper.d.ts +117 -0
  37. package/dist/backend/backend/src/services/credential/helpers/gemini-cli-workspace.helper.d.ts.map +1 -0
  38. package/dist/backend/backend/src/services/credential/helpers/gemini-cli-workspace.helper.js +293 -0
  39. package/dist/backend/backend/src/services/credential/helpers/gemini-cli-workspace.helper.js.map +1 -0
  40. package/dist/backend/backend/src/services/project/task.service.d.ts +18 -2
  41. package/dist/backend/backend/src/services/project/task.service.d.ts.map +1 -1
  42. package/dist/backend/backend/src/services/project/task.service.js +69 -53
  43. package/dist/backend/backend/src/services/project/task.service.js.map +1 -1
  44. package/dist/backend/backend/src/services/v3/contract-matcher.d.ts +20 -0
  45. package/dist/backend/backend/src/services/v3/contract-matcher.d.ts.map +1 -0
  46. package/dist/backend/backend/src/services/v3/contract-matcher.js +33 -0
  47. package/dist/backend/backend/src/services/v3/contract-matcher.js.map +1 -0
  48. package/dist/backend/backend/src/services/v3/escalation.service.d.ts +20 -1
  49. package/dist/backend/backend/src/services/v3/escalation.service.d.ts.map +1 -1
  50. package/dist/backend/backend/src/services/v3/escalation.service.js +97 -28
  51. package/dist/backend/backend/src/services/v3/escalation.service.js.map +1 -1
  52. package/dist/backend/backend/src/services/v3/service-contract-gate.service.d.ts +6 -4
  53. package/dist/backend/backend/src/services/v3/service-contract-gate.service.d.ts.map +1 -1
  54. package/dist/backend/backend/src/services/v3/service-contract-gate.service.js +18 -28
  55. package/dist/backend/backend/src/services/v3/service-contract-gate.service.js.map +1 -1
  56. package/dist/backend/backend/src/services/v3/team-trigger-reconciler.service.d.ts.map +1 -1
  57. package/dist/backend/backend/src/services/v3/team-trigger-reconciler.service.js +14 -9
  58. package/dist/backend/backend/src/services/v3/team-trigger-reconciler.service.js.map +1 -1
  59. package/dist/backend/backend/src/services/v3/trigger-engine.service.d.ts +34 -1
  60. package/dist/backend/backend/src/services/v3/trigger-engine.service.d.ts.map +1 -1
  61. package/dist/backend/backend/src/services/v3/trigger-engine.service.js +115 -5
  62. package/dist/backend/backend/src/services/v3/trigger-engine.service.js.map +1 -1
  63. package/dist/backend/backend/src/types/credential.types.d.ts +185 -0
  64. package/dist/backend/backend/src/types/credential.types.d.ts.map +1 -0
  65. package/dist/backend/backend/src/types/credential.types.js +76 -0
  66. package/dist/backend/backend/src/types/credential.types.js.map +1 -0
  67. package/dist/backend/backend/src/utils/encryption.utils.d.ts +57 -0
  68. package/dist/backend/backend/src/utils/encryption.utils.d.ts.map +1 -0
  69. package/dist/backend/backend/src/utils/encryption.utils.js +162 -0
  70. package/dist/backend/backend/src/utils/encryption.utils.js.map +1 -0
  71. package/dist/cli/backend/src/services/credential/credential-store.service.d.ts +161 -0
  72. package/dist/cli/backend/src/services/credential/credential-store.service.d.ts.map +1 -0
  73. package/dist/cli/backend/src/services/credential/credential-store.service.js +298 -0
  74. package/dist/cli/backend/src/services/credential/credential-store.service.js.map +1 -0
  75. package/dist/cli/backend/src/services/credential/helpers/gemini-cli-workspace.helper.d.ts +117 -0
  76. package/dist/cli/backend/src/services/credential/helpers/gemini-cli-workspace.helper.d.ts.map +1 -0
  77. package/dist/cli/backend/src/services/credential/helpers/gemini-cli-workspace.helper.js +293 -0
  78. package/dist/cli/backend/src/services/credential/helpers/gemini-cli-workspace.helper.js.map +1 -0
  79. package/dist/cli/backend/src/services/settings/settings.service.d.ts +168 -0
  80. package/dist/cli/backend/src/services/settings/settings.service.d.ts.map +1 -0
  81. package/dist/cli/backend/src/services/settings/settings.service.js +312 -0
  82. package/dist/cli/backend/src/services/settings/settings.service.js.map +1 -0
  83. package/dist/cli/backend/src/services/skill/skill-executor.service.d.ts +159 -0
  84. package/dist/cli/backend/src/services/skill/skill-executor.service.d.ts.map +1 -0
  85. package/dist/cli/backend/src/services/skill/skill-executor.service.js +626 -0
  86. package/dist/cli/backend/src/services/skill/skill-executor.service.js.map +1 -0
  87. package/dist/cli/backend/src/services/skill/skill.service.d.ts +273 -0
  88. package/dist/cli/backend/src/services/skill/skill.service.d.ts.map +1 -0
  89. package/dist/cli/backend/src/services/skill/skill.service.js +655 -0
  90. package/dist/cli/backend/src/services/skill/skill.service.js.map +1 -0
  91. package/dist/cli/backend/src/types/credential.types.d.ts +185 -0
  92. package/dist/cli/backend/src/types/credential.types.d.ts.map +1 -0
  93. package/dist/cli/backend/src/types/credential.types.js +76 -0
  94. package/dist/cli/backend/src/types/credential.types.js.map +1 -0
  95. package/dist/cli/backend/src/utils/encryption.utils.d.ts +57 -0
  96. package/dist/cli/backend/src/utils/encryption.utils.d.ts.map +1 -0
  97. package/dist/cli/backend/src/utils/encryption.utils.js +162 -0
  98. package/dist/cli/backend/src/utils/encryption.utils.js.map +1 -0
  99. package/dist/cli/backend/src/utils/skill-md-parser.d.ts +38 -0
  100. package/dist/cli/backend/src/utils/skill-md-parser.d.ts.map +1 -0
  101. package/dist/cli/backend/src/utils/skill-md-parser.js +47 -0
  102. package/dist/cli/backend/src/utils/skill-md-parser.js.map +1 -0
  103. package/frontend/dist/assets/{index-dc92ab64.css → index-6aaa0630.css} +1 -1
  104. package/frontend/dist/assets/{index-76d76633.js → index-9e6d97d1.js} +334 -328
  105. package/frontend/dist/index.html +2 -2
  106. package/package.json +1 -1
  107. package/config/experts/empathetic-resolver/expert.json +0 -11
  108. package/config/experts/empathetic-resolver.md +0 -32
  109. package/config/experts/pragmatic-architect/expert.json +0 -11
  110. package/config/experts/pragmatic-architect.md +0 -32
  111. package/config/experts/viral-alchemist/expert.json +0 -11
  112. package/config/experts/viral-alchemist.md +0 -32
@@ -0,0 +1,312 @@
1
+ /**
2
+ * Settings Management Service
3
+ *
4
+ * Handles persistence and validation of Crewly application settings.
5
+ * Settings are stored in ~/.crewly/settings.json.
6
+ *
7
+ * @module services/settings/settings.service
8
+ */
9
+ import { promises as fs } from 'fs';
10
+ import path from 'path';
11
+ import { getDefaultSettings, validateSettings, mergeSettings, resolveApiKey, } from '../../types/settings.types.js';
12
+ import { atomicWriteJson, safeReadJson } from '../../utils/file-io.utils.js';
13
+ // ============================================================================
14
+ // Custom Error Classes
15
+ // ============================================================================
16
+ /**
17
+ * Error thrown when settings validation fails
18
+ */
19
+ export class SettingsValidationError extends Error {
20
+ errors;
21
+ constructor(errors) {
22
+ super(`Settings validation failed: ${errors.join(', ')}`);
23
+ this.name = 'SettingsValidationError';
24
+ this.errors = errors;
25
+ }
26
+ }
27
+ /**
28
+ * Error thrown when settings file cannot be read or parsed
29
+ */
30
+ export class SettingsFileError extends Error {
31
+ cause;
32
+ constructor(message, cause) {
33
+ super(message);
34
+ this.cause = cause;
35
+ this.name = 'SettingsFileError';
36
+ }
37
+ }
38
+ // ============================================================================
39
+ // SettingsService Class
40
+ // ============================================================================
41
+ /**
42
+ * Service for managing Crewly application settings
43
+ *
44
+ * Settings are stored in ~/.crewly/settings.json by default.
45
+ * Default values are used when no settings file exists.
46
+ *
47
+ * @example
48
+ * ```typescript
49
+ * const service = getSettingsService();
50
+ *
51
+ * // Get current settings
52
+ * const settings = await service.getSettings();
53
+ *
54
+ * // Update settings
55
+ * await service.updateSettings({
56
+ * general: { verboseLogging: true },
57
+ * });
58
+ *
59
+ * // Reset to defaults
60
+ * await service.resetSettings();
61
+ * ```
62
+ */
63
+ export class SettingsService {
64
+ settingsDir;
65
+ settingsFile;
66
+ settingsCache = null;
67
+ /**
68
+ * Create a new SettingsService instance
69
+ *
70
+ * @param options - Configuration options
71
+ * @param options.settingsDir - Directory for settings file
72
+ */
73
+ constructor(options) {
74
+ this.settingsDir = options?.settingsDir ??
75
+ path.join(process.env.HOME || '~', '.crewly');
76
+ this.settingsFile = path.join(this.settingsDir, 'settings.json');
77
+ }
78
+ /**
79
+ * Get current settings, loading from file if not cached
80
+ *
81
+ * If settings file doesn't exist or is invalid, returns default settings.
82
+ *
83
+ * @returns Current settings
84
+ */
85
+ async getSettings() {
86
+ if (this.settingsCache) {
87
+ return this.settingsCache;
88
+ }
89
+ const loaded = await safeReadJson(this.settingsFile, null);
90
+ if (loaded) {
91
+ // Migrate legacy claudeCodeCommand/claudeCodeInitScript → runtimeCommands
92
+ this.migrateSettings(loaded);
93
+ this.settingsCache = mergeSettings(getDefaultSettings(), loaded);
94
+ return this.settingsCache;
95
+ }
96
+ return getDefaultSettings();
97
+ }
98
+ /**
99
+ * Update settings with partial input
100
+ *
101
+ * Merges the input with current settings and validates before saving.
102
+ *
103
+ * @param input - Partial settings to update
104
+ * @returns Updated settings
105
+ * @throws {SettingsValidationError} If validation fails
106
+ */
107
+ async updateSettings(input) {
108
+ const current = await this.getSettings();
109
+ const merged = mergeSettings(current, input);
110
+ const validation = validateSettings(merged);
111
+ if (!validation.valid) {
112
+ throw new SettingsValidationError(validation.errors);
113
+ }
114
+ await this.saveSettings(merged);
115
+ this.settingsCache = merged;
116
+ return merged;
117
+ }
118
+ /**
119
+ * Reset all settings to defaults
120
+ *
121
+ * @returns Default settings
122
+ */
123
+ async resetSettings() {
124
+ const defaults = getDefaultSettings();
125
+ await this.saveSettings(defaults);
126
+ this.settingsCache = defaults;
127
+ return defaults;
128
+ }
129
+ /**
130
+ * Reset a specific settings section to defaults
131
+ *
132
+ * @param section - The section to reset ('general', 'chat', or 'skills')
133
+ * @returns Updated settings
134
+ */
135
+ async resetSection(section) {
136
+ const current = await this.getSettings();
137
+ const defaults = getDefaultSettings();
138
+ const updated = {
139
+ ...current,
140
+ [section]: defaults[section],
141
+ };
142
+ await this.saveSettings(updated);
143
+ this.settingsCache = updated;
144
+ return updated;
145
+ }
146
+ /**
147
+ * Validate settings input without saving
148
+ *
149
+ * Useful for form validation before submission.
150
+ *
151
+ * @param input - Settings to validate
152
+ * @returns Validation result
153
+ */
154
+ async validateSettingsInput(input) {
155
+ const current = await this.getSettings();
156
+ const merged = mergeSettings(current, input);
157
+ return validateSettings(merged);
158
+ }
159
+ /**
160
+ * Export settings to a file
161
+ *
162
+ * @param exportPath - Path to export file
163
+ */
164
+ async exportSettings(exportPath) {
165
+ const settings = await this.getSettings();
166
+ await atomicWriteJson(exportPath, settings);
167
+ }
168
+ /**
169
+ * Import settings from a file
170
+ *
171
+ * Validates imported settings before saving.
172
+ *
173
+ * @param importPath - Path to import file
174
+ * @returns Imported settings
175
+ * @throws {SettingsValidationError} If imported settings are invalid
176
+ * @throws {SettingsFileError} If file cannot be read or parsed
177
+ */
178
+ async importSettings(importPath) {
179
+ let content;
180
+ try {
181
+ content = await fs.readFile(importPath, 'utf-8');
182
+ }
183
+ catch (err) {
184
+ throw new SettingsFileError(`Failed to read settings file: ${importPath}`, err);
185
+ }
186
+ let imported;
187
+ try {
188
+ imported = JSON.parse(content);
189
+ }
190
+ catch (err) {
191
+ throw new SettingsFileError('Failed to parse settings file: invalid JSON', err);
192
+ }
193
+ // Merge with defaults to fill in missing properties
194
+ const defaults = getDefaultSettings();
195
+ const merged = mergeSettings(defaults, imported);
196
+ const validation = validateSettings(merged);
197
+ if (!validation.valid) {
198
+ throw new SettingsValidationError(validation.errors);
199
+ }
200
+ await this.saveSettings(merged);
201
+ this.settingsCache = merged;
202
+ return merged;
203
+ }
204
+ /**
205
+ * Resolve an API key through the override chain: skill → runtime → global → env var
206
+ *
207
+ * @param provider - The API key provider (gemini, anthropic, openai)
208
+ * @param context - Optional context with runtime and/or skill for override resolution
209
+ * @returns The resolved API key or undefined if not configured anywhere
210
+ */
211
+ async getApiKey(provider, context) {
212
+ const settings = await this.getSettings();
213
+ return resolveApiKey(provider, settings.apiKeys, context);
214
+ }
215
+ /**
216
+ * Clear the settings cache
217
+ *
218
+ * Forces the next getSettings call to reload from disk.
219
+ */
220
+ clearCache() {
221
+ this.settingsCache = null;
222
+ }
223
+ /**
224
+ * Get the path to the settings file
225
+ *
226
+ * @returns Absolute path to settings.json
227
+ */
228
+ getSettingsFilePath() {
229
+ return this.settingsFile;
230
+ }
231
+ /**
232
+ * Check if a settings file exists
233
+ *
234
+ * @returns True if settings file exists
235
+ */
236
+ async hasSettingsFile() {
237
+ try {
238
+ await fs.access(this.settingsFile);
239
+ return true;
240
+ }
241
+ catch {
242
+ return false;
243
+ }
244
+ }
245
+ // ============================================================================
246
+ // Private Methods
247
+ // ============================================================================
248
+ /**
249
+ * Migrate legacy settings format to current format
250
+ *
251
+ * Converts old claudeCodeCommand/claudeCodeInitScript fields
252
+ * to the new runtimeCommands map.
253
+ *
254
+ * @param loaded - Partially loaded settings from disk
255
+ */
256
+ migrateSettings(loaded) {
257
+ const general = loaded.general;
258
+ if (!general)
259
+ return;
260
+ const hasLegacyCommand = typeof general['claudeCodeCommand'] === 'string';
261
+ const hasRuntimeCommands = general['runtimeCommands'] !== undefined;
262
+ if (hasLegacyCommand && !hasRuntimeCommands) {
263
+ const defaults = getDefaultSettings();
264
+ general['runtimeCommands'] = {
265
+ 'claude-code': general['claudeCodeCommand'],
266
+ 'gemini-cli': defaults.general.runtimeCommands['gemini-cli'],
267
+ 'codex-cli': defaults.general.runtimeCommands['codex-cli'],
268
+ 'crewly-agent': defaults.general.runtimeCommands['crewly-agent'],
269
+ };
270
+ }
271
+ // Keep existing users aligned with the current safer Codex default.
272
+ // Only rewrite when their value is exactly the previous built-in default.
273
+ const runtimeCommands = general['runtimeCommands'];
274
+ if (runtimeCommands?.['codex-cli'] === 'codex --full-auto') {
275
+ runtimeCommands['codex-cli'] = 'codex -a never -s danger-full-access';
276
+ }
277
+ // Clean up legacy fields
278
+ delete general['claudeCodeCommand'];
279
+ delete general['claudeCodeInitScript'];
280
+ }
281
+ /**
282
+ * Save settings to disk
283
+ *
284
+ * @param settings - Settings to save
285
+ */
286
+ async saveSettings(settings) {
287
+ await fs.mkdir(this.settingsDir, { recursive: true });
288
+ await atomicWriteJson(this.settingsFile, settings);
289
+ }
290
+ }
291
+ // ============================================================================
292
+ // Singleton Instance
293
+ // ============================================================================
294
+ let settingsServiceInstance = null;
295
+ /**
296
+ * Get the singleton SettingsService instance
297
+ *
298
+ * @returns The SettingsService instance
299
+ */
300
+ export function getSettingsService() {
301
+ if (!settingsServiceInstance) {
302
+ settingsServiceInstance = new SettingsService();
303
+ }
304
+ return settingsServiceInstance;
305
+ }
306
+ /**
307
+ * Reset the singleton instance (for testing)
308
+ */
309
+ export function resetSettingsService() {
310
+ settingsServiceInstance = null;
311
+ }
312
+ //# sourceMappingURL=settings.service.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"settings.service.js","sourceRoot":"","sources":["../../../../../../backend/src/services/settings/settings.service.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,159 @@
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 { SkillWithPrompt, SkillExecutionContext, SkillExecutionResult } from '../../types/skill.types.js';
11
+ /**
12
+ * Service for executing skills
13
+ *
14
+ * Handles:
15
+ * - Script execution with environment variable injection
16
+ * - Browser automation via Claude's Chrome MCP
17
+ * - MCP tool invocation
18
+ * - Composite skill orchestration
19
+ */
20
+ export declare class SkillExecutorService {
21
+ private readonly defaultTimeoutMs;
22
+ private readonly logger;
23
+ /** Lazy-instantiated helpers for credential refresh. */
24
+ private geminiCliHelper;
25
+ private getGeminiCliHelper;
26
+ /**
27
+ * Execute a skill by ID
28
+ *
29
+ * @param skillId - ID of the skill to execute
30
+ * @param context - Execution context with agent and task information
31
+ * @returns Execution result with success status and output
32
+ */
33
+ executeSkill(skillId: string, context: SkillExecutionContext): Promise<SkillExecutionResult>;
34
+ /**
35
+ * Execute a skill with the full skill object
36
+ *
37
+ * @param skill - Full skill object with prompt content
38
+ * @param context - Execution context
39
+ * @returns Execution result
40
+ */
41
+ executeSkillInternal(skill: SkillWithPrompt, context: SkillExecutionContext): Promise<SkillExecutionResult>;
42
+ /**
43
+ * Execute a script-based skill
44
+ *
45
+ * @param skill - Skill with script configuration
46
+ * @param context - Execution context
47
+ * @returns Execution result
48
+ */
49
+ private executeScript;
50
+ /**
51
+ * Execute browser automation skill
52
+ *
53
+ * This returns instructions for Claude to use with the Chrome MCP.
54
+ * The actual browser automation is performed by Claude using the
55
+ * mcp__claude-in-chrome__* tools.
56
+ *
57
+ * @param skill - Skill with browser configuration
58
+ * @param context - Execution context
59
+ * @returns Execution result with browser automation prompt
60
+ */
61
+ private executeBrowserAutomation;
62
+ /**
63
+ * Execute MCP tool skill
64
+ *
65
+ * Returns instructions for invoking the specified MCP tool.
66
+ *
67
+ * @param skill - Skill with MCP tool configuration
68
+ * @param context - Execution context
69
+ * @returns Execution result with MCP tool invocation prompt
70
+ */
71
+ private executeMcpTool;
72
+ /**
73
+ * Execute composite skill (sequence of other skills)
74
+ *
75
+ * @param skill - Skill with composite configuration
76
+ * @param context - Execution context
77
+ * @returns Combined execution result
78
+ */
79
+ private executeComposite;
80
+ /**
81
+ * Build environment variables for script execution
82
+ *
83
+ * @param skill - Skill with environment configuration
84
+ * @param context - Execution context
85
+ * @returns Environment variables object
86
+ */
87
+ private buildEnvironment;
88
+ /**
89
+ * Build environment variables and collect the list of live secret values
90
+ * that need to be redacted from the child process's output. Used by
91
+ * `executeScript` to wire up per-execution output redaction.
92
+ */
93
+ private buildEnvironmentWithSecrets;
94
+ /**
95
+ * For each credential requirement declared on the skill:
96
+ * - Resolve it to a credential UUID (agent binding → skill default)
97
+ * - Look up the credential, decrypt the payload
98
+ * - Verify scopes (OAuth)
99
+ * - Refresh tokens if near expiry
100
+ * - Inject values into env vars named `CREWLY_CRED_<SLOT>_*`
101
+ * - Register secret values for output redaction
102
+ */
103
+ private resolveAndInjectCredentials;
104
+ /**
105
+ * Slot name to env var prefix. `gmail-drive` → `CREWLY_CRED_GMAIL_DRIVE`.
106
+ */
107
+ private credentialEnvPrefix;
108
+ /**
109
+ * Parse .env file content into key-value pairs
110
+ *
111
+ * @param content - Content of .env file
112
+ * @returns Parsed environment variables
113
+ */
114
+ private parseEnvFile;
115
+ /**
116
+ * Get interpreter command and arguments for script execution
117
+ *
118
+ * @param interpreter - Script interpreter type
119
+ * @param scriptPath - Path to the script file
120
+ * @returns Command and arguments
121
+ */
122
+ private getInterpreterCommand;
123
+ /**
124
+ * Spawn a process and capture output
125
+ *
126
+ * @param command - Command to execute
127
+ * @param args - Command arguments
128
+ * @param options - Execution options
129
+ * @returns Process result with stdout, stderr, and exit code
130
+ */
131
+ private spawnProcess;
132
+ /**
133
+ * Build browser automation prompt for Claude
134
+ *
135
+ * @param config - Browser configuration
136
+ * @param context - Execution context
137
+ * @returns Formatted prompt for browser automation
138
+ */
139
+ private buildBrowserAutomationPrompt;
140
+ /**
141
+ * Build MCP tool invocation prompt
142
+ *
143
+ * @param config - MCP tool configuration
144
+ * @param context - Execution context
145
+ * @returns Formatted prompt for MCP tool invocation
146
+ */
147
+ private buildMcpToolPrompt;
148
+ }
149
+ /**
150
+ * Get the singleton SkillExecutorService instance
151
+ *
152
+ * @returns The SkillExecutorService instance
153
+ */
154
+ export declare function getSkillExecutorService(): SkillExecutorService;
155
+ /**
156
+ * Reset the singleton instance (for testing)
157
+ */
158
+ export declare function resetSkillExecutorService(): void;
159
+ //# sourceMappingURL=skill-executor.service.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"skill-executor.service.d.ts","sourceRoot":"","sources":["../../../../../../backend/src/services/skill/skill-executor.service.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAKH,OAAO,EACL,eAAe,EACf,qBAAqB,EACrB,oBAAoB,EAKrB,MAAM,4BAA4B,CAAC;AAiDpC;;;;;;;;GAQG;AACH,qBAAa,oBAAoB;IAC/B,OAAO,CAAC,QAAQ,CAAC,gBAAgB,CAAsD;IACvF,OAAO,CAAC,QAAQ,CAAC,MAAM,CAA8F;IAErH,wDAAwD;IACxD,OAAO,CAAC,eAAe,CAAyC;IAEhE,OAAO,CAAC,kBAAkB;IAO1B;;;;;;OAMG;IACG,YAAY,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,qBAAqB,GAAG,OAAO,CAAC,oBAAoB,CAAC;IAiClG;;;;;;OAMG;IACG,oBAAoB,CACxB,KAAK,EAAE,eAAe,EACtB,OAAO,EAAE,qBAAqB,GAC7B,OAAO,CAAC,oBAAoB,CAAC;IAoEhC;;;;;;OAMG;YACW,aAAa;IA0D3B;;;;;;;;;;OAUG;YACW,wBAAwB;IA8BtC;;;;;;;;OAQG;YACW,cAAc;IA8B5B;;;;;;OAMG;YACW,gBAAgB;IA+C9B;;;;;;OAMG;YACW,gBAAgB;IAS9B;;;;OAIG;YACW,2BAA2B;IA4DzC;;;;;;;;OAQG;YACW,2BAA2B;IA8FzC;;OAEG;IACH,OAAO,CAAC,mBAAmB;IAI3B;;;;;OAKG;IACH,OAAO,CAAC,YAAY;IA4BpB;;;;;;OAMG;IACH,OAAO,CAAC,qBAAqB;IAgB7B;;;;;;;OAOG;IACH,OAAO,CAAC,YAAY;IAmDpB;;;;;;OAMG;IACH,OAAO,CAAC,4BAA4B;IAyBpC;;;;;;OAMG;IACH,OAAO,CAAC,kBAAkB;CAiB3B;AAQD;;;;GAIG;AACH,wBAAgB,uBAAuB,IAAI,oBAAoB,CAK9D;AAED;;GAEG;AACH,wBAAgB,yBAAyB,IAAI,IAAI,CAEhD"}