ofiere-openclaw-plugin 4.3.1 → 4.4.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.
Files changed (2) hide show
  1. package/package.json +1 -1
  2. package/src/tools.ts +85 -13
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ofiere-openclaw-plugin",
3
- "version": "4.3.1",
3
+ "version": "4.4.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
@@ -2098,8 +2098,11 @@ function registerConstellationOps(
2098
2098
  return path.join(OPENCLAW_ROOT, `workspace-${agentName.toLowerCase()}`);
2099
2099
  }
2100
2100
 
2101
- function listWorkspaceAgents(): Array<{ name: string; codename: string; role: string; files: string[]; hasSkills: boolean }> {
2102
- const result: Array<{ name: string; codename: string; role: string; files: string[]; hasSkills: boolean }> = [];
2101
+ // System-generated .md files that OpenClaw creates automatically not user-authored
2102
+ const SYSTEM_MD_FILES = new Set(["HEARTBEAT.md", "USER.md", "MEMORY.md"]);
2103
+
2104
+ function listWorkspaceAgents(): Array<{ name: string; codename: string; role: string; files: string[]; system_files: string[]; hasSkills: boolean }> {
2105
+ const result: Array<{ name: string; codename: string; role: string; files: string[]; system_files: string[]; hasSkills: boolean }> = [];
2103
2106
  try {
2104
2107
  const entries = fs.readdirSync(OPENCLAW_ROOT, { withFileTypes: true });
2105
2108
  for (const entry of entries) {
@@ -2107,7 +2110,9 @@ function registerConstellationOps(
2107
2110
  const agentName = entry.name.replace("workspace-", "");
2108
2111
  if (agentName === "main" || agentName === "zero" || agentName === "echo") continue; // skip system agents
2109
2112
  const wsPath = path.join(OPENCLAW_ROOT, entry.name);
2110
- const files = fs.readdirSync(wsPath).filter((f: string) => f.endsWith(".md"));
2113
+ const allMd = fs.readdirSync(wsPath).filter((f: string) => f.endsWith(".md"));
2114
+ const files = allMd.filter((f: string) => !SYSTEM_MD_FILES.has(f));
2115
+ const system_files = allMd.filter((f: string) => SYSTEM_MD_FILES.has(f));
2111
2116
  // Try to extract codename and role from IDENTITY.md
2112
2117
  let codename = agentName.toUpperCase();
2113
2118
  let role = "Agent";
@@ -2119,7 +2124,7 @@ function registerConstellationOps(
2119
2124
  if (roleMatch) role = roleMatch[1].trim();
2120
2125
  } catch {}
2121
2126
  const hasSkills = fs.existsSync(path.join(wsPath, "skills"));
2122
- result.push({ name: agentName, codename, role, files, hasSkills });
2127
+ result.push({ name: agentName, codename, role, files, system_files, hasSkills });
2123
2128
  }
2124
2129
  } catch (e) {
2125
2130
  api.logger?.warn?.(`[ofiere] Failed to list workspaces: ${e}`);
@@ -2158,6 +2163,7 @@ function registerConstellationOps(
2158
2163
  if (p.emoji) lines.push(`**Emoji:** ${p.emoji}`);
2159
2164
  lines.push(`**Role:** ${p.role || "Agent"}`);
2160
2165
  lines.push(`**Codename:** ${p.codename}`);
2166
+ if (p.color_hex) lines.push(`**Color:** ${p.color_hex}`);
2161
2167
  if (p.voice_sample) lines.push(`**Sample:** ${p.voice_sample}`);
2162
2168
  lines.push("");
2163
2169
  if (p.one_liner) {
@@ -2170,10 +2176,34 @@ function registerConstellationOps(
2170
2176
  lines.push("");
2171
2177
  lines.push(p.core_identity || `${p.agent_name} is an AI agent specializing in ${p.role || "general tasks"}.`);
2172
2178
  lines.push("");
2179
+ if (p.personality) {
2180
+ lines.push("## Personality");
2181
+ lines.push("");
2182
+ lines.push(p.personality);
2183
+ lines.push("");
2184
+ }
2173
2185
  lines.push("## Operating Style");
2174
2186
  lines.push("");
2175
2187
  lines.push(p.operating_style || "Focused, professional, detail-oriented.");
2176
2188
  lines.push("");
2189
+ if (p.tone) {
2190
+ lines.push("## Tone");
2191
+ lines.push("");
2192
+ lines.push(p.tone);
2193
+ lines.push("");
2194
+ }
2195
+ if (p.worldview) {
2196
+ lines.push("## Worldview");
2197
+ lines.push("");
2198
+ lines.push(p.worldview);
2199
+ lines.push("");
2200
+ }
2201
+ if (p.pacing) {
2202
+ lines.push("## Pacing");
2203
+ lines.push("");
2204
+ lines.push(p.pacing);
2205
+ lines.push("");
2206
+ }
2177
2207
  lines.push("## Relationship to Team");
2178
2208
  lines.push("");
2179
2209
  lines.push(p.team_relationship || "Collaborative team member within the agent constellation.");
@@ -2440,6 +2470,7 @@ function registerConstellationOps(
2440
2470
  role: a.role,
2441
2471
  file_count: a.files.length,
2442
2472
  files: a.files,
2473
+ system_files: a.system_files,
2443
2474
  has_skills: a.hasSkills,
2444
2475
  })),
2445
2476
  count: agents.length,
@@ -2540,7 +2571,46 @@ function registerConstellationOps(
2540
2571
 
2541
2572
  // Create doctrine file (codename.md) — empty scaffold
2542
2573
  const doctrineName = `${(params.codename as string).toUpperCase()}.md`;
2543
- const doctrineMd = `# ${params.codename} Doctrine\n\n## Mission\n\n${p.mission || "To be defined."}\n\n## Decision Frameworks\n\n- (Define frameworks here)\n\n## Non-Goals\n\n- (Define non-goals here)\n\n## Evaluation Criteria\n\n- (Define criteria here)\n\n## Metrics\n\n- (Define metrics here)\n\n## Standard Deliverables\n\n- (Define deliverables here)\n\n## Anti-Patterns\n\n- (Define anti-patterns here)\n\n## Handoff Rules\n\n- (Define handoff rules here)\n`;
2574
+ const doctrineMd = [
2575
+ `# ${params.codename} Doctrine`,
2576
+ "",
2577
+ "## Mission",
2578
+ "",
2579
+ p.mission || "To be defined.",
2580
+ "",
2581
+ "## Scope of Responsibility",
2582
+ "",
2583
+ p.scope || `All tasks related to ${p.role || "the assigned domain"}.`,
2584
+ "",
2585
+ "## Decision Frameworks",
2586
+ "",
2587
+ "*To be defined by the operator.*",
2588
+ "",
2589
+ "## Non-Goals",
2590
+ "",
2591
+ "*To be defined by the operator.*",
2592
+ "",
2593
+ "## Evaluation Criteria",
2594
+ "",
2595
+ "*To be defined by the operator.*",
2596
+ "",
2597
+ "## Metrics",
2598
+ "",
2599
+ "*To be defined by the operator.*",
2600
+ "",
2601
+ "## Standard Deliverables",
2602
+ "",
2603
+ "*To be defined by the operator.*",
2604
+ "",
2605
+ "## Anti-Patterns",
2606
+ "",
2607
+ "*To be defined by the operator.*",
2608
+ "",
2609
+ "## Handoff Rules",
2610
+ "",
2611
+ "*To be defined by the operator.*",
2612
+ "",
2613
+ ].join("\n");
2544
2614
  writeAgentFile(agentName, doctrineName, doctrineMd);
2545
2615
  filesWritten.push(doctrineName);
2546
2616
 
@@ -2618,12 +2688,13 @@ function registerConstellationOps(
2618
2688
  const agentsContent = readAgentFile(agent.name, "AGENTS.md");
2619
2689
  const owns: string[] = [];
2620
2690
  if (agentsContent) {
2621
- // Extract ### Owns section
2622
- const ownsMatch = agentsContent.match(/###\s+Owns\s*\n([\s\S]*?)(?=\n###|\n##|$)/i);
2691
+ // Extract Owns section — flexible heading match (##, ###, or ####)
2692
+ // Also try matching under a Boundaries parent section
2693
+ const ownsMatch = agentsContent.match(/#{2,4}\s+Owns\s*\n+([\s\S]*?)(?=\n#{2,4}\s|$)/i);
2623
2694
  if (ownsMatch) {
2624
2695
  const items = ownsMatch[1].split("\n")
2625
2696
  .map((l: string) => l.replace(/^[\s-*]+/, "").trim())
2626
- .filter((l: string) => l.length > 0);
2697
+ .filter((l: string) => l.length > 0 && !l.startsWith("#"));
2627
2698
  owns.push(...items);
2628
2699
  }
2629
2700
  }
@@ -2640,17 +2711,18 @@ function registerConstellationOps(
2640
2711
 
2641
2712
  // Safety gate: confirm must be explicitly true
2642
2713
  if (params.confirm !== true) {
2643
- // List what would be deleted so the agent can show the user
2644
- let fileList: string[] = [];
2714
+ // List only user-visible files that would be deleted (exclude internal dirs)
2715
+ let userFiles: string[] = [];
2645
2716
  try {
2646
2717
  if (fs.existsSync(wsPath)) {
2647
- fileList = fs.readdirSync(wsPath, { recursive: true }) as string[];
2718
+ userFiles = fs.readdirSync(wsPath)
2719
+ .filter((f: string) => f.endsWith(".md") || f === "skills");
2648
2720
  }
2649
2721
  } catch {}
2650
2722
  return err(
2651
- `⚠️ DESTRUCTIVE ACTION: This will permanently delete agent "${agentName}" and ALL files in workspace-${agentName}/ (${fileList.length} items). ` +
2723
+ `⚠️ DESTRUCTIVE ACTION: This will permanently delete agent "${agentName}" and ALL files in workspace-${agentName}/ (${userFiles.length} user files). ` +
2652
2724
  `This CANNOT be undone.\n\n` +
2653
- `Files that will be deleted:\n${fileList.map((f: string) => ` - ${f}`).join("\n") || " (directory not found)"}\n\n` +
2725
+ `Files that will be deleted:\n${userFiles.map((f: string) => ` - ${f}`).join("\n") || " (directory not found)"}\n\n` +
2654
2726
  `To proceed, ask the user for explicit confirmation and then call this action again with confirm: true.`
2655
2727
  );
2656
2728
  }