@alfe.ai/openclaw-chat 0.8.2 → 0.9.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.
package/dist/index.d.cts CHANGED
@@ -1,2 +1,2 @@
1
- import { _ as AlfeResolvedAccount, b as SessionSummary, g as AlfePluginConfig, h as AlfeChannelConfig, m as createAlfeChannelPlugin, u as plugin, v as ChatMessage, y as SessionData } from "./plugin.cjs";
1
+ import { S as SessionSummary, _ as AlfeChannelConfig, b as ChatMessage, f as plugin, g as createAlfeChannelPlugin, v as AlfePluginConfig, x as SessionData, y as AlfeResolvedAccount } from "./plugin.cjs";
2
2
  export { type AlfeChannelConfig, type AlfePluginConfig, type AlfeResolvedAccount, type ChatMessage, type SessionData, type SessionSummary, createAlfeChannelPlugin, plugin as default };
package/dist/index.d.ts CHANGED
@@ -1,2 +1,2 @@
1
- import { _ as AlfeResolvedAccount, b as SessionSummary, g as AlfePluginConfig, h as AlfeChannelConfig, m as createAlfeChannelPlugin, u as plugin, v as ChatMessage, y as SessionData } from "./plugin.js";
1
+ import { S as SessionSummary, _ as AlfeChannelConfig, b as ChatMessage, f as plugin, g as createAlfeChannelPlugin, v as AlfePluginConfig, x as SessionData, y as AlfeResolvedAccount } from "./plugin.js";
2
2
  export { type AlfeChannelConfig, type AlfePluginConfig, type AlfeResolvedAccount, type ChatMessage, type SessionData, type SessionSummary, createAlfeChannelPlugin, plugin as default };
package/dist/index.js CHANGED
@@ -1,2 +1,2 @@
1
- import { c as plugin, f as createAlfeChannelPlugin } from "./plugin2.js";
1
+ import { m as createAlfeChannelPlugin, u as plugin } from "./plugin2.js";
2
2
  export { createAlfeChannelPlugin, plugin as default };
package/dist/plugin.cjs CHANGED
@@ -3,11 +3,13 @@ Object.defineProperties(exports, {
3
3
  [Symbol.toStringTag]: { value: "Module" }
4
4
  });
5
5
  const require_plugin = require("./plugin2.cjs");
6
+ exports.VOICE_REPLY_SYSTEM_PROMPT = require_plugin.VOICE_REPLY_SYSTEM_PROMPT;
6
7
  exports.__agentTurnQueueForTest = require_plugin.__agentTurnQueueForTest;
7
8
  exports.__resetAgentTurnQueueForTest = require_plugin.__resetAgentTurnQueueForTest;
8
9
  exports.__setActiveRunForTest = require_plugin.__setActiveRunForTest;
9
10
  exports.admitAgentEvent = require_plugin.admitAgentEvent;
10
11
  exports.buildA2ACompletePayload = require_plugin.buildA2ACompletePayload;
12
+ exports.buildOriginEnvelopeContext = require_plugin.buildOriginEnvelopeContext;
11
13
  exports.buildToolActivity = require_plugin.buildToolActivity;
12
14
  exports.default = require_plugin.plugin;
13
15
  exports.joinAssistantText = require_plugin.joinAssistantText;
package/dist/plugin.d.cts CHANGED
@@ -597,6 +597,38 @@ declare function __setActiveRunForTest(ref: ActiveRunRef | null): void;
597
597
  * never abort another session's run on a shared daemon.
598
598
  */
599
599
  declare function resolveAbortTargetKeys(active: ActiveRunRef | null, abortSessionKey: string | undefined): string[];
