@metabob/minibob 0.1.2

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 (174) hide show
  1. package/ARCHITECTURE.md +255 -0
  2. package/CHANGELOG.md +112 -0
  3. package/README.md +380 -0
  4. package/bin/minibob.js +36 -0
  5. package/dist/acp-gossip.d.ts +72 -0
  6. package/dist/acp-gossip.d.ts.map +1 -0
  7. package/dist/acp-gossip.js +156 -0
  8. package/dist/acp-gossip.js.map +1 -0
  9. package/dist/acp.d.ts +62 -0
  10. package/dist/acp.d.ts.map +1 -0
  11. package/dist/acp.js +292 -0
  12. package/dist/acp.js.map +1 -0
  13. package/dist/activity.d.ts +157 -0
  14. package/dist/activity.d.ts.map +1 -0
  15. package/dist/activity.js +518 -0
  16. package/dist/activity.js.map +1 -0
  17. package/dist/agent-runtime.d.ts +104 -0
  18. package/dist/agent-runtime.d.ts.map +1 -0
  19. package/dist/boredom.d.ts +125 -0
  20. package/dist/boredom.d.ts.map +1 -0
  21. package/dist/boredom.js +244 -0
  22. package/dist/boredom.js.map +1 -0
  23. package/dist/cli/acp-server.d.ts +23 -0
  24. package/dist/cli/acp-server.d.ts.map +1 -0
  25. package/dist/cli/burrow.d.ts +26 -0
  26. package/dist/cli/burrow.d.ts.map +1 -0
  27. package/dist/cli/doctor.d.ts +22 -0
  28. package/dist/cli/doctor.d.ts.map +1 -0
  29. package/dist/cli/goal.d.ts +22 -0
  30. package/dist/cli/goal.d.ts.map +1 -0
  31. package/dist/cli/index.d.ts +47 -0
  32. package/dist/cli/index.d.ts.map +1 -0
  33. package/dist/cli/instance-registry.d.ts +78 -0
  34. package/dist/cli/instance-registry.d.ts.map +1 -0
  35. package/dist/cli/observe.d.ts +35 -0
  36. package/dist/cli/observe.d.ts.map +1 -0
  37. package/dist/cli/vessel.d.ts +14 -0
  38. package/dist/cli/vessel.d.ts.map +1 -0
  39. package/dist/composition-observer.d.ts +96 -0
  40. package/dist/composition-observer.d.ts.map +1 -0
  41. package/dist/config.d.ts +36 -0
  42. package/dist/config.d.ts.map +1 -0
  43. package/dist/config.js +128 -0
  44. package/dist/config.js.map +1 -0
  45. package/dist/docker/Dockerfile +35 -0
  46. package/dist/environment.d.ts +72 -0
  47. package/dist/environment.d.ts.map +1 -0
  48. package/dist/environment.js +142 -0
  49. package/dist/environment.js.map +1 -0
  50. package/dist/goal-processor.d.ts +165 -0
  51. package/dist/goal-processor.d.ts.map +1 -0
  52. package/dist/helm/minibob-cluster/Chart.yaml +13 -0
  53. package/dist/helm/minibob-cluster/templates/_helpers.tpl +60 -0
  54. package/dist/helm/minibob-cluster/templates/configmap.yaml +11 -0
  55. package/dist/helm/minibob-cluster/templates/deployment.yaml +108 -0
  56. package/dist/helm/minibob-cluster/templates/secret.yaml +10 -0
  57. package/dist/helm/minibob-cluster/templates/service.yaml +37 -0
  58. package/dist/helm/minibob-cluster/values-local.yaml +41 -0
  59. package/dist/helm/minibob-cluster/values-production.yaml +57 -0
  60. package/dist/helm/minibob-cluster/values-testing-cluster.yaml +43 -0
  61. package/dist/helm/minibob-cluster/values.yaml +127 -0
  62. package/dist/improviser.d.ts +74 -0
  63. package/dist/improviser.d.ts.map +1 -0
  64. package/dist/impulse-filter.d.ts +74 -0
  65. package/dist/impulse-filter.d.ts.map +1 -0
  66. package/dist/impulse.d.ts +92 -0
  67. package/dist/impulse.d.ts.map +1 -0
  68. package/dist/impulse.js +234 -0
  69. package/dist/impulse.js.map +1 -0
  70. package/dist/lib.d.ts +29 -0
  71. package/dist/lib.d.ts.map +1 -0
  72. package/dist/lib.js +18561 -0
  73. package/dist/lib.js.map +98 -0
  74. package/dist/lifecycle-hooks.d.ts +99 -0
  75. package/dist/lifecycle-hooks.d.ts.map +1 -0
  76. package/dist/lifecycle-hooks.js +135 -0
  77. package/dist/lifecycle-hooks.js.map +1 -0
  78. package/dist/llm.d.ts +31 -0
  79. package/dist/llm.d.ts.map +1 -0
  80. package/dist/llm.js +349 -0
  81. package/dist/llm.js.map +1 -0
  82. package/dist/mcp-activity-bridge.d.ts +66 -0
  83. package/dist/mcp-activity-bridge.d.ts.map +1 -0
  84. package/dist/mcp-activity-bridge.js +126 -0
  85. package/dist/mcp-activity-bridge.js.map +1 -0
  86. package/dist/mcp.d.ts +216 -0
  87. package/dist/mcp.d.ts.map +1 -0
  88. package/dist/mcp.js +292 -0
  89. package/dist/mcp.js.map +1 -0
  90. package/dist/memory-agent.d.ts +92 -0
  91. package/dist/memory-agent.d.ts.map +1 -0
  92. package/dist/memory-agent.js +277 -0
  93. package/dist/memory-agent.js.map +1 -0
  94. package/dist/runtime-mapping.d.ts +97 -0
  95. package/dist/runtime-mapping.d.ts.map +1 -0
  96. package/dist/search-first-executor.d.ts +113 -0
  97. package/dist/search-first-executor.d.ts.map +1 -0
  98. package/dist/session.d.ts +48 -0
  99. package/dist/session.d.ts.map +1 -0
  100. package/dist/template-extractor.d.ts +9 -0
  101. package/dist/template-extractor.d.ts.map +1 -0
  102. package/dist/template-generator.d.ts +12 -0
  103. package/dist/template-generator.d.ts.map +1 -0
  104. package/dist/tools.d.ts +58 -0
  105. package/dist/tools.d.ts.map +1 -0
  106. package/dist/tools.js +771 -0
  107. package/dist/tools.js.map +1 -0
  108. package/dist/types.d.ts +503 -0
  109. package/dist/types.d.ts.map +1 -0
  110. package/dist/types.js +8 -0
  111. package/dist/types.js.map +1 -0
  112. package/dist/understanding/analyzer.d.ts +55 -0
  113. package/dist/understanding/analyzer.d.ts.map +1 -0
  114. package/dist/understanding/explorer.d.ts +73 -0
  115. package/dist/understanding/explorer.d.ts.map +1 -0
  116. package/dist/understanding/index.d.ts +7 -0
  117. package/dist/understanding/index.d.ts.map +1 -0
  118. package/dist/understanding/types.d.ts +136 -0
  119. package/dist/understanding/types.d.ts.map +1 -0
  120. package/dist/validation.d.ts +29 -0
  121. package/dist/validation.d.ts.map +1 -0
  122. package/dist/validation.js +106 -0
  123. package/dist/validation.js.map +1 -0
  124. package/dist/vessel-bootstrap.d.ts +190 -0
  125. package/dist/vessel-bootstrap.d.ts.map +1 -0
  126. package/dist/vessel-registry.d.ts +229 -0
  127. package/dist/vessel-registry.d.ts.map +1 -0
  128. package/index.ts +1329 -0
  129. package/package.json +54 -0
  130. package/src/acp-gossip.ts +193 -0
  131. package/src/acp.ts +362 -0
  132. package/src/activity.ts +1464 -0
  133. package/src/agent-runtime.ts +365 -0
  134. package/src/boredom.ts +423 -0
  135. package/src/cli/acp-server.ts +377 -0
  136. package/src/cli/burrow.ts +896 -0
  137. package/src/cli/doctor.ts +526 -0
  138. package/src/cli/goal.ts +224 -0
  139. package/src/cli/index.ts +147 -0
  140. package/src/cli/instance-registry.ts +271 -0
  141. package/src/cli/observe.ts +682 -0
  142. package/src/cli/vessel.ts +287 -0
  143. package/src/components/SystemOverview.tsx +331 -0
  144. package/src/composition-observer.ts +449 -0
  145. package/src/config.ts +172 -0
  146. package/src/environment.ts +167 -0
  147. package/src/goal-processor.ts +654 -0
  148. package/src/improviser.ts +591 -0
  149. package/src/impulse-filter.ts +273 -0
  150. package/src/impulse.ts +311 -0
  151. package/src/lib.ts +147 -0
  152. package/src/lifecycle-hooks.ts +181 -0
  153. package/src/llm.ts +434 -0
  154. package/src/mcp-activity-bridge.ts +158 -0
  155. package/src/mcp.ts +747 -0
  156. package/src/memory-agent.ts +316 -0
  157. package/src/runtime-mapping.ts +527 -0
  158. package/src/search-first-executor.ts +666 -0
  159. package/src/session.ts +141 -0
  160. package/src/template-extractor.ts +256 -0
  161. package/src/template-generator.ts +130 -0
  162. package/src/tools.ts +924 -0
  163. package/src/types.ts +497 -0
  164. package/src/understanding/analyzer.ts +354 -0
  165. package/src/understanding/explorer.ts +488 -0
  166. package/src/understanding/index.ts +27 -0
  167. package/src/understanding/types.ts +153 -0
  168. package/src/validation.ts +125 -0
  169. package/src/vessel-bootstrap.ts +440 -0
  170. package/src/vessel-registry.ts +621 -0
  171. package/templates/core/edit-file.json +85 -0
  172. package/templates/understanding/diagnose-problem.json +32 -0
  173. package/templates/understanding/explore-codebase-v2.json +57 -0
  174. package/templates/understanding/explore-codebase.json +37 -0
