@wooters/crabcallr 0.1.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/LICENSE +21 -0
- package/README.md +136 -0
- package/dist/channel.d.ts +28 -0
- package/dist/channel.d.ts.map +1 -0
- package/dist/channel.js +448 -0
- package/dist/channel.js.map +1 -0
- package/dist/config.d.ts +17 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +53 -0
- package/dist/config.js.map +1 -0
- package/dist/index.d.ts +44 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +55 -0
- package/dist/index.js.map +1 -0
- package/dist/runtime.d.ts +4 -0
- package/dist/runtime.d.ts.map +1 -0
- package/dist/runtime.js +11 -0
- package/dist/runtime.js.map +1 -0
- package/dist/types.d.ts +107 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +19 -0
- package/dist/types.js.map +1 -0
- package/dist/websocket.d.ts +77 -0
- package/dist/websocket.d.ts.map +1 -0
- package/dist/websocket.js +318 -0
- package/dist/websocket.js.map +1 -0
- package/openclaw.plugin.json +13 -0
- package/package.json +76 -0
- package/skills/crabcallr/SKILL.md +84 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Chuck Wooters
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
# CrabCallr Plugin for OpenClaw
|
|
2
|
+
|
|
3
|
+
Talk to your OpenClaw assistant via phone or browser with CrabCallr.
|
|
4
|
+
|
|
5
|
+
## Overview
|
|
6
|
+
|
|
7
|
+
CrabCallr is a voice interface that lets you have natural conversations with your OpenClaw assistant. This plugin connects your OpenClaw instance to the CrabCallr hosted service, enabling:
|
|
8
|
+
|
|
9
|
+
- **Browser calling** - Talk to OpenClaw from any web browser via WebRTC
|
|
10
|
+
- **Phone calling** - Call a phone number to reach your assistant (Basic tier)
|
|
11
|
+
- **Streaming speech recognition** - Real-time transcription with Deepgram
|
|
12
|
+
- **Natural voice responses** - High-quality text-to-speech with ElevenLabs
|
|
13
|
+
- **Barge-in support** - Interrupt the assistant mid-response
|
|
14
|
+
|
|
15
|
+
## Installation
|
|
16
|
+
|
|
17
|
+
```bash
|
|
18
|
+
openclaw plugins install @wooters/crabcallr
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
## Setup
|
|
22
|
+
|
|
23
|
+
1. **Get an API key** - Sign up at [app.crabcallr.com](https://app.crabcallr.com) and generate an API key
|
|
24
|
+
|
|
25
|
+
2. **Configure the plugin** - Add to your `~/.openclaw/openclaw.json`:
|
|
26
|
+
|
|
27
|
+
```json
|
|
28
|
+
{
|
|
29
|
+
"channels": {
|
|
30
|
+
"crabcallr": {
|
|
31
|
+
"accounts": {
|
|
32
|
+
"default": {
|
|
33
|
+
"apiKey": "cc_your_api_key_here"
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
3. **Restart OpenClaw Gateway** - The plugin will automatically connect to the CrabCallr service
|
|
42
|
+
|
|
43
|
+
4. **Start calling** - Visit [app.crabcallr.com](https://app.crabcallr.com) and click "Call" to talk to your assistant
|
|
44
|
+
|
|
45
|
+
## Configuration Options
|
|
46
|
+
|
|
47
|
+
| Option | Type | Default | Description |
|
|
48
|
+
| ---------------------- | ------- | ------------------------------- | -------------------------------------- |
|
|
49
|
+
| `apiKey` | string | (required) | Your CrabCallr API key |
|
|
50
|
+
| `serviceUrl` | string | `wss://ws.crabcallr.com/plugin` | WebSocket URL for the service |
|
|
51
|
+
| `autoConnect` | boolean | `true` | Connect automatically on startup |
|
|
52
|
+
| `reconnectInterval` | number | `5000` | Reconnection interval in ms |
|
|
53
|
+
| `maxReconnectAttempts` | number | `10` | Max reconnect attempts (0 = unlimited) |
|
|
54
|
+
|
|
55
|
+
## CLI Commands
|
|
56
|
+
|
|
57
|
+
Check connection status:
|
|
58
|
+
|
|
59
|
+
```bash
|
|
60
|
+
openclaw channels status --probe
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
## How It Works
|
|
64
|
+
|
|
65
|
+
```plaintext
|
|
66
|
+
┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐
|
|
67
|
+
│ Your Phone │────▶│ CrabCallr │────▶│ Your │
|
|
68
|
+
│ or Browser │◀────│ Service │◀────│ OpenClaw │
|
|
69
|
+
└─────────────────┘ └─────────────────┘ └─────────────────┘
|
|
70
|
+
│ │ │
|
|
71
|
+
│ Audio/WebRTC │ WebSocket │ Messages
|
|
72
|
+
│ │ │
|
|
73
|
+
You speak Transcribed text OpenClaw responds
|
|
74
|
+
You hear Response audio via this plugin
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
1. You speak into your phone or browser
|
|
78
|
+
2. CrabCallr transcribes your speech in real-time (Deepgram)
|
|
79
|
+
3. The transcript is sent to your OpenClaw via this plugin
|
|
80
|
+
4. OpenClaw processes your request and generates a response
|
|
81
|
+
5. The response is sent back to CrabCallr
|
|
82
|
+
6. CrabCallr converts the response to speech (ElevenLabs)
|
|
83
|
+
7. You hear the response
|
|
84
|
+
|
|
85
|
+
## Voice Skill
|
|
86
|
+
|
|
87
|
+
This plugin includes a voice skill that automatically adapts OpenClaw's responses for spoken conversation:
|
|
88
|
+
|
|
89
|
+
- Concise, conversational responses (1-3 sentences)
|
|
90
|
+
- No bullet points, markdown, or code blocks
|
|
91
|
+
- Natural speech patterns with contractions
|
|
92
|
+
- Graceful handling of interruptions
|
|
93
|
+
|
|
94
|
+
The skill is automatically loaded when the plugin is enabled.
|
|
95
|
+
|
|
96
|
+
## Pricing
|
|
97
|
+
|
|
98
|
+
- **Free tier** - 30 min/month browser calling via WebRTC
|
|
99
|
+
- **Basic tier** ($5/month) - 120 min browser + 30 min phone calling, $0.15/minute overage
|
|
100
|
+
|
|
101
|
+
See [crabcallr.com](https://crabcallr.com) for current pricing.
|
|
102
|
+
|
|
103
|
+
## Troubleshooting
|
|
104
|
+
|
|
105
|
+
### Plugin won't connect
|
|
106
|
+
|
|
107
|
+
- Verify your API key is correct (should start with `cc_`)
|
|
108
|
+
- Check that your OpenClaw Gateway can reach `ws.crabcallr.com`
|
|
109
|
+
- Run `openclaw channels status --probe` to see connection details
|
|
110
|
+
|
|
111
|
+
### No response from assistant
|
|
112
|
+
|
|
113
|
+
- Ensure your OpenClaw agent is configured and working
|
|
114
|
+
- Check OpenClaw logs for errors processing messages
|
|
115
|
+
|
|
116
|
+
### Poor audio quality
|
|
117
|
+
|
|
118
|
+
- Use a quiet environment or headphones
|
|
119
|
+
- Browser calling typically has better quality than phone
|
|
120
|
+
|
|
121
|
+
## Development
|
|
122
|
+
|
|
123
|
+
```bash
|
|
124
|
+
# Install dependencies
|
|
125
|
+
npm install
|
|
126
|
+
|
|
127
|
+
# Build
|
|
128
|
+
npm run build
|
|
129
|
+
|
|
130
|
+
# Watch mode
|
|
131
|
+
npm run dev
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
## License
|
|
135
|
+
|
|
136
|
+
MIT
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import type { ChannelPlugin } from "openclaw/plugin-sdk";
|
|
2
|
+
import type { CrabCallrAccountConfig, ConnectionStatus } from "./types.js";
|
|
3
|
+
type ResolvedCrabCallrAccount = {
|
|
4
|
+
accountId: string;
|
|
5
|
+
name?: string;
|
|
6
|
+
enabled: boolean;
|
|
7
|
+
configured: boolean;
|
|
8
|
+
config: CrabCallrAccountConfig;
|
|
9
|
+
};
|
|
10
|
+
export declare function getCrabCallrStatus(accountId?: string): {
|
|
11
|
+
accountId: string;
|
|
12
|
+
connected: boolean;
|
|
13
|
+
status: ConnectionStatus;
|
|
14
|
+
userId: string | null;
|
|
15
|
+
running: boolean;
|
|
16
|
+
reconnectAttempts: number;
|
|
17
|
+
};
|
|
18
|
+
export declare function sendCrabCallrResponse(params: {
|
|
19
|
+
accountId?: string;
|
|
20
|
+
requestId: string;
|
|
21
|
+
text: string;
|
|
22
|
+
}): {
|
|
23
|
+
ok: boolean;
|
|
24
|
+
error?: string;
|
|
25
|
+
};
|
|
26
|
+
export declare const crabcallrPlugin: ChannelPlugin<ResolvedCrabCallrAccount>;
|
|
27
|
+
export {};
|
|
28
|
+
//# sourceMappingURL=channel.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"channel.d.ts","sourceRoot":"","sources":["../src/channel.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAGV,aAAa,EAGd,MAAM,qBAAqB,CAAC;AAQ7B,OAAO,KAAK,EACV,sBAAsB,EAEtB,gBAAgB,EACjB,MAAM,YAAY,CAAC;AAKpB,KAAK,wBAAwB,GAAG;IAC9B,SAAS,EAAE,MAAM,CAAC;IAClB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,OAAO,CAAC;IACjB,UAAU,EAAE,OAAO,CAAC;IACpB,MAAM,EAAE,sBAAsB,CAAC;CAChC,CAAC;AA4RF,wBAAgB,kBAAkB,CAAC,SAAS,CAAC,EAAE,MAAM,GAAG;IACtD,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,OAAO,CAAC;IACnB,MAAM,EAAE,gBAAgB,CAAC;IACzB,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,OAAO,EAAE,OAAO,CAAC;IACjB,iBAAiB,EAAE,MAAM,CAAC;CAC3B,CAqBA;AAED,wBAAgB,qBAAqB,CAAC,MAAM,EAAE;IAC5C,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;IAClB,IAAI,EAAE,MAAM,CAAC;CACd,GAAG;IAAE,EAAE,EAAE,OAAO,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAA;CAAE,CAYlC;AAED,eAAO,MAAM,eAAe,EAAE,aAAa,CAAC,wBAAwB,CAgNnE,CAAC"}
|
package/dist/channel.js
ADDED
|
@@ -0,0 +1,448 @@
|
|
|
1
|
+
import { Type } from "@sinclair/typebox";
|
|
2
|
+
import { createReplyPrefixOptions, DEFAULT_ACCOUNT_ID, normalizeAccountId, } from "openclaw/plugin-sdk";
|
|
3
|
+
import { validateConfig } from "./config.js";
|
|
4
|
+
import { getCrabCallrRuntime } from "./runtime.js";
|
|
5
|
+
import { CrabCallrWebSocket } from "./websocket.js";
|
|
6
|
+
const CHANNEL_ID = "crabcallr";
|
|
7
|
+
const connections = new Map();
|
|
8
|
+
const CrabCallrAccountSchema = Type.Object({
|
|
9
|
+
name: Type.Optional(Type.String()),
|
|
10
|
+
enabled: Type.Optional(Type.Boolean()),
|
|
11
|
+
apiKey: Type.Optional(Type.String({
|
|
12
|
+
description: "Your CrabCallr API key from app.crabcallr.com",
|
|
13
|
+
})),
|
|
14
|
+
serviceUrl: Type.Optional(Type.String({
|
|
15
|
+
description: "CrabCallr service WebSocket URL",
|
|
16
|
+
default: "wss://ws.crabcallr.com/plugin",
|
|
17
|
+
})),
|
|
18
|
+
autoConnect: Type.Optional(Type.Boolean({
|
|
19
|
+
description: "Automatically connect to CrabCallr service on startup",
|
|
20
|
+
default: true,
|
|
21
|
+
})),
|
|
22
|
+
reconnectInterval: Type.Optional(Type.Number({
|
|
23
|
+
description: "Reconnection interval in milliseconds",
|
|
24
|
+
default: 5000,
|
|
25
|
+
})),
|
|
26
|
+
maxReconnectAttempts: Type.Optional(Type.Number({
|
|
27
|
+
description: "Maximum number of reconnection attempts (0 for unlimited)",
|
|
28
|
+
default: 10,
|
|
29
|
+
})),
|
|
30
|
+
}, { additionalProperties: false });
|
|
31
|
+
const CrabCallrChannelSchema = Type.Object({
|
|
32
|
+
...CrabCallrAccountSchema.properties,
|
|
33
|
+
accounts: Type.Optional(Type.Record(Type.String(), CrabCallrAccountSchema)),
|
|
34
|
+
}, { additionalProperties: false });
|
|
35
|
+
const crabcallrConfigSchema = {
|
|
36
|
+
schema: CrabCallrChannelSchema,
|
|
37
|
+
uiHints: {
|
|
38
|
+
apiKey: {
|
|
39
|
+
label: "CrabCallr API Key",
|
|
40
|
+
sensitive: true,
|
|
41
|
+
placeholder: "cc_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
|
|
42
|
+
},
|
|
43
|
+
serviceUrl: {
|
|
44
|
+
label: "Service URL",
|
|
45
|
+
advanced: true,
|
|
46
|
+
},
|
|
47
|
+
autoConnect: {
|
|
48
|
+
label: "Auto-connect on startup",
|
|
49
|
+
},
|
|
50
|
+
reconnectInterval: {
|
|
51
|
+
label: "Reconnect interval (ms)",
|
|
52
|
+
advanced: true,
|
|
53
|
+
},
|
|
54
|
+
maxReconnectAttempts: {
|
|
55
|
+
label: "Max reconnect attempts",
|
|
56
|
+
advanced: true,
|
|
57
|
+
},
|
|
58
|
+
},
|
|
59
|
+
};
|
|
60
|
+
function resolveChannelConfig(cfg) {
|
|
61
|
+
const channel = cfg.channels?.crabcallr;
|
|
62
|
+
if (!channel || typeof channel !== "object") {
|
|
63
|
+
return {};
|
|
64
|
+
}
|
|
65
|
+
return channel;
|
|
66
|
+
}
|
|
67
|
+
function hasBaseConfig(cfg) {
|
|
68
|
+
return Boolean(cfg.apiKey ||
|
|
69
|
+
cfg.serviceUrl ||
|
|
70
|
+
typeof cfg.autoConnect === "boolean" ||
|
|
71
|
+
typeof cfg.reconnectInterval === "number" ||
|
|
72
|
+
typeof cfg.maxReconnectAttempts === "number" ||
|
|
73
|
+
typeof cfg.enabled === "boolean" ||
|
|
74
|
+
cfg.name);
|
|
75
|
+
}
|
|
76
|
+
function listCrabCallrAccountIds(cfg) {
|
|
77
|
+
const channel = resolveChannelConfig(cfg);
|
|
78
|
+
const ids = new Set();
|
|
79
|
+
if (hasBaseConfig(channel)) {
|
|
80
|
+
ids.add(DEFAULT_ACCOUNT_ID);
|
|
81
|
+
}
|
|
82
|
+
const accounts = channel.accounts;
|
|
83
|
+
if (accounts && typeof accounts === "object") {
|
|
84
|
+
for (const key of Object.keys(accounts)) {
|
|
85
|
+
if (!key) {
|
|
86
|
+
continue;
|
|
87
|
+
}
|
|
88
|
+
ids.add(normalizeAccountId(key));
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
if (ids.size === 0) {
|
|
92
|
+
ids.add(DEFAULT_ACCOUNT_ID);
|
|
93
|
+
}
|
|
94
|
+
return [...ids].sort((a, b) => a.localeCompare(b));
|
|
95
|
+
}
|
|
96
|
+
function resolveAccountConfig(cfg, accountId) {
|
|
97
|
+
const channel = resolveChannelConfig(cfg);
|
|
98
|
+
const { accounts: _ignored, ...base } = channel;
|
|
99
|
+
const accounts = channel.accounts ?? {};
|
|
100
|
+
const direct = accounts[accountId];
|
|
101
|
+
if (direct) {
|
|
102
|
+
return { ...base, ...direct };
|
|
103
|
+
}
|
|
104
|
+
const normalized = normalizeAccountId(accountId);
|
|
105
|
+
const matchKey = Object.keys(accounts).find((key) => normalizeAccountId(key) === normalized);
|
|
106
|
+
const resolved = matchKey ? accounts[matchKey] : undefined;
|
|
107
|
+
return { ...base, ...(resolved ?? {}) };
|
|
108
|
+
}
|
|
109
|
+
function resolveDefaultCrabCallrAccountId(cfg) {
|
|
110
|
+
const ids = listCrabCallrAccountIds(cfg);
|
|
111
|
+
if (ids.includes(DEFAULT_ACCOUNT_ID)) {
|
|
112
|
+
return DEFAULT_ACCOUNT_ID;
|
|
113
|
+
}
|
|
114
|
+
return ids[0] ?? DEFAULT_ACCOUNT_ID;
|
|
115
|
+
}
|
|
116
|
+
function resolveCrabCallrAccount(params) {
|
|
117
|
+
const id = normalizeAccountId(params.accountId ?? DEFAULT_ACCOUNT_ID);
|
|
118
|
+
const merged = resolveAccountConfig(params.cfg, id);
|
|
119
|
+
const channel = resolveChannelConfig(params.cfg);
|
|
120
|
+
const enabled = (channel.enabled ?? true) && merged.enabled !== false;
|
|
121
|
+
const configured = Boolean(merged.apiKey?.trim());
|
|
122
|
+
return {
|
|
123
|
+
accountId: id,
|
|
124
|
+
name: merged.name?.trim() || undefined,
|
|
125
|
+
enabled,
|
|
126
|
+
configured,
|
|
127
|
+
config: merged,
|
|
128
|
+
};
|
|
129
|
+
}
|
|
130
|
+
function createStatusSink(ctx) {
|
|
131
|
+
return (patch) => {
|
|
132
|
+
const base = ctx.getStatus?.() ?? { accountId: ctx.accountId };
|
|
133
|
+
ctx.setStatus?.({ ...base, ...patch, accountId: ctx.accountId });
|
|
134
|
+
};
|
|
135
|
+
}
|
|
136
|
+
async function handleRequest(params) {
|
|
137
|
+
const { cfg, accountId, requestId, text, callId, ws, statusSink, logError } = params;
|
|
138
|
+
const core = getCrabCallrRuntime();
|
|
139
|
+
const route = core.channel.routing.resolveAgentRoute({
|
|
140
|
+
cfg,
|
|
141
|
+
channel: CHANNEL_ID,
|
|
142
|
+
accountId,
|
|
143
|
+
peer: {
|
|
144
|
+
kind: "dm",
|
|
145
|
+
id: callId,
|
|
146
|
+
},
|
|
147
|
+
});
|
|
148
|
+
const storePath = core.channel.session.resolveStorePath(cfg.session?.store, {
|
|
149
|
+
agentId: route.agentId,
|
|
150
|
+
});
|
|
151
|
+
const envelopeOptions = core.channel.reply.resolveEnvelopeFormatOptions(cfg);
|
|
152
|
+
const previousTimestamp = core.channel.session.readSessionUpdatedAt({
|
|
153
|
+
storePath,
|
|
154
|
+
sessionKey: route.sessionKey,
|
|
155
|
+
});
|
|
156
|
+
const body = core.channel.reply.formatAgentEnvelope({
|
|
157
|
+
channel: "CrabCallr",
|
|
158
|
+
from: "Voice Caller",
|
|
159
|
+
timestamp: Date.now(),
|
|
160
|
+
previousTimestamp,
|
|
161
|
+
envelope: envelopeOptions,
|
|
162
|
+
body: text,
|
|
163
|
+
});
|
|
164
|
+
const ctxPayload = core.channel.reply.finalizeInboundContext({
|
|
165
|
+
Body: body,
|
|
166
|
+
RawBody: text,
|
|
167
|
+
CommandBody: text,
|
|
168
|
+
From: `crabcallr:call:${callId}`,
|
|
169
|
+
To: `crabcallr:call:${callId}`,
|
|
170
|
+
SessionKey: route.sessionKey,
|
|
171
|
+
AccountId: route.accountId,
|
|
172
|
+
ChatType: "direct",
|
|
173
|
+
ConversationLabel: `call:${callId}`,
|
|
174
|
+
SenderName: "Voice Caller",
|
|
175
|
+
SenderId: callId,
|
|
176
|
+
Provider: CHANNEL_ID,
|
|
177
|
+
Surface: CHANNEL_ID,
|
|
178
|
+
MessageSid: requestId,
|
|
179
|
+
Timestamp: Date.now(),
|
|
180
|
+
OriginatingChannel: CHANNEL_ID,
|
|
181
|
+
OriginatingTo: `crabcallr:call:${callId}`,
|
|
182
|
+
});
|
|
183
|
+
await core.channel.session.recordInboundSession({
|
|
184
|
+
storePath,
|
|
185
|
+
sessionKey: ctxPayload.SessionKey ?? route.sessionKey,
|
|
186
|
+
ctx: ctxPayload,
|
|
187
|
+
onRecordError: (err) => {
|
|
188
|
+
logError(`[CrabCallr] Failed updating session meta: ${String(err)}`);
|
|
189
|
+
},
|
|
190
|
+
});
|
|
191
|
+
const { onModelSelected, ...prefixOptions } = createReplyPrefixOptions({
|
|
192
|
+
cfg,
|
|
193
|
+
agentId: route.agentId,
|
|
194
|
+
channel: CHANNEL_ID,
|
|
195
|
+
accountId: route.accountId,
|
|
196
|
+
});
|
|
197
|
+
await core.channel.reply.dispatchReplyWithBufferedBlockDispatcher({
|
|
198
|
+
ctx: ctxPayload,
|
|
199
|
+
cfg,
|
|
200
|
+
dispatcherOptions: {
|
|
201
|
+
...prefixOptions,
|
|
202
|
+
deliver: async (payload, info) => {
|
|
203
|
+
if (info.kind !== "final") {
|
|
204
|
+
return;
|
|
205
|
+
}
|
|
206
|
+
const replyText = payload.text?.trim();
|
|
207
|
+
if (!replyText) {
|
|
208
|
+
return;
|
|
209
|
+
}
|
|
210
|
+
ws.sendResponse(requestId, replyText);
|
|
211
|
+
statusSink?.({ lastOutboundAt: Date.now() });
|
|
212
|
+
},
|
|
213
|
+
onError: (err, info) => {
|
|
214
|
+
logError(`[CrabCallr] ${info.kind} reply failed: ${String(err)}`);
|
|
215
|
+
},
|
|
216
|
+
},
|
|
217
|
+
replyOptions: {
|
|
218
|
+
onModelSelected,
|
|
219
|
+
disableBlockStreaming: true,
|
|
220
|
+
},
|
|
221
|
+
});
|
|
222
|
+
}
|
|
223
|
+
function getConnection(accountId) {
|
|
224
|
+
return connections.get(normalizeAccountId(accountId));
|
|
225
|
+
}
|
|
226
|
+
export function getCrabCallrStatus(accountId) {
|
|
227
|
+
const resolvedId = normalizeAccountId(accountId ?? DEFAULT_ACCOUNT_ID);
|
|
228
|
+
const record = connections.get(resolvedId);
|
|
229
|
+
if (!record) {
|
|
230
|
+
return {
|
|
231
|
+
accountId: resolvedId,
|
|
232
|
+
connected: false,
|
|
233
|
+
status: "disconnected",
|
|
234
|
+
userId: null,
|
|
235
|
+
running: false,
|
|
236
|
+
reconnectAttempts: 0,
|
|
237
|
+
};
|
|
238
|
+
}
|
|
239
|
+
return {
|
|
240
|
+
accountId: resolvedId,
|
|
241
|
+
connected: record.ws.isConnected(),
|
|
242
|
+
status: record.ws.getStatus(),
|
|
243
|
+
userId: record.ws.getUserId(),
|
|
244
|
+
running: true,
|
|
245
|
+
reconnectAttempts: record.ws.getReconnectAttempts(),
|
|
246
|
+
};
|
|
247
|
+
}
|
|
248
|
+
export function sendCrabCallrResponse(params) {
|
|
249
|
+
const resolvedId = normalizeAccountId(params.accountId ?? DEFAULT_ACCOUNT_ID);
|
|
250
|
+
const record = connections.get(resolvedId);
|
|
251
|
+
if (!record) {
|
|
252
|
+
return { ok: false, error: "CrabCallr connection not running" };
|
|
253
|
+
}
|
|
254
|
+
if (!record.ws.isConnected()) {
|
|
255
|
+
return { ok: false, error: "CrabCallr is not connected" };
|
|
256
|
+
}
|
|
257
|
+
record.ws.sendResponse(params.requestId, params.text);
|
|
258
|
+
record.statusSink?.({ lastOutboundAt: Date.now() });
|
|
259
|
+
return { ok: true };
|
|
260
|
+
}
|
|
261
|
+
export const crabcallrPlugin = {
|
|
262
|
+
id: CHANNEL_ID,
|
|
263
|
+
meta: {
|
|
264
|
+
id: CHANNEL_ID,
|
|
265
|
+
label: "CrabCallr Voice",
|
|
266
|
+
selectionLabel: "CrabCallr (Voice)",
|
|
267
|
+
docsPath: "/channels/crabcallr",
|
|
268
|
+
blurb: "Voice calling via phone or browser",
|
|
269
|
+
aliases: ["voice", "phone"],
|
|
270
|
+
order: 100,
|
|
271
|
+
},
|
|
272
|
+
capabilities: {
|
|
273
|
+
chatTypes: ["direct"],
|
|
274
|
+
blockStreaming: true,
|
|
275
|
+
},
|
|
276
|
+
reload: { configPrefixes: ["channels.crabcallr"] },
|
|
277
|
+
configSchema: crabcallrConfigSchema,
|
|
278
|
+
config: {
|
|
279
|
+
listAccountIds: (cfg) => listCrabCallrAccountIds(cfg),
|
|
280
|
+
resolveAccount: (cfg, accountId) => resolveCrabCallrAccount({ cfg, accountId }),
|
|
281
|
+
defaultAccountId: (cfg) => resolveDefaultCrabCallrAccountId(cfg),
|
|
282
|
+
isConfigured: (account) => account.configured,
|
|
283
|
+
isEnabled: (account) => account.enabled,
|
|
284
|
+
describeAccount: (account) => ({
|
|
285
|
+
accountId: account.accountId,
|
|
286
|
+
name: account.name,
|
|
287
|
+
enabled: account.enabled,
|
|
288
|
+
configured: account.configured,
|
|
289
|
+
}),
|
|
290
|
+
},
|
|
291
|
+
gateway: {
|
|
292
|
+
startAccount: async (ctx) => {
|
|
293
|
+
const account = ctx.account;
|
|
294
|
+
if (!account.enabled) {
|
|
295
|
+
ctx.log?.info(`[${account.accountId}] CrabCallr disabled`);
|
|
296
|
+
ctx.setStatus?.({
|
|
297
|
+
accountId: account.accountId,
|
|
298
|
+
running: false,
|
|
299
|
+
connected: false,
|
|
300
|
+
lastStopAt: Date.now(),
|
|
301
|
+
});
|
|
302
|
+
return;
|
|
303
|
+
}
|
|
304
|
+
let config;
|
|
305
|
+
try {
|
|
306
|
+
config = validateConfig({
|
|
307
|
+
apiKey: account.config.apiKey,
|
|
308
|
+
serviceUrl: account.config.serviceUrl,
|
|
309
|
+
autoConnect: account.config.autoConnect,
|
|
310
|
+
reconnectInterval: account.config.reconnectInterval,
|
|
311
|
+
maxReconnectAttempts: account.config.maxReconnectAttempts,
|
|
312
|
+
});
|
|
313
|
+
}
|
|
314
|
+
catch (err) {
|
|
315
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
316
|
+
ctx.setStatus?.({
|
|
317
|
+
accountId: account.accountId,
|
|
318
|
+
running: false,
|
|
319
|
+
connected: false,
|
|
320
|
+
lastError: message,
|
|
321
|
+
lastStopAt: Date.now(),
|
|
322
|
+
});
|
|
323
|
+
throw err;
|
|
324
|
+
}
|
|
325
|
+
const logger = ctx.log ??
|
|
326
|
+
{
|
|
327
|
+
info: console.log,
|
|
328
|
+
warn: console.warn,
|
|
329
|
+
error: console.error,
|
|
330
|
+
debug: console.debug,
|
|
331
|
+
};
|
|
332
|
+
const statusSink = createStatusSink({
|
|
333
|
+
accountId: account.accountId,
|
|
334
|
+
getStatus: ctx.getStatus,
|
|
335
|
+
setStatus: ctx.setStatus,
|
|
336
|
+
});
|
|
337
|
+
const ws = new CrabCallrWebSocket(config, logger);
|
|
338
|
+
connections.set(account.accountId, { accountId: account.accountId, ws, statusSink });
|
|
339
|
+
statusSink({
|
|
340
|
+
running: true,
|
|
341
|
+
connected: ws.isConnected(),
|
|
342
|
+
lastStartAt: Date.now(),
|
|
343
|
+
lastError: null,
|
|
344
|
+
reconnectAttempts: ws.getReconnectAttempts(),
|
|
345
|
+
});
|
|
346
|
+
ws.on("connected", () => {
|
|
347
|
+
statusSink({
|
|
348
|
+
connected: true,
|
|
349
|
+
lastConnectedAt: Date.now(),
|
|
350
|
+
lastDisconnect: null,
|
|
351
|
+
reconnectAttempts: ws.getReconnectAttempts(),
|
|
352
|
+
lastError: null,
|
|
353
|
+
});
|
|
354
|
+
});
|
|
355
|
+
ws.on("disconnected", (reason) => {
|
|
356
|
+
statusSink({
|
|
357
|
+
connected: false,
|
|
358
|
+
lastDisconnect: {
|
|
359
|
+
at: Date.now(),
|
|
360
|
+
error: reason,
|
|
361
|
+
},
|
|
362
|
+
reconnectAttempts: ws.getReconnectAttempts(),
|
|
363
|
+
});
|
|
364
|
+
});
|
|
365
|
+
ws.on("error", (error) => {
|
|
366
|
+
statusSink({
|
|
367
|
+
lastError: error.message,
|
|
368
|
+
reconnectAttempts: ws.getReconnectAttempts(),
|
|
369
|
+
});
|
|
370
|
+
});
|
|
371
|
+
ws.on("request", (requestId, text, callId) => {
|
|
372
|
+
statusSink({ lastInboundAt: Date.now() });
|
|
373
|
+
handleRequest({
|
|
374
|
+
cfg: ctx.cfg,
|
|
375
|
+
accountId: account.accountId,
|
|
376
|
+
requestId,
|
|
377
|
+
text,
|
|
378
|
+
callId,
|
|
379
|
+
ws,
|
|
380
|
+
statusSink,
|
|
381
|
+
logError: (message) => logger.error(message),
|
|
382
|
+
}).catch((err) => {
|
|
383
|
+
logger.error(`[CrabCallr] Failed to handle request: ${String(err)}`);
|
|
384
|
+
});
|
|
385
|
+
});
|
|
386
|
+
ws.on("callStart", (callId, source) => {
|
|
387
|
+
logger.info(`[CrabCallr] Call started from ${source}: ${callId}`);
|
|
388
|
+
});
|
|
389
|
+
ws.on("callEnd", (callId, durationSeconds, source) => {
|
|
390
|
+
logger.info(`[CrabCallr] Call ended: ${callId} (${durationSeconds}s from ${source})`);
|
|
391
|
+
});
|
|
392
|
+
const stop = () => {
|
|
393
|
+
ws.disconnect();
|
|
394
|
+
connections.delete(account.accountId);
|
|
395
|
+
statusSink({
|
|
396
|
+
running: false,
|
|
397
|
+
connected: false,
|
|
398
|
+
lastStopAt: Date.now(),
|
|
399
|
+
});
|
|
400
|
+
};
|
|
401
|
+
ctx.abortSignal.addEventListener("abort", stop, { once: true });
|
|
402
|
+
if (config.autoConnect) {
|
|
403
|
+
logger.info("[CrabCallr] Auto-connecting to CrabCallr service");
|
|
404
|
+
ws.connect();
|
|
405
|
+
}
|
|
406
|
+
},
|
|
407
|
+
stopAccount: async (ctx) => {
|
|
408
|
+
const record = getConnection(ctx.accountId);
|
|
409
|
+
if (record) {
|
|
410
|
+
record.ws.disconnect();
|
|
411
|
+
connections.delete(record.accountId);
|
|
412
|
+
}
|
|
413
|
+
ctx.setStatus?.({
|
|
414
|
+
accountId: ctx.accountId,
|
|
415
|
+
running: false,
|
|
416
|
+
connected: false,
|
|
417
|
+
lastStopAt: Date.now(),
|
|
418
|
+
});
|
|
419
|
+
},
|
|
420
|
+
},
|
|
421
|
+
status: {
|
|
422
|
+
defaultRuntime: {
|
|
423
|
+
accountId: DEFAULT_ACCOUNT_ID,
|
|
424
|
+
running: false,
|
|
425
|
+
connected: false,
|
|
426
|
+
lastStartAt: null,
|
|
427
|
+
lastStopAt: null,
|
|
428
|
+
lastError: null,
|
|
429
|
+
},
|
|
430
|
+
buildAccountSnapshot: ({ account, runtime, }) => ({
|
|
431
|
+
accountId: account.accountId,
|
|
432
|
+
name: account.name,
|
|
433
|
+
enabled: account.enabled,
|
|
434
|
+
configured: account.configured,
|
|
435
|
+
running: runtime?.running ?? false,
|
|
436
|
+
connected: runtime?.connected ?? false,
|
|
437
|
+
reconnectAttempts: runtime?.reconnectAttempts ?? 0,
|
|
438
|
+
lastConnectedAt: runtime?.lastConnectedAt ?? null,
|
|
439
|
+
lastDisconnect: runtime?.lastDisconnect ?? null,
|
|
440
|
+
lastError: runtime?.lastError ?? null,
|
|
441
|
+
lastStartAt: runtime?.lastStartAt ?? null,
|
|
442
|
+
lastStopAt: runtime?.lastStopAt ?? null,
|
|
443
|
+
lastInboundAt: runtime?.lastInboundAt ?? null,
|
|
444
|
+
lastOutboundAt: runtime?.lastOutboundAt ?? null,
|
|
445
|
+
}),
|
|
446
|
+
},
|
|
447
|
+
};
|
|
448
|
+
//# sourceMappingURL=channel.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"channel.js","sourceRoot":"","sources":["../src/channel.ts"],"names":[],"mappings":"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"}
|
package/dist/config.d.ts
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Configuration handling for CrabCallr plugin
|
|
3
|
+
*/
|
|
4
|
+
import type { CrabCallrConfig } from './types.js';
|
|
5
|
+
/**
|
|
6
|
+
* Default configuration values
|
|
7
|
+
*/
|
|
8
|
+
export declare const DEFAULT_CONFIG: Omit<CrabCallrConfig, 'apiKey'>;
|
|
9
|
+
/**
|
|
10
|
+
* Validates and normalizes plugin configuration
|
|
11
|
+
*/
|
|
12
|
+
export declare function validateConfig(config: Partial<CrabCallrConfig>): CrabCallrConfig;
|
|
13
|
+
/**
|
|
14
|
+
* Masks an API key for logging (shows first 3 and last 4 chars)
|
|
15
|
+
*/
|
|
16
|
+
export declare function maskApiKey(apiKey: string): string;
|
|
17
|
+
//# sourceMappingURL=config.d.ts.map
|