crewly 1.11.5 → 1.12.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 (208) hide show
  1. package/config/skills/agent/onboarding/synthesize-hierarchy/SKILL.md +65 -0
  2. package/config/skills/agent/onboarding/synthesize-hierarchy/execute.sh +61 -0
  3. package/config/skills/agent/web-search/SKILL.md +70 -0
  4. package/config/skills/agent/web-search/execute.sh +170 -0
  5. package/config/skills/agent/web-search/skill.json +23 -0
  6. package/dist/backend/backend/src/constants.d.ts +34 -1
  7. package/dist/backend/backend/src/constants.d.ts.map +1 -1
  8. package/dist/backend/backend/src/constants.js +34 -1
  9. package/dist/backend/backend/src/constants.js.map +1 -1
  10. package/dist/backend/backend/src/controllers/cloud/cloud.controller.d.ts +22 -0
  11. package/dist/backend/backend/src/controllers/cloud/cloud.controller.d.ts.map +1 -1
  12. package/dist/backend/backend/src/controllers/cloud/cloud.controller.js +58 -0
  13. package/dist/backend/backend/src/controllers/cloud/cloud.controller.js.map +1 -1
  14. package/dist/backend/backend/src/controllers/cloud/cloud.routes.d.ts.map +1 -1
  15. package/dist/backend/backend/src/controllers/cloud/cloud.routes.js +3 -1
  16. package/dist/backend/backend/src/controllers/cloud/cloud.routes.js.map +1 -1
  17. package/dist/backend/backend/src/controllers/orchestrator-onboarding/orchestrator-onboarding.controller.d.ts +27 -0
  18. package/dist/backend/backend/src/controllers/orchestrator-onboarding/orchestrator-onboarding.controller.d.ts.map +1 -1
  19. package/dist/backend/backend/src/controllers/orchestrator-onboarding/orchestrator-onboarding.controller.js +108 -0
  20. package/dist/backend/backend/src/controllers/orchestrator-onboarding/orchestrator-onboarding.controller.js.map +1 -1
  21. package/dist/backend/backend/src/controllers/orchestrator-onboarding/orchestrator-onboarding.routes.d.ts +6 -2
  22. package/dist/backend/backend/src/controllers/orchestrator-onboarding/orchestrator-onboarding.routes.d.ts.map +1 -1
  23. package/dist/backend/backend/src/controllers/orchestrator-onboarding/orchestrator-onboarding.routes.js +9 -3
  24. package/dist/backend/backend/src/controllers/orchestrator-onboarding/orchestrator-onboarding.routes.js.map +1 -1
  25. package/dist/backend/backend/src/index.d.ts.map +1 -1
  26. package/dist/backend/backend/src/index.js +36 -2
  27. package/dist/backend/backend/src/index.js.map +1 -1
  28. package/dist/backend/backend/src/services/agent/crewly-agent/crewly-agent-external-runtime.service.d.ts +18 -0
  29. package/dist/backend/backend/src/services/agent/crewly-agent/crewly-agent-external-runtime.service.d.ts.map +1 -1
  30. package/dist/backend/backend/src/services/agent/crewly-agent/crewly-agent-external-runtime.service.js +24 -2
  31. package/dist/backend/backend/src/services/agent/crewly-agent/crewly-agent-external-runtime.service.js.map +1 -1
  32. package/dist/backend/backend/src/services/backup/backup-archive.service.d.ts +90 -0
  33. package/dist/backend/backend/src/services/backup/backup-archive.service.d.ts.map +1 -0
  34. package/dist/backend/backend/src/services/backup/backup-archive.service.js +309 -0
  35. package/dist/backend/backend/src/services/backup/backup-archive.service.js.map +1 -0
  36. package/dist/backend/backend/src/services/backup/backup-cloud.client.d.ts +75 -0
  37. package/dist/backend/backend/src/services/backup/backup-cloud.client.d.ts.map +1 -0
  38. package/dist/backend/backend/src/services/backup/backup-cloud.client.js +134 -0
  39. package/dist/backend/backend/src/services/backup/backup-cloud.client.js.map +1 -0
  40. package/dist/backend/backend/src/services/backup/backup-restore.service.d.ts +78 -0
  41. package/dist/backend/backend/src/services/backup/backup-restore.service.d.ts.map +1 -0
  42. package/dist/backend/backend/src/services/backup/backup-restore.service.js +358 -0
  43. package/dist/backend/backend/src/services/backup/backup-restore.service.js.map +1 -0
  44. package/dist/backend/backend/src/services/backup/backup.types.d.ts +163 -0
  45. package/dist/backend/backend/src/services/backup/backup.types.d.ts.map +1 -0
  46. package/dist/backend/backend/src/services/backup/backup.types.js +13 -0
  47. package/dist/backend/backend/src/services/backup/backup.types.js.map +1 -0
  48. package/dist/backend/backend/src/services/cloud/cloud-sync.service.d.ts +29 -2
  49. package/dist/backend/backend/src/services/cloud/cloud-sync.service.d.ts.map +1 -1
  50. package/dist/backend/backend/src/services/cloud/cloud-sync.service.js +97 -13
  51. package/dist/backend/backend/src/services/cloud/cloud-sync.service.js.map +1 -1
  52. package/dist/backend/backend/src/services/cloud/mobile-api-relay.service.d.ts +102 -0
  53. package/dist/backend/backend/src/services/cloud/mobile-api-relay.service.d.ts.map +1 -0
  54. package/dist/backend/backend/src/services/cloud/mobile-api-relay.service.js +164 -0
  55. package/dist/backend/backend/src/services/cloud/mobile-api-relay.service.js.map +1 -0
  56. package/dist/backend/backend/src/services/fission/fission-guard.service.d.ts +21 -0
  57. package/dist/backend/backend/src/services/fission/fission-guard.service.d.ts.map +1 -1
  58. package/dist/backend/backend/src/services/fission/fission-guard.service.js +30 -0
  59. package/dist/backend/backend/src/services/fission/fission-guard.service.js.map +1 -1
  60. package/dist/backend/backend/src/services/intent-task/intent-classifier.rules.d.ts +4 -0
  61. package/dist/backend/backend/src/services/intent-task/intent-classifier.rules.d.ts.map +1 -1
  62. package/dist/backend/backend/src/services/intent-task/intent-classifier.rules.js +8 -0
  63. package/dist/backend/backend/src/services/intent-task/intent-classifier.rules.js.map +1 -1
  64. package/dist/backend/backend/src/services/orchestrator/onboarding/materialize-team.d.ts +79 -58
  65. package/dist/backend/backend/src/services/orchestrator/onboarding/materialize-team.d.ts.map +1 -1
  66. package/dist/backend/backend/src/services/orchestrator/onboarding/materialize-team.js +140 -65
  67. package/dist/backend/backend/src/services/orchestrator/onboarding/materialize-team.js.map +1 -1
  68. package/dist/backend/backend/src/services/orchestrator/onboarding/synthesize-hierarchy.d.ts +117 -0
  69. package/dist/backend/backend/src/services/orchestrator/onboarding/synthesize-hierarchy.d.ts.map +1 -0
  70. package/dist/backend/backend/src/services/orchestrator/onboarding/synthesize-hierarchy.js +189 -0
  71. package/dist/backend/backend/src/services/orchestrator/onboarding/synthesize-hierarchy.js.map +1 -0
  72. package/dist/backend/backend/src/services/orchestrator/onboarding-mode-loader.d.ts.map +1 -1
  73. package/dist/backend/backend/src/services/orchestrator/onboarding-mode-loader.js +1 -0
  74. package/dist/backend/backend/src/services/orchestrator/onboarding-mode-loader.js.map +1 -1
  75. package/dist/backend/backend/src/services/orchestrator/onboarding-mode.skill-allowlist.d.ts.map +1 -1
  76. package/dist/backend/backend/src/services/orchestrator/onboarding-mode.skill-allowlist.js +2 -0
  77. package/dist/backend/backend/src/services/orchestrator/onboarding-mode.skill-allowlist.js.map +1 -1
  78. package/dist/backend/backend/src/services/orchestrator/prompts/onboarding-mode.prompt.d.ts.map +1 -1
  79. package/dist/backend/backend/src/services/orchestrator/prompts/onboarding-mode.prompt.js +17 -1
  80. package/dist/backend/backend/src/services/orchestrator/prompts/onboarding-mode.prompt.js.map +1 -1
  81. package/dist/backend/backend/src/services/reconciler/reconcile-rules.d.ts +50 -0
  82. package/dist/backend/backend/src/services/reconciler/reconcile-rules.d.ts.map +1 -1
  83. package/dist/backend/backend/src/services/reconciler/reconcile-rules.js +71 -0
  84. package/dist/backend/backend/src/services/reconciler/reconcile-rules.js.map +1 -1
  85. package/dist/backend/backend/src/services/reconciler/reconciler.service.d.ts +18 -0
  86. package/dist/backend/backend/src/services/reconciler/reconciler.service.d.ts.map +1 -1
  87. package/dist/backend/backend/src/services/reconciler/reconciler.service.js +75 -1
  88. package/dist/backend/backend/src/services/reconciler/reconciler.service.js.map +1 -1
  89. package/dist/backend/backend/src/services/session/pty/pty-session-backend.d.ts +115 -0
  90. package/dist/backend/backend/src/services/session/pty/pty-session-backend.d.ts.map +1 -1
  91. package/dist/backend/backend/src/services/session/pty/pty-session-backend.js +189 -3
  92. package/dist/backend/backend/src/services/session/pty/pty-session-backend.js.map +1 -1
  93. package/dist/backend/backend/src/services/session/pty/pty-session.d.ts +28 -0
  94. package/dist/backend/backend/src/services/session/pty/pty-session.d.ts.map +1 -1
  95. package/dist/backend/backend/src/services/session/pty/pty-session.js +61 -1
  96. package/dist/backend/backend/src/services/session/pty/pty-session.js.map +1 -1
  97. package/dist/backend/backend/src/services/template/template.service.d.ts.map +1 -1
  98. package/dist/backend/backend/src/services/template/template.service.js +67 -2
  99. package/dist/backend/backend/src/services/template/template.service.js.map +1 -1
  100. package/dist/backend/backend/src/services/v3/cascade-request-status.d.ts +19 -1
  101. package/dist/backend/backend/src/services/v3/cascade-request-status.d.ts.map +1 -1
  102. package/dist/backend/backend/src/services/v3/cascade-request-status.js +39 -2
  103. package/dist/backend/backend/src/services/v3/cascade-request-status.js.map +1 -1
  104. package/dist/backend/backend/src/services/v3/escalation-router.service.d.ts +41 -0
  105. package/dist/backend/backend/src/services/v3/escalation-router.service.d.ts.map +1 -1
  106. package/dist/backend/backend/src/services/v3/escalation-router.service.js +169 -0
  107. package/dist/backend/backend/src/services/v3/escalation-router.service.js.map +1 -1
  108. package/dist/backend/backend/src/services/v3/request-cascade.subscriber.d.ts +4 -1
  109. package/dist/backend/backend/src/services/v3/request-cascade.subscriber.d.ts.map +1 -1
  110. package/dist/backend/backend/src/services/v3/request-cascade.subscriber.js +21 -0
  111. package/dist/backend/backend/src/services/v3/request-cascade.subscriber.js.map +1 -1
  112. package/dist/backend/backend/src/types/intent-task.types.d.ts.map +1 -1
  113. package/dist/backend/backend/src/types/intent-task.types.js +8 -0
  114. package/dist/backend/backend/src/types/intent-task.types.js.map +1 -1
  115. package/dist/backend/backend/src/types/v2/request.types.d.ts +1 -1
  116. package/dist/backend/backend/src/types/v2/request.types.d.ts.map +1 -1
  117. package/dist/backend/backend/src/types/v2/request.types.js +1 -0
  118. package/dist/backend/backend/src/types/v2/request.types.js.map +1 -1
  119. package/dist/cli/backend/src/constants.d.ts +34 -1
  120. package/dist/cli/backend/src/constants.d.ts.map +1 -1
  121. package/dist/cli/backend/src/constants.js +34 -1
  122. package/dist/cli/backend/src/constants.js.map +1 -1
  123. package/dist/cli/backend/src/controllers/cloud/cloud-google-auth.controller.d.ts +70 -0
  124. package/dist/cli/backend/src/controllers/cloud/cloud-google-auth.controller.d.ts.map +1 -0
  125. package/dist/cli/backend/src/controllers/cloud/cloud-google-auth.controller.js +427 -0
  126. package/dist/cli/backend/src/controllers/cloud/cloud-google-auth.controller.js.map +1 -0
  127. package/dist/cli/backend/src/services/backup/backup-archive.service.d.ts +90 -0
  128. package/dist/cli/backend/src/services/backup/backup-archive.service.d.ts.map +1 -0
  129. package/dist/cli/backend/src/services/backup/backup-archive.service.js +309 -0
  130. package/dist/cli/backend/src/services/backup/backup-archive.service.js.map +1 -0
  131. package/dist/cli/backend/src/services/backup/backup-cloud.client.d.ts +75 -0
  132. package/dist/cli/backend/src/services/backup/backup-cloud.client.d.ts.map +1 -0
  133. package/dist/cli/backend/src/services/backup/backup-cloud.client.js +134 -0
  134. package/dist/cli/backend/src/services/backup/backup-cloud.client.js.map +1 -0
  135. package/dist/cli/backend/src/services/backup/backup-restore.service.d.ts +78 -0
  136. package/dist/cli/backend/src/services/backup/backup-restore.service.d.ts.map +1 -0
  137. package/dist/cli/backend/src/services/backup/backup-restore.service.js +358 -0
  138. package/dist/cli/backend/src/services/backup/backup-restore.service.js.map +1 -0
  139. package/dist/cli/backend/src/services/backup/backup.types.d.ts +163 -0
  140. package/dist/cli/backend/src/services/backup/backup.types.d.ts.map +1 -0
  141. package/dist/cli/backend/src/services/backup/backup.types.js +13 -0
  142. package/dist/cli/backend/src/services/backup/backup.types.js.map +1 -0
  143. package/dist/cli/backend/src/services/cloud/cloud-client.service.d.ts +410 -0
  144. package/dist/cli/backend/src/services/cloud/cloud-client.service.d.ts.map +1 -0
  145. package/dist/cli/backend/src/services/cloud/cloud-client.service.js +863 -0
  146. package/dist/cli/backend/src/services/cloud/cloud-client.service.js.map +1 -0
  147. package/dist/cli/backend/src/services/cloud/cloud-sync.service.d.ts +292 -0
  148. package/dist/cli/backend/src/services/cloud/cloud-sync.service.d.ts.map +1 -0
  149. package/dist/cli/backend/src/services/cloud/cloud-sync.service.js +1093 -0
  150. package/dist/cli/backend/src/services/cloud/cloud-sync.service.js.map +1 -0
  151. package/dist/cli/backend/src/services/cloud/cloud-sync.types.d.ts +328 -0
  152. package/dist/cli/backend/src/services/cloud/cloud-sync.types.d.ts.map +1 -0
  153. package/dist/cli/backend/src/services/cloud/cloud-sync.types.js +171 -0
  154. package/dist/cli/backend/src/services/cloud/cloud-sync.types.js.map +1 -0
  155. package/dist/cli/backend/src/services/cloud/device-identity.service.d.ts +89 -0
  156. package/dist/cli/backend/src/services/cloud/device-identity.service.d.ts.map +1 -0
  157. package/dist/cli/backend/src/services/cloud/device-identity.service.js +148 -0
  158. package/dist/cli/backend/src/services/cloud/device-identity.service.js.map +1 -0
  159. package/dist/cli/backend/src/services/user/user-identity.service.d.ts +86 -0
  160. package/dist/cli/backend/src/services/user/user-identity.service.d.ts.map +1 -0
  161. package/dist/cli/backend/src/services/user/user-identity.service.js +190 -0
  162. package/dist/cli/backend/src/services/user/user-identity.service.js.map +1 -0
  163. package/dist/cli/cli/src/commands/backup.d.ts +31 -0
  164. package/dist/cli/cli/src/commands/backup.d.ts.map +1 -0
  165. package/dist/cli/cli/src/commands/backup.js +280 -0
  166. package/dist/cli/cli/src/commands/backup.js.map +1 -0
  167. package/dist/cli/cli/src/index.js +10 -0
  168. package/dist/cli/cli/src/index.js.map +1 -1
  169. package/package.json +9 -3
  170. package/packages/crewly-agent/README.md +27 -0
  171. package/packages/crewly-agent/bin/crewly-agent +33 -0
  172. package/packages/crewly-agent/package.json +39 -0
  173. package/packages/crewly-agent/src/cli.ts +168 -0
  174. package/packages/crewly-agent/src/runtime/agent-runner.service.test.ts +2355 -0
  175. package/packages/crewly-agent/src/runtime/agent-runner.service.ts +1827 -0
  176. package/packages/crewly-agent/src/runtime/agent-stream.service.test.ts +153 -0
  177. package/packages/crewly-agent/src/runtime/agent-stream.service.ts +225 -0
  178. package/packages/crewly-agent/src/runtime/agent-worker.test.ts +171 -0
  179. package/packages/crewly-agent/src/runtime/agent-worker.ts +193 -0
  180. package/packages/crewly-agent/src/runtime/api-client.ts +143 -0
  181. package/packages/crewly-agent/src/runtime/approval-queue.service.ts +307 -0
  182. package/packages/crewly-agent/src/runtime/audit-log.service.test.ts +208 -0
  183. package/packages/crewly-agent/src/runtime/audit-log.service.ts +332 -0
  184. package/packages/crewly-agent/src/runtime/audit-trail.service.test.ts +178 -0
  185. package/packages/crewly-agent/src/runtime/audit-trail.service.ts +151 -0
  186. package/packages/crewly-agent/src/runtime/auditor-tools.test.ts +274 -0
  187. package/packages/crewly-agent/src/runtime/auditor-tools.ts +311 -0
  188. package/packages/crewly-agent/src/runtime/cloud-config.ts +67 -0
  189. package/packages/crewly-agent/src/runtime/deepseek-sse-transform.test.ts +165 -0
  190. package/packages/crewly-agent/src/runtime/deepseek-sse-transform.ts +168 -0
  191. package/packages/crewly-agent/src/runtime/env-isolation.service.ts +246 -0
  192. package/packages/crewly-agent/src/runtime/in-process-log-buffer.test.ts +280 -0
  193. package/packages/crewly-agent/src/runtime/in-process-log-buffer.ts +317 -0
  194. package/packages/crewly-agent/src/runtime/index.ts +38 -0
  195. package/packages/crewly-agent/src/runtime/mcp-tool-bridge.test.ts +352 -0
  196. package/packages/crewly-agent/src/runtime/mcp-tool-bridge.ts +244 -0
  197. package/packages/crewly-agent/src/runtime/model-manager.test.ts +326 -0
  198. package/packages/crewly-agent/src/runtime/model-manager.ts +363 -0
  199. package/packages/crewly-agent/src/runtime/output-filter.service.ts +175 -0
  200. package/packages/crewly-agent/src/runtime/prompt-guard.service.ts +303 -0
  201. package/packages/crewly-agent/src/runtime/rate-limiter.test.ts +228 -0
  202. package/packages/crewly-agent/src/runtime/rate-limiter.ts +353 -0
  203. package/packages/crewly-agent/src/runtime/tool-registry.test.ts +2510 -0
  204. package/packages/crewly-agent/src/runtime/tool-registry.ts +2104 -0
  205. package/packages/crewly-agent/src/runtime/types.test.ts +519 -0
  206. package/packages/crewly-agent/src/runtime/types.ts +637 -0
  207. package/packages/crewly-agent/src/runtime/web-search.tool.test.ts +131 -0
  208. package/packages/crewly-agent/src/runtime/web-search.tool.ts +140 -0
