ofiere-openclaw-plugin 4.7.0 → 4.8.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/package.json +1 -1
- package/src/tools.ts +58 -16
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "ofiere-openclaw-plugin",
|
|
3
|
-
"version": "4.
|
|
3
|
+
"version": "4.8.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "OpenClaw plugin for Ofiere PM - 10 meta-tools with 13-action workflow mastery covering tasks, agents, projects, scheduling, knowledge, workflows, notifications, memory, prompts, and constellation agent architecture",
|
|
6
6
|
"keywords": ["openclaw", "ofiere", "project-management", "agents", "plugin"],
|
package/src/tools.ts
CHANGED
|
@@ -190,7 +190,8 @@ function registerTaskOps(
|
|
|
190
190
|
description:
|
|
191
191
|
`Manage tasks in the Ofiere PM dashboard. All task operations go through this tool.\n\n` +
|
|
192
192
|
`Actions:\n` +
|
|
193
|
-
`- "list": List/filter tasks. Optional: status, agent_id, space_id, folder_id, limit\n` +
|
|
193
|
+
`- "list": List/filter tasks. Optional: status, agent_id, space_id, folder_id, task_id, limit\n` +
|
|
194
|
+
`- "get": Get a single task by ID. Required: task_id\n` +
|
|
194
195
|
`- "create": Create a task. Required: title. Optional: agent_id, description, status, priority, space_id, folder_id, start_date, due_date, tags, instructions, execution_plan, goals, constraints, system_prompt, recurrence_type, recurrence_interval, scheduled_time\n` +
|
|
195
196
|
`- "update": Update a task. Required: task_id. Optional: all create fields + progress\n` +
|
|
196
197
|
`- "delete": Delete task + subtasks. Required: task_id\n\n` +
|
|
@@ -212,6 +213,10 @@ function registerTaskOps(
|
|
|
212
213
|
title: { type: "string", description: "Task title (required for create)" },
|
|
213
214
|
description: { type: "string", description: "Task description" },
|
|
214
215
|
instructions: { type: "string", description: "Detailed instructions for the agent executing this task" },
|
|
216
|
+
task_id: {
|
|
217
|
+
type: "string",
|
|
218
|
+
description: "Task ID — use with 'list' to filter or 'get' to fetch a single task",
|
|
219
|
+
},
|
|
215
220
|
agent_id: {
|
|
216
221
|
type: "string",
|
|
217
222
|
description: "Agent name or ID. Your name to self-assign, 'none' for unassigned.",
|
|
@@ -284,6 +289,9 @@ function registerTaskOps(
|
|
|
284
289
|
switch (action) {
|
|
285
290
|
case "list":
|
|
286
291
|
return handleListTasks(supabase, userId, params);
|
|
292
|
+
case "get":
|
|
293
|
+
if (!params.task_id) return err("Missing required field: task_id");
|
|
294
|
+
return handleListTasks(supabase, userId, { ...params, limit: 1 });
|
|
287
295
|
case "create":
|
|
288
296
|
return handleCreateTask(supabase, userId, resolveAgent, params);
|
|
289
297
|
case "update":
|
|
@@ -292,7 +300,7 @@ function registerTaskOps(
|
|
|
292
300
|
return handleDeleteTask(supabase, userId, params);
|
|
293
301
|
default:
|
|
294
302
|
return err(
|
|
295
|
-
`Unknown action "${action}". Valid actions: list, create, update, delete`,
|
|
303
|
+
`Unknown action "${action}". Valid actions: list, get, create, update, delete`,
|
|
296
304
|
);
|
|
297
305
|
}
|
|
298
306
|
},
|
|
@@ -316,6 +324,7 @@ async function handleListTasks(
|
|
|
316
324
|
.eq("user_id", userId)
|
|
317
325
|
.order("updated_at", { ascending: false });
|
|
318
326
|
|
|
327
|
+
if (params.task_id) query = query.eq("id", params.task_id as string);
|
|
319
328
|
if (params.space_id) query = query.eq("space_id", params.space_id as string);
|
|
320
329
|
if (params.folder_id) query = query.eq("folder_id", params.folder_id as string);
|
|
321
330
|
if (params.agent_id) query = query.eq("agent_id", params.agent_id as string);
|
|
@@ -600,33 +609,45 @@ async function handleUpdateTask(
|
|
|
600
609
|
const mergedCf = { ...existingCf };
|
|
601
610
|
|
|
602
611
|
if (params.execution_plan !== undefined) {
|
|
603
|
-
|
|
612
|
+
const existingSteps = (existingCf.execution_plan || []) as any[];
|
|
613
|
+
const newSteps = Array.isArray(params.execution_plan)
|
|
604
614
|
? (params.execution_plan as any[]).map((step: any, i: number) => ({
|
|
605
615
|
id: step.id || `step-${Date.now()}-${i}`,
|
|
606
616
|
text: typeof step === "string" ? step : step.text || String(step),
|
|
607
|
-
order: i,
|
|
617
|
+
order: existingSteps.length + i,
|
|
608
618
|
}))
|
|
609
619
|
: [];
|
|
620
|
+
// Merge: concat existing + new, dedup by id
|
|
621
|
+
const stepIds = new Set(existingSteps.map((s: any) => s.id));
|
|
622
|
+
mergedCf.execution_plan = [...existingSteps, ...newSteps.filter((s: any) => !stepIds.has(s.id))];
|
|
610
623
|
}
|
|
611
624
|
|
|
612
625
|
if (params.goals !== undefined) {
|
|
613
|
-
|
|
626
|
+
const existingGoals = (existingCf.goals || []) as any[];
|
|
627
|
+
const newGoals = Array.isArray(params.goals)
|
|
614
628
|
? (params.goals as any[]).map((g: any, i: number) => ({
|
|
615
629
|
id: g.id || `goal-${Date.now()}-${i}`,
|
|
616
630
|
type: g.type || "custom",
|
|
617
631
|
label: typeof g === "string" ? g : g.label || String(g),
|
|
618
632
|
}))
|
|
619
633
|
: [];
|
|
634
|
+
// Merge: concat existing + new, dedup by id
|
|
635
|
+
const goalIds = new Set(existingGoals.map((g: any) => g.id));
|
|
636
|
+
mergedCf.goals = [...existingGoals, ...newGoals.filter((g: any) => !goalIds.has(g.id))];
|
|
620
637
|
}
|
|
621
638
|
|
|
622
639
|
if (params.constraints !== undefined) {
|
|
623
|
-
|
|
640
|
+
const existingConstraints = (existingCf.constraints || []) as any[];
|
|
641
|
+
const newConstraints = Array.isArray(params.constraints)
|
|
624
642
|
? (params.constraints as any[]).map((c: any, i: number) => ({
|
|
625
643
|
id: c.id || `cstr-${Date.now()}-${i}`,
|
|
626
644
|
type: c.type || "custom",
|
|
627
645
|
label: typeof c === "string" ? c : c.label || String(c),
|
|
628
646
|
}))
|
|
629
647
|
: [];
|
|
648
|
+
// Merge: concat existing + new, dedup by id
|
|
649
|
+
const cstrIds = new Set(existingConstraints.map((c: any) => c.id));
|
|
650
|
+
mergedCf.constraints = [...existingConstraints, ...newConstraints.filter((c: any) => !cstrIds.has(c.id))];
|
|
630
651
|
}
|
|
631
652
|
|
|
632
653
|
if (params.system_prompt !== undefined) mergedCf.system_prompt = params.system_prompt;
|
|
@@ -753,15 +774,6 @@ async function handleListAgents(
|
|
|
753
774
|
fallbackAgentId: string,
|
|
754
775
|
): Promise<ToolResult> {
|
|
755
776
|
try {
|
|
756
|
-
// Resolve calling agent's ID for the "your_agent_id" hint
|
|
757
|
-
const callerName = getCallingAgentName(api);
|
|
758
|
-
let yourAgentId = fallbackAgentId || "";
|
|
759
|
-
if (callerName && !yourAgentId) {
|
|
760
|
-
try {
|
|
761
|
-
yourAgentId = await resolveAgentId(callerName, userId, supabase);
|
|
762
|
-
} catch { /* ignore */ }
|
|
763
|
-
}
|
|
764
|
-
|
|
765
777
|
const { data, error } = await supabase
|
|
766
778
|
.from("agents")
|
|
767
779
|
.select("id, name, codename, role, status")
|
|
@@ -769,10 +781,40 @@ async function handleListAgents(
|
|
|
769
781
|
.order("name");
|
|
770
782
|
|
|
771
783
|
if (error) return err(error.message);
|
|
784
|
+
|
|
785
|
+
// BUG 1 fix: resolve your_agent_id to the agent NAME (e.g. "celia")
|
|
786
|
+
// so callers can use it directly for task assignment.
|
|
787
|
+
// Previous behavior returned an internal UUID/auto-generated ID that
|
|
788
|
+
// didn't match any assignable agent in the list.
|
|
789
|
+
let yourAgentName: string | null = null;
|
|
790
|
+
|
|
791
|
+
// Try fallbackAgentId first (env var OFIERE_AGENT_ID)
|
|
792
|
+
if (fallbackAgentId) {
|
|
793
|
+
// If fallback is a UUID, find the matching agent name
|
|
794
|
+
const match = (data || []).find((a: any) => a.id === fallbackAgentId);
|
|
795
|
+
yourAgentName = match?.name || null;
|
|
796
|
+
}
|
|
797
|
+
|
|
798
|
+
// Try runtime detection
|
|
799
|
+
if (!yourAgentName) {
|
|
800
|
+
const callerName = getCallingAgentName(api);
|
|
801
|
+
if (callerName && !isSystemName(callerName)) {
|
|
802
|
+
// Check if callerName matches any agent name (case-insensitive)
|
|
803
|
+
const match = (data || []).find(
|
|
804
|
+
(a: any) => a.name?.toLowerCase() === callerName.toLowerCase() ||
|
|
805
|
+
a.codename?.toLowerCase() === callerName.toLowerCase()
|
|
806
|
+
);
|
|
807
|
+
yourAgentName = match?.name || null;
|
|
808
|
+
}
|
|
809
|
+
}
|
|
810
|
+
|
|
772
811
|
return ok({
|
|
773
812
|
agents: data || [],
|
|
774
813
|
count: (data || []).length,
|
|
775
|
-
your_agent_id:
|
|
814
|
+
your_agent_id: yourAgentName,
|
|
815
|
+
hint: !yourAgentName
|
|
816
|
+
? "Could not auto-detect your agent. Use an agent name from the list above (e.g. 'celia') when creating tasks."
|
|
817
|
+
: undefined,
|
|
776
818
|
});
|
|
777
819
|
} catch (e) {
|
|
778
820
|
return err(e instanceof Error ? e.message : String(e));
|