create-bk-agent 0.23.4 → 0.23.5
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/dist/src/add/patcher.js +106 -68
- package/dist/src/scaffold.js +28 -15
- package/package.json +2 -2
- package/templates/base/autonomous/package.json +1 -1
- package/templates/base/autonomous/src/index.ts +83 -83
- package/templates/base/coding/package.json +1 -1
- package/templates/base/enterprise/package.json +1 -1
- package/templates/base/minimal/package.json +1 -1
- package/templates/base/minimal/src/index.ts +43 -43
- package/templates/base/multi-agent/package.json +2 -2
- package/templates/base/multi-agent/src/engine.ts +78 -78
- package/templates/base/single/package.json +2 -2
- package/templates/base/single/src/engine.ts +67 -67
- package/templates/autonomous/.env.example +0 -8
- package/templates/autonomous/package.json +0 -25
- package/templates/autonomous/src/index.ts +0 -64
- package/templates/autonomous/tsconfig.json +0 -16
- package/templates/base/multi-agent/src/providers/openai-compatible.ts +0 -104
- package/templates/base/single/src/providers/openai-compatible.ts +0 -104
- package/templates/coding/.env.example +0 -8
- package/templates/coding/package.json +0 -26
- package/templates/coding/src/index.ts +0 -42
- package/templates/coding/tsconfig.json +0 -17
- package/templates/domain-agent/.env.example +0 -7
- package/templates/domain-agent/package.json +0 -27
- package/templates/domain-agent/src/agents/orchestrator.ts +0 -22
- package/templates/domain-agent/src/agents/specialist-a.ts +0 -17
- package/templates/domain-agent/src/agents/specialist-b.ts +0 -16
- package/templates/domain-agent/src/config.ts +0 -19
- package/templates/domain-agent/src/engine.ts +0 -49
- package/templates/domain-agent/src/index.ts +0 -27
- package/templates/domain-agent/src/providers/openai-compatible.ts +0 -104
- package/templates/domain-agent/src/tools/example-tools.ts +0 -28
- package/templates/domain-agent/tsconfig.json +0 -17
- package/templates/mcp-server/package.json +0 -30
- package/templates/mcp-server/src/server.ts +0 -40
- package/templates/mcp-server/src/tools/example.ts +0 -10
- package/templates/mcp-server/tsconfig.json +0 -16
- package/templates/minimal/package.json +0 -25
- package/templates/minimal/src/index.ts +0 -40
- package/templates/minimal/tsconfig.json +0 -16
|
@@ -1,78 +1,78 @@
|
|
|
1
|
-
import * as os from 'os';
|
|
2
|
-
import * as path from 'path';
|
|
3
|
-
import {
|
|
4
|
-
AgentEngine,
|
|
5
|
-
AgentRegistry,
|
|
6
|
-
ToolRegistry,
|
|
7
|
-
ProviderRegistry,
|
|
8
|
-
CallbackTransport,
|
|
9
|
-
createMemorySystem,
|
|
10
|
-
} from '@backendkit-labs/agent-core';
|
|
11
|
-
import { OpenAICompatibleProvider } from '
|
|
12
|
-
import { loadConfig } from './config';
|
|
13
|
-
import { ORCHESTRATOR_PROFILE } from './agents/orchestrator';
|
|
14
|
-
import { SPECIALIST_A_PROFILE } from './agents/specialist-a';
|
|
15
|
-
import { SPECIALIST_B_PROFILE } from './agents/specialist-b';
|
|
16
|
-
import { exampleAction, exampleQuery } from './tools/example-tools';
|
|
17
|
-
|
|
18
|
-
// ── Persistent storage paths ──────────────────────────────────────────────────
|
|
19
|
-
// All state lives in ~/.my-agent/ so it survives restarts.
|
|
20
|
-
|
|
21
|
-
const APP_DIR = path.join(os.homedir(), '.my-agent');
|
|
22
|
-
const HISTORY = path.join(APP_DIR, 'history.json');
|
|
23
|
-
const MEM_DIR = path.join(APP_DIR, 'memory');
|
|
24
|
-
|
|
25
|
-
// ── Memory system ─────────────────────────────────────────────────────────────
|
|
26
|
-
// Three-tier: episodic (past experiences) + semantic (knowledge) + procedural (patterns).
|
|
27
|
-
// buildContextBlock() auto-injects relevant memories into each agent turn.
|
|
28
|
-
|
|
29
|
-
const memory = createMemorySystem({
|
|
30
|
-
episodic: { provider: 'json', path: path.join(MEM_DIR, 'episodes.json') },
|
|
31
|
-
semantic: { provider: 'json', path: path.join(MEM_DIR, 'knowledge.json') },
|
|
32
|
-
procedural: { provider: 'json', path: path.join(MEM_DIR, 'patterns.json') },
|
|
33
|
-
retention: { maxEpisodes: 500 },
|
|
34
|
-
});
|
|
35
|
-
|
|
36
|
-
export function createEngine(transport: CallbackTransport): AgentEngine {
|
|
37
|
-
const config = loadConfig();
|
|
38
|
-
|
|
39
|
-
const tools = new ToolRegistry();
|
|
40
|
-
tools
|
|
41
|
-
.register(exampleAction)
|
|
42
|
-
.register(exampleQuery);
|
|
43
|
-
// Register memory tools so agents can explicitly save/recall memories
|
|
44
|
-
for (const t of memory.getTools()) tools.register(t);
|
|
45
|
-
// TODO: register more tools
|
|
46
|
-
|
|
47
|
-
const agents = new AgentRegistry();
|
|
48
|
-
agents
|
|
49
|
-
.register(ORCHESTRATOR_PROFILE)
|
|
50
|
-
.register(SPECIALIST_A_PROFILE)
|
|
51
|
-
.register(SPECIALIST_B_PROFILE);
|
|
52
|
-
// TODO: register more specialists
|
|
53
|
-
|
|
54
|
-
const providers = new ProviderRegistry();
|
|
55
|
-
providers.register('default', new OpenAICompatibleProvider({
|
|
56
|
-
apiKey: config.llmApiKey,
|
|
57
|
-
baseUrl: config.llmBaseUrl,
|
|
58
|
-
model: config.llmModel,
|
|
59
|
-
}));
|
|
60
|
-
|
|
61
|
-
return new AgentEngine({
|
|
62
|
-
model: { provider: 'default', id: config.llmModel },
|
|
63
|
-
agents,
|
|
64
|
-
tools,
|
|
65
|
-
providers,
|
|
66
|
-
defaultProvider: 'default',
|
|
67
|
-
defaultAgentId: 'orchestrator',
|
|
68
|
-
transport,
|
|
69
|
-
maxIterations: 30,
|
|
70
|
-
iterationMode: 'auto',
|
|
71
|
-
// Conversation history — persists between runs
|
|
72
|
-
historyPath: HISTORY,
|
|
73
|
-
maxContextMessages: 100,
|
|
74
|
-
// Long-term memory — injects relevant context each turn
|
|
75
|
-
memorySystem: memory,
|
|
76
|
-
additionalRoots: [APP_DIR],
|
|
77
|
-
});
|
|
78
|
-
}
|
|
1
|
+
import * as os from 'os';
|
|
2
|
+
import * as path from 'path';
|
|
3
|
+
import {
|
|
4
|
+
AgentEngine,
|
|
5
|
+
AgentRegistry,
|
|
6
|
+
ToolRegistry,
|
|
7
|
+
ProviderRegistry,
|
|
8
|
+
CallbackTransport,
|
|
9
|
+
createMemorySystem,
|
|
10
|
+
} from '@backendkit-labs/agent-core';
|
|
11
|
+
import { OpenAICompatibleProvider } from '@backendkit-labs/agent-providers';
|
|
12
|
+
import { loadConfig } from './config';
|
|
13
|
+
import { ORCHESTRATOR_PROFILE } from './agents/orchestrator';
|
|
14
|
+
import { SPECIALIST_A_PROFILE } from './agents/specialist-a';
|
|
15
|
+
import { SPECIALIST_B_PROFILE } from './agents/specialist-b';
|
|
16
|
+
import { exampleAction, exampleQuery } from './tools/example-tools';
|
|
17
|
+
|
|
18
|
+
// ── Persistent storage paths ──────────────────────────────────────────────────
|
|
19
|
+
// All state lives in ~/.my-agent/ so it survives restarts.
|
|
20
|
+
|
|
21
|
+
const APP_DIR = path.join(os.homedir(), '.my-agent');
|
|
22
|
+
const HISTORY = path.join(APP_DIR, 'history.json');
|
|
23
|
+
const MEM_DIR = path.join(APP_DIR, 'memory');
|
|
24
|
+
|
|
25
|
+
// ── Memory system ─────────────────────────────────────────────────────────────
|
|
26
|
+
// Three-tier: episodic (past experiences) + semantic (knowledge) + procedural (patterns).
|
|
27
|
+
// buildContextBlock() auto-injects relevant memories into each agent turn.
|
|
28
|
+
|
|
29
|
+
const memory = createMemorySystem({
|
|
30
|
+
episodic: { provider: 'json', path: path.join(MEM_DIR, 'episodes.json') },
|
|
31
|
+
semantic: { provider: 'json', path: path.join(MEM_DIR, 'knowledge.json') },
|
|
32
|
+
procedural: { provider: 'json', path: path.join(MEM_DIR, 'patterns.json') },
|
|
33
|
+
retention: { maxEpisodes: 500 },
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
export function createEngine(transport: CallbackTransport): AgentEngine {
|
|
37
|
+
const config = loadConfig();
|
|
38
|
+
|
|
39
|
+
const tools = new ToolRegistry();
|
|
40
|
+
tools
|
|
41
|
+
.register(exampleAction)
|
|
42
|
+
.register(exampleQuery);
|
|
43
|
+
// Register memory tools so agents can explicitly save/recall memories
|
|
44
|
+
for (const t of memory.getTools()) tools.register(t);
|
|
45
|
+
// TODO: register more tools
|
|
46
|
+
|
|
47
|
+
const agents = new AgentRegistry();
|
|
48
|
+
agents
|
|
49
|
+
.register(ORCHESTRATOR_PROFILE)
|
|
50
|
+
.register(SPECIALIST_A_PROFILE)
|
|
51
|
+
.register(SPECIALIST_B_PROFILE);
|
|
52
|
+
// TODO: register more specialists
|
|
53
|
+
|
|
54
|
+
const providers = new ProviderRegistry();
|
|
55
|
+
providers.register('default', new OpenAICompatibleProvider({
|
|
56
|
+
apiKey: config.llmApiKey,
|
|
57
|
+
baseUrl: config.llmBaseUrl,
|
|
58
|
+
model: config.llmModel,
|
|
59
|
+
}));
|
|
60
|
+
|
|
61
|
+
return new AgentEngine({
|
|
62
|
+
model: { provider: 'default', id: config.llmModel },
|
|
63
|
+
agents,
|
|
64
|
+
tools,
|
|
65
|
+
providers,
|
|
66
|
+
defaultProvider: 'default',
|
|
67
|
+
defaultAgentId: 'orchestrator',
|
|
68
|
+
transport,
|
|
69
|
+
maxIterations: 30,
|
|
70
|
+
iterationMode: 'auto',
|
|
71
|
+
// Conversation history — persists between runs
|
|
72
|
+
historyPath: HISTORY,
|
|
73
|
+
maxContextMessages: 100,
|
|
74
|
+
// Long-term memory — injects relevant context each turn
|
|
75
|
+
memorySystem: memory,
|
|
76
|
+
additionalRoots: [APP_DIR],
|
|
77
|
+
});
|
|
78
|
+
}
|
|
@@ -12,9 +12,9 @@
|
|
|
12
12
|
"typecheck": "tsc --noEmit"
|
|
13
13
|
},
|
|
14
14
|
"dependencies": {
|
|
15
|
-
"@backendkit-labs/agent-core": "^0.
|
|
15
|
+
"@backendkit-labs/agent-core": "^0.37.0",
|
|
16
|
+
"@backendkit-labs/agent-providers": "^0.3.3",
|
|
16
17
|
"dotenv": "^16.0.0",
|
|
17
|
-
"openai": "^4.0.0",
|
|
18
18
|
"zod": "^4.6.6"
|
|
19
19
|
},
|
|
20
20
|
"devDependencies": {
|
|
@@ -1,67 +1,67 @@
|
|
|
1
|
-
import * as os from 'os';
|
|
2
|
-
import * as path from 'path';
|
|
3
|
-
import {
|
|
4
|
-
AgentEngine,
|
|
5
|
-
AgentRegistry,
|
|
6
|
-
ToolRegistry,
|
|
7
|
-
ProviderRegistry,
|
|
8
|
-
CallbackTransport,
|
|
9
|
-
createMemorySystem,
|
|
10
|
-
} from '@backendkit-labs/agent-core';
|
|
11
|
-
import { OpenAICompatibleProvider } from '
|
|
12
|
-
import { loadConfig } from './config';
|
|
13
|
-
import { MY_AGENT_PROFILE } from './agents/my-agent';
|
|
14
|
-
import { exampleAction, exampleQuery } from './tools/example-tools';
|
|
15
|
-
|
|
16
|
-
// ── Persistent storage paths ──────────────────────────────────────────────────
|
|
17
|
-
|
|
18
|
-
const APP_DIR = path.join(os.homedir(), '.my-agent');
|
|
19
|
-
const HISTORY = path.join(APP_DIR, 'history.json');
|
|
20
|
-
const MEM_DIR = path.join(APP_DIR, 'memory');
|
|
21
|
-
|
|
22
|
-
// ── Memory system ─────────────────────────────────────────────────────────────
|
|
23
|
-
|
|
24
|
-
const memory = createMemorySystem({
|
|
25
|
-
episodic: { provider: 'json', path: path.join(MEM_DIR, 'episodes.json') },
|
|
26
|
-
semantic: { provider: 'json', path: path.join(MEM_DIR, 'knowledge.json') },
|
|
27
|
-
procedural: { provider: 'json', path: path.join(MEM_DIR, 'patterns.json') },
|
|
28
|
-
retention: { maxEpisodes: 500 },
|
|
29
|
-
});
|
|
30
|
-
|
|
31
|
-
export function createEngine(transport: CallbackTransport): AgentEngine {
|
|
32
|
-
const config = loadConfig();
|
|
33
|
-
|
|
34
|
-
const tools = new ToolRegistry();
|
|
35
|
-
tools
|
|
36
|
-
.register(exampleAction)
|
|
37
|
-
.register(exampleQuery);
|
|
38
|
-
for (const t of memory.getTools()) tools.register(t);
|
|
39
|
-
// TODO: register more tools
|
|
40
|
-
|
|
41
|
-
const agents = new AgentRegistry();
|
|
42
|
-
agents.register(MY_AGENT_PROFILE);
|
|
43
|
-
// TODO: register more specialists
|
|
44
|
-
|
|
45
|
-
const providers = new ProviderRegistry();
|
|
46
|
-
providers.register('default', new OpenAICompatibleProvider({
|
|
47
|
-
apiKey: config.llmApiKey,
|
|
48
|
-
baseUrl: config.llmBaseUrl,
|
|
49
|
-
model: config.llmModel,
|
|
50
|
-
}));
|
|
51
|
-
|
|
52
|
-
return new AgentEngine({
|
|
53
|
-
model: { provider: 'default', id: config.llmModel },
|
|
54
|
-
agents,
|
|
55
|
-
tools,
|
|
56
|
-
providers,
|
|
57
|
-
defaultProvider: 'default',
|
|
58
|
-
defaultAgentId: 'my-agent',
|
|
59
|
-
transport,
|
|
60
|
-
maxIterations: 20,
|
|
61
|
-
iterationMode: 'auto',
|
|
62
|
-
historyPath: HISTORY,
|
|
63
|
-
maxContextMessages: 100,
|
|
64
|
-
memorySystem: memory,
|
|
65
|
-
additionalRoots: [APP_DIR],
|
|
66
|
-
});
|
|
67
|
-
}
|
|
1
|
+
import * as os from 'os';
|
|
2
|
+
import * as path from 'path';
|
|
3
|
+
import {
|
|
4
|
+
AgentEngine,
|
|
5
|
+
AgentRegistry,
|
|
6
|
+
ToolRegistry,
|
|
7
|
+
ProviderRegistry,
|
|
8
|
+
CallbackTransport,
|
|
9
|
+
createMemorySystem,
|
|
10
|
+
} from '@backendkit-labs/agent-core';
|
|
11
|
+
import { OpenAICompatibleProvider } from '@backendkit-labs/agent-providers';
|
|
12
|
+
import { loadConfig } from './config';
|
|
13
|
+
import { MY_AGENT_PROFILE } from './agents/my-agent';
|
|
14
|
+
import { exampleAction, exampleQuery } from './tools/example-tools';
|
|
15
|
+
|
|
16
|
+
// ── Persistent storage paths ──────────────────────────────────────────────────
|
|
17
|
+
|
|
18
|
+
const APP_DIR = path.join(os.homedir(), '.my-agent');
|
|
19
|
+
const HISTORY = path.join(APP_DIR, 'history.json');
|
|
20
|
+
const MEM_DIR = path.join(APP_DIR, 'memory');
|
|
21
|
+
|
|
22
|
+
// ── Memory system ─────────────────────────────────────────────────────────────
|
|
23
|
+
|
|
24
|
+
const memory = createMemorySystem({
|
|
25
|
+
episodic: { provider: 'json', path: path.join(MEM_DIR, 'episodes.json') },
|
|
26
|
+
semantic: { provider: 'json', path: path.join(MEM_DIR, 'knowledge.json') },
|
|
27
|
+
procedural: { provider: 'json', path: path.join(MEM_DIR, 'patterns.json') },
|
|
28
|
+
retention: { maxEpisodes: 500 },
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
export function createEngine(transport: CallbackTransport): AgentEngine {
|
|
32
|
+
const config = loadConfig();
|
|
33
|
+
|
|
34
|
+
const tools = new ToolRegistry();
|
|
35
|
+
tools
|
|
36
|
+
.register(exampleAction)
|
|
37
|
+
.register(exampleQuery);
|
|
38
|
+
for (const t of memory.getTools()) tools.register(t);
|
|
39
|
+
// TODO: register more tools
|
|
40
|
+
|
|
41
|
+
const agents = new AgentRegistry();
|
|
42
|
+
agents.register(MY_AGENT_PROFILE);
|
|
43
|
+
// TODO: register more specialists
|
|
44
|
+
|
|
45
|
+
const providers = new ProviderRegistry();
|
|
46
|
+
providers.register('default', new OpenAICompatibleProvider({
|
|
47
|
+
apiKey: config.llmApiKey,
|
|
48
|
+
baseUrl: config.llmBaseUrl,
|
|
49
|
+
model: config.llmModel,
|
|
50
|
+
}));
|
|
51
|
+
|
|
52
|
+
return new AgentEngine({
|
|
53
|
+
model: { provider: 'default', id: config.llmModel },
|
|
54
|
+
agents,
|
|
55
|
+
tools,
|
|
56
|
+
providers,
|
|
57
|
+
defaultProvider: 'default',
|
|
58
|
+
defaultAgentId: 'my-agent',
|
|
59
|
+
transport,
|
|
60
|
+
maxIterations: 20,
|
|
61
|
+
iterationMode: 'auto',
|
|
62
|
+
historyPath: HISTORY,
|
|
63
|
+
maxContextMessages: 100,
|
|
64
|
+
memorySystem: memory,
|
|
65
|
+
additionalRoots: [APP_DIR],
|
|
66
|
+
});
|
|
67
|
+
}
|
|
@@ -1,25 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "my-autonomous-agent",
|
|
3
|
-
"version": "0.1.0",
|
|
4
|
-
"private": true,
|
|
5
|
-
"description": "Autonomous agent — activates on cron, webhooks, or custom events",
|
|
6
|
-
"main": "dist/index.js",
|
|
7
|
-
"scripts": {
|
|
8
|
-
"dev": "ts-node src/index.ts",
|
|
9
|
-
"build": "tsc",
|
|
10
|
-
"start": "node dist/index.js",
|
|
11
|
-
"typecheck": "tsc --noEmit"
|
|
12
|
-
},
|
|
13
|
-
"dependencies": {
|
|
14
|
-
"@backendkit-labs/agent-core": "^0.36.0",
|
|
15
|
-
"dotenv": "^16.0.0"
|
|
16
|
-
},
|
|
17
|
-
"devDependencies": {
|
|
18
|
-
"@types/node": "^20.0.0",
|
|
19
|
-
"ts-node": "^10.9.0",
|
|
20
|
-
"typescript": "^5.4.0"
|
|
21
|
-
},
|
|
22
|
-
"engines": {
|
|
23
|
-
"node": ">=20.0.0"
|
|
24
|
-
}
|
|
25
|
-
}
|
|
@@ -1,64 +0,0 @@
|
|
|
1
|
-
import 'dotenv/config';
|
|
2
|
-
import { createAutonomousAgent } from '@backendkit-labs/agent-core';
|
|
3
|
-
import type { AgentProfile } from '@backendkit-labs/agent-core';
|
|
4
|
-
|
|
5
|
-
// ── Agent definition ──────────────────────────────────────────────────────────
|
|
6
|
-
|
|
7
|
-
const monitorAgent: AgentProfile = {
|
|
8
|
-
id: 'monitor',
|
|
9
|
-
name: 'Monitor',
|
|
10
|
-
icon: '👁',
|
|
11
|
-
description: 'Monitors events and executes scheduled tasks',
|
|
12
|
-
allowedTools: [],
|
|
13
|
-
delegatesTo: [],
|
|
14
|
-
systemPrompt: `You are an autonomous monitor agent.
|
|
15
|
-
// TODO: describe what this agent monitors and what actions it takes.
|
|
16
|
-
When activated by a trigger, analyze the input and take appropriate action.`,
|
|
17
|
-
};
|
|
18
|
-
|
|
19
|
-
// ── Provider ──────────────────────────────────────────────────────────────────
|
|
20
|
-
|
|
21
|
-
const provider = process.env.LLM_PROVIDER ?? 'anthropic';
|
|
22
|
-
const apiKey = process.env.ANTHROPIC_API_KEY ?? process.env.OPENAI_API_KEY ?? '';
|
|
23
|
-
|
|
24
|
-
if (!apiKey) { console.error('Missing API key'); process.exit(1); }
|
|
25
|
-
|
|
26
|
-
// ── Autonomous agent ──────────────────────────────────────────────────────────
|
|
27
|
-
|
|
28
|
-
const agent = createAutonomousAgent({
|
|
29
|
-
providers: { [provider]: { apiKey } },
|
|
30
|
-
defaultProvider: provider,
|
|
31
|
-
agents: [monitorAgent],
|
|
32
|
-
defaultAgent: 'monitor',
|
|
33
|
-
goal: 'TODO: describe the agent goal',
|
|
34
|
-
|
|
35
|
-
triggers: [
|
|
36
|
-
// Run every day at 9:00 AM
|
|
37
|
-
{
|
|
38
|
-
type: 'schedule',
|
|
39
|
-
cron: '0 9 * * *',
|
|
40
|
-
task: 'Run daily check and report findings',
|
|
41
|
-
},
|
|
42
|
-
|
|
43
|
-
// Listen for webhook events (e.g. from GitHub, Slack, etc.)
|
|
44
|
-
{
|
|
45
|
-
type: 'webhook',
|
|
46
|
-
path: '/events',
|
|
47
|
-
// secret: process.env.WEBHOOK_SECRET, // uncomment to validate signatures
|
|
48
|
-
},
|
|
49
|
-
|
|
50
|
-
// TODO: add more triggers as needed
|
|
51
|
-
// { type: 'event', topic: 'my.custom.event' },
|
|
52
|
-
],
|
|
53
|
-
|
|
54
|
-
webhookPort: parseInt(process.env.WEBHOOK_PORT ?? '3000'),
|
|
55
|
-
});
|
|
56
|
-
|
|
57
|
-
// ── Start ─────────────────────────────────────────────────────────────────────
|
|
58
|
-
|
|
59
|
-
await agent.start();
|
|
60
|
-
console.log('Autonomous agent started.');
|
|
61
|
-
console.log('Webhook listening on port', process.env.WEBHOOK_PORT ?? 3000);
|
|
62
|
-
|
|
63
|
-
process.on('SIGTERM', async () => { await agent.stop(); process.exit(0); });
|
|
64
|
-
process.on('SIGINT', async () => { await agent.stop(); process.exit(0); });
|
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"compilerOptions": {
|
|
3
|
-
"target": "ES2022",
|
|
4
|
-
"module": "commonjs",
|
|
5
|
-
"moduleResolution": "node16",
|
|
6
|
-
"lib": ["ES2022"],
|
|
7
|
-
"types": ["node"],
|
|
8
|
-
"outDir": "dist",
|
|
9
|
-
"rootDir": "src",
|
|
10
|
-
"strict": true,
|
|
11
|
-
"skipLibCheck": true,
|
|
12
|
-
"esModuleInterop": true
|
|
13
|
-
},
|
|
14
|
-
"include": ["src/**/*"],
|
|
15
|
-
"exclude": ["node_modules", "dist"]
|
|
16
|
-
}
|
|
@@ -1,104 +0,0 @@
|
|
|
1
|
-
import OpenAI from 'openai';
|
|
2
|
-
import type { LLMProvider, LLMMessage, LLMStreamCallbacks, ToolDefinition } from '@backendkit-labs/agent-core';
|
|
3
|
-
|
|
4
|
-
export interface OpenAICompatibleProviderOptions {
|
|
5
|
-
apiKey: string;
|
|
6
|
-
baseUrl: string;
|
|
7
|
-
model: string;
|
|
8
|
-
maxRetries?: number;
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
function isRetryable(err: unknown): boolean {
|
|
12
|
-
if (err && typeof err === 'object' && 'status' in err) {
|
|
13
|
-
const s = (err as { status: number }).status;
|
|
14
|
-
return s === 429 || s >= 500;
|
|
15
|
-
}
|
|
16
|
-
return false;
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
const sleep = (ms: number) => new Promise<void>(r => setTimeout(r, ms));
|
|
20
|
-
|
|
21
|
-
export class OpenAICompatibleProvider implements LLMProvider {
|
|
22
|
-
private readonly client: OpenAI;
|
|
23
|
-
private readonly model: string;
|
|
24
|
-
private readonly maxRetries: number;
|
|
25
|
-
|
|
26
|
-
constructor(opts: OpenAICompatibleProviderOptions) {
|
|
27
|
-
this.client = new OpenAI({ apiKey: opts.apiKey, baseURL: opts.baseUrl, maxRetries: 0 });
|
|
28
|
-
this.model = opts.model;
|
|
29
|
-
this.maxRetries = opts.maxRetries ?? 3;
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
async chat(messages: LLMMessage[], tools: ToolDefinition[], callbacks: LLMStreamCallbacks): Promise<void> {
|
|
33
|
-
const oaiTools = tools.map(t => ({
|
|
34
|
-
type: 'function' as const,
|
|
35
|
-
function: { name: t.name, description: t.description, parameters: t.parameters },
|
|
36
|
-
})) as OpenAI.Chat.ChatCompletionTool[];
|
|
37
|
-
|
|
38
|
-
let attempt = 0;
|
|
39
|
-
let emitted = false;
|
|
40
|
-
|
|
41
|
-
while (attempt < this.maxRetries) {
|
|
42
|
-
attempt++;
|
|
43
|
-
try {
|
|
44
|
-
await this.stream(messages, oaiTools, {
|
|
45
|
-
...callbacks,
|
|
46
|
-
onChunk: (d) => { emitted = true; callbacks.onChunk?.(d); },
|
|
47
|
-
});
|
|
48
|
-
return;
|
|
49
|
-
} catch (err) {
|
|
50
|
-
if (emitted || !isRetryable(err) || attempt >= this.maxRetries) {
|
|
51
|
-
callbacks.onError(err instanceof Error ? err : new Error(String(err)));
|
|
52
|
-
return;
|
|
53
|
-
}
|
|
54
|
-
await sleep(Math.min(1000 * 2 ** attempt, 16_000));
|
|
55
|
-
}
|
|
56
|
-
}
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
private async stream(
|
|
60
|
-
messages: LLMMessage[],
|
|
61
|
-
oaiTools: OpenAI.Chat.ChatCompletionTool[],
|
|
62
|
-
callbacks: LLMStreamCallbacks,
|
|
63
|
-
): Promise<void> {
|
|
64
|
-
const stream = await this.client.chat.completions.create({
|
|
65
|
-
model: this.model,
|
|
66
|
-
messages: messages as OpenAI.Chat.ChatCompletionMessageParam[],
|
|
67
|
-
tools: oaiTools.length ? oaiTools : undefined,
|
|
68
|
-
tool_choice: oaiTools.length ? 'auto' : undefined,
|
|
69
|
-
stream: true,
|
|
70
|
-
stream_options: { include_usage: true },
|
|
71
|
-
});
|
|
72
|
-
|
|
73
|
-
let content = '';
|
|
74
|
-
const toolBuffers = new Map<number, { id: string; name: string; args: string }>();
|
|
75
|
-
|
|
76
|
-
for await (const chunk of stream) {
|
|
77
|
-
if (chunk.usage) callbacks.onMetrics?.(chunk.usage.prompt_tokens, chunk.usage.completion_tokens);
|
|
78
|
-
const delta = chunk.choices[0]?.delta;
|
|
79
|
-
if (!delta) continue;
|
|
80
|
-
if (delta.content) { content += delta.content; callbacks.onChunk?.(delta.content); }
|
|
81
|
-
if (delta.tool_calls) {
|
|
82
|
-
for (const tc of delta.tool_calls) {
|
|
83
|
-
if (!toolBuffers.has(tc.index)) toolBuffers.set(tc.index, { id: '', name: '', args: '' });
|
|
84
|
-
const buf = toolBuffers.get(tc.index)!;
|
|
85
|
-
if (tc.id) buf.id = tc.id;
|
|
86
|
-
if (tc.function?.name) buf.name += tc.function.name;
|
|
87
|
-
if (tc.function?.arguments) buf.args += tc.function.arguments;
|
|
88
|
-
}
|
|
89
|
-
}
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
const toolCalls = [...toolBuffers.entries()]
|
|
93
|
-
.sort(([a], [b]) => a - b)
|
|
94
|
-
.map(([, b]) => ({ id: b.id, type: 'function' as const, function: { name: b.name, arguments: b.args } }));
|
|
95
|
-
|
|
96
|
-
for (const tc of toolCalls) callbacks.onToolCall?.(tc.function.name, tc.function.arguments, tc.id);
|
|
97
|
-
|
|
98
|
-
callbacks.onDone({
|
|
99
|
-
role: 'assistant',
|
|
100
|
-
content: content || null,
|
|
101
|
-
tool_calls: toolCalls.length ? toolCalls : undefined,
|
|
102
|
-
});
|
|
103
|
-
}
|
|
104
|
-
}
|
|
@@ -1,104 +0,0 @@
|
|
|
1
|
-
import OpenAI from 'openai';
|
|
2
|
-
import type { LLMProvider, LLMMessage, LLMStreamCallbacks, ToolDefinition } from '@backendkit-labs/agent-core';
|
|
3
|
-
|
|
4
|
-
export interface OpenAICompatibleProviderOptions {
|
|
5
|
-
apiKey: string;
|
|
6
|
-
baseUrl: string;
|
|
7
|
-
model: string;
|
|
8
|
-
maxRetries?: number;
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
function isRetryable(err: unknown): boolean {
|
|
12
|
-
if (err && typeof err === 'object' && 'status' in err) {
|
|
13
|
-
const s = (err as { status: number }).status;
|
|
14
|
-
return s === 429 || s >= 500;
|
|
15
|
-
}
|
|
16
|
-
return false;
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
const sleep = (ms: number) => new Promise<void>(r => setTimeout(r, ms));
|
|
20
|
-
|
|
21
|
-
export class OpenAICompatibleProvider implements LLMProvider {
|
|
22
|
-
private readonly client: OpenAI;
|
|
23
|
-
private readonly model: string;
|
|
24
|
-
private readonly maxRetries: number;
|
|
25
|
-
|
|
26
|
-
constructor(opts: OpenAICompatibleProviderOptions) {
|
|
27
|
-
this.client = new OpenAI({ apiKey: opts.apiKey, baseURL: opts.baseUrl, maxRetries: 0 });
|
|
28
|
-
this.model = opts.model;
|
|
29
|
-
this.maxRetries = opts.maxRetries ?? 3;
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
async chat(messages: LLMMessage[], tools: ToolDefinition[], callbacks: LLMStreamCallbacks): Promise<void> {
|
|
33
|
-
const oaiTools = tools.map(t => ({
|
|
34
|
-
type: 'function' as const,
|
|
35
|
-
function: { name: t.name, description: t.description, parameters: t.parameters },
|
|
36
|
-
})) as OpenAI.Chat.ChatCompletionTool[];
|
|
37
|
-
|
|
38
|
-
let attempt = 0;
|
|
39
|
-
let emitted = false;
|
|
40
|
-
|
|
41
|
-
while (attempt < this.maxRetries) {
|
|
42
|
-
attempt++;
|
|
43
|
-
try {
|
|
44
|
-
await this.stream(messages, oaiTools, {
|
|
45
|
-
...callbacks,
|
|
46
|
-
onChunk: (d) => { emitted = true; callbacks.onChunk?.(d); },
|
|
47
|
-
});
|
|
48
|
-
return;
|
|
49
|
-
} catch (err) {
|
|
50
|
-
if (emitted || !isRetryable(err) || attempt >= this.maxRetries) {
|
|
51
|
-
callbacks.onError(err instanceof Error ? err : new Error(String(err)));
|
|
52
|
-
return;
|
|
53
|
-
}
|
|
54
|
-
await sleep(Math.min(1000 * 2 ** attempt, 16_000));
|
|
55
|
-
}
|
|
56
|
-
}
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
private async stream(
|
|
60
|
-
messages: LLMMessage[],
|
|
61
|
-
oaiTools: OpenAI.Chat.ChatCompletionTool[],
|
|
62
|
-
callbacks: LLMStreamCallbacks,
|
|
63
|
-
): Promise<void> {
|
|
64
|
-
const stream = await this.client.chat.completions.create({
|
|
65
|
-
model: this.model,
|
|
66
|
-
messages: messages as OpenAI.Chat.ChatCompletionMessageParam[],
|
|
67
|
-
tools: oaiTools.length ? oaiTools : undefined,
|
|
68
|
-
tool_choice: oaiTools.length ? 'auto' : undefined,
|
|
69
|
-
stream: true,
|
|
70
|
-
stream_options: { include_usage: true },
|
|
71
|
-
});
|
|
72
|
-
|
|
73
|
-
let content = '';
|
|
74
|
-
const toolBuffers = new Map<number, { id: string; name: string; args: string }>();
|
|
75
|
-
|
|
76
|
-
for await (const chunk of stream) {
|
|
77
|
-
if (chunk.usage) callbacks.onMetrics?.(chunk.usage.prompt_tokens, chunk.usage.completion_tokens);
|
|
78
|
-
const delta = chunk.choices[0]?.delta;
|
|
79
|
-
if (!delta) continue;
|
|
80
|
-
if (delta.content) { content += delta.content; callbacks.onChunk?.(delta.content); }
|
|
81
|
-
if (delta.tool_calls) {
|
|
82
|
-
for (const tc of delta.tool_calls) {
|
|
83
|
-
if (!toolBuffers.has(tc.index)) toolBuffers.set(tc.index, { id: '', name: '', args: '' });
|
|
84
|
-
const buf = toolBuffers.get(tc.index)!;
|
|
85
|
-
if (tc.id) buf.id = tc.id;
|
|
86
|
-
if (tc.function?.name) buf.name += tc.function.name;
|
|
87
|
-
if (tc.function?.arguments) buf.args += tc.function.arguments;
|
|
88
|
-
}
|
|
89
|
-
}
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
const toolCalls = [...toolBuffers.entries()]
|
|
93
|
-
.sort(([a], [b]) => a - b)
|
|
94
|
-
.map(([, b]) => ({ id: b.id, type: 'function' as const, function: { name: b.name, arguments: b.args } }));
|
|
95
|
-
|
|
96
|
-
for (const tc of toolCalls) callbacks.onToolCall?.(tc.function.name, tc.function.arguments, tc.id);
|
|
97
|
-
|
|
98
|
-
callbacks.onDone({
|
|
99
|
-
role: 'assistant',
|
|
100
|
-
content: content || null,
|
|
101
|
-
tool_calls: toolCalls.length ? toolCalls : undefined,
|
|
102
|
-
});
|
|
103
|
-
}
|
|
104
|
-
}
|
|
@@ -1,26 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "my-coding-agent",
|
|
3
|
-
"version": "0.1.0",
|
|
4
|
-
"private": true,
|
|
5
|
-
"description": "Coding assistant agent — edit files, run commands, search code",
|
|
6
|
-
"main": "dist/index.js",
|
|
7
|
-
"scripts": {
|
|
8
|
-
"dev": "ts-node src/index.ts",
|
|
9
|
-
"build": "tsc",
|
|
10
|
-
"start": "node dist/index.js",
|
|
11
|
-
"typecheck": "tsc --noEmit"
|
|
12
|
-
},
|
|
13
|
-
"dependencies": {
|
|
14
|
-
"@backendkit-labs/agent-coding": "^0.28.0",
|
|
15
|
-
"@backendkit-labs/agent-core": "^0.36.0",
|
|
16
|
-
"dotenv": "^16.0.0"
|
|
17
|
-
},
|
|
18
|
-
"devDependencies": {
|
|
19
|
-
"@types/node": "^20.0.0",
|
|
20
|
-
"ts-node": "^10.9.0",
|
|
21
|
-
"typescript": "^5.4.0"
|
|
22
|
-
},
|
|
23
|
-
"engines": {
|
|
24
|
-
"node": ">=20.0.0"
|
|
25
|
-
}
|
|
26
|
-
}
|