0xkobold 0.3.2 → 0.4.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.
- package/HEARTBEAT.md +170 -43
- package/dist/package.json +1 -1
- package/dist/src/cli/commands/cron.js +329 -0
- package/dist/src/cli/commands/cron.js.map +1 -0
- package/dist/src/cli/commands/init.js +142 -90
- package/dist/src/cli/commands/init.js.map +1 -1
- package/dist/src/cli/program.js +4 -0
- package/dist/src/cli/program.js.map +1 -1
- package/dist/src/cron/index.js +38 -0
- package/dist/src/cron/index.js.map +1 -0
- package/dist/src/cron/parser.js +294 -0
- package/dist/src/cron/parser.js.map +1 -0
- package/dist/src/cron/runner.js +243 -0
- package/dist/src/cron/runner.js.map +1 -0
- package/dist/src/cron/scheduler.js +512 -0
- package/dist/src/cron/scheduler.js.map +1 -0
- package/dist/src/cron/types.js +8 -0
- package/dist/src/cron/types.js.map +1 -0
- package/package.json +1 -1
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* 0xKobold Init Command
|
|
3
3
|
*
|
|
4
|
-
* Sets up the workspace with
|
|
4
|
+
* Sets up the workspace with existing persona system (v0.2.0).
|
|
5
|
+
* Integrates with IDENTITY.md, USER.md, SOUL.md, AGENT.md.
|
|
5
6
|
* No immediate API key required - works out of the box.
|
|
6
7
|
*/
|
|
7
8
|
import { Command } from "commander";
|
|
@@ -30,74 +31,9 @@ async function ask(question, defaultValue = "") {
|
|
|
30
31
|
const GLOBAL_KOBOLD_DIR = join(homedir(), ".0xkobold");
|
|
31
32
|
const GLOBAL_DB_PATH = join(GLOBAL_KOBOLD_DIR, "kobold.db");
|
|
32
33
|
const GLOBAL_CONFIG_PATH = join(GLOBAL_KOBOLD_DIR, "config.json");
|
|
33
|
-
|
|
34
|
+
// Local workspace
|
|
34
35
|
const LOCAL_KOBOLD_DIR = ".0xkobold";
|
|
35
36
|
const LOCAL_DB_PATH = join(LOCAL_KOBOLD_DIR, "workspace.db");
|
|
36
|
-
const LOCAL_MEMORY_PATH = join(LOCAL_KOBOLD_DIR, "MEMORY.md");
|
|
37
|
-
// 0xKobold Persona Template - Customizable
|
|
38
|
-
const KOBOLD_PERSONA_TEMPLATE = `# {{agentName}} Identity
|
|
39
|
-
|
|
40
|
-
## Name
|
|
41
|
-
{{agentName}}
|
|
42
|
-
|
|
43
|
-
## Role
|
|
44
|
-
{{agentRole}}
|
|
45
|
-
|
|
46
|
-
## Mission
|
|
47
|
-
{{agentMission}}
|
|
48
|
-
|
|
49
|
-
## Personality
|
|
50
|
-
- Helpful and direct
|
|
51
|
-
- {{personalityTrait}}
|
|
52
|
-
- Values clean code and efficiency
|
|
53
|
-
- Prefers working solutions over perfect ones
|
|
54
|
-
|
|
55
|
-
## Capabilities
|
|
56
|
-
- File operations with safety checks
|
|
57
|
-
- Shell command execution (with blocks)
|
|
58
|
-
- Multi-channel communication (Telegram, Slack, WhatsApp)
|
|
59
|
-
- Docker sandboxing for safe execution
|
|
60
|
-
- Semantic memory with SQLite
|
|
61
|
-
- Agent spawning for parallel tasks
|
|
62
|
-
- Gateway server for remote access
|
|
63
|
-
|
|
64
|
-
## Default Behavior
|
|
65
|
-
- LLM: Ollama Cloud ({{model}})
|
|
66
|
-
- Mode: build (unless investigating)
|
|
67
|
-
- Auto-compact on context overflow
|
|
68
|
-
- Proactive duplicate detection
|
|
69
|
-
|
|
70
|
-
## Style
|
|
71
|
-
- Concise responses for simple tasks
|
|
72
|
-
- Detailed breakdowns for complex ones
|
|
73
|
-
- Code blocks with language tags
|
|
74
|
-
- Error handling with actionable fixes
|
|
75
|
-
`;
|
|
76
|
-
// User memory template with customization
|
|
77
|
-
const MEMORY_TEMPLATE = `# {{agentName}} Memory
|
|
78
|
-
|
|
79
|
-
## User Profile
|
|
80
|
-
- Name: {{userName}}
|
|
81
|
-
- Background: {{userBackground}}
|
|
82
|
-
- Goals: {{userGoals}}
|
|
83
|
-
- Preferences: {{userPreferences}}
|
|
84
|
-
|
|
85
|
-
## Agent Context
|
|
86
|
-
- Created: {{timestamp}}
|
|
87
|
-
- Purpose: {{agentMission}}
|
|
88
|
-
|
|
89
|
-
## Conversations
|
|
90
|
-
|
|
91
|
-
### Session: {{timestamp}}
|
|
92
|
-
- Context: Initial setup
|
|
93
|
-
- Topics:
|
|
94
|
-
|
|
95
|
-
## Learned Patterns
|
|
96
|
-
|
|
97
|
-
## Active Tasks
|
|
98
|
-
|
|
99
|
-
## Notes
|
|
100
|
-
`;
|
|
101
37
|
// Default config - Ollama Cloud ready
|
|
102
38
|
const DEFAULT_CONFIG = {
|
|
103
39
|
version: "0.3.0",
|
|
@@ -224,27 +160,132 @@ export const initCommand = new Command("init")
|
|
|
224
160
|
`);
|
|
225
161
|
db.close();
|
|
226
162
|
console.log("✓ Database initialized");
|
|
227
|
-
// Create
|
|
228
|
-
const personaContent = KOBOLD_PERSONA_TEMPLATE
|
|
229
|
-
.replace(/\{\{agentName\}\}/g, agentName)
|
|
230
|
-
.replace(/\{\{agentRole\}\}/g, agentRole)
|
|
231
|
-
.replace(/\{\{agentMission\}\}/g, agentMission)
|
|
232
|
-
.replace(/\{\{personalityTrait\}\}/g, personalityTrait)
|
|
233
|
-
.replace(/\{\{model\}\}/g, model);
|
|
234
|
-
await writeFile(join(GLOBAL_KOBOLD_DIR, "persona.md"), personaContent, "utf-8");
|
|
235
|
-
console.log(`✓ ${agentName} persona created`);
|
|
236
|
-
// Create personalized memory template
|
|
163
|
+
// Create persona files (v0.2.0 system)
|
|
237
164
|
const timestamp = new Date().toISOString();
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
165
|
+
// IDENTITY.md - Agent identity
|
|
166
|
+
const identityContent = `# IDENTITY
|
|
167
|
+
|
|
168
|
+
**Name:** ${agentName}
|
|
169
|
+
**Emoji:** 🐉
|
|
170
|
+
**Tagline:** ${agentMission}
|
|
171
|
+
**Role:** ${agentRole}
|
|
172
|
+
|
|
173
|
+
## Tone
|
|
174
|
+
- ${personalityTrait}
|
|
175
|
+
- Uses emojis occasionally 🎉
|
|
176
|
+
- Celebrates wins with enthusiasm
|
|
177
|
+
- Gentle with mistakes
|
|
178
|
+
`;
|
|
179
|
+
await writeFile(join(GLOBAL_KOBOLD_DIR, "IDENTITY.md"), identityContent, "utf-8");
|
|
180
|
+
console.log(`✓ IDENTITY.md created`);
|
|
181
|
+
// SOUL.md - Agent soul/personality
|
|
182
|
+
const soulContent = `# SOUL - Agent Personality
|
|
183
|
+
|
|
184
|
+
## Identity
|
|
185
|
+
**Name:** ${agentName}
|
|
186
|
+
**Role:** ${agentRole}
|
|
187
|
+
**Vibe:** ${personalityTrait}
|
|
188
|
+
|
|
189
|
+
## Tone
|
|
190
|
+
- Style: Clear and conversational
|
|
191
|
+
- Formality: Casual but respectful
|
|
192
|
+
- Humor: Light and appropriate
|
|
193
|
+
|
|
194
|
+
## Core Values
|
|
195
|
+
- Helpfulness: ${agentMission}
|
|
196
|
+
- Honesty: Be truthful about capabilities
|
|
197
|
+
- Learning: Improve from every interaction
|
|
198
|
+
|
|
199
|
+
## Guidelines
|
|
200
|
+
- Ask clarifying questions when needed
|
|
201
|
+
- Provide examples when helpful
|
|
202
|
+
- Admit when unsure or need more info
|
|
203
|
+
`;
|
|
204
|
+
await writeFile(join(GLOBAL_KOBOLD_DIR, "SOUL.md"), soulContent, "utf-8");
|
|
205
|
+
console.log(`✓ SOUL.md created`);
|
|
206
|
+
// USER.md - User profile
|
|
207
|
+
const userContent = `# User Profile
|
|
208
|
+
|
|
209
|
+
## Identity
|
|
210
|
+
- **Name**: ${userName || "Developer"}
|
|
211
|
+
- **Role**: ${userBackground || "Not specified"}
|
|
212
|
+
- **Goals**: ${userGoals || "Not specified"}
|
|
213
|
+
- **Preferences**: ${userPreferences || "Not specified"}
|
|
214
|
+
|
|
215
|
+
## Working Style
|
|
216
|
+
- Collaborative and iterative
|
|
217
|
+
- Values clean, maintainable code
|
|
218
|
+
|
|
219
|
+
## Context
|
|
220
|
+
- Using 0xKobold with ${model}
|
|
221
|
+
- Setup: ${timestamp}
|
|
222
|
+
|
|
223
|
+
## Notes
|
|
224
|
+
Add any personal notes here...
|
|
225
|
+
`;
|
|
226
|
+
await writeFile(join(GLOBAL_KOBOLD_DIR, "USER.md"), userContent, "utf-8");
|
|
227
|
+
console.log(`✓ USER.md created`);
|
|
228
|
+
// AGENT.md - Agent behavior config
|
|
229
|
+
const agentContent = `# Agent Configuration
|
|
230
|
+
|
|
231
|
+
## Default Behavior
|
|
232
|
+
- Model: ${model}
|
|
233
|
+
- Understand the problem before proposing solutions
|
|
234
|
+
- Ask clarifying questions when needed
|
|
235
|
+
- Provide options with trade-offs
|
|
236
|
+
- Write maintainable, readable code
|
|
237
|
+
|
|
238
|
+
## Code Standards
|
|
239
|
+
- Preferred: TypeScript/Bun
|
|
240
|
+
- Style: Clean, documented
|
|
241
|
+
- Testing: Include where appropriate
|
|
242
|
+
|
|
243
|
+
## Communication Style
|
|
244
|
+
- ${personalityTrait}
|
|
245
|
+
- Clear explanations with examples
|
|
246
|
+
- Honest about limitations
|
|
247
|
+
|
|
248
|
+
## Tool Usage
|
|
249
|
+
- Safe file operations
|
|
250
|
+
- Sandbox for risky commands
|
|
251
|
+
- Gateway for remote access
|
|
252
|
+
`;
|
|
253
|
+
await writeFile(join(GLOBAL_KOBOLD_DIR, "AGENT.md"), agentContent, "utf-8");
|
|
254
|
+
console.log(`✓ AGENT.md created`);
|
|
255
|
+
// MEMORY.md - Long-term memory template
|
|
256
|
+
const memoryContent = `# Long-term Memory
|
|
257
|
+
|
|
258
|
+
## User Profile
|
|
259
|
+
- Name: ${userName || "Developer"}
|
|
260
|
+
- Background: ${userBackground || "Not specified"}
|
|
261
|
+
- Goals: ${userGoals || "Not specified"}
|
|
262
|
+
- Preferences: ${userPreferences || "Not specified"}
|
|
263
|
+
|
|
264
|
+
## Agent Context
|
|
265
|
+
- Name: ${agentName}
|
|
266
|
+
- Purpose: ${agentMission}
|
|
267
|
+
- Model: ${model}
|
|
268
|
+
- Created: ${timestamp}
|
|
269
|
+
|
|
270
|
+
## Conversations
|
|
271
|
+
|
|
272
|
+
### Session: ${timestamp}
|
|
273
|
+
- Context: Initial setup
|
|
274
|
+
- Topics:
|
|
275
|
+
|
|
276
|
+
## Learned Patterns
|
|
277
|
+
|
|
278
|
+
## Known Preferences
|
|
279
|
+
- Preferred model: ${model}
|
|
280
|
+
- Agent personality: ${personalityTrait}
|
|
281
|
+
|
|
282
|
+
## Recent Context
|
|
283
|
+
[Updated with current project state]
|
|
284
|
+
|
|
285
|
+
## Notes
|
|
286
|
+
`;
|
|
287
|
+
await writeFile(join(GLOBAL_KOBOLD_DIR, "MEMORY.md"), memoryContent, "utf-8");
|
|
288
|
+
console.log(`✓ MEMORY.md created`);
|
|
248
289
|
// Write config with personalized model
|
|
249
290
|
const config = {
|
|
250
291
|
...DEFAULT_CONFIG,
|
|
@@ -293,21 +334,32 @@ export const initCommand = new Command("init")
|
|
|
293
334
|
`);
|
|
294
335
|
localDb.close();
|
|
295
336
|
console.log("✓ Workspace DB initialized");
|
|
296
|
-
|
|
337
|
+
// Simple local memory template
|
|
338
|
+
const localMemoryContent = `# Project Memory
|
|
339
|
+
|
|
340
|
+
## Context
|
|
341
|
+
Project-specific context goes here.
|
|
342
|
+
|
|
343
|
+
## Notes
|
|
344
|
+
`;
|
|
345
|
+
await writeFile(join(LOCAL_KOBOLD_DIR, "MEMORY.md"), localMemoryContent, "utf-8");
|
|
297
346
|
}
|
|
298
347
|
console.log("\n🎉 " + agentName + " is ready!");
|
|
299
348
|
console.log("\n📁 Locations:");
|
|
300
349
|
console.log(` Config: ${GLOBAL_CONFIG_PATH}`);
|
|
301
350
|
console.log(` Data: ${GLOBAL_DB_PATH}`);
|
|
302
|
-
console.log(` Persona: ${GLOBAL_KOBOLD_DIR}/
|
|
351
|
+
console.log(` Persona: ${GLOBAL_KOBOLD_DIR}/IDENTITY.md, SOUL.md, USER.md, AGENT.md`);
|
|
303
352
|
console.log(`\n\n🚀 Quick Start:`);
|
|
304
353
|
console.log(` 0xkobold chat # Chat with ${agentName}`);
|
|
305
354
|
console.log(" 0xkobold gateway start # Start web gateway");
|
|
306
355
|
console.log(" 0xkobold daemon # Start background daemon");
|
|
356
|
+
console.log("\n🎭 Manage persona:");
|
|
357
|
+
console.log(" 0xkobold persona list # List persona files");
|
|
358
|
+
console.log(" 0xkobold persona show # View all personas");
|
|
359
|
+
console.log(" 0xkobold persona edit IDENTITY.md # Customize identity");
|
|
307
360
|
console.log("\n🔧 To add API keys for paid models:");
|
|
308
361
|
console.log(" export CLOUD_API_KEY=your_key");
|
|
309
362
|
console.log(" # Or edit ~/.0xkobold/config.json");
|
|
310
|
-
console.log("\n💡 Tip: Add your projects with: 0xkobold projects add /path/to/project");
|
|
311
363
|
}
|
|
312
364
|
catch (error) {
|
|
313
365
|
console.error("❌ Init failed:", error);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"init.js","sourceRoot":"","sources":["../../../../src/cli/commands/init.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"init.js","sourceRoot":"","sources":["../../../../src/cli/commands/init.ts"],"names":[],"mappings":"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"}
|
package/dist/src/cli/program.js
CHANGED
|
@@ -24,6 +24,8 @@ import { createGatewayCommand } from "./commands/gateway.js";
|
|
|
24
24
|
import { createWhatsAppCommand } from "./commands/whatsapp.js";
|
|
25
25
|
// v0.3.0: Telegram
|
|
26
26
|
import { createTelegramCommand } from "./commands/telegram.js";
|
|
27
|
+
// v0.4.0: Cron
|
|
28
|
+
import { cronCommand } from "./commands/cron.js";
|
|
27
29
|
// v0.3.0: Migration
|
|
28
30
|
import { migrateCommand } from "./commands/migrate.js";
|
|
29
31
|
// v0.3.0: Duplicate check
|
|
@@ -59,6 +61,8 @@ export function createCli() {
|
|
|
59
61
|
// v0.3.0: Duplicate detection
|
|
60
62
|
program.addCommand(checkCommand);
|
|
61
63
|
program.addCommand(createEmbeddedCommand());
|
|
64
|
+
// v0.4.0: Cron jobs
|
|
65
|
+
program.addCommand(cronCommand);
|
|
62
66
|
// Extension CLIs
|
|
63
67
|
registerDiscordCli(program);
|
|
64
68
|
registerHeartbeatCli(program);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"program.js","sourceRoot":"","sources":["../../../src/cli/program.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"program.js","sourceRoot":"","sources":["../../../src/cli/program.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Cron Module - 0xKobold
|
|
3
|
+
*
|
|
4
|
+
* Export all cron-related functionality.
|
|
5
|
+
*
|
|
6
|
+
* Example usage:
|
|
7
|
+
* ```typescript
|
|
8
|
+
* import { getCronScheduler, parseExpression } from "./cron/index.js";
|
|
9
|
+
*
|
|
10
|
+
* const scheduler = getCronScheduler();
|
|
11
|
+
* scheduler.start();
|
|
12
|
+
*
|
|
13
|
+
* // Add a daily morning briefing
|
|
14
|
+
* scheduler.addJob({
|
|
15
|
+
* name: "Morning Brief",
|
|
16
|
+
* cron: "0 7 * * *",
|
|
17
|
+
* session: "isolated",
|
|
18
|
+
* message: "Generate today's briefing: weather, calendar, tasks"
|
|
19
|
+
* });
|
|
20
|
+
*
|
|
21
|
+
* // One-shot reminder in 20 minutes
|
|
22
|
+
* scheduler.addJob({
|
|
23
|
+
* name: "Call Reminder",
|
|
24
|
+
* at: "20m",
|
|
25
|
+
* session: "main",
|
|
26
|
+
* wake: true,
|
|
27
|
+
* deleteAfterRun: true,
|
|
28
|
+
* message: "Call the client back"
|
|
29
|
+
* });
|
|
30
|
+
* ```
|
|
31
|
+
*/
|
|
32
|
+
// Parser
|
|
33
|
+
export { parseCron, parseExpression, parseDuration, parseAt, getNextRun, formatCron, validateCron, CRON_PRESETS, } from "./parser.js";
|
|
34
|
+
// Scheduler
|
|
35
|
+
export { CronScheduler, getCronScheduler, resetCronScheduler, } from "./scheduler.js";
|
|
36
|
+
// Runner
|
|
37
|
+
export { runJobRunner, runSystemEvent, validateJob, } from "./runner.js";
|
|
38
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/cron/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AAeH,SAAS;AACT,OAAO,EACL,SAAS,EACT,eAAe,EACf,aAAa,EACb,OAAO,EACP,UAAU,EACV,UAAU,EACV,YAAY,EACZ,YAAY,GACb,MAAM,aAAa,CAAC;AAErB,YAAY;AACZ,OAAO,EACL,aAAa,EACb,gBAAgB,EAChB,kBAAkB,GACnB,MAAM,gBAAgB,CAAC;AAExB,SAAS;AACT,OAAO,EACL,YAAY,EACZ,cAAc,EACd,WAAW,GACZ,MAAM,aAAa,CAAC"}
|
|
@@ -0,0 +1,294 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Cron Expression Parser - 0xKobold
|
|
3
|
+
*
|
|
4
|
+
* Parses standard cron expressions and calculates next run times.
|
|
5
|
+
* Supports: standard cron, L (last), W (weekday), # (nth)
|
|
6
|
+
*/
|
|
7
|
+
// Standard cron ranges
|
|
8
|
+
const RANGES = {
|
|
9
|
+
minute: { min: 0, max: 59 },
|
|
10
|
+
hour: { min: 0, max: 23 },
|
|
11
|
+
dayOfMonth: { min: 1, max: 31 },
|
|
12
|
+
month: { min: 1, max: 12 },
|
|
13
|
+
dayOfWeek: { min: 0, max: 6 }, // 0 = Sunday
|
|
14
|
+
};
|
|
15
|
+
const MONTH_NAMES = {
|
|
16
|
+
jan: 1, feb: 2, mar: 3, apr: 4, may: 5, jun: 6,
|
|
17
|
+
jul: 7, aug: 8, sep: 9, oct: 10, nov: 11, dec: 12,
|
|
18
|
+
};
|
|
19
|
+
const DAY_NAMES = {
|
|
20
|
+
sun: 0, mon: 1, tue: 2, wed: 3, thu: 4, fri: 5, sat: 6,
|
|
21
|
+
};
|
|
22
|
+
/**
|
|
23
|
+
* Parse a cron expression into structured components
|
|
24
|
+
*/
|
|
25
|
+
export function parseCron(expression, timezone = 'UTC') {
|
|
26
|
+
const parts = expression.trim().split(/\s+/);
|
|
27
|
+
if (parts.length !== 5 && parts.length !== 6) {
|
|
28
|
+
throw new Error(`Invalid cron expression "${expression}". Expected 5 fields (min hour day month dow) or 6 fields (with seconds).`);
|
|
29
|
+
}
|
|
30
|
+
// Handle 6-field format (with seconds)
|
|
31
|
+
let [minute, hour, dayOfMonth, month, dayOfWeek] = parts;
|
|
32
|
+
if (parts.length === 6) {
|
|
33
|
+
// Skip seconds, use rest
|
|
34
|
+
[, minute, hour, dayOfMonth, month, dayOfWeek] = parts;
|
|
35
|
+
}
|
|
36
|
+
return {
|
|
37
|
+
minute: parseField(minute, 'minute'),
|
|
38
|
+
hour: parseField(hour, 'hour'),
|
|
39
|
+
dayOfMonth: parseField(dayOfMonth, 'dayOfMonth'),
|
|
40
|
+
month: parseField(month, 'month'),
|
|
41
|
+
dayOfWeek: parseField(dayOfWeek, 'dayOfWeek'),
|
|
42
|
+
timezone,
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Parse a single cron field
|
|
47
|
+
*/
|
|
48
|
+
function parseField(field, type) {
|
|
49
|
+
const range = RANGES[type];
|
|
50
|
+
// Wildcard
|
|
51
|
+
if (field === '*')
|
|
52
|
+
return '*';
|
|
53
|
+
// Step syntax (*/5 = every 5)
|
|
54
|
+
if (field.startsWith('*/')) {
|
|
55
|
+
const step = parseInt(field.slice(2), 10);
|
|
56
|
+
if (isNaN(step) || step <= 0) {
|
|
57
|
+
throw new Error(`Invalid step value in "${field}"`);
|
|
58
|
+
}
|
|
59
|
+
const values = [];
|
|
60
|
+
for (let i = range.min; i <= range.max; i += step) {
|
|
61
|
+
values.push(i);
|
|
62
|
+
}
|
|
63
|
+
return values;
|
|
64
|
+
}
|
|
65
|
+
// Range with step (1-10/2)
|
|
66
|
+
if (field.includes('/')) {
|
|
67
|
+
const [rangePart, stepStr] = field.split('/');
|
|
68
|
+
const step = parseInt(stepStr, 10);
|
|
69
|
+
if (isNaN(step) || step <= 0) {
|
|
70
|
+
throw new Error(`Invalid step in "${field}"`);
|
|
71
|
+
}
|
|
72
|
+
const [start, end] = parseRange(rangePart, type);
|
|
73
|
+
const values = [];
|
|
74
|
+
for (let i = start; i <= end; i += step) {
|
|
75
|
+
values.push(i);
|
|
76
|
+
}
|
|
77
|
+
return values;
|
|
78
|
+
}
|
|
79
|
+
// Simple range (1-5)
|
|
80
|
+
if (field.includes('-')) {
|
|
81
|
+
const [start, end] = parseRange(field, type);
|
|
82
|
+
const values = [];
|
|
83
|
+
for (let i = start; i <= end; i++) {
|
|
84
|
+
values.push(i);
|
|
85
|
+
}
|
|
86
|
+
return values;
|
|
87
|
+
}
|
|
88
|
+
// List (1,2,3 or MON,WED,FRI)
|
|
89
|
+
if (field.includes(',')) {
|
|
90
|
+
const values = [];
|
|
91
|
+
for (const part of field.split(',')) {
|
|
92
|
+
const val = parseValue(part.trim(), type);
|
|
93
|
+
values.push(val);
|
|
94
|
+
}
|
|
95
|
+
return [...new Set(values)].sort((a, b) => a - b);
|
|
96
|
+
}
|
|
97
|
+
// Single value
|
|
98
|
+
return [parseValue(field, type)];
|
|
99
|
+
}
|
|
100
|
+
/**
|
|
101
|
+
* Parse a range like "1-5" or "MON-FRI"
|
|
102
|
+
*/
|
|
103
|
+
function parseRange(rangeStr, type) {
|
|
104
|
+
const [startStr, endStr] = rangeStr.split('-');
|
|
105
|
+
return [
|
|
106
|
+
parseValue(startStr.trim(), type),
|
|
107
|
+
parseValue(endStr.trim(), type),
|
|
108
|
+
];
|
|
109
|
+
}
|
|
110
|
+
/**
|
|
111
|
+
* Parse a single value (number or name)
|
|
112
|
+
*/
|
|
113
|
+
function parseValue(value, type) {
|
|
114
|
+
const lower = value.toLowerCase();
|
|
115
|
+
// Handle month names
|
|
116
|
+
if (type === 'month' && MONTH_NAMES[lower] !== undefined) {
|
|
117
|
+
return MONTH_NAMES[lower];
|
|
118
|
+
}
|
|
119
|
+
// Handle day names
|
|
120
|
+
if (type === 'dayOfWeek' && DAY_NAMES[lower] !== undefined) {
|
|
121
|
+
return DAY_NAMES[lower];
|
|
122
|
+
}
|
|
123
|
+
// Special: L (last day of month)
|
|
124
|
+
if (type === 'dayOfMonth' && lower === 'l') {
|
|
125
|
+
return -1; // Special marker for last day
|
|
126
|
+
}
|
|
127
|
+
const num = parseInt(value, 10);
|
|
128
|
+
const range = RANGES[type];
|
|
129
|
+
if (isNaN(num)) {
|
|
130
|
+
throw new Error(`Invalid value "${value}" for ${type}`);
|
|
131
|
+
}
|
|
132
|
+
if (num < range.min || num > range.max) {
|
|
133
|
+
throw new Error(`Value ${num} out of range [${range.min}-${range.max}] for ${type}`);
|
|
134
|
+
}
|
|
135
|
+
return num;
|
|
136
|
+
}
|
|
137
|
+
/**
|
|
138
|
+
* Calculate the next run time for a cron expression
|
|
139
|
+
*/
|
|
140
|
+
export function getNextRun(expression, from = new Date()) {
|
|
141
|
+
const { minute, hour, dayOfMonth, month, dayOfWeek } = expression;
|
|
142
|
+
// Start from the next minute
|
|
143
|
+
let candidate = new Date(from);
|
|
144
|
+
candidate.setSeconds(0, 0);
|
|
145
|
+
candidate.setMinutes(candidate.getMinutes() + 1);
|
|
146
|
+
// Limit search to prevent infinite loops
|
|
147
|
+
const maxIterations = 366 * 24 * 60; // ~1 year in minutes
|
|
148
|
+
for (let i = 0; i < maxIterations; i++) {
|
|
149
|
+
if (matches(candidate, expression)) {
|
|
150
|
+
return candidate;
|
|
151
|
+
}
|
|
152
|
+
candidate.setMinutes(candidate.getMinutes() + 1);
|
|
153
|
+
}
|
|
154
|
+
throw new Error('Could not find next run time within 1 year');
|
|
155
|
+
}
|
|
156
|
+
/**
|
|
157
|
+
* Check if a date matches the cron expression
|
|
158
|
+
*/
|
|
159
|
+
function matches(date, expression) {
|
|
160
|
+
const { minute, hour, dayOfMonth, month, dayOfWeek } = expression;
|
|
161
|
+
if (!matchesField(date.getMinutes(), minute))
|
|
162
|
+
return false;
|
|
163
|
+
if (!matchesField(date.getHours(), hour))
|
|
164
|
+
return false;
|
|
165
|
+
if (!matchesMonth(date.getMonth() + 1, month))
|
|
166
|
+
return false;
|
|
167
|
+
if (!matchesDayOfMonth(date.getDate(), dayOfMonth, date))
|
|
168
|
+
return false;
|
|
169
|
+
if (!matchesField(date.getDay(), dayOfWeek))
|
|
170
|
+
return false;
|
|
171
|
+
return true;
|
|
172
|
+
}
|
|
173
|
+
function matchesField(value, pattern) {
|
|
174
|
+
if (pattern === '*')
|
|
175
|
+
return true;
|
|
176
|
+
return pattern.includes(value);
|
|
177
|
+
}
|
|
178
|
+
function matchesMonth(value, pattern) {
|
|
179
|
+
if (pattern === '*')
|
|
180
|
+
return true;
|
|
181
|
+
return pattern.includes(value);
|
|
182
|
+
}
|
|
183
|
+
function matchesDayOfMonth(value, pattern, date) {
|
|
184
|
+
if (pattern === '*')
|
|
185
|
+
return true;
|
|
186
|
+
// Handle L (last day of month)
|
|
187
|
+
if (pattern.includes(-1)) {
|
|
188
|
+
const lastDay = new Date(date.getFullYear(), date.getMonth() + 1, 0).getDate();
|
|
189
|
+
if (value === lastDay)
|
|
190
|
+
return true;
|
|
191
|
+
}
|
|
192
|
+
return pattern.includes(value);
|
|
193
|
+
}
|
|
194
|
+
/**
|
|
195
|
+
* Parse duration strings like "20m", "2h", "1h30m", "1d"
|
|
196
|
+
*/
|
|
197
|
+
export function parseDuration(duration) {
|
|
198
|
+
const regex = /^(?:(\d+)d)?\s*(?:(\d+)h)?\s*(?:(\d+)m)?\s*(?:(\d+)s?)?$/i;
|
|
199
|
+
const match = duration.trim().match(regex);
|
|
200
|
+
if (!match) {
|
|
201
|
+
throw new Error(`Invalid duration "${duration}". Use format: 1d, 2h, 30m, 1h30m`);
|
|
202
|
+
}
|
|
203
|
+
const days = parseInt(match[1] || '0', 10);
|
|
204
|
+
const hours = parseInt(match[2] || '0', 10);
|
|
205
|
+
const minutes = parseInt(match[3] || '0', 10);
|
|
206
|
+
const seconds = parseInt(match[4] || '0', 10);
|
|
207
|
+
const milliseconds = days * 24 * 60 * 60 * 1000 +
|
|
208
|
+
hours * 60 * 60 * 1000 +
|
|
209
|
+
minutes * 60 * 1000 +
|
|
210
|
+
seconds * 1000;
|
|
211
|
+
return {
|
|
212
|
+
milliseconds,
|
|
213
|
+
hours: days * 24 + hours,
|
|
214
|
+
minutes,
|
|
215
|
+
seconds,
|
|
216
|
+
};
|
|
217
|
+
}
|
|
218
|
+
/**
|
|
219
|
+
* Parse absolute time like "2025-01-10T09:00:00" or ISO string
|
|
220
|
+
*/
|
|
221
|
+
export function parseAt(at) {
|
|
222
|
+
// Try parsing as ISO date
|
|
223
|
+
const date = new Date(at);
|
|
224
|
+
if (!isNaN(date.getTime())) {
|
|
225
|
+
return date.getTime();
|
|
226
|
+
}
|
|
227
|
+
// Try parsing relative (e.g., "20m" shorthand for duration)
|
|
228
|
+
try {
|
|
229
|
+
const duration = parseDuration(at);
|
|
230
|
+
return Date.now() + duration.milliseconds;
|
|
231
|
+
}
|
|
232
|
+
catch {
|
|
233
|
+
// Not a valid duration either
|
|
234
|
+
}
|
|
235
|
+
throw new Error(`Invalid time "${at}". Use ISO date (2025-01-10T09:00:00) or duration (20m)`);
|
|
236
|
+
}
|
|
237
|
+
/**
|
|
238
|
+
* Format a cron expression in human-readable form
|
|
239
|
+
*/
|
|
240
|
+
export function formatCron(expression) {
|
|
241
|
+
const parts = [];
|
|
242
|
+
if (expression.minute !== '*') {
|
|
243
|
+
parts.push(`minute(s): ${Array.isArray(expression.minute) ? expression.minute.join(', ') : expression.minute}`);
|
|
244
|
+
}
|
|
245
|
+
if (expression.hour !== '*') {
|
|
246
|
+
parts.push(`hour(s): ${Array.isArray(expression.hour) ? expression.hour.join(', ') : expression.hour}`);
|
|
247
|
+
}
|
|
248
|
+
if (expression.dayOfMonth !== '*') {
|
|
249
|
+
parts.push(`day(s): ${Array.isArray(expression.dayOfMonth) ? expression.dayOfMonth.join(', ') : expression.dayOfMonth}`);
|
|
250
|
+
}
|
|
251
|
+
if (expression.month !== '*') {
|
|
252
|
+
parts.push(`month(s): ${Array.isArray(expression.month) ? expression.month.join(', ') : expression.month}`);
|
|
253
|
+
}
|
|
254
|
+
if (expression.dayOfWeek !== '*') {
|
|
255
|
+
parts.push(`weekday(s): ${Array.isArray(expression.dayOfWeek) ? expression.dayOfWeek.join(', ') : expression.dayOfWeek}`);
|
|
256
|
+
}
|
|
257
|
+
return parts.length > 0 ? parts.join(', ') : 'every minute';
|
|
258
|
+
}
|
|
259
|
+
/**
|
|
260
|
+
* Validate a cron expression
|
|
261
|
+
*/
|
|
262
|
+
export function validateCron(expression) {
|
|
263
|
+
try {
|
|
264
|
+
parseCron(expression);
|
|
265
|
+
return { valid: true };
|
|
266
|
+
}
|
|
267
|
+
catch (error) {
|
|
268
|
+
return { valid: false, error: error.message };
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
/**
|
|
272
|
+
* Common cron presets
|
|
273
|
+
*/
|
|
274
|
+
export const CRON_PRESETS = {
|
|
275
|
+
'@yearly': '0 0 1 1 *',
|
|
276
|
+
'@annually': '0 0 1 1 *',
|
|
277
|
+
'@monthly': '0 0 1 * *',
|
|
278
|
+
'@weekly': '0 0 * * 0',
|
|
279
|
+
'@daily': '0 0 * * *',
|
|
280
|
+
'@midnight': '0 0 * * *',
|
|
281
|
+
'@hourly': '0 * * * *',
|
|
282
|
+
};
|
|
283
|
+
/**
|
|
284
|
+
* Parse preset or standard expression
|
|
285
|
+
*/
|
|
286
|
+
export function parseExpression(expression, timezone) {
|
|
287
|
+
const normalized = expression.trim();
|
|
288
|
+
// Check for presets
|
|
289
|
+
if (normalized in CRON_PRESETS) {
|
|
290
|
+
return parseCron(CRON_PRESETS[normalized], timezone);
|
|
291
|
+
}
|
|
292
|
+
return parseCron(normalized, timezone);
|
|
293
|
+
}
|
|
294
|
+
//# sourceMappingURL=parser.js.map
|