ofiere-openclaw-plugin 3.2.0 → 3.3.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 (2) hide show
  1. package/package.json +1 -1
  2. package/src/tools.ts +51 -8
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ofiere-openclaw-plugin",
3
- "version": "3.2.0",
3
+ "version": "3.3.0",
4
4
  "type": "module",
5
5
  "description": "OpenClaw plugin for Ofiere PM — 9 meta-tools covering tasks, agents, projects, scheduling, knowledge, workflows, notifications, memory, and prompts",
6
6
  "keywords": ["openclaw", "ofiere", "project-management", "agents", "plugin"],
package/src/tools.ts CHANGED
@@ -430,11 +430,54 @@ async function handleCreateTask(
430
430
  const effectiveAgentId = (insertData.agent_id as string) || assignee;
431
431
  if (startDate && effectiveAgentId) {
432
432
  try {
433
- const scheduledTime = (params.scheduled_time as string) || "09:00"; // default 9am
434
- const datePart = startDate; // YYYY-MM-DD
435
- const timePart = scheduledTime; // HH:MM
436
- const dt = new Date(`${datePart}T${timePart}:00`);
437
- const nextRunAt = Math.floor(dt.getTime() / 1000);
433
+ // Parse start_date robustly it can be:
434
+ // "2026-04-19" (date only)
435
+ // "2026-04-19T18:45:00" (local datetime)
436
+ // "2026-04-19 11:45:00+00" (Supabase timestamptz)
437
+ // "2026-04-19T11:45:00.000Z" (ISO UTC)
438
+ const parsedDate = new Date(startDate);
439
+ const explicitScheduledTime = params.scheduled_time as string | undefined;
440
+
441
+ let nextRunAtEpoch: number;
442
+ let scheduledTimeFinal: string;
443
+ let scheduledDateFinal: string;
444
+
445
+ if (!isNaN(parsedDate.getTime())) {
446
+ // Valid date — check if it includes a meaningful time component
447
+ const hasTimeInfo = /[T ]\d{2}:\d{2}/.test(startDate);
448
+
449
+ if (explicitScheduledTime) {
450
+ // Agent explicitly passed a scheduled_time — use date from start_date + explicit time
451
+ const dateStr = parsedDate.toISOString().split("T")[0]; // YYYY-MM-DD
452
+ const dt = new Date(`${dateStr}T${explicitScheduledTime}:00Z`);
453
+ nextRunAtEpoch = Math.floor(dt.getTime() / 1000);
454
+ scheduledTimeFinal = explicitScheduledTime;
455
+ scheduledDateFinal = dateStr;
456
+ } else if (hasTimeInfo) {
457
+ // start_date already contains time — use it directly
458
+ nextRunAtEpoch = Math.floor(parsedDate.getTime() / 1000);
459
+ scheduledTimeFinal = `${String(parsedDate.getUTCHours()).padStart(2, "0")}:${String(parsedDate.getUTCMinutes()).padStart(2, "0")}`;
460
+ scheduledDateFinal = parsedDate.toISOString().split("T")[0];
461
+ } else {
462
+ // Date only, no time — default to 09:00 UTC
463
+ const dateStr = parsedDate.toISOString().split("T")[0];
464
+ const dt = new Date(`${dateStr}T09:00:00Z`);
465
+ nextRunAtEpoch = Math.floor(dt.getTime() / 1000);
466
+ scheduledTimeFinal = "09:00";
467
+ scheduledDateFinal = dateStr;
468
+ }
469
+ } else {
470
+ // Unparseable date — fallback to now + 60s
471
+ nextRunAtEpoch = Math.floor(Date.now() / 1000) + 60;
472
+ scheduledTimeFinal = "00:00";
473
+ scheduledDateFinal = new Date().toISOString().split("T")[0];
474
+ }
475
+
476
+ // Safety net: if computed time is in the past, schedule for now + 60s
477
+ const nowEpoch = Math.floor(Date.now() / 1000);
478
+ if (nextRunAtEpoch <= nowEpoch) {
479
+ nextRunAtEpoch = nowEpoch + 60;
480
+ }
438
481
 
439
482
  await supabase.from("scheduler_events").insert({
440
483
  id: crypto.randomUUID(),
@@ -443,13 +486,13 @@ async function handleCreateTask(
443
486
  agent_id: effectiveAgentId,
444
487
  title: params.title,
445
488
  description: (params.description as string) || (params.instructions as string) || null,
446
- scheduled_date: datePart,
447
- scheduled_time: timePart,
489
+ scheduled_date: scheduledDateFinal,
490
+ scheduled_time: scheduledTimeFinal,
448
491
  duration_minutes: 30,
449
492
  recurrence_type: "none",
450
493
  recurrence_interval: 1,
451
494
  status: "scheduled",
452
- next_run_at: nextRunAt,
495
+ next_run_at: nextRunAtEpoch,
453
496
  run_count: 0,
454
497
  priority: params.priority !== undefined ? params.priority : 1,
455
498
  });