aamp-openclaw-plugin 0.1.31 → 0.1.33

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/dist/index.js CHANGED
@@ -2537,6 +2537,12 @@ var pendingTasks = /* @__PURE__ */ new Map();
2537
2537
  var activeTaskStreams = /* @__PURE__ */ new Map();
2538
2538
  var terminalTaskIds = new Set(loadTaskState(defaultTaskStatePath()).terminalTaskIds ?? []);
2539
2539
  var AAMP_SESSION_PREFIX = "aamp:";
2540
+ var DEFAULT_OPENCLAW_AGENT_ID = "main";
2541
+ var OPENCLAW_AGENT_SESSION_PREFIX = "agent:";
2542
+ var VALID_OPENCLAW_AGENT_ID_RE = /^[a-z0-9][a-z0-9_-]{0,63}$/i;
2543
+ var INVALID_OPENCLAW_AGENT_ID_RE = /[^a-z0-9_-]+/g;
2544
+ var LEADING_DASH_RE = /^-+/;
2545
+ var TRAILING_DASH_RE = /-+$/;
2540
2546
  var dispatchedSubtasks = /* @__PURE__ */ new Map();
2541
2547
  var waitingDispatches = /* @__PURE__ */ new Map();
2542
2548
  var aampClient = null;
@@ -2614,12 +2620,88 @@ function logTransportState(api, mode, email, previousMode) {
2614
2620
  function isSyntheticPendingKey(taskKey) {
2615
2621
  return taskKey.startsWith("result:") || taskKey.startsWith("help:");
2616
2622
  }
2623
+ function isTaskAwaitingHelpReply(task) {
2624
+ return task.awaitingHelpReply === true;
2625
+ }
2626
+ function isActionablePendingTask(taskKey, task) {
2627
+ return !isSyntheticPendingKey(taskKey) && !isTaskAwaitingHelpReply(task);
2628
+ }
2629
+ function normalizeOpenClawAgentId(value) {
2630
+ const trimmed = typeof value === "string" ? value.trim() : "";
2631
+ if (!trimmed)
2632
+ return DEFAULT_OPENCLAW_AGENT_ID;
2633
+ if (VALID_OPENCLAW_AGENT_ID_RE.test(trimmed))
2634
+ return trimmed.toLowerCase();
2635
+ return trimmed.toLowerCase().replace(INVALID_OPENCLAW_AGENT_ID_RE, "-").replace(LEADING_DASH_RE, "").replace(TRAILING_DASH_RE, "").slice(0, 64) || DEFAULT_OPENCLAW_AGENT_ID;
2636
+ }
2637
+ function resolveDefaultOpenClawAgentId(config) {
2638
+ const agents = config?.agents?.list;
2639
+ if (!Array.isArray(agents) || agents.length === 0)
2640
+ return DEFAULT_OPENCLAW_AGENT_ID;
2641
+ const defaults = agents.filter((agent) => agent?.default);
2642
+ return normalizeOpenClawAgentId((defaults[0] ?? agents[0])?.id);
2643
+ }
2644
+ function stripOpenClawAgentScope(sessionKey) {
2645
+ const trimmed = sessionKey.trim();
2646
+ if (!trimmed.toLowerCase().startsWith(OPENCLAW_AGENT_SESSION_PREFIX))
2647
+ return trimmed;
2648
+ const parts = trimmed.split(":");
2649
+ if (parts.length < 3 || parts[0]?.toLowerCase() !== "agent")
2650
+ return trimmed;
2651
+ return parts.slice(2).join(":");
2652
+ }
2617
2653
  function isAampSessionKey(sessionKey) {
2618
- return typeof sessionKey === "string" && sessionKey.startsWith(AAMP_SESSION_PREFIX);
2654
+ return typeof sessionKey === "string" && stripOpenClawAgentScope(sessionKey).toLowerCase().startsWith(AAMP_SESSION_PREFIX);
2655
+ }
2656
+ function buildOpenClawMainSessionKey(mainKey, config) {
2657
+ const trimmed = mainKey.trim();
2658
+ if (!trimmed)
2659
+ return `${OPENCLAW_AGENT_SESSION_PREFIX}${resolveDefaultOpenClawAgentId(config)}:main`;
2660
+ if (trimmed.toLowerCase().startsWith(OPENCLAW_AGENT_SESSION_PREFIX))
2661
+ return trimmed;
2662
+ return `${OPENCLAW_AGENT_SESSION_PREFIX}${resolveDefaultOpenClawAgentId(config)}:${trimmed}`;
2663
+ }
2664
+ function buildAampConversationSessionKey(value, config) {
2665
+ return buildOpenClawMainSessionKey(`${AAMP_SESSION_PREFIX}default:${value}`, config);
2666
+ }
2667
+ function buildAampTaskSessionKey(taskId, config) {
2668
+ return buildAampConversationSessionKey(`task:${taskId}`, config);
2619
2669
  }
2620
2670
  function buildAampWakeSessionKey(kind, id) {
2621
2671
  return `${AAMP_SESSION_PREFIX}wake:${kind}:${id}`;
2622
2672
  }
2673
+ function resolvePendingKeyFromSessionKey(sessionKey) {
2674
+ if (typeof sessionKey !== "string")
2675
+ return void 0;
2676
+ const normalized = stripOpenClawAgentScope(sessionKey).trim();
2677
+ if (!normalized)
2678
+ return void 0;
2679
+ const parts = normalized.split(":");
2680
+ if (parts[0]?.toLowerCase() !== "aamp")
2681
+ return void 0;
2682
+ if (parts[1]?.toLowerCase() === "wake") {
2683
+ const kind = parts[2]?.toLowerCase();
2684
+ const id = parts.slice(3).join(":").trim();
2685
+ if (!id)
2686
+ return void 0;
2687
+ if (kind === "task")
2688
+ return id;
2689
+ if (kind === "result" || kind === "help")
2690
+ return `${kind}:${id}`;
2691
+ return void 0;
2692
+ }
2693
+ if (parts[1]?.toLowerCase() === "default") {
2694
+ const kind = parts[2]?.toLowerCase();
2695
+ const id = parts.slice(3).join(":").trim();
2696
+ if (!id)
2697
+ return void 0;
2698
+ if (kind === "task")
2699
+ return id;
2700
+ if (kind === "result" || kind === "help")
2701
+ return `${kind}:${id}`;
2702
+ }
2703
+ return void 0;
2704
+ }
2623
2705
  function saveTerminalTaskIds() {
2624
2706
  saveTaskState({ terminalTaskIds: [...terminalTaskIds] }, defaultTaskStatePath());
2625
2707
  }
@@ -2662,7 +2744,7 @@ function nextPendingEntry() {
2662
2744
  if (notifications.length > 0) {
2663
2745
  return notifications.sort((a, b) => new Date(a[1].receivedAt).getTime() - new Date(b[1].receivedAt).getTime())[0];
2664
2746
  }
2665
- return entries.filter(([key]) => !key.startsWith("result:") && !key.startsWith("help:")).sort((a, b) => {
2747
+ return entries.filter(([key, task]) => isActionablePendingTask(key, task)).sort((a, b) => {
2666
2748
  const rankDiff = priorityRank(a[1].priority) - priorityRank(b[1].priority);
2667
2749
  if (rankDiff !== 0)
2668
2750
  return rankDiff;
@@ -2856,10 +2938,11 @@ var src_default = {
2856
2938
  }
2857
2939
  function wakeAgentForPendingTask(task) {
2858
2940
  const fallbackSessionKey = buildAampWakeSessionKey("task", task.taskId);
2941
+ const openClawSessionKey = buildAampTaskSessionKey(task.taskId, api.config);
2859
2942
  const fallback = () => triggerHeartbeatWake(fallbackSessionKey, `task ${task.taskId}`);
2860
2943
  const dispatcher = channelRuntime?.reply?.dispatchReplyWithBufferedBlockDispatcher;
2861
2944
  api.logger.info(
2862
- `[AAMP] Wake requested for task ${task.taskId} \u2014 channelRuntime=${channelRuntime ? "yes" : "no"} channelCfg=${channelCfg ? "yes" : "no"} dispatcher=${typeof dispatcher === "function" ? "yes" : "no"} fallbackSession=${fallbackSessionKey}`
2945
+ `[AAMP] Wake requested for task ${task.taskId} \u2014 channelRuntime=${channelRuntime ? "yes" : "no"} channelCfg=${channelCfg ? "yes" : "no"} dispatcher=${typeof dispatcher === "function" ? "yes" : "no"} session=${openClawSessionKey} fallbackSession=${fallbackSessionKey}`
2863
2946
  );
2864
2947
  if (!channelRuntime || !channelCfg || typeof dispatcher !== "function") {
2865
2948
  fallback();
@@ -2879,7 +2962,7 @@ var src_default = {
2879
2962
  BodyForAgent: prompt,
2880
2963
  From: task.from,
2881
2964
  To: agentEmail,
2882
- SessionKey: `aamp:default:task:${task.taskId}`,
2965
+ SessionKey: openClawSessionKey,
2883
2966
  AccountId: "default",
2884
2967
  ChatType: "dm",
2885
2968
  Provider: "aamp",
@@ -3093,7 +3176,7 @@ ${notifyBody?.bodyText ?? "Sub-task completed."}${actionSection}`;
3093
3176
  BodyForAgent: prompt,
3094
3177
  From: result.from,
3095
3178
  To: agentEmail,
3096
- SessionKey: `aamp:default:${result.from}`,
3179
+ SessionKey: buildAampConversationSessionKey(result.from, api.config),
3097
3180
  AccountId: "default",
3098
3181
  ChatType: "dm",
3099
3182
  Provider: "aamp",
@@ -3170,7 +3253,7 @@ ${notifyBody?.bodyText ?? help.question}`;
3170
3253
  BodyForAgent: prompt,
3171
3254
  From: help.from,
3172
3255
  To: agentEmail,
3173
- SessionKey: `aamp:default:${help.from}`,
3256
+ SessionKey: buildAampConversationSessionKey(help.from, api.config),
3174
3257
  AccountId: "default",
3175
3258
  ChatType: "dm",
3176
3259
  Provider: "aamp",
@@ -3376,7 +3459,17 @@ ${notifyBody?.bodyText ?? help.question}`;
3376
3459
  }
3377
3460
  if (pendingTasks.size === 0)
3378
3461
  return {};
3379
- const nextEntry = nextPendingEntry();
3462
+ const targetedPendingKey = resolvePendingKeyFromSessionKey(ctx?.sessionKey);
3463
+ const targetedEntry = targetedPendingKey ? (() => {
3464
+ const targetedTask = pendingTasks.get(targetedPendingKey);
3465
+ if (!targetedTask)
3466
+ return void 0;
3467
+ if (!isSyntheticPendingKey(targetedPendingKey) && isTaskAwaitingHelpReply(targetedTask)) {
3468
+ return void 0;
3469
+ }
3470
+ return [targetedPendingKey, targetedTask];
3471
+ })() : void 0;
3472
+ const nextEntry = targetedPendingKey ? targetedEntry : nextPendingEntry();
3380
3473
  if (!nextEntry)
3381
3474
  return {};
3382
3475
  const [taskKey, task] = nextEntry;
@@ -3384,12 +3477,13 @@ ${notifyBody?.bodyText ?? help.question}`;
3384
3477
  if (isNotification && taskKey) {
3385
3478
  pendingTasks.delete(taskKey);
3386
3479
  }
3387
- const actionableTasks = [...pendingTasks.entries()].filter(([key]) => !key.startsWith("result:") && !key.startsWith("help:")).map(([, t]) => t).sort((a, b) => {
3480
+ const actionableTasks = [...pendingTasks.entries()].filter(([key, pendingTask]) => isActionablePendingTask(key, pendingTask)).map(([, t]) => t).sort((a, b) => {
3388
3481
  const rankDiff = priorityRank(a.priority) - priorityRank(b.priority);
3389
3482
  if (rankDiff !== 0)
3390
3483
  return rankDiff;
3391
3484
  return new Date(a.receivedAt).getTime() - new Date(b.receivedAt).getTime();
3392
3485
  });
3486
+ const otherActionableTasks = actionableTasks.filter((pendingTask) => pendingTask.taskId !== task.taskId);
3393
3487
  const hasAttachmentInfo = isNotification && (task.bodyText?.includes("aamp_download_attachment") ?? false);
3394
3488
  const actionRequiredSection = isNotification && actionableTasks.length > 0 ? [
3395
3489
  ``,
@@ -3423,8 +3517,8 @@ ${notifyBody?.bodyText ?? help.question}`;
3423
3517
  task.bodyText ? `
3424
3518
  ${task.bodyText}` : "",
3425
3519
  actionRequiredSection,
3426
- pendingTasks.size > 1 ? `
3427
- (+${pendingTasks.size - 1} more items queued)` : ""
3520
+ otherActionableTasks.length > 0 ? `
3521
+ (+${otherActionableTasks.length} more tasks queued)` : ""
3428
3522
  ] : [
3429
3523
  `## Pending AAMP Task (action required)`,
3430
3524
  ``,
@@ -3464,8 +3558,8 @@ ${task.bodyText}` : "",
3464
3558
  ${task.contextLinks.map((l) => ` - ${l}`).join("\n")}` : "",
3465
3559
  task.expiresAt ? `Expires: ${task.expiresAt}` : `Expires: none`,
3466
3560
  `Received: ${task.receivedAt}`,
3467
- pendingTasks.size > 1 ? `
3468
- (+${pendingTasks.size - 1} more tasks queued)` : ""
3561
+ otherActionableTasks.length > 0 ? `
3562
+ (+${otherActionableTasks.length} more tasks queued)` : ""
3469
3563
  ].filter(Boolean).join("\n");
3470
3564
  return { prependContext: lines };
3471
3565
  },
@@ -3704,12 +3798,16 @@ ${task.contextLinks.map((l) => ` - ${l}`).join("\n")}` : "",
3704
3798
  suggestedOptions: p.suggestedOptions ?? [],
3705
3799
  inReplyTo: task.messageId || void 0
3706
3800
  });
3801
+ pendingTasks.set(task.taskId, {
3802
+ ...task,
3803
+ awaitingHelpReply: true
3804
+ });
3707
3805
  api.logger.info(`[AAMP] \u2192 task.help_needed ${task.taskId}`);
3708
3806
  return {
3709
3807
  content: [
3710
3808
  {
3711
3809
  type: "text",
3712
- text: `Help request sent for task ${task.taskId}. The task remains pending until the dispatcher replies.`
3810
+ text: `Help request sent for task ${task.taskId}. The task is now suspended until the dispatcher replies.`
3713
3811
  }
3714
3812
  ]
3715
3813
  };
@@ -3729,7 +3827,7 @@ ${task.contextLinks.map((l) => ` - ${l}`).join("\n")}` : "",
3729
3827
  return rankDiff;
3730
3828
  return new Date(a.receivedAt).getTime() - new Date(b.receivedAt).getTime();
3731
3829
  }).map(
3732
- (t, i) => `${i + 1}. [${t.priority}] [${t.taskId}] "${t.title}"${t.bodyText ? `
3830
+ (t, i) => `${i + 1}. [${t.priority}] [${t.taskId}] "${t.title}"${isTaskAwaitingHelpReply(t) ? " (waiting for dispatcher reply)" : ""}${t.bodyText ? `
3733
3831
  Description: ${t.bodyText}` : ""} \u2014 from ${t.from} (received ${t.receivedAt})`
3734
3832
  );
3735
3833
  return {