@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,41 @@
1
+ import * as fs from "fs";
2
+ import * as path from "path";
3
+ export class SessionManager {
4
+ filePath;
5
+ constructor(sessionDir, sessionId) {
6
+ fs.mkdirSync(sessionDir, { recursive: true });
7
+ this.filePath = path.join(sessionDir, `${sessionId}.jsonl`);
8
+ }
9
+ getMessages() {
10
+ if (!fs.existsSync(this.filePath))
11
+ return [];
12
+ const lines = fs.readFileSync(this.filePath, "utf-8").split("\n");
13
+ const messages = [];
14
+ for (const line of lines) {
15
+ if (!line.trim())
16
+ continue;
17
+ try {
18
+ messages.push(JSON.parse(line));
19
+ }
20
+ catch {
21
+ // Skip corrupt lines (crash recovery)
22
+ }
23
+ }
24
+ return messages;
25
+ }
26
+ append(message) {
27
+ fs.appendFileSync(this.filePath, JSON.stringify(message) + "\n");
28
+ }
29
+ replaceAll(messages) {
30
+ const content = messages.map((m) => JSON.stringify(m)).join("\n") + "\n";
31
+ fs.writeFileSync(this.filePath, content);
32
+ }
33
+ static list(sessionDir) {
34
+ if (!fs.existsSync(sessionDir))
35
+ return [];
36
+ return fs
37
+ .readdirSync(sessionDir)
38
+ .filter((f) => f.endsWith(".jsonl"))
39
+ .map((f) => f.replace(".jsonl", ""));
40
+ }
41
+ }
@@ -0,0 +1,11 @@
1
+ import type { Tool } from "../tools/types.js";
2
+ import type { ToolRegistry } from "../tools/registry.js";
3
+ import type { SkillManifest } from "./schema.js";
4
+ export interface SkillActivationContext {
5
+ manifests: SkillManifest[];
6
+ skillsDir: string;
7
+ toolRegistry: ToolRegistry;
8
+ promptFragments: string[];
9
+ activatedSkills: Set<string>;
10
+ }
11
+ export declare function createActivateSkillTool(ctx: SkillActivationContext): Tool;
@@ -0,0 +1,62 @@
1
+ import * as fs from "fs";
2
+ import * as path from "path";
3
+ import { loadSkillManifest } from "./loader.js";
4
+ export function createActivateSkillTool(ctx) {
5
+ return {
6
+ name: "activate_skill",
7
+ description: "Activate a skill to load its full instructions and tools. Call this when you need a skill's capabilities.",
8
+ parameters: {
9
+ type: "object",
10
+ properties: {
11
+ skill_name: {
12
+ type: "string",
13
+ description: "Name of the skill to activate",
14
+ },
15
+ },
16
+ required: ["skill_name"],
17
+ },
18
+ execute: async (args) => {
19
+ const skillName = args.skill_name;
20
+ if (ctx.activatedSkills.has(skillName)) {
21
+ return `Skill "${skillName}" is already activated.`;
22
+ }
23
+ const manifest = ctx.manifests.find((m) => m.name === skillName);
24
+ if (!manifest) {
25
+ return `Skill "${skillName}" is not available. Available skills: ${ctx.manifests.map((m) => m.name).join(", ")}`;
26
+ }
27
+ const skillDir = path.join(ctx.skillsDir, skillName);
28
+ const fullManifest = loadSkillManifest(skillDir);
29
+ const loadedTools = [];
30
+ // Load prompt fragment
31
+ if (fullManifest.prompt) {
32
+ const promptPath = path.join(skillDir, fullManifest.prompt);
33
+ if (fs.existsSync(promptPath)) {
34
+ ctx.promptFragments.push(fs.readFileSync(promptPath, "utf-8"));
35
+ }
36
+ }
37
+ // Load tools via dynamic import
38
+ if (fullManifest.tools) {
39
+ for (const toolName of fullManifest.tools) {
40
+ const toolPath = path.join(skillDir, "tools", `${toolName}.ts`);
41
+ if (fs.existsSync(toolPath)) {
42
+ try {
43
+ const mod = await import(toolPath);
44
+ const tool = mod.default;
45
+ ctx.toolRegistry.register(tool);
46
+ loadedTools.push(tool.name);
47
+ }
48
+ catch (err) {
49
+ return `Error loading tool "${toolName}" from skill "${skillName}": ${err instanceof Error ? err.message : String(err)}`;
50
+ }
51
+ }
52
+ }
53
+ }
54
+ ctx.activatedSkills.add(skillName);
55
+ const parts = [`Skill "${skillName}" activated.`];
56
+ if (loadedTools.length > 0) {
57
+ parts.push(`Tools now available: ${loadedTools.join(", ")}`);
58
+ }
59
+ return parts.join(" ");
60
+ },
61
+ };
62
+ }
@@ -0,0 +1,3 @@
1
+ export { SkillManifestSchema, type SkillManifest } from "./schema.js";
2
+ export { loadSkillManifest, loadAllSkillManifests } from "./loader.js";
3
+ export { createActivateSkillTool, type SkillActivationContext } from "./activate.js";
@@ -0,0 +1,3 @@
1
+ export { SkillManifestSchema } from "./schema.js";
2
+ export { loadSkillManifest, loadAllSkillManifests } from "./loader.js";
3
+ export { createActivateSkillTool } from "./activate.js";
@@ -0,0 +1,3 @@
1
+ import { type SkillManifest } from "./schema.js";
2
+ export declare function loadSkillManifest(skillDir: string): SkillManifest;
3
+ export declare function loadAllSkillManifests(skillNames: string[], skillsDir: string): SkillManifest[];
@@ -0,0 +1,20 @@
1
+ import * as fs from "fs";
2
+ import * as path from "path";
3
+ import { SkillManifestSchema } from "./schema.js";
4
+ export function loadSkillManifest(skillDir) {
5
+ const manifestPath = path.join(skillDir, "skill.json");
6
+ if (!fs.existsSync(manifestPath)) {
7
+ throw new Error(`Missing skill.json in ${skillDir}`);
8
+ }
9
+ const raw = JSON.parse(fs.readFileSync(manifestPath, "utf-8"));
10
+ return SkillManifestSchema.parse(raw);
11
+ }
12
+ export function loadAllSkillManifests(skillNames, skillsDir) {
13
+ return skillNames.map((name) => {
14
+ const skillDir = path.join(skillsDir, name);
15
+ if (!fs.existsSync(skillDir)) {
16
+ throw new Error(`Skill directory not found: "${name}" (expected at ${skillDir})`);
17
+ }
18
+ return loadSkillManifest(skillDir);
19
+ });
20
+ }
@@ -0,0 +1,8 @@
1
+ import { z } from "zod";
2
+ export declare const SkillManifestSchema: z.ZodObject<{
3
+ name: z.ZodString;
4
+ description: z.ZodString;
5
+ tools: z.ZodOptional<z.ZodArray<z.ZodString>>;
6
+ prompt: z.ZodOptional<z.ZodString>;
7
+ }, z.core.$strip>;
8
+ export type SkillManifest = z.infer<typeof SkillManifestSchema>;
@@ -0,0 +1,7 @@
1
+ import { z } from "zod";
2
+ export const SkillManifestSchema = z.object({
3
+ name: z.string().min(1),
4
+ description: z.string().min(1),
5
+ tools: z.array(z.string().min(1)).optional(),
6
+ prompt: z.string().min(1).optional(),
7
+ });
package/dist/text.d.ts ADDED
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Truncate a string to `max` characters, appending an ellipsis if trimmed.
3
+ */
4
+ export declare function truncate(text: string, max: number): string;
5
+ /**
6
+ * Returns a context string with the current date/time for injection into system prompts.
7
+ */
8
+ export declare function dateContext(): string;
package/dist/text.js ADDED
@@ -0,0 +1,24 @@
1
+ /**
2
+ * Truncate a string to `max` characters, appending an ellipsis if trimmed.
3
+ */
4
+ export function truncate(text, max) {
5
+ return text.length > max ? text.slice(0, max) + "\u2026" : text;
6
+ }
7
+ /**
8
+ * Returns a context string with the current date/time for injection into system prompts.
9
+ */
10
+ export function dateContext() {
11
+ const now = new Date();
12
+ const date = now.toLocaleDateString("en-US", {
13
+ weekday: "long",
14
+ year: "numeric",
15
+ month: "long",
16
+ day: "numeric",
17
+ });
18
+ const time = now.toLocaleTimeString("en-US", {
19
+ hour: "2-digit",
20
+ minute: "2-digit",
21
+ hour12: true,
22
+ });
23
+ return `Current date: ${date}. Current time: ${time}.`;
24
+ }
@@ -0,0 +1,21 @@
1
+ import { ToolRegistry } from "../registry.js";
2
+ import { readFileTool } from "./read-file.js";
3
+ import { writeFileTool } from "./write-file.js";
4
+ import { runCommandTool } from "./run-command.js";
5
+ export { readFileTool, writeFileTool, runCommandTool };
6
+ interface BuiltinRegistryOptions {
7
+ allowedCommands?: string[];
8
+ allowedPaths?: string[];
9
+ memoryConfig?: {
10
+ dbPath: string;
11
+ ollamaEndpoint: string;
12
+ ollamaModel: string;
13
+ };
14
+ webSearch?: {
15
+ provider?: "brave" | "grok";
16
+ grok?: {
17
+ model?: string;
18
+ };
19
+ };
20
+ }
21
+ export declare function createBuiltinRegistry(options?: BuiltinRegistryOptions): ToolRegistry;
@@ -0,0 +1,21 @@
1
+ import { ToolRegistry } from "../registry.js";
2
+ import { createReadFileTool, readFileTool } from "./read-file.js";
3
+ import { createWriteFileTool, writeFileTool } from "./write-file.js";
4
+ import { createRunCommandTool, runCommandTool } from "./run-command.js";
5
+ import { createMemoryTools } from "./memory.js";
6
+ import { createWebSearchTool } from "./web-search.js";
7
+ export { readFileTool, writeFileTool, runCommandTool };
8
+ export function createBuiltinRegistry(options = {}) {
9
+ const registry = new ToolRegistry();
10
+ registry.register(createReadFileTool(options.allowedPaths));
11
+ registry.register(createWriteFileTool(options.allowedPaths));
12
+ registry.register(createRunCommandTool(options.allowedCommands));
13
+ registry.register(createWebSearchTool(options.webSearch));
14
+ if (options.memoryConfig) {
15
+ const memoryTools = createMemoryTools(options.memoryConfig);
16
+ for (const tool of memoryTools) {
17
+ registry.register(tool);
18
+ }
19
+ }
20
+ return registry;
21
+ }
@@ -0,0 +1,8 @@
1
+ import type { Tool } from "../types.js";
2
+ interface MemoryToolsConfig {
3
+ dbPath: string;
4
+ ollamaEndpoint: string;
5
+ ollamaModel: string;
6
+ }
7
+ export declare function createMemoryTools(config: MemoryToolsConfig): Tool[];
8
+ export {};
@@ -0,0 +1,164 @@
1
+ import { createDatabase, MemoryStore, HybridSearch, OllamaEmbeddingProvider } from "../../_memory/index.js";
2
+ import * as os from "os";
3
+ import * as path from "path";
4
+ import * as fs from "fs";
5
+ export function createMemoryTools(config) {
6
+ const provider = new OllamaEmbeddingProvider({
7
+ endpoint: config.ollamaEndpoint,
8
+ model: config.ollamaModel,
9
+ });
10
+ const resolvedPath = config.dbPath.startsWith("~")
11
+ ? path.join(os.homedir(), config.dbPath.slice(1))
12
+ : config.dbPath;
13
+ const dir = path.dirname(resolvedPath);
14
+ if (!fs.existsSync(dir))
15
+ fs.mkdirSync(dir, { recursive: true });
16
+ const db = createDatabase(resolvedPath, provider.dimensions);
17
+ const store = new MemoryStore(db, provider);
18
+ const search = new HybridSearch(db, provider);
19
+ const storeMemory = {
20
+ name: "store_memory",
21
+ description: "Store a new memory for future retrieval. Use for facts, preferences, decisions, learnings, or observations worth remembering across sessions.",
22
+ parameters: {
23
+ type: "object",
24
+ properties: {
25
+ content: { type: "string", description: "The memory content" },
26
+ type: {
27
+ type: "string",
28
+ enum: ["fact", "preference", "decision", "learning", "observation"],
29
+ description: "Memory type",
30
+ },
31
+ namespace: { type: "string", description: "Scope: global, finance, dev/project-name, etc." },
32
+ agent_id: { type: "string", description: "Who is storing this" },
33
+ metadata: { type: "object", description: "Optional metadata" },
34
+ },
35
+ required: ["content", "type", "namespace", "agent_id"],
36
+ },
37
+ execute: async (args) => {
38
+ const result = await store.store({
39
+ content: args.content,
40
+ type: args.type,
41
+ namespace: args.namespace,
42
+ agent_id: args.agent_id,
43
+ metadata: args.metadata,
44
+ });
45
+ return JSON.stringify(result);
46
+ },
47
+ };
48
+ const searchMemory = {
49
+ name: "search_memory",
50
+ description: "Search stored memories using natural language. Returns semantically similar memories ranked by relevance.",
51
+ parameters: {
52
+ type: "object",
53
+ properties: {
54
+ query: { type: "string", description: "Search query" },
55
+ namespace: { type: "string", description: "Filter by namespace" },
56
+ agent_id: { type: "string", description: "Filter by agent" },
57
+ type: {
58
+ type: "string",
59
+ enum: ["fact", "preference", "decision", "learning", "observation"],
60
+ description: "Filter by type",
61
+ },
62
+ limit: { type: "number", description: "Max results (default 10)" },
63
+ min_score: { type: "number", description: "Minimum relevance score 0-1 (default 0.1). Filters out noise" },
64
+ },
65
+ required: ["query"],
66
+ },
67
+ execute: async (args) => {
68
+ const results = await search.search({
69
+ query: args.query,
70
+ namespace: args.namespace,
71
+ agent_id: args.agent_id,
72
+ type: args.type,
73
+ limit: args.limit,
74
+ min_score: args.min_score,
75
+ });
76
+ return JSON.stringify(results, null, 2);
77
+ },
78
+ };
79
+ const getMemory = {
80
+ name: "get_memory",
81
+ description: "Retrieve a specific memory by its ID.",
82
+ parameters: {
83
+ type: "object",
84
+ properties: {
85
+ id: { type: "string", description: "Memory ID" },
86
+ },
87
+ required: ["id"],
88
+ },
89
+ execute: async (args) => {
90
+ const memory = await store.get(args.id);
91
+ if (!memory)
92
+ return JSON.stringify({ error: "Memory not found" });
93
+ return JSON.stringify(memory, null, 2);
94
+ },
95
+ };
96
+ const updateMemory = {
97
+ name: "update_memory",
98
+ description: "Update an existing memory. Re-embeds if content changes.",
99
+ parameters: {
100
+ type: "object",
101
+ properties: {
102
+ id: { type: "string", description: "Memory ID to update" },
103
+ content: { type: "string", description: "New content" },
104
+ type: {
105
+ type: "string",
106
+ enum: ["fact", "preference", "decision", "learning", "observation"],
107
+ description: "New type",
108
+ },
109
+ metadata: { type: "object", description: "New metadata (replaces existing)" },
110
+ },
111
+ required: ["id"],
112
+ },
113
+ execute: async (args) => {
114
+ const { id, ...updates } = args;
115
+ const result = await store.update(id, updates);
116
+ return JSON.stringify(result);
117
+ },
118
+ };
119
+ const forgetMemory = {
120
+ name: "forget_memory",
121
+ description: "Soft-delete a memory. It will no longer appear in search results.",
122
+ parameters: {
123
+ type: "object",
124
+ properties: {
125
+ id: { type: "string", description: "Memory ID to forget" },
126
+ },
127
+ required: ["id"],
128
+ },
129
+ execute: async (args) => {
130
+ const result = await store.forget(args.id);
131
+ return JSON.stringify(result);
132
+ },
133
+ };
134
+ const listMemories = {
135
+ name: "list_memories",
136
+ description: "Browse memories by scope, sorted by most recent first.",
137
+ parameters: {
138
+ type: "object",
139
+ properties: {
140
+ namespace: { type: "string", description: "Filter by namespace" },
141
+ agent_id: { type: "string", description: "Filter by agent" },
142
+ type: {
143
+ type: "string",
144
+ enum: ["fact", "preference", "decision", "learning", "observation"],
145
+ description: "Filter by type",
146
+ },
147
+ limit: { type: "number", description: "Max results (default 50)" },
148
+ offset: { type: "number", description: "Pagination offset" },
149
+ },
150
+ required: [],
151
+ },
152
+ execute: async (args) => {
153
+ const results = await store.list({
154
+ namespace: args.namespace,
155
+ agent_id: args.agent_id,
156
+ type: args.type,
157
+ limit: args.limit,
158
+ offset: args.offset,
159
+ });
160
+ return JSON.stringify(results, null, 2);
161
+ },
162
+ };
163
+ return [storeMemory, searchMemory, getMemory, updateMemory, forgetMemory, listMemories];
164
+ }
@@ -0,0 +1,3 @@
1
+ import type { Tool } from "../types.js";
2
+ export declare function createReadFileTool(allowedPaths?: string[]): Tool;
3
+ export declare const readFileTool: Tool;
@@ -0,0 +1,30 @@
1
+ import * as fs from "fs";
2
+ import { validatePath } from "../sandbox.js";
3
+ export function createReadFileTool(allowedPaths) {
4
+ return {
5
+ name: "read_file",
6
+ description: "Read the contents of a file from the filesystem",
7
+ parameters: {
8
+ type: "object",
9
+ properties: {
10
+ path: { type: "string", description: "Absolute path to the file" },
11
+ },
12
+ required: ["path"],
13
+ },
14
+ execute: async (args) => {
15
+ try {
16
+ const filePath = args.path;
17
+ const validation = validatePath(filePath, allowedPaths);
18
+ if (!validation.allowed) {
19
+ return validation.error;
20
+ }
21
+ return fs.readFileSync(filePath, "utf-8");
22
+ }
23
+ catch (err) {
24
+ return `Error: ${err instanceof Error ? err.message : String(err)}`;
25
+ }
26
+ },
27
+ };
28
+ }
29
+ // Backwards-compatible default export (unrestricted)
30
+ export const readFileTool = createReadFileTool();
@@ -0,0 +1,3 @@
1
+ import type { Tool } from "../types.js";
2
+ export declare function createRunCommandTool(allowedCommands?: string[]): Tool;
3
+ export declare const runCommandTool: Tool;
@@ -0,0 +1,37 @@
1
+ import { execSync } from "child_process";
2
+ import { validateCommand } from "../sandbox.js";
3
+ export function createRunCommandTool(allowedCommands) {
4
+ return {
5
+ name: "run_command",
6
+ description: "Execute a shell command and return the output",
7
+ parameters: {
8
+ type: "object",
9
+ properties: {
10
+ command: { type: "string", description: "The shell command to run" },
11
+ timeout: { type: "number", description: "Timeout in seconds (default: 30)" },
12
+ },
13
+ required: ["command"],
14
+ },
15
+ execute: async (args) => {
16
+ const command = args.command;
17
+ const validation = validateCommand(command, allowedCommands);
18
+ if (!validation.allowed) {
19
+ return validation.error;
20
+ }
21
+ try {
22
+ const timeout = (args.timeout ?? 30) * 1000;
23
+ const output = execSync(command, {
24
+ timeout,
25
+ encoding: "utf-8",
26
+ stdio: ["pipe", "pipe", "pipe"],
27
+ });
28
+ return output;
29
+ }
30
+ catch (err) {
31
+ return err.stderr || err.stdout || `Error: ${err.message}`;
32
+ }
33
+ },
34
+ };
35
+ }
36
+ // Backwards-compatible default export (unrestricted)
37
+ export const runCommandTool = createRunCommandTool();
@@ -0,0 +1,15 @@
1
+ import type { SpawnTarget, Config } from "../../config/schema.js";
2
+ import type { AgentRegistry } from "../../multi/registry.js";
3
+ import type { ToolRegistry } from "../registry.js";
4
+ import type { Tool } from "../types.js";
5
+ import type { UsageStore } from "../../usage/store.js";
6
+ interface SpawnWrapperOptions {
7
+ target: SpawnTarget;
8
+ config: Config;
9
+ agentRegistry: AgentRegistry;
10
+ toolRegistry: ToolRegistry;
11
+ usageStore?: UsageStore;
12
+ }
13
+ export declare function createSpawnWrapperTool(options: SpawnWrapperOptions): Tool;
14
+ export declare function registerSpawnWrappers(canSpawn: SpawnTarget[], config: Config, agentRegistry: AgentRegistry, toolRegistry: ToolRegistry, usageStore?: UsageStore): void;
15
+ export {};
@@ -0,0 +1,59 @@
1
+ import { resolveModelAlias, buildFallbacks } from "../../config/resolve.js";
2
+ import { spawnAgent } from "../../multi/spawn.js";
3
+ import { createLogger } from "../../logger.js";
4
+ import { truncate } from "../../text.js";
5
+ const log = createLogger("spawn");
6
+ export function createSpawnWrapperTool(options) {
7
+ const { target, config, agentRegistry, toolRegistry } = options;
8
+ return {
9
+ name: target.tool,
10
+ description: target.description,
11
+ parameters: {
12
+ type: "object",
13
+ properties: {
14
+ task: {
15
+ type: "string",
16
+ description: "The task to delegate to the sub-agent",
17
+ },
18
+ },
19
+ required: ["task"],
20
+ },
21
+ execute: async (args) => {
22
+ const task = args.task;
23
+ const entry = agentRegistry.getAgent(target.agent);
24
+ if (!entry) {
25
+ log.error({ tool: target.tool, agent: target.agent }, "spawn target agent not found in registry");
26
+ return `Error: agent "${target.agent}" not found in registry`;
27
+ }
28
+ const model = resolveModelAlias(entry.model, config.models);
29
+ const fallbacks = buildFallbacks(model, config.models);
30
+ const tools = toolRegistry.resolve(entry.tools);
31
+ log.info({ tool: target.tool, agent: target.agent, task: truncate(task, 200) }, "spawning sub-agent");
32
+ const start = Date.now();
33
+ try {
34
+ const result = await spawnAgent({
35
+ model,
36
+ fallbacks,
37
+ systemPrompt: entry.soul,
38
+ task,
39
+ tools,
40
+ maxIterations: 10,
41
+ label: target.agent,
42
+ usageStore: options.usageStore,
43
+ });
44
+ log.info({ tool: target.tool, agent: target.agent, elapsed: Date.now() - start, snippet: truncate(result.text, 150) }, "sub-agent completed");
45
+ return result.text;
46
+ }
47
+ catch (err) {
48
+ log.error({ err, tool: target.tool, agent: target.agent, elapsed: Date.now() - start }, "sub-agent failed");
49
+ throw err;
50
+ }
51
+ },
52
+ };
53
+ }
54
+ export function registerSpawnWrappers(canSpawn, config, agentRegistry, toolRegistry, usageStore) {
55
+ for (const target of canSpawn) {
56
+ const tool = createSpawnWrapperTool({ target, config, agentRegistry, toolRegistry, usageStore });
57
+ toolRegistry.register(tool);
58
+ }
59
+ }
@@ -0,0 +1,8 @@
1
+ import type { Tool } from "../types.js";
2
+ export interface WebSearchOptions {
3
+ provider?: "brave" | "grok";
4
+ grok?: {
5
+ model?: string;
6
+ };
7
+ }
8
+ export declare function createWebSearchTool(options?: WebSearchOptions): Tool;