@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,217 @@
1
+ import { z } from "zod";
2
+ declare const SandboxSchema: z.ZodObject<{
3
+ allowedCommands: z.ZodOptional<z.ZodArray<z.ZodString>>;
4
+ allowedPaths: z.ZodOptional<z.ZodArray<z.ZodString>>;
5
+ }, z.core.$strip>;
6
+ declare const ModelEntrySchema: z.ZodObject<{
7
+ model: z.ZodString;
8
+ alias: z.ZodString;
9
+ }, z.core.$strip>;
10
+ declare const MemorySchema: z.ZodObject<{
11
+ dbPath: z.ZodDefault<z.ZodString>;
12
+ ollamaEndpoint: z.ZodDefault<z.ZodString>;
13
+ ollamaModel: z.ZodDefault<z.ZodString>;
14
+ }, z.core.$strip>;
15
+ declare const UsageSchema: z.ZodObject<{
16
+ dbPath: z.ZodDefault<z.ZodString>;
17
+ apiPort: z.ZodDefault<z.ZodNumber>;
18
+ }, z.core.$strip>;
19
+ declare const WebSearchConfigSchema: z.ZodOptional<z.ZodObject<{
20
+ provider: z.ZodDefault<z.ZodEnum<{
21
+ brave: "brave";
22
+ grok: "grok";
23
+ }>>;
24
+ grok: z.ZodOptional<z.ZodObject<{
25
+ model: z.ZodDefault<z.ZodString>;
26
+ }, z.core.$strip>>;
27
+ }, z.core.$strip>>;
28
+ declare const SlackBindingSchema: z.ZodObject<{
29
+ channelId: z.ZodString;
30
+ channelName: z.ZodString;
31
+ }, z.core.$strip>;
32
+ declare const SpawnTargetSchema: z.ZodObject<{
33
+ agent: z.ZodString;
34
+ tool: z.ZodString;
35
+ description: z.ZodString;
36
+ }, z.core.$strip>;
37
+ declare const HeartbeatSchema: z.ZodObject<{
38
+ enabled: z.ZodDefault<z.ZodBoolean>;
39
+ intervalMinutes: z.ZodDefault<z.ZodNumber>;
40
+ model: z.ZodOptional<z.ZodString>;
41
+ maxIterations: z.ZodOptional<z.ZodNumber>;
42
+ activeHours: z.ZodOptional<z.ZodObject<{
43
+ start: z.ZodNumber;
44
+ end: z.ZodNumber;
45
+ timezone: z.ZodDefault<z.ZodString>;
46
+ }, z.core.$strip>>;
47
+ slack: z.ZodOptional<z.ZodObject<{
48
+ channelId: z.ZodString;
49
+ channelName: z.ZodString;
50
+ }, z.core.$strip>>;
51
+ }, z.core.$strip>;
52
+ declare const AgentSchema: z.ZodObject<{
53
+ displayName: z.ZodOptional<z.ZodString>;
54
+ emoji: z.ZodOptional<z.ZodString>;
55
+ avatar: z.ZodOptional<z.ZodString>;
56
+ model: z.ZodOptional<z.ZodString>;
57
+ tools: z.ZodDefault<z.ZodArray<z.ZodString>>;
58
+ skills: z.ZodDefault<z.ZodArray<z.ZodString>>;
59
+ spawn_only: z.ZodDefault<z.ZodBoolean>;
60
+ can_spawn: z.ZodDefault<z.ZodArray<z.ZodObject<{
61
+ agent: z.ZodString;
62
+ tool: z.ZodString;
63
+ description: z.ZodString;
64
+ }, z.core.$strip>>>;
65
+ maxIterations: z.ZodOptional<z.ZodNumber>;
66
+ maxTokens: z.ZodOptional<z.ZodNumber>;
67
+ sandbox: z.ZodOptional<z.ZodObject<{
68
+ allowedCommands: z.ZodOptional<z.ZodArray<z.ZodString>>;
69
+ allowedPaths: z.ZodOptional<z.ZodArray<z.ZodString>>;
70
+ }, z.core.$strip>>;
71
+ slack: z.ZodOptional<z.ZodObject<{
72
+ channelId: z.ZodString;
73
+ channelName: z.ZodString;
74
+ }, z.core.$strip>>;
75
+ heartbeat: z.ZodOptional<z.ZodObject<{
76
+ enabled: z.ZodDefault<z.ZodBoolean>;
77
+ intervalMinutes: z.ZodDefault<z.ZodNumber>;
78
+ model: z.ZodOptional<z.ZodString>;
79
+ maxIterations: z.ZodOptional<z.ZodNumber>;
80
+ activeHours: z.ZodOptional<z.ZodObject<{
81
+ start: z.ZodNumber;
82
+ end: z.ZodNumber;
83
+ timezone: z.ZodDefault<z.ZodString>;
84
+ }, z.core.$strip>>;
85
+ slack: z.ZodOptional<z.ZodObject<{
86
+ channelId: z.ZodString;
87
+ channelName: z.ZodString;
88
+ }, z.core.$strip>>;
89
+ }, z.core.$strip>>;
90
+ webSearch: z.ZodOptional<z.ZodObject<{
91
+ provider: z.ZodDefault<z.ZodEnum<{
92
+ brave: "brave";
93
+ grok: "grok";
94
+ }>>;
95
+ grok: z.ZodOptional<z.ZodObject<{
96
+ model: z.ZodDefault<z.ZodString>;
97
+ }, z.core.$strip>>;
98
+ }, z.core.$strip>>;
99
+ }, z.core.$strip>;
100
+ declare const CronJobSchema: z.ZodObject<{
101
+ id: z.ZodString;
102
+ agent: z.ZodString;
103
+ schedule: z.ZodString;
104
+ prompt: z.ZodString;
105
+ enabled: z.ZodBoolean;
106
+ slack: z.ZodOptional<z.ZodObject<{
107
+ channelId: z.ZodString;
108
+ channelName: z.ZodString;
109
+ }, z.core.$strip>>;
110
+ }, z.core.$strip>;
111
+ export declare const ConfigSchema: z.ZodObject<{
112
+ models: z.ZodOptional<z.ZodArray<z.ZodObject<{
113
+ model: z.ZodString;
114
+ alias: z.ZodString;
115
+ }, z.core.$strip>>>;
116
+ defaults: z.ZodDefault<z.ZodObject<{
117
+ model: z.ZodDefault<z.ZodString>;
118
+ maxTokens: z.ZodDefault<z.ZodNumber>;
119
+ maxIterations: z.ZodDefault<z.ZodNumber>;
120
+ compactionThreshold: z.ZodDefault<z.ZodNumber>;
121
+ commandTimeout: z.ZodDefault<z.ZodNumber>;
122
+ maxToolResultSize: z.ZodDefault<z.ZodNumber>;
123
+ sandbox: z.ZodOptional<z.ZodObject<{
124
+ allowedCommands: z.ZodOptional<z.ZodArray<z.ZodString>>;
125
+ allowedPaths: z.ZodOptional<z.ZodArray<z.ZodString>>;
126
+ }, z.core.$strip>>;
127
+ memory: z.ZodOptional<z.ZodObject<{
128
+ dbPath: z.ZodDefault<z.ZodString>;
129
+ ollamaEndpoint: z.ZodDefault<z.ZodString>;
130
+ ollamaModel: z.ZodDefault<z.ZodString>;
131
+ }, z.core.$strip>>;
132
+ usage: z.ZodOptional<z.ZodObject<{
133
+ dbPath: z.ZodDefault<z.ZodString>;
134
+ apiPort: z.ZodDefault<z.ZodNumber>;
135
+ }, z.core.$strip>>;
136
+ webSearch: z.ZodOptional<z.ZodObject<{
137
+ provider: z.ZodDefault<z.ZodEnum<{
138
+ brave: "brave";
139
+ grok: "grok";
140
+ }>>;
141
+ grok: z.ZodOptional<z.ZodObject<{
142
+ model: z.ZodDefault<z.ZodString>;
143
+ }, z.core.$strip>>;
144
+ }, z.core.$strip>>;
145
+ }, z.core.$strip>>;
146
+ agents: z.ZodDefault<z.ZodRecord<z.ZodString, z.ZodObject<{
147
+ displayName: z.ZodOptional<z.ZodString>;
148
+ emoji: z.ZodOptional<z.ZodString>;
149
+ avatar: z.ZodOptional<z.ZodString>;
150
+ model: z.ZodOptional<z.ZodString>;
151
+ tools: z.ZodDefault<z.ZodArray<z.ZodString>>;
152
+ skills: z.ZodDefault<z.ZodArray<z.ZodString>>;
153
+ spawn_only: z.ZodDefault<z.ZodBoolean>;
154
+ can_spawn: z.ZodDefault<z.ZodArray<z.ZodObject<{
155
+ agent: z.ZodString;
156
+ tool: z.ZodString;
157
+ description: z.ZodString;
158
+ }, z.core.$strip>>>;
159
+ maxIterations: z.ZodOptional<z.ZodNumber>;
160
+ maxTokens: z.ZodOptional<z.ZodNumber>;
161
+ sandbox: z.ZodOptional<z.ZodObject<{
162
+ allowedCommands: z.ZodOptional<z.ZodArray<z.ZodString>>;
163
+ allowedPaths: z.ZodOptional<z.ZodArray<z.ZodString>>;
164
+ }, z.core.$strip>>;
165
+ slack: z.ZodOptional<z.ZodObject<{
166
+ channelId: z.ZodString;
167
+ channelName: z.ZodString;
168
+ }, z.core.$strip>>;
169
+ heartbeat: z.ZodOptional<z.ZodObject<{
170
+ enabled: z.ZodDefault<z.ZodBoolean>;
171
+ intervalMinutes: z.ZodDefault<z.ZodNumber>;
172
+ model: z.ZodOptional<z.ZodString>;
173
+ maxIterations: z.ZodOptional<z.ZodNumber>;
174
+ activeHours: z.ZodOptional<z.ZodObject<{
175
+ start: z.ZodNumber;
176
+ end: z.ZodNumber;
177
+ timezone: z.ZodDefault<z.ZodString>;
178
+ }, z.core.$strip>>;
179
+ slack: z.ZodOptional<z.ZodObject<{
180
+ channelId: z.ZodString;
181
+ channelName: z.ZodString;
182
+ }, z.core.$strip>>;
183
+ }, z.core.$strip>>;
184
+ webSearch: z.ZodOptional<z.ZodObject<{
185
+ provider: z.ZodDefault<z.ZodEnum<{
186
+ brave: "brave";
187
+ grok: "grok";
188
+ }>>;
189
+ grok: z.ZodOptional<z.ZodObject<{
190
+ model: z.ZodDefault<z.ZodString>;
191
+ }, z.core.$strip>>;
192
+ }, z.core.$strip>>;
193
+ }, z.core.$strip>>>;
194
+ cron: z.ZodDefault<z.ZodArray<z.ZodObject<{
195
+ id: z.ZodString;
196
+ agent: z.ZodString;
197
+ schedule: z.ZodString;
198
+ prompt: z.ZodString;
199
+ enabled: z.ZodBoolean;
200
+ slack: z.ZodOptional<z.ZodObject<{
201
+ channelId: z.ZodString;
202
+ channelName: z.ZodString;
203
+ }, z.core.$strip>>;
204
+ }, z.core.$strip>>>;
205
+ }, z.core.$strip>;
206
+ export type Config = z.infer<typeof ConfigSchema>;
207
+ export type AgentDef = z.infer<typeof AgentSchema>;
208
+ export type CronJobDef = z.infer<typeof CronJobSchema>;
209
+ export type SandboxDef = z.infer<typeof SandboxSchema>;
210
+ export type SlackBinding = z.infer<typeof SlackBindingSchema>;
211
+ export type ModelEntry = z.infer<typeof ModelEntrySchema>;
212
+ export type MemoryConfig = z.infer<typeof MemorySchema>;
213
+ export type UsageConfig = z.infer<typeof UsageSchema>;
214
+ export type SpawnTarget = z.infer<typeof SpawnTargetSchema>;
215
+ export type HeartbeatDef = z.infer<typeof HeartbeatSchema>;
216
+ export type WebSearchConfig = z.infer<typeof WebSearchConfigSchema>;
217
+ export {};
@@ -0,0 +1,159 @@
1
+ import { z } from "zod";
2
+ const modelPattern = /^[a-z]+:.+$/;
3
+ const SandboxSchema = z.object({
4
+ allowedCommands: z.array(z.string().min(1)).min(1).optional(),
5
+ allowedPaths: z.array(z.string().min(1)).min(1).optional(),
6
+ }).refine((s) => s.allowedCommands !== undefined || s.allowedPaths !== undefined, { message: "Sandbox must specify at least allowedCommands or allowedPaths" });
7
+ const ModelEntrySchema = z.object({
8
+ model: z.string().regex(modelPattern, "Model must be in 'provider:model-name' format"),
9
+ alias: z.string().min(1),
10
+ });
11
+ const MemorySchema = z.object({
12
+ dbPath: z.string().min(1).default("~/.agent-kit/memory.db"),
13
+ ollamaEndpoint: z.string().min(1).default("http://localhost:11434"),
14
+ ollamaModel: z.string().min(1).default("all-minilm:l6-v2"),
15
+ });
16
+ const UsageSchema = z.object({
17
+ dbPath: z.string().min(1).default("~/.agent-kit/usage.db"),
18
+ apiPort: z.number().positive().default(7878),
19
+ });
20
+ const WebSearchConfigSchema = z.object({
21
+ provider: z.enum(["brave", "grok"]).default("brave"),
22
+ grok: z.object({
23
+ model: z.string().min(1).default("grok-4-1-fast"),
24
+ }).optional(),
25
+ }).optional();
26
+ const DefaultsSchema = z.object({
27
+ model: z.string().min(1).default("anthropic:claude-sonnet-4-6"),
28
+ maxTokens: z.number().positive().default(4096),
29
+ maxIterations: z.number().positive().int().default(20),
30
+ compactionThreshold: z.number().positive().default(100_000),
31
+ commandTimeout: z.number().positive().default(30),
32
+ maxToolResultSize: z.number().positive().default(8192),
33
+ sandbox: SandboxSchema.optional(),
34
+ memory: MemorySchema.optional(),
35
+ usage: UsageSchema.optional(),
36
+ webSearch: WebSearchConfigSchema,
37
+ });
38
+ const DefaultsWithDefault = DefaultsSchema.default({
39
+ model: "anthropic:claude-sonnet-4-6",
40
+ maxTokens: 4096,
41
+ maxIterations: 20,
42
+ compactionThreshold: 100_000,
43
+ commandTimeout: 30,
44
+ maxToolResultSize: 8192,
45
+ sandbox: undefined,
46
+ usage: undefined,
47
+ webSearch: undefined,
48
+ });
49
+ const SlackBindingSchema = z.object({
50
+ channelId: z.string().min(1),
51
+ channelName: z.string().min(1),
52
+ });
53
+ const SpawnTargetSchema = z.object({
54
+ agent: z.string().min(1),
55
+ tool: z.string().min(1),
56
+ description: z.string().min(1),
57
+ });
58
+ const ActiveHoursSchema = z.object({
59
+ start: z.number().int().min(0).max(23),
60
+ end: z.number().int().min(0).max(23),
61
+ timezone: z.string().min(1).default("America/Chicago").refine((tz) => {
62
+ try {
63
+ Intl.DateTimeFormat(undefined, { timeZone: tz });
64
+ return true;
65
+ }
66
+ catch {
67
+ return false;
68
+ }
69
+ }, { message: "must be a valid IANA timezone (e.g., 'America/Chicago', 'UTC')" }),
70
+ }).refine((h) => h.start !== h.end, { message: "start and end must differ" });
71
+ const HeartbeatSchema = z.object({
72
+ enabled: z.boolean().default(true),
73
+ intervalMinutes: z.number().positive().int().default(30),
74
+ model: z.string().min(1).optional(),
75
+ maxIterations: z.number().positive().int().optional(),
76
+ activeHours: ActiveHoursSchema.optional(),
77
+ slack: SlackBindingSchema.optional(),
78
+ });
79
+ const AgentSchema = z.object({
80
+ displayName: z.string().min(1).optional(),
81
+ emoji: z.string().min(1).optional(),
82
+ avatar: z.string().url().optional(),
83
+ model: z.string().min(1).optional(),
84
+ tools: z.array(z.string()).default([]),
85
+ skills: z.array(z.string().min(1)).default([]),
86
+ spawn_only: z.boolean().default(false),
87
+ can_spawn: z.array(SpawnTargetSchema).default([]),
88
+ maxIterations: z.number().positive().int().optional(),
89
+ maxTokens: z.number().positive().optional(),
90
+ sandbox: SandboxSchema.optional(),
91
+ slack: SlackBindingSchema.optional(),
92
+ heartbeat: HeartbeatSchema.optional(),
93
+ webSearch: WebSearchConfigSchema,
94
+ });
95
+ const CronJobSchema = z.object({
96
+ id: z.string().min(1),
97
+ agent: z.string().min(1),
98
+ schedule: z.string().min(1),
99
+ prompt: z.string().min(1),
100
+ enabled: z.boolean(),
101
+ slack: SlackBindingSchema.optional(),
102
+ });
103
+ export const ConfigSchema = z
104
+ .object({
105
+ models: z.array(ModelEntrySchema).optional(),
106
+ defaults: DefaultsWithDefault,
107
+ agents: z.record(z.string(), AgentSchema).default({}),
108
+ cron: z.array(CronJobSchema).default([]),
109
+ })
110
+ .refine((config) => config.cron.every((job) => job.agent in config.agents), { message: "Cron job references an agent not defined in agents" })
111
+ .refine((config) => {
112
+ if (!config.models)
113
+ return true;
114
+ const aliases = config.models.map((m) => m.alias);
115
+ return new Set(aliases).size === aliases.length;
116
+ }, { message: "Duplicate alias in models" })
117
+ .refine((config) => {
118
+ if (!config.models)
119
+ return true;
120
+ const modelStrings = config.models.map((m) => m.model);
121
+ return new Set(modelStrings).size === modelStrings.length;
122
+ }, { message: "Duplicate model string in models" })
123
+ .refine((config) => {
124
+ if (!config.models)
125
+ return true;
126
+ const aliases = new Set(config.models.map((m) => m.alias));
127
+ return aliases.has(config.defaults.model);
128
+ }, { message: "defaults.model must reference a valid alias when models is defined" })
129
+ .refine((config) => {
130
+ if (!config.models)
131
+ return true;
132
+ const aliases = new Set(config.models.map((m) => m.alias));
133
+ return Object.values(config.agents).every((agent) => !agent.model || aliases.has(agent.model));
134
+ }, { message: "Agent model must reference a valid alias when models is defined" })
135
+ .refine((config) => {
136
+ if (!config.models)
137
+ return true;
138
+ const aliases = new Set(config.models.map((m) => m.alias));
139
+ return Object.values(config.agents).every((agent) => !agent.heartbeat?.model || aliases.has(agent.heartbeat.model));
140
+ }, { message: "Heartbeat model must reference a valid alias when models is defined" })
141
+ .refine((config) => {
142
+ for (const agent of Object.values(config.agents)) {
143
+ for (const target of agent.can_spawn) {
144
+ if (!(target.agent in config.agents))
145
+ return false;
146
+ }
147
+ }
148
+ return true;
149
+ }, { message: "can_spawn references an agent not defined in agents" })
150
+ .refine((config) => {
151
+ for (const agent of Object.values(config.agents)) {
152
+ for (const target of agent.can_spawn) {
153
+ const targetAgent = config.agents[target.agent];
154
+ if (targetAgent && !targetAgent.spawn_only)
155
+ return false;
156
+ }
157
+ }
158
+ return true;
159
+ }, { message: "can_spawn target must have spawn_only: true" });
@@ -0,0 +1,22 @@
1
+ import type { Config, CronJobDef } from "../config/schema.js";
2
+ import type { ToolRegistry } from "../tools/registry.js";
3
+ import type { AgentResult } from "../agent/types.js";
4
+ import type { AgentRegistry } from "../multi/registry.js";
5
+ import type { UsageStore } from "../usage/store.js";
6
+ export declare class CronScheduler {
7
+ private tasks;
8
+ private config;
9
+ private toolRegistry;
10
+ private agentRegistry;
11
+ private dataDir;
12
+ private skillsDir;
13
+ private usageStore?;
14
+ constructor(config: Config, toolRegistry: ToolRegistry, agentRegistry: AgentRegistry, dataDir: string, skillsDir?: string, usageStore?: UsageStore);
15
+ getJobs(): CronJobDef[];
16
+ runJob(jobId: string): Promise<AgentResult | undefined>;
17
+ start(callbacks?: {
18
+ onResult?: (jobId: string, agentName: string, result: AgentResult) => void;
19
+ onError?: (jobId: string, agentName: string, error: Error) => void;
20
+ }): void;
21
+ stop(): void;
22
+ }
@@ -0,0 +1,115 @@
1
+ import cron from "node-cron";
2
+ import { runAgentLoop } from "../agent/loop.js";
3
+ import { setupAgentSession } from "../agent/setup.js";
4
+ import { resolveAgent, resolveWebSearch } from "../config/resolve.js";
5
+ import { createBuiltinRegistry } from "../tools/builtin/index.js";
6
+ import { registerSpawnWrappers } from "../tools/builtin/spawn.js";
7
+ import * as path from "path";
8
+ import { createActivateSkillTool } from "../skills/index.js";
9
+ import { createLogger } from "../logger.js";
10
+ import { dateContext } from "../text.js";
11
+ const log = createLogger("cron");
12
+ export class CronScheduler {
13
+ tasks = [];
14
+ config;
15
+ toolRegistry;
16
+ agentRegistry;
17
+ dataDir;
18
+ skillsDir;
19
+ usageStore;
20
+ constructor(config, toolRegistry, agentRegistry, dataDir, skillsDir, usageStore) {
21
+ this.config = config;
22
+ this.toolRegistry = toolRegistry;
23
+ this.agentRegistry = agentRegistry;
24
+ this.dataDir = dataDir;
25
+ this.skillsDir = skillsDir ?? path.join(process.cwd(), "skills");
26
+ this.usageStore = usageStore;
27
+ }
28
+ getJobs() {
29
+ return this.config.cron;
30
+ }
31
+ async runJob(jobId) {
32
+ const job = this.config.cron.find((j) => j.id === jobId);
33
+ if (!job)
34
+ return undefined;
35
+ // Resolve sandbox for this job's agent
36
+ const agentDef = this.config.agents[job.agent];
37
+ const sandbox = agentDef?.sandbox ?? this.config.defaults.sandbox;
38
+ const memoryConfig = this.config.defaults.memory;
39
+ const jobRegistry = createBuiltinRegistry({
40
+ allowedCommands: sandbox?.allowedCommands,
41
+ allowedPaths: sandbox?.allowedPaths,
42
+ memoryConfig,
43
+ webSearch: resolveWebSearch(job.agent, this.config),
44
+ });
45
+ const resolved = resolveAgent(job.agent, this.config, jobRegistry, this.skillsDir);
46
+ // Skills setup for this job
47
+ const promptFragments = [];
48
+ let skillsIndex = "";
49
+ if (resolved.skills.length > 0) {
50
+ const ctx = {
51
+ manifests: resolved.skills,
52
+ skillsDir: this.skillsDir,
53
+ toolRegistry: jobRegistry,
54
+ promptFragments,
55
+ activatedSkills: new Set(),
56
+ };
57
+ jobRegistry.register(createActivateSkillTool(ctx));
58
+ skillsIndex = "\n\nYou have the following skills available:\n\n"
59
+ + resolved.skills.map((s) => `- **${s.name}**: ${s.description}`).join("\n")
60
+ + "\n\nTo use a skill, call the `activate_skill` tool with the skill name.";
61
+ }
62
+ // Spawn wrapper registration
63
+ if (resolved.canSpawn.length > 0) {
64
+ registerSpawnWrappers(resolved.canSpawn, this.config, this.agentRegistry, jobRegistry, this.usageStore);
65
+ }
66
+ const sessionId = `cron-${job.id}`;
67
+ const { soul, session } = setupAgentSession(this.dataDir, job.agent, sessionId);
68
+ const userMsg = { role: "user", content: job.prompt };
69
+ session.append(userMsg);
70
+ const systemPrompt = [soul, dateContext(), skillsIndex, ...promptFragments]
71
+ .filter(Boolean)
72
+ .join("\n\n") || undefined;
73
+ const result = await runAgentLoop([userMsg], {
74
+ model: resolved.model,
75
+ fallbacks: resolved.fallbacks,
76
+ systemPrompt,
77
+ toolRegistry: jobRegistry,
78
+ maxIterations: resolved.maxIterations,
79
+ compactionThreshold: resolved.compactionThreshold,
80
+ maxToolResultSize: resolved.maxToolResultSize,
81
+ agentName: job.agent,
82
+ usageStore: this.usageStore,
83
+ source: "cron",
84
+ });
85
+ const lastMsg = result.messages[result.messages.length - 1];
86
+ session.append(lastMsg);
87
+ return result;
88
+ }
89
+ start(callbacks) {
90
+ for (const job of this.config.cron) {
91
+ if (!job.enabled)
92
+ continue;
93
+ const task = cron.schedule(job.schedule, async () => {
94
+ log.info({ jobId: job.id }, "running job");
95
+ try {
96
+ const result = await this.runJob(job.id);
97
+ if (result && callbacks?.onResult)
98
+ callbacks.onResult(job.id, job.agent, result);
99
+ }
100
+ catch (err) {
101
+ const error = err instanceof Error ? err : new Error(String(err));
102
+ log.error({ err: error, jobId: job.id }, "job failed");
103
+ if (callbacks?.onError)
104
+ callbacks.onError(job.id, job.agent, error);
105
+ }
106
+ });
107
+ this.tasks.push(task);
108
+ }
109
+ }
110
+ stop() {
111
+ for (const task of this.tasks)
112
+ task.stop();
113
+ this.tasks = [];
114
+ }
115
+ }
@@ -0,0 +1,13 @@
1
+ export interface SlackClientOptions {
2
+ botToken: string;
3
+ appToken: string;
4
+ }
5
+ export interface SlackClient {
6
+ start(): Promise<void>;
7
+ stop(): Promise<void>;
8
+ postMessage(channelId: string, text: string, blocks?: unknown[], threadTs?: string): Promise<{
9
+ ok: boolean;
10
+ }>;
11
+ app: import("@slack/bolt").App;
12
+ }
13
+ export declare function createSlackClient(options: SlackClientOptions): SlackClient;
@@ -0,0 +1,44 @@
1
+ import { App } from "@slack/bolt";
2
+ const MAX_MESSAGE_LENGTH = 4000;
3
+ const TRUNCATION_SUFFIX = "\n... (truncated)";
4
+ export function createSlackClient(options) {
5
+ const app = new App({
6
+ token: options.botToken,
7
+ appToken: options.appToken,
8
+ socketMode: true,
9
+ });
10
+ // Increase ping timeouts on the underlying SocketModeClient to avoid
11
+ // spurious "pong wasn't received" warnings during long-running agent jobs.
12
+ // The Bolt App doesn't expose these options, so we patch via the receiver.
13
+ const internal = app;
14
+ if (internal.receiver?.client) {
15
+ internal.receiver.client.clientPingTimeoutMS = 30_000;
16
+ internal.receiver.client.serverPingTimeoutMS = 60_000;
17
+ }
18
+ function truncate(text) {
19
+ if (text.length <= MAX_MESSAGE_LENGTH)
20
+ return text;
21
+ return text.slice(0, MAX_MESSAGE_LENGTH - TRUNCATION_SUFFIX.length) + TRUNCATION_SUFFIX;
22
+ }
23
+ return {
24
+ app,
25
+ async start() {
26
+ await app.start();
27
+ },
28
+ async stop() {
29
+ await app.stop();
30
+ },
31
+ async postMessage(channelId, text, blocks, threadTs) {
32
+ const result = await app.client.chat.postMessage({
33
+ channel: channelId,
34
+ text: truncate(text) || " ",
35
+ ...(blocks && { blocks }),
36
+ ...(threadTs && { thread_ts: threadTs }),
37
+ });
38
+ if (!result.ok) {
39
+ throw new Error(`Slack postMessage failed for channel ${channelId}`);
40
+ }
41
+ return { ok: true };
42
+ },
43
+ };
44
+ }
@@ -0,0 +1,30 @@
1
+ /**
2
+ * Convert markdown (as produced by LLMs) to Slack Block Kit blocks.
3
+ *
4
+ * Produces an array of Block Kit objects for rich rendering:
5
+ * - Headings → header blocks
6
+ * - Horizontal rules → divider blocks
7
+ * - Tables → section blocks with monospace code for alignment
8
+ * - Text paragraphs → section blocks with mrkdwn
9
+ * - Code blocks → section blocks with triple-backtick mrkdwn
10
+ */
11
+ export interface SlackBlock {
12
+ type: string;
13
+ text?: {
14
+ type: string;
15
+ text: string;
16
+ emoji?: boolean;
17
+ };
18
+ elements?: Array<{
19
+ type: string;
20
+ text?: string;
21
+ elements?: unknown[];
22
+ }>;
23
+ [key: string]: unknown;
24
+ }
25
+ /** Convert markdown to Slack mrkdwn inline formatting */
26
+ export declare function convertInlineFormatting(text: string): string;
27
+ /** Convert full markdown string to Slack Block Kit blocks */
28
+ export declare function markdownToBlocks(md: string): SlackBlock[];
29
+ /** Plain-text fallback for notifications/accessibility */
30
+ export declare function markdownToPlainText(md: string): string;