@@ -0,0 +1,316 @@
1
+ /**
2
+ * SessionMemoryAgent - Automatic context preparation for activity execution
3
+ *
4
+ * Moved from metabob-opencode to minibob as part of library integration.
5
+ * This version is simplified to work with minibob's minimal dependencies.
6
+ *
7
+ * Design goals:
8
+ * - Fast analysis (<2s with Claude Haiku)
9
+ * - Automatic impulse creation based on intent
10
+ * - Self-contained (no opencode dependencies)
11
+ */
12
+
13
+ import type { Impulse } from "./types"
14
+ import { createAnthropicClient } from "./llm"
15
+ import { createImpulse, getImpulseStore } from "./impulse"
16
+ import z from "zod"
17
+
18
+ export namespace SessionMemoryAgent {
19
+ /**
20
+ * User intent classification schema
21
+ */
22
+ const IntentSchema = z.object({
23
+ type: z.enum(["code_fix", "feature_request", "question", "refactor", "exploration", "other"]),
24
+ confidence: z.number().min(0).max(1),
25
+ reasoning: z.string(),
26
+ suggestedImpulses: z.array(
27
+ z.object({
28
+ id: z.string(),
29
+ type: z.enum(["file", "metabobIssue", "history", "memo", "bashOutput"]),
30
+ description: z.string(),
31
+ priority: z.enum(["critical", "high", "medium", "low"]),
32
+ budget: z.number().positive(),
33
+ pointer: z.union([
34
+ z.object({
35
+ type: z.literal("file"),
36
+ path: z.string(),
37
+ offset: z.number().optional(),
38
+ limit: z.number().optional(),
39
+ }),
40
+ z.object({
41
+ type: z.literal("memo"),
42
+ content: z.string(),
43
+ }),
44
+ z.object({
45
+ type: z.literal("custom"),
46
+ resolver: z.string(),
47
+ data: z.record(z.string(), z.unknown()),
48
+ }),
49
+ ]),
50
+ }),
51
+ ),
52
+ })
53
+
54
+ export type Intent = z.infer<typeof IntentSchema>
55
+
56
+ /**
57
+ * Configuration for session memory agent
58
+ */
59
+ export interface Config {
60
+ enabled: boolean
61
+ timeout: number // Max time for analysis (ms)
62
+ model: string // Model to use (e.g., "claude-3-5-haiku-20241022")
63
+ defaultBudget: number // Default token budget per impulse
64
+ maxImpulses: number // Max impulses per turn
65
+ }
66
+
67
+ const DEFAULT_CONFIG: Config = {
68
+ enabled: true,
69
+ timeout: 3000,
70
+ model: "claude-3-5-haiku-20241022",
71
+ defaultBudget: 2000,
72
+ maxImpulses: 5,
73
+ }
74
+
75
+ /**
76
+ * Analyze user intent from prompt text
77
+ * Returns intent classification with suggested impulses
78
+ */
79
+ export async function analyzeIntent(input: {
80
+ promptText: string
81
+ workingDirectory?: string
82
+ config?: Partial<Config>
83
+ }): Promise<Intent> {
84
+ const cfg = { ...DEFAULT_CONFIG, ...input.config }
85
+ const start = Date.now()
86
+
87
+ try {
88
+ console.log("[MemoryAgent] Analyzing intent", {
89
+ promptLength: input.promptText.length,
90
+ model: cfg.model,
91
+ timeout: cfg.timeout,
92
+ })
93
+
94
+ if (!process.env.ANTHROPIC_API_KEY) {
95
+ throw new Error("ANTHROPIC_API_KEY environment variable not set")
96
+ }
97
+
98
+ // Create LLM client
99
+ const llmClient = createAnthropicClient(process.env.ANTHROPIC_API_KEY)
100
+
101
+ // Build system prompt
102
+ const systemPrompt = `You are the Session Memory Agent - an intent analyzer for conversational coding assistance.
103
+
104
+ ## Your Role
105
+
106
+ Analyze user messages to understand their intent and recommend context (impulses) to load.
107
+ You DO NOT execute tasks. You ONLY analyze intent and suggest what context might be helpful.
108
+
109
+ For trivial messages (greetings, acknowledgments), classify as type="other" with empty suggestedImpulses array.
110
+
111
+ ## Intent Types
112
+
113
+ - **code_fix**: User reports a bug, error, or unexpected behavior
114
+ - **feature_request**: User wants to add/modify functionality
115
+ - **question**: User asks about code, architecture, or how things work
116
+ - **refactor**: User wants to improve existing code structure
117
+ - **exploration**: User is exploring codebase or investigating
118
+ - **other**: Greetings, acknowledgments, or messages that don't need coding context
119
+
120
+ ## Impulse Types
121
+
122
+ 1. **file**: Specific source files
123
+ - For code_fix: error file, related tests
124
+ - For feature_request: files to modify, similar features
125
+ - For question: files being asked about
126
+
127
+ 2. **memo**: Inline context notes
128
+ - For important constraints, requirements, or decisions
129
+ - Short-term memory across turns
130
+
131
+ 3. **custom**: Custom pointer types for specialized resolvers
132
+
133
+ ## Budget Guidelines
134
+
135
+ - file: 1500-3000 tokens (depends on file size)
136
+ - memo: 200-500 tokens
137
+ - custom: Varies by resolver
138
+
139
+ ## Priority Guidelines
140
+
141
+ - **critical**: Must-have for understanding request
142
+ - **high**: Very important for request
143
+ - **medium**: Helpful but not essential
144
+ - **low**: Background context
145
+
146
+ ## Output Format
147
+
148
+ Return JSON with:
149
+ - type: Intent classification
150
+ - confidence: 0-1 (how confident you are)
151
+ - reasoning: Why you classified this way (1 sentence)
152
+ - suggestedImpulses: Array of recommended impulses (0-${cfg.maxImpulses})
153
+
154
+ ## Examples
155
+
156
+ **Input**: "Fix the TypeError in calculator.ts"
157
+ **Output**:
158
+ {
159
+ "type": "code_fix",
160
+ "confidence": 0.95,
161
+ "reasoning": "User reports specific error with file reference",
162
+ "suggestedImpulses": [
163
+ {
164
+ "id": "errorFile",
165
+ "type": "file",
166
+ "description": "File containing the error",
167
+ "priority": "high",
168
+ "budget": 2000,
169
+ "pointer": { "type": "file", "path": "calculator.ts" }
170
+ }
171
+ ]
172
+ }
173
+
174
+ **Input**: "hi"
175
+ **Output**:
176
+ {
177
+ "type": "other",
178
+ "confidence": 1.0,
179
+ "reasoning": "Simple greeting, no coding context needed",
180
+ "suggestedImpulses": []
181
+ }
182
+
183
+ Be conservative with impulses. Quality over quantity. Only suggest what's clearly needed.`
184
+
185
+ // Call LLM
186
+ const result = await llmClient.complete({
187
+ model: cfg.model,
188
+ messages: [
189
+ {
190
+ role: "system",
191
+ content: systemPrompt + "\n\nIMPORTANT: Return ONLY valid JSON matching this schema. No markdown, no explanations.",
192
+ },
193
+ {
194
+ role: "user",
195
+ content: `Analyze this user message and suggest context impulses:\n\n"${input.promptText}"\n\nReturn JSON only.`,
196
+ },
197
+ ],
198
+ maxTokens: 2000,
199
+ temperature: 0.2,
200
+ })
201
+
202
+ // Parse JSON response
203
+ let intent: Intent
204
+ try {
205
+ // Remove markdown code blocks if present
206
+ let jsonStr = result.content.trim()
207
+ if (jsonStr.startsWith("```json")) {
208
+ jsonStr = jsonStr.slice(7)
209
+ }
210
+ if (jsonStr.startsWith("```")) {
211
+ jsonStr = jsonStr.slice(3)
212
+ }
213
+ if (jsonStr.endsWith("```")) {
214
+ jsonStr = jsonStr.slice(0, -3)
215
+ }
216
+
217
+ const parsed = JSON.parse(jsonStr.trim())
218
+ intent = IntentSchema.parse(parsed)
219
+ } catch (parseError) {
220
+ console.warn("[MemoryAgent] Failed to parse LLM response as JSON", {
221
+ error: parseError instanceof Error ? parseError.message : String(parseError),
222
+ response: result.content.slice(0, 200),
223
+ })
224
+ throw new Error("Failed to parse intent analysis response")
225
+ }
226
+
227
+ console.log("[MemoryAgent] Analysis complete", {
228
+ type: intent.type,
229
+ confidence: intent.confidence,
230
+ impulseCount: intent.suggestedImpulses.length,
231
+ elapsed: Date.now() - start,
232
+ })
233
+
234
+ return intent
235
+ } catch (error) {
236
+ console.warn("[MemoryAgent] Analysis failed, returning fallback", {
237
+ error: error instanceof Error ? error.message : String(error),
238
+ elapsed: Date.now() - start,
239
+ })
240
+
241
+ // Fallback: return "other" with no impulses
242
+ return {
243
+ type: "other",
244
+ confidence: 0,
245
+ reasoning: "Analysis failed, proceeding without context",
246
+ suggestedImpulses: [],
247
+ }
248
+ }
249
+ }
250
+
251
+ /**
252
+ * Prepare impulses based on intent analysis
253
+ * Creates impulses in the impulse store
254
+ */
255
+ export async function prepare(input: { intent: Intent }): Promise<{
256
+ impulsesCreated: number
257
+ impulseIds: string[]
258
+ }> {
259
+ const start = Date.now()
260
+
261
+ try {
262
+ const store = getImpulseStore()
263
+ let created = 0
264
+ const impulseIds: string[] = []
265
+
266
+ // Create impulses from suggestions
267
+ for (const suggestion of input.intent.suggestedImpulses) {
268
+ // Check if impulse already exists
269
+ const existing = store.get(suggestion.id)
270
+ if (existing) {
271
+ console.log("[MemoryAgent] Impulse already exists, skipping", { impulseId: suggestion.id })
272
+ continue
273
+ }
274
+
275
+ // Create impulse (match Impulse type minus loaded/createdAt)
276
+ const impulse = createImpulse({
277
+ id: suggestion.id,
278
+ pointer: suggestion.pointer as any,
279
+ budget: suggestion.budget,
280
+ priority: suggestion.priority,
281
+ tags: ["memory-agent", `type:${suggestion.type}`],
282
+ })
283
+
284
+ created++
285
+ impulseIds.push(impulse.id)
286
+
287
+ console.log("[MemoryAgent] Impulse created", {
288
+ impulseId: impulse.id,
289
+ type: suggestion.type,
290
+ priority: suggestion.priority,
291
+ budget: suggestion.budget,
292
+ })
293
+ }
294
+
295
+ console.log("[MemoryAgent] Preparation complete", {
296
+ created,
297
+ elapsed: Date.now() - start,
298
+ })
299
+
300
+ return {
301
+ impulsesCreated: created,
302
+ impulseIds,
303
+ }
304
+ } catch (error) {
305
+ console.error("[MemoryAgent] Preparation failed", {
306
+ error: error instanceof Error ? error.message : String(error),
307
+ elapsed: Date.now() - start,
308
+ })
309
+
310
+ return {
311
+ impulsesCreated: 0,
312
+ impulseIds: [],
313
+ }
314
+ }
315
+ }
316
+ }