beercan 0.4.7 → 0.5.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.
- package/README.md +62 -4
- package/dist/config.d.ts +30 -0
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +40 -0
- package/dist/config.js.map +1 -1
- package/dist/core/heartbeat.d.ts +57 -0
- package/dist/core/heartbeat.d.ts.map +1 -0
- package/dist/core/heartbeat.js +179 -0
- package/dist/core/heartbeat.js.map +1 -0
- package/dist/core/job-queue.d.ts +3 -0
- package/dist/core/job-queue.d.ts.map +1 -1
- package/dist/core/job-queue.js +2 -0
- package/dist/core/job-queue.js.map +1 -1
- package/dist/core/reflection.d.ts +38 -0
- package/dist/core/reflection.d.ts.map +1 -0
- package/dist/core/reflection.js +287 -0
- package/dist/core/reflection.js.map +1 -0
- package/dist/core/role-templates.d.ts.map +1 -1
- package/dist/core/role-templates.js +40 -0
- package/dist/core/role-templates.js.map +1 -1
- package/dist/core/runner.d.ts +3 -1
- package/dist/core/runner.d.ts.map +1 -1
- package/dist/core/runner.js +17 -1
- package/dist/core/runner.js.map +1 -1
- package/dist/events/daemon.d.ts.map +1 -1
- package/dist/events/daemon.js +5 -0
- package/dist/events/daemon.js.map +1 -1
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +44 -2
- package/dist/index.js.map +1 -1
- package/dist/memory/hybrid-search.d.ts +3 -2
- package/dist/memory/hybrid-search.d.ts.map +1 -1
- package/dist/memory/hybrid-search.js +13 -2
- package/dist/memory/hybrid-search.js.map +1 -1
- package/dist/memory/index.d.ts +5 -0
- package/dist/memory/index.d.ts.map +1 -1
- package/dist/memory/index.js +26 -2
- package/dist/memory/index.js.map +1 -1
- package/dist/skills/index.d.ts +4 -0
- package/dist/skills/index.d.ts.map +1 -1
- package/dist/skills/index.js +8 -0
- package/dist/skills/index.js.map +1 -1
- package/dist/storage/database.d.ts +6 -0
- package/dist/storage/database.d.ts.map +1 -1
- package/dist/storage/database.js +47 -2
- package/dist/storage/database.js.map +1 -1
- package/dist/tools/builtin/filesystem.d.ts.map +1 -1
- package/dist/tools/builtin/filesystem.js +3 -0
- package/dist/tools/builtin/filesystem.js.map +1 -1
- package/dist/tools/builtin/integration.d.ts +20 -0
- package/dist/tools/builtin/integration.d.ts.map +1 -0
- package/dist/tools/builtin/integration.js +220 -0
- package/dist/tools/builtin/integration.js.map +1 -0
- package/dist/tools/builtin/scheduling.d.ts +62 -0
- package/dist/tools/builtin/scheduling.d.ts.map +1 -0
- package/dist/tools/builtin/scheduling.js +280 -0
- package/dist/tools/builtin/scheduling.js.map +1 -0
- package/dist/tools/builtin/skills.d.ts +10 -0
- package/dist/tools/builtin/skills.d.ts.map +1 -0
- package/dist/tools/builtin/skills.js +195 -0
- package/dist/tools/builtin/skills.js.map +1 -0
- package/dist/tools/builtin/spawning.d.ts +33 -0
- package/dist/tools/builtin/spawning.d.ts.map +1 -0
- package/dist/tools/builtin/spawning.js +243 -0
- package/dist/tools/builtin/spawning.js.map +1 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
Autonomous AI agent system — powered by Skippy the Magnificent.
|
|
4
4
|
|
|
5
|
-
Sandboxed projects, multi-agent pipelines with dynamic team composition, 4-layer hybrid RAG memory, conversational chat interface (terminal, Telegram, Slack, WebSocket), REST API with auth, and a magnificently sarcastic AI overlord.
|
|
5
|
+
Sandboxed projects, multi-agent pipelines with dynamic team composition, 4-layer hybrid RAG memory, self-spawning agents with cross-project collaboration, heartbeat awareness loops, post-bloop reflection & learning, build-verify-integrate pipelines, conversational chat interface (terminal, Telegram, Slack, WebSocket), REST API with auth, and a magnificently sarcastic AI overlord.
|
|
6
6
|
|
|
7
7
|
## Install
|
|
8
8
|
|
|
@@ -88,6 +88,7 @@ Uptime: 2h 15m | Projects: 1 | Running: 0
|
|
|
88
88
|
```
|
|
89
89
|
|
|
90
90
|
Natural language or slash commands — Skippy understands both.
|
|
91
|
+
Skippy remembers your conversation — refer to previous messages and he'll follow along.
|
|
91
92
|
|
|
92
93
|
### Shortcuts
|
|
93
94
|
|
|
@@ -141,15 +142,15 @@ $ beercan run my-project "Add OAuth2 login with Google provider"
|
|
|
141
142
|
| `managed` | Manager → Coder → Manager | Planned execution |
|
|
142
143
|
| `full_team` | Manager → Coder → Reviewer → Tester | Production code |
|
|
143
144
|
|
|
144
|
-
##
|
|
145
|
+
## 16 Dynamic Roles
|
|
145
146
|
|
|
146
147
|
**5 built-in:** manager, coder, reviewer, tester, solo
|
|
147
148
|
|
|
148
|
-
**
|
|
149
|
+
**11 templates** (gatekeeper picks as needed): writer, researcher, analyst, data_processor, summarizer, planner, editor, devops, architect, heartbeat, verifier
|
|
149
150
|
|
|
150
151
|
The gatekeeper can also invent custom roles with LLM-generated prompts for unusual tasks.
|
|
151
152
|
|
|
152
|
-
## Built-in Tools
|
|
153
|
+
## 32 Built-in Tools
|
|
153
154
|
|
|
154
155
|
| Category | Tools |
|
|
155
156
|
|----------|-------|
|
|
@@ -157,9 +158,53 @@ The gatekeeper can also invent custom roles with LLM-generated prompts for unusu
|
|
|
157
158
|
| Web | `web_fetch` (Cloudflare Browser Rendering + native), `http_request` |
|
|
158
159
|
| Notification | `send_notification` (macOS desktop) |
|
|
159
160
|
| Memory | `memory_search`, `memory_store`, `memory_update`, `memory_link`, `memory_query_graph`, `memory_scratch` |
|
|
161
|
+
| Spawning | `spawn_bloop`, `get_bloop_result`, `list_child_bloops`, `list_projects`, `search_cross_project`, `search_previous_attempts` |
|
|
162
|
+
| Scheduling | `create_schedule`, `create_trigger`, `list_schedules`, `list_triggers`, `remove_schedule`, `remove_trigger` |
|
|
163
|
+
| Skills | `create_skill`, `update_skill`, `list_skills`, `update_project_context` |
|
|
164
|
+
| Integration | `register_tool_from_file`, `register_skill_from_bloop`, `verify_and_integrate` |
|
|
160
165
|
|
|
161
166
|
Plus custom tools from `~/.beercan/tools/` and MCP servers.
|
|
162
167
|
|
|
168
|
+
## Agentic Autonomy
|
|
169
|
+
|
|
170
|
+
BeerCan agents are self-directed, not just task-driven:
|
|
171
|
+
|
|
172
|
+
### Self-Spawning & Cross-Project
|
|
173
|
+
Agents decompose work into child bloops and delegate across projects:
|
|
174
|
+
```bash
|
|
175
|
+
# Agent can spawn sub-tasks automatically
|
|
176
|
+
beercan run my-project "Analyze codebase, spawn child bloops for each module"
|
|
177
|
+
|
|
178
|
+
# Cross-project: agents discover and leverage other projects' knowledge
|
|
179
|
+
```
|
|
180
|
+
Safety limits: max 5 children per bloop, max depth 3, cross-project access configurable per project.
|
|
181
|
+
|
|
182
|
+
### Self-Scheduling
|
|
183
|
+
Agents create their own schedules and triggers:
|
|
184
|
+
```
|
|
185
|
+
"I'll check back on this PR tomorrow" → agent creates a cron job
|
|
186
|
+
"Alert me if builds fail" → agent creates an event trigger
|
|
187
|
+
```
|
|
188
|
+
|
|
189
|
+
### Heartbeat
|
|
190
|
+
Per-project periodic awareness loops. Agent wakes up, checks a configurable checklist, surfaces findings or stays silent:
|
|
191
|
+
```bash
|
|
192
|
+
beercan heartbeat:configure my-project # Set checklist, interval, active hours
|
|
193
|
+
beercan daemon # Heartbeats run automatically
|
|
194
|
+
```
|
|
195
|
+
|
|
196
|
+
### Self-Education
|
|
197
|
+
Optional post-bloop reflection extracts lessons, patterns, and error resolutions into memory. Future bloops automatically receive relevant lessons from past work:
|
|
198
|
+
```bash
|
|
199
|
+
export BEERCAN_REFLECTION_ENABLED=true # Or set per-project
|
|
200
|
+
```
|
|
201
|
+
|
|
202
|
+
### Build-Verify-Integrate
|
|
203
|
+
Agents build tools, spawn verification bloops, and auto-register on APPROVE:
|
|
204
|
+
```
|
|
205
|
+
Agent builds csv-parser.js → spawns verifier → tests pass → tool registered → available to all future bloops
|
|
206
|
+
```
|
|
207
|
+
|
|
163
208
|
## Custom Tools
|
|
164
209
|
|
|
165
210
|
Drop a `.js` file in `~/.beercan/tools/` and it's auto-loaded on startup. Every agent gets access automatically — no template changes needed.
|
|
@@ -331,6 +376,15 @@ All providers share the same ChatBridge — slash commands and natural language
|
|
|
331
376
|
- **Interactive setup** — `beercan setup` wizard for first-time configuration
|
|
332
377
|
- **Skippy personality** — randomized phrase pools with 60+ responses across 13 categories
|
|
333
378
|
- **Status dashboard** — live web UI at `beercan-site/status.html`
|
|
379
|
+
- **Conversation memory** — Skippy remembers last 20 messages per chat channel for multi-turn context
|
|
380
|
+
- **Skills system** — workflow recipes with trigger matching and context injection (`~/.beercan/skills/`)
|
|
381
|
+
- **Auto version badge** — landing page auto-fetches latest version from npm
|
|
382
|
+
- **Self-spawning agents** — agents decompose work into child bloops with depth/count limits
|
|
383
|
+
- **Cross-project collaboration** — agents search and delegate across projects
|
|
384
|
+
- **Heartbeat awareness** — per-project periodic monitoring with active hours and suppression
|
|
385
|
+
- **Post-bloop reflection** — opt-in learning from completed bloops via lightweight Haiku analysis
|
|
386
|
+
- **Build-verify-integrate** — agents build tools, verify them, and auto-register for future use
|
|
387
|
+
- **Self-scheduling** — agents create their own cron jobs and event triggers
|
|
334
388
|
|
|
335
389
|
## CLI Reference
|
|
336
390
|
|
|
@@ -404,6 +458,10 @@ Set in `.env` file:
|
|
|
404
458
|
| `BEERCAN_TELEGRAM_TOKEN` | — | Telegram bot token |
|
|
405
459
|
| `BEERCAN_SLACK_TOKEN` | — | Slack bot token |
|
|
406
460
|
| `BEERCAN_SLACK_SIGNING_SECRET` | — | Slack signing secret |
|
|
461
|
+
| `BEERCAN_MAX_CHILDREN_PER_BLOOP` | `5` | Max child bloops per parent |
|
|
462
|
+
| `BEERCAN_MAX_SPAWN_DEPTH` | `3` | Max spawn chain depth |
|
|
463
|
+
| `BEERCAN_HEARTBEAT_INTERVAL` | `30` | Default heartbeat interval (min) |
|
|
464
|
+
| `BEERCAN_REFLECTION_ENABLED` | `false` | Enable post-bloop reflection |
|
|
407
465
|
|
|
408
466
|
## Architecture
|
|
409
467
|
|
package/dist/config.d.ts
CHANGED
|
@@ -16,6 +16,16 @@ declare const ConfigSchema: z.ZodObject<{
|
|
|
16
16
|
apiKey: z.ZodOptional<z.ZodString>;
|
|
17
17
|
notifyOnComplete: z.ZodDefault<z.ZodBoolean>;
|
|
18
18
|
notifyWebhookUrl: z.ZodOptional<z.ZodString>;
|
|
19
|
+
maxChildrenPerBloop: z.ZodDefault<z.ZodNumber>;
|
|
20
|
+
maxSpawnDepth: z.ZodDefault<z.ZodNumber>;
|
|
21
|
+
maxSchedulesPerProject: z.ZodDefault<z.ZodNumber>;
|
|
22
|
+
maxTriggersPerProject: z.ZodDefault<z.ZodNumber>;
|
|
23
|
+
minCronIntervalMinutes: z.ZodDefault<z.ZodNumber>;
|
|
24
|
+
heartbeatDefaultInterval: z.ZodDefault<z.ZodNumber>;
|
|
25
|
+
heartbeatActiveHours: z.ZodDefault<z.ZodString>;
|
|
26
|
+
heartbeatMinInterval: z.ZodDefault<z.ZodNumber>;
|
|
27
|
+
reflectionEnabled: z.ZodDefault<z.ZodBoolean>;
|
|
28
|
+
reflectionModel: z.ZodOptional<z.ZodString>;
|
|
19
29
|
}, "strip", z.ZodTypeAny, {
|
|
20
30
|
anthropicApiKey: string;
|
|
21
31
|
dataDir: string;
|
|
@@ -30,9 +40,19 @@ declare const ConfigSchema: z.ZodObject<{
|
|
|
30
40
|
webhookRateLimit: number;
|
|
31
41
|
webhookMaxBodySize: number;
|
|
32
42
|
notifyOnComplete: boolean;
|
|
43
|
+
maxChildrenPerBloop: number;
|
|
44
|
+
maxSpawnDepth: number;
|
|
45
|
+
maxSchedulesPerProject: number;
|
|
46
|
+
maxTriggersPerProject: number;
|
|
47
|
+
minCronIntervalMinutes: number;
|
|
48
|
+
heartbeatDefaultInterval: number;
|
|
49
|
+
heartbeatActiveHours: string;
|
|
50
|
+
heartbeatMinInterval: number;
|
|
51
|
+
reflectionEnabled: boolean;
|
|
33
52
|
logFile?: string | undefined;
|
|
34
53
|
apiKey?: string | undefined;
|
|
35
54
|
notifyWebhookUrl?: string | undefined;
|
|
55
|
+
reflectionModel?: string | undefined;
|
|
36
56
|
}, {
|
|
37
57
|
anthropicApiKey?: string | undefined;
|
|
38
58
|
dataDir?: string | undefined;
|
|
@@ -50,6 +70,16 @@ declare const ConfigSchema: z.ZodObject<{
|
|
|
50
70
|
apiKey?: string | undefined;
|
|
51
71
|
notifyOnComplete?: boolean | undefined;
|
|
52
72
|
notifyWebhookUrl?: string | undefined;
|
|
73
|
+
maxChildrenPerBloop?: number | undefined;
|
|
74
|
+
maxSpawnDepth?: number | undefined;
|
|
75
|
+
maxSchedulesPerProject?: number | undefined;
|
|
76
|
+
maxTriggersPerProject?: number | undefined;
|
|
77
|
+
minCronIntervalMinutes?: number | undefined;
|
|
78
|
+
heartbeatDefaultInterval?: number | undefined;
|
|
79
|
+
heartbeatActiveHours?: string | undefined;
|
|
80
|
+
heartbeatMinInterval?: number | undefined;
|
|
81
|
+
reflectionEnabled?: boolean | undefined;
|
|
82
|
+
reflectionModel?: string | undefined;
|
|
53
83
|
}>;
|
|
54
84
|
export type Config = z.infer<typeof ConfigSchema>;
|
|
55
85
|
export declare function getConfig(): Config;
|
package/dist/config.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAkBxB,QAAA,MAAM,YAAY
|
|
1
|
+
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAkBxB,QAAA,MAAM,YAAY;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EA+BhB,CAAC;AAEH,MAAM,MAAM,MAAM,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,YAAY,CAAC,CAAC;AAIlD,wBAAgB,SAAS,IAAI,MAAM,CA8DlC;AAED,yCAAyC;AACzC,wBAAgB,WAAW,IAAI,IAAI,CAElC;AAED,wBAAgB,aAAa,CAAC,WAAW,EAAE,MAAM,GAAG,MAAM,CAEzD"}
|
package/dist/config.js
CHANGED
|
@@ -30,6 +30,20 @@ const ConfigSchema = z.object({
|
|
|
30
30
|
apiKey: z.string().optional(),
|
|
31
31
|
notifyOnComplete: z.boolean().default(true),
|
|
32
32
|
notifyWebhookUrl: z.string().url().optional(),
|
|
33
|
+
// Phase 1: Self-spawning limits
|
|
34
|
+
maxChildrenPerBloop: z.number().default(5),
|
|
35
|
+
maxSpawnDepth: z.number().default(3),
|
|
36
|
+
// Phase 2: Self-scheduling limits
|
|
37
|
+
maxSchedulesPerProject: z.number().default(20),
|
|
38
|
+
maxTriggersPerProject: z.number().default(20),
|
|
39
|
+
minCronIntervalMinutes: z.number().default(5),
|
|
40
|
+
// Phase 3: Heartbeat
|
|
41
|
+
heartbeatDefaultInterval: z.number().default(30),
|
|
42
|
+
heartbeatActiveHours: z.string().default("08:00-22:00"),
|
|
43
|
+
heartbeatMinInterval: z.number().default(5),
|
|
44
|
+
// Phase 4: Reflection
|
|
45
|
+
reflectionEnabled: z.boolean().default(false),
|
|
46
|
+
reflectionModel: z.string().optional(),
|
|
33
47
|
});
|
|
34
48
|
let _config = null;
|
|
35
49
|
export function getConfig() {
|
|
@@ -65,6 +79,32 @@ export function getConfig() {
|
|
|
65
79
|
? process.env.BEERCAN_NOTIFY_ON_COMPLETE !== "false"
|
|
66
80
|
: undefined,
|
|
67
81
|
notifyWebhookUrl: process.env.BEERCAN_NOTIFY_WEBHOOK_URL,
|
|
82
|
+
maxChildrenPerBloop: process.env.BEERCAN_MAX_CHILDREN_PER_BLOOP
|
|
83
|
+
? parseInt(process.env.BEERCAN_MAX_CHILDREN_PER_BLOOP)
|
|
84
|
+
: undefined,
|
|
85
|
+
maxSpawnDepth: process.env.BEERCAN_MAX_SPAWN_DEPTH
|
|
86
|
+
? parseInt(process.env.BEERCAN_MAX_SPAWN_DEPTH)
|
|
87
|
+
: undefined,
|
|
88
|
+
maxSchedulesPerProject: process.env.BEERCAN_MAX_SCHEDULES_PER_PROJECT
|
|
89
|
+
? parseInt(process.env.BEERCAN_MAX_SCHEDULES_PER_PROJECT)
|
|
90
|
+
: undefined,
|
|
91
|
+
maxTriggersPerProject: process.env.BEERCAN_MAX_TRIGGERS_PER_PROJECT
|
|
92
|
+
? parseInt(process.env.BEERCAN_MAX_TRIGGERS_PER_PROJECT)
|
|
93
|
+
: undefined,
|
|
94
|
+
minCronIntervalMinutes: process.env.BEERCAN_MIN_CRON_INTERVAL
|
|
95
|
+
? parseInt(process.env.BEERCAN_MIN_CRON_INTERVAL)
|
|
96
|
+
: undefined,
|
|
97
|
+
heartbeatDefaultInterval: process.env.BEERCAN_HEARTBEAT_INTERVAL
|
|
98
|
+
? parseInt(process.env.BEERCAN_HEARTBEAT_INTERVAL)
|
|
99
|
+
: undefined,
|
|
100
|
+
heartbeatActiveHours: process.env.BEERCAN_HEARTBEAT_HOURS,
|
|
101
|
+
heartbeatMinInterval: process.env.BEERCAN_HEARTBEAT_MIN_INTERVAL
|
|
102
|
+
? parseInt(process.env.BEERCAN_HEARTBEAT_MIN_INTERVAL)
|
|
103
|
+
: undefined,
|
|
104
|
+
reflectionEnabled: process.env.BEERCAN_REFLECTION_ENABLED
|
|
105
|
+
? process.env.BEERCAN_REFLECTION_ENABLED === "true"
|
|
106
|
+
: undefined,
|
|
107
|
+
reflectionModel: process.env.BEERCAN_REFLECTION_MODEL,
|
|
68
108
|
});
|
|
69
109
|
}
|
|
70
110
|
return _config;
|
package/dist/config.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,IAAI,OAAO,EAAE,MAAM,QAAQ,CAAC;AAC3C,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,IAAI,MAAM,MAAM,CAAC;AACxB,OAAO,EAAE,MAAM,IAAI,CAAC;AACpB,OAAO,EAAE,aAAa,EAAE,MAAM,KAAK,CAAC;AAEpC,qEAAqE;AACrE,wDAAwD;AACxD,6BAA6B;AAC7B,cAAc;AACd,MAAM,OAAO,GAAG,OAAO,CAAC,GAAG,CAAC,gBAAgB,IAAI,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,OAAO,EAAE,EAAE,UAAU,CAAC,CAAC;AACpF,OAAO,CAAC,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,MAAM,CAAC,EAAE,CAAC,CAAC;AAE9C,MAAM,SAAS,GAAG,IAAI,CAAC,OAAO,CAAC,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;AAC/D,MAAM,WAAW,GAAG,IAAI,CAAC,OAAO,CAAC,SAAS,EAAE,IAAI,CAAC,CAAC;AAClD,OAAO,CAAC,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,MAAM,CAAC,EAAE,CAAC,CAAC;AAElD,OAAO,EAAE,CAAC,CAAC,WAAW;AAEtB,MAAM,YAAY,GAAG,CAAC,CAAC,MAAM,CAAC;IAC5B,eAAe,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,OAAO,CAAC,EAAE,CAAC;IACvC,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,OAAO,EAAE,EAAE,UAAU,CAAC,CAAC;IAChE,YAAY,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,OAAO,CAAC,mBAAmB,CAAC;IACrD,UAAU,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,OAAO,CAAC,iBAAiB,CAAC;IACjD,eAAe,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,OAAO,CAAC,2BAA2B,CAAC;IAChE,kBAAkB,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,OAAO,CAAC,EAAE,CAAC;IAC1C,cAAc,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,OAAO,CAAC,OAAO,CAAC;IAC3C,aAAa,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,OAAO,CAAC,CAAC,CAAC;IACpC,kBAAkB,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,OAAO,CAAC,OAAO,CAAC;IAC/C,QAAQ,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC,MAAM,CAAC;IACpE,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IAC9B,gBAAgB,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,OAAO,CAAC,EAAE,CAAC;IACxC,kBAAkB,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,OAAO,CAAC,SAAS,CAAC;IACjD,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IAC7B,gBAAgB,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC;IAC3C,gBAAgB,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,QAAQ,EAAE;
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import type { BeerCanDB } from "../storage/database.js";
|
|
2
|
+
import type { Project } from "../schemas.js";
|
|
3
|
+
export interface HeartbeatConfig {
|
|
4
|
+
enabled: boolean;
|
|
5
|
+
intervalMinutes: number;
|
|
6
|
+
activeHours?: {
|
|
7
|
+
start: string;
|
|
8
|
+
end: string;
|
|
9
|
+
};
|
|
10
|
+
checklist: string[];
|
|
11
|
+
suppressIfEmpty: boolean;
|
|
12
|
+
}
|
|
13
|
+
export interface HeartbeatExecutor {
|
|
14
|
+
runBloop(opts: {
|
|
15
|
+
projectSlug: string;
|
|
16
|
+
goal: string;
|
|
17
|
+
team?: string;
|
|
18
|
+
extraContext?: string;
|
|
19
|
+
}): Promise<any>;
|
|
20
|
+
}
|
|
21
|
+
export interface HeartbeatEventPublisher {
|
|
22
|
+
publish(event: {
|
|
23
|
+
type: string;
|
|
24
|
+
projectSlug: string;
|
|
25
|
+
source: string;
|
|
26
|
+
data: Record<string, unknown>;
|
|
27
|
+
timestamp: string;
|
|
28
|
+
}): void;
|
|
29
|
+
}
|
|
30
|
+
export declare class HeartbeatManager {
|
|
31
|
+
private db;
|
|
32
|
+
private executor;
|
|
33
|
+
private publisher;
|
|
34
|
+
private intervals;
|
|
35
|
+
private running;
|
|
36
|
+
constructor(db: BeerCanDB, executor: HeartbeatExecutor, publisher?: HeartbeatEventPublisher);
|
|
37
|
+
/** Load all projects and start heartbeats for those with config */
|
|
38
|
+
init(): void;
|
|
39
|
+
/** Stop all heartbeat intervals */
|
|
40
|
+
stop(): void;
|
|
41
|
+
/** Start heartbeat for a single project */
|
|
42
|
+
startProject(slug: string, config?: HeartbeatConfig): void;
|
|
43
|
+
/** Stop heartbeat for a single project */
|
|
44
|
+
stopProject(slug: string): void;
|
|
45
|
+
/** Run a single heartbeat check */
|
|
46
|
+
runHeartbeat(project: Project, config: HeartbeatConfig): Promise<void>;
|
|
47
|
+
/** Get the heartbeat config from a project's context */
|
|
48
|
+
getHeartbeatConfig(project: Project): HeartbeatConfig | null;
|
|
49
|
+
buildHeartbeatGoal(project: Project, config: HeartbeatConfig): string;
|
|
50
|
+
isInActiveHours(hours: {
|
|
51
|
+
start: string;
|
|
52
|
+
end: string;
|
|
53
|
+
}): boolean;
|
|
54
|
+
private parseTimeToMinutes;
|
|
55
|
+
private parseActiveHours;
|
|
56
|
+
}
|
|
57
|
+
//# sourceMappingURL=heartbeat.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"heartbeat.d.ts","sourceRoot":"","sources":["../../src/core/heartbeat.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,wBAAwB,CAAC;AACxD,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,eAAe,CAAC;AAI7C,MAAM,WAAW,eAAe;IAC9B,OAAO,EAAE,OAAO,CAAC;IACjB,eAAe,EAAE,MAAM,CAAC;IACxB,WAAW,CAAC,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,GAAG,EAAE,MAAM,CAAA;KAAE,CAAC;IAC7C,SAAS,EAAE,MAAM,EAAE,CAAC;IACpB,eAAe,EAAE,OAAO,CAAC;CAC1B;AAID,MAAM,WAAW,iBAAiB;IAChC,QAAQ,CAAC,IAAI,EAAE;QACb,WAAW,EAAE,MAAM,CAAC;QACpB,IAAI,EAAE,MAAM,CAAC;QACb,IAAI,CAAC,EAAE,MAAM,CAAC;QACd,YAAY,CAAC,EAAE,MAAM,CAAC;KACvB,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC;CAClB;AAED,MAAM,WAAW,uBAAuB;IACtC,OAAO,CAAC,KAAK,EAAE;QACb,IAAI,EAAE,MAAM,CAAC;QACb,WAAW,EAAE,MAAM,CAAC;QACpB,MAAM,EAAE,MAAM,CAAC;QACf,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;QAC9B,SAAS,EAAE,MAAM,CAAC;KACnB,GAAG,IAAI,CAAC;CACV;AAED,qBAAa,gBAAgB;IAC3B,OAAO,CAAC,EAAE,CAAY;IACtB,OAAO,CAAC,QAAQ,CAAoB;IACpC,OAAO,CAAC,SAAS,CAAiC;IAClD,OAAO,CAAC,SAAS,CAAqD;IACtE,OAAO,CAAC,OAAO,CAAS;gBAGtB,EAAE,EAAE,SAAS,EACb,QAAQ,EAAE,iBAAiB,EAC3B,SAAS,CAAC,EAAE,uBAAuB;IAOrC,mEAAmE;IACnE,IAAI,IAAI,IAAI;IAkBZ,mCAAmC;IACnC,IAAI,IAAI,IAAI;IASZ,2CAA2C;IAC3C,YAAY,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,eAAe,GAAG,IAAI;IAqB1D,0CAA0C;IAC1C,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI;IAQ/B,mCAAmC;IAC7B,YAAY,CAAC,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,eAAe,GAAG,OAAO,CAAC,IAAI,CAAC;IA0D5E,wDAAwD;IACxD,kBAAkB,CAAC,OAAO,EAAE,OAAO,GAAG,eAAe,GAAG,IAAI;IAsB5D,kBAAkB,CAAC,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,eAAe,GAAG,MAAM;IAYrE,eAAe,CAAC,KAAK,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,GAAG,EAAE,MAAM,CAAA;KAAE,GAAG,OAAO;IAkB/D,OAAO,CAAC,kBAAkB;IAS1B,OAAO,CAAC,gBAAgB;CAKzB"}
|
|
@@ -0,0 +1,179 @@
|
|
|
1
|
+
import { getConfig } from "../config.js";
|
|
2
|
+
export class HeartbeatManager {
|
|
3
|
+
db;
|
|
4
|
+
executor;
|
|
5
|
+
publisher;
|
|
6
|
+
intervals = new Map();
|
|
7
|
+
running = false;
|
|
8
|
+
constructor(db, executor, publisher) {
|
|
9
|
+
this.db = db;
|
|
10
|
+
this.executor = executor;
|
|
11
|
+
this.publisher = publisher ?? null;
|
|
12
|
+
}
|
|
13
|
+
/** Load all projects and start heartbeats for those with config */
|
|
14
|
+
init() {
|
|
15
|
+
this.running = true;
|
|
16
|
+
const projects = this.db.listProjects();
|
|
17
|
+
let started = 0;
|
|
18
|
+
for (const project of projects) {
|
|
19
|
+
const config = this.getHeartbeatConfig(project);
|
|
20
|
+
if (config?.enabled) {
|
|
21
|
+
this.startProject(project.slug, config);
|
|
22
|
+
started++;
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
if (started > 0) {
|
|
26
|
+
console.log(`[heartbeat] Started ${started} project heartbeats`);
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
/** Stop all heartbeat intervals */
|
|
30
|
+
stop() {
|
|
31
|
+
this.running = false;
|
|
32
|
+
for (const [slug, interval] of this.intervals) {
|
|
33
|
+
clearInterval(interval);
|
|
34
|
+
this.intervals.delete(slug);
|
|
35
|
+
}
|
|
36
|
+
console.log("[heartbeat] Stopped all heartbeats");
|
|
37
|
+
}
|
|
38
|
+
/** Start heartbeat for a single project */
|
|
39
|
+
startProject(slug, config) {
|
|
40
|
+
if (this.intervals.has(slug))
|
|
41
|
+
return; // Already running
|
|
42
|
+
const project = this.db.getProjectBySlug(slug);
|
|
43
|
+
if (!project)
|
|
44
|
+
return;
|
|
45
|
+
const hbConfig = config ?? this.getHeartbeatConfig(project);
|
|
46
|
+
if (!hbConfig?.enabled)
|
|
47
|
+
return;
|
|
48
|
+
const globalConfig = getConfig();
|
|
49
|
+
const intervalMs = Math.max(hbConfig.intervalMinutes, globalConfig.heartbeatMinInterval) * 60 * 1000;
|
|
50
|
+
const interval = setInterval(() => {
|
|
51
|
+
this.runHeartbeat(project, hbConfig).catch((err) => {
|
|
52
|
+
console.error(`[heartbeat] Error for ${slug}: ${err.message}`);
|
|
53
|
+
});
|
|
54
|
+
}, intervalMs);
|
|
55
|
+
this.intervals.set(slug, interval);
|
|
56
|
+
}
|
|
57
|
+
/** Stop heartbeat for a single project */
|
|
58
|
+
stopProject(slug) {
|
|
59
|
+
const interval = this.intervals.get(slug);
|
|
60
|
+
if (interval) {
|
|
61
|
+
clearInterval(interval);
|
|
62
|
+
this.intervals.delete(slug);
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
/** Run a single heartbeat check */
|
|
66
|
+
async runHeartbeat(project, config) {
|
|
67
|
+
// Check active hours
|
|
68
|
+
if (config.activeHours && !this.isInActiveHours(config.activeHours)) {
|
|
69
|
+
return;
|
|
70
|
+
}
|
|
71
|
+
// Build goal from checklist
|
|
72
|
+
const goal = this.buildHeartbeatGoal(project, config);
|
|
73
|
+
const extraContext = [
|
|
74
|
+
"This is an automated heartbeat check. Be concise.",
|
|
75
|
+
"If you find nothing noteworthy and everything looks fine, respond exactly with: HEARTBEAT_EMPTY",
|
|
76
|
+
"If you find something worth reporting, provide a brief summary of your findings.",
|
|
77
|
+
].join("\n");
|
|
78
|
+
try {
|
|
79
|
+
const bloop = await this.executor.runBloop({
|
|
80
|
+
projectSlug: project.slug,
|
|
81
|
+
goal,
|
|
82
|
+
team: "solo",
|
|
83
|
+
extraContext,
|
|
84
|
+
});
|
|
85
|
+
// Check if result indicates nothing noteworthy
|
|
86
|
+
const resultStr = bloop.result
|
|
87
|
+
? typeof bloop.result === "string"
|
|
88
|
+
? bloop.result
|
|
89
|
+
: JSON.stringify(bloop.result)
|
|
90
|
+
: "";
|
|
91
|
+
const isEmpty = resultStr.includes("HEARTBEAT_EMPTY");
|
|
92
|
+
if (isEmpty && config.suppressIfEmpty) {
|
|
93
|
+
// Silent — don't notify
|
|
94
|
+
return;
|
|
95
|
+
}
|
|
96
|
+
// Publish heartbeat result event
|
|
97
|
+
if (this.publisher) {
|
|
98
|
+
this.publisher.publish({
|
|
99
|
+
type: "heartbeat:result",
|
|
100
|
+
projectSlug: project.slug,
|
|
101
|
+
source: "heartbeat",
|
|
102
|
+
data: {
|
|
103
|
+
bloopId: bloop.id,
|
|
104
|
+
goal,
|
|
105
|
+
result: resultStr.slice(0, 2000),
|
|
106
|
+
empty: isEmpty,
|
|
107
|
+
tokensUsed: bloop.tokensUsed,
|
|
108
|
+
},
|
|
109
|
+
timestamp: new Date().toISOString(),
|
|
110
|
+
});
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
catch (err) {
|
|
114
|
+
console.error(`[heartbeat] Failed for ${project.slug}: ${err.message}`);
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
/** Get the heartbeat config from a project's context */
|
|
118
|
+
getHeartbeatConfig(project) {
|
|
119
|
+
const ctx = project.context?.heartbeat;
|
|
120
|
+
if (!ctx || typeof ctx !== "object")
|
|
121
|
+
return null;
|
|
122
|
+
const config = getConfig();
|
|
123
|
+
const hb = ctx;
|
|
124
|
+
return {
|
|
125
|
+
enabled: hb.enabled === true,
|
|
126
|
+
intervalMinutes: typeof hb.intervalMinutes === "number"
|
|
127
|
+
? hb.intervalMinutes
|
|
128
|
+
: config.heartbeatDefaultInterval,
|
|
129
|
+
activeHours: hb.activeHours && typeof hb.activeHours === "object"
|
|
130
|
+
? hb.activeHours
|
|
131
|
+
: this.parseActiveHours(config.heartbeatActiveHours),
|
|
132
|
+
checklist: Array.isArray(hb.checklist) ? hb.checklist : [],
|
|
133
|
+
suppressIfEmpty: hb.suppressIfEmpty !== false, // default true
|
|
134
|
+
};
|
|
135
|
+
}
|
|
136
|
+
// ── Internal ──────────────────────────────────────────────
|
|
137
|
+
buildHeartbeatGoal(project, config) {
|
|
138
|
+
if (config.checklist.length === 0) {
|
|
139
|
+
return `Heartbeat check for ${project.name}: Review project health, check for any issues or pending work.`;
|
|
140
|
+
}
|
|
141
|
+
const items = config.checklist
|
|
142
|
+
.map((item, i) => `${i + 1}. ${item}`)
|
|
143
|
+
.join("; ");
|
|
144
|
+
return `Heartbeat check for ${project.name}: ${items}`;
|
|
145
|
+
}
|
|
146
|
+
isInActiveHours(hours) {
|
|
147
|
+
const now = new Date();
|
|
148
|
+
const currentMinutes = now.getHours() * 60 + now.getMinutes();
|
|
149
|
+
const startMinutes = this.parseTimeToMinutes(hours.start);
|
|
150
|
+
const endMinutes = this.parseTimeToMinutes(hours.end);
|
|
151
|
+
if (startMinutes === null || endMinutes === null)
|
|
152
|
+
return true; // Invalid → allow
|
|
153
|
+
if (startMinutes <= endMinutes) {
|
|
154
|
+
// Normal range: e.g., 08:00 - 22:00
|
|
155
|
+
return currentMinutes >= startMinutes && currentMinutes <= endMinutes;
|
|
156
|
+
}
|
|
157
|
+
else {
|
|
158
|
+
// Overnight range: e.g., 22:00 - 06:00
|
|
159
|
+
return currentMinutes >= startMinutes || currentMinutes <= endMinutes;
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
parseTimeToMinutes(time) {
|
|
163
|
+
const match = time.match(/^(\d{1,2}):(\d{2})$/);
|
|
164
|
+
if (!match)
|
|
165
|
+
return null;
|
|
166
|
+
const hours = parseInt(match[1]);
|
|
167
|
+
const minutes = parseInt(match[2]);
|
|
168
|
+
if (hours < 0 || hours > 23 || minutes < 0 || minutes > 59)
|
|
169
|
+
return null;
|
|
170
|
+
return hours * 60 + minutes;
|
|
171
|
+
}
|
|
172
|
+
parseActiveHours(str) {
|
|
173
|
+
const parts = str.split("-");
|
|
174
|
+
if (parts.length !== 2)
|
|
175
|
+
return undefined;
|
|
176
|
+
return { start: parts[0].trim(), end: parts[1].trim() };
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
//# sourceMappingURL=heartbeat.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"heartbeat.js","sourceRoot":"","sources":["../../src/core/heartbeat.ts"],"names":[],"mappings":"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"}
|
package/dist/core/job-queue.d.ts
CHANGED
|
@@ -7,6 +7,7 @@ export interface EnqueueOptions {
|
|
|
7
7
|
source?: "manual" | "cron" | "event";
|
|
8
8
|
sourceId?: string;
|
|
9
9
|
extraContext?: string;
|
|
10
|
+
parentBloopId?: string;
|
|
10
11
|
}
|
|
11
12
|
export interface Job {
|
|
12
13
|
id: string;
|
|
@@ -18,6 +19,7 @@ export interface Job {
|
|
|
18
19
|
source: string;
|
|
19
20
|
sourceId: string | null;
|
|
20
21
|
extraContext: string | null;
|
|
22
|
+
parentBloopId: string | null;
|
|
21
23
|
bloopId: string | null;
|
|
22
24
|
error: string | null;
|
|
23
25
|
createdAt: string;
|
|
@@ -43,6 +45,7 @@ export declare class JobQueue {
|
|
|
43
45
|
goal: string;
|
|
44
46
|
team: string;
|
|
45
47
|
extraContext?: string;
|
|
48
|
+
parentBloopId?: string;
|
|
46
49
|
signal?: AbortSignal;
|
|
47
50
|
}) => Promise<{
|
|
48
51
|
id: string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"job-queue.d.ts","sourceRoot":"","sources":["../../src/core/job-queue.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,wBAAwB,CAAC;AAMxD,MAAM,WAAW,cAAc;IAC7B,WAAW,EAAE,MAAM,CAAC;IACpB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,MAAM,CAAC,EAAE,QAAQ,GAAG,MAAM,GAAG,OAAO,CAAC;IACrC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,YAAY,CAAC,EAAE,MAAM,CAAC;
|
|
1
|
+
{"version":3,"file":"job-queue.d.ts","sourceRoot":"","sources":["../../src/core/job-queue.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,wBAAwB,CAAC;AAMxD,MAAM,WAAW,cAAc;IAC7B,WAAW,EAAE,MAAM,CAAC;IACpB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,MAAM,CAAC,EAAE,QAAQ,GAAG,MAAM,GAAG,OAAO,CAAC;IACrC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AAED,MAAM,WAAW,GAAG;IAClB,EAAE,EAAE,MAAM,CAAC;IACX,WAAW,EAAE,MAAM,CAAC;IACpB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,SAAS,GAAG,SAAS,GAAG,WAAW,GAAG,QAAQ,GAAG,SAAS,GAAG,WAAW,CAAC;IACjF,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,aAAa,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;CAC5B;AAED,MAAM,WAAW,QAAQ;IACvB,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,qBAAa,QAAQ;IACnB,OAAO,CAAC,OAAO,CAAoC;IACnD,OAAO,CAAC,gBAAgB,CAAsC;IAC9D,OAAO,CAAC,aAAa,CAAS;IAC9B,OAAO,CAAC,EAAE,CAAY;IACtB,OAAO,CAAC,QAAQ,CAA8L;gBAElM,EAAE,EAAE,SAAS,EAAE,aAAa,EAAE,MAAM;IAKhD,wEAAwE;IACxE,WAAW,CAAC,EAAE,EAAE,CAAC,IAAI,EAAE;QAAE,WAAW,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,YAAY,CAAC,EAAE,MAAM,CAAC;QAAC,aAAa,CAAC,EAAE,MAAM,CAAC;QAAC,MAAM,CAAC,EAAE,WAAW,CAAA;KAAE,KAAK,OAAO,CAAC;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC,GAAG,IAAI;IAIlM,yCAAyC;IACzC,OAAO,CAAC,IAAI,EAAE,cAAc,GAAG,MAAM;IAiCrC,+DAA+D;IAC/D,WAAW,IAAI,IAAI;YAyBL,UAAU;IAqCxB,uCAAuC;IACvC,SAAS,CAAC,KAAK,EAAE,MAAM,GAAG;QAAE,SAAS,EAAE,OAAO,CAAC;QAAC,MAAM,CAAC,EAAE,MAAM,CAAC;QAAC,MAAM,CAAC,EAAE,MAAM,CAAA;KAAE;IA+BlF,4BAA4B;IAC5B,QAAQ,IAAI,QAAQ;IAIpB,gDAAgD;IAChD,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,EAAE,KAAK,SAAK,GAAG,GAAG,EAAE;IAI5C,yDAAyD;IACnD,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;CAmB7B"}
|
package/dist/core/job-queue.js
CHANGED
|
@@ -29,6 +29,7 @@ export class JobQueue {
|
|
|
29
29
|
source: opts.source ?? "manual",
|
|
30
30
|
sourceId: opts.sourceId ?? null,
|
|
31
31
|
extraContext: opts.extraContext ?? null,
|
|
32
|
+
parentBloopId: opts.parentBloopId ?? null,
|
|
32
33
|
bloopId: null,
|
|
33
34
|
error: null,
|
|
34
35
|
createdAt: now,
|
|
@@ -75,6 +76,7 @@ export class JobQueue {
|
|
|
75
76
|
goal: job.goal,
|
|
76
77
|
team: job.team,
|
|
77
78
|
extraContext: job.extraContext ?? undefined,
|
|
79
|
+
parentBloopId: job.parentBloopId ?? undefined,
|
|
78
80
|
signal: controller.signal,
|
|
79
81
|
});
|
|
80
82
|
this.db.updateJob(job.id, {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"job-queue.js","sourceRoot":"","sources":["../../src/core/job-queue.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,EAAE,IAAI,IAAI,EAAE,MAAM,MAAM,CAAC;AAClC,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"job-queue.js","sourceRoot":"","sources":["../../src/core/job-queue.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import Anthropic from "@anthropic-ai/sdk";
|
|
2
|
+
import type { MemoryManager } from "../memory/index.js";
|
|
3
|
+
import type { BeerCanDB } from "../storage/database.js";
|
|
4
|
+
import type { Bloop, Project } from "../schemas.js";
|
|
5
|
+
export interface ReflectionItem {
|
|
6
|
+
title: string;
|
|
7
|
+
content: string;
|
|
8
|
+
}
|
|
9
|
+
export interface ReflectionResult {
|
|
10
|
+
lessons: ReflectionItem[];
|
|
11
|
+
patterns: ReflectionItem[];
|
|
12
|
+
errors: ReflectionItem[];
|
|
13
|
+
suggestions: string[];
|
|
14
|
+
}
|
|
15
|
+
export declare class ReflectionEngine {
|
|
16
|
+
private client;
|
|
17
|
+
private memory;
|
|
18
|
+
private db;
|
|
19
|
+
constructor(client: Anthropic, memory: MemoryManager, db: BeerCanDB);
|
|
20
|
+
/**
|
|
21
|
+
* Run a lightweight reflection on a completed/failed bloop.
|
|
22
|
+
* Single Haiku call with structured output.
|
|
23
|
+
*/
|
|
24
|
+
reflect(bloop: Bloop, projectSlug: string): Promise<ReflectionResult | null>;
|
|
25
|
+
/**
|
|
26
|
+
* Periodic consolidation: merge duplicate reflection memories,
|
|
27
|
+
* strengthen high-confidence insights, prune low-value ones.
|
|
28
|
+
*/
|
|
29
|
+
consolidate(projectSlug: string): Promise<{
|
|
30
|
+
merged: number;
|
|
31
|
+
pruned: number;
|
|
32
|
+
}>;
|
|
33
|
+
private buildReflectionSummary;
|
|
34
|
+
private storeLessons;
|
|
35
|
+
private updateKnowledgeGraph;
|
|
36
|
+
}
|
|
37
|
+
export declare function shouldReflect(bloop: Bloop, project: Project): boolean;
|
|
38
|
+
//# sourceMappingURL=reflection.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"reflection.d.ts","sourceRoot":"","sources":["../../src/core/reflection.ts"],"names":[],"mappings":"AAAA,OAAO,SAAS,MAAM,mBAAmB,CAAC;AAE1C,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AACxD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,wBAAwB,CAAC;AACxD,OAAO,KAAK,EAAE,KAAK,EAAE,OAAO,EAAE,MAAM,eAAe,CAAC;AAIpD,MAAM,WAAW,cAAc;IAC7B,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,gBAAgB;IAC/B,OAAO,EAAE,cAAc,EAAE,CAAC;IAC1B,QAAQ,EAAE,cAAc,EAAE,CAAC;IAC3B,MAAM,EAAE,cAAc,EAAE,CAAC;IACzB,WAAW,EAAE,MAAM,EAAE,CAAC;CACvB;AA0DD,qBAAa,gBAAgB;IAC3B,OAAO,CAAC,MAAM,CAAY;IAC1B,OAAO,CAAC,MAAM,CAAgB;IAC9B,OAAO,CAAC,EAAE,CAAY;gBAEV,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,aAAa,EAAE,EAAE,EAAE,SAAS;IAMnE;;;OAGG;IACG,OAAO,CAAC,KAAK,EAAE,KAAK,EAAE,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,gBAAgB,GAAG,IAAI,CAAC;IAyClF;;;OAGG;IACG,WAAW,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC;IAqFnF,OAAO,CAAC,sBAAsB;YAgChB,YAAY;YA6CZ,oBAAoB;CAkDnC;AAID,wBAAgB,aAAa,CAAC,KAAK,EAAE,KAAK,EAAE,OAAO,EAAE,OAAO,GAAG,OAAO,CA0BrE"}
|