@alejandroroman/agent-kit 0.1.2 → 0.1.4
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/bootstrap.d.ts +3 -4
- package/dist/cli/chat.js +15 -62
- package/dist/cli/config-writer.js +5 -0
- package/dist/cli/create.js +1 -4
- package/dist/cli/init.js +4 -7
- package/dist/cli/list.js +1 -2
- package/dist/cli/paths.d.ts +3 -0
- package/dist/cli/paths.js +4 -0
- package/dist/cli/repl.d.ts +23 -0
- package/dist/cli/repl.js +73 -0
- package/dist/cli/start.js +31 -80
- package/dist/cli/ui.d.ts +0 -2
- package/dist/cli/ui.js +1 -4
- package/dist/cli/validate.js +1 -4
- package/dist/index.js +4 -209
- package/dist/tools/registry.js +8 -1
- package/package.json +3 -4
package/dist/bootstrap.d.ts
CHANGED
|
@@ -6,7 +6,8 @@ import type { Message } from "./llm/types.js";
|
|
|
6
6
|
import type { AgentResult } from "./agent/types.js";
|
|
7
7
|
import type { ResolvedAgent } from "./config/resolve.js";
|
|
8
8
|
import type { SessionManager } from "./session/manager.js";
|
|
9
|
-
|
|
9
|
+
type AgentExecutorFn = (agentName: string, messages: Message[]) => Promise<AgentResult>;
|
|
10
|
+
interface AgentRuntime {
|
|
10
11
|
resolved: ResolvedAgent;
|
|
11
12
|
toolRegistry: ToolRegistry;
|
|
12
13
|
agentRegistry: AgentRegistry;
|
|
@@ -15,9 +16,6 @@ export interface AgentRuntime {
|
|
|
15
16
|
soul: string | undefined;
|
|
16
17
|
session: SessionManager;
|
|
17
18
|
}
|
|
18
|
-
export interface AgentExecutorFn {
|
|
19
|
-
(agentName: string, messages: Message[]): Promise<AgentResult>;
|
|
20
|
-
}
|
|
21
19
|
/**
|
|
22
20
|
* Build a fully-initialized agent runtime: tool registry, skills, spawn wrappers, session.
|
|
23
21
|
*/
|
|
@@ -49,3 +47,4 @@ export declare function createAgentExecutor(config: Config, opts: {
|
|
|
49
47
|
usageStore?: UsageStore;
|
|
50
48
|
source: string;
|
|
51
49
|
}): AgentExecutorFn;
|
|
50
|
+
export {};
|
package/dist/cli/chat.js
CHANGED
|
@@ -1,14 +1,9 @@
|
|
|
1
|
-
import * as readline from "readline";
|
|
2
|
-
import * as path from "path";
|
|
3
1
|
import { loadConfig } from "../config/index.js";
|
|
4
|
-
import { buildAgentRuntime
|
|
5
|
-
import { runAgentLoop } from "../agent/loop.js";
|
|
6
|
-
import { compactMessages } from "../session/compaction.js";
|
|
2
|
+
import { buildAgentRuntime } from "../bootstrap.js";
|
|
7
3
|
import { ensureOllama } from "./ollama.js";
|
|
8
4
|
import { resolveApiKey } from "./ui.js";
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
const SKILLS_DIR = path.join(process.cwd(), "skills");
|
|
5
|
+
import { CONFIG_PATH, DATA_DIR, SKILLS_DIR } from "./paths.js";
|
|
6
|
+
import { startRepl } from "./repl.js";
|
|
12
7
|
export async function chat(agentName) {
|
|
13
8
|
if (!agentName) {
|
|
14
9
|
const config = loadConfig(CONFIG_PATH);
|
|
@@ -30,7 +25,6 @@ export async function chat(agentName) {
|
|
|
30
25
|
console.error(`Agent "${agentName}" not found. Available: ${names}`);
|
|
31
26
|
process.exit(1);
|
|
32
27
|
}
|
|
33
|
-
// Warn if Ollama isn't running (memory tools won't work)
|
|
34
28
|
if (config.defaults.memory) {
|
|
35
29
|
const ollama = await ensureOllama();
|
|
36
30
|
if (!ollama.running) {
|
|
@@ -54,58 +48,17 @@ export async function chat(agentName) {
|
|
|
54
48
|
}
|
|
55
49
|
console.log(` Commands: /new (reset), /quit`);
|
|
56
50
|
console.log();
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
51
|
+
startRepl({
|
|
52
|
+
agentName,
|
|
53
|
+
model: resolved.model,
|
|
54
|
+
fallbacks: resolved.fallbacks,
|
|
55
|
+
maxIterations: resolved.maxIterations,
|
|
56
|
+
compactionThreshold: resolved.compactionThreshold,
|
|
57
|
+
maxToolResultSize: resolved.maxToolResultSize,
|
|
58
|
+
toolRegistry,
|
|
59
|
+
session,
|
|
60
|
+
soul,
|
|
61
|
+
skillsIndex,
|
|
62
|
+
promptFragments,
|
|
61
63
|
});
|
|
62
|
-
const ask = () => {
|
|
63
|
-
rl.question("You: ", async (input) => {
|
|
64
|
-
const trimmed = input.trim();
|
|
65
|
-
if (trimmed === "/quit") {
|
|
66
|
-
rl.close();
|
|
67
|
-
return;
|
|
68
|
-
}
|
|
69
|
-
if (trimmed === "/new") {
|
|
70
|
-
messages = [];
|
|
71
|
-
console.log(" Session reset.\n");
|
|
72
|
-
ask();
|
|
73
|
-
return;
|
|
74
|
-
}
|
|
75
|
-
if (!trimmed) {
|
|
76
|
-
ask();
|
|
77
|
-
return;
|
|
78
|
-
}
|
|
79
|
-
const userMsg = { role: "user", content: trimmed };
|
|
80
|
-
messages.push(userMsg);
|
|
81
|
-
session.append(userMsg);
|
|
82
|
-
messages = await compactMessages(messages, resolved.model, resolved.compactionThreshold);
|
|
83
|
-
try {
|
|
84
|
-
const systemPrompt = buildSystemPrompt(soul, skillsIndex, promptFragments);
|
|
85
|
-
const result = await runAgentLoop(messages, {
|
|
86
|
-
model: resolved.model,
|
|
87
|
-
fallbacks: resolved.fallbacks,
|
|
88
|
-
systemPrompt,
|
|
89
|
-
toolRegistry,
|
|
90
|
-
maxIterations: resolved.maxIterations,
|
|
91
|
-
compactionThreshold: resolved.compactionThreshold,
|
|
92
|
-
maxToolResultSize: resolved.maxToolResultSize,
|
|
93
|
-
agentName,
|
|
94
|
-
source: "cli",
|
|
95
|
-
});
|
|
96
|
-
const newMessages = result.messages.slice(messages.length - 1);
|
|
97
|
-
for (const msg of newMessages) {
|
|
98
|
-
session.append(msg);
|
|
99
|
-
}
|
|
100
|
-
messages = result.messages;
|
|
101
|
-
console.log(`\nAgent: ${result.text}`);
|
|
102
|
-
console.log(` (${result.usage.inputTokens + result.usage.outputTokens} tokens)\n`);
|
|
103
|
-
}
|
|
104
|
-
catch (err) {
|
|
105
|
-
console.error(`\n Error: ${err instanceof Error ? err.message : err}\n`);
|
|
106
|
-
}
|
|
107
|
-
ask();
|
|
108
|
-
});
|
|
109
|
-
};
|
|
110
|
-
ask();
|
|
111
64
|
}
|
|
@@ -35,6 +35,11 @@ export function createFreshConfig(opts) {
|
|
|
35
35
|
maxIterations: 20,
|
|
36
36
|
compactionThreshold: 100_000,
|
|
37
37
|
commandTimeout: 30,
|
|
38
|
+
memory: {
|
|
39
|
+
dbPath: "./data/memory.db",
|
|
40
|
+
ollamaEndpoint: "http://localhost:11434",
|
|
41
|
+
ollamaModel: "all-minilm:l6-v2",
|
|
42
|
+
},
|
|
38
43
|
},
|
|
39
44
|
agents: {},
|
|
40
45
|
cron: [],
|
package/dist/cli/create.js
CHANGED
|
@@ -1,12 +1,9 @@
|
|
|
1
1
|
import * as fs from "fs";
|
|
2
|
-
import * as path from "path";
|
|
3
2
|
import * as p from "@clack/prompts";
|
|
4
3
|
import { banner, done, resolveApiKey } from "./ui.js";
|
|
5
4
|
import { loadConfig } from "../config/index.js";
|
|
6
5
|
import { runSetupAgent } from "./setup-agent/index.js";
|
|
7
|
-
|
|
8
|
-
const DATA_DIR = path.join(process.cwd(), "data");
|
|
9
|
-
const SKILLS_DIR = path.join(process.cwd(), "skills");
|
|
6
|
+
import { CONFIG_PATH, DATA_DIR, SKILLS_DIR } from "./paths.js";
|
|
10
7
|
export async function create() {
|
|
11
8
|
banner();
|
|
12
9
|
// Require existing config
|
package/dist/cli/init.js
CHANGED
|
@@ -1,14 +1,11 @@
|
|
|
1
1
|
import * as fs from "fs";
|
|
2
|
-
import * as path from "path";
|
|
3
2
|
import { execSync } from "child_process";
|
|
4
3
|
import * as p from "@clack/prompts";
|
|
5
4
|
import { banner, isCancel, done, resolveApiKey } from "./ui.js";
|
|
6
5
|
import { checkOllama } from "./ollama.js";
|
|
7
6
|
import { createFreshConfig, scaffoldProjectPackageJson } from "./config-writer.js";
|
|
8
7
|
import { runSetupAgent } from "./setup-agent/index.js";
|
|
9
|
-
|
|
10
|
-
const DATA_DIR = path.join(process.cwd(), "data");
|
|
11
|
-
const SKILLS_DIR = path.join(process.cwd(), "skills");
|
|
8
|
+
import { CONFIG_PATH, DATA_DIR, SKILLS_DIR } from "./paths.js";
|
|
12
9
|
function detectPackageManager() {
|
|
13
10
|
try {
|
|
14
11
|
execSync("pnpm --version", { stdio: "ignore" });
|
|
@@ -53,13 +50,13 @@ export async function init() {
|
|
|
53
50
|
const pm = detectPackageManager();
|
|
54
51
|
s.start(`Installing dependencies (${pm} install)...`);
|
|
55
52
|
try {
|
|
56
|
-
execSync(`${pm} install`, { cwd: process.cwd(), stdio: "
|
|
53
|
+
execSync(`${pm} install`, { cwd: process.cwd(), stdio: "pipe" });
|
|
54
|
+
s.stop("Dependencies installed");
|
|
57
55
|
}
|
|
58
56
|
catch (err) {
|
|
59
57
|
s.stop(`Failed to install dependencies: ${err instanceof Error ? err.message : err}`);
|
|
60
|
-
p.log.warn(
|
|
58
|
+
p.log.warn(`Run \`${pm} install\` manually before starting.`);
|
|
61
59
|
}
|
|
62
|
-
s.stop("Dependencies installed");
|
|
63
60
|
// Ask if they want to create agents now
|
|
64
61
|
const createNow = await p.confirm({
|
|
65
62
|
message: "Create your first agent now? (AI-powered setup)",
|
package/dist/cli/list.js
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
|
-
import * as path from "path";
|
|
2
1
|
import { loadConfig } from "../config/index.js";
|
|
3
|
-
|
|
2
|
+
import { CONFIG_PATH } from "./paths.js";
|
|
4
3
|
export function list() {
|
|
5
4
|
const config = loadConfig(CONFIG_PATH);
|
|
6
5
|
const agents = Object.entries(config.agents);
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import type { ToolRegistry } from "../tools/registry.js";
|
|
2
|
+
import type { SessionManager } from "../session/manager.js";
|
|
3
|
+
import type { UsageStore } from "../usage/index.js";
|
|
4
|
+
interface ReplOptions {
|
|
5
|
+
agentName: string;
|
|
6
|
+
model: string;
|
|
7
|
+
fallbacks: string[];
|
|
8
|
+
maxIterations: number;
|
|
9
|
+
compactionThreshold: number;
|
|
10
|
+
maxToolResultSize: number;
|
|
11
|
+
toolRegistry: ToolRegistry;
|
|
12
|
+
session: SessionManager;
|
|
13
|
+
soul: string | undefined;
|
|
14
|
+
skillsIndex: string;
|
|
15
|
+
promptFragments: string[];
|
|
16
|
+
usageStore?: UsageStore;
|
|
17
|
+
/** Extra commands beyond /quit and /new */
|
|
18
|
+
commands?: Record<string, () => void>;
|
|
19
|
+
/** Called on /quit before closing */
|
|
20
|
+
onQuit?: () => Promise<void>;
|
|
21
|
+
}
|
|
22
|
+
export declare function startRepl(opts: ReplOptions): void;
|
|
23
|
+
export {};
|
package/dist/cli/repl.js
ADDED
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import * as readline from "readline";
|
|
2
|
+
import { runAgentLoop } from "../agent/loop.js";
|
|
3
|
+
import { compactMessages } from "../session/compaction.js";
|
|
4
|
+
import { buildSystemPrompt } from "../bootstrap.js";
|
|
5
|
+
export function startRepl(opts) {
|
|
6
|
+
let messages = opts.session.getMessages();
|
|
7
|
+
const rl = readline.createInterface({
|
|
8
|
+
input: process.stdin,
|
|
9
|
+
output: process.stdout,
|
|
10
|
+
});
|
|
11
|
+
const ask = () => {
|
|
12
|
+
rl.question("You: ", async (input) => {
|
|
13
|
+
const trimmed = input.trim();
|
|
14
|
+
if (trimmed === "/quit") {
|
|
15
|
+
try {
|
|
16
|
+
await opts.onQuit?.();
|
|
17
|
+
}
|
|
18
|
+
catch (err) {
|
|
19
|
+
console.error(`Warning: cleanup error: ${err instanceof Error ? err.message : err}`);
|
|
20
|
+
}
|
|
21
|
+
rl.close();
|
|
22
|
+
return;
|
|
23
|
+
}
|
|
24
|
+
if (trimmed === "/new") {
|
|
25
|
+
messages = [];
|
|
26
|
+
console.log(" Session reset.\n");
|
|
27
|
+
ask();
|
|
28
|
+
return;
|
|
29
|
+
}
|
|
30
|
+
// Custom commands
|
|
31
|
+
if (opts.commands && trimmed in opts.commands) {
|
|
32
|
+
opts.commands[trimmed]();
|
|
33
|
+
ask();
|
|
34
|
+
return;
|
|
35
|
+
}
|
|
36
|
+
if (!trimmed) {
|
|
37
|
+
ask();
|
|
38
|
+
return;
|
|
39
|
+
}
|
|
40
|
+
const userMsg = { role: "user", content: trimmed };
|
|
41
|
+
messages.push(userMsg);
|
|
42
|
+
opts.session.append(userMsg);
|
|
43
|
+
messages = await compactMessages(messages, opts.model, opts.compactionThreshold);
|
|
44
|
+
try {
|
|
45
|
+
const systemPrompt = buildSystemPrompt(opts.soul, opts.skillsIndex, opts.promptFragments);
|
|
46
|
+
const result = await runAgentLoop(messages, {
|
|
47
|
+
model: opts.model,
|
|
48
|
+
fallbacks: opts.fallbacks,
|
|
49
|
+
systemPrompt,
|
|
50
|
+
toolRegistry: opts.toolRegistry,
|
|
51
|
+
maxIterations: opts.maxIterations,
|
|
52
|
+
compactionThreshold: opts.compactionThreshold,
|
|
53
|
+
maxToolResultSize: opts.maxToolResultSize,
|
|
54
|
+
agentName: opts.agentName,
|
|
55
|
+
usageStore: opts.usageStore,
|
|
56
|
+
source: "cli",
|
|
57
|
+
});
|
|
58
|
+
const newMessages = result.messages.slice(messages.length);
|
|
59
|
+
for (const msg of newMessages) {
|
|
60
|
+
opts.session.append(msg);
|
|
61
|
+
}
|
|
62
|
+
messages = result.messages;
|
|
63
|
+
console.log(`\nAgent: ${result.text}`);
|
|
64
|
+
console.log(` (${result.usage.inputTokens + result.usage.outputTokens} tokens)\n`);
|
|
65
|
+
}
|
|
66
|
+
catch (err) {
|
|
67
|
+
console.error(`\n Error: ${err instanceof Error ? err.message : err}\n`);
|
|
68
|
+
}
|
|
69
|
+
ask();
|
|
70
|
+
});
|
|
71
|
+
};
|
|
72
|
+
ask();
|
|
73
|
+
}
|
package/dist/cli/start.js
CHANGED
|
@@ -1,20 +1,15 @@
|
|
|
1
|
-
import * as readline from "readline";
|
|
2
|
-
import * as path from "path";
|
|
3
1
|
import { loadConfig } from "../config/index.js";
|
|
4
|
-
import { runAgentLoop } from "../agent/loop.js";
|
|
5
|
-
import { compactMessages } from "../session/compaction.js";
|
|
6
2
|
import { CronScheduler } from "../cron/scheduler.js";
|
|
7
3
|
import { HeartbeatRunner } from "../heartbeat/index.js";
|
|
8
4
|
import { createSlackGateway } from "../gateways/slack/index.js";
|
|
9
5
|
import { createApiServer } from "../api/router.js";
|
|
10
6
|
import { createLogger } from "../logger.js";
|
|
11
|
-
import { buildAgentRuntime,
|
|
7
|
+
import { buildAgentRuntime, initUsageStore, createAgentExecutor, } from "../bootstrap.js";
|
|
12
8
|
import { ensureOllama } from "./ollama.js";
|
|
13
9
|
import { resolveApiKey } from "./ui.js";
|
|
10
|
+
import { CONFIG_PATH, DATA_DIR, SKILLS_DIR } from "./paths.js";
|
|
11
|
+
import { startRepl } from "./repl.js";
|
|
14
12
|
const log = createLogger("start");
|
|
15
|
-
const CONFIG_PATH = path.join(process.cwd(), "agent-kit.json");
|
|
16
|
-
const DATA_DIR = path.join(process.cwd(), "data");
|
|
17
|
-
const SKILLS_DIR = path.join(process.cwd(), "skills");
|
|
18
13
|
const DEFAULT_AGENT = "default";
|
|
19
14
|
export async function start() {
|
|
20
15
|
await resolveApiKey({ save: false });
|
|
@@ -152,87 +147,43 @@ export async function start() {
|
|
|
152
147
|
console.log(` Commands: /new (reset), /agents, /help, /quit`);
|
|
153
148
|
console.log();
|
|
154
149
|
// REPL
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
};
|
|
171
|
-
const ask = () => {
|
|
172
|
-
rl.question("You: ", async (input) => {
|
|
173
|
-
const trimmed = input.trim();
|
|
174
|
-
if (trimmed === "/quit") {
|
|
175
|
-
await shutdown();
|
|
176
|
-
return;
|
|
177
|
-
}
|
|
178
|
-
if (trimmed === "/new") {
|
|
179
|
-
messages = [];
|
|
180
|
-
console.log(" Session reset.\n");
|
|
181
|
-
ask();
|
|
182
|
-
return;
|
|
183
|
-
}
|
|
184
|
-
if (trimmed === "/agents") {
|
|
150
|
+
startRepl({
|
|
151
|
+
agentName,
|
|
152
|
+
model: resolved.model,
|
|
153
|
+
fallbacks: resolved.fallbacks,
|
|
154
|
+
maxIterations: resolved.maxIterations,
|
|
155
|
+
compactionThreshold: resolved.compactionThreshold,
|
|
156
|
+
maxToolResultSize: resolved.maxToolResultSize,
|
|
157
|
+
toolRegistry,
|
|
158
|
+
session,
|
|
159
|
+
soul,
|
|
160
|
+
skillsIndex,
|
|
161
|
+
promptFragments,
|
|
162
|
+
usageStore,
|
|
163
|
+
commands: {
|
|
164
|
+
"/agents": () => {
|
|
185
165
|
for (const [name, def] of agentList) {
|
|
186
166
|
const emoji = def.emoji ?? " ";
|
|
187
167
|
const display = def.displayName ?? name;
|
|
188
168
|
console.log(` ${emoji} ${display} (${name})`);
|
|
189
169
|
}
|
|
190
170
|
console.log();
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
}
|
|
194
|
-
if (trimmed === "/help") {
|
|
171
|
+
},
|
|
172
|
+
"/help": () => {
|
|
195
173
|
console.log(" /new — Reset conversation");
|
|
196
174
|
console.log(" /agents — List agents");
|
|
197
175
|
console.log(" /quit — Shut down\n");
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
const userMsg = { role: "user", content: trimmed };
|
|
206
|
-
messages.push(userMsg);
|
|
207
|
-
session.append(userMsg);
|
|
208
|
-
messages = await compactMessages(messages, resolved.model, resolved.compactionThreshold);
|
|
176
|
+
},
|
|
177
|
+
},
|
|
178
|
+
onQuit: async () => {
|
|
179
|
+
scheduler.stop();
|
|
180
|
+
heartbeat.stop();
|
|
181
|
+
await gateway?.stop();
|
|
182
|
+
await apiServer.stop();
|
|
209
183
|
try {
|
|
210
|
-
|
|
211
|
-
const result = await runAgentLoop(messages, {
|
|
212
|
-
model: resolved.model,
|
|
213
|
-
fallbacks: resolved.fallbacks,
|
|
214
|
-
systemPrompt,
|
|
215
|
-
toolRegistry,
|
|
216
|
-
maxIterations: resolved.maxIterations,
|
|
217
|
-
compactionThreshold: resolved.compactionThreshold,
|
|
218
|
-
maxToolResultSize: resolved.maxToolResultSize,
|
|
219
|
-
agentName,
|
|
220
|
-
usageStore,
|
|
221
|
-
source: "cli",
|
|
222
|
-
});
|
|
223
|
-
const newMessages = result.messages.slice(messages.length - 1);
|
|
224
|
-
for (const msg of newMessages) {
|
|
225
|
-
session.append(msg);
|
|
226
|
-
}
|
|
227
|
-
messages = result.messages;
|
|
228
|
-
console.log(`\nAgent: ${result.text}`);
|
|
229
|
-
console.log(` (${result.usage.inputTokens + result.usage.outputTokens} tokens)\n`);
|
|
184
|
+
usageStore?.close();
|
|
230
185
|
}
|
|
231
|
-
catch
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
ask();
|
|
235
|
-
});
|
|
236
|
-
};
|
|
237
|
-
ask();
|
|
186
|
+
catch { }
|
|
187
|
+
},
|
|
188
|
+
});
|
|
238
189
|
}
|
package/dist/cli/ui.d.ts
CHANGED
|
@@ -1,7 +1,5 @@
|
|
|
1
1
|
export declare function banner(): void;
|
|
2
|
-
export declare function status(label: string, value: string): void;
|
|
3
2
|
export declare function done(message: string): void;
|
|
4
|
-
export declare function onCancel(): void;
|
|
5
3
|
/**
|
|
6
4
|
* Check if a @clack/prompts value was cancelled. Exits the process if so.
|
|
7
5
|
* The `return` after `isCancel()` in callers is technically unreachable
|
package/dist/cli/ui.js
CHANGED
|
@@ -6,13 +6,10 @@ export function banner() {
|
|
|
6
6
|
console.log();
|
|
7
7
|
p.intro(`agent-kit v${VERSION}`);
|
|
8
8
|
}
|
|
9
|
-
export function status(label, value) {
|
|
10
|
-
p.log.info(`${label}: ${value}`);
|
|
11
|
-
}
|
|
12
9
|
export function done(message) {
|
|
13
10
|
p.outro(message);
|
|
14
11
|
}
|
|
15
|
-
|
|
12
|
+
function onCancel() {
|
|
16
13
|
p.cancel("Cancelled.");
|
|
17
14
|
process.exit(0);
|
|
18
15
|
}
|
package/dist/cli/validate.js
CHANGED
|
@@ -1,11 +1,8 @@
|
|
|
1
|
-
import * as path from "path";
|
|
2
1
|
import { loadConfig } from "../config/index.js";
|
|
3
2
|
import { validateAgent } from "../scripts/validate-agent.js";
|
|
3
|
+
import { CONFIG_PATH, DATA_DIR, SKILLS_DIR } from "./paths.js";
|
|
4
4
|
const PASS = "\u2713";
|
|
5
5
|
const FAIL = "\u2717";
|
|
6
|
-
const CONFIG_PATH = path.join(process.cwd(), "agent-kit.json");
|
|
7
|
-
const SKILLS_DIR = path.join(process.cwd(), "skills");
|
|
8
|
-
const DATA_DIR = path.join(process.cwd(), "data");
|
|
9
6
|
function printResult(result) {
|
|
10
7
|
for (const check of result.checks) {
|
|
11
8
|
const icon = check.passed ? PASS : FAIL;
|
package/dist/index.js
CHANGED
|
@@ -1,209 +1,4 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
import {
|
|
4
|
-
|
|
5
|
-
import { loadConfig } from "./config/index.js";
|
|
6
|
-
import { CronScheduler } from "./cron/scheduler.js";
|
|
7
|
-
import { HeartbeatRunner } from "./heartbeat/index.js";
|
|
8
|
-
import { createSlackGateway } from "./gateways/slack/index.js";
|
|
9
|
-
import { createLogger } from "./logger.js";
|
|
10
|
-
import { createApiServer } from "./api/router.js";
|
|
11
|
-
import { buildAgentRuntime, buildSystemPrompt, initUsageStore, createAgentExecutor, } from "./bootstrap.js";
|
|
12
|
-
const log = createLogger("startup");
|
|
13
|
-
const CONFIG_PATH = path.join(process.cwd(), "agent-kit.json");
|
|
14
|
-
const DATA_DIR = path.join(process.cwd(), "data");
|
|
15
|
-
const DEFAULT_AGENT = "default";
|
|
16
|
-
const SKILLS_DIR = path.join(process.cwd(), "skills");
|
|
17
|
-
async function main() {
|
|
18
|
-
const config = loadConfig(CONFIG_PATH);
|
|
19
|
-
const { usageStore, apiPort } = initUsageStore(config);
|
|
20
|
-
const apiServer = createApiServer({
|
|
21
|
-
config,
|
|
22
|
-
configPath: CONFIG_PATH,
|
|
23
|
-
usageStore,
|
|
24
|
-
dataDir: DATA_DIR,
|
|
25
|
-
}, apiPort);
|
|
26
|
-
const agentName = process.argv[2] ?? DEFAULT_AGENT;
|
|
27
|
-
// Validate all agent tool references at startup
|
|
28
|
-
const runtime = buildAgentRuntime(agentName, config, {
|
|
29
|
-
dataDir: DATA_DIR,
|
|
30
|
-
skillsDir: SKILLS_DIR,
|
|
31
|
-
usageStore,
|
|
32
|
-
});
|
|
33
|
-
const toolWarnings = runtime.toolRegistry.validateAgents(config.agents);
|
|
34
|
-
for (const w of toolWarnings)
|
|
35
|
-
console.warn(` ⚠ ${w}`);
|
|
36
|
-
const { resolved, toolRegistry, agentRegistry, promptFragments, skillsIndex, soul, session } = runtime;
|
|
37
|
-
const sandbox = config.agents[agentName]?.sandbox ?? config.defaults.sandbox;
|
|
38
|
-
console.log("Agent Kit");
|
|
39
|
-
console.log(` Model: ${resolved.model}`);
|
|
40
|
-
if (resolved.fallbacks.length > 0) {
|
|
41
|
-
console.log(` Fallbacks: ${resolved.fallbacks.join(" → ")}`);
|
|
42
|
-
}
|
|
43
|
-
console.log(` Agent: ${agentName}`);
|
|
44
|
-
console.log(` SOUL: ${soul ? "loaded" : "none (create data/agents/default/SOUL.md)"}`);
|
|
45
|
-
console.log(` Tools: ${resolved.tools.map((t) => t.name).join(", ")}`);
|
|
46
|
-
if (resolved.skills.length > 0) {
|
|
47
|
-
console.log(` Skills: ${resolved.skills.map((s) => s.name).join(", ")}`);
|
|
48
|
-
}
|
|
49
|
-
const sandboxSummary = (() => {
|
|
50
|
-
if (!sandbox)
|
|
51
|
-
return "off (unrestricted)";
|
|
52
|
-
const parts = [];
|
|
53
|
-
if (sandbox.allowedCommands?.length) {
|
|
54
|
-
parts.push(`${sandbox.allowedCommands.length} commands allowed`);
|
|
55
|
-
}
|
|
56
|
-
if (sandbox.allowedPaths?.length) {
|
|
57
|
-
parts.push(`${sandbox.allowedPaths.length} paths allowed`);
|
|
58
|
-
}
|
|
59
|
-
return parts.length > 0 ? parts.join(", ") : "configured (no restrictions)";
|
|
60
|
-
})();
|
|
61
|
-
console.log(` Sandbox: ${sandboxSummary}`);
|
|
62
|
-
if (config.defaults.usage) {
|
|
63
|
-
console.log(` Usage: tracking enabled (${config.defaults.usage.dbPath})`);
|
|
64
|
-
}
|
|
65
|
-
const scheduler = new CronScheduler(config, toolRegistry, agentRegistry, DATA_DIR, SKILLS_DIR, usageStore);
|
|
66
|
-
const enabledJobs = scheduler.getJobs().filter((j) => j.enabled);
|
|
67
|
-
// Agent executor for inbound Slack messages
|
|
68
|
-
const executeAgent = createAgentExecutor(config, {
|
|
69
|
-
dataDir: DATA_DIR,
|
|
70
|
-
skillsDir: SKILLS_DIR,
|
|
71
|
-
agentRegistry,
|
|
72
|
-
usageStore,
|
|
73
|
-
source: "slack",
|
|
74
|
-
});
|
|
75
|
-
// Slack gateway (optional — requires both tokens + agent slack bindings)
|
|
76
|
-
let gateway;
|
|
77
|
-
const hasSlackBindings = Object.values(config.agents).some((a) => a.slack);
|
|
78
|
-
if (hasSlackBindings && process.env.SLACK_BOT_TOKEN && process.env.SLACK_APP_TOKEN) {
|
|
79
|
-
try {
|
|
80
|
-
gateway = createSlackGateway(config, { onAgentRequest: executeAgent });
|
|
81
|
-
await gateway.start();
|
|
82
|
-
const bindingCount = Object.values(config.agents).filter((a) => a.slack).length;
|
|
83
|
-
log.info({ bindings: bindingCount }, "Slack connected");
|
|
84
|
-
}
|
|
85
|
-
catch (err) {
|
|
86
|
-
log.warn({ err }, "Slack failed to connect");
|
|
87
|
-
}
|
|
88
|
-
}
|
|
89
|
-
try {
|
|
90
|
-
const actualPort = await apiServer.start();
|
|
91
|
-
console.log(` API: http://localhost:${actualPort}/api`);
|
|
92
|
-
}
|
|
93
|
-
catch (err) {
|
|
94
|
-
log.warn({ err }, "failed to start API server — continuing without it");
|
|
95
|
-
}
|
|
96
|
-
if (enabledJobs.length > 0) {
|
|
97
|
-
const jobList = enabledJobs.map((j) => `${j.id} @ ${j.schedule}`).join(", ");
|
|
98
|
-
log.info({ jobs: enabledJobs.length, jobList }, "cron scheduled");
|
|
99
|
-
scheduler.start({
|
|
100
|
-
onResult: (jobId, agentName, result) => {
|
|
101
|
-
log.info({ jobId, tokens: result.usage.inputTokens + result.usage.outputTokens }, "cron job completed");
|
|
102
|
-
process.stdout.write("You: ");
|
|
103
|
-
const channelOverride = config.cron.find((j) => j.id === jobId)?.slack?.channelId;
|
|
104
|
-
gateway?.onJobResult(agentName, jobId, result, channelOverride).catch((err) => log.warn({ err, jobId }, "failed to post cron result to Slack"));
|
|
105
|
-
},
|
|
106
|
-
onError: (jobId, agentName, error) => {
|
|
107
|
-
log.error({ err: error, jobId }, "cron job failed");
|
|
108
|
-
process.stdout.write("You: ");
|
|
109
|
-
const channelOverride = config.cron.find((j) => j.id === jobId)?.slack?.channelId;
|
|
110
|
-
gateway?.onJobError(agentName, jobId, error, channelOverride).catch((err) => log.warn({ err, jobId }, "failed to post cron error to Slack"));
|
|
111
|
-
},
|
|
112
|
-
});
|
|
113
|
-
}
|
|
114
|
-
const heartbeat = new HeartbeatRunner(config, agentRegistry, DATA_DIR, SKILLS_DIR, usageStore);
|
|
115
|
-
const heartbeatAgents = heartbeat.getHeartbeatAgents();
|
|
116
|
-
if (heartbeatAgents.length > 0) {
|
|
117
|
-
log.info({ agents: heartbeatAgents }, "heartbeat started");
|
|
118
|
-
heartbeat.start({
|
|
119
|
-
onResult: (agentName, result) => {
|
|
120
|
-
log.info({ agent: agentName, tokens: result.usage.inputTokens + result.usage.outputTokens }, "heartbeat alert");
|
|
121
|
-
process.stdout.write("You: ");
|
|
122
|
-
const channelOverride = config.agents[agentName]?.heartbeat?.slack?.channelId;
|
|
123
|
-
gateway?.onJobResult(agentName, "heartbeat", result, channelOverride).catch((err) => log.warn({ err, agent: agentName }, "failed to post heartbeat result to Slack"));
|
|
124
|
-
},
|
|
125
|
-
onError: (agentName, error) => {
|
|
126
|
-
log.error({ err: error, agent: agentName }, "heartbeat failed");
|
|
127
|
-
process.stdout.write("You: ");
|
|
128
|
-
const channelOverride = config.agents[agentName]?.heartbeat?.slack?.channelId;
|
|
129
|
-
gateway?.onJobError(agentName, "heartbeat", error, channelOverride).catch((err) => log.warn({ err, agent: agentName }, "failed to post heartbeat error to Slack"));
|
|
130
|
-
},
|
|
131
|
-
onSuppressed: (agentName) => {
|
|
132
|
-
log.debug({ agent: agentName }, "heartbeat OK, suppressed");
|
|
133
|
-
},
|
|
134
|
-
});
|
|
135
|
-
}
|
|
136
|
-
if (heartbeatAgents.length > 0) {
|
|
137
|
-
console.log(` Heartbeat: ${heartbeatAgents.join(", ")}`);
|
|
138
|
-
}
|
|
139
|
-
console.log(` Commands: /new (reset), /quit`);
|
|
140
|
-
console.log();
|
|
141
|
-
let messages = session.getMessages();
|
|
142
|
-
const rl = readline.createInterface({
|
|
143
|
-
input: process.stdin,
|
|
144
|
-
output: process.stdout,
|
|
145
|
-
});
|
|
146
|
-
const ask = () => {
|
|
147
|
-
rl.question("You: ", async (input) => {
|
|
148
|
-
const trimmed = input.trim();
|
|
149
|
-
if (trimmed === "/quit") {
|
|
150
|
-
scheduler.stop();
|
|
151
|
-
heartbeat.stop();
|
|
152
|
-
await gateway?.stop();
|
|
153
|
-
await apiServer.stop();
|
|
154
|
-
try {
|
|
155
|
-
usageStore?.close();
|
|
156
|
-
}
|
|
157
|
-
catch (err) {
|
|
158
|
-
log.warn({ err }, "failed to close usage store");
|
|
159
|
-
}
|
|
160
|
-
finally {
|
|
161
|
-
rl.close();
|
|
162
|
-
}
|
|
163
|
-
return;
|
|
164
|
-
}
|
|
165
|
-
if (trimmed === "/new") {
|
|
166
|
-
messages = [];
|
|
167
|
-
console.log(" Session reset.\n");
|
|
168
|
-
ask();
|
|
169
|
-
return;
|
|
170
|
-
}
|
|
171
|
-
if (!trimmed) {
|
|
172
|
-
ask();
|
|
173
|
-
return;
|
|
174
|
-
}
|
|
175
|
-
const userMsg = { role: "user", content: trimmed };
|
|
176
|
-
messages.push(userMsg);
|
|
177
|
-
session.append(userMsg);
|
|
178
|
-
messages = await compactMessages(messages, resolved.model, resolved.compactionThreshold);
|
|
179
|
-
try {
|
|
180
|
-
const systemPrompt = buildSystemPrompt(soul, skillsIndex, promptFragments);
|
|
181
|
-
const result = await runAgentLoop(messages, {
|
|
182
|
-
model: resolved.model,
|
|
183
|
-
fallbacks: resolved.fallbacks,
|
|
184
|
-
systemPrompt,
|
|
185
|
-
toolRegistry,
|
|
186
|
-
maxIterations: resolved.maxIterations,
|
|
187
|
-
compactionThreshold: resolved.compactionThreshold,
|
|
188
|
-
maxToolResultSize: resolved.maxToolResultSize,
|
|
189
|
-
agentName,
|
|
190
|
-
usageStore,
|
|
191
|
-
source: "cli",
|
|
192
|
-
});
|
|
193
|
-
const newMessages = result.messages.slice(messages.length - 1);
|
|
194
|
-
for (const msg of newMessages) {
|
|
195
|
-
session.append(msg);
|
|
196
|
-
}
|
|
197
|
-
messages = result.messages;
|
|
198
|
-
console.log(`\nAgent: ${result.text}`);
|
|
199
|
-
console.log(` (${result.usage.inputTokens + result.usage.outputTokens} tokens)\n`);
|
|
200
|
-
}
|
|
201
|
-
catch (err) {
|
|
202
|
-
console.error(`\n Error: ${err instanceof Error ? err.message : err}\n`);
|
|
203
|
-
}
|
|
204
|
-
ask();
|
|
205
|
-
});
|
|
206
|
-
};
|
|
207
|
-
ask();
|
|
208
|
-
}
|
|
209
|
-
main();
|
|
1
|
+
// Legacy entry point — delegates to the CLI start command.
|
|
2
|
+
// Kept for backwards compatibility with `pnpm dev` / `pnpm dev:local`.
|
|
3
|
+
import { start } from "./cli/start.js";
|
|
4
|
+
start();
|
package/dist/tools/registry.js
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { createLogger } from "../logger.js";
|
|
2
|
+
const log = createLogger("tools");
|
|
1
3
|
export class ToolRegistry {
|
|
2
4
|
tools = new Map();
|
|
3
5
|
register(tool) {
|
|
@@ -5,7 +7,12 @@ export class ToolRegistry {
|
|
|
5
7
|
}
|
|
6
8
|
resolve(names) {
|
|
7
9
|
return names
|
|
8
|
-
.map((name) =>
|
|
10
|
+
.map((name) => {
|
|
11
|
+
const tool = this.tools.get(name);
|
|
12
|
+
if (!tool)
|
|
13
|
+
log.warn(`Unknown tool "${name}" — skipping`);
|
|
14
|
+
return tool;
|
|
15
|
+
})
|
|
9
16
|
.filter((tool) => !!tool);
|
|
10
17
|
}
|
|
11
18
|
list() {
|
package/package.json
CHANGED
|
@@ -1,11 +1,10 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@alejandroroman/agent-kit",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.4",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"main": "./dist/index.js",
|
|
6
6
|
"exports": {
|
|
7
|
-
".": "./dist/index.js"
|
|
8
|
-
"./bootstrap": "./dist/bootstrap.js"
|
|
7
|
+
".": "./dist/index.js"
|
|
9
8
|
},
|
|
10
9
|
"bin": {
|
|
11
10
|
"agent-kit": "./dist/cli.js"
|
|
@@ -14,7 +13,7 @@
|
|
|
14
13
|
"dist/"
|
|
15
14
|
],
|
|
16
15
|
"scripts": {
|
|
17
|
-
"build": "pnpm --filter @agent-kit/memory run build && tsc && cp -r packages/memory/dist dist/_memory &&
|
|
16
|
+
"build": "pnpm --filter @agent-kit/memory run build && tsc && cp -r packages/memory/dist dist/_memory && node -e \"const f='dist/tools/builtin/memory.js',s=require('fs');s.writeFileSync(f,s.readFileSync(f,'utf8').replaceAll('from \\\"@agent-kit/memory\\\"','from \\\"../../_memory/index.js\\\"'))\"",
|
|
18
17
|
"prepublishOnly": "pnpm run build",
|
|
19
18
|
"cli": "tsx src/cli.ts",
|
|
20
19
|
"dev": "doppler run -- tsx src/index.ts",
|