ofiere-openclaw-plugin 4.1.0 → 4.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.
- package/package.json +1 -1
- package/src/tools.ts +52 -14
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "ofiere-openclaw-plugin",
|
|
3
|
-
"version": "4.
|
|
3
|
+
"version": "4.3.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
|
@@ -1334,17 +1334,24 @@ function registerWorkflowOps(
|
|
|
1334
1334
|
return { wf: data, error: null };
|
|
1335
1335
|
}
|
|
1336
1336
|
|
|
1337
|
-
// Helper: save updated graph back to DB
|
|
1337
|
+
// Helper: save updated graph back to DB with verification re-read
|
|
1338
1338
|
async function saveGraph(wfId: string, nodes: any[], edges: any[]) {
|
|
1339
|
-
const {
|
|
1339
|
+
const { error } = await supabase
|
|
1340
1340
|
.from("workflows")
|
|
1341
1341
|
.update({ nodes, edges, updated_at: new Date().toISOString() })
|
|
1342
1342
|
.eq("id", wfId)
|
|
1343
|
+
.eq("user_id", userId);
|
|
1344
|
+
if (error) return { wf: null, error: error.message };
|
|
1345
|
+
// Verification re-read — guarantees we return the actual persisted state,
|
|
1346
|
+
// not a potentially stale response from the update's connection.
|
|
1347
|
+
const { data: verified, error: readErr } = await supabase
|
|
1348
|
+
.from("workflows")
|
|
1349
|
+
.select("*")
|
|
1350
|
+
.eq("id", wfId)
|
|
1343
1351
|
.eq("user_id", userId)
|
|
1344
|
-
.select()
|
|
1345
1352
|
.single();
|
|
1346
|
-
if (
|
|
1347
|
-
return { wf:
|
|
1353
|
+
if (readErr) return { wf: null, error: readErr.message };
|
|
1354
|
+
return { wf: verified, error: null };
|
|
1348
1355
|
}
|
|
1349
1356
|
|
|
1350
1357
|
switch (action) {
|
|
@@ -1358,9 +1365,12 @@ function registerWorkflowOps(
|
|
|
1358
1365
|
case "get": {
|
|
1359
1366
|
const wfId = (params.id || params.workflow_id) as string;
|
|
1360
1367
|
if (!wfId) return err("Missing required: id");
|
|
1361
|
-
|
|
1362
|
-
|
|
1363
|
-
|
|
1368
|
+
// Route through serialization queue so reads wait for pending mutations
|
|
1369
|
+
return sequentialWorkflowOp(wfId, async () => {
|
|
1370
|
+
const { data, error } = await supabase.from("workflows").select("*").eq("id", wfId).eq("user_id", userId).single();
|
|
1371
|
+
if (error) return err(error.message);
|
|
1372
|
+
return ok({ workflow: data });
|
|
1373
|
+
});
|
|
1364
1374
|
}
|
|
1365
1375
|
case "create": {
|
|
1366
1376
|
if (!params.name) return err("Missing required: name");
|
|
@@ -1389,8 +1399,37 @@ function registerWorkflowOps(
|
|
|
1389
1399
|
finalNodes.unshift(triggerNode);
|
|
1390
1400
|
}
|
|
1391
1401
|
|
|
1392
|
-
// Build edges
|
|
1393
|
-
|
|
1402
|
+
// Build edges — remap IDs from pre-normalization to post-normalization
|
|
1403
|
+
const idRemap = new Map<string, string>();
|
|
1404
|
+
rawNodes.forEach((raw, i) => {
|
|
1405
|
+
if (raw.id && finalNodes[hasTrigger ? i : i + 1]?.id !== raw.id) {
|
|
1406
|
+
idRemap.set(raw.id, finalNodes[hasTrigger ? i : i + 1].id);
|
|
1407
|
+
}
|
|
1408
|
+
});
|
|
1409
|
+
|
|
1410
|
+
let finalEdges: any[];
|
|
1411
|
+
const suppliedEdges = (params.edges as any[]) || [];
|
|
1412
|
+
|
|
1413
|
+
if (suppliedEdges.length > 0) {
|
|
1414
|
+
// Remap source/target IDs in user-supplied edges
|
|
1415
|
+
finalEdges = suppliedEdges.map((e: any, i: number) => {
|
|
1416
|
+
const remapped = {
|
|
1417
|
+
...e,
|
|
1418
|
+
source: idRemap.get(e.source) || e.source,
|
|
1419
|
+
target: idRemap.get(e.target) || e.target,
|
|
1420
|
+
};
|
|
1421
|
+
return normalizeEdge(remapped, i);
|
|
1422
|
+
});
|
|
1423
|
+
} else {
|
|
1424
|
+
// No edges supplied — auto-chain all nodes in order
|
|
1425
|
+
finalEdges = [];
|
|
1426
|
+
for (let i = 0; i < finalNodes.length - 1; i++) {
|
|
1427
|
+
finalEdges.push(normalizeEdge({
|
|
1428
|
+
source: finalNodes[i].id,
|
|
1429
|
+
target: finalNodes[i + 1].id,
|
|
1430
|
+
}, i));
|
|
1431
|
+
}
|
|
1432
|
+
}
|
|
1394
1433
|
|
|
1395
1434
|
// Auto-wire trigger to first non-trigger node if no edge connects from trigger
|
|
1396
1435
|
if (!hasTrigger && finalNodes.length > 1) {
|
|
@@ -1398,11 +1437,10 @@ function registerWorkflowOps(
|
|
|
1398
1437
|
const firstStepId = finalNodes[1].id;
|
|
1399
1438
|
const triggerHasEdge = finalEdges.some((e: any) => e.source === triggerId);
|
|
1400
1439
|
if (!triggerHasEdge) {
|
|
1401
|
-
finalEdges.unshift({
|
|
1402
|
-
id: `edge-trigger-${Date.now()}`,
|
|
1440
|
+
finalEdges.unshift(normalizeEdge({
|
|
1403
1441
|
source: triggerId,
|
|
1404
1442
|
target: firstStepId,
|
|
1405
|
-
});
|
|
1443
|
+
}, finalEdges.length));
|
|
1406
1444
|
}
|
|
1407
1445
|
}
|
|
1408
1446
|
|
|
@@ -1453,7 +1491,7 @@ function registerWorkflowOps(
|
|
|
1453
1491
|
if (!wfId) return err("Missing required: workflow_id");
|
|
1454
1492
|
const { data, error } = await supabase.from("workflow_runs").select("*")
|
|
1455
1493
|
.eq("workflow_id", wfId)
|
|
1456
|
-
.order("
|
|
1494
|
+
.order("started_at", { ascending: false })
|
|
1457
1495
|
.limit((params.limit as number) || 20);
|
|
1458
1496
|
if (error) return err(error.message);
|
|
1459
1497
|
return ok({ runs: data || [], count: (data || []).length });
|