600
+ /**
601
+ * Speech-style reply guidance injected into the agent's SYSTEM PROMPT for a
602
+ * live voice-call turn (`origin:'voice'`). The user is speaking on a call and
603
+ * the reply is read aloud by TTS, so a huge markdown paragraph reads terribly.
604
+ * This biases STYLE only — explicitly NOT a hard cap: it must not suppress tool
605
+ * use or make the agent omit information the user actually needs.
606
+ */
607
+ declare const VOICE_REPLY_SYSTEM_PROMPT: string;
608
+ /**
609
+ * Per-turn envelope context derived from the RPC `origin` flag. For a live
610
+ * voice call it returns a `GroupSystemPrompt` block, which is the PROVEN
611
+ * runtime-rendered seam for per-turn system-prompt guidance: dispatchInbound
612
+ * spreads `extraContext` into `finalizeInboundContext` → `sessionCtx.GroupSystemPrompt`
613
+ * → `extraSystemPrompt` → the model's system prompt (rendered under a
614
+ * "## Group Chat Context" heading; read unconditionally, NOT gated on group
615
+ * chats). Returns `{}` for every other origin, so text/A2A turns are unchanged.
616
+ *
617
+ * Why `GroupSystemPrompt` and not a bespoke key like `A2ASystemPrompt`: the
618
+ * OpenClaw runtime does NOT read arbitrary `extraContext` keys — a custom key
619
+ * only reaches the model if a persona/AGENTS.md template interpolates it, so it
620
+ * silently rots into a dead wire otherwise (the `thinking` param is the
621
+ * cautionary precedent). `GroupSystemPrompt` is verified to reach the system
622
+ * prompt via the runtime itself.
623
+ *
624
+ * Transcript stays clean: this only feeds the model's system prompt for THIS
625
+ * turn. The persisted user message (`addMessage(sessionId, 'user', message)`)
626
+ * and everything `sessions.get` returns are the raw user text — the guidance is
627
+ * never stored or broadcast.
628
+ *
629
+ * Exported pure for unit testing (mirrors the codebase's pure-helper pattern).
630
+ */
631
+ declare function buildOriginEnvelopeContext(origin: string | undefined): Record<string, unknown>;
600
632
  declare const plugin: {
601
633
  id: string;
602
634
  name: string;
@@ -606,4 +638,4 @@ declare const plugin: {
606
638
  deactivate(api: PluginApi): Promise<void>;
607
639
  };
608
640
  //#endregion
609
- export { AlfeResolvedAccount as _, __setActiveRunForTest as a, SessionSummary as b, buildToolActivity as c, resolveAbortTargetKeys as d, rewriteAssistantText as f, AlfePluginConfig as g, AlfeChannelConfig as h, __resetAgentTurnQueueForTest as i, joinAssistantText as l, createAlfeChannelPlugin as m, RunEventGate as n, admitAgentEvent as o, stripLeakedToolSummary as p, __agentTurnQueueForTest as r, buildA2ACompletePayload as s, ActiveRunRef as t, plugin as u, ChatMessage as v, SessionData as y };
641
+ export { SessionSummary as S, AlfeChannelConfig as _, __resetAgentTurnQueueForTest as a, ChatMessage as b, buildA2ACompletePayload as c, joinAssistantText as d, plugin as f, createAlfeChannelPlugin as g, stripLeakedToolSummary as h, __agentTurnQueueForTest as i, buildOriginEnvelopeContext as l, rewriteAssistantText as m, RunEventGate as n, __setActiveRunForTest as o, resolveAbortTargetKeys as p, VOICE_REPLY_SYSTEM_PROMPT as r, admitAgentEvent as s, ActiveRunRef as t, buildToolActivity as u, AlfePluginConfig as v, SessionData as x, AlfeResolvedAccount as y };
package/dist/plugin.d.ts CHANGED
@@ -597,6 +597,38 @@ declare function __setActiveRunForTest(ref: ActiveRunRef | null): void;
597
597
  * never abort another session's run on a shared daemon.
598
598
  */
599
599
  declare function resolveAbortTargetKeys(active: ActiveRunRef | null, abortSessionKey: string | undefined): string[];
600
+ /**
601
+ * Speech-style reply guidance injected into the agent's SYSTEM PROMPT for a
602
+ * live voice-call turn (`origin:'voice'`). The user is speaking on a call and
603
+ * the reply is read aloud by TTS, so a huge markdown paragraph reads terribly.
604
+ * This biases STYLE only — explicitly NOT a hard cap: it must not suppress tool
605
+ * use or make the agent omit information the user actually needs.
606
+ */
607
+ declare const VOICE_REPLY_SYSTEM_PROMPT: string;
608
+ /**
609
+ * Per-turn envelope context derived from the RPC `origin` flag. For a live
610
+ * voice call it returns a `GroupSystemPrompt` block, which is the PROVEN
611
+ * runtime-rendered seam for per-turn system-prompt guidance: dispatchInbound
612
+ * spreads `extraContext` into `finalizeInboundContext` → `sessionCtx.GroupSystemPrompt`
613
+ * → `extraSystemPrompt` → the model's system prompt (rendered under a
614
+ * "## Group Chat Context" heading; read unconditionally, NOT gated on group
615
+ * chats). Returns `{}` for every other origin, so text/A2A turns are unchanged.
616
+ *
617
+ * Why `GroupSystemPrompt` and not a bespoke key like `A2ASystemPrompt`: the
618
+ * OpenClaw runtime does NOT read arbitrary `extraContext` keys — a custom key
619
+ * only reaches the model if a persona/AGENTS.md template interpolates it, so it
620
+ * silently rots into a dead wire otherwise (the `thinking` param is the
621
+ * cautionary precedent). `GroupSystemPrompt` is verified to reach the system
622
+ * prompt via the runtime itself.
623
+ *
624
+ * Transcript stays clean: this only feeds the model's system prompt for THIS
625
+ * turn. The persisted user message (`addMessage(sessionId, 'user', message)`)
626
+ * and everything `sessions.get` returns are the raw user text — the guidance is
627
+ * never stored or broadcast.
628
+ *
629
+ * Exported pure for unit testing (mirrors the codebase's pure-helper pattern).
630
+ */
631
+ declare function buildOriginEnvelopeContext(origin: string | undefined): Record<string, unknown>;
600
632
  declare const plugin: {
601
633
  id: string;
602
634
  name: string;
@@ -606,4 +638,4 @@ declare const plugin: {
606
638
  deactivate(api: PluginApi): Promise<void>;
607
639
  };
608
640
  //#endregion
609
- export { AlfeResolvedAccount as _, __setActiveRunForTest as a, SessionSummary as b, buildToolActivity as c, resolveAbortTargetKeys as d, rewriteAssistantText as f, AlfePluginConfig as g, AlfeChannelConfig as h, __resetAgentTurnQueueForTest as i, joinAssistantText as l, createAlfeChannelPlugin as m, RunEventGate as n, admitAgentEvent as o, stripLeakedToolSummary as p, __agentTurnQueueForTest as r, buildA2ACompletePayload as s, ActiveRunRef as t, plugin as u, ChatMessage as v, SessionData as y };
641
+ export { SessionSummary as S, AlfeChannelConfig as _, __resetAgentTurnQueueForTest as a, ChatMessage as b, buildA2ACompletePayload as c, joinAssistantText as d, plugin as f, createAlfeChannelPlugin as g, stripLeakedToolSummary as h, __agentTurnQueueForTest as i, buildOriginEnvelopeContext as l, rewriteAssistantText as m, RunEventGate as n, __setActiveRunForTest as o, resolveAbortTargetKeys as p, VOICE_REPLY_SYSTEM_PROMPT as r, admitAgentEvent as s, ActiveRunRef as t, buildToolActivity as u, AlfePluginConfig as v, SessionData as x, AlfeResolvedAccount as y };
package/dist/plugin.js CHANGED
@@ -1,2 +1,2 @@
1
- import { a as buildA2ACompletePayload, c as plugin, d as stripLeakedToolSummary, i as admitAgentEvent, l as resolveAbortTargetKeys, n as __resetAgentTurnQueueForTest, o as buildToolActivity, r as __setActiveRunForTest, s as joinAssistantText, t as __agentTurnQueueForTest, u as rewriteAssistantText } from "./plugin2.js";
2
- export { __agentTurnQueueForTest, __resetAgentTurnQueueForTest, __setActiveRunForTest, admitAgentEvent, buildA2ACompletePayload, buildToolActivity, plugin as default, joinAssistantText, resolveAbortTargetKeys, rewriteAssistantText, stripLeakedToolSummary };
1
+ import { a as admitAgentEvent, c as buildToolActivity, d as resolveAbortTargetKeys, f as rewriteAssistantText, i as __setActiveRunForTest, l as joinAssistantText, n as __agentTurnQueueForTest, o as buildA2ACompletePayload, p as stripLeakedToolSummary, r as __resetAgentTurnQueueForTest, s as buildOriginEnvelopeContext, t as VOICE_REPLY_SYSTEM_PROMPT, u as plugin } from "./plugin2.js";
2
+ export { VOICE_REPLY_SYSTEM_PROMPT, __agentTurnQueueForTest, __resetAgentTurnQueueForTest, __setActiveRunForTest, admitAgentEvent, buildA2ACompletePayload, buildOriginEnvelopeContext, buildToolActivity, plugin as default, joinAssistantText, resolveAbortTargetKeys, rewriteAssistantText, stripLeakedToolSummary };
package/dist/plugin2.cjs CHANGED
@@ -2288,6 +2288,48 @@ function handleChatAbort(request, log) {
2288
2288
  } else log.warn("chat.abort: OpenClaw abort primitives unavailable — cannot hard-abort the running turn");
2289
2289
  chatClient?.sendResponse(request.id, true, { aborted });
2290
2290
  }
2291
+ /**
2292
+ * Speech-style reply guidance injected into the agent's SYSTEM PROMPT for a
2293
+ * live voice-call turn (`origin:'voice'`). The user is speaking on a call and
2294
+ * the reply is read aloud by TTS, so a huge markdown paragraph reads terribly.
2295
+ * This biases STYLE only — explicitly NOT a hard cap: it must not suppress tool
2296
+ * use or make the agent omit information the user actually needs.
2297
+ */
2298
+ const VOICE_REPLY_SYSTEM_PROMPT = [
2299
+ "This message arrived over a LIVE VOICE CALL — your reply is read aloud by text-to-speech.",
2300
+ "Speak the way a helpful person would on a phone call:",
2301
+ "- Keep it brief and conversational — usually 1-3 short sentences.",
2302
+ "- Plain spoken language only: no markdown, no bullet or numbered lists, no headings, no code blocks, no URLs or link syntax.",
2303
+ "- If the full answer is long or detailed, give the short spoken version and offer to send the details to the chat.",
2304
+ "This is guidance on speaking STYLE only. Do NOT skip tool calls you would otherwise make, and never omit information the user actually needs — just deliver it the way you would say it out loud."
2305
+ ].join("\n");
2306
+ /**
2307
+ * Per-turn envelope context derived from the RPC `origin` flag. For a live
2308
+ * voice call it returns a `GroupSystemPrompt` block, which is the PROVEN
2309
+ * runtime-rendered seam for per-turn system-prompt guidance: dispatchInbound
2310
+ * spreads `extraContext` into `finalizeInboundContext` → `sessionCtx.GroupSystemPrompt`
2311
+ * → `extraSystemPrompt` → the model's system prompt (rendered under a
2312
+ * "## Group Chat Context" heading; read unconditionally, NOT gated on group
2313
+ * chats). Returns `{}` for every other origin, so text/A2A turns are unchanged.
2314
+ *
2315
+ * Why `GroupSystemPrompt` and not a bespoke key like `A2ASystemPrompt`: the
2316
+ * OpenClaw runtime does NOT read arbitrary `extraContext` keys — a custom key
2317
+ * only reaches the model if a persona/AGENTS.md template interpolates it, so it
2318
+ * silently rots into a dead wire otherwise (the `thinking` param is the
2319
+ * cautionary precedent). `GroupSystemPrompt` is verified to reach the system
2320
+ * prompt via the runtime itself.
2321
+ *
2322
+ * Transcript stays clean: this only feeds the model's system prompt for THIS
2323
+ * turn. The persisted user message (`addMessage(sessionId, 'user', message)`)
2324
+ * and everything `sessions.get` returns are the raw user text — the guidance is
2325
+ * never stored or broadcast.
2326
+ *
2327
+ * Exported pure for unit testing (mirrors the codebase's pure-helper pattern).
2328
+ */
2329
+ function buildOriginEnvelopeContext(origin) {
2330
+ if (origin === "voice") return { GroupSystemPrompt: VOICE_REPLY_SYSTEM_PROMPT };
2331
+ return {};
2332
+ }
2291
2333
  async function handleAgentRequest(request, log) {
2292
2334
  const runtime = pluginRuntime;
2293
2335
  if (!runtime) {
@@ -2298,7 +2340,7 @@ async function handleAgentRequest(request, log) {
2298
2340
  chatClient?.sendResponse(request.id, false, { message: "OpenClaw SDK not available — cannot dispatch" });
2299
2341
  return;
2300
2342
  }
2301
- const { message, sessionKey: legacySessionKey, userId, conversationId, conversationType, tenantId, clientType, displayName, identityId, senderPermissions, attachments: rawAttachments, a2a, chatMessageId } = request.params;
2343
+ const { message, sessionKey: legacySessionKey, userId, conversationId, conversationType, tenantId, clientType, origin, displayName, identityId, senderPermissions, attachments: rawAttachments, a2a, chatMessageId } = request.params;
2302
2344
  const isA2A = !!a2a;
2303
2345
  if (!message && !rawAttachments?.length) {
2304
2346
  chatClient?.sendResponse(request.id, false, { message: "Missing message" });
@@ -2520,6 +2562,7 @@ async function handleAgentRequest(request, log) {
2520
2562
  ...userId ? { UserId: userId } : {},
2521
2563
  ...senderPermissions?.length ? { SenderPermissions: senderPermissions } : {},
2522
2564
  ChannelMode: channelMode,
2565
+ ...buildOriginEnvelopeContext(origin),
2523
2566
  ...isA2A ? {
2524
2567
  CallerType: "agent",
2525
2568
  CallerAgentId: a2a.sourceAgentId,
@@ -2869,6 +2912,12 @@ const plugin = {
2869
2912
  }
2870
2913
  };
2871
2914
  //#endregion
2915
+ Object.defineProperty(exports, "VOICE_REPLY_SYSTEM_PROMPT", {
2916
+ enumerable: true,
2917
+ get: function() {
2918
+ return VOICE_REPLY_SYSTEM_PROMPT;
2919
+ }
2920
+ });
2872
2921
  Object.defineProperty(exports, "__agentTurnQueueForTest", {
2873
2922
  enumerable: true,
2874
2923
  get: function() {
@@ -2899,6 +2948,12 @@ Object.defineProperty(exports, "buildA2ACompletePayload", {
2899
2948
  return buildA2ACompletePayload;
2900
2949
  }
2901
2950
  });
2951
+ Object.defineProperty(exports, "buildOriginEnvelopeContext", {
2952
+ enumerable: true,
2953
+ get: function() {
2954
+ return buildOriginEnvelopeContext;
2955
+ }
2956
+ });
2902
2957
  Object.defineProperty(exports, "buildToolActivity", {
2903
2958
  enumerable: true,
2904
2959
  get: function() {
@@ -1,2 +1,2 @@
1
- import { a as __setActiveRunForTest, c as buildToolActivity, d as resolveAbortTargetKeys, f as rewriteAssistantText, i as __resetAgentTurnQueueForTest, l as joinAssistantText, n as RunEventGate, o as admitAgentEvent, p as stripLeakedToolSummary, r as __agentTurnQueueForTest, s as buildA2ACompletePayload, t as ActiveRunRef, u as plugin } from "./plugin.cjs";
2
- export { ActiveRunRef, RunEventGate, __agentTurnQueueForTest, __resetAgentTurnQueueForTest, __setActiveRunForTest, admitAgentEvent, buildA2ACompletePayload, buildToolActivity, plugin as default, joinAssistantText, resolveAbortTargetKeys, rewriteAssistantText, stripLeakedToolSummary };
1
+ import { a as __resetAgentTurnQueueForTest, c as buildA2ACompletePayload, d as joinAssistantText, f as plugin, h as stripLeakedToolSummary, i as __agentTurnQueueForTest, l as buildOriginEnvelopeContext, m as rewriteAssistantText, n as RunEventGate, o as __setActiveRunForTest, p as resolveAbortTargetKeys, r as VOICE_REPLY_SYSTEM_PROMPT, s as admitAgentEvent, t as ActiveRunRef, u as buildToolActivity } from "./plugin.cjs";
2
+ export { ActiveRunRef, RunEventGate, VOICE_REPLY_SYSTEM_PROMPT, __agentTurnQueueForTest, __resetAgentTurnQueueForTest, __setActiveRunForTest, admitAgentEvent, buildA2ACompletePayload, buildOriginEnvelopeContext, buildToolActivity, plugin as default, joinAssistantText, resolveAbortTargetKeys, rewriteAssistantText, stripLeakedToolSummary };
package/dist/plugin2.d.ts CHANGED
@@ -1,2 +1,2 @@
1
- import { a as __setActiveRunForTest, c as buildToolActivity, d as resolveAbortTargetKeys, f as rewriteAssistantText, i as __resetAgentTurnQueueForTest, l as joinAssistantText, n as RunEventGate, o as admitAgentEvent, p as stripLeakedToolSummary, r as __agentTurnQueueForTest, s as buildA2ACompletePayload, t as ActiveRunRef, u as plugin } from "./plugin.js";
2
- export { ActiveRunRef, RunEventGate, __agentTurnQueueForTest, __resetAgentTurnQueueForTest, __setActiveRunForTest, admitAgentEvent, buildA2ACompletePayload, buildToolActivity, plugin as default, joinAssistantText, resolveAbortTargetKeys, rewriteAssistantText, stripLeakedToolSummary };
1
+ import { a as __resetAgentTurnQueueForTest, c as buildA2ACompletePayload, d as joinAssistantText, f as plugin, h as stripLeakedToolSummary, i as __agentTurnQueueForTest, l as buildOriginEnvelopeContext, m as rewriteAssistantText, n as RunEventGate, o as __setActiveRunForTest, p as resolveAbortTargetKeys, r as VOICE_REPLY_SYSTEM_PROMPT, s as admitAgentEvent, t as ActiveRunRef, u as buildToolActivity } from "./plugin.js";
2
+ export { ActiveRunRef, RunEventGate, VOICE_REPLY_SYSTEM_PROMPT, __agentTurnQueueForTest, __resetAgentTurnQueueForTest, __setActiveRunForTest, admitAgentEvent, buildA2ACompletePayload, buildOriginEnvelopeContext, buildToolActivity, plugin as default, joinAssistantText, resolveAbortTargetKeys, rewriteAssistantText, stripLeakedToolSummary };
package/dist/plugin2.js CHANGED
@@ -2288,6 +2288,48 @@ function handleChatAbort(request, log) {
2288
2288
  } else log.warn("chat.abort: OpenClaw abort primitives unavailable — cannot hard-abort the running turn");
2289
2289
  chatClient?.sendResponse(request.id, true, { aborted });
2290
2290
  }
2291
+ /**
2292
+ * Speech-style reply guidance injected into the agent's SYSTEM PROMPT for a
2293
+ * live voice-call turn (`origin:'voice'`). The user is speaking on a call and
2294
+ * the reply is read aloud by TTS, so a huge markdown paragraph reads terribly.
2295
+ * This biases STYLE only — explicitly NOT a hard cap: it must not suppress tool
2296
+ * use or make the agent omit information the user actually needs.
2297
+ */
2298
+ const VOICE_REPLY_SYSTEM_PROMPT = [
2299
+ "This message arrived over a LIVE VOICE CALL — your reply is read aloud by text-to-speech.",
2300
+ "Speak the way a helpful person would on a phone call:",
2301
+ "- Keep it brief and conversational — usually 1-3 short sentences.",
2302
+ "- Plain spoken language only: no markdown, no bullet or numbered lists, no headings, no code blocks, no URLs or link syntax.",
2303
+ "- If the full answer is long or detailed, give the short spoken version and offer to send the details to the chat.",
2304
+ "This is guidance on speaking STYLE only. Do NOT skip tool calls you would otherwise make, and never omit information the user actually needs — just deliver it the way you would say it out loud."
2305
+ ].join("\n");
2306
+ /**
2307
+ * Per-turn envelope context derived from the RPC `origin` flag. For a live
2308
+ * voice call it returns a `GroupSystemPrompt` block, which is the PROVEN
2309
+ * runtime-rendered seam for per-turn system-prompt guidance: dispatchInbound
2310
+ * spreads `extraContext` into `finalizeInboundContext` → `sessionCtx.GroupSystemPrompt`
2311
+ * → `extraSystemPrompt` → the model's system prompt (rendered under a
2312
+ * "## Group Chat Context" heading; read unconditionally, NOT gated on group
2313
+ * chats). Returns `{}` for every other origin, so text/A2A turns are unchanged.
2314
+ *
2315
+ * Why `GroupSystemPrompt` and not a bespoke key like `A2ASystemPrompt`: the
2316
+ * OpenClaw runtime does NOT read arbitrary `extraContext` keys — a custom key
2317
+ * only reaches the model if a persona/AGENTS.md template interpolates it, so it
2318
+ * silently rots into a dead wire otherwise (the `thinking` param is the
2319
+ * cautionary precedent). `GroupSystemPrompt` is verified to reach the system
2320
+ * prompt via the runtime itself.
2321
+ *
2322
+ * Transcript stays clean: this only feeds the model's system prompt for THIS
2323
+ * turn. The persisted user message (`addMessage(sessionId, 'user', message)`)
2324
+ * and everything `sessions.get` returns are the raw user text — the guidance is
2325
+ * never stored or broadcast.
2326
+ *
2327
+ * Exported pure for unit testing (mirrors the codebase's pure-helper pattern).
2328
+ */
2329
+ function buildOriginEnvelopeContext(origin) {
2330
+ if (origin === "voice") return { GroupSystemPrompt: VOICE_REPLY_SYSTEM_PROMPT };
2331
+ return {};
2332
+ }
2291
2333
  async function handleAgentRequest(request, log) {
2292
2334
  const runtime = pluginRuntime;
2293
2335
  if (!runtime) {
@@ -2298,7 +2340,7 @@ async function handleAgentRequest(request, log) {
2298
2340
  chatClient?.sendResponse(request.id, false, { message: "OpenClaw SDK not available — cannot dispatch" });
2299
2341
  return;
2300
2342
  }
2301
- const { message, sessionKey: legacySessionKey, userId, conversationId, conversationType, tenantId, clientType, displayName, identityId, senderPermissions, attachments: rawAttachments, a2a, chatMessageId } = request.params;
2343
+ const { message, sessionKey: legacySessionKey, userId, conversationId, conversationType, tenantId, clientType, origin, displayName, identityId, senderPermissions, attachments: rawAttachments, a2a, chatMessageId } = request.params;
2302
2344
  const isA2A = !!a2a;
2303
2345
  if (!message && !rawAttachments?.length) {
2304
2346
  chatClient?.sendResponse(request.id, false, { message: "Missing message" });
@@ -2520,6 +2562,7 @@ async function handleAgentRequest(request, log) {
2520
2562
  ...userId ? { UserId: userId } : {},
2521
2563
  ...senderPermissions?.length ? { SenderPermissions: senderPermissions } : {},
2522
2564
  ChannelMode: channelMode,
2565
+ ...buildOriginEnvelopeContext(origin),
2523
2566
  ...isA2A ? {
2524
2567
  CallerType: "agent",
2525
2568
  CallerAgentId: a2a.sourceAgentId,
@@ -2869,4 +2912,4 @@ const plugin = {
2869
2912
  }
2870
2913
  };
2871
2914
  //#endregion
2872
- export { buildA2ACompletePayload as a, plugin as c, stripLeakedToolSummary as d, createAlfeChannelPlugin as f, admitAgentEvent as i, resolveAbortTargetKeys as l, __resetAgentTurnQueueForTest as n, buildToolActivity as o, __setActiveRunForTest as r, joinAssistantText as s, __agentTurnQueueForTest as t, rewriteAssistantText as u };
2915
+ export { admitAgentEvent as a, buildToolActivity as c, resolveAbortTargetKeys as d, rewriteAssistantText as f, __setActiveRunForTest as i, joinAssistantText as l, createAlfeChannelPlugin as m, __agentTurnQueueForTest as n, buildA2ACompletePayload as o, stripLeakedToolSummary as p, __resetAgentTurnQueueForTest as r, buildOriginEnvelopeContext as s, VOICE_REPLY_SYSTEM_PROMPT as t, plugin as u };
@@ -26,6 +26,6 @@
26
26
  }
27
27
  },
28
28
  "contracts": {
29
- "tools": ["list_agents", "message_agent", "end_conversation"]
29
+ "tools": ["list_agents", "message_agent", "end_conversation", "chat_present_components"]
30
30
  }
31
31
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@alfe.ai/openclaw-chat",
3
- "version": "0.8.2",
3
+ "version": "0.9.1",
4
4
  "description": "OpenClaw chat plugin for Alfe — web widget and mobile app channels",
5
5
  "type": "module",
6
6
  "main": "./dist/plugin.js",
@@ -28,8 +28,8 @@
28
28
  ],
29
29
  "dependencies": {
30
30
  "@alfe.ai/agent-api-client": "^0.8.0",
31
- "@alfe.ai/config": "^0.3.0",
32
- "@alfe.ai/chat": "^0.0.14"
31
+ "@alfe.ai/chat": "^0.0.15",
32
+ "@alfe.ai/config": "^0.3.0"
33
33
  },
34
34
  "peerDependencies": {
35
35
  "openclaw": ">=2026.3.0"