@agentrux/agentrux-openclaw-plugin 0.3.2 → 0.3.4

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 CHANGED
@@ -2,12 +2,15 @@
2
2
 
3
3
  Connect your OpenClaw agent to other agents via AgenTrux — authenticated Pub/Sub for autonomous agents.
4
4
 
5
- **v0.3.1**: Now supports **Ingress mode** external clients can send commands to OpenClaw via AgenTrux Topics and receive LLM-processed results back.
5
+ **v0.3.3**: Ingress mode with image attachments, auto topic resolution for uploads, SSE/webhook dual support.
6
6
 
7
7
  ## Install
8
8
 
9
+ > **Important:** `openclaw.json` に plugin config を設定してからインストールしてください。
10
+ > config 未設定だと OpenClaw CLI がロードエラーで停止します。
11
+
9
12
  ```bash
10
- openclaw plugins install @agentrux/agentrux-openclaw-plugin
13
+ openclaw plugins install @agentrux/agentrux-openclaw-plugin@0.3.3
11
14
  ```
12
15
 
13
16
  ## Quick Start
@@ -197,8 +197,12 @@ class Dispatcher {
197
197
  message: wrappedMessage,
198
198
  idempotencyKey,
199
199
  timeoutMs: this.config.subagentTimeoutMs,
200
+ extraSystemPrompt: `AgenTrux context: commandTopicId=${this.config.commandTopicId} ` +
201
+ `resultTopicId=${this.config.resultTopicId}. ` +
202
+ `Use resultTopicId as topic_id for agentrux_upload and agentrux_publish.`,
200
203
  });
201
204
  const responseText = dispatchResult.responseText || "";
205
+ const attachments = dispatchResult.attachments || [];
202
206
  // Add to outbox (waterline is NOT advanced here — outbox flush owns that)
203
207
  (0, outbox_1.addToOutbox)({
204
208
  eventId,
@@ -208,6 +212,7 @@ class Dispatcher {
208
212
  message: (0, sanitize_1.sanitizeResponse)(responseText || "No response from agent"),
209
213
  status: dispatchResult.status === "ok" ? "completed" : "failed",
210
214
  conversationKey,
215
+ ...(attachments.length > 0 ? { attachments } : {}),
211
216
  },
212
217
  });
213
218
  // Record processed event AFTER durable outbox write
@@ -173,6 +173,7 @@ async function uploadFile(creds, topicId, filePath, contentType) {
173
173
  const info = await authRequest(creds, "POST", `/topics/${topicId}/payloads`, {
174
174
  content_type: contentType,
175
175
  filename,
176
+ size: data.length,
176
177
  });
177
178
  // 2. Upload file to presigned URL
178
179
  const uploadUrl = new URL(info.upload_url);
package/dist/index.d.ts CHANGED
@@ -12,4 +12,10 @@
12
12
  *
13
13
  * Credentials: ~/.agentrux/credentials.json (0600)
14
14
  */
15
+ export declare function consumeAttachments(sessionKey: string): Array<{
16
+ download_url?: string;
17
+ content_type: string;
18
+ name: string;
19
+ object_id: string;
20
+ }>;
15
21
  export default function (api: any): void;
package/dist/index.js CHANGED
@@ -13,7 +13,41 @@
13
13
  *
14
14
  * Credentials: ~/.agentrux/credentials.json (0600)
15
15
  */
16
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
17
+ if (k2 === undefined) k2 = k;
18
+ var desc = Object.getOwnPropertyDescriptor(m, k);
19
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
20
+ desc = { enumerable: true, get: function() { return m[k]; } };
21
+ }
22
+ Object.defineProperty(o, k2, desc);
23
+ }) : (function(o, m, k, k2) {
24
+ if (k2 === undefined) k2 = k;
25
+ o[k2] = m[k];
26
+ }));
27
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
28
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
29
+ }) : function(o, v) {
30
+ o["default"] = v;
31
+ });
32
+ var __importStar = (this && this.__importStar) || (function () {
33
+ var ownKeys = function(o) {
34
+ ownKeys = Object.getOwnPropertyNames || function (o) {
35
+ var ar = [];
36
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
37
+ return ar;
38
+ };
39
+ return ownKeys(o);
40
+ };
41
+ return function (mod) {
42
+ if (mod && mod.__esModule) return mod;
43
+ var result = {};
44
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
45
+ __setModuleDefault(result, mod);
46
+ return result;
47
+ };
48
+ })();
16
49
  Object.defineProperty(exports, "__esModule", { value: true });
