cognitive-core 0.0.2 → 0.1.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 +302 -116
- package/SKILL.md +193 -0
- package/dist/agents/index.d.ts +3 -0
- package/dist/agents/index.d.ts.map +1 -0
- package/dist/agents/index.js +5 -0
- package/dist/agents/index.js.map +1 -0
- package/dist/agents/mock-provider.d.ts +23 -0
- package/dist/agents/mock-provider.d.ts.map +1 -0
- package/dist/agents/mock-provider.js +71 -0
- package/dist/agents/mock-provider.js.map +1 -0
- package/dist/agents/types.d.ts +98 -0
- package/dist/agents/types.d.ts.map +1 -0
- package/dist/agents/types.js +44 -0
- package/dist/agents/types.js.map +1 -0
- package/dist/atlas.d.ts +196 -0
- package/dist/atlas.d.ts.map +1 -0
- package/dist/atlas.js +373 -0
- package/dist/atlas.js.map +1 -0
- package/dist/bin/cognitive-core.d.ts +18 -0
- package/dist/bin/cognitive-core.d.ts.map +1 -0
- package/dist/bin/cognitive-core.js +419 -0
- package/dist/bin/cognitive-core.js.map +1 -0
- package/dist/embeddings/bm25.d.ts +104 -0
- package/dist/embeddings/bm25.d.ts.map +1 -0
- package/dist/embeddings/bm25.js +264 -0
- package/dist/embeddings/bm25.js.map +1 -0
- package/dist/embeddings/index.d.ts +12 -0
- package/dist/embeddings/index.d.ts.map +1 -0
- package/dist/embeddings/index.js +16 -0
- package/dist/embeddings/index.js.map +1 -0
- package/dist/embeddings/manager.d.ts +112 -0
- package/dist/embeddings/manager.d.ts.map +1 -0
- package/dist/embeddings/manager.js +215 -0
- package/dist/embeddings/manager.js.map +1 -0
- package/dist/embeddings/provider.d.ts +101 -0
- package/dist/embeddings/provider.d.ts.map +1 -0
- package/dist/embeddings/provider.js +232 -0
- package/dist/embeddings/provider.js.map +1 -0
- package/dist/embeddings/vector-store.d.ts +101 -0
- package/dist/embeddings/vector-store.d.ts.map +1 -0
- package/dist/embeddings/vector-store.js +256 -0
- package/dist/embeddings/vector-store.js.map +1 -0
- package/dist/factory.d.ts +193 -0
- package/dist/factory.d.ts.map +1 -0
- package/dist/factory.js +109 -0
- package/dist/factory.js.map +1 -0
- package/dist/index.d.ts +30 -453
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +84 -509
- package/dist/index.js.map +1 -0
- package/dist/learning/analyzer.d.ts +110 -0
- package/dist/learning/analyzer.d.ts.map +1 -0
- package/dist/learning/analyzer.js +213 -0
- package/dist/learning/analyzer.js.map +1 -0
- package/dist/learning/effectiveness.d.ts +158 -0
- package/dist/learning/effectiveness.d.ts.map +1 -0
- package/dist/learning/effectiveness.js +251 -0
- package/dist/learning/effectiveness.js.map +1 -0
- package/dist/learning/index.d.ts +8 -0
- package/dist/learning/index.d.ts.map +1 -0
- package/dist/learning/index.js +11 -0
- package/dist/learning/index.js.map +1 -0
- package/dist/learning/llm-extractor.d.ts +88 -0
- package/dist/learning/llm-extractor.d.ts.map +1 -0
- package/dist/learning/llm-extractor.js +372 -0
- package/dist/learning/llm-extractor.js.map +1 -0
- package/dist/learning/meta-learner.d.ts +80 -0
- package/dist/learning/meta-learner.d.ts.map +1 -0
- package/dist/learning/meta-learner.js +355 -0
- package/dist/learning/meta-learner.js.map +1 -0
- package/dist/learning/pipeline.d.ts +65 -0
- package/dist/learning/pipeline.d.ts.map +1 -0
- package/dist/learning/pipeline.js +170 -0
- package/dist/learning/pipeline.js.map +1 -0
- package/dist/learning/playbook-extractor.d.ts +113 -0
- package/dist/learning/playbook-extractor.d.ts.map +1 -0
- package/dist/learning/playbook-extractor.js +523 -0
- package/dist/learning/playbook-extractor.js.map +1 -0
- package/dist/learning/usage-inference.d.ts +82 -0
- package/dist/learning/usage-inference.d.ts.map +1 -0
- package/dist/learning/usage-inference.js +261 -0
- package/dist/learning/usage-inference.js.map +1 -0
- package/dist/mcp/index.d.ts +6 -0
- package/dist/mcp/index.d.ts.map +1 -0
- package/dist/mcp/index.js +6 -0
- package/dist/mcp/index.js.map +1 -0
- package/dist/mcp/playbook-server.d.ts +120 -0
- package/dist/mcp/playbook-server.d.ts.map +1 -0
- package/dist/mcp/playbook-server.js +427 -0
- package/dist/mcp/playbook-server.js.map +1 -0
- package/dist/memory/curated-loader.d.ts +62 -0
- package/dist/memory/curated-loader.d.ts.map +1 -0
- package/dist/memory/curated-loader.js +106 -0
- package/dist/memory/curated-loader.js.map +1 -0
- package/dist/memory/experience.d.ts +122 -0
- package/dist/memory/experience.d.ts.map +1 -0
- package/dist/memory/experience.js +392 -0
- package/dist/memory/experience.js.map +1 -0
- package/dist/memory/index.d.ts +6 -0
- package/dist/memory/index.d.ts.map +1 -0
- package/dist/memory/index.js +9 -0
- package/dist/memory/index.js.map +1 -0
- package/dist/memory/meta.d.ts +90 -0
- package/dist/memory/meta.d.ts.map +1 -0
- package/dist/memory/meta.js +362 -0
- package/dist/memory/meta.js.map +1 -0
- package/dist/memory/playbook.d.ts +133 -0
- package/dist/memory/playbook.d.ts.map +1 -0
- package/dist/memory/playbook.js +357 -0
- package/dist/memory/playbook.js.map +1 -0
- package/dist/memory/system.d.ts +167 -0
- package/dist/memory/system.d.ts.map +1 -0
- package/dist/memory/system.js +383 -0
- package/dist/memory/system.js.map +1 -0
- package/dist/runtime/backends/acp.d.ts +67 -0
- package/dist/runtime/backends/acp.d.ts.map +1 -0
- package/dist/runtime/backends/acp.js +290 -0
- package/dist/runtime/backends/acp.js.map +1 -0
- package/dist/runtime/backends/index.d.ts +5 -0
- package/dist/runtime/backends/index.d.ts.map +1 -0
- package/dist/runtime/backends/index.js +6 -0
- package/dist/runtime/backends/index.js.map +1 -0
- package/dist/runtime/backends/mock.d.ts +67 -0
- package/dist/runtime/backends/mock.d.ts.map +1 -0
- package/dist/runtime/backends/mock.js +153 -0
- package/dist/runtime/backends/mock.js.map +1 -0
- package/dist/runtime/backends/subprocess.d.ts +56 -0
- package/dist/runtime/backends/subprocess.d.ts.map +1 -0
- package/dist/runtime/backends/subprocess.js +260 -0
- package/dist/runtime/backends/subprocess.js.map +1 -0
- package/dist/runtime/flows/learning.d.ts +73 -0
- package/dist/runtime/flows/learning.d.ts.map +1 -0
- package/dist/runtime/flows/learning.js +116 -0
- package/dist/runtime/flows/learning.js.map +1 -0
- package/dist/runtime/flows/validation.d.ts +122 -0
- package/dist/runtime/flows/validation.d.ts.map +1 -0
- package/dist/runtime/flows/validation.js +223 -0
- package/dist/runtime/flows/validation.js.map +1 -0
- package/dist/runtime/index.d.ts +6 -0
- package/dist/runtime/index.d.ts.map +1 -0
- package/dist/runtime/index.js +8 -0
- package/dist/runtime/index.js.map +1 -0
- package/dist/runtime/manager.d.ts +116 -0
- package/dist/runtime/manager.d.ts.map +1 -0
- package/dist/runtime/manager.js +416 -0
- package/dist/runtime/manager.js.map +1 -0
- package/dist/runtime/types.d.ts +138 -0
- package/dist/runtime/types.d.ts.map +1 -0
- package/dist/runtime/types.js +2 -0
- package/dist/runtime/types.js.map +1 -0
- package/dist/search/evaluator.d.ts +102 -0
- package/dist/search/evaluator.d.ts.map +1 -0
- package/dist/search/evaluator.js +352 -0
- package/dist/search/evaluator.js.map +1 -0
- package/dist/search/index.d.ts +7 -0
- package/dist/search/index.d.ts.map +1 -0
- package/dist/search/index.js +11 -0
- package/dist/search/index.js.map +1 -0
- package/dist/search/refinement-loop.d.ts +73 -0
- package/dist/search/refinement-loop.d.ts.map +1 -0
- package/dist/search/refinement-loop.js +245 -0
- package/dist/search/refinement-loop.js.map +1 -0
- package/dist/search/refinement-types.d.ts +154 -0
- package/dist/search/refinement-types.d.ts.map +1 -0
- package/dist/search/refinement-types.js +99 -0
- package/dist/search/refinement-types.js.map +1 -0
- package/dist/search/router.d.ts +61 -0
- package/dist/search/router.d.ts.map +1 -0
- package/dist/search/router.js +197 -0
- package/dist/search/router.js.map +1 -0
- package/dist/search/solver.d.ts +75 -0
- package/dist/search/solver.d.ts.map +1 -0
- package/dist/search/solver.js +216 -0
- package/dist/search/solver.js.map +1 -0
- package/dist/search/verification-runner.d.ts +125 -0
- package/dist/search/verification-runner.d.ts.map +1 -0
- package/dist/search/verification-runner.js +440 -0
- package/dist/search/verification-runner.js.map +1 -0
- package/dist/surfacing/index.d.ts +2 -0
- package/dist/surfacing/index.d.ts.map +1 -0
- package/dist/surfacing/index.js +2 -0
- package/dist/surfacing/index.js.map +1 -0
- package/dist/surfacing/skill-library.d.ts +158 -0
- package/dist/surfacing/skill-library.d.ts.map +1 -0
- package/dist/surfacing/skill-library.js +429 -0
- package/dist/surfacing/skill-library.js.map +1 -0
- package/dist/types/config.d.ts +1113 -0
- package/dist/types/config.d.ts.map +1 -0
- package/dist/types/config.js +274 -0
- package/dist/types/config.js.map +1 -0
- package/dist/types/index.d.ts +9 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/index.js +14 -0
- package/dist/types/index.js.map +1 -0
- package/dist/types/memory.d.ts +339 -0
- package/dist/types/memory.d.ts.map +1 -0
- package/dist/types/memory.js +207 -0
- package/dist/types/memory.js.map +1 -0
- package/dist/types/meta.d.ts +146 -0
- package/dist/types/meta.d.ts.map +1 -0
- package/dist/types/meta.js +51 -0
- package/dist/types/meta.js.map +1 -0
- package/dist/types/outcome.d.ts +42 -0
- package/dist/types/outcome.d.ts.map +1 -0
- package/dist/types/outcome.js +50 -0
- package/dist/types/outcome.js.map +1 -0
- package/dist/types/playbook.d.ts +119 -0
- package/dist/types/playbook.d.ts.map +1 -0
- package/dist/types/playbook.js +71 -0
- package/dist/types/playbook.js.map +1 -0
- package/dist/types/step.d.ts +44 -0
- package/dist/types/step.d.ts.map +1 -0
- package/dist/types/step.js +32 -0
- package/dist/types/step.js.map +1 -0
- package/dist/types/task.d.ts +91 -0
- package/dist/types/task.d.ts.map +1 -0
- package/dist/types/task.js +39 -0
- package/dist/types/task.js.map +1 -0
- package/dist/types/trajectory.d.ts +221 -0
- package/dist/types/trajectory.d.ts.map +1 -0
- package/dist/types/trajectory.js +60 -0
- package/dist/types/trajectory.js.map +1 -0
- package/dist/utils/index.d.ts +4 -0
- package/dist/utils/index.d.ts.map +1 -0
- package/dist/utils/index.js +4 -0
- package/dist/utils/index.js.map +1 -0
- package/dist/utils/similarity.d.ts +31 -0
- package/dist/utils/similarity.d.ts.map +1 -0
- package/dist/utils/similarity.js +107 -0
- package/dist/utils/similarity.js.map +1 -0
- package/dist/utils/storage.d.ts +106 -0
- package/dist/utils/storage.d.ts.map +1 -0
- package/dist/utils/storage.js +203 -0
- package/dist/utils/storage.js.map +1 -0
- package/dist/utils/validation.d.ts +129 -0
- package/dist/utils/validation.d.ts.map +1 -0
- package/dist/utils/validation.js +171 -0
- package/dist/utils/validation.js.map +1 -0
- package/package.json +50 -34
- package/scripts/migrate-to-playbooks.ts +307 -0
- package/src/agents/index.ts +14 -0
- package/src/agents/mock-provider.ts +93 -0
- package/src/agents/types.ts +137 -0
- package/src/atlas.ts +560 -0
- package/src/bin/cognitive-core.ts +470 -0
- package/src/embeddings/bm25.ts +337 -0
- package/src/embeddings/index.ts +39 -0
- package/src/embeddings/manager.ts +288 -0
- package/src/embeddings/provider.ts +311 -0
- package/src/embeddings/vector-store.ts +353 -0
- package/src/factory.ts +263 -0
- package/src/index.ts +246 -0
- package/src/learning/analyzer.ts +335 -0
- package/src/learning/effectiveness.ts +428 -0
- package/src/learning/index.ts +58 -0
- package/src/learning/llm-extractor.ts +542 -0
- package/src/learning/meta-learner.ts +516 -0
- package/src/learning/pipeline.ts +244 -0
- package/src/learning/playbook-extractor.ts +702 -0
- package/src/learning/usage-inference.ts +372 -0
- package/src/mcp/index.ts +12 -0
- package/src/mcp/playbook-server.ts +565 -0
- package/src/memory/curated-loader.ts +160 -0
- package/src/memory/experience.ts +515 -0
- package/src/memory/index.ts +27 -0
- package/src/memory/meta.ts +506 -0
- package/src/memory/playbook.ts +493 -0
- package/src/memory/system.ts +551 -0
- package/src/runtime/backends/acp.ts +378 -0
- package/src/runtime/backends/index.ts +24 -0
- package/src/runtime/backends/mock.ts +218 -0
- package/src/runtime/backends/subprocess.ts +356 -0
- package/src/runtime/flows/learning.ts +183 -0
- package/src/runtime/flows/validation.ts +381 -0
- package/src/runtime/index.ts +53 -0
- package/src/runtime/manager.ts +541 -0
- package/src/runtime/types.ts +157 -0
- package/src/search/evaluator.ts +474 -0
- package/src/search/index.ts +59 -0
- package/src/search/refinement-loop.ts +363 -0
- package/src/search/refinement-types.ts +159 -0
- package/src/search/router.ts +261 -0
- package/src/search/solver.ts +303 -0
- package/src/search/verification-runner.ts +570 -0
- package/src/surfacing/index.ts +6 -0
- package/src/surfacing/skill-library.ts +594 -0
- package/src/types/config.ts +333 -0
- package/src/types/index.ts +130 -0
- package/src/types/memory.ts +270 -0
- package/src/types/meta.ts +218 -0
- package/src/types/outcome.ts +66 -0
- package/src/types/playbook.ts +196 -0
- package/src/types/step.ts +40 -0
- package/src/types/task.ts +52 -0
- package/src/types/trajectory.ts +80 -0
- package/src/utils/index.ts +38 -0
- package/src/utils/similarity.ts +139 -0
- package/src/utils/storage.ts +249 -0
- package/src/utils/validation.ts +286 -0
- package/tests/embeddings/bm25.test.ts +130 -0
- package/tests/embeddings/manager.test.ts +205 -0
- package/tests/integration/atlas.test.ts +266 -0
- package/tests/integration/e2e.test.ts +929 -0
- package/tests/learning/analyzer.test.ts +426 -0
- package/tests/learning/effectiveness.test.ts +542 -0
- package/tests/learning/pipeline.test.ts +176 -0
- package/tests/learning/playbook-extractor-provenance.test.ts +114 -0
- package/tests/learning/usage-inference.test.ts +254 -0
- package/tests/mcp/playbook-server.test.ts +252 -0
- package/tests/memory/experience.test.ts +198 -0
- package/tests/memory/playbook.test.ts +338 -0
- package/tests/memory/provenance.test.ts +639 -0
- package/tests/memory/system.test.ts +325 -0
- package/tests/runtime/agent-manager.test.ts +512 -0
- package/tests/runtime/mock-backend.test.ts +248 -0
- package/tests/search/refinement-loop.test.ts +468 -0
- package/tests/search/refinement.test.ts +267 -0
- package/tests/search/router.test.ts +427 -0
- package/tests/surfacing/skill-library.test.ts +292 -0
- package/tests/types/outcome.test.ts +147 -0
- package/tests/types/step.test.ts +133 -0
- package/tests/types/task.test.ts +158 -0
- package/tests/types/trajectory.test.ts +253 -0
- package/tests/utils/similarity.test.ts +188 -0
- package/tests/utils/validation.test.ts +252 -0
- package/tsconfig.json +25 -0
- package/vitest.config.ts +22 -0
- package/dist/index.d.mts +0 -466
- package/dist/index.mjs +0 -478
|
@@ -0,0 +1,356 @@
|
|
|
1
|
+
import { spawn, type ChildProcess } from 'child_process';
|
|
2
|
+
import { EventEmitter } from 'events';
|
|
3
|
+
import type {
|
|
4
|
+
AgentBackend,
|
|
5
|
+
AgentSpawnConfig,
|
|
6
|
+
AgentSession,
|
|
7
|
+
AgentMessage,
|
|
8
|
+
ToolCall,
|
|
9
|
+
} from '../types.js';
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Configuration for subprocess-based agents
|
|
13
|
+
*/
|
|
14
|
+
export interface SubprocessAgentConfig {
|
|
15
|
+
/** Command to run the agent */
|
|
16
|
+
command: string;
|
|
17
|
+
/** Arguments for the command */
|
|
18
|
+
args?: string[];
|
|
19
|
+
/** How to pass the task to the agent */
|
|
20
|
+
taskPassingMode: 'stdin' | 'arg' | 'env' | 'file';
|
|
21
|
+
/** Environment variable name for task (if taskPassingMode is 'env') */
|
|
22
|
+
taskEnvVar?: string;
|
|
23
|
+
/** How to pass knowledge injection */
|
|
24
|
+
knowledgePassingMode: 'stdin' | 'env' | 'file' | 'system-prompt';
|
|
25
|
+
/** Environment variable name for knowledge (if knowledgePassingMode is 'env') */
|
|
26
|
+
knowledgeEnvVar?: string;
|
|
27
|
+
/** Parser for agent output to extract tool calls */
|
|
28
|
+
outputParser?: (output: string) => {
|
|
29
|
+
messages: AgentMessage[];
|
|
30
|
+
toolCalls: ToolCall[];
|
|
31
|
+
result?: unknown;
|
|
32
|
+
isComplete: boolean;
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* Running subprocess session
|
|
38
|
+
*/
|
|
39
|
+
interface SubprocessSession {
|
|
40
|
+
session: AgentSession;
|
|
41
|
+
process: ChildProcess;
|
|
42
|
+
outputBuffer: string;
|
|
43
|
+
emitter: EventEmitter;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* Subprocess-based agent backend
|
|
48
|
+
* Spawns agents as child processes (e.g., Claude Code CLI, custom scripts)
|
|
49
|
+
*/
|
|
50
|
+
export class SubprocessBackend implements AgentBackend {
|
|
51
|
+
readonly name = 'subprocess';
|
|
52
|
+
readonly supportedTypes: string[];
|
|
53
|
+
|
|
54
|
+
private configs: Map<string, SubprocessAgentConfig> = new Map();
|
|
55
|
+
private sessions: Map<string, SubprocessSession> = new Map();
|
|
56
|
+
|
|
57
|
+
constructor(configs: Record<string, SubprocessAgentConfig>) {
|
|
58
|
+
this.supportedTypes = Object.keys(configs);
|
|
59
|
+
for (const [type, config] of Object.entries(configs)) {
|
|
60
|
+
this.configs.set(type, config);
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
async isAvailable(): Promise<boolean> {
|
|
65
|
+
// Check if at least one configured command exists
|
|
66
|
+
// For now, just return true
|
|
67
|
+
return true;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
async spawn(config: AgentSpawnConfig): Promise<AgentSession> {
|
|
71
|
+
const agentConfig = this.configs.get(config.agentType);
|
|
72
|
+
if (!agentConfig) {
|
|
73
|
+
const error = new Error(`Unknown agent type: ${config.agentType}`);
|
|
74
|
+
console.error('[SubprocessBackend] Spawn failed:', error.message);
|
|
75
|
+
throw error;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
const sessionId = crypto.randomUUID();
|
|
79
|
+
const session: AgentSession = {
|
|
80
|
+
id: sessionId,
|
|
81
|
+
agentType: config.agentType,
|
|
82
|
+
task: config.task,
|
|
83
|
+
state: 'running',
|
|
84
|
+
messages: [],
|
|
85
|
+
toolCalls: [],
|
|
86
|
+
startTime: new Date(),
|
|
87
|
+
metadata: {},
|
|
88
|
+
};
|
|
89
|
+
|
|
90
|
+
// Build environment (filter out undefined values from process.env)
|
|
91
|
+
const env: Record<string, string> = Object.fromEntries(
|
|
92
|
+
Object.entries({ ...process.env, ...config.env }).filter(
|
|
93
|
+
(entry): entry is [string, string] => entry[1] !== undefined
|
|
94
|
+
)
|
|
95
|
+
);
|
|
96
|
+
|
|
97
|
+
// Pass task via env if configured
|
|
98
|
+
if (agentConfig.taskPassingMode === 'env' && agentConfig.taskEnvVar) {
|
|
99
|
+
env[agentConfig.taskEnvVar] = config.task.description;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
// Pass knowledge via env if configured
|
|
103
|
+
if (
|
|
104
|
+
agentConfig.knowledgePassingMode === 'env' &&
|
|
105
|
+
agentConfig.knowledgeEnvVar &&
|
|
106
|
+
config.systemPromptAdditions
|
|
107
|
+
) {
|
|
108
|
+
env[agentConfig.knowledgeEnvVar] = config.systemPromptAdditions;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
// Build arguments
|
|
112
|
+
const args = [...(agentConfig.args ?? [])];
|
|
113
|
+
if (agentConfig.taskPassingMode === 'arg') {
|
|
114
|
+
args.push(config.task.description);
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
// Spawn the process
|
|
118
|
+
const childProcess = spawn(agentConfig.command, args, {
|
|
119
|
+
cwd: config.cwd,
|
|
120
|
+
env,
|
|
121
|
+
stdio: ['pipe', 'pipe', 'pipe'],
|
|
122
|
+
});
|
|
123
|
+
|
|
124
|
+
const emitter = new EventEmitter();
|
|
125
|
+
const subSession: SubprocessSession = {
|
|
126
|
+
session,
|
|
127
|
+
process: childProcess,
|
|
128
|
+
outputBuffer: '',
|
|
129
|
+
emitter,
|
|
130
|
+
};
|
|
131
|
+
|
|
132
|
+
this.sessions.set(sessionId, subSession);
|
|
133
|
+
|
|
134
|
+
// Pass task via stdin if configured
|
|
135
|
+
if (agentConfig.taskPassingMode === 'stdin') {
|
|
136
|
+
let input = config.task.description;
|
|
137
|
+
if (config.systemPromptAdditions) {
|
|
138
|
+
input = `${config.systemPromptAdditions}\n\n${input}`;
|
|
139
|
+
}
|
|
140
|
+
childProcess.stdin?.write(input);
|
|
141
|
+
childProcess.stdin?.end();
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
// Handle output
|
|
145
|
+
const parser = agentConfig.outputParser ?? this.defaultParser;
|
|
146
|
+
|
|
147
|
+
childProcess.stdout?.on('data', (data: Buffer) => {
|
|
148
|
+
const output = data.toString();
|
|
149
|
+
subSession.outputBuffer += output;
|
|
150
|
+
|
|
151
|
+
// Parse and emit events
|
|
152
|
+
const parsed = parser(subSession.outputBuffer);
|
|
153
|
+
|
|
154
|
+
// Add new messages
|
|
155
|
+
for (const msg of parsed.messages) {
|
|
156
|
+
if (!session.messages.some((m) => m.timestamp === msg.timestamp)) {
|
|
157
|
+
session.messages.push(msg);
|
|
158
|
+
config.onMessage?.(msg);
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
// Add new tool calls
|
|
163
|
+
for (const tc of parsed.toolCalls) {
|
|
164
|
+
if (!session.toolCalls.some((t) => t.id === tc.id)) {
|
|
165
|
+
session.toolCalls.push(tc);
|
|
166
|
+
config.onToolCall?.(tc);
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
if (parsed.isComplete) {
|
|
171
|
+
session.result = parsed.result;
|
|
172
|
+
}
|
|
173
|
+
});
|
|
174
|
+
|
|
175
|
+
childProcess.stderr?.on('data', (data: Buffer) => {
|
|
176
|
+
const error = data.toString();
|
|
177
|
+
session.messages.push({
|
|
178
|
+
role: 'system',
|
|
179
|
+
content: `[stderr] ${error}`,
|
|
180
|
+
timestamp: new Date(),
|
|
181
|
+
});
|
|
182
|
+
});
|
|
183
|
+
|
|
184
|
+
// Handle exit
|
|
185
|
+
childProcess.on('close', (code) => {
|
|
186
|
+
session.endTime = new Date();
|
|
187
|
+
session.state = code === 0 ? 'completed' : 'failed';
|
|
188
|
+
if (code !== 0) {
|
|
189
|
+
session.error = `Process exited with code ${code}`;
|
|
190
|
+
console.error(
|
|
191
|
+
`[SubprocessBackend] Session ${sessionId} failed: exit code ${code}`
|
|
192
|
+
);
|
|
193
|
+
}
|
|
194
|
+
emitter.emit('complete', session);
|
|
195
|
+
});
|
|
196
|
+
|
|
197
|
+
childProcess.on('error', (error) => {
|
|
198
|
+
session.endTime = new Date();
|
|
199
|
+
session.state = 'failed';
|
|
200
|
+
session.error = error.message;
|
|
201
|
+
console.error(
|
|
202
|
+
`[SubprocessBackend] Session ${sessionId} process error:`,
|
|
203
|
+
error.message
|
|
204
|
+
);
|
|
205
|
+
emitter.emit('complete', session);
|
|
206
|
+
});
|
|
207
|
+
|
|
208
|
+
// Set up timeout
|
|
209
|
+
if (config.timeout) {
|
|
210
|
+
setTimeout(() => {
|
|
211
|
+
if (session.state === 'running') {
|
|
212
|
+
console.error(
|
|
213
|
+
`[SubprocessBackend] Session ${sessionId} timed out after ${config.timeout}ms`
|
|
214
|
+
);
|
|
215
|
+
childProcess.kill('SIGTERM');
|
|
216
|
+
session.state = 'failed';
|
|
217
|
+
session.error = 'Timeout';
|
|
218
|
+
session.endTime = new Date();
|
|
219
|
+
}
|
|
220
|
+
}, config.timeout);
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
return session;
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
async getSession(sessionId: string): Promise<AgentSession | undefined> {
|
|
227
|
+
return this.sessions.get(sessionId)?.session;
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
async sendMessage(sessionId: string, message: string): Promise<void> {
|
|
231
|
+
const subSession = this.sessions.get(sessionId);
|
|
232
|
+
if (!subSession || subSession.session.state !== 'running') {
|
|
233
|
+
throw new Error('Session not found or not running');
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
subSession.process.stdin?.write(message + '\n');
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
async terminate(sessionId: string): Promise<void> {
|
|
240
|
+
const subSession = this.sessions.get(sessionId);
|
|
241
|
+
if (!subSession) return;
|
|
242
|
+
|
|
243
|
+
subSession.process.kill('SIGTERM');
|
|
244
|
+
subSession.session.state = 'failed';
|
|
245
|
+
subSession.session.error = 'Terminated';
|
|
246
|
+
subSession.session.endTime = new Date();
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
async listSessions(): Promise<AgentSession[]> {
|
|
250
|
+
return Array.from(this.sessions.values()).map((s) => s.session);
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
/**
|
|
254
|
+
* Default parser for agent output
|
|
255
|
+
* Override with custom parser for specific agent formats
|
|
256
|
+
*/
|
|
257
|
+
private defaultParser(output: string): {
|
|
258
|
+
messages: AgentMessage[];
|
|
259
|
+
toolCalls: ToolCall[];
|
|
260
|
+
result?: unknown;
|
|
261
|
+
isComplete: boolean;
|
|
262
|
+
} {
|
|
263
|
+
const messages: AgentMessage[] = [];
|
|
264
|
+
const toolCalls: ToolCall[] = [];
|
|
265
|
+
let result: unknown;
|
|
266
|
+
let isComplete = false;
|
|
267
|
+
|
|
268
|
+
// Simple line-based parsing
|
|
269
|
+
const lines = output.split('\n');
|
|
270
|
+
for (const line of lines) {
|
|
271
|
+
if (line.trim()) {
|
|
272
|
+
messages.push({
|
|
273
|
+
role: 'assistant',
|
|
274
|
+
content: line,
|
|
275
|
+
timestamp: new Date(),
|
|
276
|
+
});
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
// Look for completion markers
|
|
280
|
+
if (line.includes('DONE:') || line.includes('COMPLETE:')) {
|
|
281
|
+
isComplete = true;
|
|
282
|
+
result = line.split(':').slice(1).join(':').trim();
|
|
283
|
+
}
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
return { messages, toolCalls, result, isComplete };
|
|
287
|
+
}
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
/**
|
|
291
|
+
* Create a subprocess backend with common agent configurations
|
|
292
|
+
*/
|
|
293
|
+
export function createSubprocessBackend(
|
|
294
|
+
configs: Record<string, SubprocessAgentConfig>
|
|
295
|
+
): SubprocessBackend {
|
|
296
|
+
return new SubprocessBackend(configs);
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
/**
|
|
300
|
+
* Pre-configured Claude Code agent
|
|
301
|
+
*/
|
|
302
|
+
export const claudeCodeConfig: SubprocessAgentConfig = {
|
|
303
|
+
command: 'claude',
|
|
304
|
+
args: ['--print', '--output-format', 'json'],
|
|
305
|
+
taskPassingMode: 'arg',
|
|
306
|
+
knowledgePassingMode: 'system-prompt',
|
|
307
|
+
outputParser: (output: string) => {
|
|
308
|
+
const messages: AgentMessage[] = [];
|
|
309
|
+
const toolCalls: ToolCall[] = [];
|
|
310
|
+
let result: unknown;
|
|
311
|
+
let isComplete = false;
|
|
312
|
+
|
|
313
|
+
// Try to parse JSON lines (Claude Code output format)
|
|
314
|
+
const lines = output.split('\n');
|
|
315
|
+
for (const line of lines) {
|
|
316
|
+
if (!line.trim()) continue;
|
|
317
|
+
|
|
318
|
+
try {
|
|
319
|
+
const parsed = JSON.parse(line);
|
|
320
|
+
|
|
321
|
+
if (parsed.type === 'assistant') {
|
|
322
|
+
messages.push({
|
|
323
|
+
role: 'assistant',
|
|
324
|
+
content: parsed.content ?? '',
|
|
325
|
+
timestamp: new Date(parsed.timestamp ?? Date.now()),
|
|
326
|
+
});
|
|
327
|
+
} else if (parsed.type === 'tool_use') {
|
|
328
|
+
toolCalls.push({
|
|
329
|
+
id: parsed.id ?? crypto.randomUUID(),
|
|
330
|
+
name: parsed.name,
|
|
331
|
+
input: parsed.input,
|
|
332
|
+
startTime: new Date(parsed.timestamp ?? Date.now()),
|
|
333
|
+
});
|
|
334
|
+
} else if (parsed.type === 'tool_result') {
|
|
335
|
+
const tc = toolCalls.find((t) => t.id === parsed.tool_use_id);
|
|
336
|
+
if (tc) {
|
|
337
|
+
tc.output = parsed.content;
|
|
338
|
+
tc.endTime = new Date(parsed.timestamp ?? Date.now());
|
|
339
|
+
}
|
|
340
|
+
} else if (parsed.type === 'result') {
|
|
341
|
+
isComplete = true;
|
|
342
|
+
result = parsed.result;
|
|
343
|
+
}
|
|
344
|
+
} catch {
|
|
345
|
+
// Not JSON, treat as plain text
|
|
346
|
+
messages.push({
|
|
347
|
+
role: 'assistant',
|
|
348
|
+
content: line,
|
|
349
|
+
timestamp: new Date(),
|
|
350
|
+
});
|
|
351
|
+
}
|
|
352
|
+
}
|
|
353
|
+
|
|
354
|
+
return { messages, toolCalls, result, isComplete };
|
|
355
|
+
},
|
|
356
|
+
};
|
|
@@ -0,0 +1,183 @@
|
|
|
1
|
+
import type { Task } from '../../types/index.js';
|
|
2
|
+
import type { MemorySystem } from '../../memory/system.js';
|
|
3
|
+
import type { LearningPipeline, ProcessResult, BatchResult } from '../../learning/index.js';
|
|
4
|
+
import type { AgentManager } from '../manager.js';
|
|
5
|
+
import type { AgentResult, AgentSession, AgentObserverCallbacks } from '../types.js';
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Configuration for the learning flow
|
|
9
|
+
*/
|
|
10
|
+
export interface LearningFlowConfig {
|
|
11
|
+
/** Agent type to use for execution */
|
|
12
|
+
agentType: string;
|
|
13
|
+
/** Minimum trajectories before running batch learning */
|
|
14
|
+
batchThreshold?: number;
|
|
15
|
+
/** Whether to auto-run batch learning when threshold is reached */
|
|
16
|
+
autoBatch?: boolean;
|
|
17
|
+
/** Observer callbacks for real-time monitoring */
|
|
18
|
+
observer?: AgentObserverCallbacks;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Result of a learning flow execution
|
|
23
|
+
*/
|
|
24
|
+
export interface LearningFlowResult {
|
|
25
|
+
/** The agent result */
|
|
26
|
+
agentResult: AgentResult;
|
|
27
|
+
/** Processing result from learning pipeline */
|
|
28
|
+
processResult: ProcessResult;
|
|
29
|
+
/** Batch result if batch learning was triggered */
|
|
30
|
+
batchResult?: BatchResult;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Learning Flow
|
|
35
|
+
* Orchestrates: Agent execution → Trajectory capture → Playbook extraction → Memory storage
|
|
36
|
+
*
|
|
37
|
+
* This flow is for the "observation" direction:
|
|
38
|
+
* - Watch agents solve tasks
|
|
39
|
+
* - Extract learning signals from their trajectories
|
|
40
|
+
* - Store playbooks for future guidance
|
|
41
|
+
*/
|
|
42
|
+
export class LearningFlow {
|
|
43
|
+
private manager: AgentManager;
|
|
44
|
+
private pipeline: LearningPipeline;
|
|
45
|
+
private config: LearningFlowConfig;
|
|
46
|
+
|
|
47
|
+
constructor(
|
|
48
|
+
manager: AgentManager,
|
|
49
|
+
pipeline: LearningPipeline,
|
|
50
|
+
_memory: MemorySystem,
|
|
51
|
+
config: LearningFlowConfig
|
|
52
|
+
) {
|
|
53
|
+
this.manager = manager;
|
|
54
|
+
this.pipeline = pipeline;
|
|
55
|
+
this.config = {
|
|
56
|
+
batchThreshold: 10,
|
|
57
|
+
autoBatch: true,
|
|
58
|
+
...config,
|
|
59
|
+
};
|
|
60
|
+
|
|
61
|
+
// Register observer if provided
|
|
62
|
+
if (config.observer) {
|
|
63
|
+
this.manager.addObserver(config.observer);
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* Run a single task through the learning flow
|
|
69
|
+
*/
|
|
70
|
+
async run(task: Task): Promise<LearningFlowResult> {
|
|
71
|
+
// 1. Spawn agent and get result (WITHOUT knowledge injection for pure learning)
|
|
72
|
+
const agentResult = await this.manager.spawnBaseline({
|
|
73
|
+
agentType: this.config.agentType,
|
|
74
|
+
task,
|
|
75
|
+
captureToolCalls: true,
|
|
76
|
+
});
|
|
77
|
+
|
|
78
|
+
// 2. Process trajectory through learning pipeline
|
|
79
|
+
const processResult = await this.pipeline.processTrajectory(
|
|
80
|
+
agentResult.trajectory
|
|
81
|
+
);
|
|
82
|
+
|
|
83
|
+
// 3. Run batch learning if threshold reached
|
|
84
|
+
let batchResult: BatchResult | undefined;
|
|
85
|
+
if (
|
|
86
|
+
this.config.autoBatch &&
|
|
87
|
+
this.pipeline.getAccumulatedCount() >= (this.config.batchThreshold ?? 10)
|
|
88
|
+
) {
|
|
89
|
+
batchResult = await this.pipeline.runBatchLearning();
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
return {
|
|
93
|
+
agentResult,
|
|
94
|
+
processResult,
|
|
95
|
+
batchResult,
|
|
96
|
+
};
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
/**
|
|
100
|
+
* Run multiple tasks through the learning flow
|
|
101
|
+
*/
|
|
102
|
+
async runBatch(tasks: Task[]): Promise<LearningFlowResult[]> {
|
|
103
|
+
const results: LearningFlowResult[] = [];
|
|
104
|
+
for (const task of tasks) {
|
|
105
|
+
const result = await this.run(task);
|
|
106
|
+
results.push(result);
|
|
107
|
+
}
|
|
108
|
+
return results;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
/**
|
|
112
|
+
* Observe an external session and learn from it
|
|
113
|
+
* Use this when another system provides the session
|
|
114
|
+
*/
|
|
115
|
+
async observeExternal(
|
|
116
|
+
session: AgentSession,
|
|
117
|
+
task: Task
|
|
118
|
+
): Promise<LearningFlowResult> {
|
|
119
|
+
// Extract trajectory from session
|
|
120
|
+
const trajectory = await this.manager.observeAndLearn(session, task);
|
|
121
|
+
|
|
122
|
+
// Process through learning pipeline
|
|
123
|
+
const processResult = await this.pipeline.processTrajectory(trajectory);
|
|
124
|
+
|
|
125
|
+
// Check for batch learning
|
|
126
|
+
let batchResult: BatchResult | undefined;
|
|
127
|
+
if (
|
|
128
|
+
this.config.autoBatch &&
|
|
129
|
+
this.pipeline.getAccumulatedCount() >= (this.config.batchThreshold ?? 10)
|
|
130
|
+
) {
|
|
131
|
+
batchResult = await this.pipeline.runBatchLearning();
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
return {
|
|
135
|
+
agentResult: {
|
|
136
|
+
session,
|
|
137
|
+
trajectory,
|
|
138
|
+
success: session.state === 'completed',
|
|
139
|
+
metrics: {
|
|
140
|
+
totalTime: session.endTime
|
|
141
|
+
? session.endTime.getTime() - session.startTime.getTime()
|
|
142
|
+
: 0,
|
|
143
|
+
toolCallCount: session.toolCalls.length,
|
|
144
|
+
messageCount: session.messages.length,
|
|
145
|
+
},
|
|
146
|
+
},
|
|
147
|
+
processResult,
|
|
148
|
+
batchResult,
|
|
149
|
+
};
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
/**
|
|
153
|
+
* Force batch learning
|
|
154
|
+
*/
|
|
155
|
+
async runBatchLearning(): Promise<BatchResult> {
|
|
156
|
+
return this.pipeline.runBatchLearning();
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
/**
|
|
160
|
+
* Get learning statistics
|
|
161
|
+
*/
|
|
162
|
+
getStats(): {
|
|
163
|
+
pendingTrajectories: number;
|
|
164
|
+
batchThreshold: number;
|
|
165
|
+
} {
|
|
166
|
+
return {
|
|
167
|
+
pendingTrajectories: this.pipeline.getAccumulatedCount(),
|
|
168
|
+
batchThreshold: this.config.batchThreshold ?? 10,
|
|
169
|
+
};
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
/**
|
|
174
|
+
* Create a learning flow
|
|
175
|
+
*/
|
|
176
|
+
export function createLearningFlow(
|
|
177
|
+
manager: AgentManager,
|
|
178
|
+
pipeline: LearningPipeline,
|
|
179
|
+
memory: MemorySystem,
|
|
180
|
+
config: LearningFlowConfig
|
|
181
|
+
): LearningFlow {
|
|
182
|
+
return new LearningFlow(manager, pipeline, memory, config);
|
|
183
|
+
}
|