ofiere-openclaw-plugin 4.56.6 → 4.56.8

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/dist/src/tools.js CHANGED
@@ -849,7 +849,8 @@ async function handleCreateTask(supabase, userId, resolveAgent, params, fallback
849
849
  const effectiveAgentId = insertData.agent_id || assignee;
850
850
  if (startDate && effectiveAgentId && normalized) {
851
851
  try {
852
- let { nextRunAtEpoch } = normalized;
852
+ const originalEpoch = normalized.nextRunAtEpoch;
853
+ let nextRunAtEpoch = originalEpoch;
853
854
  const nowEpoch = Math.floor(Date.now() / 1000);
854
855
  // Safety net: if computed time is in the past, schedule for now + 60s
855
856
  // Fix #2 (2026-05-17): jitter past-time bump 0..5min so bulk creates
@@ -886,6 +887,21 @@ async function handleCreateTask(supabase, userId, resolveAgent, params, fallback
886
887
  nextRunAtEpoch += recent * perSlotSecs;
887
888
  }
888
889
  }
890
+ // Fix #3 cosmetic parity (2026-05-17): when either Fix #2 jitter or
891
+ // Fix #3 stagger mutated nextRunAtEpoch, recompute the local-clock
892
+ // display fields so the dashboard UI doesn't show the ORIGINAL T0 for
893
+ // an event that actually fires minutes later. Dispatch uses
894
+ // next_run_at, but users read scheduled_date+scheduled_time.
895
+ let scheduledDateLocalFinal = normalized.scheduledDateLocal;
896
+ let scheduledTimeLocalFinal = normalized.scheduledTimeLocal;
897
+ if (nextRunAtEpoch !== originalEpoch) {
898
+ const offsetMin = Math.round(TZ_OFFSET_HOURS * 60);
899
+ const localMs = nextRunAtEpoch * 1000 + offsetMin * 60 * 1000;
900
+ const localD = new Date(localMs);
901
+ const padN = (n) => String(n).padStart(2, "0");
902
+ scheduledDateLocalFinal = `${localD.getUTCFullYear()}-${padN(localD.getUTCMonth() + 1)}-${padN(localD.getUTCDate())}`;
903
+ scheduledTimeLocalFinal = `${padN(localD.getUTCHours())}:${padN(localD.getUTCMinutes())}`;
904
+ }
889
905
  await supabase.from("scheduler_events").insert({
890
906
  id: crypto.randomUUID(),
891
907
  user_id: userId,
@@ -894,8 +910,8 @@ async function handleCreateTask(supabase, userId, resolveAgent, params, fallback
894
910
  subagent_id: subagentId,
895
911
  title: params.title,
896
912
  description: params.description || params.instructions || null,
897
- scheduled_date: normalized.scheduledDateLocal,
898
- scheduled_time: normalized.scheduledTimeLocal,
913
+ scheduled_date: scheduledDateLocalFinal,
914
+ scheduled_time: scheduledTimeLocalFinal,
899
915
  duration_minutes: 30,
900
916
  recurrence_type: params.recurrence_type || "none",
901
917
  recurrence_interval: params.recurrence_interval || 1,
@@ -1127,7 +1143,7 @@ async function handleDeleteTask(supabase, userId, params) {
1127
1143
  if (!params.task_id)
1128
1144
  return err("Missing required field: task_id");
1129
1145
  const taskId = params.task_id;
1130
- await supabase.from("scheduler_events").delete().eq("task_id", taskId);
1146
+ await supabase.from("scheduler_events").delete().eq("task_id", taskId).eq("user_id", userId);
1131
1147
  const { data: subtasks } = await supabase
1132
1148
  .from("tasks")
1133
1149
  .select("id")
@@ -1135,7 +1151,7 @@ async function handleDeleteTask(supabase, userId, params) {
1135
1151
  .eq("user_id", userId);
1136
1152
  if (subtasks && subtasks.length > 0) {
1137
1153
  for (const sub of subtasks) {
1138
- await supabase.from("scheduler_events").delete().eq("task_id", sub.id);
1154
+ await supabase.from("scheduler_events").delete().eq("task_id", sub.id).eq("user_id", userId);
1139
1155
  }
1140
1156
  await supabase
1141
1157
  .from("tasks")
@@ -1822,7 +1838,7 @@ function registerScheduleOps(api, supabase, userId) {
1822
1838
  if (upd.status === "completed" || upd.status === "cancelled") {
1823
1839
  upd.next_run_at = null;
1824
1840
  }
1825
- const { error } = await supabase.from("scheduler_events").update(upd).eq("id", params.id);
1841
+ const { error } = await supabase.from("scheduler_events").update(upd).eq("id", params.id).eq("user_id", userId);
1826
1842
  if (error)
1827
1843
  return err(error.message);
1828
1844
  return ok({ message: "Event updated", ok: true });
@@ -1830,7 +1846,7 @@ function registerScheduleOps(api, supabase, userId) {
1830
1846
  case "delete": {
1831
1847
  if (!params.id)
1832
1848
  return err("Missing required: id");
1833
- const { error } = await supabase.from("scheduler_events").delete().eq("id", params.id);
1849
+ const { error } = await supabase.from("scheduler_events").delete().eq("id", params.id).eq("user_id", userId);
1834
1850
  if (error)
1835
1851
  return err(error.message);
1836
1852
  return ok({ message: "Event deleted", ok: true });
@@ -1944,7 +1960,7 @@ function registerKnowledgeOps(api, supabase, userId) {
1944
1960
  upd[k] = params[k];
1945
1961
  if (Object.keys(upd).length === 0)
1946
1962
  return err("No valid fields to update");
1947
- const { error } = await supabase.from("knowledge_documents").update(upd).eq("id", params.id);
1963
+ const { error } = await supabase.from("knowledge_documents").update(upd).eq("id", params.id).eq("user_id", userId);
1948
1964
  if (error)
1949
1965
  return err(error.message);
1950
1966
  return ok({ message: "Document updated", ok: true });
@@ -1952,7 +1968,7 @@ function registerKnowledgeOps(api, supabase, userId) {
1952
1968
  case "delete": {
1953
1969
  if (!params.id)
1954
1970
  return err("Missing required: id");
1955
- const { error } = await supabase.from("knowledge_documents").delete().eq("id", params.id);
1971
+ const { error } = await supabase.from("knowledge_documents").delete().eq("id", params.id).eq("user_id", userId);
1956
1972
  if (error)
1957
1973
  return err(error.message);
1958
1974
  return ok({ message: "Document deleted", ok: true });
@@ -2654,13 +2670,13 @@ function registerNotifyOps(api, supabase, userId, resolveAgent) {
2654
2670
  case "mark_read": {
2655
2671
  if (!params.id)
2656
2672
  return err("Missing required: id");
2657
- const { error } = await supabase.from("notifications").update({ read: true }).eq("id", params.id);
2673
+ const { error } = await supabase.from("notifications").update({ read: true }).eq("id", params.id).eq("user_id", userId);
2658
2674
  if (error)
2659
2675
  return err(error.message);
2660
2676
  return ok({ message: "Notification marked as read", ok: true });
2661
2677
  }
2662
2678
  case "mark_all_read": {
2663
- const { error } = await supabase.from("notifications").update({ read: true }).eq("read", false);
2679
+ const { error } = await supabase.from("notifications").update({ read: true }).eq("read", false).eq("user_id", userId);
2664
2680
  if (error)
2665
2681
  return err(error.message);
2666
2682
  return ok({ message: "All notifications marked as read", ok: true });
@@ -2668,7 +2684,7 @@ function registerNotifyOps(api, supabase, userId, resolveAgent) {
2668
2684
  case "delete": {
2669
2685
  if (!params.id)
2670
2686
  return err("Missing required: id");
2671
- const { error } = await supabase.from("notifications").delete().eq("id", params.id);
2687
+ const { error } = await supabase.from("notifications").delete().eq("id", params.id).eq("user_id", userId);
2672
2688
  if (error)
2673
2689
  return err(error.message);
2674
2690
  return ok({ message: "Notification deleted", ok: true });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ofiere-openclaw-plugin",
3
- "version": "4.56.6",
3
+ "version": "4.56.8",
4
4
  "type": "module",
5
5
  "description": "OpenClaw plugin for Ofiere PM - 18 meta-tools covering tasks, agents, projects, scheduling, knowledge, workflows, notifications, memory, prompts, constellation, space file management, execution plan builder, SOP management, agent brain, talent management, corporate frameworks, agent office canvas, and PM gate approvals",
6
6
  "keywords": [
package/src/tools.ts CHANGED
@@ -946,7 +946,8 @@ async function handleCreateTask(
946
946
  const effectiveAgentId = (insertData.agent_id as string) || assignee;
947
947
  if (startDate && effectiveAgentId && normalized) {
948
948
  try {
949
- let { nextRunAtEpoch } = normalized;
949
+ const originalEpoch = normalized.nextRunAtEpoch;
950
+ let nextRunAtEpoch = originalEpoch;
950
951
  const nowEpoch = Math.floor(Date.now() / 1000);
951
952
  // Safety net: if computed time is in the past, schedule for now + 60s
952
953
  // Fix #2 (2026-05-17): jitter past-time bump 0..5min so bulk creates
@@ -985,6 +986,22 @@ async function handleCreateTask(
985
986
  }
986
987
  }
987
988
 
989
+ // Fix #3 cosmetic parity (2026-05-17): when either Fix #2 jitter or
990
+ // Fix #3 stagger mutated nextRunAtEpoch, recompute the local-clock
991
+ // display fields so the dashboard UI doesn't show the ORIGINAL T0 for
992
+ // an event that actually fires minutes later. Dispatch uses
993
+ // next_run_at, but users read scheduled_date+scheduled_time.
994
+ let scheduledDateLocalFinal = normalized.scheduledDateLocal;
995
+ let scheduledTimeLocalFinal = normalized.scheduledTimeLocal;
996
+ if (nextRunAtEpoch !== originalEpoch) {
997
+ const offsetMin = Math.round(TZ_OFFSET_HOURS * 60);
998
+ const localMs = nextRunAtEpoch * 1000 + offsetMin * 60 * 1000;
999
+ const localD = new Date(localMs);
1000
+ const padN = (n: number) => String(n).padStart(2, "0");
1001
+ scheduledDateLocalFinal = `${localD.getUTCFullYear()}-${padN(localD.getUTCMonth() + 1)}-${padN(localD.getUTCDate())}`;
1002
+ scheduledTimeLocalFinal = `${padN(localD.getUTCHours())}:${padN(localD.getUTCMinutes())}`;
1003
+ }
1004
+
988
1005
  await supabase.from("scheduler_events").insert({
989
1006
  id: crypto.randomUUID(),
990
1007
  user_id: userId,
@@ -993,8 +1010,8 @@ async function handleCreateTask(
993
1010
  subagent_id: subagentId,
994
1011
  title: params.title,
995
1012
  description: (params.description as string) || (params.instructions as string) || null,
996
- scheduled_date: normalized.scheduledDateLocal,
997
- scheduled_time: normalized.scheduledTimeLocal,
1013
+ scheduled_date: scheduledDateLocalFinal,
1014
+ scheduled_time: scheduledTimeLocalFinal,
998
1015
  duration_minutes: 30,
999
1016
  recurrence_type: (params.recurrence_type as string) || "none",
1000
1017
  recurrence_interval: (params.recurrence_interval as number) || 1,
@@ -1247,7 +1264,7 @@ async function handleDeleteTask(
1247
1264
  if (!params.task_id) return err("Missing required field: task_id");
1248
1265
  const taskId = params.task_id as string;
1249
1266
 
1250
- await supabase.from("scheduler_events").delete().eq("task_id", taskId);
1267
+ await supabase.from("scheduler_events").delete().eq("task_id", taskId).eq("user_id", userId);
1251
1268
 
1252
1269
  const { data: subtasks } = await supabase
1253
1270
  .from("tasks")
@@ -1257,7 +1274,7 @@ async function handleDeleteTask(
1257
1274
 
1258
1275
  if (subtasks && subtasks.length > 0) {
1259
1276
  for (const sub of subtasks) {
1260
- await supabase.from("scheduler_events").delete().eq("task_id", sub.id);
1277
+ await supabase.from("scheduler_events").delete().eq("task_id", sub.id).eq("user_id", userId);
1261
1278
  }
1262
1279
  await supabase
1263
1280
  .from("tasks")
@@ -1973,13 +1990,13 @@ function registerScheduleOps(
1973
1990
  if (upd.status === "completed" || upd.status === "cancelled") {
1974
1991
  upd.next_run_at = null;
1975
1992
  }
1976
- const { error } = await supabase.from("scheduler_events").update(upd).eq("id", params.id);
1993
+ const { error } = await supabase.from("scheduler_events").update(upd).eq("id", params.id).eq("user_id", userId);
1977
1994
  if (error) return err(error.message);
1978
1995
  return ok({ message: "Event updated", ok: true });
1979
1996
  }
1980
1997
  case "delete": {
1981
1998
  if (!params.id) return err("Missing required: id");
1982
- const { error } = await supabase.from("scheduler_events").delete().eq("id", params.id);
1999
+ const { error } = await supabase.from("scheduler_events").delete().eq("id", params.id).eq("user_id", userId);
1983
2000
  if (error) return err(error.message);
1984
2001
  return ok({ message: "Event deleted", ok: true });
1985
2002
  }
@@ -2090,13 +2107,13 @@ function registerKnowledgeOps(
2090
2107
  const upd: Record<string, any> = {};
2091
2108
  for (const k of allowed) if ((params as any)[k] !== undefined) upd[k] = (params as any)[k];
2092
2109
  if (Object.keys(upd).length === 0) return err("No valid fields to update");
2093
- const { error } = await supabase.from("knowledge_documents").update(upd).eq("id", params.id);
2110
+ const { error } = await supabase.from("knowledge_documents").update(upd).eq("id", params.id).eq("user_id", userId);
2094
2111
  if (error) return err(error.message);
2095
2112
  return ok({ message: "Document updated", ok: true });
2096
2113
  }
2097
2114
  case "delete": {
2098
2115
  if (!params.id) return err("Missing required: id");
2099
- const { error } = await supabase.from("knowledge_documents").delete().eq("id", params.id);
2116
+ const { error } = await supabase.from("knowledge_documents").delete().eq("id", params.id).eq("user_id", userId);
2100
2117
  if (error) return err(error.message);
2101
2118
  return ok({ message: "Document deleted", ok: true });
2102
2119
  }
@@ -2823,18 +2840,18 @@ function registerNotifyOps(
2823
2840
  }
2824
2841
  case "mark_read": {
2825
2842
  if (!params.id) return err("Missing required: id");
2826
- const { error } = await supabase.from("notifications").update({ read: true }).eq("id", params.id);
2843
+ const { error } = await supabase.from("notifications").update({ read: true }).eq("id", params.id).eq("user_id", userId);
2827
2844
  if (error) return err(error.message);
2828
2845
  return ok({ message: "Notification marked as read", ok: true });
2829
2846
  }
2830
2847
  case "mark_all_read": {
2831
- const { error } = await supabase.from("notifications").update({ read: true }).eq("read", false);
2848
+ const { error } = await supabase.from("notifications").update({ read: true }).eq("read", false).eq("user_id", userId);
2832
2849
  if (error) return err(error.message);
2833
2850
  return ok({ message: "All notifications marked as read", ok: true });
2834
2851
  }
2835
2852
  case "delete": {
2836
2853
  if (!params.id) return err("Missing required: id");
2837
- const { error } = await supabase.from("notifications").delete().eq("id", params.id);
2854
+ const { error } = await supabase.from("notifications").delete().eq("id", params.id).eq("user_id", userId);
2838
2855
  if (error) return err(error.message);
2839
2856
  return ok({ message: "Notification deleted", ok: true });
2840
2857
  }