openclaw-remote 0.4.0 → 0.4.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.
Files changed (2) hide show
  1. package/dist/index.js +59 -2
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -2800,6 +2800,45 @@ var LEADER_DEBOUNCE_MS = 6e4;
2800
2800
  var leaderRolesCache = [];
2801
2801
  var leaderRolesCacheTime = 0;
2802
2802
  var LEADER_CACHE_TTL = 5 * 6e4;
2803
+ async function resolveAgentIdentity(account, log) {
2804
+ try {
2805
+ const res = await fetch(`${account.baseUrl}/api/v1/roles`, {
2806
+ headers: { Authorization: `Bearer ${account.apiKey}`, Accept: "application/json" },
2807
+ signal: AbortSignal.timeout(1e4)
2808
+ });
2809
+ if (!res.ok) {
2810
+ log?.warn?.(`Failed to resolve agent identity: HTTP ${res.status}`);
2811
+ return null;
2812
+ }
2813
+ const data = await res.json();
2814
+ const roles = data.roles || [];
2815
+ const myRoles = roles.filter((r) => r.is_mine);
2816
+ const myRoleIds = myRoles.map((r) => r.id);
2817
+ const isLeader = myRoles.some((r) => r.is_leader);
2818
+ let agentName = "";
2819
+ for (const r of myRoles) {
2820
+ if (r.assigned_to?.type === "agent" && r.assigned_to?.name) {
2821
+ agentName = r.assigned_to.name;
2822
+ break;
2823
+ }
2824
+ }
2825
+ if (!agentName) {
2826
+ const hbRes = await fetch(`${account.baseUrl}/api/v1/heartbeat`, {
2827
+ headers: { Authorization: `Bearer ${account.apiKey}`, Accept: "application/json" },
2828
+ signal: AbortSignal.timeout(1e4)
2829
+ });
2830
+ if (hbRes.ok) {
2831
+ const hb = await hbRes.json();
2832
+ agentName = hb.agent_name || "";
2833
+ }
2834
+ }
2835
+ log?.info?.(`Agent identity resolved: "${agentName}", roles: [${myRoleIds.join(", ")}], leader: ${isLeader}`);
2836
+ return { agentName, myRoleIds, isLeader };
2837
+ } catch (err) {
2838
+ log?.warn?.(`Failed to resolve agent identity: ${err}`);
2839
+ return null;
2840
+ }
2841
+ }
2803
2842
  async function fetchLeaderRoles(supabase, log) {
2804
2843
  const now = Date.now();
2805
2844
  if (now - leaderRolesCacheTime < LEADER_CACHE_TTL && leaderRolesCache.length > 0) {
@@ -2824,7 +2863,7 @@ async function fetchLeaderRoles(supabase, log) {
2824
2863
  log?.info?.(`Leader roles cache refreshed: ${leaderRolesCache.length} leader role(s)`);
2825
2864
  return leaderRolesCache;
2826
2865
  }
2827
- function connectRealtime(account, onEvent, onError, log) {
2866
+ function connectRealtime(account, identity, onEvent, onError, log) {
2828
2867
  const { supabaseUrl, supabaseKey } = account;
2829
2868
  if (!supabaseUrl || !supabaseKey) {
2830
2869
  throw new Error("Supabase URL and key are required for Realtime listener. Set supabaseUrl and supabaseKey in channels.remote config.");
@@ -2851,12 +2890,28 @@ function connectRealtime(account, onEvent, onError, log) {
2851
2890
  scheduleLeaderNotification(row.task_id, row.agent_author_id, supabase, log);
2852
2891
  return;
2853
2892
  }
2893
+ const body = row.body || row.content || "";
2894
+ if (!row.author_id && !row.agent_author_id && identity) {
2895
+ if (body.startsWith("\u{1F4CC} Assigned to ")) {
2896
+ const targetName = body.replace("\u{1F4CC} Assigned to ", "").trim();
2897
+ if (targetName.toLowerCase() !== identity.agentName.toLowerCase()) {
2898
+ log?.info?.(`Skipping assignment notification for ${targetName} (I am ${identity.agentName})`);
2899
+ return;
2900
+ }
2901
+ }
2902
+ if (body.startsWith("\u{1F440} ")) {
2903
+ if (!identity.isLeader) {
2904
+ log?.info?.(`Skipping leader notification (I am not a leader)`);
2905
+ return;
2906
+ }
2907
+ }
2908
+ }
2854
2909
  const event = {
2855
2910
  type: "task.commented",
2856
2911
  task_id: row.task_id,
2857
2912
  comment: {
2858
2913
  id: row.id,
2859
- content: row.body || row.content || "",
2914
+ content: body,
2860
2915
  author_name: row.author_name || "System",
2861
2916
  author_id: row.author_id || "",
2862
2917
  created_at: row.created_at
@@ -3231,8 +3286,10 @@ function createRemotePlugin() {
3231
3286
  let realtimeHandle = null;
3232
3287
  if (account.supabaseUrl && account.supabaseKey) {
3233
3288
  try {
3289
+ const identity = await resolveAgentIdentity(account, log);
3234
3290
  realtimeHandle = connectRealtime(
3235
3291
  account,
3292
+ identity,
3236
3293
  async (event) => {
3237
3294
  const formatted = formatEvent(event);
3238
3295
  if (!formatted) return;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "openclaw-remote",
3
- "version": "0.4.0",
3
+ "version": "0.4.2",
4
4
  "description": "Remote project board channel plugin for OpenClaw",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",