ofiere-openclaw-plugin 4.41.0 → 4.41.1

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/agent-tier.ts +32 -14
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ofiere-openclaw-plugin",
3
- "version": "4.41.0",
3
+ "version": "4.41.1",
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/agent-tier.ts CHANGED
@@ -53,12 +53,12 @@ export async function resolveAgentTier(
53
53
  if (!id || !userId) return { tier: null, source: "none" };
54
54
 
55
55
  const key = k(userId, id);
56
- const hit = cache.get(key);
57
- if (hit && hit.expires > Date.now()) return hit.value;
58
56
 
59
- let result: TierResolution = { tier: null, source: "none" };
60
-
61
- // 1. Manual override
57
+ // 1. Manual override ALWAYS fresh (uncached). Direct-SQL writes to
58
+ // agent_tier_overrides must win immediately, even when a non-override
59
+ // branch is already cached from a prior call.
60
+ let overrideRow: { tier?: string | null } | null = null;
61
+ let overrideQueryFailed = false;
62
62
  try {
63
63
  const { data } = await supabase
64
64
  .from("agent_tier_overrides")
@@ -66,23 +66,41 @@ export async function resolveAgentTier(
66
66
  .eq("user_id", userId)
67
67
  .eq("agent_id", id)
68
68
  .maybeSingle();
69
- if (data?.tier === "c-suite" || data?.tier === "staff") {
70
- result = { tier: data.tier, source: "manual" };
71
- cache.set(key, { value: result, expires: Date.now() + TTL_MS });
72
- return result;
73
- }
69
+ overrideRow = data ?? null;
74
70
  } catch {
75
- // Table missing in older installs — fall through
71
+ // Table missing in older installs — skip override path
72
+ overrideQueryFailed = true;
76
73
  }
77
74
 
78
- // 2. C-Suite: hardcoded roster
75
+ if (overrideRow?.tier === "c-suite" || overrideRow?.tier === "staff") {
76
+ const result: TierResolution = { tier: overrideRow.tier, source: "manual" };
77
+ cache.set(key, { value: result, expires: Date.now() + TTL_MS });
78
+ return result;
79
+ }
80
+
81
+ // Override absent: if cache holds a stale `manual` entry from a deleted
82
+ // override row, drop it so the auto branches re-resolve.
83
+ if (!overrideQueryFailed) {
84
+ const cachedManual = cache.get(key);
85
+ if (cachedManual && cachedManual.value.source === "manual") {
86
+ cache.delete(key);
87
+ }
88
+ }
89
+
90
+ // 2. Cache lookup for non-override branches.
91
+ const hit = cache.get(key);
92
+ if (hit && hit.expires > Date.now()) return hit.value;
93
+
94
+ let result: TierResolution = { tier: null, source: "none" };
95
+
96
+ // 3. C-Suite: hardcoded roster
79
97
  if (ROSTER_IDS.has(id)) {
80
98
  result = { tier: "c-suite", source: "roster" };
81
99
  cache.set(key, { value: result, expires: Date.now() + TTL_MS });
82
100
  return result;
83
101
  }
84
102
 
85
- // 3. agent_architectures.executive_role / department_role
103
+ // 4. agent_architectures.executive_role / department_role
86
104
  try {
87
105
  const { data } = await supabase
88
106
  .from("agent_architectures")
@@ -105,7 +123,7 @@ export async function resolveAgentTier(
105
123
  // Table missing — fall through
106
124
  }
107
125
 
108
- // 4. Staff: registered as subagent
126
+ // 5. Staff: registered as subagent
109
127
  try {
110
128
  const { data } = await supabase
111
129
  .from("agent_subagents")