@alejandroroman/agent-kit 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.
Files changed (169) hide show
  1. package/dist/_memory/config.d.ts +14 -0
  2. package/dist/_memory/config.js +16 -0
  3. package/dist/_memory/db/client.d.ts +2 -0
  4. package/dist/_memory/db/client.js +15 -0
  5. package/dist/_memory/db/schema.d.ts +14 -0
  6. package/dist/_memory/db/schema.js +51 -0
  7. package/dist/_memory/embeddings/ollama.d.ts +12 -0
  8. package/dist/_memory/embeddings/ollama.js +22 -0
  9. package/dist/_memory/embeddings/provider.d.ts +4 -0
  10. package/dist/_memory/embeddings/provider.js +1 -0
  11. package/dist/_memory/index.d.ts +10 -0
  12. package/dist/_memory/index.js +6 -0
  13. package/dist/_memory/search.d.ts +30 -0
  14. package/dist/_memory/search.js +121 -0
  15. package/dist/_memory/server.d.ts +8 -0
  16. package/dist/_memory/server.js +126 -0
  17. package/dist/_memory/store.d.ts +51 -0
  18. package/dist/_memory/store.js +115 -0
  19. package/dist/agent/loop.d.ts +3 -0
  20. package/dist/agent/loop.js +195 -0
  21. package/dist/agent/setup.d.ts +6 -0
  22. package/dist/agent/setup.js +11 -0
  23. package/dist/agent/soul.d.ts +1 -0
  24. package/dist/agent/soul.js +8 -0
  25. package/dist/agent/types.d.ts +23 -0
  26. package/dist/agent/types.js +1 -0
  27. package/dist/api/agents.d.ts +2 -0
  28. package/dist/api/agents.js +43 -0
  29. package/dist/api/config.d.ts +2 -0
  30. package/dist/api/config.js +20 -0
  31. package/dist/api/cron.d.ts +2 -0
  32. package/dist/api/cron.js +15 -0
  33. package/dist/api/health.d.ts +2 -0
  34. package/dist/api/health.js +8 -0
  35. package/dist/api/logs.d.ts +5 -0
  36. package/dist/api/logs.js +28 -0
  37. package/dist/api/router.d.ts +6 -0
  38. package/dist/api/router.js +80 -0
  39. package/dist/api/sessions.d.ts +2 -0
  40. package/dist/api/sessions.js +67 -0
  41. package/dist/api/types.d.ts +12 -0
  42. package/dist/api/types.js +13 -0
  43. package/dist/api/usage.d.ts +3 -0
  44. package/dist/api/usage.js +50 -0
  45. package/dist/bootstrap.d.ts +51 -0
  46. package/dist/bootstrap.js +110 -0
  47. package/dist/cli/chat.d.ts +1 -0
  48. package/dist/cli/chat.js +102 -0
  49. package/dist/cli/config-writer.d.ts +40 -0
  50. package/dist/cli/config-writer.js +108 -0
  51. package/dist/cli/create.d.ts +1 -0
  52. package/dist/cli/create.js +37 -0
  53. package/dist/cli/init.d.ts +1 -0
  54. package/dist/cli/init.js +85 -0
  55. package/dist/cli/list.d.ts +1 -0
  56. package/dist/cli/list.js +36 -0
  57. package/dist/cli/ollama.d.ts +6 -0
  58. package/dist/cli/ollama.js +44 -0
  59. package/dist/cli/setup-agent/index.d.ts +9 -0
  60. package/dist/cli/setup-agent/index.js +100 -0
  61. package/dist/cli/setup-agent/soul.d.ts +2 -0
  62. package/dist/cli/setup-agent/soul.js +79 -0
  63. package/dist/cli/setup-agent/tools.d.ts +9 -0
  64. package/dist/cli/setup-agent/tools.js +362 -0
  65. package/dist/cli/start.d.ts +1 -0
  66. package/dist/cli/start.js +235 -0
  67. package/dist/cli/ui.d.ts +17 -0
  68. package/dist/cli/ui.js +79 -0
  69. package/dist/cli/validate.d.ts +1 -0
  70. package/dist/cli/validate.js +47 -0
  71. package/dist/cli.d.ts +4 -0
  72. package/dist/cli.js +59 -0
  73. package/dist/config/index.d.ts +4 -0
  74. package/dist/config/index.js +3 -0
  75. package/dist/config/loader.d.ts +2 -0
  76. package/dist/config/loader.js +10 -0
  77. package/dist/config/resolve.d.ts +22 -0
  78. package/dist/config/resolve.js +45 -0
  79. package/dist/config/schema.d.ts +217 -0
  80. package/dist/config/schema.js +159 -0
  81. package/dist/cron/scheduler.d.ts +22 -0
  82. package/dist/cron/scheduler.js +115 -0
  83. package/dist/gateways/slack/client.d.ts +13 -0
  84. package/dist/gateways/slack/client.js +44 -0
  85. package/dist/gateways/slack/format.d.ts +30 -0
  86. package/dist/gateways/slack/format.js +170 -0
  87. package/dist/gateways/slack/handler.d.ts +9 -0
  88. package/dist/gateways/slack/handler.js +95 -0
  89. package/dist/gateways/slack/index.d.ts +16 -0
  90. package/dist/gateways/slack/index.js +102 -0
  91. package/dist/gateways/slack/listener.d.ts +10 -0
  92. package/dist/gateways/slack/listener.js +35 -0
  93. package/dist/gateways/slack/sessions.d.ts +11 -0
  94. package/dist/gateways/slack/sessions.js +32 -0
  95. package/dist/gateways/slack/types.d.ts +13 -0
  96. package/dist/gateways/slack/types.js +7 -0
  97. package/dist/heartbeat/index.d.ts +2 -0
  98. package/dist/heartbeat/index.js +1 -0
  99. package/dist/heartbeat/runner.d.ts +31 -0
  100. package/dist/heartbeat/runner.js +215 -0
  101. package/dist/index.d.ts +1 -0
  102. package/dist/index.js +207 -0
  103. package/dist/llm/anthropic.d.ts +12 -0
  104. package/dist/llm/anthropic.js +89 -0
  105. package/dist/llm/fallback.d.ts +6 -0
  106. package/dist/llm/fallback.js +30 -0
  107. package/dist/llm/index.d.ts +9 -0
  108. package/dist/llm/index.js +40 -0
  109. package/dist/llm/openai.d.ts +12 -0
  110. package/dist/llm/openai.js +85 -0
  111. package/dist/llm/provider.d.ts +12 -0
  112. package/dist/llm/provider.js +9 -0
  113. package/dist/llm/types.d.ts +73 -0
  114. package/dist/llm/types.js +6 -0
  115. package/dist/logger.d.ts +2 -0
  116. package/dist/logger.js +15 -0
  117. package/dist/multi/registry.d.ts +15 -0
  118. package/dist/multi/registry.js +28 -0
  119. package/dist/multi/spawn.d.ts +14 -0
  120. package/dist/multi/spawn.js +14 -0
  121. package/dist/scripts/validate-agent-cli.d.ts +1 -0
  122. package/dist/scripts/validate-agent-cli.js +47 -0
  123. package/dist/scripts/validate-agent.d.ts +17 -0
  124. package/dist/scripts/validate-agent.js +242 -0
  125. package/dist/session/compaction.d.ts +4 -0
  126. package/dist/session/compaction.js +30 -0
  127. package/dist/session/manager.d.ts +9 -0
  128. package/dist/session/manager.js +41 -0
  129. package/dist/skills/activate.d.ts +11 -0
  130. package/dist/skills/activate.js +62 -0
  131. package/dist/skills/index.d.ts +3 -0
  132. package/dist/skills/index.js +3 -0
  133. package/dist/skills/loader.d.ts +3 -0
  134. package/dist/skills/loader.js +20 -0
  135. package/dist/skills/schema.d.ts +8 -0
  136. package/dist/skills/schema.js +7 -0
  137. package/dist/text.d.ts +8 -0
  138. package/dist/text.js +24 -0
  139. package/dist/tools/builtin/index.d.ts +21 -0
  140. package/dist/tools/builtin/index.js +21 -0
  141. package/dist/tools/builtin/memory.d.ts +8 -0
  142. package/dist/tools/builtin/memory.js +164 -0
  143. package/dist/tools/builtin/read-file.d.ts +3 -0
  144. package/dist/tools/builtin/read-file.js +30 -0
  145. package/dist/tools/builtin/run-command.d.ts +3 -0
  146. package/dist/tools/builtin/run-command.js +37 -0
  147. package/dist/tools/builtin/spawn.d.ts +15 -0
  148. package/dist/tools/builtin/spawn.js +59 -0
  149. package/dist/tools/builtin/web-search.d.ts +8 -0
  150. package/dist/tools/builtin/web-search.js +99 -0
  151. package/dist/tools/builtin/write-file.d.ts +3 -0
  152. package/dist/tools/builtin/write-file.js +34 -0
  153. package/dist/tools/registry.d.ts +10 -0
  154. package/dist/tools/registry.js +26 -0
  155. package/dist/tools/sandbox.d.ts +9 -0
  156. package/dist/tools/sandbox.js +74 -0
  157. package/dist/tools/types.d.ts +8 -0
  158. package/dist/tools/types.js +7 -0
  159. package/dist/usage/index.d.ts +4 -0
  160. package/dist/usage/index.js +3 -0
  161. package/dist/usage/pricing.d.ts +10 -0
  162. package/dist/usage/pricing.js +35 -0
  163. package/dist/usage/schema.d.ts +1 -0
  164. package/dist/usage/schema.js +45 -0
  165. package/dist/usage/store.d.ts +10 -0
  166. package/dist/usage/store.js +227 -0
  167. package/dist/usage/types.d.ts +61 -0
  168. package/dist/usage/types.js +1 -0
  169. package/package.json +53 -0
