@johpaz/hive-sdk 0.0.14 → 0.0.16
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/CHANGELOG.md +64 -0
- package/README.md +280 -0
- package/docs/API-AGENTS.md +316 -0
- package/docs/API-CONTEXT-COMPILER.md +252 -0
- package/docs/API-DAG-SCHEDULER.md +273 -0
- package/docs/API-TOOLS-SKILLS-CHANNELS.md +350 -0
- package/docs/API-WORKERS-EVENTS.md +299 -0
- package/docs/INDEX.md +190 -0
- package/docs/README.md +161 -0
- package/docs/TEMPLATE-HIVE-APP.md +360 -0
- package/package.json +60 -104
- package/packages/cli/bin/hive +2 -0
- package/packages/cli/package.json +17 -0
- package/packages/cli/src/commands/add-skill.ts +42 -0
- package/packages/cli/src/commands/add-tool.ts +45 -0
- package/packages/cli/src/commands/add-worker.ts +49 -0
- package/packages/cli/src/commands/create-app-utils.ts +32 -0
- package/packages/cli/src/commands/create-app.test.ts +151 -0
- package/packages/cli/src/commands/create-app.ts +35 -0
- package/packages/cli/src/commands/init.ts +56 -0
- package/packages/cli/src/commands/run.ts +45 -0
- package/packages/cli/src/commands/test.ts +42 -0
- package/packages/cli/src/commands/trace.ts +55 -0
- package/packages/cli/src/index.ts +59 -0
- package/packages/cli/templates/hive-app/.env.example +17 -0
- package/packages/cli/templates/hive-app/docker-compose.yml +20 -0
- package/packages/cli/templates/hive-app/hive.config.ts +19 -0
- package/packages/cli/templates/hive-app/package.json +16 -0
- package/packages/cli/templates/hive-app/src/agents/coordinator.ts +9 -0
- package/packages/cli/templates/hive-app/src/main.ts +56 -0
- package/packages/core/package.json +58 -0
- package/packages/core/src/ace/Curator.ts +158 -0
- package/packages/core/src/ace/Reflector.ts +200 -0
- package/packages/core/src/ace/Tracer.ts +100 -0
- package/packages/core/src/ace/index.ts +4 -0
- package/packages/core/src/agent/AgentRunner.ts +699 -0
- package/packages/core/src/agent/Compaction.ts +221 -0
- package/packages/core/src/agent/ContextCompiler.ts +567 -0
- package/packages/core/src/agent/ContextGuard.ts +91 -0
- package/packages/core/src/agent/ConversationStore.ts +244 -0
- package/packages/core/src/agent/Hooks.ts +166 -0
- package/packages/core/src/agent/NativeTools.ts +31 -0
- package/packages/core/src/agent/PromptBuilder.ts +169 -0
- package/packages/core/src/agent/Service.ts +267 -0
- package/packages/core/src/agent/StuckLoop.ts +133 -0
- package/packages/core/src/agent/index.ts +12 -0
- package/packages/core/src/agent/providers/LLMClient.ts +149 -0
- package/packages/core/src/agent/providers/anthropic.ts +212 -0
- package/packages/core/src/agent/providers/gemini.ts +215 -0
- package/packages/core/src/agent/providers/index.ts +199 -0
- package/packages/core/src/agent/providers/interface.ts +195 -0
- package/packages/core/src/agent/providers/ollama.ts +175 -0
- package/packages/core/src/agent/providers/openai-compat.ts +231 -0
- package/packages/core/src/agent/selectors/PlaybookSelector.ts +147 -0
- package/packages/core/src/agent/selectors/SkillSelector.ts +478 -0
- package/packages/core/src/agent/selectors/ToolSelector.ts +577 -0
- package/packages/core/src/agent/selectors/index.ts +6 -0
- package/packages/core/src/api/createAgent.test.ts +48 -0
- package/packages/core/src/api/createAgent.ts +122 -0
- package/packages/core/src/api/index.ts +2 -0
- package/packages/core/src/auth/auth.ts +108 -0
- package/packages/core/src/auth/index.ts +1 -0
- package/packages/core/src/canvas/CanvasManager.ts +390 -0
- package/packages/core/src/canvas/a2ui-tools.ts +255 -0
- package/packages/core/src/canvas/canvas-tools.ts +448 -0
- package/packages/core/src/canvas/canvas.test.ts +32 -0
- package/packages/core/src/canvas/emitter.ts +149 -0
- package/packages/core/src/canvas/index.ts +3 -0
- package/packages/core/src/channels/base.ts +154 -0
- package/packages/core/src/channels/channels.test.ts +18 -0
- package/packages/core/src/channels/discord.ts +273 -0
- package/packages/core/src/channels/index.ts +7 -0
- package/packages/core/src/channels/manager.ts +450 -0
- package/packages/core/src/channels/slack.ts +323 -0
- package/packages/core/src/channels/telegram.ts +612 -0
- package/packages/core/src/channels/webchat.ts +139 -0
- package/packages/core/src/channels/whatsapp.ts +548 -0
- package/packages/core/src/config/index.ts +2 -0
- package/packages/core/src/config/loader.ts +554 -0
- package/packages/core/src/ethics/EthicsGuard.test.ts +54 -0
- package/packages/core/src/ethics/EthicsGuard.ts +66 -0
- package/packages/core/src/ethics/index.ts +2 -0
- package/packages/core/src/events/agent-bus.ts +460 -0
- package/packages/core/src/events/event-bus.ts +169 -0
- package/packages/core/src/gateway/channel-notify.ts +37 -0
- package/packages/core/src/gateway/gateway.test.ts +38 -0
- package/packages/core/src/gateway/index.ts +2 -0
- package/packages/core/src/gateway/server.ts +139 -0
- package/packages/core/src/heartbeat/index.ts +157 -0
- package/packages/core/src/index.ts +81 -0
- package/packages/core/src/mcp/MCPClient.ts +439 -0
- package/packages/core/src/mcp/MCPToolAdapter.ts +176 -0
- package/packages/core/src/mcp/config.ts +13 -0
- package/packages/core/src/mcp/hot-reload.ts +147 -0
- package/packages/core/src/mcp/index.ts +11 -0
- package/packages/core/src/mcp/logger.ts +42 -0
- package/packages/core/src/mcp/singleton.ts +21 -0
- package/packages/core/src/mcp/transports/index.ts +67 -0
- package/packages/core/src/mcp/transports/sse.ts +241 -0
- package/packages/core/src/mcp/transports/websocket.ts +159 -0
- package/packages/core/src/memory/Scratchpad.test.ts +47 -0
- package/packages/core/src/memory/Scratchpad.ts +37 -0
- package/packages/core/src/memory/Storage.ts +6 -0
- package/packages/core/src/memory/index.ts +2 -0
- package/packages/core/src/multimodal/VisionService.ts +293 -0
- package/packages/core/src/multimodal/index.ts +2 -0
- package/packages/core/src/multimodal/types.ts +28 -0
- package/packages/core/src/multimodal/vision-service.ts +283 -0
- package/packages/core/src/plugins/api.ts +128 -0
- package/packages/core/src/plugins/index.ts +2 -0
- package/packages/core/src/plugins/loader.ts +365 -0
- package/packages/core/src/resilience/circuit-breaker.ts +225 -0
- package/packages/core/src/scheduler/CronScheduler.ts +699 -0
- package/packages/core/src/scheduler/dag/AgentExecutor.ts +53 -0
- package/packages/core/src/scheduler/dag/DAGScheduler.ts +250 -0
- package/packages/core/src/scheduler/dag/EventBridge.ts +122 -0
- package/packages/core/src/scheduler/dag/TaskGraph.ts +192 -0
- package/packages/core/src/scheduler/dag/TaskNode.ts +97 -0
- package/packages/core/src/scheduler/dag/TaskResult.ts +22 -0
- package/packages/core/src/scheduler/dag/errors.ts +37 -0
- package/packages/core/src/scheduler/dag/index.ts +26 -0
- package/packages/core/src/scheduler/dag/presets/ResearchPreset.ts +97 -0
- package/packages/core/src/scheduler/dag/strategies/ParallelStrategy.ts +21 -0
- package/packages/core/src/scheduler/dag/strategies/PriorityStrategy.ts +46 -0
- package/packages/core/src/scheduler/index.ts +22 -0
- package/packages/core/src/scheduler/integration.ts +237 -0
- package/packages/core/src/scheduler/scheduler.test.ts +19 -0
- package/packages/core/src/scheduler/types.ts +164 -0
- package/packages/core/src/security/Pairing.ts +250 -0
- package/packages/core/src/security/RateLimit.ts +270 -0
- package/packages/core/src/security/google-chat.ts +269 -0
- package/packages/core/src/security/index.ts +192 -0
- package/packages/core/src/security/rate-limit.ts +270 -0
- package/packages/core/src/security/signal.ts +321 -0
- package/packages/core/src/skills/SkillLoader.ts +388 -0
- package/packages/core/src/skills/bundled-data.generated.ts +3332 -0
- package/packages/core/src/skills/defineSkill.ts +18 -0
- package/packages/core/src/skills/index.ts +4 -0
- package/packages/core/src/state/index.ts +2 -0
- package/packages/core/src/state/store.ts +312 -0
- package/packages/core/src/storage/SQLiteStorage.ts +407 -0
- package/packages/core/src/storage/crypto.ts +233 -0
- package/packages/core/src/storage/index.ts +10 -0
- package/packages/core/src/storage/onboarding.ts +1603 -0
- package/packages/core/src/storage/schema.ts +689 -0
- package/packages/core/src/storage/seed.ts +740 -0
- package/packages/core/src/storage/storage.test.ts +37 -0
- package/packages/core/src/storage/usage.ts +374 -0
- package/packages/core/src/swarm/AgentBus.ts +460 -0
- package/packages/core/src/swarm/AgentExecutor.ts +53 -0
- package/packages/core/src/swarm/Coordinator.ts +251 -0
- package/packages/core/src/swarm/EventBridge.ts +122 -0
- package/packages/core/src/swarm/EventBus.ts +169 -0
- package/packages/core/src/swarm/TaskGraph.ts +192 -0
- package/packages/core/src/swarm/TaskNode.ts +97 -0
- package/packages/core/src/swarm/TaskResult.ts +22 -0
- package/packages/core/src/swarm/WorkerPool.ts +236 -0
- package/packages/core/src/swarm/errors.ts +37 -0
- package/packages/core/src/swarm/index.ts +30 -0
- package/packages/core/src/swarm/presets/HiveLearnPreset.ts +99 -0
- package/packages/core/src/swarm/presets/ResearchPreset.ts +97 -0
- package/packages/core/src/swarm/presets/index.ts +4 -0
- package/packages/core/src/swarm/strategies/ParallelStrategy.ts +21 -0
- package/packages/core/src/swarm/strategies/PriorityStrategy.ts +46 -0
- package/packages/core/src/swarm/strategies/index.ts +3 -0
- package/packages/core/src/swarm/swarm.test.ts +24 -0
- package/packages/core/src/swarm/types.ts +164 -0
- package/packages/core/src/tool-runtime/index.ts +522 -0
- package/packages/core/src/tool-runtime/tool-runtime.test.ts +91 -0
- package/packages/core/src/tool-runtime/tool-worker.ts +125 -0
- package/packages/core/src/tools/ToolExecutor.ts +58 -0
- package/packages/core/src/tools/ToolRegistry.test.ts +98 -0
- package/packages/core/src/tools/ToolRegistry.ts +61 -0
- package/packages/core/src/tools/agents/get-available-models.ts +118 -0
- package/packages/core/src/tools/agents/index.ts +715 -0
- package/packages/core/src/tools/bridge-events.ts +26 -0
- package/packages/core/src/tools/canvas/index.ts +375 -0
- package/packages/core/src/tools/cli/index.ts +142 -0
- package/packages/core/src/tools/codebridge/index.ts +342 -0
- package/packages/core/src/tools/core/index.ts +476 -0
- package/packages/core/src/tools/cron/index.ts +626 -0
- package/packages/core/src/tools/filesystem/fs-delete.ts +78 -0
- package/packages/core/src/tools/filesystem/fs-edit.ts +106 -0
- package/packages/core/src/tools/filesystem/fs-exists.ts +63 -0
- package/packages/core/src/tools/filesystem/fs-glob.ts +108 -0
- package/packages/core/src/tools/filesystem/fs-list.ts +129 -0
- package/packages/core/src/tools/filesystem/fs-read.ts +72 -0
- package/packages/core/src/tools/filesystem/fs-write.ts +67 -0
- package/packages/core/src/tools/filesystem/index.ts +34 -0
- package/packages/core/src/tools/filesystem/workspace-guard.ts +62 -0
- package/packages/core/src/tools/index.ts +231 -0
- package/packages/core/src/tools/meeting/index.ts +363 -0
- package/packages/core/src/tools/office/index.ts +47 -0
- package/packages/core/src/tools/office/office-escribir-docx.ts +192 -0
- package/packages/core/src/tools/office/office-escribir-pdf.ts +172 -0
- package/packages/core/src/tools/office/office-escribir-pptx.ts +174 -0
- package/packages/core/src/tools/office/office-escribir-xlsx.ts +116 -0
- package/packages/core/src/tools/office/office-leer-docx.ts +93 -0
- package/packages/core/src/tools/office/office-leer-pdf.ts +114 -0
- package/packages/core/src/tools/office/office-leer-pptx.ts +136 -0
- package/packages/core/src/tools/office/office-leer-xlsx.ts +124 -0
- package/packages/core/src/tools/projects/index.ts +37 -0
- package/packages/core/src/tools/projects/project-create.ts +94 -0
- package/packages/core/src/tools/projects/project-done.ts +66 -0
- package/packages/core/src/tools/projects/project-fail.ts +66 -0
- package/packages/core/src/tools/projects/project-list.ts +96 -0
- package/packages/core/src/tools/projects/project-update.ts +72 -0
- package/packages/core/src/tools/projects/task-create.ts +68 -0
- package/packages/core/src/tools/projects/task-evaluate.ts +93 -0
- package/packages/core/src/tools/projects/task-update.ts +93 -0
- package/packages/core/src/tools/types.ts +39 -0
- package/packages/core/src/tools/voice/index.ts +104 -0
- package/packages/core/src/tools/web/browser-click.ts +78 -0
- package/packages/core/src/tools/web/browser-extract.ts +139 -0
- package/packages/core/src/tools/web/browser-navigate.ts +106 -0
- package/packages/core/src/tools/web/browser-screenshot.ts +87 -0
- package/packages/core/src/tools/web/browser-script.ts +88 -0
- package/packages/core/src/tools/web/browser-service.ts +554 -0
- package/packages/core/src/tools/web/browser-type.ts +101 -0
- package/packages/core/src/tools/web/browser-wait.ts +136 -0
- package/packages/core/src/tools/web/index.ts +41 -0
- package/packages/core/src/tools/web/web-fetch.ts +78 -0
- package/packages/core/src/tools/web/web-search.ts +123 -0
- package/packages/core/src/utils/benchmark.ts +80 -0
- package/packages/core/src/utils/crypto.ts +73 -0
- package/packages/core/src/utils/date.ts +42 -0
- package/packages/core/src/utils/index.ts +10 -0
- package/packages/core/src/utils/logger.ts +389 -0
- package/packages/core/src/utils/retry.ts +70 -0
- package/packages/core/src/utils/toon.ts +253 -0
- package/packages/core/src/voice/index.ts +643 -0
- package/packages/core/src/workers/WorkerPool.ts +167 -0
- package/packages/core/src/workers/agent.worker.ts +68 -0
- package/packages/core/src/workers/createWorker.ts +144 -0
- package/packages/core/src/workers/index.ts +5 -0
- package/packages/core/src/workers/workers.test.ts +48 -0
- package/test/setup-db.ts +216 -0
- package/tsconfig.json +40 -0
- package/src/agents.ts +0 -1
- package/src/canvas.ts +0 -1
- package/src/channels.ts +0 -1
- package/src/config.ts +0 -1
- package/src/events.ts +0 -1
- package/src/gateway.ts +0 -1
- package/src/index.ts +0 -304
- package/src/mcp.ts +0 -1
- package/src/multimodal.ts +0 -1
- package/src/scheduler.ts +0 -1
- package/src/security.ts +0 -1
- package/src/skills.ts +0 -1
- package/src/state.ts +0 -1
- package/src/storage.ts +0 -1
- package/src/tools.ts +0 -1
- package/src/tts.ts +0 -1
- package/src/types.ts +0 -82
- package/src/utils.ts +0 -1
- package/src/voice.ts +0 -1
|
@@ -0,0 +1,200 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ACE Reflector — analyzes recent traces and produces insights.
|
|
3
|
+
*
|
|
4
|
+
* Runs in the background (never blocks the main agent loop).
|
|
5
|
+
* Triggered by the tracer after N new traces.
|
|
6
|
+
*
|
|
7
|
+
* Output → `reflections` table → picked up by Curator.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
import { logger } from "../utils/logger.ts"
|
|
11
|
+
|
|
12
|
+
const log = logger.child("reflector")
|
|
13
|
+
|
|
14
|
+
const MAX_TRACES_TO_ANALYZE = 30
|
|
15
|
+
const MIN_TRACES_TO_RUN = 10
|
|
16
|
+
|
|
17
|
+
/** Main entry point — called from tracer.ts */
|
|
18
|
+
export async function runReflector(): Promise<void> {
|
|
19
|
+
try {
|
|
20
|
+
const { getDb } = await import("../storage/SQLiteStorage.ts")
|
|
21
|
+
const db = getDb()
|
|
22
|
+
|
|
23
|
+
log.info(`[reflector] Starting reflection cycle...`)
|
|
24
|
+
|
|
25
|
+
// Fetch traces not yet covered by any reflection
|
|
26
|
+
log.debug(`[reflector] Querying last reflection ID...`)
|
|
27
|
+
const lastReflectionId = (db.query<any, []>(
|
|
28
|
+
"SELECT MAX(id) as mid FROM reflections"
|
|
29
|
+
).get() as any)?.mid ?? 0
|
|
30
|
+
log.debug(`[reflector] Last reflection ID: ${lastReflectionId}`)
|
|
31
|
+
|
|
32
|
+
// Get last processed trace ID from reflections
|
|
33
|
+
log.debug(`[reflector] Querying last processed trace ID with json_each...`)
|
|
34
|
+
let lastProcessedTrace = 0
|
|
35
|
+
try {
|
|
36
|
+
const result = (db.query<any, []>(
|
|
37
|
+
`SELECT MAX(CAST(json_each.value AS INTEGER)) as max_id
|
|
38
|
+
FROM reflections, json_each(reflections.trace_ids)
|
|
39
|
+
WHERE reflections.id = (SELECT MAX(id) FROM reflections)`
|
|
40
|
+
).get() as any)?.max_id ?? 0
|
|
41
|
+
lastProcessedTrace = result
|
|
42
|
+
log.debug(`[reflector] Last processed trace ID: ${lastProcessedTrace}`)
|
|
43
|
+
} catch (jsonErr) {
|
|
44
|
+
log.error(`[reflector] json_each query failed:`, jsonErr)
|
|
45
|
+
log.error(`[reflector] Full error details:`, {
|
|
46
|
+
message: (jsonErr as Error).message,
|
|
47
|
+
stack: (jsonErr as Error).stack,
|
|
48
|
+
errno: (jsonErr as any).errno,
|
|
49
|
+
byteOffset: (jsonErr as any).byteOffset,
|
|
50
|
+
})
|
|
51
|
+
throw jsonErr // Re-throw to see full stack trace in main catch
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
log.debug(`[reflector] Fetching traces from DB, lastProcessedTrace=${lastProcessedTrace}, limit=${MAX_TRACES_TO_ANALYZE}`)
|
|
55
|
+
const traces = db.query<any, [number, number]>(`
|
|
56
|
+
SELECT id, agent_id, agent_name, tool_used, input_summary,
|
|
57
|
+
output_summary, success, error_message, duration_ms, tokens_used, created_at
|
|
58
|
+
FROM traces
|
|
59
|
+
WHERE id > ?
|
|
60
|
+
ORDER BY id ASC
|
|
61
|
+
LIMIT ?
|
|
62
|
+
`).all(lastProcessedTrace, MAX_TRACES_TO_ANALYZE)
|
|
63
|
+
|
|
64
|
+
log.debug(`[reflector] Fetched ${traces.length} traces from DB`)
|
|
65
|
+
|
|
66
|
+
if (traces.length < MIN_TRACES_TO_RUN) {
|
|
67
|
+
log.debug(`[reflector] Not enough traces (${traces.length}/${MIN_TRACES_TO_RUN}), skipping`)
|
|
68
|
+
return
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
log.info(`[reflector] Analyzing ${traces.length} traces...`)
|
|
72
|
+
|
|
73
|
+
const insights = analyzeTracesLocally(traces)
|
|
74
|
+
|
|
75
|
+
if (insights.length === 0) {
|
|
76
|
+
log.debug("[reflector] No insights generated")
|
|
77
|
+
return
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
const traceIds = JSON.stringify(traces.map((t: any) => t.id))
|
|
81
|
+
|
|
82
|
+
for (const insight of insights) {
|
|
83
|
+
db.query(`
|
|
84
|
+
INSERT INTO reflections (trace_ids, insight_type, description, affected_tools, affected_agents, confidence)
|
|
85
|
+
VALUES (?, ?, ?, ?, ?, ?)
|
|
86
|
+
`).run(
|
|
87
|
+
traceIds,
|
|
88
|
+
insight.type,
|
|
89
|
+
insight.description,
|
|
90
|
+
insight.affectedTools ? JSON.stringify(insight.affectedTools) : null,
|
|
91
|
+
insight.affectedAgents ? JSON.stringify(insight.affectedAgents) : null,
|
|
92
|
+
insight.confidence,
|
|
93
|
+
)
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
log.info(`[reflector] Generated ${insights.length} insights`)
|
|
97
|
+
|
|
98
|
+
// Trigger curator
|
|
99
|
+
const { runCurator } = await import("./Curator.ts")
|
|
100
|
+
await runCurator()
|
|
101
|
+
|
|
102
|
+
log.info(`[reflector] Reflection cycle completed successfully`)
|
|
103
|
+
} catch (err) {
|
|
104
|
+
log.error(`[reflector] Error during reflection:`, {
|
|
105
|
+
message: (err as Error).message,
|
|
106
|
+
stack: (err as Error).stack,
|
|
107
|
+
errno: (err as any).errno,
|
|
108
|
+
byteOffset: (err as any).byteOffset,
|
|
109
|
+
code: (err as any).code,
|
|
110
|
+
})
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
// ─── Local analysis (heuristic, no LLM call needed for basic patterns) ────────
|
|
115
|
+
|
|
116
|
+
interface Insight {
|
|
117
|
+
type: "success_pattern" | "failure_pattern" | "optimization" | "ethics_violation"
|
|
118
|
+
description: string
|
|
119
|
+
affectedTools?: string[]
|
|
120
|
+
affectedAgents?: string[]
|
|
121
|
+
confidence: number
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
function analyzeTracesLocally(traces: any[]): Insight[] {
|
|
125
|
+
const insights: Insight[] = []
|
|
126
|
+
|
|
127
|
+
// ── Failure patterns ─────────────────────────────────────────────────────
|
|
128
|
+
const failures = traces.filter((t: any) => !t.success)
|
|
129
|
+
if (failures.length > 3) {
|
|
130
|
+
// Group by tool
|
|
131
|
+
const toolFailures: Record<string, number> = {}
|
|
132
|
+
for (const f of failures) {
|
|
133
|
+
if (f.tool_used) {
|
|
134
|
+
toolFailures[f.tool_used] = (toolFailures[f.tool_used] || 0) + 1
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
for (const [tool, count] of Object.entries(toolFailures)) {
|
|
138
|
+
if (count >= 3) {
|
|
139
|
+
insights.push({
|
|
140
|
+
type: "failure_pattern",
|
|
141
|
+
description: `Tool '${tool}' failed ${count} times recently. Consider verifying its configuration or avoiding it for this type of task.`,
|
|
142
|
+
affectedTools: [tool],
|
|
143
|
+
confidence: Math.min(0.9, count / 10),
|
|
144
|
+
})
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
// ── Slow tools ───────────────────────────────────────────────────────────
|
|
150
|
+
const slowThresholdMs = 5000
|
|
151
|
+
const slowTools: Record<string, number[]> = {}
|
|
152
|
+
for (const t of traces) {
|
|
153
|
+
if (t.tool_used && t.duration_ms > slowThresholdMs) {
|
|
154
|
+
if (!slowTools[t.tool_used]) slowTools[t.tool_used] = []
|
|
155
|
+
slowTools[t.tool_used].push(t.duration_ms)
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
for (const [tool, durations] of Object.entries(slowTools)) {
|
|
159
|
+
if (durations.length >= 3) {
|
|
160
|
+
const avg = Math.round(durations.reduce((a, b) => a + b, 0) / durations.length)
|
|
161
|
+
insights.push({
|
|
162
|
+
type: "optimization",
|
|
163
|
+
description: `Tool '${tool}' is consistently slow (avg ${avg}ms). Cache results when possible or use a faster alternative.`,
|
|
164
|
+
affectedTools: [tool],
|
|
165
|
+
confidence: 0.6,
|
|
166
|
+
})
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
// ── High success pattern ─────────────────────────────────────────────────
|
|
171
|
+
const successByTool: Record<string, { ok: number; total: number }> = {}
|
|
172
|
+
for (const t of traces) {
|
|
173
|
+
if (!t.tool_used) continue
|
|
174
|
+
if (!successByTool[t.tool_used]) successByTool[t.tool_used] = { ok: 0, total: 0 }
|
|
175
|
+
successByTool[t.tool_used].total++
|
|
176
|
+
if (t.success) successByTool[t.tool_used].ok++
|
|
177
|
+
}
|
|
178
|
+
for (const [tool, stats] of Object.entries(successByTool)) {
|
|
179
|
+
if (stats.total >= 5 && stats.ok / stats.total >= 0.9) {
|
|
180
|
+
insights.push({
|
|
181
|
+
type: "success_pattern",
|
|
182
|
+
description: `Tool '${tool}' has a high success rate (${stats.ok}/${stats.total}). Prefer it for related tasks.`,
|
|
183
|
+
affectedTools: [tool],
|
|
184
|
+
confidence: stats.ok / stats.total,
|
|
185
|
+
})
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
// ── High token usage ─────────────────────────────────────────────────────
|
|
190
|
+
const highTokenTraces = traces.filter((t: any) => t.tokens_used > 4000)
|
|
191
|
+
if (highTokenTraces.length > 3) {
|
|
192
|
+
insights.push({
|
|
193
|
+
type: "optimization",
|
|
194
|
+
description: `${highTokenTraces.length} recent calls used >4000 tokens. Be more concise and use tool results as summaries, not raw dumps.`,
|
|
195
|
+
confidence: 0.7,
|
|
196
|
+
})
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
return insights
|
|
200
|
+
}
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tracer — ACE Generator output.
|
|
3
|
+
*
|
|
4
|
+
* Records every agent execution to the `traces` table.
|
|
5
|
+
* Fire-and-forget (non-blocking). Also updates playbook helpful/harmful counts
|
|
6
|
+
* based on execution outcome.
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
import { logger } from "../utils/logger.ts"
|
|
10
|
+
|
|
11
|
+
const log = logger.child("tracer")
|
|
12
|
+
|
|
13
|
+
export interface TraceInput {
|
|
14
|
+
threadId: string
|
|
15
|
+
agentId: string
|
|
16
|
+
agentName: string
|
|
17
|
+
toolUsed?: string | null
|
|
18
|
+
inputSummary: string
|
|
19
|
+
outputSummary: string
|
|
20
|
+
success: boolean
|
|
21
|
+
errorMessage?: string | null
|
|
22
|
+
durationMs?: number
|
|
23
|
+
tokensUsed?: number
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Save a trace record. Non-blocking — errors are swallowed so they never
|
|
28
|
+
* affect the main agent loop.
|
|
29
|
+
*/
|
|
30
|
+
export function saveTrace(trace: TraceInput): void {
|
|
31
|
+
// Run asynchronously so it never blocks the caller
|
|
32
|
+
Promise.resolve().then(async () => {
|
|
33
|
+
try {
|
|
34
|
+
const { getDb } = await import("../storage/SQLiteStorage.ts")
|
|
35
|
+
const db = getDb()
|
|
36
|
+
|
|
37
|
+
db.query(`
|
|
38
|
+
INSERT INTO traces
|
|
39
|
+
(thread_id, agent_id, agent_name, tool_used, input_summary,
|
|
40
|
+
output_summary, success, error_message, duration_ms, tokens_used)
|
|
41
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
42
|
+
`).run(
|
|
43
|
+
trace.threadId,
|
|
44
|
+
trace.agentId,
|
|
45
|
+
trace.agentName,
|
|
46
|
+
trace.toolUsed ?? null,
|
|
47
|
+
trace.inputSummary.substring(0, 500),
|
|
48
|
+
trace.outputSummary.substring(0, 500),
|
|
49
|
+
trace.success ? 1 : 0,
|
|
50
|
+
trace.errorMessage ?? null,
|
|
51
|
+
trace.durationMs ?? null,
|
|
52
|
+
trace.tokensUsed ?? null,
|
|
53
|
+
)
|
|
54
|
+
|
|
55
|
+
// Trigger reflector check in background
|
|
56
|
+
checkReflectorTrigger().catch(() => { /* ignore */ })
|
|
57
|
+
} catch (err) {
|
|
58
|
+
log.warn("[tracer] Failed to save trace:", err)
|
|
59
|
+
}
|
|
60
|
+
})
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
// ─── Reflector trigger ────────────────────────────────────────────────────────
|
|
64
|
+
|
|
65
|
+
const REFLECTOR_TRACE_THRESHOLD = 20 // run reflector after N new traces
|
|
66
|
+
|
|
67
|
+
let _tracesSinceLastReflection = 0
|
|
68
|
+
|
|
69
|
+
async function checkReflectorTrigger(): Promise<void> {
|
|
70
|
+
_tracesSinceLastReflection++
|
|
71
|
+
if (_tracesSinceLastReflection < REFLECTOR_TRACE_THRESHOLD) return
|
|
72
|
+
_tracesSinceLastReflection = 0
|
|
73
|
+
|
|
74
|
+
// Lazy import to avoid circular deps
|
|
75
|
+
const { runReflector } = await import("./Reflector.ts")
|
|
76
|
+
runReflector().catch((err) => {
|
|
77
|
+
log.warn("[tracer] Reflector run failed:", err)
|
|
78
|
+
})
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
// ─── Usage recording ──────────────────────────────────────────────────────────
|
|
82
|
+
|
|
83
|
+
export function recordLLMUsage(opts: {
|
|
84
|
+
provider: string
|
|
85
|
+
model: string
|
|
86
|
+
inputTokens: number
|
|
87
|
+
outputTokens: number
|
|
88
|
+
}): void {
|
|
89
|
+
Promise.resolve().then(async () => {
|
|
90
|
+
try {
|
|
91
|
+
const { recordUsage } = await import("../storage/usage.ts")
|
|
92
|
+
recordUsage({
|
|
93
|
+
provider: opts.provider,
|
|
94
|
+
model: opts.model,
|
|
95
|
+
inputTokens: opts.inputTokens,
|
|
96
|
+
outputTokens: opts.outputTokens,
|
|
97
|
+
})
|
|
98
|
+
} catch { /* ignore */ }
|
|
99
|
+
})
|
|
100
|
+
}
|