ofiere-openclaw-plugin 4.47.0 → 4.49.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/attachments.ts +6 -3
- package/src/staffPersona.ts +58 -10
- package/src/tools.ts +30 -3
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "ofiere-openclaw-plugin",
|
|
3
|
-
"version": "4.
|
|
3
|
+
"version": "4.49.0",
|
|
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/attachments.ts
CHANGED
|
@@ -15,7 +15,7 @@ import {
|
|
|
15
15
|
invalidateAgentTier,
|
|
16
16
|
} from "./agent-tier.js";
|
|
17
17
|
import { issueAttachmentToken, verifyAttachmentToken } from "./attach-token.js";
|
|
18
|
-
import { loadSubagentRow, buildStaffPersonaBlock, readDispatchSubagentId, loadChiefStaffDefaults, loadDispatchContextBySession, resolveStaffModels, type SubagentRow, type DispatchContextRow } from "./staffPersona.js";
|
|
18
|
+
import { loadSubagentRow, buildStaffPersonaBlock, readDispatchSubagentId, loadChiefStaffDefaults, loadChiefAgentConfig, loadDispatchContextBySession, resolveStaffModels, type SubagentRow, type DispatchContextRow } from "./staffPersona.js";
|
|
19
19
|
|
|
20
20
|
interface ToolResult {
|
|
21
21
|
content: Array<{ type: "text"; text: string }>;
|
|
@@ -453,8 +453,11 @@ export function registerAttachmentContextHook(args: {
|
|
|
453
453
|
if (subagentId) {
|
|
454
454
|
staffRow = await loadSubagentRow(supabase, userId, subagentId);
|
|
455
455
|
if (staffRow && staffRow.chief_agent_id === resolvedAgentId) {
|
|
456
|
-
const chiefDefaults = await
|
|
457
|
-
|
|
456
|
+
const [chiefDefaults, chiefConfig] = await Promise.all([
|
|
457
|
+
loadChiefStaffDefaults(supabase, userId, staffRow.chief_agent_id).catch(() => null),
|
|
458
|
+
loadChiefAgentConfig(supabase, userId, staffRow.chief_agent_id).catch(() => null),
|
|
459
|
+
]);
|
|
460
|
+
const resolved = resolveStaffModels(staffRow, chiefDefaults, chiefConfig);
|
|
458
461
|
staffPrefix = buildStaffPersonaBlock(staffRow, resolved) + "\n\n---\n\n";
|
|
459
462
|
api.logger?.debug?.(
|
|
460
463
|
`[ofiere-staff] subagent ${subagentId} (${staffRow.name}) reporting to ${resolvedAgentId} — persona injected; resolved models: ${JSON.stringify(resolved)}`,
|
package/src/staffPersona.ts
CHANGED
|
@@ -127,7 +127,7 @@ export interface ResolvedStaffModels {
|
|
|
127
127
|
tool_call_model: string | null;
|
|
128
128
|
function_call_model: string | null;
|
|
129
129
|
vision_model: string | null;
|
|
130
|
-
source: Record<StaffModelSlot, "staff" | "chief_default" | "chief_fallback" | null>;
|
|
130
|
+
source: Record<StaffModelSlot, "staff" | "chief_default" | "chief_primary" | "chief_fallback" | null>;
|
|
131
131
|
}
|
|
132
132
|
|
|
133
133
|
const SLOTS: StaffModelSlot[] = [
|
|
@@ -138,6 +138,17 @@ const SLOTS: StaffModelSlot[] = [
|
|
|
138
138
|
"vision_model",
|
|
139
139
|
];
|
|
140
140
|
|
|
141
|
+
// Cycle 7b BUGSHOOT-3 — chief's own ofie_agent_config row, used as the third
|
|
142
|
+
// fallback tier when neither the staff slot nor the chief STAFF MODEL slot is
|
|
143
|
+
// set. Mirrors the dispatcher's loadStaffPrimaryModel chain.
|
|
144
|
+
export interface ChiefAgentConfigRow {
|
|
145
|
+
agent_id: string;
|
|
146
|
+
primary_model: string | null;
|
|
147
|
+
coding_model: string | null;
|
|
148
|
+
tool_call_model: string | null;
|
|
149
|
+
vision_model: string | null;
|
|
150
|
+
}
|
|
151
|
+
|
|
141
152
|
export async function loadChiefStaffDefaults(
|
|
142
153
|
supabase: SupabaseClient,
|
|
143
154
|
userId: string,
|
|
@@ -155,19 +166,42 @@ export async function loadChiefStaffDefaults(
|
|
|
155
166
|
return data as ChiefStaffDefaultsRow;
|
|
156
167
|
}
|
|
157
168
|
|
|
169
|
+
export async function loadChiefAgentConfig(
|
|
170
|
+
supabase: SupabaseClient,
|
|
171
|
+
userId: string,
|
|
172
|
+
chiefAgentId: string,
|
|
173
|
+
): Promise<ChiefAgentConfigRow | null> {
|
|
174
|
+
const { data, error } = await supabase
|
|
175
|
+
.from("ofie_agent_config")
|
|
176
|
+
.select("agent_id, primary_model, coding_model, tool_call_model, vision_model")
|
|
177
|
+
.eq("user_id", userId)
|
|
178
|
+
.eq("agent_id", chiefAgentId)
|
|
179
|
+
.maybeSingle();
|
|
180
|
+
if (error || !data) return null;
|
|
181
|
+
return data as ChiefAgentConfigRow;
|
|
182
|
+
}
|
|
183
|
+
|
|
158
184
|
/**
|
|
159
|
-
* Resolution chain at delegate_to_staff time:
|
|
160
|
-
* staff.<slot>
|
|
161
|
-
*
|
|
162
|
-
*
|
|
163
|
-
*
|
|
185
|
+
* Resolution chain at delegate_to_staff time (BUGSHOOT-3):
|
|
186
|
+
* 1. staff.<slot> (per-staff override)
|
|
187
|
+
* 2. chief_staff_defaults.<slot> (chief-level STAFF MODEL)
|
|
188
|
+
* 3. ofie_agent_config.<slot> (chief's OWN slot, NEW)
|
|
189
|
+
* 4. ofie_agent_config.primary_model (chief's primary, last-resort sub)
|
|
190
|
+
* 5. null (gateway picks gateway default)
|
|
191
|
+
*
|
|
192
|
+
* Tier 3 was added in BUGSHOOT-3 because the prior chain stopped at tier 2 and
|
|
193
|
+
* relied on an implicit "gateway default" — which is opaque and led to BUG 10
|
|
194
|
+
* when the staff override held a model id the gateway rejected. With tier 3,
|
|
195
|
+
* an empty staff slot deterministically inherits the chief's actual model.
|
|
164
196
|
*
|
|
165
|
-
*
|
|
166
|
-
*
|
|
197
|
+
* Tier 4 (slot → primary_model fallback) handles the common case where chief
|
|
198
|
+
* has only a primary_model set and no per-slot routing — a staff with
|
|
199
|
+
* coding_model blank still inherits chief's primary_model rather than null.
|
|
167
200
|
*/
|
|
168
201
|
export function resolveStaffModels(
|
|
169
202
|
staff: SubagentRow,
|
|
170
203
|
chiefDefaults: ChiefStaffDefaultsRow | null,
|
|
204
|
+
chiefConfig?: ChiefAgentConfigRow | null,
|
|
171
205
|
): ResolvedStaffModels {
|
|
172
206
|
const out: ResolvedStaffModels = {
|
|
173
207
|
primary_model: null,
|
|
@@ -183,15 +217,26 @@ export function resolveStaffModels(
|
|
|
183
217
|
vision_model: null,
|
|
184
218
|
},
|
|
185
219
|
};
|
|
220
|
+
const chiefPrimary = typeof chiefConfig?.primary_model === "string" && chiefConfig.primary_model.trim()
|
|
221
|
+
? chiefConfig.primary_model.trim()
|
|
222
|
+
: null;
|
|
186
223
|
for (const slot of SLOTS) {
|
|
187
224
|
const staffVal = (staff as any)[slot] as string | null | undefined;
|
|
188
225
|
const chiefVal = chiefDefaults ? (chiefDefaults as any)[slot] as string | null | undefined : null;
|
|
226
|
+
const chiefSlotVal = chiefConfig ? (chiefConfig as any)[slot] as string | null | undefined : null;
|
|
189
227
|
if (staffVal && staffVal.trim()) {
|
|
190
228
|
out[slot] = staffVal;
|
|
191
229
|
out.source[slot] = "staff";
|
|
192
230
|
} else if (chiefVal && chiefVal.trim()) {
|
|
193
231
|
out[slot] = chiefVal;
|
|
194
232
|
out.source[slot] = "chief_default";
|
|
233
|
+
} else if (chiefSlotVal && chiefSlotVal.trim()) {
|
|
234
|
+
out[slot] = chiefSlotVal;
|
|
235
|
+
out.source[slot] = "chief_primary";
|
|
236
|
+
} else if (chiefPrimary) {
|
|
237
|
+
// Sub-fallback: chief has a primary_model but no per-slot override.
|
|
238
|
+
out[slot] = chiefPrimary;
|
|
239
|
+
out.source[slot] = "chief_primary";
|
|
195
240
|
} else {
|
|
196
241
|
out[slot] = null;
|
|
197
242
|
out.source[slot] = "chief_fallback";
|
|
@@ -225,8 +270,11 @@ export function buildStaffPersonaBlock(
|
|
|
225
270
|
lines.push(``, `## Operating Instructions`, staff.instructions.trim());
|
|
226
271
|
}
|
|
227
272
|
if (resolved && (resolved.primary_model || resolved.coding_model || resolved.tool_call_model || resolved.function_call_model || resolved.vision_model)) {
|
|
228
|
-
const sourceLabel = (s: "staff" | "chief_default" | "chief_fallback" | null) =>
|
|
229
|
-
s === "staff" ? "per-staff override"
|
|
273
|
+
const sourceLabel = (s: "staff" | "chief_default" | "chief_primary" | "chief_fallback" | null) =>
|
|
274
|
+
s === "staff" ? "per-staff override"
|
|
275
|
+
: s === "chief_default" ? "chief STAFF MODEL"
|
|
276
|
+
: s === "chief_primary" ? "chief's own model"
|
|
277
|
+
: "inherits chief (gateway default)";
|
|
230
278
|
const rows: string[] = [];
|
|
231
279
|
if (resolved.primary_model) rows.push(`- primary: \`${resolved.primary_model}\` (${sourceLabel(resolved.source.primary_model)})`);
|
|
232
280
|
if (resolved.coding_model) rows.push(`- coding: \`${resolved.coding_model}\` (${sourceLabel(resolved.source.coding_model)})`);
|
package/src/tools.ts
CHANGED
|
@@ -6562,10 +6562,20 @@ function registerBrainExtractionHook(
|
|
|
6562
6562
|
): void {
|
|
6563
6563
|
try {
|
|
6564
6564
|
api.on("agent_end", async (event: any, ctx: any) => {
|
|
6565
|
+
// Cycle 7b BUGSHOOT-4 — entry log is load-bearing: 4 prior cycles spent
|
|
6566
|
+
// chasing downstream symptoms because no log existed to prove the hook
|
|
6567
|
+
// even fired. If you're debugging staff-dispatch persistence and DO NOT
|
|
6568
|
+
// see this line in the gateway log, the hook never ran — investigate
|
|
6569
|
+
// hook registration / agent scoping before anything else.
|
|
6570
|
+
const _entrySessionKey = ctx?.sessionKey || event?.sessionKey || event?.context?.sessionKey || "(none)";
|
|
6571
|
+
api.logger.info?.(`[ofiere-brain] agent_end fired (sessionKey=${_entrySessionKey})`);
|
|
6565
6572
|
try {
|
|
6566
6573
|
// Extract messages from event — agent_end provides the conversation
|
|
6567
6574
|
const messages: any[] = event?.messages || event?.context?.messages || [];
|
|
6568
|
-
if (!messages || messages.length < 2)
|
|
6575
|
+
if (!messages || messages.length < 2) {
|
|
6576
|
+
api.logger.debug?.(`[ofiere-brain] agent_end early-exit: messages.length=${messages?.length ?? 0} (<2)`);
|
|
6577
|
+
return;
|
|
6578
|
+
}
|
|
6569
6579
|
|
|
6570
6580
|
// Find last user + last assistant message
|
|
6571
6581
|
let lastUser = "";
|
|
@@ -6589,8 +6599,15 @@ function registerBrainExtractionHook(
|
|
|
6589
6599
|
if (lastUser && lastAssistant) break;
|
|
6590
6600
|
}
|
|
6591
6601
|
|
|
6592
|
-
//
|
|
6593
|
-
if
|
|
6602
|
+
// Cycle 7b BUGSHOOT-4 — REMOVED early-return on short messages here.
|
|
6603
|
+
// The prior gate (`if lastUser<20 || lastAssistant<30 return`) sat
|
|
6604
|
+
// BEFORE the staff_report / task_dispatch_log / conversation_messages
|
|
6605
|
+
// writes, which silently killed every staff dispatch whose output was
|
|
6606
|
+
// shorter than 30 chars (e.g. smoke tests outputting "SMOKE-OK" = 8).
|
|
6607
|
+
// The trivial-skip is now applied just before the brain L1/L2/L3/L4
|
|
6608
|
+
// extraction below — those are noise filters, not bookkeeping.
|
|
6609
|
+
// Bookkeeping (dispatch_log completion, conversation messages,
|
|
6610
|
+
// staff_report) MUST run regardless of message length.
|
|
6594
6611
|
|
|
6595
6612
|
// ── Agent identity resolution (FIX) ──────────────────────────
|
|
6596
6613
|
// Priority: ctx.agentId (from PluginHookAgentContext, the CORRECT source)
|
|
@@ -6776,6 +6793,16 @@ function registerBrainExtractionHook(
|
|
|
6776
6793
|
}
|
|
6777
6794
|
}
|
|
6778
6795
|
|
|
6796
|
+
// Cycle 7b BUGSHOOT-4 — trivial-skip moved here from line ~6593.
|
|
6797
|
+
// Brain L1/L2/L3/L4 extraction skips trivial chit-chat to reduce
|
|
6798
|
+
// memory noise. This MUST sit AFTER staff_report + task_dispatch_log
|
|
6799
|
+
// bookkeeping above, otherwise short-output staff dispatches silently
|
|
6800
|
+
// fail to persist (root cause of cycles 7b BUGSHOOT 1-4).
|
|
6801
|
+
if (lastUser.length < 20 || lastAssistant.length < 30) {
|
|
6802
|
+
api.logger.debug?.(`[ofiere-brain] skip brain extraction (trivial: user=${lastUser.length}c assistant=${lastAssistant.length}c)`);
|
|
6803
|
+
return;
|
|
6804
|
+
}
|
|
6805
|
+
|
|
6779
6806
|
// ── Fast Stream: Write L1_focus + L2_episode in parallel ──
|
|
6780
6807
|
const rawContent = `User: ${lastUser}\nAssistant: ${lastAssistant}`;
|
|
6781
6808
|
const immediateWrites: PromiseLike<any>[] = [];
|