@@ -0,0 +1,637 @@
1
+ /**
2
+ * Crewly Agent Runtime Type Definitions
3
+ *
4
+ * Types for the in-process Crewly Agent runtime powered by Vercel AI SDK.
5
+ * Covers model configuration, conversation state, and agent lifecycle.
6
+ *
7
+ * @module services/agent/crewly-agent/types
8
+ */
9
+
10
+ import type { ModelMessage } from 'ai';
11
+ import type { z } from 'zod';
12
+
13
+ /**
14
+ * Minimal MCP server configuration used by the standalone runtime.
15
+ * Mirrors OSS `McpServerConfig` from `services/mcp-client.ts` — kept
16
+ * field-compatible so the bridge can pass JSON payloads unchanged.
17
+ */
18
+ export interface McpServerConfig {
19
+ command?: string;
20
+ args?: string[];
21
+ env?: Record<string, string>;
22
+ cwd?: string;
23
+ url?: string;
24
+ timeoutMs?: number;
25
+ headers?: Record<string, string>;
26
+ }
27
+
28
+ /** MCP tool metadata used by the standalone tool bridge. */
29
+ export interface McpToolInfo {
30
+ serverName: string;
31
+ name: string;
32
+ description?: string;
33
+ inputSchema: Record<string, unknown>;
34
+ }
35
+
36
+ /** MCP call result shape. */
37
+ export interface McpCallResult {
38
+ isError: boolean;
39
+ content: Array<Record<string, unknown>>;
40
+ }
41
+
42
+ /**
43
+ * Interface a caller can use to inject an MCP client implementation.
44
+ * Standalone has no concrete implementation by default; OSS bridges via
45
+ * the JSON protocol if MCP is needed in cloud-resident agents.
46
+ */
47
+ export interface McpClientLike {
48
+ connectAll(serverConfigs: Record<string, McpServerConfig>): Promise<Map<string, Error>>;
49
+ listTools(): McpToolInfo[];
50
+ callTool(serverName: string, toolName: string, args: Record<string, unknown>): Promise<McpCallResult>;
51
+ disconnectAll(): Promise<void>;
52
+ getConnectedServers(): string[];
53
+ }
54
+
55
+ /**
56
+ * Sensitivity overrides for MCP tools, keyed by 'serverName:toolName' or
57
+ * just 'toolName'. Mirrors the OSS `McpSensitivityOverrides` type formerly
58
+ * imported from `./mcp-tool-bridge.js`.
59
+ */
60
+ export type McpSensitivityOverrides = Record<string, 'safe' | 'sensitive' | 'destructive'>;
61
+
62
+ /**
63
+ * Supported model providers for Crewly Agent.
64
+ *
65
+ * Note: 'deepseek' is served through the OpenAI-compatible API at
66
+ * https://api.deepseek.com/v1, but is exposed as a distinct provider
67
+ * so users can select it explicitly. Its API key (DEEPSEEK_API_KEY) is
68
+ * read from the environment, not from the settings service — see
69
+ * model-manager.ts for details.
70
+ */
71
+ export type ModelProvider = 'anthropic' | 'openai' | 'google' | 'ollama' | 'deepseek';
72
+
73
+ /**
74
+ * All valid model providers
75
+ */
76
+ export const MODEL_PROVIDERS: readonly ModelProvider[] = [
77
+ 'anthropic',
78
+ 'openai',
79
+ 'google',
80
+ 'ollama',
81
+ 'deepseek',
82
+ ] as const;
83
+
84
+ /**
85
+ * Configuration for a specific model instance
86
+ */
87
+ export interface ModelConfig {
88
+ /** Model provider (e.g., 'anthropic', 'openai', 'google', 'ollama') */
89
+ provider: ModelProvider;
90
+ /** Model identifier (e.g., 'claude-sonnet-4-20250514', 'gpt-4o', 'gemini-2.0-flash') */
91
+ modelId: string;
92
+ /** Optional temperature override (0-1) */
93
+ temperature?: number;
94
+ /** Optional max tokens per response */
95
+ maxTokens?: number;
96
+ }
97
+
98
+ /**
99
+ * Conversation state maintained by the AgentRunner
100
+ */
101
+ export interface ConversationState {
102
+ /** AI SDK ModelMessage array — the full conversation history */
103
+ messages: ModelMessage[];
104
+ /** System prompt loaded from prompt.md */
105
+ systemPrompt: string;
106
+ /** Cumulative token usage across all generateText calls */
107
+ totalTokens: { input: number; output: number };
108
+ /** Conversation creation time */
109
+ createdAt: Date;
110
+ /** Last activity timestamp */
111
+ lastActivityAt: Date;
112
+ }
113
+
114
+ /**
115
+ * Configuration for the Crewly Agent runtime
116
+ */
117
+ export interface CrewlyAgentConfig {
118
+ /** Model configuration for the agent */
119
+ model: ModelConfig;
120
+ /** Maximum reasoning steps per generateText call */
121
+ maxSteps: number;
122
+ /** Session name for this agent instance */
123
+ sessionName: string;
124
+ /** Agent role (e.g. developer, product-manager) */
125
+ role?: string;
126
+ /** Base URL for the Crewly REST API */
127
+ apiBaseUrl: string;
128
+ /** System prompt content (loaded from prompt.md) */
129
+ systemPrompt: string;
130
+ /** Maximum conversation history messages before compaction triggers */
131
+ maxHistoryMessages: number;
132
+ /** Token budget threshold (percentage of context window) for compaction */
133
+ compactionThreshold: number;
134
+ /** Project path for memory and task tools (auto-injected) */
135
+ projectPath?: string;
136
+ /** Team member ID for heartbeat tracking (used as key in teamAgentStatus.json) */
137
+ memberId?: string;
138
+ /** MCP server configurations for external tool integration */
139
+ mcpServers?: Record<string, McpServerConfig>;
140
+ /** Sensitivity overrides for MCP tools (key: 'serverName:toolName' or 'toolName') */
141
+ mcpSensitivityOverrides?: McpSensitivityOverrides;
142
+ /**
143
+ * Eval mode flag. When true:
144
+ * - Strips TL delegation-first instructions from system prompt
145
+ * - Agent implements directly instead of delegating to workers
146
+ * - Enables post-execution deliverable self-check (Stop Hook)
147
+ */
148
+ evalMode?: boolean;
149
+ }
150
+
151
+ /**
152
+ * Result of a single agent run (one generateText invocation)
153
+ */
154
+ export interface AgentRunResult {
155
+ /** Final text response from the model */
156
+ text: string;
157
+ /** Number of steps taken in this run */
158
+ steps: number;
159
+ /** Token usage for this run */
160
+ usage: { input: number; output: number };
161
+ /** Tool calls made during this run */
162
+ toolCalls: ToolCallRecord[];
163
+ /** Reason the generation finished */
164
+ finishReason: string;
165
+ /** Budget warning message when token usage is approaching limits */
166
+ budgetWarning?: string;
167
+ /**
168
+ * I2: DeepSeek-R1 chain-of-thought text extracted from `delta.reasoning_content`.
169
+ *
170
+ * Present only for `deepseek-reasoner` model runs. `null` if the run did not
171
+ * produce any reasoning content (e.g. non-R1 model, or R1 returned content-only).
172
+ * `undefined` for non-DeepSeek providers (no extraction is performed).
173
+ *
174
+ * Concatenated across all agentic steps in this single AgentRunResult — i.e.
175
+ * if the model made N HTTP calls during this run, the reasoning from all N
176
+ * is joined in call order.
177
+ *
178
+ * **SECURITY — UNTRUSTED CONTENT.** This string is downstream of user input
179
+ * (R1 reasoning is generated in response to the user's prompt). When re-injected
180
+ * into ANY subsequent model call, it MUST be wrapped as untrusted-context — e.g.
181
+ * `<reasoning-from-deepseek-r1 trust="untrusted">...</reasoning-from-deepseek-r1>`
182
+ * with explicit framing as "hint material from another model, not authoritative
183
+ * instructions." Direct splicing into a system prompt = jailbreak primitive.
184
+ * See P0-1 design-review gate for I2.5 reasoning-pipe routing.
185
+ */
186
+ reasoning?: string | null;
187
+ }
188
+
189
+ /**
190
+ * Record of a single tool call during agent execution
191
+ */
192
+ export interface ToolCallRecord {
193
+ /** Tool name */
194
+ toolName: string;
195
+ /** Arguments passed to the tool */
196
+ args: Record<string, unknown>;
197
+ /** Result returned by the tool */
198
+ result: unknown;
199
+ }
200
+
201
+ /**
202
+ * Result of an API call to the Crewly backend
203
+ */
204
+ export interface ApiCallResult<T = unknown> {
205
+ /** Whether the call succeeded (HTTP 2xx) */
206
+ success: boolean;
207
+ /** Response data on success */
208
+ data?: T;
209
+ /** Error message on failure */
210
+ error?: string;
211
+ /** HTTP status code */
212
+ status: number;
213
+ }
214
+
215
+ /**
216
+ * Sensitivity classification for tool security auditing.
217
+ *
218
+ * - 'safe': Read-only or informational tools (no side effects)
219
+ * - 'sensitive': Tools that modify state or communicate externally
220
+ * - 'destructive': Tools that can cause irreversible damage
221
+ */
222
+ export type ToolSensitivity = 'safe' | 'sensitive' | 'destructive';
223
+
224
+ /**
225
+ * Tool definition shape matching AI SDK Tool interface.
226
+ * Shared by both the main tool registry and the auditor tool registry.
227
+ */
228
+ export interface ToolDefinition {
229
+ /** Human-readable description of what the tool does */
230
+ description: string;
231
+ /** Zod schema for validating tool input */
232
+ inputSchema: z.ZodType;
233
+ /** Execute the tool with the given validated arguments */
234
+ execute: (args: Record<string, unknown>) => Promise<unknown>;
235
+ /** Security sensitivity classification for audit purposes */
236
+ sensitivity?: ToolSensitivity;
237
+ }
238
+
239
+ /**
240
+ * Callbacks for streaming events during agent execution.
241
+ * Emitted in real-time as the model generates text and calls tools.
242
+ */
243
+ export interface StreamingEventCallbacks {
244
+ /** Called when a text chunk arrives from the model */
245
+ onTextChunk?: (chunk: string) => void;
246
+ /** Called when a tool call starts executing */
247
+ onToolCallStart?: (toolName: string, args: Record<string, unknown>) => void;
248
+ /** Called when a tool call completes */
249
+ onToolCallFinish?: (toolName: string, args: Record<string, unknown>, result: unknown, durationMs: number) => void;
250
+ /** Called when a reasoning step completes */
251
+ onStepFinish?: (stepIndex: number, hasToolCalls: boolean) => void;
252
+ }
253
+
254
+ /**
255
+ * A single entry in the security audit trail.
256
+ * Records every tool invocation with timing, classification, and result status.
257
+ */
258
+ export interface AuditEntry {
259
+ /** ISO timestamp of the tool invocation */
260
+ timestamp: string;
261
+ /** Agent session name that invoked the tool */
262
+ sessionName?: string;
263
+ /** Name of the tool that was called */
264
+ toolName: string;
265
+ /** Sensitivity classification of the tool */
266
+ sensitivity: ToolSensitivity;
267
+ /** Arguments passed to the tool (sanitized — no secrets) */
268
+ args: Record<string, unknown>;
269
+ /** Whether the tool call succeeded */
270
+ success: boolean;
271
+ /** Error message if the call failed */
272
+ error?: string;
273
+ /** Execution duration in milliseconds */
274
+ durationMs: number;
275
+ }
276
+
277
+ /**
278
+ * Security policy configuration for the agent runtime.
279
+ * Controls which tool sensitivity levels require approval or are blocked.
280
+ */
281
+ export interface SecurityPolicy {
282
+ /** Whether audit logging is enabled */
283
+ auditEnabled: boolean;
284
+ /** Tool sensitivity levels that require explicit approval */
285
+ requireApproval: ToolSensitivity[];
286
+ /** Tool names that are completely blocked */
287
+ blockedTools: string[];
288
+ /** Maximum audit log entries to retain in memory */
289
+ maxAuditEntries: number;
290
+ /**
291
+ * Read-only audit mode. When enabled, all tools classified as
292
+ * 'sensitive' or 'destructive' are blocked — only 'safe' (read-only)
293
+ * tools can execute. Tool invocations are still logged to the audit trail.
294
+ */
295
+ readOnlyMode: boolean;
296
+ }
297
+
298
+ /**
299
+ * Tools that perform write/modify operations.
300
+ * Used by readOnlyMode to determine which tools to block.
301
+ */
302
+ export const WRITE_TOOLS: readonly string[] = [
303
+ 'edit_file',
304
+ 'write_file',
305
+ 'start_agent',
306
+ 'stop_agent',
307
+ 'handle_agent_failure',
308
+ 'delegate_task',
309
+ 'send_message',
310
+ 'reply_slack',
311
+ 'broadcast',
312
+ 'schedule_check',
313
+ 'cancel_schedule',
314
+ 'register_self',
315
+ 'report_status',
316
+ 'remember',
317
+ 'complete_task',
318
+ ] as const;
319
+
320
+ /**
321
+ * Context budget status for the current conversation.
322
+ * Tracks token usage against the model's context window limit.
323
+ */
324
+ export interface ContextBudgetStatus {
325
+ /** Total tokens used so far (input + output) */
326
+ totalTokensUsed: number;
327
+ /** Estimated context window size for the current model */
328
+ contextWindowSize: number;
329
+ /** Usage as a fraction (0.0 - 1.0) */
330
+ usagePercent: number;
331
+ /** Current threshold level based on compactionThreshold */
332
+ level: 'normal' | 'warning' | 'critical';
333
+ /** Number of messages in conversation history */
334
+ messageCount: number;
335
+ /** Whether auto-compaction will trigger on next message */
336
+ compactionPending: boolean;
337
+ /** Human-readable summary */
338
+ summary: string;
339
+ }
340
+
341
+ /**
342
+ * Estimated context window sizes (in tokens) for known models.
343
+ * Used for budget tracking when the model doesn't report its own limit.
344
+ */
345
+ export const MODEL_CONTEXT_WINDOWS: Record<string, number> = {
346
+ // Anthropic
347
+ 'claude-opus-4-20250514': 200_000,
348
+ 'claude-sonnet-4-20250514': 200_000,
349
+ 'claude-haiku-4-20250506': 200_000,
350
+ // Google
351
+ 'gemini-2.0-flash': 1_000_000,
352
+ 'gemini-2.5-flash-preview-05-20': 1_000_000,
353
+ 'gemini-3-flash-preview': 1_000_000,
354
+ // OpenAI
355
+ 'gpt-4o': 128_000,
356
+ 'gpt-4o-mini': 128_000,
357
+ 'gpt-4-turbo': 128_000,
358
+ // DeepSeek — V3 chat and R1 reasoner both ship with a 64k context window.
359
+ // Without these entries the manager falls back to `default: 128_000`, which
360
+ // would let Crewly's compaction trigger (0.8 × budget) skip past the real
361
+ // 64k cap and let DeepSeek 4xx with context_length_exceeded.
362
+ 'deepseek-chat': 64_000,
363
+ 'deepseek-reasoner': 64_000,
364
+ // Fallback
365
+ default: 128_000,
366
+ } as const;
367
+
368
+ /**
369
+ * Per-model floor on `maxOutputTokens` (the AI SDK's name for the
370
+ * `max_tokens` request param). Used to defend against a class of bugs where
371
+ * a low user-configured limit silently produces an empty response.
372
+ *
373
+ * Currently only `deepseek-reasoner` has a real floor: R1 mixes
374
+ * `reasoning_tokens` into the same `max_tokens` budget as `completion_tokens`,
375
+ * so a user value < ~200 can be entirely consumed by the reasoning trace,
376
+ * leaving `message.content = ""` (200 OK, no error).
377
+ *
378
+ * Models not listed here resolve to a floor of 0 (no clamp).
379
+ *
380
+ * Discovered 2026-05-03 via live smoke test D — see
381
+ * `.crewly/specs/2026-05-03-crewly-agent-deepseek-gap-list.md` (finding N5).
382
+ */
383
+ export const MODEL_OUTPUT_TOKEN_FLOORS: Record<string, number> = {
384
+ 'deepseek-reasoner': 1024,
385
+ } as const;
386
+
387
+ /**
388
+ * Resolve the effective `maxOutputTokens` for a given model configuration,
389
+ * applying any per-model floor from `MODEL_OUTPUT_TOKEN_FLOORS`.
390
+ *
391
+ * If `config.maxTokens` is unset, falls back to the runtime default
392
+ * (`CREWLY_AGENT_DEFAULTS.DEFAULT_MODEL.maxTokens`). The result is always
393
+ * `>= floor` for the model, where `floor` defaults to 0.
394
+ *
395
+ * @param config - Model configuration (may have `maxTokens` undefined)
396
+ * @returns Effective max output tokens to pass to generateText/streamText
397
+ */
398
+ export function resolveMaxOutputTokens(config: ModelConfig): number {
399
+ const requested = config.maxTokens ?? CREWLY_AGENT_DEFAULTS.DEFAULT_MODEL.maxTokens ?? 0;
400
+ const floor = MODEL_OUTPUT_TOKEN_FLOORS[config.modelId] ?? 0;
401
+ return Math.max(requested, floor);
402
+ }
403
+
404
+ /**
405
+ * Result of an autonomous context compaction operation.
406
+ * Returned by the compact_memory tool and requestCompaction().
407
+ */
408
+ export interface CompactionResult {
409
+ /** Whether compaction was performed */
410
+ compacted: boolean;
411
+ /** Number of messages before compaction */
412
+ messagesBefore: number;
413
+ /** Number of messages after compaction */
414
+ messagesAfter: number;
415
+ /** Reason if compaction was skipped */
416
+ reason?: string;
417
+ }
418
+
419
+ /**
420
+ * Result of a tool approval check.
421
+ * Returned by the onCheckApproval callback to determine if a tool can execute.
422
+ */
423
+ export interface ApprovalCheckResult {
424
+ /** Whether the tool is allowed to execute */
425
+ allowed: boolean;
426
+ /** Reason if the tool is blocked or requires approval */
427
+ reason?: string;
428
+ /** Whether the tool was blocked (vs requiring approval) */
429
+ blocked?: boolean;
430
+ }
431
+
432
+ /**
433
+ * Callbacks from tool registry to the agent runner.
434
+ * Allows tools to trigger runner-level operations like compaction and security checks.
435
+ */
436
+ export interface ToolCallbacks {
437
+ /** Trigger intelligent context compaction */
438
+ onCompactMemory?: () => Promise<CompactionResult>;
439
+ /** Get current context budget status */
440
+ onGetContextBudget?: () => ContextBudgetStatus;
441
+ /** Record an audit entry for a tool call */
442
+ onAuditLog?: (entry: AuditEntry) => void;
443
+ /** Check if a tool is allowed to execute given current security policy */
444
+ onCheckApproval?: (toolName: string, sensitivity: ToolSensitivity) => ApprovalCheckResult;
445
+ /** Retrieve audit log entries with optional filters */
446
+ onGetAuditLog?: (filters: AuditLogFilters) => AuditEntry[];
447
+ /** Enqueue a tool call for approval when it requires explicit approval */
448
+ onEnqueueApproval?: (toolName: string, sensitivity: ToolSensitivity, args: Record<string, unknown>) => { approvalId: string };
449
+ }
450
+
451
+ /**
452
+ * Filters for querying the audit log.
453
+ */
454
+ export interface AuditLogFilters {
455
+ /** Maximum entries to return (most recent first) */
456
+ limit: number;
457
+ /** Filter by sensitivity level */
458
+ sensitivity?: ToolSensitivity;
459
+ /** Filter by specific tool name */
460
+ toolName?: string;
461
+ }
462
+
463
+ /**
464
+ * Configuration for API key security guardrails.
465
+ * Controls output filtering, environment isolation, and prompt protection.
466
+ */
467
+ export interface SecurityGuardrailConfig {
468
+ /** Enable output filtering (redact API keys from agent responses) */
469
+ outputFilterEnabled: boolean;
470
+ /** Enable environment isolation (strip secrets from bash child processes) */
471
+ envIsolationEnabled: boolean;
472
+ /** Enable prompt guard (block key extraction commands and prompt injections) */
473
+ promptGuardEnabled: boolean;
474
+ /** Additional env vars to explicitly allow in child processes */
475
+ explicitEnvVars: string[];
476
+ }
477
+
478
+ /**
479
+ * Default configuration values for Crewly Agent
480
+ */
481
+ export const CREWLY_AGENT_DEFAULTS = {
482
+ /** Default max reasoning steps per generateText call (high to mimic unlimited like Claude Code) */
483
+ MAX_STEPS: 500,
484
+ /** Maximum tool calls allowed per single response to prevent polling dead-loops */
485
+ MAX_TOOL_CALLS_PER_RESPONSE: 15,
486
+ /** Consecutive identical tool calls before aborting (loop detection) */
487
+ LOOP_DETECTION_THRESHOLD: 3,
488
+ /** Consecutive error responses (404, 4xx, 5xx) from the same tool before aborting */
489
+ ERROR_LOOP_THRESHOLD: 3,
490
+ /** Default API base URL */
491
+ API_BASE_URL: 'http://localhost:8787',
492
+ /** Default max history messages before compaction */
493
+ MAX_HISTORY_MESSAGES: 100,
494
+ /** Default compaction threshold (80% of context window) */
495
+ COMPACTION_THRESHOLD: 0.8,
496
+ /** Default model configuration */
497
+ DEFAULT_MODEL: {
498
+ provider: 'google' as ModelProvider,
499
+ modelId: 'gemini-3-flash-preview',
500
+ temperature: 0.3,
501
+ maxTokens: 8192,
502
+ } satisfies ModelConfig,
503
+ /** HTTP request timeout in milliseconds */
504
+ API_TIMEOUT_MS: 30_000,
505
+ /** Heartbeat interval in milliseconds for keeping in-process agent active between messages */
506
+ HEARTBEAT_INTERVAL_MS: 30_000,
507
+ /** Maximum time in milliseconds for a single message processing (generateText call) — hard abort.
508
+ * Override via CREWLY_AGENT_MESSAGE_TIMEOUT_MS env var.
509
+ *
510
+ * This is the **default** timeout used when the model has no entry in
511
+ * `MODEL_TIMEOUT_MS`. Per-model overrides take precedence — see below. */
512
+ MESSAGE_TIMEOUT_MS: Number(process.env.CREWLY_AGENT_MESSAGE_TIMEOUT_MS) || 300_000,
513
+ /** I4 — Per-model hard-timeout overrides. Looked up by `modelId`.
514
+ *
515
+ * When the runtime service is about to run a message, it checks
516
+ * `MODEL_TIMEOUT_MS[config.model.modelId]` first; falls back to
517
+ * `MESSAGE_TIMEOUT_MS` if no entry exists.
518
+ *
519
+ * **Why per-model:** different models have radically different latency
520
+ * characteristics. DeepSeek-R1 (`deepseek-reasoner`) emits chain-of-thought
521
+ * reasoning_tokens which are slower to generate than plain content tokens.
522
+ * Live smoke (2026-05-03) measured R1 single-step at avg 2.8s/max 4.8s, but
523
+ * long-context (>32k) latency rises sharply per vendor docs, and multi-step
524
+ * agentic loops can accumulate 30+ steps. 5min default is tight; 10min gives
525
+ * safety margin without inviting runaway loops. See gap-list spec §I4 for
526
+ * measurement evidence. */
527
+ /**
528
+ * Frozen at module load via `Object.freeze` — defensive guard against
529
+ * runtime mutation. `as const` is compile-time only and the
530
+ * `Record<string, number>` cast widens it back to mutable, so freeze
531
+ * is the only line of defense against accidental writes like
532
+ * `CREWLY_AGENT_DEFAULTS.MODEL_TIMEOUT_MS['x'] = 999` from elsewhere
533
+ * in the codebase. Per-model overrides should be added by editing this
534
+ * file (treat as a config table, not runtime state).
535
+ */
536
+ MODEL_TIMEOUT_MS: Object.freeze({
537
+ /** DeepSeek-R1: 2× default — reasoning chain-of-thought is slower per token. */
538
+ 'deepseek-reasoner': 600_000,
539
+ }) as Readonly<Record<string, number>>,
540
+ /** Soft warning threshold in milliseconds — logs a warning but does not kill the request.
541
+ * Override via CREWLY_AGENT_MESSAGE_SOFT_WARNING_MS env var. */
542
+ MESSAGE_SOFT_WARNING_MS: Number(process.env.CREWLY_AGENT_MESSAGE_SOFT_WARNING_MS) || 240_000,
543
+ /** Cooldown period in milliseconds after rate limit retries are exhausted */
544
+ RATE_LIMIT_COOLDOWN_MS: 300_000,
545
+ /** Maximum number of automatic retries for recoverable errors (429, 5xx, network) */
546
+ MAX_RETRIES: 3,
547
+ /** Base delay in milliseconds for exponential backoff between retries */
548
+ RETRY_BASE_DELAY_MS: 1_000,
549
+ /** Default Ollama API base URL for local LLM provider */
550
+ OLLAMA_BASE_URL: 'http://localhost:11434/api',
551
+ /** Default security policy */
552
+ SECURITY_POLICY: {
553
+ auditEnabled: true,
554
+ requireApproval: [] as ToolSensitivity[],
555
+ blockedTools: [] as string[],
556
+ maxAuditEntries: 500,
557
+ readOnlyMode: false,
558
+ } satisfies SecurityPolicy,
559
+ /** Default security guardrail configuration */
560
+ SECURITY_GUARDRAILS: {
561
+ outputFilterEnabled: true,
562
+ envIsolationEnabled: true,
563
+ promptGuardEnabled: true,
564
+ explicitEnvVars: [],
565
+ } satisfies SecurityGuardrailConfig,
566
+ } as const;
567
+
568
+ /**
569
+ * Type guard to check if a string is a valid ModelProvider
570
+ *
571
+ * @param value - String to check
572
+ * @returns True if the value is a valid ModelProvider
573
+ */
574
+ export function isModelProvider(value: string): value is ModelProvider {
575
+ return MODEL_PROVIDERS.includes(value as ModelProvider);
576
+ }
577
+
578
+ /**
579
+ * Supported models for the UI dropdown.
580
+ * Format: provider/modelId → display label
581
+ */
582
+ export const SUPPORTED_MODELS: Array<{ id: string; label: string; provider: ModelProvider }> = [
583
+ { id: 'google/gemini-3-flash-preview', label: 'Gemini 3 Flash (Preview)', provider: 'google' },
584
+ { id: 'google/gemini-2.5-flash-preview-05-20', label: 'Gemini 2.5 Flash', provider: 'google' },
585
+ { id: 'anthropic/claude-sonnet-4-20250514', label: 'Claude Sonnet 4', provider: 'anthropic' },
586
+ { id: 'anthropic/claude-haiku-4-20250514', label: 'Claude Haiku 4', provider: 'anthropic' },
587
+ { id: 'openai/gpt-4o', label: 'GPT-4o', provider: 'openai' },
588
+ { id: 'openai/gpt-4o-mini', label: 'GPT-4o Mini', provider: 'openai' },
589
+ { id: 'deepseek/deepseek-chat', label: 'DeepSeek V3', provider: 'deepseek' },
590
+ { id: 'deepseek/deepseek-reasoner', label: 'DeepSeek R1', provider: 'deepseek' },
591
+ { id: 'ollama/llama3', label: 'Llama 3 (Ollama)', provider: 'ollama' },
592
+ ];
593
+
594
+ /**
595
+ * Parse a modelId string (provider/modelId) into a ModelConfig.
596
+ * Falls back to DEFAULT_MODEL if the input is invalid.
597
+ *
598
+ * @param modelId - Format: "provider/modelId" (e.g. "google/gemini-3-flash-preview")
599
+ * @returns Parsed ModelConfig
600
+ */
601
+ export function parseModelId(modelId: string | undefined): ModelConfig {
602
+ if (!modelId || !modelId.includes('/')) {
603
+ return CREWLY_AGENT_DEFAULTS.DEFAULT_MODEL;
604
+ }
605
+
606
+ const slashIdx = modelId.indexOf('/');
607
+ const provider = modelId.substring(0, slashIdx);
608
+ const model = modelId.substring(slashIdx + 1);
609
+
610
+ if (!isModelProvider(provider) || !model) {
611
+ return CREWLY_AGENT_DEFAULTS.DEFAULT_MODEL;
612
+ }
613
+
614
+ return {
615
+ provider,
616
+ modelId: model,
617
+ temperature: CREWLY_AGENT_DEFAULTS.DEFAULT_MODEL.temperature,
618
+ maxTokens: CREWLY_AGENT_DEFAULTS.DEFAULT_MODEL.maxTokens,
619
+ };
620
+ }
621
+
622
+ /**
623
+ * Type guard to check if an object is a valid ModelConfig
624
+ *
625
+ * @param obj - Object to validate
626
+ * @returns True if the object has all required ModelConfig fields
627
+ */
628
+ export function isModelConfig(obj: unknown): obj is ModelConfig {
629
+ if (typeof obj !== 'object' || obj === null) return false;
630
+ const candidate = obj as Record<string, unknown>;
631
+ return (
632
+ typeof candidate.provider === 'string' &&
633
+ isModelProvider(candidate.provider) &&
634
+ typeof candidate.modelId === 'string' &&
635
+ candidate.modelId.length > 0
636
+ );
637
+ }