crewly 1.5.22 → 1.6.1

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 (180) hide show
  1. package/config/roles/orchestrator/fragments/role-boundary.md +4 -1
  2. package/config/roles/orchestrator/prompt.md +219 -25
  3. package/config/roles/orchestrator/soul.md +47 -10
  4. package/config/skills/_common/lib.sh +28 -0
  5. package/config/skills/agent/core/cancel-followup/SKILL.md +38 -0
  6. package/config/skills/agent/core/cancel-followup/execute.sh +92 -0
  7. package/config/skills/agent/core/cancel-followup/execute.test.sh +42 -0
  8. package/config/skills/agent/core/list-my-followups/SKILL.md +36 -0
  9. package/config/skills/agent/core/list-my-followups/execute.sh +74 -0
  10. package/config/skills/agent/core/list-my-followups/execute.test.sh +41 -0
  11. package/config/skills/agent/core/schedule-followup/SKILL.md +53 -0
  12. package/config/skills/agent/core/schedule-followup/execute.sh +176 -0
  13. package/config/skills/agent/core/schedule-followup/execute.test.sh +48 -0
  14. package/config/skills/agent/core/watch-for-event/SKILL.md +60 -0
  15. package/config/skills/agent/core/watch-for-event/execute.sh +158 -0
  16. package/config/skills/agent/core/watch-for-event/execute.test.sh +43 -0
  17. package/config/skills/orchestrator/credential-manager/SKILL.md +218 -0
  18. package/config/skills/orchestrator/credential-manager/execute.sh +166 -0
  19. package/config/skills/orchestrator/credential-manager/execute.test.sh +88 -0
  20. package/dist/backend/backend/src/config/oauth.config.d.ts +33 -0
  21. package/dist/backend/backend/src/config/oauth.config.d.ts.map +1 -0
  22. package/dist/backend/backend/src/config/oauth.config.js +45 -0
  23. package/dist/backend/backend/src/config/oauth.config.js.map +1 -0
  24. package/dist/backend/backend/src/controllers/credentials/credentials.controller.d.ts +54 -0
  25. package/dist/backend/backend/src/controllers/credentials/credentials.controller.d.ts.map +1 -0
  26. package/dist/backend/backend/src/controllers/credentials/credentials.controller.js +228 -0
  27. package/dist/backend/backend/src/controllers/credentials/credentials.controller.js.map +1 -0
  28. package/dist/backend/backend/src/controllers/credentials/credentials.routes.d.ts +26 -0
  29. package/dist/backend/backend/src/controllers/credentials/credentials.routes.d.ts.map +1 -0
  30. package/dist/backend/backend/src/controllers/credentials/credentials.routes.js +41 -0
  31. package/dist/backend/backend/src/controllers/credentials/credentials.routes.js.map +1 -0
  32. package/dist/backend/backend/src/controllers/credentials/google-oauth.controller.d.ts +40 -0
  33. package/dist/backend/backend/src/controllers/credentials/google-oauth.controller.d.ts.map +1 -0
  34. package/dist/backend/backend/src/controllers/credentials/google-oauth.controller.js +162 -0
  35. package/dist/backend/backend/src/controllers/credentials/google-oauth.controller.js.map +1 -0
  36. package/dist/backend/backend/src/controllers/skill/skill.controller.d.ts.map +1 -1
  37. package/dist/backend/backend/src/controllers/skill/skill.controller.js +1 -0
  38. package/dist/backend/backend/src/controllers/skill/skill.controller.js.map +1 -1
  39. package/dist/backend/backend/src/controllers/task-pool/task-pool.controller.js +23 -14
  40. package/dist/backend/backend/src/controllers/task-pool/task-pool.controller.js.map +1 -1
  41. package/dist/backend/backend/src/index.d.ts.map +1 -1
  42. package/dist/backend/backend/src/index.js +23 -4
  43. package/dist/backend/backend/src/index.js.map +1 -1
  44. package/dist/backend/backend/src/routes/api.routes.d.ts.map +1 -1
  45. package/dist/backend/backend/src/routes/api.routes.js +3 -0
  46. package/dist/backend/backend/src/routes/api.routes.js.map +1 -1
  47. package/dist/backend/backend/src/scripts/backfill-mission-priority.d.ts +3 -1
  48. package/dist/backend/backend/src/scripts/backfill-mission-priority.d.ts.map +1 -1
  49. package/dist/backend/backend/src/scripts/backfill-mission-priority.js +16 -4
  50. package/dist/backend/backend/src/scripts/backfill-mission-priority.js.map +1 -1
  51. package/dist/backend/backend/src/services/ai/prompt-modules/role-boundary.module.d.ts.map +1 -1
  52. package/dist/backend/backend/src/services/ai/prompt-modules/role-boundary.module.js +4 -1
  53. package/dist/backend/backend/src/services/ai/prompt-modules/role-boundary.module.js.map +1 -1
  54. package/dist/backend/backend/src/services/ai/prompt-modules/skills-reference.module.d.ts.map +1 -1
  55. package/dist/backend/backend/src/services/ai/prompt-modules/skills-reference.module.js +17 -0
  56. package/dist/backend/backend/src/services/ai/prompt-modules/skills-reference.module.js.map +1 -1
  57. package/dist/backend/backend/src/services/browser/browser-proxy.service.js +1 -1
  58. package/dist/backend/backend/src/services/browser/browser-proxy.service.js.map +1 -1
  59. package/dist/backend/backend/src/services/credential/credential-store.service.d.ts +161 -0
  60. package/dist/backend/backend/src/services/credential/credential-store.service.d.ts.map +1 -0
  61. package/dist/backend/backend/src/services/credential/credential-store.service.js +298 -0
  62. package/dist/backend/backend/src/services/credential/credential-store.service.js.map +1 -0
  63. package/dist/backend/backend/src/services/credential/helpers/gemini-cli-workspace.helper.d.ts +105 -0
  64. package/dist/backend/backend/src/services/credential/helpers/gemini-cli-workspace.helper.d.ts.map +1 -0
  65. package/dist/backend/backend/src/services/credential/helpers/gemini-cli-workspace.helper.js +272 -0
  66. package/dist/backend/backend/src/services/credential/helpers/gemini-cli-workspace.helper.js.map +1 -0
  67. package/dist/backend/backend/src/services/mcp-server.d.ts +46 -2
  68. package/dist/backend/backend/src/services/mcp-server.d.ts.map +1 -1
  69. package/dist/backend/backend/src/services/mcp-server.js +216 -211
  70. package/dist/backend/backend/src/services/mcp-server.js.map +1 -1
  71. package/dist/backend/backend/src/services/mcp-tool-definitions.d.ts +254 -0
  72. package/dist/backend/backend/src/services/mcp-tool-definitions.d.ts.map +1 -0
  73. package/dist/backend/backend/src/services/mcp-tool-definitions.js +285 -0
  74. package/dist/backend/backend/src/services/mcp-tool-definitions.js.map +1 -0
  75. package/dist/backend/backend/src/services/project/task.service.d.ts +18 -2
  76. package/dist/backend/backend/src/services/project/task.service.d.ts.map +1 -1
  77. package/dist/backend/backend/src/services/project/task.service.js +74 -53
  78. package/dist/backend/backend/src/services/project/task.service.js.map +1 -1
  79. package/dist/backend/backend/src/services/skill/skill-executor.service.d.ts +41 -0
  80. package/dist/backend/backend/src/services/skill/skill-executor.service.d.ts.map +1 -1
  81. package/dist/backend/backend/src/services/skill/skill-executor.service.js +136 -7
  82. package/dist/backend/backend/src/services/skill/skill-executor.service.js.map +1 -1
  83. package/dist/backend/backend/src/services/skill/skill.service.d.ts.map +1 -1
  84. package/dist/backend/backend/src/services/skill/skill.service.js +1 -0
  85. package/dist/backend/backend/src/services/skill/skill.service.js.map +1 -1
  86. package/dist/backend/backend/src/services/v3/contract-matcher.d.ts +20 -0
  87. package/dist/backend/backend/src/services/v3/contract-matcher.d.ts.map +1 -0
  88. package/dist/backend/backend/src/services/v3/contract-matcher.js +33 -0
  89. package/dist/backend/backend/src/services/v3/contract-matcher.js.map +1 -0
  90. package/dist/backend/backend/src/services/v3/escalation.service.d.ts +20 -1
  91. package/dist/backend/backend/src/services/v3/escalation.service.d.ts.map +1 -1
  92. package/dist/backend/backend/src/services/v3/escalation.service.js +97 -28
  93. package/dist/backend/backend/src/services/v3/escalation.service.js.map +1 -1
  94. package/dist/backend/backend/src/services/v3/service-contract-gate.service.d.ts +6 -4
  95. package/dist/backend/backend/src/services/v3/service-contract-gate.service.d.ts.map +1 -1
  96. package/dist/backend/backend/src/services/v3/service-contract-gate.service.js +18 -28
  97. package/dist/backend/backend/src/services/v3/service-contract-gate.service.js.map +1 -1
  98. package/dist/backend/backend/src/services/v3/team-trigger-reconciler.service.d.ts.map +1 -1
  99. package/dist/backend/backend/src/services/v3/team-trigger-reconciler.service.js +14 -9
  100. package/dist/backend/backend/src/services/v3/team-trigger-reconciler.service.js.map +1 -1
  101. package/dist/backend/backend/src/services/v3/trigger-engine.service.d.ts +34 -1
  102. package/dist/backend/backend/src/services/v3/trigger-engine.service.d.ts.map +1 -1
  103. package/dist/backend/backend/src/services/v3/trigger-engine.service.js +115 -5
  104. package/dist/backend/backend/src/services/v3/trigger-engine.service.js.map +1 -1
  105. package/dist/backend/backend/src/types/credential.types.d.ts +185 -0
  106. package/dist/backend/backend/src/types/credential.types.d.ts.map +1 -0
  107. package/dist/backend/backend/src/types/credential.types.js +76 -0
  108. package/dist/backend/backend/src/types/credential.types.js.map +1 -0
  109. package/dist/backend/backend/src/types/skill.types.d.ts +9 -0
  110. package/dist/backend/backend/src/types/skill.types.d.ts.map +1 -1
  111. package/dist/backend/backend/src/types/skill.types.js.map +1 -1
  112. package/dist/backend/backend/src/utils/encryption.utils.d.ts +57 -0
  113. package/dist/backend/backend/src/utils/encryption.utils.d.ts.map +1 -0
  114. package/dist/backend/backend/src/utils/encryption.utils.js +162 -0
  115. package/dist/backend/backend/src/utils/encryption.utils.js.map +1 -0
  116. package/dist/backend/backend/src/utils/google-userinfo.utils.d.ts +41 -0
  117. package/dist/backend/backend/src/utils/google-userinfo.utils.d.ts.map +1 -0
  118. package/dist/backend/backend/src/utils/google-userinfo.utils.js +44 -0
  119. package/dist/backend/backend/src/utils/google-userinfo.utils.js.map +1 -0
  120. package/dist/cli/backend/src/config/oauth.config.d.ts +33 -0
  121. package/dist/cli/backend/src/config/oauth.config.d.ts.map +1 -0
  122. package/dist/cli/backend/src/config/oauth.config.js +45 -0
  123. package/dist/cli/backend/src/config/oauth.config.js.map +1 -0
  124. package/dist/cli/backend/src/services/credential/credential-store.service.d.ts +161 -0
  125. package/dist/cli/backend/src/services/credential/credential-store.service.d.ts.map +1 -0
  126. package/dist/cli/backend/src/services/credential/credential-store.service.js +298 -0
  127. package/dist/cli/backend/src/services/credential/credential-store.service.js.map +1 -0
  128. package/dist/cli/backend/src/services/credential/helpers/gemini-cli-workspace.helper.d.ts +105 -0
  129. package/dist/cli/backend/src/services/credential/helpers/gemini-cli-workspace.helper.d.ts.map +1 -0
  130. package/dist/cli/backend/src/services/credential/helpers/gemini-cli-workspace.helper.js +272 -0
  131. package/dist/cli/backend/src/services/credential/helpers/gemini-cli-workspace.helper.js.map +1 -0
  132. package/dist/cli/backend/src/services/mcp-server.d.ts +46 -2
  133. package/dist/cli/backend/src/services/mcp-server.d.ts.map +1 -1
  134. package/dist/cli/backend/src/services/mcp-server.js +216 -211
  135. package/dist/cli/backend/src/services/mcp-server.js.map +1 -1
  136. package/dist/cli/backend/src/services/mcp-tool-definitions.d.ts +254 -0
  137. package/dist/cli/backend/src/services/mcp-tool-definitions.d.ts.map +1 -0
  138. package/dist/cli/backend/src/services/mcp-tool-definitions.js +285 -0
  139. package/dist/cli/backend/src/services/mcp-tool-definitions.js.map +1 -0
  140. package/dist/cli/backend/src/services/settings/settings.service.d.ts +168 -0
  141. package/dist/cli/backend/src/services/settings/settings.service.d.ts.map +1 -0
  142. package/dist/cli/backend/src/services/settings/settings.service.js +312 -0
  143. package/dist/cli/backend/src/services/settings/settings.service.js.map +1 -0
  144. package/dist/cli/backend/src/services/skill/skill-executor.service.d.ts +177 -0
  145. package/dist/cli/backend/src/services/skill/skill-executor.service.d.ts.map +1 -0
  146. package/dist/cli/backend/src/services/skill/skill-executor.service.js +624 -0
  147. package/dist/cli/backend/src/services/skill/skill-executor.service.js.map +1 -0
  148. package/dist/cli/backend/src/services/skill/skill.service.d.ts +273 -0
  149. package/dist/cli/backend/src/services/skill/skill.service.d.ts.map +1 -0
  150. package/dist/cli/backend/src/services/skill/skill.service.js +655 -0
  151. package/dist/cli/backend/src/services/skill/skill.service.js.map +1 -0
  152. package/dist/cli/backend/src/types/credential.types.d.ts +185 -0
  153. package/dist/cli/backend/src/types/credential.types.d.ts.map +1 -0
  154. package/dist/cli/backend/src/types/credential.types.js +76 -0
  155. package/dist/cli/backend/src/types/credential.types.js.map +1 -0
  156. package/dist/cli/backend/src/types/skill.types.d.ts +9 -0
  157. package/dist/cli/backend/src/types/skill.types.d.ts.map +1 -1
  158. package/dist/cli/backend/src/types/skill.types.js.map +1 -1
  159. package/dist/cli/backend/src/utils/encryption.utils.d.ts +57 -0
  160. package/dist/cli/backend/src/utils/encryption.utils.d.ts.map +1 -0
  161. package/dist/cli/backend/src/utils/encryption.utils.js +162 -0
  162. package/dist/cli/backend/src/utils/encryption.utils.js.map +1 -0
  163. package/dist/cli/backend/src/utils/google-userinfo.utils.d.ts +41 -0
  164. package/dist/cli/backend/src/utils/google-userinfo.utils.d.ts.map +1 -0
  165. package/dist/cli/backend/src/utils/google-userinfo.utils.js +44 -0
  166. package/dist/cli/backend/src/utils/google-userinfo.utils.js.map +1 -0
  167. package/dist/cli/backend/src/utils/skill-md-parser.d.ts +38 -0
  168. package/dist/cli/backend/src/utils/skill-md-parser.d.ts.map +1 -0
  169. package/dist/cli/backend/src/utils/skill-md-parser.js +47 -0
  170. package/dist/cli/backend/src/utils/skill-md-parser.js.map +1 -0
  171. package/frontend/dist/assets/{index-dc92ab64.css → index-6aaa0630.css} +1 -1
  172. package/frontend/dist/assets/{index-76d76633.js → index-70356616.js} +334 -328
  173. package/frontend/dist/index.html +2 -2
  174. package/package.json +1 -1
  175. package/config/experts/empathetic-resolver/expert.json +0 -11
  176. package/config/experts/empathetic-resolver.md +0 -32
  177. package/config/experts/pragmatic-architect/expert.json +0 -11
  178. package/config/experts/pragmatic-architect.md +0 -32
  179. package/config/experts/viral-alchemist/expert.json +0 -11
  180. package/config/experts/viral-alchemist.md +0 -32
