ofiere-openclaw-plugin 4.54.1 → 4.55.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/README.md +104 -104
- package/dist/src/prompt.js +130 -130
- package/dist/src/staffPersona.js +3 -1
- package/dist/src/tools.js +121 -2
- package/index.ts +105 -105
- package/package.json +12 -2
- package/src/agent-resolver.ts +90 -90
- package/src/agent-tier.ts +192 -192
- package/src/attach-token.ts +106 -106
- package/src/attachments.ts +601 -601
- package/src/cli.ts +247 -247
- package/src/config.ts +78 -78
- package/src/prompt.ts +267 -267
- package/src/sop-render.ts +216 -216
- package/src/staffPersona.ts +299 -289
- package/src/supabase.ts +13 -13
- package/src/tools.ts +122 -2
- package/src/types/openclaw.d.ts +8 -8
- package/src/types.ts +10 -10
package/src/tools.ts
CHANGED
|
@@ -6685,8 +6685,16 @@ function registerOfficeOps(
|
|
|
6685
6685
|
agent_id: { type: "string", description: "Agent identifier (defaults to calling agent)" },
|
|
6686
6686
|
office_id: { type: "string", description: "Office row UUID" },
|
|
6687
6687
|
widget_id: { type: "string", description: "Widget short id" },
|
|
6688
|
-
sections: {
|
|
6689
|
-
|
|
6688
|
+
sections: {
|
|
6689
|
+
type: "array",
|
|
6690
|
+
description: "Initial layout sections (build_office only)",
|
|
6691
|
+
items: { type: "object" },
|
|
6692
|
+
},
|
|
6693
|
+
operations: {
|
|
6694
|
+
type: "array",
|
|
6695
|
+
description: "Patch operations (update_widgets only)",
|
|
6696
|
+
items: { type: "object" },
|
|
6697
|
+
},
|
|
6690
6698
|
data: { type: "object", description: "Widget data payload (update_widget_data only)" },
|
|
6691
6699
|
},
|
|
6692
6700
|
},
|
|
@@ -7387,6 +7395,118 @@ function registerBrainExtractionHook(
|
|
|
7387
7395
|
return;
|
|
7388
7396
|
}
|
|
7389
7397
|
|
|
7398
|
+
// FIX-A2A-LATE-REPLY — direct chief↔chief A2A late reply.
|
|
7399
|
+
// Dashboard's relayToOpenClaw caps the synchronous wait at 45s; when
|
|
7400
|
+
// the responding chief takes longer (e.g. while running its own tool
|
|
7401
|
+
// calls), the dashboard WS closes and the eventual reply is dropped.
|
|
7402
|
+
// dispatch_context was pre-written with { conversation_id,
|
|
7403
|
+
// source_agent_id, a2a_pair_id } so we can route the late reply back:
|
|
7404
|
+
// 1. Insert the assistant turn into conversation_messages for the
|
|
7405
|
+
// A2A conversation so reloading the page shows the reply.
|
|
7406
|
+
// 2. POST a `chief_reply` webhook so the dashboard SSE can swap the
|
|
7407
|
+
// "still processing" placeholder bubble in the active chat UI.
|
|
7408
|
+
// Guarded by: a2a_pair_id is set AND subagent_id is null AND task_id
|
|
7409
|
+
// is null — so neither the staff nor the scheduled branches above
|
|
7410
|
+
// can collide with this path.
|
|
7411
|
+
const a2aPairId = dispatchCtxRow?.a2a_pair_id ?? null;
|
|
7412
|
+
const a2aSourceAgentId = dispatchCtxRow?.source_agent_id ?? null;
|
|
7413
|
+
const a2aConversationId = dispatchCtxRow?.conversation_id ?? null;
|
|
7414
|
+
if (
|
|
7415
|
+
a2aPairId &&
|
|
7416
|
+
!staffDispatchSubagentId &&
|
|
7417
|
+
!dispatchTaskIdFromCtx &&
|
|
7418
|
+
a2aConversationId
|
|
7419
|
+
) {
|
|
7420
|
+
(async () => {
|
|
7421
|
+
try {
|
|
7422
|
+
const excerpt = lastAssistant.slice(0, 4000);
|
|
7423
|
+
if (!excerpt) {
|
|
7424
|
+
api.logger.warn?.(`[ofiere-a2a-reply] empty assistant text — skipping late-reply persistence`);
|
|
7425
|
+
return;
|
|
7426
|
+
}
|
|
7427
|
+
|
|
7428
|
+
// Insert assistant turn into the A2A conversation. The
|
|
7429
|
+
// dashboard's synchronous path also writes the assistant row
|
|
7430
|
+
// when the reply lands in-window — UI dedup is by content +
|
|
7431
|
+
// a2a_conversation_id so a duplicate from a race is benign.
|
|
7432
|
+
try {
|
|
7433
|
+
await supabase.from("conversation_messages").insert({
|
|
7434
|
+
conversation_id: a2aConversationId,
|
|
7435
|
+
user_id: userId,
|
|
7436
|
+
role: "assistant",
|
|
7437
|
+
content: excerpt,
|
|
7438
|
+
metadata: {
|
|
7439
|
+
sender_agent_id: resolvedAgentId,
|
|
7440
|
+
target_agent_id: a2aSourceAgentId,
|
|
7441
|
+
late_reply: true,
|
|
7442
|
+
},
|
|
7443
|
+
branch_id: "main",
|
|
7444
|
+
});
|
|
7445
|
+
await supabase.from("conversations")
|
|
7446
|
+
.update({ updated_at: new Date().toISOString() })
|
|
7447
|
+
.eq("id", a2aConversationId)
|
|
7448
|
+
.eq("user_id", userId);
|
|
7449
|
+
// Best-effort message-count bump. RPC may not exist on older
|
|
7450
|
+
// schemas — swallow the error if it 404s.
|
|
7451
|
+
try {
|
|
7452
|
+
await supabase.rpc("increment_conversation_message_count", {
|
|
7453
|
+
conv_id: a2aConversationId,
|
|
7454
|
+
});
|
|
7455
|
+
} catch { /* RPC missing — count drift is acceptable */ }
|
|
7456
|
+
} catch (cmErr) {
|
|
7457
|
+
api.logger.warn?.(`[ofiere-a2a-reply] conversation_messages insert failed: ${cmErr instanceof Error ? cmErr.message : String(cmErr)}`);
|
|
7458
|
+
}
|
|
7459
|
+
|
|
7460
|
+
// Resolve responder agent name for the webhook payload so the
|
|
7461
|
+
// UI bubble can be attributed correctly without another DB hit.
|
|
7462
|
+
let responderName: string | null = null;
|
|
7463
|
+
try {
|
|
7464
|
+
const { data: agentRow } = await supabase
|
|
7465
|
+
.from("agents")
|
|
7466
|
+
.select("name")
|
|
7467
|
+
.eq("id", resolvedAgentId)
|
|
7468
|
+
.eq("user_id", userId)
|
|
7469
|
+
.maybeSingle();
|
|
7470
|
+
responderName = (agentRow?.name as string | undefined) ?? null;
|
|
7471
|
+
} catch { /* fall back to agent id */ }
|
|
7472
|
+
|
|
7473
|
+
const webhookUrl = process.env.OFIERE_DASHBOARD_WEBHOOK_URL || "";
|
|
7474
|
+
const webhookSecret = process.env.OPENCLAW_WEBHOOK_SECRET || "";
|
|
7475
|
+
if (webhookUrl && webhookSecret) {
|
|
7476
|
+
try {
|
|
7477
|
+
await fetch(webhookUrl, {
|
|
7478
|
+
method: "POST",
|
|
7479
|
+
headers: {
|
|
7480
|
+
"content-type": "application/json",
|
|
7481
|
+
authorization: `Bearer ${webhookSecret}`,
|
|
7482
|
+
},
|
|
7483
|
+
body: JSON.stringify({
|
|
7484
|
+
type: "chief_reply",
|
|
7485
|
+
payload: {
|
|
7486
|
+
user_id: userId,
|
|
7487
|
+
source_agent_id: a2aSourceAgentId,
|
|
7488
|
+
target_agent_id: resolvedAgentId,
|
|
7489
|
+
target_agent_name: responderName,
|
|
7490
|
+
conversation_id: a2aConversationId,
|
|
7491
|
+
a2a_pair_id: a2aPairId,
|
|
7492
|
+
response: excerpt,
|
|
7493
|
+
},
|
|
7494
|
+
}),
|
|
7495
|
+
});
|
|
7496
|
+
api.logger.info?.(`[ofiere-a2a-reply] chief_reply webhook posted (conv=${a2aConversationId})`);
|
|
7497
|
+
} catch (wErr) {
|
|
7498
|
+
api.logger.debug?.(`[ofiere-a2a-reply] webhook post failed: ${wErr instanceof Error ? wErr.message : String(wErr)}`);
|
|
7499
|
+
}
|
|
7500
|
+
}
|
|
7501
|
+
} catch (aErr) {
|
|
7502
|
+
api.logger.warn?.(`[ofiere-a2a-reply] failed: ${aErr instanceof Error ? aErr.message : String(aErr)}`);
|
|
7503
|
+
}
|
|
7504
|
+
})();
|
|
7505
|
+
// Continue to brain extraction below — A2A late-reply is purely
|
|
7506
|
+
// additive bookkeeping; the responding chief still owns the L1/L2
|
|
7507
|
+
// memory writes for its own turn.
|
|
7508
|
+
}
|
|
7509
|
+
|
|
7390
7510
|
// BUG 9 fix (BUGSHOOT-2): mark task_dispatch_log row complete for
|
|
7391
7511
|
// non-staff scheduled dispatches too. Without this the log row stays
|
|
7392
7512
|
// at 'dispatched' even after the chief finished the run.
|
package/src/types/openclaw.d.ts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
// Ambient declaration for the OpenClaw plugin SDK. The gateway resolves this
|
|
2
|
-
// module at runtime; npm has no published types. Keep loose — the plugin only
|
|
3
|
-
// uses a small surface (logger, on, registerTool, registerCommand, etc.).
|
|
4
|
-
|
|
5
|
-
declare module "openclaw/plugin-sdk" {
|
|
6
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
7
|
-
export type OpenClawPluginApi = any;
|
|
8
|
-
}
|
|
1
|
+
// Ambient declaration for the OpenClaw plugin SDK. The gateway resolves this
|
|
2
|
+
// module at runtime; npm has no published types. Keep loose — the plugin only
|
|
3
|
+
// uses a small surface (logger, on, registerTool, registerCommand, etc.).
|
|
4
|
+
|
|
5
|
+
declare module "openclaw/plugin-sdk" {
|
|
6
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
7
|
+
export type OpenClawPluginApi = any;
|
|
8
|
+
}
|
package/src/types.ts
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
export interface OfiereConfig {
|
|
2
|
-
enabled: boolean;
|
|
3
|
-
supabaseUrl: string;
|
|
4
|
-
serviceRoleKey: string;
|
|
5
|
-
userId: string;
|
|
6
|
-
/** Optional — if not set, agent identity is resolved at runtime from OpenClaw context */
|
|
7
|
-
agentId: string;
|
|
8
|
-
/** IANA timezone string for the user (e.g. 'Asia/Jakarta', 'America/New_York'). Default: 'Asia/Jakarta' */
|
|
9
|
-
timezone: string;
|
|
10
|
-
}
|
|
1
|
+
export interface OfiereConfig {
|
|
2
|
+
enabled: boolean;
|
|
3
|
+
supabaseUrl: string;
|
|
4
|
+
serviceRoleKey: string;
|
|
5
|
+
userId: string;
|
|
6
|
+
/** Optional — if not set, agent identity is resolved at runtime from OpenClaw context */
|
|
7
|
+
agentId: string;
|
|
8
|
+
/** IANA timezone string for the user (e.g. 'Asia/Jakarta', 'America/New_York'). Default: 'Asia/Jakarta' */
|
|
9
|
+
timezone: string;
|
|
10
|
+
}
|