@ravi-hq/ravi 0.4.1 → 0.5.0
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/channels/email.d.ts +65 -11
- package/dist/channels/email.d.ts.map +1 -1
- package/dist/channels/email.js +233 -10
- package/dist/channels/email.js.map +1 -1
- package/dist/channels/sms.d.ts +71 -11
- package/dist/channels/sms.d.ts.map +1 -1
- package/dist/channels/sms.js +232 -10
- package/dist/channels/sms.js.map +1 -1
- package/dist/cli.js +3 -3
- package/dist/index.d.ts +7 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +8 -1
- package/dist/index.js.map +1 -1
- package/dist/runtime.d.ts +34 -0
- package/dist/runtime.d.ts.map +1 -0
- package/dist/runtime.js +41 -0
- package/dist/runtime.js.map +1 -0
- package/dist/tools/identity.js +1 -1
- package/dist/types.d.ts +60 -1
- package/dist/types.d.ts.map +1 -1
- package/package.json +1 -1
package/dist/channels/email.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { RaviClient } from "../client.js";
|
|
2
|
-
import type { EmailEvent } from "../types.js";
|
|
2
|
+
import type { EmailEvent, BaseGatewayContext } from "../types.js";
|
|
3
3
|
/** Configuration for a single email account within the ravi-email channel. */
|
|
4
4
|
export interface EmailAccountConfig {
|
|
5
5
|
/** The identity UUID this account is bound to. */
|
|
@@ -41,6 +41,8 @@ export interface EmailInboundEnvelope {
|
|
|
41
41
|
lastMessageId: number;
|
|
42
42
|
};
|
|
43
43
|
}
|
|
44
|
+
/** Context passed by the ChannelManager to `gateway.startAccount()`. */
|
|
45
|
+
export type EmailGatewayContext = BaseGatewayContext<EmailAccountConfig>;
|
|
44
46
|
/**
|
|
45
47
|
* Creates the ravi-email channel definition for OpenClaw.
|
|
46
48
|
*
|
|
@@ -69,17 +71,22 @@ export declare function createEmailChannel(): {
|
|
|
69
71
|
/**
|
|
70
72
|
* List all configured account IDs (identity UUIDs) for the ravi-email channel.
|
|
71
73
|
*
|
|
72
|
-
*
|
|
74
|
+
* Reads from the plugin config path first (set by `openclaw ravi login`),
|
|
75
|
+
* then falls back to the standard `channels.ravi-email.accounts` path.
|
|
76
|
+
* Deduplicates when both sources contain the same UUID.
|
|
77
|
+
*
|
|
78
|
+
* @param cfg - The full OpenClaw gateway configuration object.
|
|
73
79
|
* @returns Array of identity UUID strings.
|
|
74
80
|
*/
|
|
75
81
|
listAccountIds: (cfg: Record<string, unknown>) => string[];
|
|
76
82
|
/**
|
|
77
83
|
* Resolve an account configuration by its ID (identity UUID).
|
|
78
84
|
*
|
|
79
|
-
* Returns a
|
|
80
|
-
*
|
|
85
|
+
* Returns a minimal config with just the UUID if the account is not
|
|
86
|
+
* found in the standard channels path. The gateway adapter will fetch
|
|
87
|
+
* identity details at startup.
|
|
81
88
|
*
|
|
82
|
-
* @param cfg - The full OpenClaw
|
|
89
|
+
* @param cfg - The full OpenClaw gateway configuration object.
|
|
83
90
|
* @param accountId - The identity UUID to look up.
|
|
84
91
|
* @returns The resolved {@link EmailAccountConfig}.
|
|
85
92
|
*/
|
|
@@ -94,7 +101,7 @@ export declare function createEmailChannel(): {
|
|
|
94
101
|
*
|
|
95
102
|
* @param event - The raw {@link EmailEvent} from the SSE stream.
|
|
96
103
|
* @param account - The {@link EmailAccountConfig} for the receiving identity.
|
|
97
|
-
* @returns A normalized {@link EmailInboundEnvelope}
|
|
104
|
+
* @returns A normalized {@link EmailInboundEnvelope}. Current implementation always returns non-null.
|
|
98
105
|
*/
|
|
99
106
|
normalizeInbound(event: EmailEvent, account: EmailAccountConfig): EmailInboundEnvelope | null;
|
|
100
107
|
outbound: {
|
|
@@ -134,6 +141,27 @@ export declare function createEmailChannel(): {
|
|
|
134
141
|
* @returns The deterministic session key string.
|
|
135
142
|
*/
|
|
136
143
|
getSessionKey(agentId: string, accountId: string, threadId: string): string;
|
|
144
|
+
gateway: {
|
|
145
|
+
/**
|
|
146
|
+
* Start monitoring inbound emails for a single identity account.
|
|
147
|
+
*
|
|
148
|
+
* Called by the ChannelManager once per account. Opens an SSE stream
|
|
149
|
+
* to the Ravi backend, dispatches inbound emails through the OpenClaw
|
|
150
|
+
* reply pipeline, and blocks until the abort signal fires.
|
|
151
|
+
*
|
|
152
|
+
* This gateway adapter is the ChannelManager-driven path, used when
|
|
153
|
+
* OpenClaw manages channel lifecycles directly. The `normalizeInbound` +
|
|
154
|
+
* `RaviListenerService` path in service.ts is the legacy self-managed
|
|
155
|
+
* approach for environments where the gateway doesn't call startAccount.
|
|
156
|
+
*
|
|
157
|
+
* Owner/self senders get full dispatch with reply delivery.
|
|
158
|
+
* External senders trigger an agent turn but reply delivery is suppressed.
|
|
159
|
+
*
|
|
160
|
+
* @param ctx - Gateway context provided by the ChannelManager.
|
|
161
|
+
* @returns Promise that resolves when the account is stopped.
|
|
162
|
+
*/
|
|
163
|
+
startAccount: (ctx: EmailGatewayContext) => Promise<void>;
|
|
164
|
+
};
|
|
137
165
|
};
|
|
138
166
|
/** The singleton ravi-email channel instance. */
|
|
139
167
|
export declare const raviEmailChannel: {
|
|
@@ -152,17 +180,22 @@ export declare const raviEmailChannel: {
|
|
|
152
180
|
/**
|
|
153
181
|
* List all configured account IDs (identity UUIDs) for the ravi-email channel.
|
|
154
182
|
*
|
|
155
|
-
*
|
|
183
|
+
* Reads from the plugin config path first (set by `openclaw ravi login`),
|
|
184
|
+
* then falls back to the standard `channels.ravi-email.accounts` path.
|
|
185
|
+
* Deduplicates when both sources contain the same UUID.
|
|
186
|
+
*
|
|
187
|
+
* @param cfg - The full OpenClaw gateway configuration object.
|
|
156
188
|
* @returns Array of identity UUID strings.
|
|
157
189
|
*/
|
|
158
190
|
listAccountIds: (cfg: Record<string, unknown>) => string[];
|
|
159
191
|
/**
|
|
160
192
|
* Resolve an account configuration by its ID (identity UUID).
|
|
161
193
|
*
|
|
162
|
-
* Returns a
|
|
163
|
-
*
|
|
194
|
+
* Returns a minimal config with just the UUID if the account is not
|
|
195
|
+
* found in the standard channels path. The gateway adapter will fetch
|
|
196
|
+
* identity details at startup.
|
|
164
197
|
*
|
|
165
|
-
* @param cfg - The full OpenClaw
|
|
198
|
+
* @param cfg - The full OpenClaw gateway configuration object.
|
|
166
199
|
* @param accountId - The identity UUID to look up.
|
|
167
200
|
* @returns The resolved {@link EmailAccountConfig}.
|
|
168
201
|
*/
|
|
@@ -177,7 +210,7 @@ export declare const raviEmailChannel: {
|
|
|
177
210
|
*
|
|
178
211
|
* @param event - The raw {@link EmailEvent} from the SSE stream.
|
|
179
212
|
* @param account - The {@link EmailAccountConfig} for the receiving identity.
|
|
180
|
-
* @returns A normalized {@link EmailInboundEnvelope}
|
|
213
|
+
* @returns A normalized {@link EmailInboundEnvelope}. Current implementation always returns non-null.
|
|
181
214
|
*/
|
|
182
215
|
normalizeInbound(event: EmailEvent, account: EmailAccountConfig): EmailInboundEnvelope | null;
|
|
183
216
|
outbound: {
|
|
@@ -217,5 +250,26 @@ export declare const raviEmailChannel: {
|
|
|
217
250
|
* @returns The deterministic session key string.
|
|
218
251
|
*/
|
|
219
252
|
getSessionKey(agentId: string, accountId: string, threadId: string): string;
|
|
253
|
+
gateway: {
|
|
254
|
+
/**
|
|
255
|
+
* Start monitoring inbound emails for a single identity account.
|
|
256
|
+
*
|
|
257
|
+
* Called by the ChannelManager once per account. Opens an SSE stream
|
|
258
|
+
* to the Ravi backend, dispatches inbound emails through the OpenClaw
|
|
259
|
+
* reply pipeline, and blocks until the abort signal fires.
|
|
260
|
+
*
|
|
261
|
+
* This gateway adapter is the ChannelManager-driven path, used when
|
|
262
|
+
* OpenClaw manages channel lifecycles directly. The `normalizeInbound` +
|
|
263
|
+
* `RaviListenerService` path in service.ts is the legacy self-managed
|
|
264
|
+
* approach for environments where the gateway doesn't call startAccount.
|
|
265
|
+
*
|
|
266
|
+
* Owner/self senders get full dispatch with reply delivery.
|
|
267
|
+
* External senders trigger an agent turn but reply delivery is suppressed.
|
|
268
|
+
*
|
|
269
|
+
* @param ctx - Gateway context provided by the ChannelManager.
|
|
270
|
+
* @returns Promise that resolves when the account is stopped.
|
|
271
|
+
*/
|
|
272
|
+
startAccount: (ctx: EmailGatewayContext) => Promise<void>;
|
|
273
|
+
};
|
|
220
274
|
};
|
|
221
275
|
//# sourceMappingURL=email.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"email.d.ts","sourceRoot":"","sources":["../../src/channels/email.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAC/C,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"email.d.ts","sourceRoot":"","sources":["../../src/channels/email.ts"],"names":[],"mappings":"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"}
|
package/dist/channels/email.js
CHANGED
|
@@ -29,30 +29,44 @@ export function createEmailChannel() {
|
|
|
29
29
|
/**
|
|
30
30
|
* List all configured account IDs (identity UUIDs) for the ravi-email channel.
|
|
31
31
|
*
|
|
32
|
-
*
|
|
32
|
+
* Reads from the plugin config path first (set by `openclaw ravi login`),
|
|
33
|
+
* then falls back to the standard `channels.ravi-email.accounts` path.
|
|
34
|
+
* Deduplicates when both sources contain the same UUID.
|
|
35
|
+
*
|
|
36
|
+
* @param cfg - The full OpenClaw gateway configuration object.
|
|
33
37
|
* @returns Array of identity UUID strings.
|
|
34
38
|
*/
|
|
35
39
|
listAccountIds: (cfg) => {
|
|
40
|
+
// Primary: read from plugin config (set by `openclaw ravi login`)
|
|
41
|
+
const plugins = cfg.plugins;
|
|
42
|
+
const uuid = plugins?.entries?.ravi?.config?.identityUuid;
|
|
43
|
+
// Fallback: standard channel accounts path
|
|
36
44
|
const channels = cfg.channels;
|
|
37
|
-
|
|
45
|
+
const channelIds = Object.keys(channels?.["ravi-email"]?.accounts ?? {});
|
|
46
|
+
// Deduplicate — plugin config uuid takes priority
|
|
47
|
+
if (uuid) {
|
|
48
|
+
return [uuid, ...channelIds.filter((id) => id !== uuid)];
|
|
49
|
+
}
|
|
50
|
+
return channelIds;
|
|
38
51
|
},
|
|
39
52
|
/**
|
|
40
53
|
* Resolve an account configuration by its ID (identity UUID).
|
|
41
54
|
*
|
|
42
|
-
* Returns a
|
|
43
|
-
*
|
|
55
|
+
* Returns a minimal config with just the UUID if the account is not
|
|
56
|
+
* found in the standard channels path. The gateway adapter will fetch
|
|
57
|
+
* identity details at startup.
|
|
44
58
|
*
|
|
45
|
-
* @param cfg - The full OpenClaw
|
|
59
|
+
* @param cfg - The full OpenClaw gateway configuration object.
|
|
46
60
|
* @param accountId - The identity UUID to look up.
|
|
47
61
|
* @returns The resolved {@link EmailAccountConfig}.
|
|
48
62
|
*/
|
|
49
63
|
resolveAccount: (cfg, accountId) => {
|
|
50
64
|
const channels = cfg.channels;
|
|
51
65
|
const found = channels?.["ravi-email"]?.accounts?.[accountId];
|
|
52
|
-
if (
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
return
|
|
66
|
+
if (found)
|
|
67
|
+
return found;
|
|
68
|
+
// Fallback: return minimal config — gateway adapter fetches details at startup
|
|
69
|
+
return {
|
|
56
70
|
identityUuid: accountId,
|
|
57
71
|
identityName: "",
|
|
58
72
|
email: "",
|
|
@@ -68,7 +82,7 @@ export function createEmailChannel() {
|
|
|
68
82
|
*
|
|
69
83
|
* @param event - The raw {@link EmailEvent} from the SSE stream.
|
|
70
84
|
* @param account - The {@link EmailAccountConfig} for the receiving identity.
|
|
71
|
-
* @returns A normalized {@link EmailInboundEnvelope}
|
|
85
|
+
* @returns A normalized {@link EmailInboundEnvelope}. Current implementation always returns non-null.
|
|
72
86
|
*/
|
|
73
87
|
normalizeInbound(event, account) {
|
|
74
88
|
const isReadOnly = event.sender_type !== "owner" && event.sender_type !== "self";
|
|
@@ -136,6 +150,215 @@ export function createEmailChannel() {
|
|
|
136
150
|
getSessionKey(agentId, accountId, threadId) {
|
|
137
151
|
return `agent:${agentId}:ravi-email:${accountId}:thread:${threadId}`;
|
|
138
152
|
},
|
|
153
|
+
// ─── Gateway Adapter ──────────────────────────────────────────────────
|
|
154
|
+
gateway: {
|
|
155
|
+
/**
|
|
156
|
+
* Start monitoring inbound emails for a single identity account.
|
|
157
|
+
*
|
|
158
|
+
* Called by the ChannelManager once per account. Opens an SSE stream
|
|
159
|
+
* to the Ravi backend, dispatches inbound emails through the OpenClaw
|
|
160
|
+
* reply pipeline, and blocks until the abort signal fires.
|
|
161
|
+
*
|
|
162
|
+
* This gateway adapter is the ChannelManager-driven path, used when
|
|
163
|
+
* OpenClaw manages channel lifecycles directly. The `normalizeInbound` +
|
|
164
|
+
* `RaviListenerService` path in service.ts is the legacy self-managed
|
|
165
|
+
* approach for environments where the gateway doesn't call startAccount.
|
|
166
|
+
*
|
|
167
|
+
* Owner/self senders get full dispatch with reply delivery.
|
|
168
|
+
* External senders trigger an agent turn but reply delivery is suppressed.
|
|
169
|
+
*
|
|
170
|
+
* @param ctx - Gateway context provided by the ChannelManager.
|
|
171
|
+
* @returns Promise that resolves when the account is stopped.
|
|
172
|
+
*/
|
|
173
|
+
startAccount: async (ctx) => {
|
|
174
|
+
const log = ctx.log ?? {
|
|
175
|
+
info: (...args) => console.log("[ravi-email]", ...args),
|
|
176
|
+
warn: (...args) => console.warn("[ravi-email]", ...args),
|
|
177
|
+
error: (...args) => console.error("[ravi-email]", ...args),
|
|
178
|
+
};
|
|
179
|
+
// Lazy imports — only loaded when the gateway actually starts an account.
|
|
180
|
+
// This avoids pulling in runtime/auth/config/client/sse in test environments
|
|
181
|
+
// where gateway.startAccount() is never called.
|
|
182
|
+
let getRaviRuntime, loadAuth, RAVI_API_URL, RaviClient, RaviSSEClient;
|
|
183
|
+
try {
|
|
184
|
+
({ getRaviRuntime } = await import("../runtime.js"));
|
|
185
|
+
({ loadAuth } = await import("../auth.js"));
|
|
186
|
+
({ RAVI_API_URL } = await import("../config.js"));
|
|
187
|
+
({ RaviClient } = await import("../client.js"));
|
|
188
|
+
({ RaviSSEClient } = await import("../sse.js"));
|
|
189
|
+
}
|
|
190
|
+
catch (err) {
|
|
191
|
+
const detail = err instanceof Error ? err.message : String(err);
|
|
192
|
+
log.error(`[ravi-email] Failed to load dependencies: ${detail}. Is the plugin built correctly?`);
|
|
193
|
+
return;
|
|
194
|
+
}
|
|
195
|
+
const runtime = getRaviRuntime();
|
|
196
|
+
const auth = loadAuth();
|
|
197
|
+
if (!auth?.access_token) {
|
|
198
|
+
log.error("[ravi-email] No auth credentials — cannot start email channel. Run 'openclaw ravi login'.");
|
|
199
|
+
return;
|
|
200
|
+
}
|
|
201
|
+
// Build HTTP client for identity lookup + outbound replies
|
|
202
|
+
const client = new RaviClient({
|
|
203
|
+
apiUrl: RAVI_API_URL,
|
|
204
|
+
token: auth.access_token,
|
|
205
|
+
refreshToken: auth.refresh_token,
|
|
206
|
+
identityUuid: ctx.accountId,
|
|
207
|
+
});
|
|
208
|
+
// Fetch identity details (email address, name) if not in config
|
|
209
|
+
let email = ctx.account.email;
|
|
210
|
+
let identityName = ctx.account.identityName;
|
|
211
|
+
if (!email) {
|
|
212
|
+
try {
|
|
213
|
+
const identities = await client.listIdentities();
|
|
214
|
+
const identity = identities.find((i) => i.uuid === ctx.accountId);
|
|
215
|
+
email = identity?.inbox ?? "";
|
|
216
|
+
identityName = identity?.display_name ?? identity?.name ?? ctx.accountId;
|
|
217
|
+
}
|
|
218
|
+
catch (err) {
|
|
219
|
+
if (err?.name === "RaviApiError") {
|
|
220
|
+
const status = err.status;
|
|
221
|
+
log.error(`[ravi-email] Failed to fetch identity details (HTTP ${status}): ${err.message}` +
|
|
222
|
+
(status === 401 ? ". Token may be expired — run 'openclaw ravi login'." : ""));
|
|
223
|
+
}
|
|
224
|
+
else {
|
|
225
|
+
const detail = err instanceof Error ? err.message : String(err);
|
|
226
|
+
log.error(`[ravi-email] Failed to fetch identity details: ${detail}`);
|
|
227
|
+
}
|
|
228
|
+
return;
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
if (!email) {
|
|
232
|
+
log.error(`[ravi-email] Identity ${ctx.accountId} has no email address — cannot start email channel`);
|
|
233
|
+
return;
|
|
234
|
+
}
|
|
235
|
+
log.info(`[ravi-email] Starting email channel for ${identityName} (${email})`);
|
|
236
|
+
// Build SSE client for real-time events
|
|
237
|
+
const sse = new RaviSSEClient({
|
|
238
|
+
apiUrl: RAVI_API_URL,
|
|
239
|
+
token: auth.access_token,
|
|
240
|
+
identityUuid: ctx.accountId,
|
|
241
|
+
});
|
|
242
|
+
sse.onEmail((event) => {
|
|
243
|
+
try {
|
|
244
|
+
// Classify sender: owner/self get full reply; external/unknown wakes agent but suppresses delivery
|
|
245
|
+
const isAuthorizedSender = event.sender_type === "owner" || event.sender_type === "self";
|
|
246
|
+
const lastMessageId = Number(event.id) || 0;
|
|
247
|
+
if (!lastMessageId) {
|
|
248
|
+
log.warn(`[ravi-email] Event has non-numeric id "${event.id}" — reply threading may fail`);
|
|
249
|
+
}
|
|
250
|
+
const subject = event.subject;
|
|
251
|
+
// Resolve agent route — maps (channel, accountId) → agentId + session key
|
|
252
|
+
const route = runtime.channel.routing.resolveAgentRoute({
|
|
253
|
+
cfg: ctx.cfg,
|
|
254
|
+
channel: "ravi-email",
|
|
255
|
+
accountId: ctx.accountId,
|
|
256
|
+
peer: { kind: "direct", id: event.thread_id },
|
|
257
|
+
});
|
|
258
|
+
const sessionKey = route.sessionKey;
|
|
259
|
+
// Build MsgContext for dispatch
|
|
260
|
+
const msgCtx = {
|
|
261
|
+
Body: event.text_content || event.subject,
|
|
262
|
+
BodyForAgent: event.text_content || event.subject,
|
|
263
|
+
From: `ravi-email:${event.from_email}`,
|
|
264
|
+
To: `ravi-email:${email}`,
|
|
265
|
+
SessionKey: sessionKey,
|
|
266
|
+
AccountId: ctx.accountId,
|
|
267
|
+
ChatType: "direct",
|
|
268
|
+
Provider: "ravi-email",
|
|
269
|
+
Surface: "ravi-email",
|
|
270
|
+
OriginatingChannel: "ravi-email",
|
|
271
|
+
OriginatingTo: ctx.accountId,
|
|
272
|
+
SenderName: event.from_display_name || event.from_email,
|
|
273
|
+
SenderId: event.from_email,
|
|
274
|
+
Timestamp: Date.now(),
|
|
275
|
+
CommandAuthorized: isAuthorizedSender,
|
|
276
|
+
MessageSid: `ravi-email:${event.id}`,
|
|
277
|
+
};
|
|
278
|
+
// Record inbound session so follow-ups route back through this email thread
|
|
279
|
+
try {
|
|
280
|
+
runtime.channel.session.recordInboundSession({
|
|
281
|
+
storePath: runtime.channel.session.resolveStorePath(ctx.cfg.session?.store, { agentId: route.agentId }),
|
|
282
|
+
sessionKey,
|
|
283
|
+
ctx: msgCtx,
|
|
284
|
+
updateLastRoute: {
|
|
285
|
+
sessionKey,
|
|
286
|
+
channel: "ravi-email",
|
|
287
|
+
to: ctx.accountId,
|
|
288
|
+
accountId: ctx.accountId,
|
|
289
|
+
threadId: event.thread_id,
|
|
290
|
+
},
|
|
291
|
+
onRecordError: (err) => {
|
|
292
|
+
const detail = err instanceof Error ? err.message : String(err);
|
|
293
|
+
log.error(`[ravi-email] Session record error for thread ${event.thread_id}: ${detail}`);
|
|
294
|
+
},
|
|
295
|
+
});
|
|
296
|
+
}
|
|
297
|
+
catch (err) {
|
|
298
|
+
const detail = err instanceof Error ? err.message : String(err);
|
|
299
|
+
log.error(`[ravi-email] recordInboundSession threw for thread ${event.thread_id}: ${detail}`);
|
|
300
|
+
}
|
|
301
|
+
// Dispatch — triggers AI agent turn.
|
|
302
|
+
// For external senders: AI wakes up, can use tools, but deliver is suppressed.
|
|
303
|
+
runtime.channel.reply.dispatchReplyWithBufferedBlockDispatcher({
|
|
304
|
+
ctx: msgCtx,
|
|
305
|
+
cfg: ctx.cfg,
|
|
306
|
+
dispatcherOptions: {
|
|
307
|
+
deliver: async (payload) => {
|
|
308
|
+
if (!payload.text) {
|
|
309
|
+
log.info(`[ravi-email] Deliver called with empty text for thread ${event.thread_id} — skipping`);
|
|
310
|
+
return;
|
|
311
|
+
}
|
|
312
|
+
// Suppress reply delivery for external senders
|
|
313
|
+
if (!isAuthorizedSender) {
|
|
314
|
+
log.info(`[ravi-email] Suppressing reply to external sender ${event.from_email}`);
|
|
315
|
+
return;
|
|
316
|
+
}
|
|
317
|
+
try {
|
|
318
|
+
await client.replyToEmail(lastMessageId, wrapInHtml(payload.text), subject);
|
|
319
|
+
}
|
|
320
|
+
catch (err) {
|
|
321
|
+
const detail = err instanceof Error ? err.message : String(err);
|
|
322
|
+
const status = err?.status;
|
|
323
|
+
log.error(`[ravi-email] Failed to deliver reply to thread ${event.thread_id}` +
|
|
324
|
+
`${status ? ` (HTTP ${status})` : ""}: ${detail}`);
|
|
325
|
+
}
|
|
326
|
+
},
|
|
327
|
+
onError: (err) => {
|
|
328
|
+
log.error(`[ravi-email] Dispatch error: ${err}`);
|
|
329
|
+
},
|
|
330
|
+
},
|
|
331
|
+
}).catch((err) => {
|
|
332
|
+
const detail = err instanceof Error ? err.message : String(err);
|
|
333
|
+
log.error(`[ravi-email] dispatchReply failed for thread ${event.thread_id}: ${detail}`);
|
|
334
|
+
});
|
|
335
|
+
}
|
|
336
|
+
catch (err) {
|
|
337
|
+
const detail = err instanceof Error ? err.message : String(err);
|
|
338
|
+
log.error(`[ravi-email] Unhandled error processing event ${event.id}: ${detail}`);
|
|
339
|
+
}
|
|
340
|
+
});
|
|
341
|
+
sse.onReconnect(() => {
|
|
342
|
+
log.info(`[ravi-email] SSE reconnecting for ${identityName}`);
|
|
343
|
+
});
|
|
344
|
+
sse.connect();
|
|
345
|
+
log.info(`[ravi-email] SSE connected for ${identityName} (${ctx.accountId})`);
|
|
346
|
+
// Block until gateway signals shutdown
|
|
347
|
+
await new Promise((resolve) => {
|
|
348
|
+
if (ctx.abortSignal.aborted) {
|
|
349
|
+
log.info(`[ravi-email] Stopping email channel for ${identityName} (already aborted)`);
|
|
350
|
+
sse.disconnect();
|
|
351
|
+
resolve();
|
|
352
|
+
return;
|
|
353
|
+
}
|
|
354
|
+
ctx.abortSignal.addEventListener("abort", () => {
|
|
355
|
+
log.info(`[ravi-email] Stopping email channel for ${identityName}`);
|
|
356
|
+
sse.disconnect();
|
|
357
|
+
resolve();
|
|
358
|
+
});
|
|
359
|
+
});
|
|
360
|
+
},
|
|
361
|
+
},
|
|
139
362
|
};
|
|
140
363
|
}
|
|
141
364
|
/** The singleton ravi-email channel instance. */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"email.js","sourceRoot":"","sources":["../../src/channels/email.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"email.js","sourceRoot":"","sources":["../../src/channels/email.ts"],"names":[],"mappings":"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"}
|
package/dist/channels/sms.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { RaviClient } from "../client.js";
|
|
2
|
-
import type { SmsEvent } from "../types.js";
|
|
2
|
+
import type { SmsEvent, BaseGatewayContext } from "../types.js";
|
|
3
3
|
/** Configuration for a single SMS account within the ravi-sms channel. */
|
|
4
4
|
export interface SmsAccountConfig {
|
|
5
5
|
/** The identity UUID this account is bound to. */
|
|
@@ -35,6 +35,8 @@ export interface SmsInboundEnvelope {
|
|
|
35
35
|
conversationId: string;
|
|
36
36
|
};
|
|
37
37
|
}
|
|
38
|
+
/** Context passed by the ChannelManager to `gateway.startAccount()`. */
|
|
39
|
+
export type SmsGatewayContext = BaseGatewayContext<SmsAccountConfig>;
|
|
38
40
|
/**
|
|
39
41
|
* Creates the ravi-sms channel definition for OpenClaw.
|
|
40
42
|
*
|
|
@@ -63,17 +65,22 @@ export declare function createSmsChannel(): {
|
|
|
63
65
|
/**
|
|
64
66
|
* List all configured account IDs (identity UUIDs) for the ravi-sms channel.
|
|
65
67
|
*
|
|
66
|
-
*
|
|
68
|
+
* Reads from the plugin config path first (set by `openclaw ravi login`),
|
|
69
|
+
* then falls back to the standard `channels.ravi-sms.accounts` path.
|
|
70
|
+
* Deduplicates when both sources contain the same UUID.
|
|
71
|
+
*
|
|
72
|
+
* @param cfg - The full OpenClaw gateway configuration object.
|
|
67
73
|
* @returns Array of identity UUID strings.
|
|
68
74
|
*/
|
|
69
75
|
listAccountIds: (cfg: Record<string, unknown>) => string[];
|
|
70
76
|
/**
|
|
71
77
|
* Resolve an account configuration by its ID (identity UUID).
|
|
72
78
|
*
|
|
73
|
-
* Returns a
|
|
74
|
-
*
|
|
79
|
+
* Returns a minimal config with just the UUID if the account is not
|
|
80
|
+
* found in the standard channels path. The gateway adapter will fetch
|
|
81
|
+
* identity details at startup.
|
|
75
82
|
*
|
|
76
|
-
* @param cfg - The full OpenClaw
|
|
83
|
+
* @param cfg - The full OpenClaw gateway configuration object.
|
|
77
84
|
* @param accountId - The identity UUID to look up.
|
|
78
85
|
* @returns The resolved {@link SmsAccountConfig}.
|
|
79
86
|
*/
|
|
@@ -88,7 +95,7 @@ export declare function createSmsChannel(): {
|
|
|
88
95
|
*
|
|
89
96
|
* @param event - The raw {@link SmsEvent} from the SSE stream.
|
|
90
97
|
* @param account - The {@link SmsAccountConfig} for the receiving identity.
|
|
91
|
-
* @returns A normalized {@link SmsInboundEnvelope}
|
|
98
|
+
* @returns A normalized {@link SmsInboundEnvelope}. Current implementation always returns non-null.
|
|
92
99
|
*/
|
|
93
100
|
normalizeInbound(event: SmsEvent, account: SmsAccountConfig): SmsInboundEnvelope | null;
|
|
94
101
|
outbound: {
|
|
@@ -132,6 +139,30 @@ export declare function createSmsChannel(): {
|
|
|
132
139
|
* @returns The deterministic session key string.
|
|
133
140
|
*/
|
|
134
141
|
getSessionKey(agentId: string, accountId: string, phoneNumber: string): string;
|
|
142
|
+
gateway: {
|
|
143
|
+
/**
|
|
144
|
+
* Start monitoring inbound SMS for a single identity account.
|
|
145
|
+
*
|
|
146
|
+
* Called by the ChannelManager once per account. Opens an SSE stream
|
|
147
|
+
* to the Ravi backend, dispatches inbound SMS through the OpenClaw
|
|
148
|
+
* reply pipeline, and blocks until the abort signal fires.
|
|
149
|
+
*
|
|
150
|
+
* Bails out early if the identity has no phone number — SMS requires
|
|
151
|
+
* a provisioned phone number.
|
|
152
|
+
*
|
|
153
|
+
* Owner/self senders get full dispatch with reply delivery.
|
|
154
|
+
* External senders trigger an agent turn but reply delivery is suppressed.
|
|
155
|
+
*
|
|
156
|
+
* This gateway adapter is the ChannelManager-driven path, used when
|
|
157
|
+
* OpenClaw manages channel lifecycles directly. The `normalizeInbound` +
|
|
158
|
+
* `RaviListenerService` path in service.ts is the legacy self-managed
|
|
159
|
+
* approach for environments where the gateway doesn't call startAccount.
|
|
160
|
+
*
|
|
161
|
+
* @param ctx - Gateway context provided by the ChannelManager.
|
|
162
|
+
* @returns Promise that resolves when the account is stopped.
|
|
163
|
+
*/
|
|
164
|
+
startAccount: (ctx: SmsGatewayContext) => Promise<void>;
|
|
165
|
+
};
|
|
135
166
|
};
|
|
136
167
|
/** The singleton ravi-sms channel instance. */
|
|
137
168
|
export declare const raviSmsChannel: {
|
|
@@ -150,17 +181,22 @@ export declare const raviSmsChannel: {
|
|
|
150
181
|
/**
|
|
151
182
|
* List all configured account IDs (identity UUIDs) for the ravi-sms channel.
|
|
152
183
|
*
|
|
153
|
-
*
|
|
184
|
+
* Reads from the plugin config path first (set by `openclaw ravi login`),
|
|
185
|
+
* then falls back to the standard `channels.ravi-sms.accounts` path.
|
|
186
|
+
* Deduplicates when both sources contain the same UUID.
|
|
187
|
+
*
|
|
188
|
+
* @param cfg - The full OpenClaw gateway configuration object.
|
|
154
189
|
* @returns Array of identity UUID strings.
|
|
155
190
|
*/
|
|
156
191
|
listAccountIds: (cfg: Record<string, unknown>) => string[];
|
|
157
192
|
/**
|
|
158
193
|
* Resolve an account configuration by its ID (identity UUID).
|
|
159
194
|
*
|
|
160
|
-
* Returns a
|
|
161
|
-
*
|
|
195
|
+
* Returns a minimal config with just the UUID if the account is not
|
|
196
|
+
* found in the standard channels path. The gateway adapter will fetch
|
|
197
|
+
* identity details at startup.
|
|
162
198
|
*
|
|
163
|
-
* @param cfg - The full OpenClaw
|
|
199
|
+
* @param cfg - The full OpenClaw gateway configuration object.
|
|
164
200
|
* @param accountId - The identity UUID to look up.
|
|
165
201
|
* @returns The resolved {@link SmsAccountConfig}.
|
|
166
202
|
*/
|
|
@@ -175,7 +211,7 @@ export declare const raviSmsChannel: {
|
|
|
175
211
|
*
|
|
176
212
|
* @param event - The raw {@link SmsEvent} from the SSE stream.
|
|
177
213
|
* @param account - The {@link SmsAccountConfig} for the receiving identity.
|
|
178
|
-
* @returns A normalized {@link SmsInboundEnvelope}
|
|
214
|
+
* @returns A normalized {@link SmsInboundEnvelope}. Current implementation always returns non-null.
|
|
179
215
|
*/
|
|
180
216
|
normalizeInbound(event: SmsEvent, account: SmsAccountConfig): SmsInboundEnvelope | null;
|
|
181
217
|
outbound: {
|
|
@@ -219,5 +255,29 @@ export declare const raviSmsChannel: {
|
|
|
219
255
|
* @returns The deterministic session key string.
|
|
220
256
|
*/
|
|
221
257
|
getSessionKey(agentId: string, accountId: string, phoneNumber: string): string;
|
|
258
|
+
gateway: {
|
|
259
|
+
/**
|
|
260
|
+
* Start monitoring inbound SMS for a single identity account.
|
|
261
|
+
*
|
|
262
|
+
* Called by the ChannelManager once per account. Opens an SSE stream
|
|
263
|
+
* to the Ravi backend, dispatches inbound SMS through the OpenClaw
|
|
264
|
+
* reply pipeline, and blocks until the abort signal fires.
|
|
265
|
+
*
|
|
266
|
+
* Bails out early if the identity has no phone number — SMS requires
|
|
267
|
+
* a provisioned phone number.
|
|
268
|
+
*
|
|
269
|
+
* Owner/self senders get full dispatch with reply delivery.
|
|
270
|
+
* External senders trigger an agent turn but reply delivery is suppressed.
|
|
271
|
+
*
|
|
272
|
+
* This gateway adapter is the ChannelManager-driven path, used when
|
|
273
|
+
* OpenClaw manages channel lifecycles directly. The `normalizeInbound` +
|
|
274
|
+
* `RaviListenerService` path in service.ts is the legacy self-managed
|
|
275
|
+
* approach for environments where the gateway doesn't call startAccount.
|
|
276
|
+
*
|
|
277
|
+
* @param ctx - Gateway context provided by the ChannelManager.
|
|
278
|
+
* @returns Promise that resolves when the account is stopped.
|
|
279
|
+
*/
|
|
280
|
+
startAccount: (ctx: SmsGatewayContext) => Promise<void>;
|
|
281
|
+
};
|
|
222
282
|
};
|
|
223
283
|
//# sourceMappingURL=sms.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sms.d.ts","sourceRoot":"","sources":["../../src/channels/sms.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAC/C,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"sms.d.ts","sourceRoot":"","sources":["../../src/channels/sms.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAC/C,OAAO,KAAK,EAAE,QAAQ,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAC;AAIhE,0EAA0E;AAC1E,MAAM,WAAW,gBAAgB;IAC/B,kDAAkD;IAClD,YAAY,EAAE,MAAM,CAAC;IACrB,yDAAyD;IACzD,YAAY,EAAE,MAAM,CAAC;IACrB,qEAAqE;IACrE,KAAK,EAAE,MAAM,CAAC;CAEf;AAED;;;;;;GAMG;AACH,MAAM,WAAW,gBAAgB;IAC/B,qDAAqD;IACrD,WAAW,EAAE,MAAM,CAAC;CACrB;AAID,gFAAgF;AAChF,MAAM,WAAW,kBAAkB;IACjC,qDAAqD;IACrD,QAAQ,EAAE,MAAM,CAAC;IACjB,0CAA0C;IAC1C,IAAI,EAAE,MAAM,CAAC;IACb,0DAA0D;IAC1D,QAAQ,EAAE,MAAM,CAAC;IACjB,2DAA2D;IAC3D,QAAQ,EAAE;QACR,UAAU,EAAE,MAAM,CAAC;QACnB,QAAQ,EAAE,OAAO,CAAC;QAClB,cAAc,EAAE,MAAM,CAAC;KACxB,CAAC;CACH;AAID,wEAAwE;AACxE,MAAM,MAAM,iBAAiB,GAAG,kBAAkB,CAAC,gBAAgB,CAAC,CAAC;AAIrE;;;;;;;;;;;GAWG;AACH,wBAAgB,gBAAgB;;;;;;;;;;;;;QAkB1B;;;;;;;;;WASG;8BACmB,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAG,MAAM,EAAE;QAoBxD;;;;;;;;;;WAUG;8BAEI,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,aACjB,MAAM,KAChB,gBAAgB;;IAgBrB;;;;;;;;;;OAUG;4BAEM,QAAQ,WACN,gBAAgB,GACxB,kBAAkB,GAAG,IAAI;;;QAkB1B;;;;;;;;;;WAUG;2BACsB;YACvB,IAAI,EAAE,MAAM,CAAC;YACb,MAAM,EAAE,UAAU,CAAC;YACnB,aAAa,CAAC,EAAE,gBAAgB,CAAC;SAClC,KAAG,OAAO,CAAC;YAAE,EAAE,EAAE,OAAO,CAAC;YAAC,KAAK,CAAC,EAAE,MAAM,CAAA;SAAE,CAAC;;IAoB9C;;;;;;;;;;;;;;;;;OAiBG;2BACoB,MAAM,aAAa,MAAM,eAAe,MAAM,GAAG,MAAM;;QAO5E;;;;;;;;;;;;;;;;;;;;WAoBG;4BACuB,iBAAiB,KAAG,OAAO,CAAC,IAAI,CAAC;;EA2MhE;AAED,+CAA+C;AAC/C,eAAO,MAAM,cAAc;;;;;;;;;;;;;QA3XrB;;;;;;;;;WASG;8BACmB,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAG,MAAM,EAAE;QAoBxD;;;;;;;;;;WAUG;8BAEI,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,aACjB,MAAM,KAChB,gBAAgB;;IAgBrB;;;;;;;;;;OAUG;4BAEM,QAAQ,WACN,gBAAgB,GACxB,kBAAkB,GAAG,IAAI;;;QAkB1B;;;;;;;;;;WAUG;2BACsB;YACvB,IAAI,EAAE,MAAM,CAAC;YACb,MAAM,EAAE,UAAU,CAAC;YACnB,aAAa,CAAC,EAAE,gBAAgB,CAAC;SAClC,KAAG,OAAO,CAAC;YAAE,EAAE,EAAE,OAAO,CAAC;YAAC,KAAK,CAAC,EAAE,MAAM,CAAA;SAAE,CAAC;;IAoB9C;;;;;;;;;;;;;;;;;OAiBG;2BACoB,MAAM,aAAa,MAAM,eAAe,MAAM,GAAG,MAAM;;QAO5E;;;;;;;;;;;;;;;;;;;;WAoBG;4BACuB,iBAAiB,KAAG,OAAO,CAAC,IAAI,CAAC;;CA8MjB,CAAC"}
|