@build-astron-co/nimbus 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (313) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +628 -0
  3. package/bin/nimbus +38 -0
  4. package/package.json +80 -0
  5. package/src/__tests__/app.test.ts +76 -0
  6. package/src/__tests__/audit.test.ts +877 -0
  7. package/src/__tests__/circuit-breaker.test.ts +116 -0
  8. package/src/__tests__/cli-run.test.ts +115 -0
  9. package/src/__tests__/context-manager.test.ts +502 -0
  10. package/src/__tests__/context.test.ts +242 -0
  11. package/src/__tests__/enterprise.test.ts +401 -0
  12. package/src/__tests__/generator.test.ts +433 -0
  13. package/src/__tests__/hooks.test.ts +582 -0
  14. package/src/__tests__/init.test.ts +436 -0
  15. package/src/__tests__/intent-parser.test.ts +229 -0
  16. package/src/__tests__/llm-router.test.ts +209 -0
  17. package/src/__tests__/lsp.test.ts +293 -0
  18. package/src/__tests__/modes.test.ts +336 -0
  19. package/src/__tests__/permissions.test.ts +338 -0
  20. package/src/__tests__/serve.test.ts +275 -0
  21. package/src/__tests__/sessions.test.ts +227 -0
  22. package/src/__tests__/sharing.test.ts +288 -0
  23. package/src/__tests__/snapshots.test.ts +581 -0
  24. package/src/__tests__/state-db.test.ts +334 -0
  25. package/src/__tests__/stream-with-tools.test.ts +732 -0
  26. package/src/__tests__/subagents.test.ts +176 -0
  27. package/src/__tests__/system-prompt.test.ts +169 -0
  28. package/src/__tests__/tool-converter.test.ts +256 -0
  29. package/src/__tests__/tool-schemas.test.ts +397 -0
  30. package/src/__tests__/tools.test.ts +143 -0
  31. package/src/__tests__/version.test.ts +49 -0
  32. package/src/agent/compaction-agent.ts +227 -0
  33. package/src/agent/context-manager.ts +435 -0
  34. package/src/agent/context.ts +427 -0
  35. package/src/agent/deploy-preview.ts +426 -0
  36. package/src/agent/index.ts +68 -0
  37. package/src/agent/loop.ts +717 -0
  38. package/src/agent/modes.ts +429 -0
  39. package/src/agent/permissions.ts +466 -0
  40. package/src/agent/subagents/base.ts +116 -0
  41. package/src/agent/subagents/cost.ts +51 -0
  42. package/src/agent/subagents/explore.ts +42 -0
  43. package/src/agent/subagents/general.ts +54 -0
  44. package/src/agent/subagents/index.ts +102 -0
  45. package/src/agent/subagents/infra.ts +59 -0
  46. package/src/agent/subagents/security.ts +69 -0
  47. package/src/agent/system-prompt.ts +436 -0
  48. package/src/app.ts +122 -0
  49. package/src/audit/activity-log.ts +290 -0
  50. package/src/audit/compliance-checker.ts +540 -0
  51. package/src/audit/cost-tracker.ts +318 -0
  52. package/src/audit/index.ts +23 -0
  53. package/src/audit/security-scanner.ts +596 -0
  54. package/src/auth/guard.ts +75 -0
  55. package/src/auth/index.ts +56 -0
  56. package/src/auth/oauth.ts +455 -0
  57. package/src/auth/providers.ts +470 -0
  58. package/src/auth/sso.ts +113 -0
  59. package/src/auth/store.ts +505 -0
  60. package/src/auth/types.ts +187 -0
  61. package/src/build.ts +141 -0
  62. package/src/cli/index.ts +16 -0
  63. package/src/cli/init.ts +854 -0
  64. package/src/cli/openapi-spec.ts +356 -0
  65. package/src/cli/run.ts +237 -0
  66. package/src/cli/serve-auth.ts +80 -0
  67. package/src/cli/serve.ts +462 -0
  68. package/src/cli/web.ts +67 -0
  69. package/src/cli.ts +1417 -0
  70. package/src/clients/core-engine-client.ts +227 -0
  71. package/src/clients/enterprise-client.ts +334 -0
  72. package/src/clients/generator-client.ts +351 -0
  73. package/src/clients/git-client.ts +627 -0
  74. package/src/clients/github-client.ts +410 -0
  75. package/src/clients/helm-client.ts +504 -0
  76. package/src/clients/index.ts +80 -0
  77. package/src/clients/k8s-client.ts +497 -0
  78. package/src/clients/llm-client.ts +161 -0
  79. package/src/clients/rest-client.ts +130 -0
  80. package/src/clients/service-discovery.ts +33 -0
  81. package/src/clients/terraform-client.ts +482 -0
  82. package/src/clients/tools-client.ts +1843 -0
  83. package/src/clients/ws-client.ts +115 -0
  84. package/src/commands/analyze/index.ts +352 -0
  85. package/src/commands/apply/helm.ts +473 -0
  86. package/src/commands/apply/index.ts +213 -0
  87. package/src/commands/apply/k8s.ts +454 -0
  88. package/src/commands/apply/terraform.ts +582 -0
  89. package/src/commands/ask.ts +167 -0
  90. package/src/commands/audit/index.ts +238 -0
  91. package/src/commands/auth-cloud.ts +294 -0
  92. package/src/commands/auth-list.ts +134 -0
  93. package/src/commands/auth-profile.ts +121 -0
  94. package/src/commands/auth-status.ts +141 -0
  95. package/src/commands/aws/ec2.ts +501 -0
  96. package/src/commands/aws/iam.ts +397 -0
  97. package/src/commands/aws/index.ts +133 -0
  98. package/src/commands/aws/lambda.ts +396 -0
  99. package/src/commands/aws/rds.ts +439 -0
  100. package/src/commands/aws/s3.ts +439 -0
  101. package/src/commands/aws/vpc.ts +393 -0
  102. package/src/commands/aws-discover.ts +649 -0
  103. package/src/commands/aws-terraform.ts +805 -0
  104. package/src/commands/azure/aks.ts +376 -0
  105. package/src/commands/azure/functions.ts +253 -0
  106. package/src/commands/azure/index.ts +116 -0
  107. package/src/commands/azure/storage.ts +478 -0
  108. package/src/commands/azure/vm.ts +355 -0
  109. package/src/commands/billing/index.ts +256 -0
  110. package/src/commands/chat.ts +314 -0
  111. package/src/commands/config.ts +346 -0
  112. package/src/commands/cost/cloud-cost-estimator.ts +266 -0
  113. package/src/commands/cost/estimator.ts +79 -0
  114. package/src/commands/cost/index.ts +594 -0
  115. package/src/commands/cost/parsers/terraform.ts +273 -0
  116. package/src/commands/cost/parsers/types.ts +25 -0
  117. package/src/commands/cost/pricing/aws.ts +544 -0
  118. package/src/commands/cost/pricing/azure.ts +499 -0
  119. package/src/commands/cost/pricing/gcp.ts +396 -0
  120. package/src/commands/cost/pricing/index.ts +40 -0
  121. package/src/commands/demo.ts +250 -0
  122. package/src/commands/doctor.ts +794 -0
  123. package/src/commands/drift/index.ts +439 -0
  124. package/src/commands/explain.ts +277 -0
  125. package/src/commands/feedback.ts +389 -0
  126. package/src/commands/fix.ts +324 -0
  127. package/src/commands/fs/index.ts +402 -0
  128. package/src/commands/gcp/compute.ts +325 -0
  129. package/src/commands/gcp/functions.ts +271 -0
  130. package/src/commands/gcp/gke.ts +438 -0
  131. package/src/commands/gcp/iam.ts +344 -0
  132. package/src/commands/gcp/index.ts +129 -0
  133. package/src/commands/gcp/storage.ts +284 -0
  134. package/src/commands/generate-helm.ts +1249 -0
  135. package/src/commands/generate-k8s.ts +1560 -0
  136. package/src/commands/generate-terraform.ts +1460 -0
  137. package/src/commands/gh/index.ts +863 -0
  138. package/src/commands/git/index.ts +1343 -0
  139. package/src/commands/helm/index.ts +1126 -0
  140. package/src/commands/help.ts +539 -0
  141. package/src/commands/history.ts +142 -0
  142. package/src/commands/import.ts +868 -0
  143. package/src/commands/index.ts +367 -0
  144. package/src/commands/init.ts +1046 -0
  145. package/src/commands/k8s/index.ts +1137 -0
  146. package/src/commands/login.ts +631 -0
  147. package/src/commands/logout.ts +83 -0
  148. package/src/commands/onboarding.ts +228 -0
  149. package/src/commands/plan/display.ts +279 -0
  150. package/src/commands/plan/index.ts +599 -0
  151. package/src/commands/preview.ts +452 -0
  152. package/src/commands/questionnaire.ts +1270 -0
  153. package/src/commands/resume.ts +55 -0
  154. package/src/commands/team/index.ts +346 -0
  155. package/src/commands/template.ts +232 -0
  156. package/src/commands/tf/index.ts +1034 -0
  157. package/src/commands/upgrade.ts +550 -0
  158. package/src/commands/usage/index.ts +134 -0
  159. package/src/commands/version.ts +170 -0
  160. package/src/compat/index.ts +2 -0
  161. package/src/compat/runtime.ts +12 -0
  162. package/src/compat/sqlite.ts +107 -0
  163. package/src/config/index.ts +17 -0
  164. package/src/config/manager.ts +530 -0
  165. package/src/config/safety-policy.ts +358 -0
  166. package/src/config/schema.ts +125 -0
  167. package/src/config/types.ts +527 -0
  168. package/src/context/context-db.ts +199 -0
  169. package/src/demo/index.ts +349 -0
  170. package/src/demo/scenarios/full-journey.ts +229 -0
  171. package/src/demo/scenarios/getting-started.ts +127 -0
  172. package/src/demo/scenarios/helm-release.ts +341 -0
  173. package/src/demo/scenarios/k8s-deployment.ts +194 -0
  174. package/src/demo/scenarios/terraform-vpc.ts +170 -0
  175. package/src/demo/types.ts +92 -0
  176. package/src/engine/cost-estimator.ts +438 -0
  177. package/src/engine/diagram-generator.ts +256 -0
  178. package/src/engine/drift-detector.ts +902 -0
  179. package/src/engine/executor.ts +1035 -0
  180. package/src/engine/index.ts +76 -0
  181. package/src/engine/orchestrator.ts +636 -0
  182. package/src/engine/planner.ts +720 -0
  183. package/src/engine/safety.ts +743 -0
  184. package/src/engine/verifier.ts +770 -0
  185. package/src/enterprise/audit.ts +348 -0
  186. package/src/enterprise/auth.ts +270 -0
  187. package/src/enterprise/billing.ts +822 -0
  188. package/src/enterprise/index.ts +17 -0
  189. package/src/enterprise/teams.ts +443 -0
  190. package/src/generator/best-practices.ts +1608 -0
  191. package/src/generator/helm.ts +630 -0
  192. package/src/generator/index.ts +37 -0
  193. package/src/generator/intent-parser.ts +514 -0
  194. package/src/generator/kubernetes.ts +976 -0
  195. package/src/generator/terraform.ts +1867 -0
  196. package/src/history/index.ts +8 -0
  197. package/src/history/manager.ts +322 -0
  198. package/src/history/types.ts +34 -0
  199. package/src/hooks/config.ts +432 -0
  200. package/src/hooks/engine.ts +391 -0
  201. package/src/hooks/index.ts +4 -0
  202. package/src/llm/auth-bridge.ts +198 -0
  203. package/src/llm/circuit-breaker.ts +140 -0
  204. package/src/llm/config-loader.ts +201 -0
  205. package/src/llm/cost-calculator.ts +171 -0
  206. package/src/llm/index.ts +8 -0
  207. package/src/llm/model-aliases.ts +115 -0
  208. package/src/llm/provider-registry.ts +63 -0
  209. package/src/llm/providers/anthropic.ts +433 -0
  210. package/src/llm/providers/bedrock.ts +477 -0
  211. package/src/llm/providers/google.ts +405 -0
  212. package/src/llm/providers/ollama.ts +767 -0
  213. package/src/llm/providers/openai-compatible.ts +340 -0
  214. package/src/llm/providers/openai.ts +328 -0
  215. package/src/llm/providers/openrouter.ts +338 -0
  216. package/src/llm/router.ts +1035 -0
  217. package/src/llm/types.ts +232 -0
  218. package/src/lsp/client.ts +298 -0
  219. package/src/lsp/languages.ts +116 -0
  220. package/src/lsp/manager.ts +278 -0
  221. package/src/mcp/client.ts +402 -0
  222. package/src/mcp/index.ts +5 -0
  223. package/src/mcp/manager.ts +133 -0
  224. package/src/nimbus.ts +214 -0
  225. package/src/plugins/index.ts +27 -0
  226. package/src/plugins/loader.ts +334 -0
  227. package/src/plugins/manager.ts +376 -0
  228. package/src/plugins/types.ts +284 -0
  229. package/src/scanners/cicd-scanner.ts +258 -0
  230. package/src/scanners/cloud-scanner.ts +466 -0
  231. package/src/scanners/framework-scanner.ts +469 -0
  232. package/src/scanners/iac-scanner.ts +388 -0
  233. package/src/scanners/index.ts +539 -0
  234. package/src/scanners/language-scanner.ts +276 -0
  235. package/src/scanners/package-manager-scanner.ts +277 -0
  236. package/src/scanners/types.ts +172 -0
  237. package/src/sessions/manager.ts +365 -0
  238. package/src/sessions/types.ts +44 -0
  239. package/src/sharing/sync.ts +296 -0
  240. package/src/sharing/viewer.ts +97 -0
  241. package/src/snapshots/index.ts +2 -0
  242. package/src/snapshots/manager.ts +530 -0
  243. package/src/state/artifacts.ts +147 -0
  244. package/src/state/audit.ts +137 -0
  245. package/src/state/billing.ts +240 -0
  246. package/src/state/checkpoints.ts +117 -0
  247. package/src/state/config.ts +67 -0
  248. package/src/state/conversations.ts +14 -0
  249. package/src/state/credentials.ts +154 -0
  250. package/src/state/db.ts +58 -0
  251. package/src/state/index.ts +26 -0
  252. package/src/state/messages.ts +115 -0
  253. package/src/state/projects.ts +123 -0
  254. package/src/state/schema.ts +236 -0
  255. package/src/state/sessions.ts +147 -0
  256. package/src/state/teams.ts +200 -0
  257. package/src/telemetry.ts +108 -0
  258. package/src/tools/aws-ops.ts +952 -0
  259. package/src/tools/azure-ops.ts +579 -0
  260. package/src/tools/file-ops.ts +593 -0
  261. package/src/tools/gcp-ops.ts +625 -0
  262. package/src/tools/git-ops.ts +773 -0
  263. package/src/tools/github-ops.ts +799 -0
  264. package/src/tools/helm-ops.ts +943 -0
  265. package/src/tools/index.ts +17 -0
  266. package/src/tools/k8s-ops.ts +819 -0
  267. package/src/tools/schemas/converter.ts +184 -0
  268. package/src/tools/schemas/devops.ts +612 -0
  269. package/src/tools/schemas/index.ts +73 -0
  270. package/src/tools/schemas/standard.ts +1144 -0
  271. package/src/tools/schemas/types.ts +705 -0
  272. package/src/tools/terraform-ops.ts +862 -0
  273. package/src/types/ambient.d.ts +193 -0
  274. package/src/types/config.ts +83 -0
  275. package/src/types/drift.ts +116 -0
  276. package/src/types/enterprise.ts +335 -0
  277. package/src/types/index.ts +20 -0
  278. package/src/types/plan.ts +44 -0
  279. package/src/types/request.ts +65 -0
  280. package/src/types/response.ts +54 -0
  281. package/src/types/service.ts +51 -0
  282. package/src/ui/App.tsx +997 -0
  283. package/src/ui/DeployPreview.tsx +169 -0
  284. package/src/ui/Header.tsx +68 -0
  285. package/src/ui/InputBox.tsx +350 -0
  286. package/src/ui/MessageList.tsx +585 -0
  287. package/src/ui/PermissionPrompt.tsx +151 -0
  288. package/src/ui/StatusBar.tsx +158 -0
  289. package/src/ui/ToolCallDisplay.tsx +409 -0
  290. package/src/ui/chat-ui.ts +853 -0
  291. package/src/ui/index.ts +33 -0
  292. package/src/ui/ink/index.ts +711 -0
  293. package/src/ui/streaming.ts +176 -0
  294. package/src/ui/types.ts +57 -0
  295. package/src/utils/analytics.ts +72 -0
  296. package/src/utils/cost-warning.ts +27 -0
  297. package/src/utils/env.ts +46 -0
  298. package/src/utils/errors.ts +69 -0
  299. package/src/utils/event-bus.ts +38 -0
  300. package/src/utils/index.ts +24 -0
  301. package/src/utils/logger.ts +171 -0
  302. package/src/utils/rate-limiter.ts +121 -0
  303. package/src/utils/service-auth.ts +49 -0
  304. package/src/utils/validation.ts +53 -0
  305. package/src/version.ts +4 -0
  306. package/src/watcher/index.ts +163 -0
  307. package/src/wizard/approval.ts +383 -0
  308. package/src/wizard/index.ts +25 -0
  309. package/src/wizard/prompts.ts +338 -0
  310. package/src/wizard/types.ts +171 -0
  311. package/src/wizard/ui.ts +556 -0
  312. package/src/wizard/wizard.ts +304 -0
  313. package/tsconfig.json +24 -0
