@relaymessenger/openclaw-plugin 0.4.7-staging.14 → 0.4.7-staging.16
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 +16 -0
- package/contracts/relay-v1.lock.json +5 -5
- package/dist/src/channel.js +1 -1
- package/dist/src/dispatch.js +4 -1
- package/dist/src/inbound.js +9 -1
- package/package.json +2 -2
- package/src/channel.ts +1 -1
- package/src/dispatch.ts +4 -1
- package/src/inbound.ts +9 -1
- package/src/types.ts +5 -0
package/README.md
CHANGED
|
@@ -12,6 +12,22 @@ delivers events over its v1 WebSocket, and the plugin sends replies through
|
|
|
12
12
|
the Relay v1 REST Message API. The plugin imports `@relaymessenger/sdk`; it
|
|
13
13
|
does not contain a copied Relay client or protocol implementation.
|
|
14
14
|
|
|
15
|
+
## Selection, coming soon
|
|
16
|
+
|
|
17
|
+
These are local candidate sources, not a claim that the published package or
|
|
18
|
+
hosted API supports selection yet.
|
|
19
|
+
|
|
20
|
+
End the final answer with a `selection` JSON fence after the question.
|
|
21
|
+
`BodyForAgent` carries structured response and rich-message JSON; `RawBody` and
|
|
22
|
+
`CommandBody` retain readable text. Stable values are not executable commands.
|
|
23
|
+
|
|
24
|
+
New human reply text is literal `• ` + each selected source label joined with
|
|
25
|
+
`\n`, followed by `selection_response` metadata in source-option order. Dispatch
|
|
26
|
+
with `selected_values` and the explicit source target, never label parsing.
|
|
27
|
+
Exact legacy comma-joined text remains a server compatibility input. Tapping a
|
|
28
|
+
selected option deselects it locally; the sole submit action is a centered
|
|
29
|
+
compact light-blue Send button. iOS checked circles are presentation only.
|
|
30
|
+
|
|
15
31
|
## Install
|
|
16
32
|
|
|
17
33
|
```bash
|
|
@@ -1,16 +1,16 @@
|
|
|
1
1
|
{
|
|
2
2
|
"relayServer": {
|
|
3
3
|
"repository": "RelayMessenger/Relay-Server",
|
|
4
|
-
"commit": "
|
|
4
|
+
"commit": "b89d90c0b325a94402456de2e91a59b66c7d9603",
|
|
5
5
|
"openapiPath": "contracts/developer/openapi.yaml",
|
|
6
|
-
"sha256": "
|
|
6
|
+
"sha256": "503646bcd2b3fbc1170046880ef39f4219592fb9e5d9d00cef022b801abbb4bb"
|
|
7
7
|
},
|
|
8
8
|
"relaySdk": {
|
|
9
9
|
"package": "@relaymessenger/sdk",
|
|
10
|
-
"version": "0.3.6-staging.
|
|
11
|
-
"integrity": "sha512-
|
|
10
|
+
"version": "0.3.6-staging.14",
|
|
11
|
+
"integrity": "sha512-0zUTLWzkFoW24w62yeSknuSKg27EeM8fmemxAsoyrWtCv5myxTm5h/FFFbnv8Guie2XxNXnwrMix6ullU/8FLw==",
|
|
12
12
|
"operationsSha256": "1691197e8db0705bcad5d0704042e98ed8c3f2262875b5e773b0e12ae0a33022",
|
|
13
|
-
"workspaceOpenapiSha256": "
|
|
13
|
+
"workspaceOpenapiSha256": "503646bcd2b3fbc1170046880ef39f4219592fb9e5d9d00cef022b801abbb4bb",
|
|
14
14
|
"usedOperations": [
|
|
15
15
|
{
|
|
16
16
|
"method": "GET",
|
package/dist/src/channel.js
CHANGED
|
@@ -249,7 +249,7 @@ export const relayChannelPlugin = createChatChannelPlugin({
|
|
|
249
249
|
deliveryQueueId: ctx.deliveryQueueId,
|
|
250
250
|
deliveryPartIndex: ctx.deliveryPartIndex,
|
|
251
251
|
}),
|
|
252
|
-
onButtonsError: (error) => ctx.log?.warn?.(`relay:
|
|
252
|
+
onButtonsError: (error) => ctx.log?.warn?.(`relay: component block left as text: ${error}`),
|
|
253
253
|
...(ctx.onPlatformSendDispatch
|
|
254
254
|
? { onPlatformSendDispatch: ctx.onPlatformSendDispatch }
|
|
255
255
|
: {}),
|
package/dist/src/dispatch.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { BUTTONS_GUIDANCE, BUTTONS_BLOCK_INSTRUCTION, LINK_LINE_INSTRUCTION, SELECTION_GUIDANCE, SELECTION_BLOCK_INSTRUCTION, selectionReplyContext } from "@relaymessenger/sdk";
|
|
1
2
|
import { buildChannelInboundEventContext, resolveChannelInboundRouteEnvelope, } from "openclaw/plugin-sdk/channel-inbound";
|
|
2
3
|
import { resolveStableChannelMessageIngress } from "openclaw/plugin-sdk/channel-ingress-runtime";
|
|
3
4
|
import { bindIngressLifecycleToReplyOptions } from "openclaw/plugin-sdk/channel-outbound";
|
|
@@ -177,7 +178,9 @@ export async function dispatchRelayEvent(params) {
|
|
|
177
178
|
message: {
|
|
178
179
|
inboundEventKind: "user_request",
|
|
179
180
|
body,
|
|
180
|
-
bodyForAgent: facts.text,
|
|
181
|
+
bodyForAgent: [facts.text, selectionReplyContext(facts.selection, facts.richMessage),
|
|
182
|
+
`${BUTTONS_BLOCK_INSTRUCTION} ${LINK_LINE_INSTRUCTION} ${BUTTONS_GUIDANCE} ${SELECTION_BLOCK_INSTRUCTION} ${SELECTION_GUIDANCE}`,
|
|
183
|
+
].filter(Boolean).join("\n\n"),
|
|
181
184
|
rawBody: facts.text,
|
|
182
185
|
commandBody: facts.text,
|
|
183
186
|
},
|
package/dist/src/inbound.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { selectionReply, selectionReplyContext } from "@relaymessenger/sdk";
|
|
1
2
|
function renderPart(part) {
|
|
2
3
|
switch (part.type) {
|
|
3
4
|
case "text":
|
|
@@ -11,6 +12,8 @@ function renderPart(part) {
|
|
|
11
12
|
// The agent's own buttons part reads as nothing, as on the server; its
|
|
12
13
|
// question is the text beside it. A tap arrives as ordinary text.
|
|
13
14
|
case "buttons":
|
|
15
|
+
case "selection":
|
|
16
|
+
case "selection_response":
|
|
14
17
|
return undefined;
|
|
15
18
|
}
|
|
16
19
|
}
|
|
@@ -41,7 +44,9 @@ export function buildRelayInboundFacts(event) {
|
|
|
41
44
|
event.data.sender_handle.kind !== "agent")
|
|
42
45
|
return null;
|
|
43
46
|
const text = renderRelayMessageParts(event.data.parts);
|
|
44
|
-
|
|
47
|
+
const message = { parts: event.data.parts, ...(event.data.reply_to ? { reply_to: event.data.reply_to } : {}) };
|
|
48
|
+
const richMessage = selectionReplyContext(undefined, message) ? message : undefined;
|
|
49
|
+
if (!text.trim() && !richMessage)
|
|
45
50
|
return null;
|
|
46
51
|
const mentionHandles = event.data.parts.flatMap((part) => part.type === "text" &&
|
|
47
52
|
typeof part.mention === "string" &&
|
|
@@ -50,7 +55,10 @@ export function buildRelayInboundFacts(event) {
|
|
|
50
55
|
: []);
|
|
51
56
|
const timestampValue = event.data.sent_at ?? event.created_at;
|
|
52
57
|
const timestamp = Date.parse(timestampValue);
|
|
58
|
+
const selection = selectionReply(event.data.parts, event.data.reply_to);
|
|
53
59
|
return {
|
|
60
|
+
...(selection ? { selection } : {}),
|
|
61
|
+
...(richMessage ? { richMessage } : {}),
|
|
54
62
|
eventId: event.event_id,
|
|
55
63
|
messageId: event.data.id,
|
|
56
64
|
chatId: event.data.chat.id,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@relaymessenger/openclaw-plugin",
|
|
3
|
-
"version": "0.4.7-staging.
|
|
3
|
+
"version": "0.4.7-staging.16",
|
|
4
4
|
"description": "Native Relay channel plugin for OpenClaw",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
@@ -37,7 +37,7 @@
|
|
|
37
37
|
"prepack": "npm run build"
|
|
38
38
|
},
|
|
39
39
|
"dependencies": {
|
|
40
|
-
"@relaymessenger/sdk": "0.3.6-staging.
|
|
40
|
+
"@relaymessenger/sdk": "0.3.6-staging.14"
|
|
41
41
|
},
|
|
42
42
|
"devDependencies": {
|
|
43
43
|
"@types/node": "^26.6.2",
|
package/src/channel.ts
CHANGED
|
@@ -331,7 +331,7 @@ export const relayChannelPlugin: ChannelPlugin<ResolvedRelayAccount> =
|
|
|
331
331
|
}),
|
|
332
332
|
onButtonsError: (error) =>
|
|
333
333
|
(ctx as { log?: { warn?: (message: string) => void } }).log?.warn?.(
|
|
334
|
-
`relay:
|
|
334
|
+
`relay: component block left as text: ${error}`,
|
|
335
335
|
),
|
|
336
336
|
...(ctx.onPlatformSendDispatch
|
|
337
337
|
? { onPlatformSendDispatch: ctx.onPlatformSendDispatch }
|
package/src/dispatch.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { BUTTONS_GUIDANCE, BUTTONS_BLOCK_INSTRUCTION, LINK_LINE_INSTRUCTION, SELECTION_GUIDANCE, SELECTION_BLOCK_INSTRUCTION, selectionReplyContext } from "@relaymessenger/sdk";
|
|
1
2
|
import type {
|
|
2
3
|
Message,
|
|
3
4
|
Relay,
|
|
@@ -243,7 +244,9 @@ export async function dispatchRelayEvent(params: {
|
|
|
243
244
|
message: {
|
|
244
245
|
inboundEventKind: "user_request",
|
|
245
246
|
body,
|
|
246
|
-
bodyForAgent: facts.text,
|
|
247
|
+
bodyForAgent: [facts.text, selectionReplyContext(facts.selection, facts.richMessage),
|
|
248
|
+
`${BUTTONS_BLOCK_INSTRUCTION} ${LINK_LINE_INSTRUCTION} ${BUTTONS_GUIDANCE} ${SELECTION_BLOCK_INSTRUCTION} ${SELECTION_GUIDANCE}`,
|
|
249
|
+
].filter(Boolean).join("\n\n"),
|
|
247
250
|
rawBody: facts.text,
|
|
248
251
|
commandBody: facts.text,
|
|
249
252
|
},
|
package/src/inbound.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { selectionReply, selectionReplyContext } from "@relaymessenger/sdk";
|
|
1
2
|
import type {
|
|
2
3
|
MessagePartResponse,
|
|
3
4
|
RelayWebhookEvent,
|
|
@@ -20,6 +21,8 @@ function renderPart(part: MessagePartResponse): string | undefined {
|
|
|
20
21
|
// The agent's own buttons part reads as nothing, as on the server; its
|
|
21
22
|
// question is the text beside it. A tap arrives as ordinary text.
|
|
22
23
|
case "buttons":
|
|
24
|
+
case "selection":
|
|
25
|
+
case "selection_response":
|
|
23
26
|
return undefined;
|
|
24
27
|
}
|
|
25
28
|
}
|
|
@@ -61,7 +64,9 @@ export function buildRelayInboundFacts(
|
|
|
61
64
|
) return null;
|
|
62
65
|
|
|
63
66
|
const text = renderRelayMessageParts(event.data.parts);
|
|
64
|
-
|
|
67
|
+
const message = { parts: event.data.parts, ...(event.data.reply_to ? { reply_to: event.data.reply_to } : {}) };
|
|
68
|
+
const richMessage = selectionReplyContext(undefined, message) ? message : undefined;
|
|
69
|
+
if (!text.trim() && !richMessage) return null;
|
|
65
70
|
|
|
66
71
|
const mentionHandles = event.data.parts.flatMap((part) =>
|
|
67
72
|
part.type === "text" &&
|
|
@@ -72,7 +77,10 @@ export function buildRelayInboundFacts(
|
|
|
72
77
|
);
|
|
73
78
|
const timestampValue = event.data.sent_at ?? event.created_at;
|
|
74
79
|
const timestamp = Date.parse(timestampValue);
|
|
80
|
+
const selection = selectionReply(event.data.parts, event.data.reply_to);
|
|
75
81
|
return {
|
|
82
|
+
...(selection ? { selection } : {}),
|
|
83
|
+
...(richMessage ? { richMessage } : {}),
|
|
76
84
|
eventId: event.event_id,
|
|
77
85
|
messageId: event.data.id,
|
|
78
86
|
chatId: event.data.chat.id,
|
package/src/types.ts
CHANGED
|
@@ -1,5 +1,8 @@
|
|
|
1
1
|
import type {
|
|
2
2
|
Chat,
|
|
3
|
+
SelectionReply,
|
|
4
|
+
MessagePartResponse,
|
|
5
|
+
ReplyTo,
|
|
3
6
|
ChatHandle,
|
|
4
7
|
MessageWebhookData,
|
|
5
8
|
Message,
|
|
@@ -61,6 +64,8 @@ export type RelayMessageReceivedEvent = RelayWebhookEnvelope<
|
|
|
61
64
|
>;
|
|
62
65
|
|
|
63
66
|
export type RelayInboundFacts = {
|
|
67
|
+
selection?: SelectionReply;
|
|
68
|
+
richMessage?: { parts: MessagePartResponse[]; reply_to?: ReplyTo | null };
|
|
64
69
|
eventId: string;
|
|
65
70
|
messageId: string;
|
|
66
71
|
chatId: string;
|