@lansenger-pm/openclaw-lansenger-channel 2.1.1 → 2.1.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.
package/dist/index.js CHANGED
@@ -1,6 +1,7 @@
1
1
  import { defineChannelPluginEntry } from "openclaw/plugin-sdk/channel-core";
2
2
  import { lansengerPlugin } from "./src/channel.js";
3
3
  import { startLansengerGateway } from "./src/runtime.js";
4
+ import { registerLansengerSendFileTool } from "./src/send-file-tool.js";
4
5
  export default defineChannelPluginEntry({
5
6
  id: "lansenger",
6
7
  name: "Lansenger (蓝信)",
@@ -21,6 +22,7 @@ export default defineChannelPluginEntry({
21
22
  },
22
23
  registerFull(api) {
23
24
  startLansengerGateway(api);
25
+ registerLansengerSendFileTool(api);
24
26
  },
25
27
  });
26
28
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,wBAAwB,EAAE,MAAM,kCAAkC,CAAC;AAC5E,OAAO,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAC;AACnD,OAAO,EAAE,qBAAqB,EAAE,MAAM,kBAAkB,CAAC;AAEzD,eAAe,wBAAwB,CAAC;IACtC,EAAE,EAAE,WAAW;IACf,IAAI,EAAE,gBAAgB;IACtB,WAAW,EAAE,4DAA4D;IACzE,MAAM,EAAE,eAAe;IACvB,mBAAmB,CAAC,GAAG;QACrB,GAAG,CAAC,WAAW,CACb,CAAC,EAAE,OAAO,EAAE,EAAE,EAAE;YACd,OAAO,CAAC,OAAO,CAAC,WAAW,CAAC,CAAC,WAAW,CAAC,2BAA2B,CAAC,CAAC;QACxE,CAAC,EACD;YACE,WAAW,EAAE;gBACX;oBACE,IAAI,EAAE,WAAW;oBACjB,WAAW,EAAE,2BAA2B;oBACxC,cAAc,EAAE,KAAK;iBACtB;aACF;SACF,CACF,CAAC;IACJ,CAAC;IACD,YAAY,CAAC,GAAG;QACd,qBAAqB,CAAC,GAAG,CAAC,CAAC;IAC7B,CAAC;CACF,CAAC,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,wBAAwB,EAAE,MAAM,kCAAkC,CAAC;AAC5E,OAAO,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAC;AACnD,OAAO,EAAE,qBAAqB,EAAE,MAAM,kBAAkB,CAAC;AACzD,OAAO,EAAE,6BAA6B,EAAE,MAAM,yBAAyB,CAAC;AAExE,eAAe,wBAAwB,CAAC;IACtC,EAAE,EAAE,WAAW;IACf,IAAI,EAAE,gBAAgB;IACtB,WAAW,EAAE,4DAA4D;IACzE,MAAM,EAAE,eAAe;IACvB,mBAAmB,CAAC,GAAG;QACrB,GAAG,CAAC,WAAW,CACb,CAAC,EAAE,OAAO,EAAE,EAAE,EAAE;YACd,OAAO,CAAC,OAAO,CAAC,WAAW,CAAC,CAAC,WAAW,CAAC,2BAA2B,CAAC,CAAC;QACxE,CAAC,EACD;YACE,WAAW,EAAE;gBACX;oBACE,IAAI,EAAE,WAAW;oBACjB,WAAW,EAAE,2BAA2B;oBACxC,cAAc,EAAE,KAAK;iBACtB;aACF;SACF,CACF,CAAC;IACJ,CAAC;IACD,YAAY,CAAC,GAAG;QACd,qBAAqB,CAAC,GAAG,CAAC,CAAC;QAC3B,6BAA6B,CAAC,GAAG,CAAC,CAAC;IACrC,CAAC;CACF,CAAC,CAAC"}
@@ -0,0 +1,68 @@
1
+ import { resolveAccount, makeClient } from "./channel.js";
2
+ import * as path from "node:path";
3
+ import * as fs from "node:fs/promises";
4
+ const SendFileSchema = {
5
+ type: "object",
6
+ properties: {
7
+ filePath: { type: "string", description: "Absolute local path to the file to send. Any path works — Documents, Desktop, workspace, /tmp, etc." },
8
+ caption: { type: "string", description: "Plain-text caption for the file (Markdown will NOT render on Lansenger). Optional." },
9
+ to: { type: "string", description: "Lansenger target chat ID. Optional — if omitted, the file is sent to the current conversation automatically." },
10
+ },
11
+ required: ["filePath"],
12
+ };
13
+ function resolveSessionTarget(ctx) {
14
+ if (ctx.to)
15
+ return ctx.to;
16
+ if (ctx.sessionKey) {
17
+ const parts = String(ctx.sessionKey).split(":");
18
+ if (parts.length >= 3 && parts[2])
19
+ return parts[2];
20
+ }
21
+ return String(ctx.requesterSenderId ?? "");
22
+ }
23
+ export function registerLansengerSendFileTool(api) {
24
+ if (!api.config)
25
+ return;
26
+ const section = api.config.channels?.["lansenger"];
27
+ if (!section)
28
+ return;
29
+ const accounts = section.accounts;
30
+ let account;
31
+ if (accounts && Object.keys(accounts).length > 0) {
32
+ const firstKey = Object.keys(accounts)[0];
33
+ account = resolveAccount(api.config, firstKey);
34
+ }
35
+ else {
36
+ account = resolveAccount(api.config, undefined);
37
+ }
38
+ if (!account.enabled || !account.appId)
39
+ return;
40
+ api.registerTool((ctx) => ({
41
+ name: "lansenger_send_file",
42
+ label: "Lansenger Send File",
43
+ description: "Send a local file as an attachment to the user on Lansenger (蓝信). Use this tool to deliver any file — PDF, image, document, video, etc. The file can be anywhere on the local disk. Do NOT use MEDIA: tags to send files on Lansenger — they silently fail for files outside the workspace; always use this tool instead.",
44
+ parameters: SendFileSchema,
45
+ async execute(_toolCallId, params) {
46
+ const filePath = params.filePath;
47
+ const caption = params.caption ?? "";
48
+ const to = resolveSessionTarget({ ...ctx, to: params.to });
49
+ if (!filePath)
50
+ return { content: [{ type: "text", text: JSON.stringify({ error: "filePath is required" }) }] };
51
+ if (!to)
52
+ return { content: [{ type: "text", text: JSON.stringify({ error: "No target specified and no active session context. Provide a 'to' parameter." }) }] };
53
+ const resolved = path.resolve(filePath);
54
+ try {
55
+ const stat = await fs.stat(resolved);
56
+ if (!stat.isFile())
57
+ return { content: [{ type: "text", text: JSON.stringify({ error: `Not a file: ${filePath}` }) }] };
58
+ }
59
+ catch {
60
+ return { content: [{ type: "text", text: JSON.stringify({ error: `File not found: ${filePath}` }) }] };
61
+ }
62
+ const client = makeClient(account);
63
+ const result = await client.sendFile(to, resolved, caption);
64
+ return { content: [{ type: "text", text: JSON.stringify({ success: result.success, messageId: result.messageId ?? null }) }] };
65
+ },
66
+ }), { name: "lansenger_send_file" });
67
+ }
68
+ //# sourceMappingURL=send-file-tool.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"send-file-tool.js","sourceRoot":"","sources":["../../src/send-file-tool.ts"],"names":[],"mappings":"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"}
package/index.ts CHANGED
@@ -1,6 +1,7 @@
1
1
  import { defineChannelPluginEntry } from "openclaw/plugin-sdk/channel-core";
2
2
  import { lansengerPlugin } from "./src/channel.js";
3
3
  import { startLansengerGateway } from "./src/runtime.js";
4
+ import { registerLansengerSendFileTool } from "./src/send-file-tool.js";
4
5
 
5
6
  export default defineChannelPluginEntry({
6
7
  id: "lansenger",
@@ -25,5 +26,6 @@ export default defineChannelPluginEntry({
25
26
  },
26
27
  registerFull(api) {
27
28
  startLansengerGateway(api);
29
+ registerLansengerSendFileTool(api);
28
30
  },
29
31
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lansenger-pm/openclaw-lansenger-channel",
3
- "version": "2.1.1",
3
+ "version": "2.1.2",
4
4
  "type": "module",
5
5
  "main": "dist/index.js",
6
6
  "files": [
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: lansenger-messaging
3
- version: 2.1.1
3
+ version: 2.1.2
4
4
  category: communication
5
5
  description: How to communicate effectively on Lansenger (蓝信) — message types, formatting rules, media, cards, approvals, and pitfalls
6
6
  trigger: When the current session channel is lansenger, or when you need to send a message, file, image, card, or approval via Lansenger
@@ -125,33 +125,33 @@ This is the correct model for personal bots — they only receive DMs from appro
125
125
 
126
126
  ## Sending Files to Users (CRITICAL)
127
127
 
128
- When you need to send a file to the user on Lansenger, **use the `message` tool with `action=send` and a `filePath` parameter**. Do NOT use `MEDIA:` tags — they only work for workspace files and are silently dropped for any other path.
128
+ When you need to send a file to the user on Lansenger, **use the `lansenger_send_file` tool**. Do NOT use `MEDIA:` tags — they only work for workspace files and are silently dropped for any other path.
129
129
 
130
- ### Use `message(action=send, filePath=...)`
130
+ ### Use `lansenger_send_file`
131
131
 
132
132
  ```
133
- message(action=send, filePath=<absolute local path>, caption=<optional plain-text>)
133
+ lansenger_send_file(filePath=<absolute local path>, caption=<optional plain-text>, to=<optional chatId>)
134
134
  ```
135
135
 
136
- - If `filePath` is provided file is sent as an attachment, `caption` is plain text only (no Markdown)
137
- - If `filePath` is omitted → `text`/`message` is sent as Markdown (default behavior)
138
- - `to` is optional — if omitted, the file/message goes to the current conversation target automatically
136
+ - `filePath` (required) absolute local path to the file to send
137
+ - `caption` (optional) plain-text caption (Markdown will NOT render)
138
+ - `to` (optional)target chat ID; if omitted, the file goes to the current conversation automatically
139
139
 
140
140
  ### ⚠️ Do NOT use `MEDIA:` tags for file delivery
141
141
 
142
- `MEDIA:` tags only work for files inside `~/.openclaw/workspace/`. For files outside the workspace (e.g. `~/Documents/`, `~/Desktop/`), `MEDIA:` tags are **silently dropped** — the user will never receive the file. Always use `message(action=send, filePath=...)` instead.
142
+ `MEDIA:` tags only work for files inside `~/.openclaw/workspace/`. For files outside the workspace (e.g. `~/Documents/`, `~/Desktop/`), `MEDIA:` tags are **silently dropped** — the user will never receive the file. Always use `lansenger_send_file` instead.
143
143
 
144
144
  ### Typical flow
145
145
 
146
146
  1. Agent reads or creates a file (any local path works)
147
- 2. `message(action=send, to=<chatId>, filePath=~/Documents/README.md)` → delivers file to the user
147
+ 2. `lansenger_send_file(filePath=/path/to/file.pdf)` → delivers file to the user
148
148
 
149
149
  ### Rules
150
150
 
151
- - Any local path works for `filePath` — workspace, Documents, Desktop, etc.
151
+ - Any local path works — workspace, Documents, Desktop, /tmp, etc.
152
152
  - `caption` is plain text only (Markdown will NOT render)
153
- - If you need both formatted explanation AND a file, send the formatted Markdown text first, then `message(action=send, filePath=...)` separately
154
- - **NEVER use `MEDIA:` tags for file delivery on Lansenger** — always use `message(action=send, filePath=...)`
153
+ - If you need both formatted explanation AND a file, send the formatted Markdown text first, then call `lansenger_send_file` separately
154
+ - **NEVER use `MEDIA:` tags for file delivery on Lansenger** — always use `lansenger_send_file`
155
155
  - Supported file types: images (.jpg/.png/.gif/.webp), videos (.mp4/.mov), documents (.pdf/.md/.txt/.zip), etc.
156
156
 
157
157
  ## Critical Pitfalls