obol-ai 0.2.31 → 0.2.32
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/CHANGELOG.md +3 -0
- package/package.json +1 -1
- package/src/claude/prompt.js +3 -2
- package/src/claude/tools/scheduler.js +11 -3
- package/src/scheduler.js +2 -2
package/CHANGELOG.md
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "obol-ai",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.32",
|
|
4
4
|
"description": "Self-evolving AI assistant that learns, remembers, and acts on its own. Persistent vector memory, self-rewriting personality, proactive heartbeats.",
|
|
5
5
|
"main": "src/index.js",
|
|
6
6
|
"bin": {
|
package/src/claude/prompt.js
CHANGED
|
@@ -161,11 +161,12 @@ Returns the tapped button label, or \`"timeout"\` if the user doesn't respond wi
|
|
|
161
161
|
|
|
162
162
|
### Scheduling (\`schedule_event\`, \`list_events\`, \`cancel_event\`)
|
|
163
163
|
Schedule one-time or recurring reminders. The user gets a Telegram message each time an event fires.
|
|
164
|
-
- \`schedule_event\` — schedule a reminder with title, due_at (ISO 8601), timezone (IANA), optional description
|
|
164
|
+
- \`schedule_event\` — schedule a reminder with title, due_at (ISO 8601), timezone (IANA), optional description
|
|
165
165
|
- \`list_events\` — list pending/sent/cancelled/completed events
|
|
166
166
|
- \`cancel_event\` — cancel a scheduled event by ID
|
|
167
167
|
|
|
168
|
-
|
|
168
|
+
**Recurring events:** use \`cron_expr\` (5-field cron). The system auto-reschedules after each fire — never chain one-time events manually.
|
|
169
|
+
Examples: \`*/30 * * * *\` (every 30 min), \`0 9 * * 1-5\` (weekdays 9am), \`0 8 * * 1\` (Mondays 8am), \`0 0 1 * *\` (1st of month).
|
|
169
170
|
|
|
170
171
|
When scheduling: always search memory first for the user's timezone/location. If no timezone found, ask the user or default to UTC. Parse natural language dates relative to the user's timezone.
|
|
171
172
|
|
|
@@ -3,7 +3,15 @@ const { toUTC } = require('../utils');
|
|
|
3
3
|
const definitions = [
|
|
4
4
|
{
|
|
5
5
|
name: 'schedule_event',
|
|
6
|
-
description:
|
|
6
|
+
description: `Schedule a one-time or recurring reminder/event. The user will receive a Telegram message each time it fires.
|
|
7
|
+
|
|
8
|
+
For RECURRING events (e.g. "every 30 minutes", "daily at 9am", "every Monday"):
|
|
9
|
+
- ALWAYS use cron_expr — do NOT schedule one-time events and chain them manually
|
|
10
|
+
- cron_expr is a standard 5-field cron: minute hour day-of-month month day-of-week
|
|
11
|
+
- Examples: "*/30 * * * *" (every 30 min), "0 9 * * 1-5" (weekdays 9am), "0 8 * * 1" (Mondays 8am)
|
|
12
|
+
- The system will auto-reschedule after each fire — no need to re-schedule manually
|
|
13
|
+
|
|
14
|
+
Always search memory first for the user's timezone/location.`,
|
|
7
15
|
input_schema: {
|
|
8
16
|
type: 'object',
|
|
9
17
|
properties: {
|
|
@@ -11,7 +19,7 @@ const definitions = [
|
|
|
11
19
|
due_at: { type: 'string', description: 'ISO 8601 datetime for the first fire time (e.g. 2026-02-25T15:00:00)' },
|
|
12
20
|
timezone: { type: 'string', description: 'IANA timezone (e.g. Europe/Brussels, America/New_York). Default: UTC' },
|
|
13
21
|
description: { type: 'string', description: 'Context or details about the event' },
|
|
14
|
-
cron_expr: { type: 'string', description: 'Cron expression for recurring events (5-field
|
|
22
|
+
cron_expr: { type: 'string', description: 'Cron expression for recurring events (5-field). REQUIRED for any repeating schedule — do not omit and chain one-time events instead.' },
|
|
15
23
|
max_runs: { type: 'number', description: 'Maximum number of times to fire (omit for unlimited)' },
|
|
16
24
|
ends_at: { type: 'string', description: 'ISO 8601 datetime after which the recurring event stops' },
|
|
17
25
|
},
|
|
@@ -51,7 +59,7 @@ const handlers = {
|
|
|
51
59
|
if (input.cron_expr) {
|
|
52
60
|
try {
|
|
53
61
|
const { parseExpression } = require('cron-parser');
|
|
54
|
-
parseExpression(input.cron_expr, { tz });
|
|
62
|
+
parseExpression(input.cron_expr, { timezone: tz });
|
|
55
63
|
} catch (e) {
|
|
56
64
|
return `Invalid cron expression "${input.cron_expr}": ${e.message}`;
|
|
57
65
|
}
|
package/src/scheduler.js
CHANGED
|
@@ -36,7 +36,7 @@ function createScheduler(supabaseConfig, userId = 0) {
|
|
|
36
36
|
async function list(opts = {}) {
|
|
37
37
|
const status = opts.status || 'pending';
|
|
38
38
|
const limit = opts.limit || 20;
|
|
39
|
-
|
|
39
|
+
const fetchUrl = `${url}/rest/v1/obol_events?user_id=eq.${userId}&status=eq.${status}&order=due_at.asc&limit=${limit}&select=id,title,description,due_at,timezone,status,created_at,cron_expr,last_run_at,run_count,max_runs,ends_at`;
|
|
40
40
|
const res = await fetch(fetchUrl, { headers });
|
|
41
41
|
const data = await res.json();
|
|
42
42
|
if (!res.ok) throw new Error(JSON.stringify(data));
|
|
@@ -87,7 +87,7 @@ function createScheduler(supabaseConfig, userId = 0) {
|
|
|
87
87
|
}
|
|
88
88
|
|
|
89
89
|
try {
|
|
90
|
-
const nextDate = parseExpression(cronExpr, { currentDate: new Date(),
|
|
90
|
+
const nextDate = parseExpression(cronExpr, { currentDate: new Date(), timezone: timezone || 'UTC' }).next().toDate();
|
|
91
91
|
|
|
92
92
|
if (endsAt && nextDate > new Date(endsAt)) {
|
|
93
93
|
return patch(eventId, { status: 'completed', run_count: newRunCount, last_run_at: new Date().toISOString() });
|