@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 +2 -0
- package/dist/index.js.map +1 -1
- package/dist/src/send-file-tool.js +68 -0
- package/dist/src/send-file-tool.js.map +1 -0
- package/index.ts +2 -0
- package/package.json +1 -1
- package/skills/lansenger-messaging/SKILL.md +12 -12
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;
|
|
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-messaging
|
|
3
|
-
version: 2.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 `
|
|
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 `
|
|
130
|
+
### Use `lansenger_send_file`
|
|
131
131
|
|
|
132
132
|
```
|
|
133
|
-
|
|
133
|
+
lansenger_send_file(filePath=<absolute local path>, caption=<optional plain-text>, to=<optional chatId>)
|
|
134
134
|
```
|
|
135
135
|
|
|
136
|
-
-
|
|
137
|
-
-
|
|
138
|
-
- `to`
|
|
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 `
|
|
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. `
|
|
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
|
|
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
|
|
154
|
-
- **NEVER use `MEDIA:` tags for file delivery on Lansenger** — always use `
|
|
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
|