ofiere-openclaw-plugin 4.7.0 → 4.9.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 +59 -18
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "ofiere-openclaw-plugin",
|
|
3
|
-
"version": "4.
|
|
3
|
+
"version": "4.9.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` +
|
|
@@ -206,12 +207,15 @@ function registerTaskOps(
|
|
|
206
207
|
action: {
|
|
207
208
|
type: "string",
|
|
208
209
|
description: "The operation to perform",
|
|
209
|
-
enum: ["list", "create", "update", "delete"],
|
|
210
|
+
enum: ["list", "get", "create", "update", "delete"],
|
|
210
211
|
},
|
|
211
|
-
task_id: { type: "string", description: "Task ID (required for update, delete)" },
|
|
212
212
|
title: { type: "string", description: "Task title (required for create)" },
|
|
213
213
|
description: { type: "string", description: "Task description" },
|
|
214
214
|
instructions: { type: "string", description: "Detailed instructions for the agent executing this task" },
|
|
215
|
+
task_id: {
|
|
216
|
+
type: "string",
|
|
217
|
+
description: "Task ID — use with 'list' to filter or 'get' to fetch a single task",
|
|
218
|
+
},
|
|
215
219
|
agent_id: {
|
|
216
220
|
type: "string",
|
|
217
221
|
description: "Agent name or ID. Your name to self-assign, 'none' for unassigned.",
|
|
@@ -284,6 +288,9 @@ function registerTaskOps(
|
|
|
284
288
|
switch (action) {
|
|
285
289
|
case "list":
|
|
286
290
|
return handleListTasks(supabase, userId, params);
|
|
291
|
+
case "get":
|
|
292
|
+
if (!params.task_id) return err("Missing required field: task_id");
|
|
293
|
+
return handleListTasks(supabase, userId, { ...params, limit: 1 });
|
|
287
294
|
case "create":
|
|
288
295
|
return handleCreateTask(supabase, userId, resolveAgent, params);
|
|
289
296
|
case "update":
|
|
@@ -292,7 +299,7 @@ function registerTaskOps(
|
|
|
292
299
|
return handleDeleteTask(supabase, userId, params);
|
|
293
300
|
default:
|
|
294
301
|
return err(
|
|
295
|
-
`Unknown action "${action}". Valid actions: list, create, update, delete`,
|
|
302
|
+
`Unknown action "${action}". Valid actions: list, get, create, update, delete`,
|
|
296
303
|
);
|
|
297
304
|
}
|
|
298
305
|
},
|
|
@@ -316,6 +323,7 @@ async function handleListTasks(
|
|
|
316
323
|
.eq("user_id", userId)
|
|
317
324
|
.order("updated_at", { ascending: false });
|
|
318
325
|
|
|
326
|
+
if (params.task_id) query = query.eq("id", params.task_id as string);
|
|
319
327
|
if (params.space_id) query = query.eq("space_id", params.space_id as string);
|
|
320
328
|
if (params.folder_id) query = query.eq("folder_id", params.folder_id as string);
|
|
321
329
|
if (params.agent_id) query = query.eq("agent_id", params.agent_id as string);
|
|
@@ -600,33 +608,45 @@ async function handleUpdateTask(
|
|
|
600
608
|
const mergedCf = { ...existingCf };
|
|
601
609
|
|
|
602
610
|
if (params.execution_plan !== undefined) {
|
|
603
|
-
|
|
611
|
+
const existingSteps = (existingCf.execution_plan || []) as any[];
|
|
612
|
+
const newSteps = Array.isArray(params.execution_plan)
|
|
604
613
|
? (params.execution_plan as any[]).map((step: any, i: number) => ({
|
|
605
614
|
id: step.id || `step-${Date.now()}-${i}`,
|
|
606
615
|
text: typeof step === "string" ? step : step.text || String(step),
|
|
607
|
-
order: i,
|
|
616
|
+
order: existingSteps.length + i,
|
|
608
617
|
}))
|
|
609
618
|
: [];
|
|
619
|
+
// Merge: concat existing + new, dedup by id
|
|
620
|
+
const stepIds = new Set(existingSteps.map((s: any) => s.id));
|
|
621
|
+
mergedCf.execution_plan = [...existingSteps, ...newSteps.filter((s: any) => !stepIds.has(s.id))];
|
|
610
622
|
}
|
|
611
623
|
|
|
612
624
|
if (params.goals !== undefined) {
|
|
613
|
-
|
|
625
|
+
const existingGoals = (existingCf.goals || []) as any[];
|
|
626
|
+
const newGoals = Array.isArray(params.goals)
|
|
614
627
|
? (params.goals as any[]).map((g: any, i: number) => ({
|
|
615
628
|
id: g.id || `goal-${Date.now()}-${i}`,
|
|
616
629
|
type: g.type || "custom",
|
|
617
630
|
label: typeof g === "string" ? g : g.label || String(g),
|
|
618
631
|
}))
|
|
619
632
|
: [];
|
|
633
|
+
// Merge: concat existing + new, dedup by id
|
|
634
|
+
const goalIds = new Set(existingGoals.map((g: any) => g.id));
|
|
635
|
+
mergedCf.goals = [...existingGoals, ...newGoals.filter((g: any) => !goalIds.has(g.id))];
|
|
620
636
|
}
|
|
621
637
|
|
|
622
638
|
if (params.constraints !== undefined) {
|
|
623
|
-
|
|
639
|
+
const existingConstraints = (existingCf.constraints || []) as any[];
|
|
640
|
+
const newConstraints = Array.isArray(params.constraints)
|
|
624
641
|
? (params.constraints as any[]).map((c: any, i: number) => ({
|
|
625
642
|
id: c.id || `cstr-${Date.now()}-${i}`,
|
|
626
643
|
type: c.type || "custom",
|
|
627
644
|
label: typeof c === "string" ? c : c.label || String(c),
|
|
628
645
|
}))
|
|
629
646
|
: [];
|
|
647
|
+
// Merge: concat existing + new, dedup by id
|
|
648
|
+
const cstrIds = new Set(existingConstraints.map((c: any) => c.id));
|
|
649
|
+
mergedCf.constraints = [...existingConstraints, ...newConstraints.filter((c: any) => !cstrIds.has(c.id))];
|
|
630
650
|
}
|
|
631
651
|
|
|
632
652
|
if (params.system_prompt !== undefined) mergedCf.system_prompt = params.system_prompt;
|
|
@@ -753,15 +773,6 @@ async function handleListAgents(
|
|
|
753
773
|
fallbackAgentId: string,
|
|
754
774
|
): Promise<ToolResult> {
|
|
755
775
|
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
776
|
const { data, error } = await supabase
|
|
766
777
|
.from("agents")
|
|
767
778
|
.select("id, name, codename, role, status")
|
|
@@ -769,10 +780,40 @@ async function handleListAgents(
|
|
|
769
780
|
.order("name");
|
|
770
781
|
|
|
771
782
|
if (error) return err(error.message);
|
|
783
|
+
|
|
784
|
+
// BUG 1 fix: resolve your_agent_id to the agent NAME (e.g. "celia")
|
|
785
|
+
// so callers can use it directly for task assignment.
|
|
786
|
+
// Previous behavior returned an internal UUID/auto-generated ID that
|
|
787
|
+
// didn't match any assignable agent in the list.
|
|
788
|
+
let yourAgentName: string | null = null;
|
|
789
|
+
|
|
790
|
+
// Try fallbackAgentId first (env var OFIERE_AGENT_ID)
|
|
791
|
+
if (fallbackAgentId) {
|
|
792
|
+
// If fallback is a UUID, find the matching agent name
|
|
793
|
+
const match = (data || []).find((a: any) => a.id === fallbackAgentId);
|
|
794
|
+
yourAgentName = match?.name || null;
|
|
795
|
+
}
|
|
796
|
+
|
|
797
|
+
// Try runtime detection
|
|
798
|
+
if (!yourAgentName) {
|
|
799
|
+
const callerName = getCallingAgentName(api);
|
|
800
|
+
if (callerName && !isSystemName(callerName)) {
|
|
801
|
+
// Check if callerName matches any agent name (case-insensitive)
|
|
802
|
+
const match = (data || []).find(
|
|
803
|
+
(a: any) => a.name?.toLowerCase() === callerName.toLowerCase() ||
|
|
804
|
+
a.codename?.toLowerCase() === callerName.toLowerCase()
|
|
805
|
+
);
|
|
806
|
+
yourAgentName = match?.name || null;
|
|
807
|
+
}
|
|
808
|
+
}
|
|
809
|
+
|
|
772
810
|
return ok({
|
|
773
811
|
agents: data || [],
|
|
774
812
|
count: (data || []).length,
|
|
775
|
-
your_agent_id:
|
|
813
|
+
your_agent_id: yourAgentName,
|
|
814
|
+
hint: !yourAgentName
|
|
815
|
+
? "Could not auto-detect your agent. Use an agent name from the list above (e.g. 'celia') when creating tasks."
|
|
816
|
+
: undefined,
|
|
776
817
|
});
|
|
777
818
|
} catch (e) {
|
|
778
819
|
return err(e instanceof Error ? e.message : String(e));
|