50
+ exports.consumeAttachments = consumeAttachments;
17
51
  exports.default = default_1;
18
52
  const credentials_1 = require("./credentials");
19
53
  const http_client_1 = require("./http-client");
@@ -25,6 +59,15 @@ const poller_1 = require("./poller");
25
59
  const sse_listener_1 = require("./sse-listener");
26
60
  // Module-level state for tools (shared across tool calls)
27
61
  let credentials = null;
62
+ // Attachment registry: sessionKey → attachments (consumed by dispatcher after subagent.run)
63
+ const pendingAttachments = new Map();
64
+ // Current session key for the active subagent run (set by dispatch endpoint)
65
+ let activeSessionKey = null;
66
+ function consumeAttachments(sessionKey) {
67
+ const attachments = pendingAttachments.get(sessionKey) || [];
68
+ pendingAttachments.delete(sessionKey);
69
+ return attachments;
70
+ }
28
71
  function getCredentials() {
29
72
  if (!credentials) {
30
73
  credentials = (0, credentials_1.loadCredentials)();
@@ -47,6 +90,10 @@ function default_1(api) {
47
90
  warn: (...a) => (rawLogger.warn || console.warn)(...a),
48
91
  error: (...a) => (rawLogger.error || console.error)(...a),
49
92
  };
93
+ // Resolve plugin config early so tools can access topic IDs
94
+ const pluginConfig = api.pluginConfig
95
+ || api.config?.plugins?.entries?.["agentrux-openclaw-plugin"]?.config
96
+ || {};
50
97
  // =======================================================================
51
98
  // TOOLS (available to LLM in all modes)
52
99
  // =======================================================================
@@ -197,19 +244,35 @@ function default_1(api) {
197
244
  api.registerTool({
198
245
  name: "agentrux_upload",
199
246
  description: "Upload a local file to AgenTrux and get a download URL. " +
200
- "Use this to attach screenshots, logs, or other files to your response.",
247
+ "Use this to attach screenshots, logs, or other files to your response. " +
248
+ "The topic is automatically resolved from plugin config.",
201
249
  parameters: {
202
250
  type: "object",
203
251
  properties: {
204
- topic_id: { type: "string", description: "Topic UUID to attach the file to" },
205
252
  file_path: { type: "string", description: "Absolute path to the local file" },
206
253
  content_type: { type: "string", description: "MIME type (e.g. image/png, text/plain)" },
207
254
  },
208
- required: ["topic_id", "file_path", "content_type"],
255
+ required: ["file_path", "content_type"],
209
256
  },
210
257
  async execute(_id, params) {
211
258
  const creds = getCredentials();
212
- const result = await (0, http_client_1.uploadFile)(creds, params.topic_id, params.file_path, params.content_type);
259
+ // Auto-resolve topic from plugin config (resultTopicId or commandTopicId)
260
+ const uploadTopicId = pluginConfig.resultTopicId || pluginConfig.commandTopicId || "";
261
+ if (!uploadTopicId) {
262
+ return { content: [{ type: "text", text: "Upload failed: no topic configured for uploads." }] };
263
+ }
264
+ const pth = await Promise.resolve().then(() => __importStar(require("path")));
265
+ const result = await (0, http_client_1.uploadFile)(creds, uploadTopicId, params.file_path, params.content_type);
266
+ // Register attachment for the active subagent run
267
+ if (activeSessionKey) {
268
+ const list = pendingAttachments.get(activeSessionKey) || [];
269
+ list.push({
270
+ object_id: result.object_id,
271
+ content_type: params.content_type,
272
+ name: pth.basename(params.file_path),
273
+ });
274
+ pendingAttachments.set(activeSessionKey, list);
275
+ }
213
276
  return {
214
277
  content: [{
215
278
  type: "text",
@@ -229,11 +292,6 @@ function default_1(api) {
229
292
  globalThis.__agentruxIngressStarted = true;
230
293
  // Clear token cache on startup to pick up latest grant scopes
231
294
  (0, http_client_1.invalidateToken)();
232
- // pluginConfig may be undefined if OpenClaw doesn't resolve it due to id mismatch
233
- // Fallback: read from api.config (full OpenClaw config)
234
- const pluginConfig = api.pluginConfig
235
- || api.config?.plugins?.entries?.["agentrux-openclaw-plugin"]?.config
236
- || {};
237
295
  const commandTopicId = pluginConfig.commandTopicId;
238
296
  const resultTopicId = pluginConfig.resultTopicId;
239
297
  const webhookSecret = pluginConfig.webhookSecret;
@@ -279,6 +337,8 @@ function default_1(api) {
279
337
  });
280
338
  const params = JSON.parse(Buffer.concat(chunks).toString());
281
339
  try {
340
+ // Track active session for attachment registry
341
+ activeSessionKey = params.sessionKey;
282
342
  // OpenClaw 2026.3.24+: provider/model override is not authorized
283
343
  // for plugin subagent runs. The agent's configured model is used.
284
344
  const { runId } = await api.runtime.subagent.run({
@@ -286,6 +346,7 @@ function default_1(api) {
286
346
  message: params.message,
287
347
  idempotencyKey: params.idempotencyKey,
288
348
  deliver: false,
349
+ ...(params.extraSystemPrompt ? { extraSystemPrompt: params.extraSystemPrompt } : {}),
289
350
  });
290
351
  const waitResult = await api.runtime.subagent.waitForRun({
291
352
  runId,
@@ -304,11 +365,17 @@ function default_1(api) {
304
365
  }
305
366
  }
306
367
  }
368
+ // Collect attachments uploaded during this run
369
+ const attachments = consumeAttachments(params.sessionKey);
370
+ activeSessionKey = null;
307
371
  res.statusCode = 200;
308
372
  res.setHeader("Content-Type", "application/json");
309
- res.end(JSON.stringify({ responseText, status: waitResult.status }));
373
+ res.end(JSON.stringify({ responseText, status: waitResult.status, attachments }));
310
374
  }
311
375
  catch (e) {
376
+ if (params.sessionKey)
377
+ consumeAttachments(params.sessionKey);
378
+ activeSessionKey = null;
312
379
  res.statusCode = 500;
313
380
  res.end(JSON.stringify({ responseText: "", status: "error", error: e.message }));
314
381
  }
package/dist/outbox.d.ts CHANGED
@@ -14,8 +14,9 @@ export interface OutboxEntry {
14
14
  status: string;
15
15
  conversationKey?: string;
16
16
  attachments?: Array<{
17
- url: string;
18
- type: string;
17
+ object_id: string;
18
+ content_type: string;
19
+ name: string;
19
20
  }>;
20
21
  };
21
22
  createdAt: string;
package/dist/outbox.js CHANGED
@@ -105,12 +105,16 @@ async function flushOutbox(creds, resultTopicId, logger) {
105
105
  if (entry.status !== "pending_publish")
106
106
  continue;
107
107
  try {
108
- await (0, http_client_1.publishEvent)(creds, resultTopicId, "openclaw.response", {
108
+ const payload = {
109
109
  request_id: entry.requestId,
110
110
  conversation_key: entry.result.conversationKey,
111
111
  status: entry.result.status,
112
112
  message: entry.result.message,
113
- });
113
+ };
114
+ if (entry.result.attachments?.length) {
115
+ payload.attachments = entry.result.attachments;
116
+ }
117
+ await (0, http_client_1.publishEvent)(creds, resultTopicId, "openclaw.response", payload);
114
118
  entry.status = "published";
115
119
  store.published.push({ ...entry });
116
120
  finalized.push(entry.sequenceNo);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@agentrux/agentrux-openclaw-plugin",
3
- "version": "0.3.2",
3
+ "version": "0.3.4",
4
4
  "description": "OpenClaw plugin for AgenTrux — Agent-to-Agent authenticated Pub/Sub",
5
5
  "keywords": [
6
6
  "openclaw",