@openclaw/voice-call 2026.7.2-beta.3 → 2026.7.2-beta.5
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 +1 -1
- package/dist/cli-metadata.js +5 -1
- package/dist/cli-output-mode.js +27 -0
- package/dist/{guarded-json-api-Dm4NvtGo.js → guarded-json-api-Dxhe25Zi.js} +1 -2
- package/dist/index.js +15 -7
- package/dist/{plivo-rISw-5A8.js → plivo-B-KvPVji.js} +2 -3
- package/dist/{realtime-handler-HSxcgwY_.js → realtime-handler-hIVPEZxN.js} +4 -10
- package/dist/{response-generator-r9wHPOEl.js → response-generator-z6M9229t.js} +1 -1
- package/dist/{runtime-entry-D8Mkwy8G.js → runtime-entry-CQtitvRd.js} +29 -13
- package/dist/runtime-entry.js +1 -1
- package/dist/{telnyx-DTD9jTqC.js → telnyx-BG56lL7z.js} +1 -1
- package/dist/{twilio-GzbIb5fv.js → twilio-B3FQ_P9x.js} +2 -2
- package/node_modules/typebox/build/compile/validator.d.mts +1 -4
- package/node_modules/typebox/build/guard/guard.d.mts +1 -1
- package/node_modules/typebox/build/guard/guard.mjs +5 -2
- package/node_modules/typebox/build/guard/string.mjs +16 -4
- package/node_modules/typebox/build/schema/engine/_functions.mjs +34 -15
- package/node_modules/typebox/build/type/action/readonly_object.d.mts +5 -0
- package/node_modules/typebox/build/type/action/readonly_object.mjs +8 -0
- package/node_modules/typebox/build/typebox.d.mts +1 -1
- package/node_modules/typebox/build/typebox.mjs +1 -1
- package/node_modules/typebox/package.json +1 -1
- package/node_modules/typebox/readme.md +29 -32
- package/node_modules/ws/lib/receiver.js +15 -32
- package/node_modules/ws/lib/websocket-server.js +4 -4
- package/node_modules/ws/lib/websocket.js +4 -4
- package/node_modules/ws/package.json +5 -1
- package/openclaw.plugin.json +1 -15
- package/package.json +6 -7
- package/npm-shrinkwrap.json +0 -61
package/README.md
CHANGED
|
@@ -115,7 +115,7 @@ See the plugin docs for recommended ranges and production examples:
|
|
|
115
115
|
|
|
116
116
|
## TTS for calls
|
|
117
117
|
|
|
118
|
-
Voice Call uses the core `
|
|
118
|
+
Voice Call uses the core `tts` configuration for
|
|
119
119
|
streaming speech on calls. Override examples and provider caveats live here:
|
|
120
120
|
`https://docs.openclaw.ai/plugins/voice-call#tts-for-calls`
|
|
121
121
|
|
package/dist/cli-metadata.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { VOICE_CALL_CLI_DESCRIPTOR } from "./cli-output-mode.js";
|
|
1
2
|
import { definePluginEntry } from "openclaw/plugin-sdk/plugin-entry";
|
|
2
3
|
//#region extensions/voice-call/cli-metadata.ts
|
|
3
4
|
var cli_metadata_default = definePluginEntry({
|
|
@@ -5,7 +6,10 @@ var cli_metadata_default = definePluginEntry({
|
|
|
5
6
|
name: "Voice Call",
|
|
6
7
|
description: "Voice call channel plugin",
|
|
7
8
|
register(api) {
|
|
8
|
-
api.registerCli(() => {}, {
|
|
9
|
+
api.registerCli(() => {}, {
|
|
10
|
+
commands: ["voicecall"],
|
|
11
|
+
descriptors: [VOICE_CALL_CLI_DESCRIPTOR]
|
|
12
|
+
});
|
|
9
13
|
}
|
|
10
14
|
});
|
|
11
15
|
//#endregion
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { getRootOptionAwareCommandPath } from "openclaw/plugin-sdk/cli-argv";
|
|
2
|
+
//#region extensions/voice-call/cli-output-mode.ts
|
|
3
|
+
const MACHINE_OUTPUT_COMMANDS = /* @__PURE__ */ new Set([
|
|
4
|
+
"call",
|
|
5
|
+
"continue",
|
|
6
|
+
"dtmf",
|
|
7
|
+
"end",
|
|
8
|
+
"expose",
|
|
9
|
+
"latency",
|
|
10
|
+
"speak",
|
|
11
|
+
"start",
|
|
12
|
+
"status",
|
|
13
|
+
"tail"
|
|
14
|
+
]);
|
|
15
|
+
/** Voice-call result actions emit JSON, while tail reserves stdout for JSONL. */
|
|
16
|
+
function isVoiceCallMachineOutput(params) {
|
|
17
|
+
const [, command] = getRootOptionAwareCommandPath(params.argv, 2);
|
|
18
|
+
return MACHINE_OUTPUT_COMMANDS.has(command ?? "");
|
|
19
|
+
}
|
|
20
|
+
const VOICE_CALL_CLI_DESCRIPTOR = {
|
|
21
|
+
name: "voicecall",
|
|
22
|
+
description: "Voice call utilities",
|
|
23
|
+
hasSubcommands: true,
|
|
24
|
+
machineOutput: isVoiceCallMachineOutput
|
|
25
|
+
};
|
|
26
|
+
//#endregion
|
|
27
|
+
export { VOICE_CALL_CLI_DESCRIPTOR };
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { fetchWithSsrFGuard } from "./runtime-api.js";
|
|
2
2
|
import "./api.js";
|
|
3
|
-
import { n as normalizeProxyIp,
|
|
3
|
+
import { n as normalizeProxyIp, s as getHeader } from "./runtime-entry-CQtitvRd.js";
|
|
4
4
|
import { n as markWebhookReplay, t as createWebhookReplayCache } from "./webhook-replay-aaP79dI8.js";
|
|
5
5
|
import { formatErrorMessage } from "openclaw/plugin-sdk/error-runtime";
|
|
6
6
|
import { isLoopbackHost } from "openclaw/plugin-sdk/gateway-runtime";
|
|
@@ -462,7 +462,6 @@ function verifyPlivoWebhook(ctx, authToken, options) {
|
|
|
462
462
|
if (options?.publicUrl) try {
|
|
463
463
|
const req = new URL(reconstructed);
|
|
464
464
|
const base = new URL(options.publicUrl);
|
|
465
|
-
base.pathname = req.pathname;
|
|
466
465
|
base.search = req.search;
|
|
467
466
|
verificationUrl = base.toString();
|
|
468
467
|
} catch {
|
package/dist/index.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { definePluginEntry, sleep } from "./runtime-api.js";
|
|
2
2
|
import "./api.js";
|
|
3
|
-
import {
|
|
3
|
+
import { VOICE_CALL_CLI_DESCRIPTOR } from "./cli-output-mode.js";
|
|
4
|
+
import { S as validateProviderConfig, b as resolveVoiceCallConfig, c as resolveWebhookExposureStatus, d as setupTailscaleExposureRoute, g as resolveUserPath, l as cleanupTailscaleExposureRoute, t as createVoiceCallRuntime, u as getTailscaleSelfInfo, y as VoiceCallConfigSchema } from "./runtime-entry-CQtitvRd.js";
|
|
4
5
|
import { g as setVoiceCallStateRuntime, t as resolveDefaultVoiceCallStoreDir, u as getCallHistoryFromStore } from "./store-path-nYL-yM0S.js";
|
|
5
6
|
import { formatErrorMessage } from "openclaw/plugin-sdk/error-runtime";
|
|
6
7
|
import { ErrorCodes, callGatewayFromCli, errorShape } from "openclaw/plugin-sdk/gateway-runtime";
|
|
@@ -87,13 +88,17 @@ function readCompletedContinueResult(payload) {
|
|
|
87
88
|
}
|
|
88
89
|
async function pollVoiceCallContinueGateway(params) {
|
|
89
90
|
const deadlineMs = resolveVoiceCallDeadlineMs(params.timeoutMs);
|
|
90
|
-
|
|
91
|
-
const
|
|
91
|
+
for (;;) {
|
|
92
|
+
const remainingMs = deadlineMs - Date.now();
|
|
93
|
+
if (remainingMs <= 0) break;
|
|
94
|
+
const gateway = await callVoiceCallGateway("voicecall.continue.result", { operationId: params.operationId }, { timeoutMs: Math.min(VOICE_CALL_GATEWAY_DEFAULT_TIMEOUT_MS, remainingMs) });
|
|
92
95
|
if (!gateway.ok) throw new Error(`gateway unavailable while waiting for voicecall continue result: ${formatErrorMessage(gateway.error)}`);
|
|
93
96
|
const result = readCompletedContinueResult(gateway.payload);
|
|
94
97
|
if (result.status === "completed") return result.result;
|
|
95
98
|
if (result.status === "failed") throw new Error(result.error);
|
|
96
|
-
|
|
99
|
+
const sleepMs = Math.min(VOICE_CALL_GATEWAY_POLL_INTERVAL_MS, deadlineMs - Date.now());
|
|
100
|
+
if (sleepMs <= 0) break;
|
|
101
|
+
await sleep(sleepMs);
|
|
97
102
|
}
|
|
98
103
|
throw new Error("voicecall continue timed out waiting for gateway operation");
|
|
99
104
|
}
|
|
@@ -533,7 +538,7 @@ const VOICE_CALL_CONTINUE_OPERATION_CLEANUP_MS = 300 * 1e3;
|
|
|
533
538
|
function createVoiceCallContinueOperationStore(params) {
|
|
534
539
|
const operations = /* @__PURE__ */ new Map();
|
|
535
540
|
const resolvePollTimeoutMs = (rt) => {
|
|
536
|
-
const ttsTimeoutMs = rt.config.tts?.timeoutMs ?? params.config.tts?.timeoutMs ?? params.coreConfig.
|
|
541
|
+
const ttsTimeoutMs = rt.config.tts?.timeoutMs ?? params.config.tts?.timeoutMs ?? params.coreConfig.tts?.timeoutMs ?? 8e3;
|
|
537
542
|
return resolveTimerTimeoutMs((rt.config.transcriptTimeoutMs ?? params.config.transcriptTimeoutMs) + ttsTimeoutMs + VOICE_CALL_CONTINUE_OPERATION_BUFFER_MS, VOICE_CALL_CONTINUE_OPERATION_BUFFER_MS);
|
|
538
543
|
};
|
|
539
544
|
const scheduleCleanup = (operationId) => {
|
|
@@ -822,7 +827,7 @@ const voiceCallConfigSchema = {
|
|
|
822
827
|
},
|
|
823
828
|
"tts.provider": {
|
|
824
829
|
label: "TTS Provider Override",
|
|
825
|
-
help: "Deep-merges with
|
|
830
|
+
help: "Deep-merges with tts (Microsoft is ignored for calls).",
|
|
826
831
|
advanced: true
|
|
827
832
|
},
|
|
828
833
|
"tts.providers": {
|
|
@@ -1345,7 +1350,10 @@ var voice_call_default = definePluginEntry({
|
|
|
1345
1350
|
ensureRuntime,
|
|
1346
1351
|
stateRuntime: api.runtime.state,
|
|
1347
1352
|
logger: api.logger
|
|
1348
|
-
}), {
|
|
1353
|
+
}), {
|
|
1354
|
+
commands: ["voicecall"],
|
|
1355
|
+
descriptors: [VOICE_CALL_CLI_DESCRIPTOR]
|
|
1356
|
+
});
|
|
1349
1357
|
api.registerService({
|
|
1350
1358
|
id: "voicecall",
|
|
1351
1359
|
start: () => {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { a as reconstructWebhookUrl, o as verifyPlivoWebhook, t as guardedJsonApiRequest } from "./guarded-json-api-
|
|
1
|
+
import { _ as escapeXml, s as getHeader } from "./runtime-entry-CQtitvRd.js";
|
|
2
|
+
import { a as reconstructWebhookUrl, o as verifyPlivoWebhook, t as guardedJsonApiRequest } from "./guarded-json-api-Dxhe25Zi.js";
|
|
3
3
|
import { normalizeLowercaseStringOrEmpty, normalizeOptionalString } from "openclaw/plugin-sdk/string-coerce-runtime";
|
|
4
4
|
import crypto from "node:crypto";
|
|
5
5
|
//#region extensions/voice-call/src/providers/plivo.ts
|
|
@@ -371,7 +371,6 @@ var PlivoProvider = class PlivoProvider {
|
|
|
371
371
|
try {
|
|
372
372
|
if (this.options.publicUrl) {
|
|
373
373
|
const base = new URL(this.options.publicUrl);
|
|
374
|
-
base.pathname = new URL(ctx.url).pathname;
|
|
375
374
|
return `${base.origin}${base.pathname}`;
|
|
376
375
|
}
|
|
377
376
|
const u = new URL(reconstructWebhookUrl(ctx, {
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { o as canonicalizeVoiceCallMediaBase64 } from "./runtime-entry-CQtitvRd.js";
|
|
1
2
|
import { formatErrorMessage } from "openclaw/plugin-sdk/error-runtime";
|
|
2
3
|
import { isFutureDateTimestampMs, resolveExpiresAtMsFromDurationMs } from "openclaw/plugin-sdk/number-runtime";
|
|
3
4
|
import { createSubsystemLogger } from "openclaw/plugin-sdk/runtime-env";
|
|
@@ -129,22 +130,15 @@ function readRecordField(record, field) {
|
|
|
129
130
|
const value = record[field];
|
|
130
131
|
return typeof value === "object" && value !== null ? value : void 0;
|
|
131
132
|
}
|
|
132
|
-
/** Normalize base64/base64url padding differences for validation. */
|
|
133
|
-
function normalizeBase64ForCompare(value) {
|
|
134
|
-
return value.replace(/=+$/u, "").replace(/-/gu, "+").replace(/_/gu, "/");
|
|
135
|
-
}
|
|
136
|
-
/** Return true when a payload round-trips as base64. */
|
|
137
|
-
function isValidBase64Payload(value) {
|
|
138
|
-
return normalizeBase64ForCompare(Buffer.from(value, "base64").toString("base64")) === normalizeBase64ForCompare(value);
|
|
139
|
-
}
|
|
140
133
|
/** Parse a common provider media frame. */
|
|
141
134
|
function parseMediaFrame(msg) {
|
|
142
135
|
const mediaData = readRecordField(msg, "media");
|
|
143
136
|
const payload = typeof mediaData?.payload === "string" ? mediaData.payload : void 0;
|
|
144
|
-
|
|
137
|
+
const canonicalPayload = payload ? canonicalizeVoiceCallMediaBase64(payload) : void 0;
|
|
138
|
+
if (!canonicalPayload) return { kind: "ignored" };
|
|
145
139
|
return {
|
|
146
140
|
kind: "media",
|
|
147
|
-
payloadBase64:
|
|
141
|
+
payloadBase64: canonicalPayload,
|
|
148
142
|
timestampMs: parseTimestampMs(mediaData?.timestamp),
|
|
149
143
|
track: typeof mediaData?.track === "string" ? mediaData.track : void 0
|
|
150
144
|
};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { h as resolveCallAgentId, m as resolveVoiceResponseModel, x as resolveVoiceCallSessionKey } from "./runtime-entry-CQtitvRd.js";
|
|
2
2
|
import { isRecord, normalizeLowercaseStringOrEmpty, normalizeStringEntries } from "openclaw/plugin-sdk/string-coerce-runtime";
|
|
3
3
|
import crypto from "node:crypto";
|
|
4
4
|
import { ModelSelectionLockedError, applyModelOverrideToSessionEntry, resolvePersistedSessionRuntimeId } from "openclaw/plugin-sdk/model-session-runtime";
|
|
@@ -8,6 +8,7 @@ import { MAX_TIMER_TIMEOUT_MS, asDateTimestampMs, resolveExpiresAtMsFromDuration
|
|
|
8
8
|
import { normalizeAgentId, parseAgentSessionKey } from "openclaw/plugin-sdk/routing";
|
|
9
9
|
import { normalizeLowercaseStringOrEmpty, normalizeOptionalLowercaseString, normalizeOptionalString, normalizeStringEntries } from "openclaw/plugin-sdk/string-coerce-runtime";
|
|
10
10
|
import { createSubsystemLogger } from "openclaw/plugin-sdk/runtime-env";
|
|
11
|
+
import { resolveDefaultAgentId } from "openclaw/plugin-sdk/agent-runtime";
|
|
11
12
|
import { createLazyRuntimeModule } from "openclaw/plugin-sdk/lazy-runtime";
|
|
12
13
|
import { REALTIME_VOICE_AGENT_CONSULT_TOOL_NAME, REALTIME_VOICE_AGENT_CONSULT_TOOL_POLICIES, assertRealtimeVoiceAgentConsultModelSelectionUnlocked, buildRealtimeVoiceAgentConsultPolicyInstructions, consultRealtimeVoiceAgent, convertPcmToMulaw8k, createTalkSessionController, recordTalkObservabilityEvent, resolveRealtimeVoiceAgentConsultTools, resolveRealtimeVoiceAgentConsultToolsAllow, resolveRealtimeVoiceFastContextConsult } from "openclaw/plugin-sdk/realtime-voice";
|
|
13
14
|
import { mergeDeep } from "openclaw/plugin-sdk/plugin-config-runtime";
|
|
@@ -29,6 +30,7 @@ import http from "node:http";
|
|
|
29
30
|
import { URL as URL$1 } from "node:url";
|
|
30
31
|
import { resolveConfiguredCapabilityProvider } from "openclaw/plugin-sdk/provider-selection-runtime";
|
|
31
32
|
import { WebSocket, WebSocketServer } from "ws";
|
|
33
|
+
import { canonicalizeBase64 } from "openclaw/plugin-sdk/media-runtime";
|
|
32
34
|
//#region extensions/voice-call/src/realtime-defaults.ts
|
|
33
35
|
/** Baseline instructions that keep realtime calls brief and route deep work to agent consult. */
|
|
34
36
|
const DEFAULT_VOICE_CALL_REALTIME_INSTRUCTIONS = `You are OpenClaw's phone-call realtime voice interface. Keep spoken replies brief and natural. When a question needs deeper reasoning, current information, or tools, call ${REALTIME_VOICE_AGENT_CONSULT_TOOL_NAME} before answering.`;
|
|
@@ -404,7 +406,7 @@ const VoiceCallConfigSchema = z.object({
|
|
|
404
406
|
publicUrl: z.string().url().optional(),
|
|
405
407
|
/** Skip webhook signature verification (development only, NOT for production) */
|
|
406
408
|
skipSignatureVerification: z.boolean().default(false),
|
|
407
|
-
/** TTS override (deep-merges with core
|
|
409
|
+
/** TTS override (deep-merges with core tts) */
|
|
408
410
|
tts: TtsConfigSchema,
|
|
409
411
|
/** Store path for call logs */
|
|
410
412
|
store: z.string().optional(),
|
|
@@ -1838,7 +1840,7 @@ async function buildRealtimeVoiceInstructions(params) {
|
|
|
1838
1840
|
if (consultGuidance) sections.push(consultGuidance);
|
|
1839
1841
|
const contextConfig = config.realtime.agentContext;
|
|
1840
1842
|
if (!contextConfig.enabled) return sections.filter(Boolean).join("\n\n");
|
|
1841
|
-
const agentId =
|
|
1843
|
+
const { agentId } = params;
|
|
1842
1844
|
const capsule = [
|
|
1843
1845
|
"OpenClaw agent voice context:",
|
|
1844
1846
|
`- Agent id: ${agentId}`,
|
|
@@ -1920,7 +1922,7 @@ async function createTelephonyTtsProvider(params) {
|
|
|
1920
1922
|
text: ""
|
|
1921
1923
|
});
|
|
1922
1924
|
return {
|
|
1923
|
-
synthesisTimeoutMs: resolveTimerTimeoutMs(preparedConfig.cfg.
|
|
1925
|
+
synthesisTimeoutMs: resolveTimerTimeoutMs(preparedConfig.cfg.tts?.timeoutMs, TELEPHONY_DEFAULT_TTS_TIMEOUT_MS),
|
|
1924
1926
|
synthesizeForTelephony: async (text) => {
|
|
1925
1927
|
const prepared = await runtime.prepareTtsRequest({
|
|
1926
1928
|
cfg: preparedConfig.cfg,
|
|
@@ -2367,6 +2369,11 @@ function getHeader(headers, name) {
|
|
|
2367
2369
|
return value;
|
|
2368
2370
|
}
|
|
2369
2371
|
//#endregion
|
|
2372
|
+
//#region extensions/voice-call/src/media-base64.ts
|
|
2373
|
+
function canonicalizeVoiceCallMediaBase64(payloadBase64) {
|
|
2374
|
+
return canonicalizeBase64(payloadBase64.replaceAll("-", "+").replaceAll("_", "/"));
|
|
2375
|
+
}
|
|
2376
|
+
//#endregion
|
|
2370
2377
|
//#region extensions/voice-call/src/media-stream.ts
|
|
2371
2378
|
const DEFAULT_PRE_START_TIMEOUT_MS = 5e3;
|
|
2372
2379
|
const DEFAULT_MAX_PENDING_CONNECTIONS = 32;
|
|
@@ -2481,7 +2488,9 @@ var MediaStreamHandler = class {
|
|
|
2481
2488
|
break;
|
|
2482
2489
|
case "media":
|
|
2483
2490
|
if (session && message.media?.payload) {
|
|
2484
|
-
const
|
|
2491
|
+
const canonicalPayload = canonicalizeVoiceCallMediaBase64(message.media.payload);
|
|
2492
|
+
if (!canonicalPayload) break;
|
|
2493
|
+
const audioBuffer = Buffer.from(canonicalPayload, "base64");
|
|
2485
2494
|
const turnId = this.ensureActiveTurn(session);
|
|
2486
2495
|
this.emitTalkEvent(session, {
|
|
2487
2496
|
type: "input.audio.delta",
|
|
@@ -3062,7 +3071,7 @@ const WEBHOOK_BODY_TIMEOUT_MS = WEBHOOK_BODY_READ_DEFAULTS.preAuth.timeoutMs;
|
|
|
3062
3071
|
const MISSING_REMOTE_ADDRESS_IN_FLIGHT_KEY = "__voice_call_no_remote__";
|
|
3063
3072
|
const STREAM_DISCONNECT_HANGUP_GRACE_MS = 2e3;
|
|
3064
3073
|
const loadRealtimeTranscriptionRuntime = createLazyRuntimeModule(() => import("./realtime-transcription.runtime-CbJAs5t_.js"));
|
|
3065
|
-
const loadResponseGeneratorModule = createLazyRuntimeModule(() => import("./response-generator-
|
|
3074
|
+
const loadResponseGeneratorModule = createLazyRuntimeModule(() => import("./response-generator-z6M9229t.js"));
|
|
3066
3075
|
function appendRecentTalkEventMetadata(call, event) {
|
|
3067
3076
|
const metadata = call.metadata ?? {};
|
|
3068
3077
|
const recent = Array.isArray(metadata.recentTalkEvents) ? metadata.recentTalkEvents.filter((entry) => Boolean(entry) && typeof entry === "object" && !Array.isArray(entry)) : [];
|
|
@@ -3737,12 +3746,12 @@ const REALTIME_VOICE_CONSULT_SYSTEM_PROMPT = [
|
|
|
3737
3746
|
"Do not print secret values or dump environment variables; only check whether required configuration is present.",
|
|
3738
3747
|
"Be accurate, brief, and speakable."
|
|
3739
3748
|
].join(" ");
|
|
3740
|
-
const loadTelnyxProvider = createLazyRuntimeModule(() => import("./telnyx-
|
|
3741
|
-
const loadTwilioProvider = createLazyRuntimeModule(() => import("./twilio-
|
|
3742
|
-
const loadPlivoProvider = createLazyRuntimeModule(() => import("./plivo-
|
|
3749
|
+
const loadTelnyxProvider = createLazyRuntimeModule(() => import("./telnyx-BG56lL7z.js"));
|
|
3750
|
+
const loadTwilioProvider = createLazyRuntimeModule(() => import("./twilio-B3FQ_P9x.js"));
|
|
3751
|
+
const loadPlivoProvider = createLazyRuntimeModule(() => import("./plivo-B-KvPVji.js"));
|
|
3743
3752
|
const loadMockProvider = createLazyRuntimeModule(() => import("./mock-YsvBTX-7.js"));
|
|
3744
3753
|
const loadRealtimeVoiceRuntime = createLazyRuntimeModule(() => import("./realtime-voice.runtime-vtdCOWg-.js"));
|
|
3745
|
-
const loadRealtimeHandler = createLazyRuntimeModule(() => import("./realtime-handler-
|
|
3754
|
+
const loadRealtimeHandler = createLazyRuntimeModule(() => import("./realtime-handler-hIVPEZxN.js"));
|
|
3746
3755
|
function resolveVoiceCallConsultSessionKey(call) {
|
|
3747
3756
|
return resolveVoiceCallSessionKey({
|
|
3748
3757
|
config: call.config,
|
|
@@ -3867,7 +3876,8 @@ async function createRealtimeInstructionsResolver(params) {
|
|
|
3867
3876
|
baseInstructions: params.config.realtime.instructions,
|
|
3868
3877
|
config: genericConfig,
|
|
3869
3878
|
coreConfig: params.coreConfig,
|
|
3870
|
-
agentRuntime: params.agentRuntime
|
|
3879
|
+
agentRuntime: params.agentRuntime,
|
|
3880
|
+
agentId: params.config.agentId
|
|
3871
3881
|
});
|
|
3872
3882
|
const entries = await Promise.all(listRealtimeAgentIds(params.config, params.coreConfig).map(async (agentId) => {
|
|
3873
3883
|
return [agentId, await buildRealtimeVoiceInstructions({
|
|
@@ -3877,7 +3887,8 @@ async function createRealtimeInstructionsResolver(params) {
|
|
|
3877
3887
|
agentId
|
|
3878
3888
|
},
|
|
3879
3889
|
coreConfig: params.coreConfig,
|
|
3880
|
-
agentRuntime: params.agentRuntime
|
|
3890
|
+
agentRuntime: params.agentRuntime,
|
|
3891
|
+
agentId
|
|
3881
3892
|
})];
|
|
3882
3893
|
}));
|
|
3883
3894
|
const instructionsByAgentId = new Map(entries);
|
|
@@ -3895,8 +3906,13 @@ async function createVoiceCallRuntime(params) {
|
|
|
3895
3906
|
error: console.error,
|
|
3896
3907
|
debug: console.debug
|
|
3897
3908
|
};
|
|
3898
|
-
const config = resolveVoiceCallConfig(rawConfig);
|
|
3899
3909
|
const cfg = fullConfig ?? coreConfig;
|
|
3910
|
+
const unresolvedConfig = resolveVoiceCallConfig(rawConfig);
|
|
3911
|
+
const configuredAgentId = unresolvedConfig.agentId ? normalizeAgentId(unresolvedConfig.agentId) : resolveDefaultAgentId(cfg);
|
|
3912
|
+
const config = {
|
|
3913
|
+
...unresolvedConfig,
|
|
3914
|
+
agentId: configuredAgentId
|
|
3915
|
+
};
|
|
3900
3916
|
if (!config.enabled) throw new Error("Voice call disabled. Enable the plugin entry in config.");
|
|
3901
3917
|
if (config.skipSignatureVerification) log.warn("[voice-call] SECURITY WARNING: skipSignatureVerification=true disables webhook signature verification (development only). Do not use in production.");
|
|
3902
3918
|
const validation = validateProviderConfig(config);
|
|
@@ -4061,4 +4077,4 @@ async function createVoiceCallRuntime(params) {
|
|
|
4061
4077
|
}
|
|
4062
4078
|
}
|
|
4063
4079
|
//#endregion
|
|
4064
|
-
export {
|
|
4080
|
+
export { validateProviderConfig as S, escapeXml as _, normalizeProviderStatus as a, resolveVoiceCallConfig as b, resolveWebhookExposureStatus as c, setupTailscaleExposureRoute as d, TELEPHONY_DEFAULT_TTS_TIMEOUT_MS as f, resolveUserPath as g, resolveCallAgentId as h, mapProviderStatusToEndReason as i, cleanupTailscaleExposureRoute as l, resolveVoiceResponseModel as m, normalizeProxyIp as n, canonicalizeVoiceCallMediaBase64 as o, chunkAudio as p, isProviderStatusTerminal as r, getHeader as s, createVoiceCallRuntime as t, getTailscaleSelfInfo as u, mapVoiceToPolly as v, resolveVoiceCallSessionKey as x, VoiceCallConfigSchema as y };
|
package/dist/runtime-entry.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { t as createVoiceCallRuntime } from "./runtime-entry-
|
|
1
|
+
import { t as createVoiceCallRuntime } from "./runtime-entry-CQtitvRd.js";
|
|
2
2
|
export { createVoiceCallRuntime };
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { s as verifyTelnyxWebhook, t as guardedJsonApiRequest } from "./guarded-json-api-
|
|
1
|
+
import { s as verifyTelnyxWebhook, t as guardedJsonApiRequest } from "./guarded-json-api-Dxhe25Zi.js";
|
|
2
2
|
import crypto from "node:crypto";
|
|
3
3
|
//#region extensions/voice-call/src/providers/telnyx.ts
|
|
4
4
|
function normalizeTelnyxDirection(direction) {
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { fetchWithSsrFGuard } from "./runtime-api.js";
|
|
2
2
|
import "./api.js";
|
|
3
3
|
import { n as requireSupportedTwilioApiHostname, r as resolveTwilioApiBaseUrl } from "./twilio-region-4fkgz3UG.js";
|
|
4
|
-
import { _ as
|
|
5
|
-
import { c as verifyTwilioWebhook, i as readProviderJsonResponseText, n as cancelProviderResponseBody, r as readProviderErrorResponseSnippet, t as guardedJsonApiRequest } from "./guarded-json-api-
|
|
4
|
+
import { _ as escapeXml, a as normalizeProviderStatus, i as mapProviderStatusToEndReason, p as chunkAudio, r as isProviderStatusTerminal, s as getHeader, v as mapVoiceToPolly } from "./runtime-entry-CQtitvRd.js";
|
|
5
|
+
import { c as verifyTwilioWebhook, i as readProviderJsonResponseText, n as cancelProviderResponseBody, r as readProviderErrorResponseSnippet, t as guardedJsonApiRequest } from "./guarded-json-api-Dxhe25Zi.js";
|
|
6
6
|
import { normalizeOptionalString } from "openclaw/plugin-sdk/string-coerce-runtime";
|
|
7
7
|
import { sleepWithAbort } from "openclaw/plugin-sdk/runtime-env";
|
|
8
8
|
import crypto from "node:crypto";
|
|
@@ -1,14 +1,11 @@
|
|
|
1
1
|
import { type TLocalizedValidationError } from '../error/index.mjs';
|
|
2
2
|
import { type StaticDecode, type StaticEncode, type TProperties, type TSchema } from '../type/index.mjs';
|
|
3
|
-
import { BuildResult, EvaluateResult } from '../schema/index.mjs';
|
|
4
3
|
export declare class Validator<Context extends TProperties = TProperties, Type extends TSchema = TSchema, Encode extends unknown = StaticEncode<Type, Context>, Decode extends unknown = StaticDecode<Type, Context>> {
|
|
5
4
|
private readonly hasCodec;
|
|
6
5
|
private readonly buildResult;
|
|
7
6
|
private readonly evaluateResult;
|
|
8
|
-
/** Constructs a Validator
|
|
7
|
+
/** Constructs a Validator. */
|
|
9
8
|
constructor(context: Context, type: Type);
|
|
10
|
-
/** Constructs a Validator with the given arguments. */
|
|
11
|
-
constructor(hasCodec: boolean, buildResult: BuildResult, evaluateResult: EvaluateResult);
|
|
12
9
|
/** Returns true if this Validator is using JIT acceleration. */
|
|
13
10
|
IsAccelerated(): boolean;
|
|
14
11
|
/** Returns the Context for this validator. */
|
|
@@ -61,5 +61,5 @@ export declare function Keys(value: Record<PropertyKey, unknown>): string[];
|
|
|
61
61
|
export declare function Symbols(value: Record<PropertyKey, unknown>): symbol[];
|
|
62
62
|
/** Returns the property values for the given object via `Object.values()` */
|
|
63
63
|
export declare function Values(value: Record<PropertyKey, unknown>): unknown[];
|
|
64
|
-
/**
|
|
64
|
+
/** Returns true if left and right values are structurally equal */
|
|
65
65
|
export declare function IsDeepEqual(left: unknown, right: unknown): boolean;
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
// deno-fmt-ignore-file
|
|
1
2
|
import * as String from './string.mjs';
|
|
2
3
|
// --------------------------------------------------------------------------
|
|
3
4
|
// Guards
|
|
@@ -203,7 +204,9 @@ function DeepEqualArray(left, right) {
|
|
|
203
204
|
return IsArray(right) && IsEqual(left.length, right.length) &&
|
|
204
205
|
left.every((_, index) => IsDeepEqual(left[index], right[index]));
|
|
205
206
|
}
|
|
206
|
-
/**
|
|
207
|
+
/** Returns true if left and right values are structurally equal */
|
|
207
208
|
export function IsDeepEqual(left, right) {
|
|
208
|
-
return (IsArray(left) ? DeepEqualArray(left, right) :
|
|
209
|
+
return (IsArray(left) ? DeepEqualArray(left, right) :
|
|
210
|
+
IsObject(left) ? DeepEqualObject(left, right) :
|
|
211
|
+
IsEqual(left, right));
|
|
209
212
|
}
|
|
@@ -5,6 +5,18 @@ function IsBetween(value, min, max) {
|
|
|
5
5
|
return value >= min && value <= max;
|
|
6
6
|
}
|
|
7
7
|
// --------------------------------------------------------------------------
|
|
8
|
+
// IsZeroWidthJoiner
|
|
9
|
+
// --------------------------------------------------------------------------
|
|
10
|
+
function IsZeroWidthJoiner(value) {
|
|
11
|
+
return (value === 0x200D);
|
|
12
|
+
}
|
|
13
|
+
// --------------------------------------------------------------------------
|
|
14
|
+
// IsHighSurrogate
|
|
15
|
+
// --------------------------------------------------------------------------
|
|
16
|
+
function IsHighSurrogate(value) {
|
|
17
|
+
return IsBetween(value, 0xD800, 0xDBFF);
|
|
18
|
+
}
|
|
19
|
+
// --------------------------------------------------------------------------
|
|
8
20
|
// IsRegionalIndicator
|
|
9
21
|
// --------------------------------------------------------------------------
|
|
10
22
|
function IsRegionalIndicator(value) {
|
|
@@ -72,10 +84,10 @@ function NextGraphemeClusterIndex(value, clusterStart) {
|
|
|
72
84
|
// IsGraphemeCodePoint
|
|
73
85
|
// --------------------------------------------------------------------------
|
|
74
86
|
function IsGraphemeCodePoint(value) {
|
|
75
|
-
return (
|
|
76
|
-
|
|
77
|
-
(value
|
|
78
|
-
|
|
87
|
+
return (IsHighSurrogate(value) ||
|
|
88
|
+
IsCombiningMark(value) ||
|
|
89
|
+
IsVariationSelector(value) ||
|
|
90
|
+
IsZeroWidthJoiner(value));
|
|
79
91
|
}
|
|
80
92
|
// --------------------------------------------------------------------------
|
|
81
93
|
// GraphemeCount
|
|
@@ -1,47 +1,66 @@
|
|
|
1
1
|
// deno-fmt-ignore-file
|
|
2
|
-
import * as Schema from '../types/index.mjs';
|
|
3
2
|
import { Hashing } from '../../system/hashing/index.mjs';
|
|
4
3
|
import { EmitGuard as E } from '../../guard/index.mjs';
|
|
5
4
|
import { BuildSchema } from './schema.mjs';
|
|
6
|
-
const
|
|
5
|
+
const index = [0];
|
|
6
|
+
const names = new Map;
|
|
7
|
+
const funcs = new Map();
|
|
8
|
+
// ------------------------------------------------------------------
|
|
9
|
+
// CreateName
|
|
10
|
+
// ------------------------------------------------------------------
|
|
11
|
+
function NextName() {
|
|
12
|
+
return Hashing.Hash(index[0]++);
|
|
13
|
+
}
|
|
14
|
+
function CreateName(schema, href) {
|
|
15
|
+
if (!names.has(schema))
|
|
16
|
+
names.set(schema, new Map());
|
|
17
|
+
const hrefs = names.get(schema);
|
|
18
|
+
if (hrefs.has(href))
|
|
19
|
+
return hrefs.get(href);
|
|
20
|
+
const name = NextName();
|
|
21
|
+
hrefs.set(href, name);
|
|
22
|
+
return name;
|
|
23
|
+
}
|
|
7
24
|
// ------------------------------------------------------------------
|
|
8
25
|
// CreateCallExpression
|
|
9
26
|
// ------------------------------------------------------------------
|
|
10
|
-
function CreateCallExpression(context, _schema,
|
|
27
|
+
function CreateCallExpression(context, _schema, name, value) {
|
|
11
28
|
return context.UseUnevaluated()
|
|
12
|
-
? E.Call(`check_${
|
|
13
|
-
: E.Call(`check_${
|
|
29
|
+
? E.Call(`check_${name}`, ['context', value])
|
|
30
|
+
: E.Call(`check_${name}`, [value]);
|
|
14
31
|
}
|
|
15
32
|
// ------------------------------------------------------------------
|
|
16
33
|
// CreateFunctionExpression
|
|
17
34
|
// ------------------------------------------------------------------
|
|
18
|
-
function CreateFunctionExpression(stack, context, schema,
|
|
35
|
+
function CreateFunctionExpression(stack, context, schema, name) {
|
|
19
36
|
const expression = BuildSchema(stack, context, schema, 'value');
|
|
20
37
|
return context.UseUnevaluated()
|
|
21
|
-
? E.ConstDeclaration(`check_${
|
|
22
|
-
: E.ConstDeclaration(`check_${
|
|
38
|
+
? E.ConstDeclaration(`check_${name}`, E.ArrowFunction(['context', 'value'], expression))
|
|
39
|
+
: E.ConstDeclaration(`check_${name}`, E.ArrowFunction(['value'], expression));
|
|
23
40
|
}
|
|
24
41
|
// ------------------------------------------------------------------
|
|
25
42
|
// ResetFunctions
|
|
26
43
|
// ------------------------------------------------------------------
|
|
27
44
|
export function ResetFunctions() {
|
|
28
|
-
|
|
45
|
+
index[0] = 0;
|
|
46
|
+
names.clear();
|
|
47
|
+
funcs.clear();
|
|
29
48
|
}
|
|
30
49
|
// ------------------------------------------------------------------
|
|
31
50
|
// GetFunctions
|
|
32
51
|
// ------------------------------------------------------------------
|
|
33
52
|
export function GetFunctions() {
|
|
34
|
-
return [...
|
|
53
|
+
return [...funcs.values()];
|
|
35
54
|
}
|
|
36
55
|
// ------------------------------------------------------------------
|
|
37
56
|
// CreateFunction
|
|
38
57
|
// ------------------------------------------------------------------
|
|
39
58
|
export function CreateFunction(stack, context, schema, value) {
|
|
40
|
-
const
|
|
41
|
-
const call = CreateCallExpression(context, schema,
|
|
42
|
-
if (
|
|
59
|
+
const name = CreateName(schema, stack.BaseURL().href);
|
|
60
|
+
const call = CreateCallExpression(context, schema, name, value);
|
|
61
|
+
if (funcs.has(name))
|
|
43
62
|
return call;
|
|
44
|
-
|
|
45
|
-
|
|
63
|
+
funcs.set(name, '');
|
|
64
|
+
funcs.set(name, CreateFunctionExpression(stack, context, schema, name));
|
|
46
65
|
return call;
|
|
47
66
|
}
|
|
@@ -9,3 +9,8 @@ export declare function ReadonlyObjectDeferred<Type extends TSchema>(type: Type,
|
|
|
9
9
|
export type TReadonlyObject<Type extends TSchema> = (TReadonlyObjectAction<Type>);
|
|
10
10
|
/** This type is an alias for TypeScript's `Readonly<T>` utility type. It will make all properties of a TObject readonly or marks an TArray or TTuple as immutable `readonly T[]`. */
|
|
11
11
|
export declare function ReadonlyObject<Type extends TSchema>(type: Type, options?: TSchemaOptions): TReadonlyObject<Type>;
|
|
12
|
+
/**
|
|
13
|
+
* This type has been renamed to ReadonlyObject.
|
|
14
|
+
* @deprecated
|
|
15
|
+
*/
|
|
16
|
+
export declare const ReadonlyType: typeof ReadonlyObject;
|
|
@@ -9,3 +9,11 @@ export function ReadonlyObjectDeferred(type, options = {}) {
|
|
|
9
9
|
export function ReadonlyObject(type, options = {}) {
|
|
10
10
|
return ReadonlyObjectAction(type, options);
|
|
11
11
|
}
|
|
12
|
+
// ------------------------------------------------------------------
|
|
13
|
+
// Alias
|
|
14
|
+
// ------------------------------------------------------------------
|
|
15
|
+
/**
|
|
16
|
+
* This type has been renamed to ReadonlyObject.
|
|
17
|
+
* @deprecated
|
|
18
|
+
*/
|
|
19
|
+
export const ReadonlyType = ReadonlyObject;
|
|
@@ -19,7 +19,7 @@ export { Omit, type TOmit, type TOmitDeferred } from './type/action/omit.mjs';
|
|
|
19
19
|
export { Parameters, type TParameters, type TParametersDeferred } from './type/action/parameters.mjs';
|
|
20
20
|
export { Partial, type TPartial, type TPartialDeferred } from './type/action/partial.mjs';
|
|
21
21
|
export { Pick, type TPick, type TPickDeferred } from './type/action/pick.mjs';
|
|
22
|
-
export { ReadonlyObject, type TReadonlyObject, type TReadonlyObjectDeferred } from './type/action/readonly_object.mjs';
|
|
22
|
+
export { ReadonlyObject, ReadonlyType, type TReadonlyObject, type TReadonlyObjectDeferred } from './type/action/readonly_object.mjs';
|
|
23
23
|
export { Required, type TRequired, type TRequiredDeferred } from './type/action/required.mjs';
|
|
24
24
|
export { ReturnType, type TReturnType, type TReturnTypeDeferred } from './type/action/return_type.mjs';
|
|
25
25
|
export { type TUncapitalize, type TUncapitalizeDeferred, Uncapitalize } from './type/action/uncapitalize.mjs';
|
|
@@ -31,7 +31,7 @@ export { Omit } from './type/action/omit.mjs';
|
|
|
31
31
|
export { Parameters } from './type/action/parameters.mjs';
|
|
32
32
|
export { Partial } from './type/action/partial.mjs';
|
|
33
33
|
export { Pick } from './type/action/pick.mjs';
|
|
34
|
-
export { ReadonlyObject } from './type/action/readonly_object.mjs';
|
|
34
|
+
export { ReadonlyObject, ReadonlyType } from './type/action/readonly_object.mjs';
|
|
35
35
|
export { Required } from './type/action/required.mjs';
|
|
36
36
|
export { ReturnType } from './type/action/return_type.mjs';
|
|
37
37
|
export { Uncapitalize } from './type/action/uncapitalize.mjs';
|
|
@@ -111,27 +111,24 @@ type User = Type.Static<typeof User> // type User = {
|
|
|
111
111
|
|
|
112
112
|
## Script
|
|
113
113
|
|
|
114
|
-
[Documentation](https://sinclairzx81.github.io/typebox/#/docs/script/overview) | [Example 1](https://www.typescriptlang.org/play/?target=99&module=7#code/
|
|
115
|
-
|
|
116
|
-
TypeBox includes a syntax engine that can transform TypeScript declarations into JSON Schema. The engine is a full syntactic frontend to Type.* and supports many advanced type-level constructs such as Conditional, Mapped, Indexed, Infer, Generics, Distributed types and more. This feature is implemented symmetrically at runtime and statically via TypeScript Template Literal types.
|
|
117
|
-
|
|
118
|
-
Syntax highlighting is available via the [Visual Studio Marketplace](https://marketplace.visualstudio.com/items?itemName=sinclairzx81.typebox-script)
|
|
114
|
+
[Documentation](https://sinclairzx81.github.io/typebox/#/docs/script/overview) | [Example 1](https://www.typescriptlang.org/play/?target=99&module=7#code/JYWwDg9gTgLgBAFQJ5gKZwGZQiOByGFVAIwgA88AoSgehrgFkIATAVwBtVKBjCAOwDO8BgEMYACzgBeREQB0AZW5RgYGAAoABpThxCaOADVU3GNABM0uAG84ZAFxw+rEMVRQANHCSPnr93AAvjp6REYmZlAAzFa2Dk4ubp7evonuXgBeqf5QQSH66Mam0AAssXbZSV4+CTmZlelwAO4NucGaAJTUdHAAIqhofMyofMIsHFy8gvC2DKgCkoFWyGiKyqoaohJemrr5YcawqGSxIbqQAsAwwPyORZElHmdO0CAi7HcR0FFPurqsADdPsUoOYQsFdAU4ABxVA4VAwKBIU5-OAA9zXbjzT5HMgAbQAur8-sAhsAsQJWoTwfsDFt3MB3ii-iJXMARjBgQ9ibpmMAMBhWAJUFzSjy4AI0NwOCIoKKoCUaZCwnMFszdABzOEgBFIxyw+GIpDit4wBnvRz0lTvGmdbr0ABKrFGoHQDtQGE4phufEoqvEcjA2DQsHZAjkWsNSMDwYxYbk6NDFLkV1QIHDQYgIeu80DEEu134MazcdzZD98wDmez8cjOqNxZrucTmNzqfTjdL4b4r3endDZYrC37OfDdd1SBH8Zb5LbZo71a7ckBU8H-tX4dN5vYG7kfIFQtQu-L68XA83Ym3u9ZxHZo2PQ6rsfPci31p3Z9HcklJhlUAftD0AoMBiOScAAJJ8Bg7gjFilCCnw3r8HAUAjMMUDqDqCyOCsR7AaB3AADwFBAGCMJWAB8HQ2CEWEBuODYzhSeIAAwEnmBY+nI5a6HREbahOCZxsxbFyD2UBvDuPFwHxDHRkx8ysexK7SXxb6Mju+6CsK3G0ZWr6Xu+cg3neMC6bx+nqX2P7Suwsq6YEQA) | [Example 2](https://www.typescriptlang.org/play/?target=99&module=7#code/JYWwDg9gTgLgBAFQJ5gKZwGZQiOByGFVAIwgA88AoSgehrgFkIATAVwBtVKA7AQxFQBnMLwDG6BrxgALOAG9KcOKjKRYcURG6D4ANVSiY0AExwAvIiIA6APLEAVgZgAKOXDIAuS2isA5ViDEqFDOAJQANHBIXsg+-oHBYXAAvqGKyqrQ8Jraek7QAMzm3qi2Dk6u7jHW8UEhEVHVcQF1YZEAXk2ltYmhKWlKKmrZWjpw+obQACzFsaV2joaVniV+Lb2R0as99R1dawm7cADu+ztJqZTJ1HRwACKoaNzMqNzwTGyclDlj+rAqs2sCwqCiUkEEwBgwC0XkkMisEyMUCm4XS3GgIF47FhUmkCPyUAKqKUrAAbjj4YiTFc0j94ABxVA4VAwKBIQE+YFLUFwUnBKHiQT7ACCUCgvCQzj+MBUEXSwGewEFIrFEuccwOrVCaUudMYUmCwCxHPm5W56X4xGArxgFLxVORxLgzGAGAwrEEqDt+MmjvSwgMHF4UG9DqmNO+o3eQlkFg1XJcPIA5kyBKytozmemnZiZVAjdj9XmCxHaPQAEqsN6gdDl1AYTiGaHcSgMGNWMDYNCwa2CKwprNsjtd-m9qx8nuCqyQ1AgPudiDdqFCDsQCFQrTDxejldkVvthdLscDtNDw87vsTgUrmdzrdHlfoqCY9j3i9WPdtwR4889lcnlkzxHP9L1HKdb3nYDlz7Mk3xAj992-ODoKsXNDSxZCxxdN0PVKX8UM-A8oLHND8ww-Cx0ta03kw3dEJ-YiV1IgtaL7ANRCDKBWIQss4AAZRgKQlTgABJbgMGCV5xEod1uCbLQ4CgV4XhCARv32AShNEAAeQg0AgDBGBjAA+PoeTUvEAPTccwKEABtAAGABdVd12bBClAs-tU0ApAbMneznKsJ8Xw8uAvKsocryVQKXNgvdPPbZiMOw91PTCrzktfKibQypKDTI192M4hDkiAA) | [Challenge](test/typescript/readme.md)
|
|
119
115
|
|
|
116
|
+
TypeBox includes a runtime scripting engine that can transform TypeScript definitions into JSON Schema. The engine is implemented symmetrically at runtime and inside TypeScript's type system. It supports many programmable type-level constructs such as Conditional, Mapped, Indexed, Generic, Distributive Conditional, and more. The engine is designed for TypeScript 7 but is supported in TypeScript 5 and above.
|
|
120
117
|
|
|
121
118
|
### Example
|
|
122
119
|
|
|
123
|
-
|
|
120
|
+
Syntax highlighting is available via the [Visual Studio Marketplace](https://marketplace.visualstudio.com/items?itemName=sinclairzx81.typebox-script)
|
|
124
121
|
|
|
125
122
|
```typescript
|
|
126
123
|
// Module
|
|
127
124
|
const Math = Type.Script(`
|
|
128
125
|
type Vector2 = { x: number, y: number }
|
|
129
|
-
type Vector3 =
|
|
130
|
-
type Vector4 =
|
|
126
|
+
type Vector3 = { x: number, y: number, z: number }
|
|
127
|
+
type Vector4 = { x: number, y: number, z: number, w: number }
|
|
131
128
|
`)
|
|
132
129
|
|
|
133
130
|
// Dependent Module
|
|
134
|
-
const { Mesh } = Type.Script(
|
|
131
|
+
const { Mesh } = Type.Script(Math, `
|
|
135
132
|
type Vertex = {
|
|
136
133
|
position: Vector4,
|
|
137
134
|
normal: Vector3,
|
|
@@ -298,29 +295,29 @@ The following table shows compile performance for various JSON Schema structures
|
|
|
298
295
|
┌──────────────────────┬─────────────┬─────────────┐
|
|
299
296
|
│ Compile │ TB1X │ AJV8 │
|
|
300
297
|
├──────────────────────┼─────────────┼─────────────┤
|
|
301
|
-
│ Boolean │
|
|
302
|
-
│ Number │
|
|
303
|
-
│ String │
|
|
304
|
-
│ Null │
|
|
305
|
-
│ Literal_String │
|
|
306
|
-
│ Literal_Number │
|
|
307
|
-
│ Literal_Boolean │
|
|
308
|
-
│ Pattern │
|
|
309
|
-
│ Object_Open │
|
|
310
|
-
│ Object_Close │
|
|
311
|
-
│ Object_Vector3 │
|
|
312
|
-
│ Object_Basis3 │
|
|
313
|
-
│ Intersect_And │
|
|
314
|
-
│ Intersect_Structural │
|
|
315
|
-
│ Union_Or │
|
|
316
|
-
│ Union_Structural │
|
|
317
|
-
│ Tuple_Values │
|
|
318
|
-
│ Tuple_Objects │
|
|
319
|
-
│ Array_Numbers_4 │
|
|
320
|
-
│ Array_Numbers_8 │
|
|
321
|
-
│ Array_Numbers_16 │
|
|
322
|
-
│ Array_Objects_Open │
|
|
323
|
-
│ Array_Objects_Close │
|
|
298
|
+
│ Boolean │ 39.7K ops/s │ 6.8K ops/s │
|
|
299
|
+
│ Number │ 86.2K ops/s │ 7.5K ops/s │
|
|
300
|
+
│ String │ 82.6K ops/s │ 8.2K ops/s │
|
|
301
|
+
│ Null │ 62K ops/s │ 7.3K ops/s │
|
|
302
|
+
│ Literal_String │ 72.1K ops/s │ 5.7K ops/s │
|
|
303
|
+
│ Literal_Number │ 72.7K ops/s │ 6.9K ops/s │
|
|
304
|
+
│ Literal_Boolean │ 80.9K ops/s │ 7K ops/s │
|
|
305
|
+
│ Pattern │ 38.7K ops/s │ 5.7K ops/s │
|
|
306
|
+
│ Object_Open │ 16.3K ops/s │ 1.3K ops/s │
|
|
307
|
+
│ Object_Close │ 15.7K ops/s │ 952 ops/s │
|
|
308
|
+
│ Object_Vector3 │ 40.2K ops/s │ 3.2K ops/s │
|
|
309
|
+
│ Object_Basis3 │ 16.1K ops/s │ 834 ops/s │
|
|
310
|
+
│ Intersect_And │ 45.7K ops/s │ 3.5K ops/s │
|
|
311
|
+
│ Intersect_Structural │ 21K ops/s │ 1.6K ops/s │
|
|
312
|
+
│ Union_Or │ 45.1K ops/s │ 3.4K ops/s │
|
|
313
|
+
│ Union_Structural │ 27.6K ops/s │ 2K ops/s │
|
|
314
|
+
│ Tuple_Values │ 14.7K ops/s │ 2K ops/s │
|
|
315
|
+
│ Tuple_Objects │ 3.7K ops/s │ 380 ops/s │
|
|
316
|
+
│ Array_Numbers_4 │ 73.6K ops/s │ 4.3K ops/s │
|
|
317
|
+
│ Array_Numbers_8 │ 50.9K ops/s │ 3.8K ops/s │
|
|
318
|
+
│ Array_Numbers_16 │ 85K ops/s │ 3.9K ops/s │
|
|
319
|
+
│ Array_Objects_Open │ 18.9K ops/s │ 789 ops/s │
|
|
320
|
+
│ Array_Objects_Close │ 17.9K ops/s │ 909 ops/s │
|
|
324
321
|
└──────────────────────┴─────────────┴─────────────┘
|
|
325
322
|
```
|
|
326
323
|
|
|
@@ -77,6 +77,7 @@ class Receiver extends Writable {
|
|
|
77
77
|
|
|
78
78
|
this._totalPayloadLength = 0;
|
|
79
79
|
this._messageLength = 0;
|
|
80
|
+
this._numFragments = 0;
|
|
80
81
|
this._fragments = [];
|
|
81
82
|
|
|
82
83
|
this._errored = false;
|
|
@@ -500,6 +501,19 @@ class Receiver extends Writable {
|
|
|
500
501
|
return;
|
|
501
502
|
}
|
|
502
503
|
|
|
504
|
+
if (this._maxFragments > 0 && ++this._numFragments > this._maxFragments) {
|
|
505
|
+
const error = this.createError(
|
|
506
|
+
RangeError,
|
|
507
|
+
'Too many message fragments',
|
|
508
|
+
false,
|
|
509
|
+
1008,
|
|
510
|
+
'WS_ERR_TOO_MANY_BUFFERED_PARTS'
|
|
511
|
+
);
|
|
512
|
+
|
|
513
|
+
cb(error);
|
|
514
|
+
return;
|
|
515
|
+
}
|
|
516
|
+
|
|
503
517
|
if (this._compressed) {
|
|
504
518
|
this._state = INFLATING;
|
|
505
519
|
this.decompress(data, cb);
|
|
@@ -507,22 +521,6 @@ class Receiver extends Writable {
|
|
|
507
521
|
}
|
|
508
522
|
|
|
509
523
|
if (data.length) {
|
|
510
|
-
if (
|
|
511
|
-
this._maxFragments > 0 &&
|
|
512
|
-
this._fragments.length >= this._maxFragments
|
|
513
|
-
) {
|
|
514
|
-
const error = this.createError(
|
|
515
|
-
RangeError,
|
|
516
|
-
'Too many message fragments',
|
|
517
|
-
false,
|
|
518
|
-
1008,
|
|
519
|
-
'WS_ERR_TOO_MANY_BUFFERED_PARTS'
|
|
520
|
-
);
|
|
521
|
-
|
|
522
|
-
cb(error);
|
|
523
|
-
return;
|
|
524
|
-
}
|
|
525
|
-
|
|
526
524
|
//
|
|
527
525
|
// This message is not compressed so its length is the sum of the payload
|
|
528
526
|
// length of all fragments.
|
|
@@ -562,22 +560,6 @@ class Receiver extends Writable {
|
|
|
562
560
|
return;
|
|
563
561
|
}
|
|
564
562
|
|
|
565
|
-
if (
|
|
566
|
-
this._maxFragments > 0 &&
|
|
567
|
-
this._fragments.length >= this._maxFragments
|
|
568
|
-
) {
|
|
569
|
-
const error = this.createError(
|
|
570
|
-
RangeError,
|
|
571
|
-
'Too many message fragments',
|
|
572
|
-
false,
|
|
573
|
-
1008,
|
|
574
|
-
'WS_ERR_TOO_MANY_BUFFERED_PARTS'
|
|
575
|
-
);
|
|
576
|
-
|
|
577
|
-
cb(error);
|
|
578
|
-
return;
|
|
579
|
-
}
|
|
580
|
-
|
|
581
563
|
this._fragments.push(buf);
|
|
582
564
|
}
|
|
583
565
|
|
|
@@ -604,6 +586,7 @@ class Receiver extends Writable {
|
|
|
604
586
|
this._totalPayloadLength = 0;
|
|
605
587
|
this._messageLength = 0;
|
|
606
588
|
this._fragmented = 0;
|
|
589
|
+
this._numFragments = 0;
|
|
607
590
|
this._fragments = [];
|
|
608
591
|
|
|
609
592
|
if (this._opcode === 2) {
|
|
@@ -43,9 +43,9 @@ class WebSocketServer extends EventEmitter {
|
|
|
43
43
|
* called
|
|
44
44
|
* @param {Function} [options.handleProtocols] A hook to handle protocols
|
|
45
45
|
* @param {String} [options.host] The hostname where to bind the server
|
|
46
|
-
* @param {Number} [options.maxBufferedChunks=
|
|
46
|
+
* @param {Number} [options.maxBufferedChunks=262144] The maximum number of
|
|
47
47
|
* buffered data chunks
|
|
48
|
-
* @param {Number} [options.maxFragments=
|
|
48
|
+
* @param {Number} [options.maxFragments=16384] The maximum number of message
|
|
49
49
|
* fragments
|
|
50
50
|
* @param {Number} [options.maxPayload=104857600] The maximum allowed message
|
|
51
51
|
* size
|
|
@@ -69,8 +69,8 @@ class WebSocketServer extends EventEmitter {
|
|
|
69
69
|
options = {
|
|
70
70
|
allowSynchronousEvents: true,
|
|
71
71
|
autoPong: true,
|
|
72
|
-
maxBufferedChunks:
|
|
73
|
-
maxFragments:
|
|
72
|
+
maxBufferedChunks: 256 * 1024,
|
|
73
|
+
maxFragments: 16 * 1024,
|
|
74
74
|
maxPayload: 100 * 1024 * 1024,
|
|
75
75
|
skipUTF8Validation: false,
|
|
76
76
|
perMessageDeflate: false,
|
|
@@ -646,9 +646,9 @@ module.exports = WebSocket;
|
|
|
646
646
|
* masking key
|
|
647
647
|
* @param {Number} [options.handshakeTimeout] Timeout in milliseconds for the
|
|
648
648
|
* handshake request
|
|
649
|
-
* @param {Number} [options.maxBufferedChunks=
|
|
649
|
+
* @param {Number} [options.maxBufferedChunks=262144] The maximum number of
|
|
650
650
|
* buffered data chunks
|
|
651
|
-
* @param {Number} [options.maxFragments=
|
|
651
|
+
* @param {Number} [options.maxFragments=16384] The maximum number of message
|
|
652
652
|
* fragments
|
|
653
653
|
* @param {Number} [options.maxPayload=104857600] The maximum allowed message
|
|
654
654
|
* size
|
|
@@ -670,8 +670,8 @@ function initAsClient(websocket, address, protocols, options) {
|
|
|
670
670
|
autoPong: true,
|
|
671
671
|
closeTimeout: CLOSE_TIMEOUT,
|
|
672
672
|
protocolVersion: protocolVersions[1],
|
|
673
|
-
maxBufferedChunks:
|
|
674
|
-
maxFragments:
|
|
673
|
+
maxBufferedChunks: 256 * 1024,
|
|
674
|
+
maxFragments: 16 * 1024,
|
|
675
675
|
maxPayload: 100 * 1024 * 1024,
|
|
676
676
|
skipUTF8Validation: false,
|
|
677
677
|
perMessageDeflate: true,
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "ws",
|
|
3
|
-
"version": "8.21.
|
|
3
|
+
"version": "8.21.1",
|
|
4
4
|
"description": "Simple to use, blazing fast and thoroughly tested websocket client and server for Node.js",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"HyBi",
|
|
@@ -66,5 +66,9 @@
|
|
|
66
66
|
"nyc": "^15.0.0",
|
|
67
67
|
"prettier": "^3.0.0",
|
|
68
68
|
"utf-8-validate": "^6.0.0"
|
|
69
|
+
},
|
|
70
|
+
"allowScripts": {
|
|
71
|
+
"bufferutil": true,
|
|
72
|
+
"utf-8-validate": true
|
|
69
73
|
}
|
|
70
74
|
}
|
package/openclaw.plugin.json
CHANGED
|
@@ -11,20 +11,6 @@
|
|
|
11
11
|
"contracts": {
|
|
12
12
|
"tools": ["voice_call"]
|
|
13
13
|
},
|
|
14
|
-
"channelEnvVars": {
|
|
15
|
-
"voice-call": [
|
|
16
|
-
"TELNYX_API_KEY",
|
|
17
|
-
"TELNYX_CONNECTION_ID",
|
|
18
|
-
"TELNYX_PUBLIC_KEY",
|
|
19
|
-
"TWILIO_ACCOUNT_SID",
|
|
20
|
-
"TWILIO_AUTH_TOKEN",
|
|
21
|
-
"TWILIO_FROM_NUMBER",
|
|
22
|
-
"PLIVO_AUTH_ID",
|
|
23
|
-
"PLIVO_AUTH_TOKEN",
|
|
24
|
-
"NGROK_AUTHTOKEN",
|
|
25
|
-
"NGROK_DOMAIN"
|
|
26
|
-
]
|
|
27
|
-
},
|
|
28
14
|
"uiHints": {
|
|
29
15
|
"provider": {
|
|
30
16
|
"label": "Provider",
|
|
@@ -219,7 +205,7 @@
|
|
|
219
205
|
},
|
|
220
206
|
"tts.provider": {
|
|
221
207
|
"label": "TTS Provider Override",
|
|
222
|
-
"help": "Deep-merges with
|
|
208
|
+
"help": "Deep-merges with top-level tts (Microsoft is ignored for calls).",
|
|
223
209
|
"advanced": true
|
|
224
210
|
},
|
|
225
211
|
"tts.providers": {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@openclaw/voice-call",
|
|
3
|
-
"version": "2026.7.2-beta.
|
|
3
|
+
"version": "2026.7.2-beta.5",
|
|
4
4
|
"description": "OpenClaw voice-call plugin for Twilio, Telnyx, and Plivo phone calls.",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -8,12 +8,12 @@
|
|
|
8
8
|
},
|
|
9
9
|
"type": "module",
|
|
10
10
|
"dependencies": {
|
|
11
|
-
"typebox": "1.3.
|
|
12
|
-
"ws": "8.21.
|
|
11
|
+
"typebox": "1.3.6",
|
|
12
|
+
"ws": "8.21.1",
|
|
13
13
|
"zod": "4.4.3"
|
|
14
14
|
},
|
|
15
15
|
"peerDependencies": {
|
|
16
|
-
"openclaw": ">=2026.7.2-beta.
|
|
16
|
+
"openclaw": ">=2026.7.2-beta.5"
|
|
17
17
|
},
|
|
18
18
|
"peerDependenciesMeta": {
|
|
19
19
|
"openclaw": {
|
|
@@ -30,10 +30,10 @@
|
|
|
30
30
|
"minHostVersion": ">=2026.4.10"
|
|
31
31
|
},
|
|
32
32
|
"compat": {
|
|
33
|
-
"pluginApi": ">=2026.7.2-beta.
|
|
33
|
+
"pluginApi": ">=2026.7.2-beta.5"
|
|
34
34
|
},
|
|
35
35
|
"build": {
|
|
36
|
-
"openclawVersion": "2026.7.2-beta.
|
|
36
|
+
"openclawVersion": "2026.7.2-beta.5"
|
|
37
37
|
},
|
|
38
38
|
"release": {
|
|
39
39
|
"publishToClawHub": true,
|
|
@@ -46,7 +46,6 @@
|
|
|
46
46
|
"files": [
|
|
47
47
|
"dist/**",
|
|
48
48
|
"openclaw.plugin.json",
|
|
49
|
-
"npm-shrinkwrap.json",
|
|
50
49
|
"README.md",
|
|
51
50
|
"skills/**"
|
|
52
51
|
],
|
package/npm-shrinkwrap.json
DELETED
|
@@ -1,61 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "@openclaw/voice-call",
|
|
3
|
-
"version": "2026.7.2-beta.3",
|
|
4
|
-
"lockfileVersion": 3,
|
|
5
|
-
"requires": true,
|
|
6
|
-
"packages": {
|
|
7
|
-
"": {
|
|
8
|
-
"name": "@openclaw/voice-call",
|
|
9
|
-
"version": "2026.7.2-beta.3",
|
|
10
|
-
"dependencies": {
|
|
11
|
-
"typebox": "1.3.3",
|
|
12
|
-
"ws": "8.21.0",
|
|
13
|
-
"zod": "4.4.3"
|
|
14
|
-
},
|
|
15
|
-
"peerDependencies": {
|
|
16
|
-
"openclaw": ">=2026.7.2-beta.3"
|
|
17
|
-
},
|
|
18
|
-
"peerDependenciesMeta": {
|
|
19
|
-
"openclaw": {
|
|
20
|
-
"optional": true
|
|
21
|
-
}
|
|
22
|
-
}
|
|
23
|
-
},
|
|
24
|
-
"node_modules/typebox": {
|
|
25
|
-
"version": "1.3.3",
|
|
26
|
-
"resolved": "https://registry.npmjs.org/typebox/-/typebox-1.3.3.tgz",
|
|
27
|
-
"integrity": "sha512-URXGUE31PJDQC+PtRMJeLdF4kmmOdFoVPikPCtV2oOIhUpNpppEdIz7W8bH8cFYPYHdDpaRvqwdegMTmHliudg==",
|
|
28
|
-
"license": "MIT"
|
|
29
|
-
},
|
|
30
|
-
"node_modules/ws": {
|
|
31
|
-
"version": "8.21.0",
|
|
32
|
-
"resolved": "https://registry.npmjs.org/ws/-/ws-8.21.0.tgz",
|
|
33
|
-
"integrity": "sha512-Vsp28b7DRcimFQvrqu2Wek3z1iYxDCWqHYB8Qsnk/S4RfaCQzPGPyBNuVjJV3cd6UiKtUtp6sNM77gWvzcCH+g==",
|
|
34
|
-
"license": "MIT",
|
|
35
|
-
"engines": {
|
|
36
|
-
"node": ">=10.0.0"
|
|
37
|
-
},
|
|
38
|
-
"peerDependencies": {
|
|
39
|
-
"bufferutil": "^4.0.1",
|
|
40
|
-
"utf-8-validate": ">=5.0.2"
|
|
41
|
-
},
|
|
42
|
-
"peerDependenciesMeta": {
|
|
43
|
-
"bufferutil": {
|
|
44
|
-
"optional": true
|
|
45
|
-
},
|
|
46
|
-
"utf-8-validate": {
|
|
47
|
-
"optional": true
|
|
48
|
-
}
|
|
49
|
-
}
|
|
50
|
-
},
|
|
51
|
-
"node_modules/zod": {
|
|
52
|
-
"version": "4.4.3",
|
|
53
|
-
"resolved": "https://registry.npmjs.org/zod/-/zod-4.4.3.tgz",
|
|
54
|
-
"integrity": "sha512-ytENFjIJFl2UwYglde2jchW2Hwm4GJFLDiSXWdTrJQBIN9Fcyp7n4DhxJEiWNAJMV1/BqWfW/kkg71UDcHJyTQ==",
|
|
55
|
-
"license": "MIT",
|
|
56
|
-
"funding": {
|
|
57
|
-
"url": "https://github.com/sponsors/colinhacks"
|
|
58
|
-
}
|
|
59
|
-
}
|
|
60
|
-
}
|
|
61
|
-
}
|