ofiere-openclaw-plugin 4.37.1 → 4.37.2
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 +38 -9
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "ofiere-openclaw-plugin",
|
|
3
|
-
"version": "4.37.
|
|
3
|
+
"version": "4.37.2",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "OpenClaw plugin for Ofiere PM - 16 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, and corporate frameworks",
|
|
6
6
|
"keywords": ["openclaw", "ofiere", "project-management", "agents", "plugin"],
|
package/src/tools.ts
CHANGED
|
@@ -5244,9 +5244,11 @@ function registerFrameworkOps(
|
|
|
5244
5244
|
`\\"strategic_objectives\\":[{\\"objective\\":\\"Grow MRR\\",\\"target\\":\\"$100k\\",\\"measurement\\":\\"Revenue dashboard\\"}],` +
|
|
5245
5245
|
`\\"risk_appetite\\":\\"moderate\\",\\"escalation_matrix\\":[{\\"trigger\\":\\"Budget >80%\\",\\"escalate_to\\":\\"CEO\\",\\"priority\\":\\"P1\\"}],` +
|
|
5246
5246
|
`\\"notes\\":\\"Quarterly review\\"}"\n\n` +
|
|
5247
|
-
`
|
|
5248
|
-
|
|
5249
|
-
|
|
5247
|
+
`Field types (must match — wrong shapes are coerced):\n` +
|
|
5248
|
+
`- string: mission, vision, decision_authority, budget_constraints, resource_limits, risk_appetite, team_composition, review_frequency, last_reviewed, next_review, notes\n` +
|
|
5249
|
+
`- string[]: core_principles, tool_stack, compliance_requirements, integration_points, tags\n` +
|
|
5250
|
+
`- object[]: strategic_objectives [{objective,target,measurement,frequency}], escalation_matrix [{trigger,escalate_to,priority,response_sla}]\n` +
|
|
5251
|
+
`- IMPORTANT: team_composition is a single STRING (a paragraph or newline-separated list), NOT an array. If you have multiple roles, join with newlines inside one string.\n\n` +
|
|
5250
5252
|
`Status values: "draft", "active", "under_review", "archived"`,
|
|
5251
5253
|
parameters: {
|
|
5252
5254
|
type: "object",
|
|
@@ -5278,6 +5280,33 @@ function registerFrameworkOps(
|
|
|
5278
5280
|
|
|
5279
5281
|
// ── Framework action handlers ────────────────────────────────────────────────
|
|
5280
5282
|
|
|
5283
|
+
// Coerce field values to the shape the dashboard editor expects. Without this,
|
|
5284
|
+
// LLMs frequently emit team_composition / core_principles etc. as the "wrong"
|
|
5285
|
+
// container shape and the editor crashes on .trim() / .map() / .length.
|
|
5286
|
+
const FW_STRING_FIELDS = ["mission", "vision", "decision_authority", "budget_constraints", "resource_limits", "risk_appetite", "team_composition", "review_frequency", "last_reviewed", "next_review", "rollback_procedure", "notes", "framework_id", "version", "category"] as const;
|
|
5287
|
+
const FW_STRING_ARRAY_FIELDS = ["core_principles", "tool_stack", "compliance_requirements", "integration_points", "tags"] as const;
|
|
5288
|
+
|
|
5289
|
+
function fwToString(v: unknown): string {
|
|
5290
|
+
if (typeof v === "string") return v;
|
|
5291
|
+
if (v == null) return "";
|
|
5292
|
+
if (Array.isArray(v)) return v.map((x) => (typeof x === "string" ? x : JSON.stringify(x))).join("\n");
|
|
5293
|
+
if (typeof v === "object") { try { return JSON.stringify(v); } catch { return ""; } }
|
|
5294
|
+
return String(v);
|
|
5295
|
+
}
|
|
5296
|
+
|
|
5297
|
+
function fwToStringArray(v: unknown): string[] {
|
|
5298
|
+
if (Array.isArray(v)) return v.map((x) => (typeof x === "string" ? x : JSON.stringify(x)));
|
|
5299
|
+
if (typeof v === "string" && v.trim()) return v.split(/\r?\n/).map((s) => s.trim()).filter(Boolean);
|
|
5300
|
+
return [];
|
|
5301
|
+
}
|
|
5302
|
+
|
|
5303
|
+
function normalizeFrameworkContent(raw: Record<string, unknown>): Record<string, unknown> {
|
|
5304
|
+
const out: Record<string, unknown> = { ...raw };
|
|
5305
|
+
for (const k of FW_STRING_FIELDS) if (k in out) out[k] = fwToString(out[k]);
|
|
5306
|
+
for (const k of FW_STRING_ARRAY_FIELDS) if (k in out) out[k] = fwToStringArray(out[k]);
|
|
5307
|
+
return out;
|
|
5308
|
+
}
|
|
5309
|
+
|
|
5281
5310
|
async function handleFWCreate(
|
|
5282
5311
|
supabase: SupabaseClient, userId: string,
|
|
5283
5312
|
resolveAgent: (id?: string) => Promise<string | null>,
|
|
@@ -5296,13 +5325,13 @@ async function handleFWCreate(
|
|
|
5296
5325
|
// Already a JSON string — merge with title
|
|
5297
5326
|
try {
|
|
5298
5327
|
const parsed = JSON.parse(params.content);
|
|
5299
|
-
content = JSON.stringify({ title, ...parsed });
|
|
5328
|
+
content = JSON.stringify(normalizeFrameworkContent({ title, ...parsed }));
|
|
5300
5329
|
} catch {
|
|
5301
5330
|
// Not valid JSON — wrap as notes
|
|
5302
|
-
content = JSON.stringify({ title, notes: params.content });
|
|
5331
|
+
content = JSON.stringify(normalizeFrameworkContent({ title, notes: params.content }));
|
|
5303
5332
|
}
|
|
5304
5333
|
} else if (params.framework_data && typeof params.framework_data === "object") {
|
|
5305
|
-
content = JSON.stringify({ title, ...(params.framework_data as Record<string, unknown>) });
|
|
5334
|
+
content = JSON.stringify(normalizeFrameworkContent({ title, ...(params.framework_data as Record<string, unknown>) }));
|
|
5306
5335
|
} else {
|
|
5307
5336
|
content = JSON.stringify({ title });
|
|
5308
5337
|
}
|
|
@@ -5363,13 +5392,13 @@ async function handleFWUpdate(supabase: SupabaseClient, userId: string, params:
|
|
|
5363
5392
|
if (typeof params.content === "string" && params.content.trim()) {
|
|
5364
5393
|
try {
|
|
5365
5394
|
const parsed = JSON.parse(params.content);
|
|
5366
|
-
updates.content = JSON.stringify({ title: parsed.title || (params.title as string) || "", ...parsed });
|
|
5395
|
+
updates.content = JSON.stringify(normalizeFrameworkContent({ title: parsed.title || (params.title as string) || "", ...parsed }));
|
|
5367
5396
|
} catch {
|
|
5368
|
-
updates.content = JSON.stringify({ title: (params.title as string) || "", notes: params.content });
|
|
5397
|
+
updates.content = JSON.stringify(normalizeFrameworkContent({ title: (params.title as string) || "", notes: params.content }));
|
|
5369
5398
|
}
|
|
5370
5399
|
} else if (params.framework_data && typeof params.framework_data === "object") {
|
|
5371
5400
|
const raw = params.framework_data as Record<string, unknown>;
|
|
5372
|
-
updates.content = JSON.stringify({ title: (raw.title as string) || (params.title as string) || "", ...raw });
|
|
5401
|
+
updates.content = JSON.stringify(normalizeFrameworkContent({ title: (raw.title as string) || (params.title as string) || "", ...raw }));
|
|
5373
5402
|
}
|
|
5374
5403
|
|
|
5375
5404
|
const { data, error } = await supabase.from("frameworks").update(updates)
|