@@ -0,0 +1,235 @@
1
+ import * as readline from "readline";
2
+ import * as path from "path";
3
+ import { loadConfig } from "../config/index.js";
4
+ import { runAgentLoop } from "../agent/loop.js";
5
+ import { compactMessages } from "../session/compaction.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 { createApiServer } from "../api/router.js";
10
+ import { createLogger } from "../logger.js";
11
+ import { buildAgentRuntime, buildSystemPrompt, initUsageStore, createAgentExecutor, } from "../bootstrap.js";
12
+ import { ensureOllama } from "./ollama.js";
13
+ import { resolveApiKey } from "./ui.js";
14
+ 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
+ const DEFAULT_AGENT = "default";
19
+ export async function start() {
20
+ await resolveApiKey({ save: false });
21
+ const config = loadConfig(CONFIG_PATH);
22
+ // Ollama check (warn only)
23
+ if (config.defaults.memory) {
24
+ const ollama = await ensureOllama();
25
+ if (!ollama.running) {
26
+ log.warn("Ollama not running — memory tools unavailable");
27
+ }
28
+ }
29
+ const { usageStore, apiPort } = initUsageStore(config);
30
+ const apiServer = createApiServer({
31
+ config,
32
+ configPath: CONFIG_PATH,
33
+ usageStore,
34
+ dataDir: DATA_DIR,
35
+ }, apiPort);
36
+ // Build primary agent runtime (for REPL)
37
+ const agentName = process.argv[3] ?? DEFAULT_AGENT;
38
+ if (!config.agents[agentName]) {
39
+ const names = Object.keys(config.agents).join(", ");
40
+ console.error(`Agent "${agentName}" not found. Available: ${names}`);
41
+ process.exit(1);
42
+ }
43
+ const runtime = buildAgentRuntime(agentName, config, {
44
+ dataDir: DATA_DIR,
45
+ skillsDir: SKILLS_DIR,
46
+ usageStore,
47
+ });
48
+ runtime.toolRegistry.validateAgents(config.agents);
49
+ const { resolved, toolRegistry, agentRegistry, promptFragments, skillsIndex, soul, session } = runtime;
50
+ // Cron scheduler
51
+ const scheduler = new CronScheduler(config, toolRegistry, agentRegistry, DATA_DIR, SKILLS_DIR, usageStore);
52
+ const enabledJobs = scheduler.getJobs().filter((j) => j.enabled);
53
+ // Agent executor for Slack
54
+ const executeAgent = createAgentExecutor(config, {
55
+ dataDir: DATA_DIR,
56
+ skillsDir: SKILLS_DIR,
57
+ agentRegistry,
58
+ usageStore,
59
+ source: "slack",
60
+ });
61
+ // Slack gateway
62
+ let gateway;
63
+ const hasSlackBindings = Object.values(config.agents).some((a) => a.slack);
64
+ if (hasSlackBindings && process.env.SLACK_BOT_TOKEN && process.env.SLACK_APP_TOKEN) {
65
+ try {
66
+ gateway = createSlackGateway(config, { onAgentRequest: executeAgent });
67
+ await gateway.start();
68
+ const bindingCount = Object.values(config.agents).filter((a) => a.slack).length;
69
+ log.info({ bindings: bindingCount }, "Slack connected");
70
+ }
71
+ catch (err) {
72
+ log.warn({ err }, "Slack failed to connect");
73
+ }
74
+ }
75
+ // API server
76
+ try {
77
+ const actualPort = await apiServer.start();
78
+ log.info({ port: actualPort }, "API server started");
79
+ }
80
+ catch (err) {
81
+ log.warn({ err }, "failed to start API server");
82
+ }
83
+ // Cron
84
+ if (enabledJobs.length > 0) {
85
+ scheduler.start({
86
+ onResult: (jobId, agentName, result) => {
87
+ log.info({ jobId, tokens: result.usage.inputTokens + result.usage.outputTokens }, "cron job completed");
88
+ process.stdout.write("You: ");
89
+ const channelOverride = config.cron.find((j) => j.id === jobId)?.slack?.channelId;
90
+ gateway?.onJobResult(agentName, jobId, result, channelOverride).catch((err) => log.warn({ err, jobId }, "failed to post cron result to Slack"));
91
+ },
92
+ onError: (jobId, agentName, error) => {
93
+ log.error({ err: error, jobId }, "cron job failed");
94
+ process.stdout.write("You: ");
95
+ const channelOverride = config.cron.find((j) => j.id === jobId)?.slack?.channelId;
96
+ gateway?.onJobError(agentName, jobId, error, channelOverride).catch((err) => log.warn({ err, jobId }, "failed to post cron error to Slack"));
97
+ },
98
+ });
99
+ }
100
+ // Heartbeat
101
+ const heartbeat = new HeartbeatRunner(config, agentRegistry, DATA_DIR, SKILLS_DIR, usageStore);
102
+ const heartbeatAgents = heartbeat.getHeartbeatAgents();
103
+ if (heartbeatAgents.length > 0) {
104
+ heartbeat.start({
105
+ onResult: (agentName, result) => {
106
+ log.info({ agent: agentName, tokens: result.usage.inputTokens + result.usage.outputTokens }, "heartbeat alert");
107
+ process.stdout.write("You: ");
108
+ const channelOverride = config.agents[agentName]?.heartbeat?.slack?.channelId;
109
+ gateway?.onJobResult(agentName, "heartbeat", result, channelOverride).catch((err) => log.warn({ err, agent: agentName }, "failed to post heartbeat result to Slack"));
110
+ },
111
+ onError: (agentName, error) => {
112
+ log.error({ err: error, agent: agentName }, "heartbeat failed");
113
+ process.stdout.write("You: ");
114
+ const channelOverride = config.agents[agentName]?.heartbeat?.slack?.channelId;
115
+ gateway?.onJobError(agentName, "heartbeat", error, channelOverride).catch((err) => log.warn({ err, agent: agentName }, "failed to post heartbeat error to Slack"));
116
+ },
117
+ onSuppressed: (agentName) => {
118
+ log.debug({ agent: agentName }, "heartbeat OK, suppressed");
119
+ },
120
+ });
121
+ }
122
+ // Status dashboard
123
+ const agentList = Object.entries(config.agents);
124
+ console.log();
125
+ console.log(" Agent Kit");
126
+ console.log();
127
+ console.log(` Agents: ${agentList.length}`);
128
+ for (const [name, def] of agentList) {
129
+ const emoji = def.emoji ?? " ";
130
+ const display = def.displayName ?? name;
131
+ console.log(` ${emoji} ${display} (${name})`);
132
+ }
133
+ console.log();
134
+ console.log(` REPL agent: ${agentName} (${resolved.model})`);
135
+ if (enabledJobs.length > 0) {
136
+ console.log(` Cron: ${enabledJobs.length} job(s)`);
137
+ }
138
+ if (heartbeatAgents.length > 0) {
139
+ console.log(` Heartbeat: ${heartbeatAgents.join(", ")}`);
140
+ }
141
+ if (gateway) {
142
+ const bindingCount = Object.values(config.agents).filter((a) => a.slack).length;
143
+ console.log(` Slack: ${bindingCount} binding(s)`);
144
+ }
145
+ if (config.defaults.usage) {
146
+ console.log(` Usage: tracking enabled`);
147
+ }
148
+ console.log();
149
+ console.log(` Commands: /new (reset), /agents, /help, /quit`);
150
+ console.log();
151
+ // REPL
152
+ let messages = session.getMessages();
153
+ const rl = readline.createInterface({
154
+ input: process.stdin,
155
+ output: process.stdout,
156
+ });
157
+ const shutdown = async () => {
158
+ scheduler.stop();
159
+ heartbeat.stop();
160
+ await gateway?.stop();
161
+ await apiServer.stop();
162
+ try {
163
+ usageStore?.close();
164
+ }
165
+ catch { }
166
+ rl.close();
167
+ };
168
+ const ask = () => {
169
+ rl.question("You: ", async (input) => {
170
+ const trimmed = input.trim();
171
+ if (trimmed === "/quit") {
172
+ await shutdown();
173
+ return;
174
+ }
175
+ if (trimmed === "/new") {
176
+ messages = [];
177
+ console.log(" Session reset.\n");
178
+ ask();
179
+ return;
180
+ }
181
+ if (trimmed === "/agents") {
182
+ for (const [name, def] of agentList) {
183
+ const emoji = def.emoji ?? " ";
184
+ const display = def.displayName ?? name;
185
+ console.log(` ${emoji} ${display} (${name})`);
186
+ }
187
+ console.log();
188
+ ask();
189
+ return;
190
+ }
191
+ if (trimmed === "/help") {
192
+ console.log(" /new — Reset conversation");
193
+ console.log(" /agents — List agents");
194
+ console.log(" /quit — Shut down\n");
195
+ ask();
196
+ return;
197
+ }
198
+ if (!trimmed) {
199
+ ask();
200
+ return;
201
+ }
202
+ const userMsg = { role: "user", content: trimmed };
203
+ messages.push(userMsg);
204
+ session.append(userMsg);
205
+ messages = await compactMessages(messages, resolved.model, resolved.compactionThreshold);
206
+ try {
207
+ const systemPrompt = buildSystemPrompt(soul, skillsIndex, promptFragments);
208
+ const result = await runAgentLoop(messages, {
209
+ model: resolved.model,
210
+ fallbacks: resolved.fallbacks,
211
+ systemPrompt,
212
+ toolRegistry,
213
+ maxIterations: resolved.maxIterations,
214
+ compactionThreshold: resolved.compactionThreshold,
215
+ maxToolResultSize: resolved.maxToolResultSize,
216
+ agentName,
217
+ usageStore,
218
+ source: "cli",
219
+ });
220
+ const newMessages = result.messages.slice(messages.length - 1);
221
+ for (const msg of newMessages) {
222
+ session.append(msg);
223
+ }
224
+ messages = result.messages;
225
+ console.log(`\nAgent: ${result.text}`);
226
+ console.log(` (${result.usage.inputTokens + result.usage.outputTokens} tokens)\n`);
227
+ }
228
+ catch (err) {
229
+ console.error(`\n Error: ${err instanceof Error ? err.message : err}\n`);
230
+ }
231
+ ask();
232
+ });
233
+ };
234
+ ask();
235
+ }
@@ -0,0 +1,17 @@
1
+ export declare function banner(): void;
2
+ export declare function status(label: string, value: string): void;
3
+ export declare function done(message: string): void;
4
+ export declare function onCancel(): void;
5
+ /**
6
+ * Check if a @clack/prompts value was cancelled. Exits the process if so.
7
+ * The `return` after `isCancel()` in callers is technically unreachable
8
+ * but satisfies TypeScript control flow analysis.
9
+ */
10
+ export declare function isCancel(value: unknown): value is symbol;
11
+ /**
12
+ * Resolve the Anthropic API key: env var → .env file → interactive prompt.
13
+ * Sets process.env.ANTHROPIC_API_KEY so downstream LLM providers pick it up.
14
+ */
15
+ export declare function resolveApiKey(opts?: {
16
+ save?: boolean;
17
+ }): Promise<string>;
package/dist/cli/ui.js ADDED
@@ -0,0 +1,79 @@
1
+ import * as fs from "fs";
2
+ import * as path from "path";
3
+ import * as p from "@clack/prompts";
4
+ const VERSION = "0.1.0";
5
+ export function banner() {
6
+ console.log();
7
+ p.intro(`agent-kit v${VERSION}`);
8
+ }
9
+ export function status(label, value) {
10
+ p.log.info(`${label}: ${value}`);
11
+ }
12
+ export function done(message) {
13
+ p.outro(message);
14
+ }
15
+ export function onCancel() {
16
+ p.cancel("Cancelled.");
17
+ process.exit(0);
18
+ }
19
+ /**
20
+ * Check if a @clack/prompts value was cancelled. Exits the process if so.
21
+ * The `return` after `isCancel()` in callers is technically unreachable
22
+ * but satisfies TypeScript control flow analysis.
23
+ */
24
+ export function isCancel(value) {
25
+ if (p.isCancel(value)) {
26
+ onCancel(); // calls process.exit(0)
27
+ }
28
+ return false;
29
+ }
30
+ /**
31
+ * Resolve the Anthropic API key: env var → .env file → interactive prompt.
32
+ * Sets process.env.ANTHROPIC_API_KEY so downstream LLM providers pick it up.
33
+ */
34
+ export async function resolveApiKey(opts) {
35
+ // 1. Check env var
36
+ if (process.env.ANTHROPIC_API_KEY) {
37
+ return process.env.ANTHROPIC_API_KEY;
38
+ }
39
+ // 2. Check .env file
40
+ const envPath = path.join(process.cwd(), ".env");
41
+ if (fs.existsSync(envPath)) {
42
+ const content = fs.readFileSync(envPath, "utf-8");
43
+ const match = content.match(/^ANTHROPIC_API_KEY=(.+)$/m);
44
+ if (match) {
45
+ const key = match[1].trim().replace(/^["']|["']$/g, "");
46
+ process.env.ANTHROPIC_API_KEY = key;
47
+ return key;
48
+ }
49
+ }
50
+ // 3. Interactive prompt
51
+ const key = await p.text({
52
+ message: "Enter your Anthropic API key:",
53
+ placeholder: "sk-ant-...",
54
+ validate: (val) => {
55
+ if (!val?.trim())
56
+ return "API key is required";
57
+ if (!val.startsWith("sk-ant-"))
58
+ return "Key should start with sk-ant-";
59
+ },
60
+ });
61
+ if (isCancel(key))
62
+ process.exit(0);
63
+ const apiKey = key.trim();
64
+ process.env.ANTHROPIC_API_KEY = apiKey;
65
+ // 4. Offer to save to .env
66
+ if (opts?.save !== false) {
67
+ const shouldSave = await p.confirm({
68
+ message: "Save API key to .env for future use?",
69
+ });
70
+ if (!isCancel(shouldSave) && shouldSave) {
71
+ const envContent = fs.existsSync(envPath)
72
+ ? fs.readFileSync(envPath, "utf-8") + "\n"
73
+ : "";
74
+ fs.writeFileSync(envPath, envContent + `ANTHROPIC_API_KEY=${apiKey}\n`);
75
+ p.log.success("Saved to .env");
76
+ }
77
+ }
78
+ return apiKey;
79
+ }
@@ -0,0 +1 @@
1
+ export declare function validate(agentName?: string): void;
@@ -0,0 +1,47 @@
1
+ import * as path from "path";
2
+ import { loadConfig } from "../config/index.js";
3
+ import { validateAgent } from "../scripts/validate-agent.js";
4
+ const PASS = "\u2713";
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
+ function printResult(result) {
10
+ for (const check of result.checks) {
11
+ const icon = check.passed ? PASS : FAIL;
12
+ console.log(` ${icon} [${check.name}] ${check.message}`);
13
+ }
14
+ }
15
+ export function validate(agentName) {
16
+ let config;
17
+ try {
18
+ config = loadConfig(CONFIG_PATH);
19
+ }
20
+ catch (err) {
21
+ console.error(`${FAIL} Config failed to load: ${err instanceof Error ? err.message : err}`);
22
+ process.exit(1);
23
+ }
24
+ const opts = { skillsDir: SKILLS_DIR, dataDir: DATA_DIR };
25
+ // Validate all agents if no name given
26
+ const names = agentName ? [agentName] : Object.keys(config.agents);
27
+ if (names.length === 0) {
28
+ console.log("No agents configured.");
29
+ return;
30
+ }
31
+ let allPassed = true;
32
+ for (const name of names) {
33
+ console.log(`\n Validating: ${name}`);
34
+ const result = validateAgent(name, config, opts);
35
+ printResult(result);
36
+ if (!result.success)
37
+ allPassed = false;
38
+ }
39
+ console.log();
40
+ if (allPassed) {
41
+ console.log(` All checks passed.`);
42
+ }
43
+ else {
44
+ console.log(` Some checks failed.`);
45
+ process.exit(1);
46
+ }
47
+ }
package/dist/cli.d.ts ADDED
@@ -0,0 +1,4 @@
1
+ #!/usr/bin/env node
2
+ declare const command: string;
3
+ declare const args: string[];
4
+ declare function main(): Promise<void>;
package/dist/cli.js ADDED
@@ -0,0 +1,59 @@
1
+ #!/usr/bin/env node
2
+ "use strict";
3
+ const command = process.argv[2];
4
+ const args = process.argv.slice(3);
5
+ async function main() {
6
+ switch (command) {
7
+ case "init": {
8
+ const { init } = await import("./cli/init.js");
9
+ await init();
10
+ break;
11
+ }
12
+ case "start": {
13
+ const { start } = await import("./cli/start.js");
14
+ await start();
15
+ break;
16
+ }
17
+ case "create": {
18
+ const { create } = await import("./cli/create.js");
19
+ await create();
20
+ break;
21
+ }
22
+ case "list": {
23
+ const { list } = await import("./cli/list.js");
24
+ list();
25
+ break;
26
+ }
27
+ case "chat": {
28
+ const { chat } = await import("./cli/chat.js");
29
+ await chat(args[0]);
30
+ break;
31
+ }
32
+ case "validate": {
33
+ const { validate } = await import("./cli/validate.js");
34
+ validate(args[0]);
35
+ break;
36
+ }
37
+ default: {
38
+ console.log(`
39
+ agent-kit — personal AI agent framework
40
+
41
+ Usage:
42
+ agent-kit init AI-powered setup wizard
43
+ agent-kit start Start all services + REPL
44
+ agent-kit create AI-powered agent creation
45
+ agent-kit list Show configured agents
46
+ agent-kit chat <agent> Lightweight single-agent chat
47
+ agent-kit validate [agent] Validate config
48
+
49
+ Options:
50
+ --help Show this help
51
+ `);
52
+ process.exit(command === "--help" || command === "-h" ? 0 : 1);
53
+ }
54
+ }
55
+ }
56
+ main().catch((err) => {
57
+ console.error(err instanceof Error ? err.message : err);
58
+ process.exit(1);
59
+ });
@@ -0,0 +1,4 @@
1
+ export { ConfigSchema, type Config, type AgentDef, type CronJobDef, type SandboxDef, type ModelEntry, type SpawnTarget } from "./schema.js";
2
+ export { loadConfig } from "./loader.js";
3
+ export { resolveAgent, resolveModelAlias, buildFallbacks, type ResolvedAgent } from "./resolve.js";
4
+ export { type SkillManifest } from "../skills/index.js";
@@ -0,0 +1,3 @@
1
+ export { ConfigSchema } from "./schema.js";
2
+ export { loadConfig } from "./loader.js";
3
+ export { resolveAgent, resolveModelAlias, buildFallbacks } from "./resolve.js";
@@ -0,0 +1,2 @@
1
+ import { type Config } from "./schema.js";
2
+ export declare function loadConfig(configPath: string): Config;
@@ -0,0 +1,10 @@
1
+ import * as fs from "fs";
2
+ import { ConfigSchema } from "./schema.js";
3
+ export function loadConfig(configPath) {
4
+ if (!fs.existsSync(configPath)) {
5
+ return ConfigSchema.parse({});
6
+ }
7
+ const raw = fs.readFileSync(configPath, "utf-8");
8
+ const json = JSON.parse(raw);
9
+ return ConfigSchema.parse(json);
10
+ }
@@ -0,0 +1,22 @@
1
+ import type { Config, SandboxDef, ModelEntry, SpawnTarget, WebSearchConfig } from "./schema.js";
2
+ import type { ToolRegistry } from "../tools/registry.js";
3
+ import type { Tool } from "../tools/types.js";
4
+ import { type SkillManifest } from "../skills/index.js";
5
+ export interface ResolvedAgent {
6
+ model: string;
7
+ fallbacks: string[];
8
+ tools: Tool[];
9
+ skills: SkillManifest[];
10
+ canSpawn: SpawnTarget[];
11
+ maxIterations: number;
12
+ maxTokens: number;
13
+ compactionThreshold: number;
14
+ commandTimeout: number;
15
+ maxToolResultSize: number;
16
+ spawn_only: boolean;
17
+ sandbox?: SandboxDef;
18
+ }
19
+ export declare function resolveWebSearch(agentName: string, config: Config): WebSearchConfig;
20
+ export declare function resolveModelAlias(alias: string, models?: ModelEntry[]): string;
21
+ export declare function buildFallbacks(primaryModel: string, models?: ModelEntry[]): string[];
22
+ export declare function resolveAgent(name: string, config: Config, toolRegistry: ToolRegistry, skillsDir?: string): ResolvedAgent;
@@ -0,0 +1,45 @@
1
+ import { loadAllSkillManifests } from "../skills/index.js";
2
+ export function resolveWebSearch(agentName, config) {
3
+ const agentDef = config.agents[agentName];
4
+ return agentDef?.webSearch ?? config.defaults.webSearch;
5
+ }
6
+ export function resolveModelAlias(alias, models) {
7
+ if (!models)
8
+ return alias;
9
+ const entry = models.find((m) => m.alias === alias);
10
+ if (!entry)
11
+ throw new Error(`Unknown model alias "${alias}"`);
12
+ return entry.model;
13
+ }
14
+ export function buildFallbacks(primaryModel, models) {
15
+ if (!models)
16
+ return [];
17
+ return models
18
+ .map((m) => m.model)
19
+ .filter((m) => m !== primaryModel);
20
+ }
21
+ export function resolveAgent(name, config, toolRegistry, skillsDir) {
22
+ const agentDef = config.agents[name];
23
+ if (!agentDef)
24
+ throw new Error(`Unknown agent "${name}"`);
25
+ const modelAlias = agentDef.model ?? config.defaults.model;
26
+ const model = resolveModelAlias(modelAlias, config.models);
27
+ const fallbacks = buildFallbacks(model, config.models);
28
+ const skills = agentDef.skills && agentDef.skills.length > 0 && skillsDir
29
+ ? loadAllSkillManifests(agentDef.skills, skillsDir)
30
+ : [];
31
+ return {
32
+ model,
33
+ fallbacks,
34
+ tools: toolRegistry.resolve(agentDef.tools),
35
+ skills,
36
+ canSpawn: agentDef.can_spawn,
37
+ maxIterations: agentDef.maxIterations ?? config.defaults.maxIterations,
38
+ maxTokens: agentDef.maxTokens ?? config.defaults.maxTokens,
39
+ compactionThreshold: config.defaults.compactionThreshold,
40
+ commandTimeout: config.defaults.commandTimeout,
41
+ maxToolResultSize: config.defaults.maxToolResultSize,
42
+ spawn_only: agentDef.spawn_only,
43
+ sandbox: agentDef.sandbox ?? config.defaults.sandbox,
44
+ };
45
+ }