@@ -0,0 +1,290 @@
1
+ /**
2
+ * Activity Log - Record and query every tool call executed by the Nimbus agent.
3
+ *
4
+ * Each entry captures the tool name, input parameters, output, duration,
5
+ * session context, and operating mode (plan/build/deploy). The log supports
6
+ * flexible filtering, summary statistics with tool-level breakdowns, and
7
+ * both concise and verbose text formatting.
8
+ */
9
+
10
+ // ---------------------------------------------------------------------------
11
+ // Types
12
+ // ---------------------------------------------------------------------------
13
+
14
+ /** A single recorded tool call */
15
+ export interface ActivityEntry {
16
+ /** Unique identifier */
17
+ id: string;
18
+ /** When the tool call was executed */
19
+ timestamp: Date;
20
+ /** Session in which the call occurred */
21
+ sessionId: string;
22
+ /** Name of the tool that was invoked */
23
+ toolName: string;
24
+ /** Input parameters passed to the tool */
25
+ toolInput: Record<string, unknown>;
26
+ /** Tool output and error status */
27
+ result: { output: string; isError: boolean };
28
+ /** Execution duration in milliseconds */
29
+ duration: number;
30
+ /** Operating mode when the call was made (e.g. plan, build, deploy) */
31
+ mode: string;
32
+ }
33
+
34
+ /** Filter criteria for querying the activity log */
35
+ export interface ActivityFilter {
36
+ /** Filter by tool name (exact match) */
37
+ toolName?: string;
38
+ /** Only include entries on or after this date */
39
+ since?: Date;
40
+ /** Only include entries on or before this date */
41
+ until?: Date;
42
+ /** Filter by session ID */
43
+ sessionId?: string;
44
+ /** Filter by error status */
45
+ isError?: boolean;
46
+ /** Maximum number of entries to return */
47
+ limit?: number;
48
+ }
49
+
50
+ // ---------------------------------------------------------------------------
51
+ // Helpers
52
+ // ---------------------------------------------------------------------------
53
+
54
+ /**
55
+ * Format a duration in milliseconds as a human-friendly string.
56
+ */
57
+ function formatDuration(ms: number): string {
58
+ if (ms < 1000) {
59
+ return `${ms}ms`;
60
+ }
61
+ if (ms < 60_000) {
62
+ return `${(ms / 1000).toFixed(1)}s`;
63
+ }
64
+ const minutes = Math.floor(ms / 60_000);
65
+ const seconds = ((ms % 60_000) / 1000).toFixed(0);
66
+ return `${minutes}m ${seconds}s`;
67
+ }
68
+
69
+ /**
70
+ * Format a Date as a compact ISO-like timestamp (YYYY-MM-DD HH:MM:SS).
71
+ */
72
+ function formatTimestamp(date: Date): string {
73
+ const y = date.getFullYear();
74
+ const mo = String(date.getMonth() + 1).padStart(2, '0');
75
+ const d = String(date.getDate()).padStart(2, '0');
76
+ const h = String(date.getHours()).padStart(2, '0');
77
+ const mi = String(date.getMinutes()).padStart(2, '0');
78
+ const s = String(date.getSeconds()).padStart(2, '0');
79
+ return `${y}-${mo}-${d} ${h}:${mi}:${s}`;
80
+ }
81
+
82
+ /**
83
+ * Truncate a string to maxLen characters, appending an ellipsis if needed.
84
+ */
85
+ function truncate(str: string, maxLen: number): string {
86
+ if (str.length <= maxLen) {
87
+ return str;
88
+ }
89
+ return `${str.slice(0, maxLen - 3)}...`;
90
+ }
91
+
92
+ // ---------------------------------------------------------------------------
93
+ // ActivityLog
94
+ // ---------------------------------------------------------------------------
95
+
96
+ /**
97
+ * In-memory log of all tool calls made during Nimbus sessions.
98
+ *
99
+ * Supports recording entries, querying with filters, computing summary
100
+ * statistics, and formatting output for display in the CLI.
101
+ *
102
+ * @example
103
+ * ```typescript
104
+ * const log = new ActivityLog();
105
+ *
106
+ * log.log({
107
+ * timestamp: new Date(),
108
+ * sessionId: 'session-1',
109
+ * toolName: 'terraform_plan',
110
+ * toolInput: { dir: '/infra' },
111
+ * result: { output: 'Plan: 3 to add', isError: false },
112
+ * duration: 4200,
113
+ * mode: 'plan',
114
+ * });
115
+ *
116
+ * const entries = log.query({ toolName: 'terraform_plan' });
117
+ * console.log(log.formatLog(entries));
118
+ * ```
119
+ */
120
+ export class ActivityLog {
121
+ private entries: ActivityEntry[] = [];
122
+
123
+ /**
124
+ * Record a tool call in the activity log.
125
+ *
126
+ * A unique ID is generated automatically. The entry is appended to the
127
+ * internal ledger and returned.
128
+ *
129
+ * @param entry - All fields except `id` (which is auto-generated)
130
+ * @returns The created activity entry with its assigned ID
131
+ */
132
+ log(entry: Omit<ActivityEntry, 'id'>): ActivityEntry {
133
+ const full: ActivityEntry = {
134
+ id: crypto.randomUUID(),
135
+ ...entry,
136
+ };
137
+
138
+ this.entries.push(full);
139
+ return full;
140
+ }
141
+
142
+ /**
143
+ * Query the activity log with optional filters.
144
+ *
145
+ * Filters are combined with AND logic. Results are returned in reverse
146
+ * chronological order (newest first). Use `limit` to cap the result count.
147
+ *
148
+ * @param filter - Optional filter criteria
149
+ * @returns Matching activity entries
150
+ */
151
+ query(filter?: ActivityFilter): ActivityEntry[] {
152
+ let results = [...this.entries];
153
+
154
+ if (filter?.toolName) {
155
+ results = results.filter(e => e.toolName === filter.toolName);
156
+ }
157
+
158
+ if (filter?.sessionId) {
159
+ results = results.filter(e => e.sessionId === filter.sessionId);
160
+ }
161
+
162
+ if (filter?.since) {
163
+ const since = filter.since.getTime();
164
+ results = results.filter(e => e.timestamp.getTime() >= since);
165
+ }
166
+
167
+ if (filter?.until) {
168
+ const until = filter.until.getTime();
169
+ results = results.filter(e => e.timestamp.getTime() <= until);
170
+ }
171
+
172
+ if (filter?.isError !== undefined) {
173
+ results = results.filter(e => e.result.isError === filter.isError);
174
+ }
175
+
176
+ // Sort newest first
177
+ results.sort((a, b) => b.timestamp.getTime() - a.timestamp.getTime());
178
+
179
+ if (filter?.limit !== undefined && filter.limit > 0) {
180
+ results = results.slice(0, filter.limit);
181
+ }
182
+
183
+ return results;
184
+ }
185
+
186
+ /**
187
+ * Compute summary statistics for the activity log.
188
+ *
189
+ * Returns total call count, error count, average duration, and a breakdown
190
+ * of call counts per tool name.
191
+ *
192
+ * @param sessionId - If provided, restrict statistics to this session
193
+ * @returns Summary statistics object
194
+ */
195
+ getStats(sessionId?: string): {
196
+ totalCalls: number;
197
+ errorCount: number;
198
+ avgDuration: number;
199
+ toolBreakdown: Record<string, number>;
200
+ } {
201
+ let entries = this.entries;
202
+ if (sessionId) {
203
+ entries = entries.filter(e => e.sessionId === sessionId);
204
+ }
205
+
206
+ const totalCalls = entries.length;
207
+ const errorCount = entries.filter(e => e.result.isError).length;
208
+
209
+ const totalDuration = entries.reduce((sum, e) => sum + e.duration, 0);
210
+ const avgDuration = totalCalls > 0 ? Math.round(totalDuration / totalCalls) : 0;
211
+
212
+ const toolBreakdown: Record<string, number> = {};
213
+ for (const entry of entries) {
214
+ toolBreakdown[entry.toolName] = (toolBreakdown[entry.toolName] ?? 0) + 1;
215
+ }
216
+
217
+ return {
218
+ totalCalls,
219
+ errorCount,
220
+ avgDuration,
221
+ toolBreakdown,
222
+ };
223
+ }
224
+
225
+ /**
226
+ * Format activity entries as a human-readable text report.
227
+ *
228
+ * In concise mode (default), each entry is a single line with timestamp,
229
+ * tool name, duration, and status. In verbose mode, input parameters and
230
+ * output are also shown.
231
+ *
232
+ * @param entries - Entries to format
233
+ * @param options - Formatting options
234
+ * @returns Multi-line formatted log
235
+ */
236
+ formatLog(entries: ActivityEntry[], options?: { verbose?: boolean }): string {
237
+ if (entries.length === 0) {
238
+ return 'No activity entries to display.';
239
+ }
240
+
241
+ const verbose = options?.verbose ?? false;
242
+
243
+ const lines: string[] = [`Activity Log (${entries.length} entries)`, '='.repeat(60), ''];
244
+
245
+ for (const entry of entries) {
246
+ const status = entry.result.isError ? '[ERROR]' : '[OK] ';
247
+ const ts = formatTimestamp(entry.timestamp);
248
+ const dur = formatDuration(entry.duration);
249
+
250
+ lines.push(`${ts} ${status} ${entry.toolName} (${dur}) [${entry.mode}]`);
251
+
252
+ if (verbose) {
253
+ // Show input
254
+ const inputStr = JSON.stringify(entry.toolInput);
255
+ lines.push(` Input: ${truncate(inputStr, 120)}`);
256
+
257
+ // Show output
258
+ const outputStr = entry.result.output;
259
+ lines.push(` Output: ${truncate(outputStr, 120)}`);
260
+
261
+ if (entry.result.isError) {
262
+ lines.push(` ** Error occurred during execution **`);
263
+ }
264
+
265
+ lines.push('');
266
+ }
267
+ }
268
+
269
+ if (!verbose) {
270
+ lines.push('');
271
+ }
272
+
273
+ // Append quick stats
274
+ const errorCount = entries.filter(e => e.result.isError).length;
275
+ const totalDuration = entries.reduce((s, e) => s + e.duration, 0);
276
+ const avgDuration = entries.length > 0 ? Math.round(totalDuration / entries.length) : 0;
277
+
278
+ lines.push('-'.repeat(60));
279
+ lines.push(`${entries.length} calls, ${errorCount} errors, avg ${formatDuration(avgDuration)}`);
280
+
281
+ return lines.join('\n');
282
+ }
283
+
284
+ /**
285
+ * Remove all entries from the activity log.
286
+ */
287
+ clear(): void {
288
+ this.entries = [];
289
+ }
290
+ }