@helmio/openclaw-helmio-chat 0.1.2 → 0.1.3

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.
@@ -1,4 +1,5 @@
1
- import type { PluginApi, PluginLogger } from "openclaw/plugin-sdk/plugin-entry";
1
+ import type { OpenClawPluginToolFactory, PluginApi, PluginLogger } from "openclaw/plugin-sdk/plugin-entry";
2
+ export declare const HELMIO_CHAT_SEND_TOOL_NAME = "helmio_chat_send";
2
3
  export interface ChatSendToolOptions {
3
4
  helmioApiUrl: string;
4
5
  bridgeToken: string;
@@ -11,4 +12,10 @@ export interface ChatSendResult {
11
12
  messageId: number;
12
13
  deduplicated?: true;
13
14
  }
15
+ export declare function buildChatSendToolFactory(opts: ChatSendToolOptions): OpenClawPluginToolFactory;
16
+ export declare function executeChatSend(ctx: {
17
+ agentId?: string;
18
+ }, args: {
19
+ body: string;
20
+ }, opts: ChatSendToolOptions): Promise<ChatSendResult>;
14
21
  export declare function registerChatSendTool(api: PluginApi, opts: ChatSendToolOptions): void;
@@ -1,7 +1,7 @@
1
- // Outbound chat-send tool. Registered once globally; the runtime passes the
2
- // calling agent's id in the tool execute context, which we parse as the
3
- // Helmio Agent.Id (CanonicalAgentList.Build sets openclaw agent id =
4
- // Agent.Id.ToString()).
1
+ // Outbound chat-send tool. Registered as a FACTORY so the runtime injects
2
+ // ctx.agentId at tool-resolve time (closure captures it for the POST). The
3
+ // agentId is parsed as the Helmio Agent.Id (CanonicalAgentList.Build sets the
4
+ // openclaw agent id = Agent.Id.ToString()).
5
5
  //
6
6
  // Wire format matches ChatMessagesController.cs InboundMessageRequest:
7
7
  // { clientMsgId, agentId, conversationKindCode: 1, body }
@@ -11,6 +11,7 @@ import { ulid } from "ulid";
11
11
  import { ConversationKind } from "./events.js";
12
12
  import { parseHelmioAgentId } from "./agent-resolver.js";
13
13
  import { trimTrailingSlash } from "./url.js";
14
+ export const HELMIO_CHAT_SEND_TOOL_NAME = "helmio_chat_send";
14
15
  class ChatHttpError extends Error {
15
16
  status;
16
17
  constructor(status, body) {
@@ -23,12 +24,13 @@ class ChatHttpError extends Error {
23
24
  }
24
25
  const MAX_RETRIES = 3;
25
26
  const BASE_BACKOFF_MS = 250;
26
- export function registerChatSendTool(api, opts) {
27
+ export function buildChatSendToolFactory(opts) {
27
28
  const fetchFn = opts.fetchFn ?? globalThis.fetch;
28
29
  const newId = opts.idFactory ?? ulid;
29
30
  const endpoint = `${trimTrailingSlash(opts.helmioApiUrl)}/api/chat/messages`;
30
- api.registerTool({
31
- name: "helmio_chat_send",
31
+ return (ctx) => ({
32
+ label: "Chat: Send",
33
+ name: HELMIO_CHAT_SEND_TOOL_NAME,
32
34
  description: "Send a message to the Company's Team conversation. The message appears to all participants (the Company owner and every active agent). Use this to reply to user messages.",
33
35
  parameters: {
34
36
  type: "object",
@@ -41,24 +43,65 @@ export function registerChatSendTool(api, opts) {
41
43
  required: ["body"],
42
44
  additionalProperties: false,
43
45
  },
44
- async execute(args, ctx) {
45
- const helmioAgentId = parseHelmioAgentId(ctx.agentId);
46
- if (helmioAgentId === null) {
47
- throw new Error(`helmio_chat_send: cannot derive Helmio agent id from openclaw agentId=${ctx.agentId}`);
48
- }
49
- if (!args.body || args.body.trim().length === 0) {
46
+ async execute(_toolCallId, params) {
47
+ const body = readBody(params);
48
+ if (body === null) {
50
49
  throw new Error("helmio_chat_send: body must be non-empty");
51
50
  }
51
+ const helmioAgentId = parseHelmioAgentId(ctx.agentId ?? "");
52
+ if (helmioAgentId === null) {
53
+ throw new Error(`helmio_chat_send: cannot derive Helmio agent id from openclaw agentId=${ctx.agentId ?? "<none>"}`);
54
+ }
52
55
  const payload = {
53
56
  clientMsgId: newId(),
54
57
  agentId: helmioAgentId,
55
58
  conversationKindCode: ConversationKind.TeamDefault,
56
- body: args.body,
59
+ body,
57
60
  };
58
- return await postWithRetry(fetchFn, endpoint, opts.bridgeToken, payload, opts.logger);
61
+ const send = await postWithRetry(fetchFn, endpoint, opts.bridgeToken, payload, opts.logger);
62
+ return toolResult(send);
59
63
  },
60
64
  });
61
65
  }
66
+ // Internal: returns the typed POST result for tests / non-tool callers.
67
+ export async function executeChatSend(ctx, args, opts) {
68
+ const fetchFn = opts.fetchFn ?? globalThis.fetch;
69
+ const newId = opts.idFactory ?? ulid;
70
+ const endpoint = `${trimTrailingSlash(opts.helmioApiUrl)}/api/chat/messages`;
71
+ if (!args.body || args.body.trim().length === 0) {
72
+ throw new Error("helmio_chat_send: body must be non-empty");
73
+ }
74
+ const helmioAgentId = parseHelmioAgentId(ctx.agentId ?? "");
75
+ if (helmioAgentId === null) {
76
+ throw new Error(`helmio_chat_send: cannot derive Helmio agent id from openclaw agentId=${ctx.agentId ?? "<none>"}`);
77
+ }
78
+ const payload = {
79
+ clientMsgId: newId(),
80
+ agentId: helmioAgentId,
81
+ conversationKindCode: ConversationKind.TeamDefault,
82
+ body: args.body,
83
+ };
84
+ return await postWithRetry(fetchFn, endpoint, opts.bridgeToken, payload, opts.logger);
85
+ }
86
+ export function registerChatSendTool(api, opts) {
87
+ const factory = buildChatSendToolFactory(opts);
88
+ api.registerTool(factory, { name: HELMIO_CHAT_SEND_TOOL_NAME });
89
+ }
90
+ function readBody(params) {
91
+ if (!params || typeof params !== "object")
92
+ return null;
93
+ const body = params.body;
94
+ if (typeof body !== "string" || body.trim().length === 0)
95
+ return null;
96
+ return body;
97
+ }
98
+ function toolResult(send) {
99
+ const tail = send.deduplicated ? " (deduplicated)" : "";
100
+ return {
101
+ content: [{ type: "text", text: `Sent (messageId=${send.messageId})${tail}` }],
102
+ details: send,
103
+ };
104
+ }
62
105
  async function postWithRetry(fetchFn, endpoint, bridgeToken, payload, logger) {
63
106
  const body = JSON.stringify(payload);
64
107
  const init = {
@@ -1 +1 @@
1
- {"version":3,"file":"chat-send-tool.js","sourceRoot":"","sources":["../src/chat-send-tool.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"chat-send-tool.js","sourceRoot":"","sources":["../src/chat-send-tool.ts"],"names":[],"mappings":"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"}
@@ -6,4 +6,6 @@ export interface InboundRouterDeps {
6
6
  logger: PluginLogger;
7
7
  ceo: ResolvedAgent | undefined;
8
8
  }
9
- export declare function routeInbound(msg: ChatMessageDto, deps: InboundRouterDeps): Promise<"dispatched" | "ignored-agent" | "ignored-no-ceo">;
9
+ export type InboundVerdict = "dispatched" | "ignored-agent" | "ignored-no-ceo" | "ignored-no-runtime";
10
+ export declare function routeInbound(msg: ChatMessageDto, deps: InboundRouterDeps): Promise<InboundVerdict>;
11
+ export declare function buildAgentMainSessionKey(openclawAgentId: string): string;
@@ -1,11 +1,15 @@
1
1
  // Routes inbound chat messages to agents. Phase 1: CEO-only — every
2
2
  // user-typed message in the Team conversation dispatches a turn to the
3
- // CEO agent. Agent-typed messages (participantTypeId === 2) are dropped
4
- // to prevent self-loops (the CEO's own outbound reply is broadcast back
5
- // to the plugin's connection).
3
+ // CEO agent via runtime.subagent.run(). Agent-typed messages
4
+ // (participantTypeId === 2) are dropped to prevent self-loops (the CEO's
5
+ // own outbound reply is broadcast back to the plugin's connection).
6
+ //
7
+ // The agent processes the message inside its main session and emits the
8
+ // reply by calling the registered `helmio_chat_send` tool — no channel
9
+ // kernel involvement needed for phase 1.
6
10
  //
7
11
  // Phase 2 will replace this with @mention parsing + AgentRouteBinding[]
8
- // fan-out per ADR-0008 probe C3 findings.
12
+ // fan-out per ADR-0008 probe C3 findings (runtime.channel.turn.run path).
9
13
  import { ParticipantType } from "./events.js";
10
14
  export async function routeInbound(msg, deps) {
11
15
  if (msg.participantTypeId !== ParticipantType.User) {
@@ -15,15 +19,27 @@ export async function routeInbound(msg, deps) {
15
19
  deps.logger.warn(`helmio-chat: dropped messageId=${msg.id} — no CEO agent found in runtime config`);
16
20
  return "ignored-no-ceo";
17
21
  }
18
- await deps.runtime.channel.turn.run({
19
- agentId: deps.ceo.openclawAgentId,
20
- conversationId: String(msg.conversationId),
21
- input: {
22
- body: msg.body,
23
- senderId: String(msg.senderId),
24
- senderType: "user",
25
- },
22
+ const subagent = deps.runtime?.subagent;
23
+ if (!subagent || typeof subagent.run !== "function") {
24
+ deps.logger.warn(`helmio-chat: messageId=${msg.id} not dispatched — runtime.subagent.run unavailable`);
25
+ return "ignored-no-runtime";
26
+ }
27
+ const sessionKey = buildAgentMainSessionKey(deps.ceo.openclawAgentId);
28
+ await subagent.run({
29
+ sessionKey,
30
+ message: msg.body,
31
+ // idempotencyKey suppresses duplicate dispatches if the same SignalR
32
+ // event fires twice (server-reconnect replay). Helmio's MessageId is
33
+ // globally unique per Company DB.
34
+ idempotencyKey: `helmio-chat:msg:${msg.id}`,
26
35
  });
27
36
  return "dispatched";
28
37
  }
38
+ // Mirrors openclaw/src/config/sessions/main-session.ts buildMainSessionKey:
39
+ // `agent:${normalizeAgentId(agentId)}:${normalizeMainKey(mainKey)}`
40
+ // Default mainKey is "main". OpenClaw normalizes agentId lowercase + trims.
41
+ export function buildAgentMainSessionKey(openclawAgentId) {
42
+ const normalized = openclawAgentId.trim().toLowerCase();
43
+ return `agent:${normalized}:main`;
44
+ }
29
45
  //# sourceMappingURL=inbound-router.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"inbound-router.js","sourceRoot":"","sources":["../src/inbound-router.ts"],"names":[],"mappings":"AAAA,oEAAoE;AACpE,uEAAuE;AACvE,wEAAwE;AACxE,wEAAwE;AACxE,+BAA+B;AAC/B,EAAE;AACF,wEAAwE;AACxE,0CAA0C;AAE1C,OAAO,EAAuB,eAAe,EAAE,MAAM,aAAa,CAAC;AAUnE,MAAM,CAAC,KAAK,UAAU,YAAY,CAChC,GAAmB,EACnB,IAAuB;IAEvB,IAAI,GAAG,CAAC,iBAAiB,KAAK,eAAe,CAAC,IAAI,EAAE,CAAC;QACnD,OAAO,eAAe,CAAC;IACzB,CAAC;IACD,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC;QACd,IAAI,CAAC,MAAM,CAAC,IAAI,CACd,kCAAkC,GAAG,CAAC,EAAE,yCAAyC,CAClF,CAAC;QACF,OAAO,gBAAgB,CAAC;IAC1B,CAAC;IACD,MAAM,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC;QAClC,OAAO,EAAE,IAAI,CAAC,GAAG,CAAC,eAAe;QACjC,cAAc,EAAE,MAAM,CAAC,GAAG,CAAC,cAAc,CAAC;QAC1C,KAAK,EAAE;YACL,IAAI,EAAE,GAAG,CAAC,IAAI;YACd,QAAQ,EAAE,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAC;YAC9B,UAAU,EAAE,MAAM;SACnB;KACF,CAAC,CAAC;IACH,OAAO,YAAY,CAAC;AACtB,CAAC"}
1
+ {"version":3,"file":"inbound-router.js","sourceRoot":"","sources":["../src/inbound-router.ts"],"names":[],"mappings":"AAAA,oEAAoE;AACpE,uEAAuE;AACvE,6DAA6D;AAC7D,yEAAyE;AACzE,oEAAoE;AACpE,EAAE;AACF,wEAAwE;AACxE,uEAAuE;AACvE,yCAAyC;AACzC,EAAE;AACF,wEAAwE;AACxE,0EAA0E;AAE1E,OAAO,EAAuB,eAAe,EAAE,MAAM,aAAa,CAAC;AAgBnE,MAAM,CAAC,KAAK,UAAU,YAAY,CAChC,GAAmB,EACnB,IAAuB;IAEvB,IAAI,GAAG,CAAC,iBAAiB,KAAK,eAAe,CAAC,IAAI,EAAE,CAAC;QACnD,OAAO,eAAe,CAAC;IACzB,CAAC;IACD,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC;QACd,IAAI,CAAC,MAAM,CAAC,IAAI,CACd,kCAAkC,GAAG,CAAC,EAAE,yCAAyC,CAClF,CAAC;QACF,OAAO,gBAAgB,CAAC;IAC1B,CAAC;IACD,MAAM,QAAQ,GAAG,IAAI,CAAC,OAAO,EAAE,QAAQ,CAAC;IACxC,IAAI,CAAC,QAAQ,IAAI,OAAO,QAAQ,CAAC,GAAG,KAAK,UAAU,EAAE,CAAC;QACpD,IAAI,CAAC,MAAM,CAAC,IAAI,CACd,0BAA0B,GAAG,CAAC,EAAE,oDAAoD,CACrF,CAAC;QACF,OAAO,oBAAoB,CAAC;IAC9B,CAAC;IACD,MAAM,UAAU,GAAG,wBAAwB,CAAC,IAAI,CAAC,GAAG,CAAC,eAAe,CAAC,CAAC;IACtE,MAAM,QAAQ,CAAC,GAAG,CAAC;QACjB,UAAU;QACV,OAAO,EAAE,GAAG,CAAC,IAAI;QACjB,qEAAqE;QACrE,qEAAqE;QACrE,kCAAkC;QAClC,cAAc,EAAE,mBAAmB,GAAG,CAAC,EAAE,EAAE;KAC5C,CAAC,CAAC;IACH,OAAO,YAAY,CAAC;AACtB,CAAC;AAED,4EAA4E;AAC5E,sEAAsE;AACtE,4EAA4E;AAC5E,MAAM,UAAU,wBAAwB,CAAC,eAAuB;IAC9D,MAAM,UAAU,GAAG,eAAe,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;IACxD,OAAO,SAAS,UAAU,OAAO,CAAC;AACpC,CAAC"}
package/dist/index.js CHANGED
@@ -5,19 +5,22 @@
5
5
  // env). Hub auto-joins us to the Company's Team conversation.
6
6
  // 2. Outbound chat-send tool registered globally; agents call it to reply,
7
7
  // tool POSTs to /api/chat/messages.
8
- // 3. Inbound router: user-typed messages dispatch a turn to the CEO agent.
9
- // (Phase 2 will add @mention parsing + multi-agent fan-out.)
8
+ // 3. Inbound router: user-typed messages dispatch a turn to the CEO agent
9
+ // via runtime.subagent.run({ sessionKey, message }). The agent runs in
10
+ // its main session and emits the reply through helmio_chat_send.
11
+ // (Phase 2 will add @mention parsing + multi-agent fan-out using the
12
+ // runtime.channel.turn.run kernel call.)
10
13
  import { definePluginEntry } from "openclaw/plugin-sdk/plugin-entry";
11
14
  import { resolveAgents } from "./agent-resolver.js";
12
- import { startChatConnection } from "./chat-connection.js";
13
15
  import { registerChatSendTool } from "./chat-send-tool.js";
16
+ import { startChatConnection } from "./chat-connection.js";
14
17
  import { routeInbound } from "./inbound-router.js";
15
18
  import { trimTrailingSlash } from "./url.js";
16
19
  let connection;
17
20
  export default definePluginEntry({
18
21
  id: "helmio-chat",
19
22
  name: "Helmio Chat",
20
- description: "Bridges Helmio's SignalR ChatHub to per-agent turns. Inbound user messages dispatch to agents via the runtime; agent replies emit through the helmio_chat_send tool which POSTs to /api/chat/messages. ADR-0008.",
23
+ description: "Bridges Helmio's SignalR ChatHub to per-agent turns. Inbound user messages dispatch to the CEO agent via runtime.subagent.run(); agent replies emit through the helmio_chat_send tool which POSTs to /api/chat/messages. ADR-0008.",
21
24
  register(api) {
22
25
  const helmioApiUrl = process.env.HELMIO_API_URL;
23
26
  const bridgeToken = process.env.HELMIO_CHAT_BRIDGE_TOKEN;
@@ -25,10 +28,9 @@ export default definePluginEntry({
25
28
  api.logger.error("helmio-chat: HELMIO_API_URL or HELMIO_CHAT_BRIDGE_TOKEN not set; plugin loaded but disabled.");
26
29
  return;
27
30
  }
28
- // Plugin is installed at provision time BEFORE agents.create runs, so
29
- // agents.list is empty at register(). Re-resolve on every inbound
30
- // message instead of caching once.
31
- const initial = resolveAgents(api.runtime.agents.list());
31
+ // Agent roster comes from the parsed openclaw.json (api.config.agents.list).
32
+ // PluginRuntime has subagent / nodes / channel NOT an agents namespace.
33
+ const initial = resolveAgents(api.config.agents?.list ?? []);
32
34
  api.logger.info(`helmio-chat: register-time agents=${initial.agents.length} ceo=${initial.ceo?.openclawAgentId ?? "<none>"}`);
33
35
  registerChatSendTool(api, {
34
36
  helmioApiUrl,
@@ -41,7 +43,7 @@ export default definePluginEntry({
41
43
  bridgeToken,
42
44
  logger: api.logger,
43
45
  onMessage: async (msg) => {
44
- const { ceo } = resolveAgents(api.runtime.agents.list());
46
+ const { ceo } = resolveAgents(api.config.agents?.list ?? []);
45
47
  const verdict = await routeInbound(msg, {
46
48
  runtime: api.runtime,
47
49
  logger: api.logger,
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,mDAAmD;AACnD,EAAE;AACF,sBAAsB;AACtB,6EAA6E;AAC7E,mEAAmE;AACnE,6EAA6E;AAC7E,yCAAyC;AACzC,6EAA6E;AAC7E,kEAAkE;AAElE,OAAO,EAAE,iBAAiB,EAAE,MAAM,kCAAkC,CAAC;AACrE,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACpD,OAAO,EAAE,mBAAmB,EAAuB,MAAM,sBAAsB,CAAC;AAChF,OAAO,EAAE,oBAAoB,EAAE,MAAM,qBAAqB,CAAC;AAC3D,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AACnD,OAAO,EAAE,iBAAiB,EAAE,MAAM,UAAU,CAAC;AAE7C,IAAI,UAAsC,CAAC;AAE3C,eAAe,iBAAiB,CAAC;IAC/B,EAAE,EAAE,aAAa;IACjB,IAAI,EAAE,aAAa;IACnB,WAAW,EAAE,kNAAkN;IAC/N,QAAQ,CAAC,GAAG;QACV,MAAM,YAAY,GAAG,OAAO,CAAC,GAAG,CAAC,cAAc,CAAC;QAChD,MAAM,WAAW,GAAG,OAAO,CAAC,GAAG,CAAC,wBAAwB,CAAC;QACzD,IAAI,CAAC,YAAY,IAAI,CAAC,WAAW,EAAE,CAAC;YAClC,GAAG,CAAC,MAAM,CAAC,KAAK,CACd,8FAA8F,CAC/F,CAAC;YACF,OAAO;QACT,CAAC;QAED,sEAAsE;QACtE,kEAAkE;QAClE,mCAAmC;QACnC,MAAM,OAAO,GAAG,aAAa,CAAC,GAAG,CAAC,OAAO,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC,CAAC;QACzD,GAAG,CAAC,MAAM,CAAC,IAAI,CACb,qCAAqC,OAAO,CAAC,MAAM,CAAC,MAAM,QAAQ,OAAO,CAAC,GAAG,EAAE,eAAe,IAAI,QAAQ,EAAE,CAC7G,CAAC;QAEF,oBAAoB,CAAC,GAAG,EAAE;YACxB,YAAY;YACZ,WAAW;YACX,MAAM,EAAE,GAAG,CAAC,MAAM;SACnB,CAAC,CAAC;QAEH,MAAM,MAAM,GAAG,GAAG,iBAAiB,CAAC,YAAY,CAAC,eAAe,CAAC;QACjE,UAAU,GAAG,mBAAmB,CAAC;YAC/B,MAAM;YACN,WAAW;YACX,MAAM,EAAE,GAAG,CAAC,MAAM;YAClB,SAAS,EAAE,KAAK,EAAE,GAAG,EAAE,EAAE;gBACvB,MAAM,EAAE,GAAG,EAAE,GAAG,aAAa,CAAC,GAAG,CAAC,OAAO,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC,CAAC;gBACzD,MAAM,OAAO,GAAG,MAAM,YAAY,CAAC,GAAG,EAAE;oBACtC,OAAO,EAAE,GAAG,CAAC,OAAO;oBACpB,MAAM,EAAE,GAAG,CAAC,MAAM;oBAClB,GAAG;iBACJ,CAAC,CAAC;gBACH,GAAG,CAAC,MAAM,CAAC,IAAI,CACb,0BAA0B,GAAG,CAAC,EAAE,oBAAoB,GAAG,CAAC,iBAAiB,YAAY,OAAO,EAAE,CAC/F,CAAC;YACJ,CAAC;SACF,CAAC,CAAC;IACL,CAAC;CACF,CAAC,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,mDAAmD;AACnD,EAAE;AACF,sBAAsB;AACtB,6EAA6E;AAC7E,mEAAmE;AACnE,6EAA6E;AAC7E,yCAAyC;AACzC,4EAA4E;AAC5E,4EAA4E;AAC5E,sEAAsE;AACtE,0EAA0E;AAC1E,8CAA8C;AAE9C,OAAO,EAAE,iBAAiB,EAAE,MAAM,kCAAkC,CAAC;AACrE,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACpD,OAAO,EAAE,oBAAoB,EAAE,MAAM,qBAAqB,CAAC;AAC3D,OAAO,EAAE,mBAAmB,EAAuB,MAAM,sBAAsB,CAAC;AAChF,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AACnD,OAAO,EAAE,iBAAiB,EAAE,MAAM,UAAU,CAAC;AAE7C,IAAI,UAAsC,CAAC;AAE3C,eAAe,iBAAiB,CAAC;IAC/B,EAAE,EAAE,aAAa;IACjB,IAAI,EAAE,aAAa;IACnB,WAAW,EACT,oOAAoO;IACtO,QAAQ,CAAC,GAAG;QACV,MAAM,YAAY,GAAG,OAAO,CAAC,GAAG,CAAC,cAAc,CAAC;QAChD,MAAM,WAAW,GAAG,OAAO,CAAC,GAAG,CAAC,wBAAwB,CAAC;QACzD,IAAI,CAAC,YAAY,IAAI,CAAC,WAAW,EAAE,CAAC;YAClC,GAAG,CAAC,MAAM,CAAC,KAAK,CACd,8FAA8F,CAC/F,CAAC;YACF,OAAO;QACT,CAAC;QAED,6EAA6E;QAC7E,0EAA0E;QAC1E,MAAM,OAAO,GAAG,aAAa,CAAC,GAAG,CAAC,MAAM,CAAC,MAAM,EAAE,IAAI,IAAI,EAAE,CAAC,CAAC;QAC7D,GAAG,CAAC,MAAM,CAAC,IAAI,CACb,qCAAqC,OAAO,CAAC,MAAM,CAAC,MAAM,QAAQ,OAAO,CAAC,GAAG,EAAE,eAAe,IAAI,QAAQ,EAAE,CAC7G,CAAC;QAEF,oBAAoB,CAAC,GAAG,EAAE;YACxB,YAAY;YACZ,WAAW;YACX,MAAM,EAAE,GAAG,CAAC,MAAM;SACnB,CAAC,CAAC;QAEH,MAAM,MAAM,GAAG,GAAG,iBAAiB,CAAC,YAAY,CAAC,eAAe,CAAC;QACjE,UAAU,GAAG,mBAAmB,CAAC;YAC/B,MAAM;YACN,WAAW;YACX,MAAM,EAAE,GAAG,CAAC,MAAM;YAClB,SAAS,EAAE,KAAK,EAAE,GAAG,EAAE,EAAE;gBACvB,MAAM,EAAE,GAAG,EAAE,GAAG,aAAa,CAAC,GAAG,CAAC,MAAM,CAAC,MAAM,EAAE,IAAI,IAAI,EAAE,CAAC,CAAC;gBAC7D,MAAM,OAAO,GAAG,MAAM,YAAY,CAAC,GAAG,EAAE;oBACtC,OAAO,EAAE,GAAG,CAAC,OAAO;oBACpB,MAAM,EAAE,GAAG,CAAC,MAAM;oBAClB,GAAG;iBACJ,CAAC,CAAC;gBACH,GAAG,CAAC,MAAM,CAAC,IAAI,CACb,0BAA0B,GAAG,CAAC,EAAE,oBAAoB,GAAG,CAAC,iBAAiB,YAAY,OAAO,EAAE,CAC/F,CAAC;YACJ,CAAC;SACF,CAAC,CAAC;IACL,CAAC;CACF,CAAC,CAAC"}
@@ -5,6 +5,9 @@
5
5
  "activation": {
6
6
  "onStartup": true
7
7
  },
8
+ "contracts": {
9
+ "tools": ["helmio_chat_send"]
10
+ },
8
11
  "configSchema": {
9
12
  "type": "object",
10
13
  "additionalProperties": false,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@helmio/openclaw-helmio-chat",
3
- "version": "0.1.2",
3
+ "version": "0.1.3",
4
4
  "private": false,
5
5
  "description": "OpenClaw plugin that bridges Helmio's SignalR ChatHub to per-agent turns inside the Company VM. Installed at cloud-init via `openclaw plugins install npm:@helmio/openclaw-helmio-chat@<pinned>`. ADR-0008.",
6
6
  "type": "module",