@@ -0,0 +1,168 @@
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 { CrewlySettings, UpdateSettingsInput, SettingsValidationResult, ApiKeyProvider, ApiKeyResolutionContext } from '../../types/settings.types.js';
10
+ /**
11
+ * Error thrown when settings validation fails
12
+ */
13
+ export declare class SettingsValidationError extends Error {
14
+ readonly errors: string[];
15
+ constructor(errors: string[]);
16
+ }
17
+ /**
18
+ * Error thrown when settings file cannot be read or parsed
19
+ */
20
+ export declare class SettingsFileError extends Error {
21
+ readonly cause?: Error | undefined;
22
+ constructor(message: string, cause?: Error | undefined);
23
+ }
24
+ /**
25
+ * Service for managing Crewly application settings
26
+ *
27
+ * Settings are stored in ~/.crewly/settings.json by default.
28
+ * Default values are used when no settings file exists.
29
+ *
30
+ * @example
31
+ * ```typescript
32
+ * const service = getSettingsService();
33
+ *
34
+ * // Get current settings
35
+ * const settings = await service.getSettings();
36
+ *
37
+ * // Update settings
38
+ * await service.updateSettings({
39
+ * general: { verboseLogging: true },
40
+ * });
41
+ *
42
+ * // Reset to defaults
43
+ * await service.resetSettings();
44
+ * ```
45
+ */
46
+ export declare class SettingsService {
47
+ private readonly settingsDir;
48
+ private readonly settingsFile;
49
+ private settingsCache;
50
+ /**
51
+ * Create a new SettingsService instance
52
+ *
53
+ * @param options - Configuration options
54
+ * @param options.settingsDir - Directory for settings file
55
+ */
56
+ constructor(options?: {
57
+ settingsDir?: string;
58
+ });
59
+ /**
60
+ * Get current settings, loading from file if not cached
61
+ *
62
+ * If settings file doesn't exist or is invalid, returns default settings.
63
+ *
64
+ * @returns Current settings
65
+ */
66
+ getSettings(): Promise<CrewlySettings>;
67
+ /**
68
+ * Update settings with partial input
69
+ *
70
+ * Merges the input with current settings and validates before saving.
71
+ *
72
+ * @param input - Partial settings to update
73
+ * @returns Updated settings
74
+ * @throws {SettingsValidationError} If validation fails
75
+ */
76
+ updateSettings(input: UpdateSettingsInput): Promise<CrewlySettings>;
77
+ /**
78
+ * Reset all settings to defaults
79
+ *
80
+ * @returns Default settings
81
+ */
82
+ resetSettings(): Promise<CrewlySettings>;
83
+ /**
84
+ * Reset a specific settings section to defaults
85
+ *
86
+ * @param section - The section to reset ('general', 'chat', or 'skills')
87
+ * @returns Updated settings
88
+ */
89
+ resetSection(section: keyof CrewlySettings): Promise<CrewlySettings>;
90
+ /**
91
+ * Validate settings input without saving
92
+ *
93
+ * Useful for form validation before submission.
94
+ *
95
+ * @param input - Settings to validate
96
+ * @returns Validation result
97
+ */
98
+ validateSettingsInput(input: UpdateSettingsInput): Promise<SettingsValidationResult>;
99
+ /**
100
+ * Export settings to a file
101
+ *
102
+ * @param exportPath - Path to export file
103
+ */
104
+ exportSettings(exportPath: string): Promise<void>;
105
+ /**
106
+ * Import settings from a file
107
+ *
108
+ * Validates imported settings before saving.
109
+ *
110
+ * @param importPath - Path to import file
111
+ * @returns Imported settings
112
+ * @throws {SettingsValidationError} If imported settings are invalid
113
+ * @throws {SettingsFileError} If file cannot be read or parsed
114
+ */
115
+ importSettings(importPath: string): Promise<CrewlySettings>;
116
+ /**
117
+ * Resolve an API key through the override chain: skill → runtime → global → env var
118
+ *
119
+ * @param provider - The API key provider (gemini, anthropic, openai)
120
+ * @param context - Optional context with runtime and/or skill for override resolution
121
+ * @returns The resolved API key or undefined if not configured anywhere
122
+ */
123
+ getApiKey(provider: ApiKeyProvider, context?: ApiKeyResolutionContext): Promise<string | undefined>;
124
+ /**
125
+ * Clear the settings cache
126
+ *
127
+ * Forces the next getSettings call to reload from disk.
128
+ */
129
+ clearCache(): void;
130
+ /**
131
+ * Get the path to the settings file
132
+ *
133
+ * @returns Absolute path to settings.json
134
+ */
135
+ getSettingsFilePath(): string;
136
+ /**
137
+ * Check if a settings file exists
138
+ *
139
+ * @returns True if settings file exists
140
+ */
141
+ hasSettingsFile(): Promise<boolean>;
142
+ /**
143
+ * Migrate legacy settings format to current format
144
+ *
145
+ * Converts old claudeCodeCommand/claudeCodeInitScript fields
146
+ * to the new runtimeCommands map.
147
+ *
148
+ * @param loaded - Partially loaded settings from disk
149
+ */
150
+ private migrateSettings;
151
+ /**
152
+ * Save settings to disk
153
+ *
154
+ * @param settings - Settings to save
155
+ */
156
+ private saveSettings;
157
+ }
158
+ /**
159
+ * Get the singleton SettingsService instance
160
+ *
161
+ * @returns The SettingsService instance
162
+ */
163
+ export declare function getSettingsService(): SettingsService;
164
+ /**
165
+ * Reset the singleton instance (for testing)
166
+ */
167
+ export declare function resetSettingsService(): void;
168
+ //# sourceMappingURL=settings.service.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"settings.service.d.ts","sourceRoot":"","sources":["../../../../../../backend/src/services/settings/settings.service.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAIH,OAAO,EACL,cAAc,EACd,mBAAmB,EACnB,wBAAwB,EAKxB,cAAc,EACd,uBAAuB,EAExB,MAAM,+BAA+B,CAAC;AAOvC;;GAEG;AACH,qBAAa,uBAAwB,SAAQ,KAAK;IAChD,SAAgB,MAAM,EAAE,MAAM,EAAE,CAAC;gBAErB,MAAM,EAAE,MAAM,EAAE;CAK7B;AAED;;GAEG;AACH,qBAAa,iBAAkB,SAAQ,KAAK;aACG,KAAK,CAAC,EAAE,KAAK;gBAA9C,OAAO,EAAE,MAAM,EAAkB,KAAK,CAAC,EAAE,KAAK,YAAA;CAI3D;AAMD;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,qBAAa,eAAe;IAC1B,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAS;IACrC,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAS;IACtC,OAAO,CAAC,aAAa,CAA+B;IAEpD;;;;;OAKG;gBACS,OAAO,CAAC,EAAE;QAAE,WAAW,CAAC,EAAE,MAAM,CAAA;KAAE;IAM9C;;;;;;OAMG;IACG,WAAW,IAAI,OAAO,CAAC,cAAc,CAAC;IAe5C;;;;;;;;OAQG;IACG,cAAc,CAAC,KAAK,EAAE,mBAAmB,GAAG,OAAO,CAAC,cAAc,CAAC;IAczE;;;;OAIG;IACG,aAAa,IAAI,OAAO,CAAC,cAAc,CAAC;IAO9C;;;;;OAKG;IACG,YAAY,CAAC,OAAO,EAAE,MAAM,cAAc,GAAG,OAAO,CAAC,cAAc,CAAC;IAc1E;;;;;;;OAOG;IACG,qBAAqB,CAAC,KAAK,EAAE,mBAAmB,GAAG,OAAO,CAAC,wBAAwB,CAAC;IAM1F;;;;OAIG;IACG,cAAc,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAKvD;;;;;;;;;OASG;IACG,cAAc,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,CAAC;IA6BjE;;;;;;OAMG;IACG,SAAS,CAAC,QAAQ,EAAE,cAAc,EAAE,OAAO,CAAC,EAAE,uBAAuB,GAAG,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC;IAKzG;;;;OAIG;IACH,UAAU,IAAI,IAAI;IAIlB;;;;OAIG;IACH,mBAAmB,IAAI,MAAM;IAI7B;;;;OAIG;IACG,eAAe,IAAI,OAAO,CAAC,OAAO,CAAC;IAazC;;;;;;;OAOG;IACH,OAAO,CAAC,eAAe;IA6BvB;;;;OAIG;YACW,YAAY;CAI3B;AAQD;;;;GAIG;AACH,wBAAgB,kBAAkB,IAAI,eAAe,CAKpD;AAED;;GAEG;AACH,wBAAgB,oBAAoB,IAAI,IAAI,CAE3C"}
@@ -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,177 @@
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
+ * A secret value captured for a given skill execution. stdout/stderr will
13
+ * have this value replaced with `<redacted:{label}>` before being returned
14
+ * to callers (so the agent/LLM never sees raw credential values in output).
15
+ *
16
+ * @internal Exported for unit tests.
17
+ */
18
+ export interface LiveSecret {
19
+ value: string;
20
+ label: string;
21
+ }
22
+ /**
23
+ * Replace all occurrences of any live secret value in `text` with a
24
+ * `<redacted:{label}>` placeholder.
25
+ *
26
+ * @internal Exported for unit tests; not part of the public service API.
27
+ */
28
+ export declare function redactSecrets(text: string, secrets: LiveSecret[]): string;
29
+ /**
30
+ * Service for executing skills
31
+ *
32
+ * Handles:
33
+ * - Script execution with environment variable injection
34
+ * - Browser automation via Claude's Chrome MCP
35
+ * - MCP tool invocation
36
+ * - Composite skill orchestration
37
+ */
38
+ export declare class SkillExecutorService {
39
+ private readonly defaultTimeoutMs;
40
+ private readonly logger;
41
+ /** Lazy-instantiated helpers for credential refresh. */
42
+ private geminiCliHelper;
43
+ private getGeminiCliHelper;
44
+ /**
45
+ * Execute a skill by ID
46
+ *
47
+ * @param skillId - ID of the skill to execute
48
+ * @param context - Execution context with agent and task information
49
+ * @returns Execution result with success status and output
50
+ */
51
+ executeSkill(skillId: string, context: SkillExecutionContext): Promise<SkillExecutionResult>;
52
+ /**
53
+ * Execute a skill with the full skill object
54
+ *
55
+ * @param skill - Full skill object with prompt content
56
+ * @param context - Execution context
57
+ * @returns Execution result
58
+ */
59
+ executeSkillInternal(skill: SkillWithPrompt, context: SkillExecutionContext): Promise<SkillExecutionResult>;
60
+ /**
61
+ * Execute a script-based skill
62
+ *
63
+ * @param skill - Skill with script configuration
64
+ * @param context - Execution context
65
+ * @returns Execution result
66
+ */
67
+ private executeScript;
68
+ /**
69
+ * Execute browser automation skill
70
+ *
71
+ * This returns instructions for Claude to use with the Chrome MCP.
72
+ * The actual browser automation is performed by Claude using the
73
+ * mcp__claude-in-chrome__* tools.
74
+ *
75
+ * @param skill - Skill with browser configuration
76
+ * @param context - Execution context
77
+ * @returns Execution result with browser automation prompt
78
+ */
79
+ private executeBrowserAutomation;
80
+ /**
81
+ * Execute MCP tool skill
82
+ *
83
+ * Returns instructions for invoking the specified MCP tool.
84
+ *
85
+ * @param skill - Skill with MCP tool configuration
86
+ * @param context - Execution context
87
+ * @returns Execution result with MCP tool invocation prompt
88
+ */
89
+ private executeMcpTool;
90
+ /**
91
+ * Execute composite skill (sequence of other skills)
92
+ *
93
+ * @param skill - Skill with composite configuration
94
+ * @param context - Execution context
95
+ * @returns Combined execution result
96
+ */
97
+ private executeComposite;
98
+ /**
99
+ * Build environment variables for script execution
100
+ *
101
+ * @param skill - Skill with environment configuration
102
+ * @param context - Execution context
103
+ * @returns Environment variables object
104
+ */
105
+ private buildEnvironment;
106
+ /**
107
+ * Build environment variables and collect the list of live secret values
108
+ * that need to be redacted from the child process's output. Used by
109
+ * `executeScript` to wire up per-execution output redaction.
110
+ */
111
+ private buildEnvironmentWithSecrets;
112
+ /**
113
+ * For each credential requirement declared on the skill:
114
+ * - Resolve it to a credential UUID (agent binding → skill default)
115
+ * - Look up the credential, decrypt the payload
116
+ * - Verify scopes (OAuth)
117
+ * - Refresh tokens if near expiry
118
+ * - Inject values into env vars named `CREWLY_CRED_<SLOT>_*`
119
+ * - Register secret values for output redaction
120
+ */
121
+ private resolveAndInjectCredentials;
122
+ /**
123
+ * Slot name to env var prefix. `gmail-drive` → `CREWLY_CRED_GMAIL_DRIVE`.
124
+ */
125
+ private credentialEnvPrefix;
126
+ /**
127
+ * Parse .env file content into key-value pairs
128
+ *
129
+ * @param content - Content of .env file
130
+ * @returns Parsed environment variables
131
+ */
132
+ private parseEnvFile;
133
+ /**
134
+ * Get interpreter command and arguments for script execution
135
+ *
136
+ * @param interpreter - Script interpreter type
137
+ * @param scriptPath - Path to the script file
138
+ * @returns Command and arguments
139
+ */
140
+ private getInterpreterCommand;
141
+ /**
142
+ * Spawn a process and capture output
143
+ *
144
+ * @param command - Command to execute
145
+ * @param args - Command arguments
146
+ * @param options - Execution options
147
+ * @returns Process result with stdout, stderr, and exit code
148
+ */
149
+ private spawnProcess;
150
+ /**
151
+ * Build browser automation prompt for Claude
152
+ *
153
+ * @param config - Browser configuration
154
+ * @param context - Execution context
155
+ * @returns Formatted prompt for browser automation
156
+ */
157
+ private buildBrowserAutomationPrompt;
158
+ /**
159
+ * Build MCP tool invocation prompt
160
+ *
161
+ * @param config - MCP tool configuration
162
+ * @param context - Execution context
163
+ * @returns Formatted prompt for MCP tool invocation
164
+ */
165
+ private buildMcpToolPrompt;
166
+ }
167
+ /**
168
+ * Get the singleton SkillExecutorService instance
169
+ *
170
+ * @returns The SkillExecutorService instance
171
+ */
172
+ export declare function getSkillExecutorService(): SkillExecutorService;
173
+ /**
174
+ * Reset the singleton instance (for testing)
175
+ */
176
+ export declare function resetSkillExecutorService(): void;
177
+ //# 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;AAuBpC;;;;;;GAMG;AACH,MAAM,WAAW,UAAU;IACzB,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;CACf;AAED;;;;;GAKG;AACH,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,UAAU,EAAE,GAAG,MAAM,CAUzE;AAED;;;;;;;;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;IA2FzC;;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"}