@elizaos/autonomous 2.0.0-alpha.10
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/package.json +270 -0
- package/src/actions/emote.ts +101 -0
- package/src/actions/restart.ts +101 -0
- package/src/actions/send-message.ts +168 -0
- package/src/actions/stream-control.ts +439 -0
- package/src/actions/switch-stream-source.ts +126 -0
- package/src/actions/terminal.ts +186 -0
- package/src/api/agent-admin-routes.ts +178 -0
- package/src/api/agent-lifecycle-routes.ts +129 -0
- package/src/api/agent-model.ts +143 -0
- package/src/api/agent-transfer-routes.ts +211 -0
- package/src/api/apps-routes.ts +210 -0
- package/src/api/auth-routes.ts +90 -0
- package/src/api/bsc-trade.ts +736 -0
- package/src/api/bug-report-routes.ts +161 -0
- package/src/api/character-routes.ts +421 -0
- package/src/api/cloud-billing-routes.ts +598 -0
- package/src/api/cloud-compat-routes.ts +192 -0
- package/src/api/cloud-routes.ts +529 -0
- package/src/api/cloud-status-routes.ts +234 -0
- package/src/api/compat-utils.ts +154 -0
- package/src/api/connector-health.ts +135 -0
- package/src/api/coordinator-wiring.ts +179 -0
- package/src/api/credit-detection.ts +47 -0
- package/src/api/database.ts +1357 -0
- package/src/api/diagnostics-routes.ts +389 -0
- package/src/api/drop-service.ts +205 -0
- package/src/api/early-logs.ts +111 -0
- package/src/api/http-helpers.ts +252 -0
- package/src/api/index.ts +85 -0
- package/src/api/knowledge-routes.ts +1189 -0
- package/src/api/knowledge-service-loader.ts +92 -0
- package/src/api/memory-bounds.ts +121 -0
- package/src/api/memory-routes.ts +349 -0
- package/src/api/merkle-tree.ts +239 -0
- package/src/api/models-routes.ts +72 -0
- package/src/api/nfa-routes.ts +169 -0
- package/src/api/nft-verify.ts +188 -0
- package/src/api/og-tracker.ts +72 -0
- package/src/api/parse-action-block.ts +145 -0
- package/src/api/permissions-routes.ts +222 -0
- package/src/api/plugin-validation.ts +355 -0
- package/src/api/provider-switch-config.ts +455 -0
- package/src/api/registry-routes.ts +165 -0
- package/src/api/registry-service.ts +292 -0
- package/src/api/route-helpers.ts +21 -0
- package/src/api/sandbox-routes.ts +1480 -0
- package/src/api/server.ts +17674 -0
- package/src/api/signal-routes.ts +265 -0
- package/src/api/stream-persistence.ts +297 -0
- package/src/api/stream-route-state.ts +48 -0
- package/src/api/stream-routes.ts +1046 -0
- package/src/api/stream-voice-routes.ts +208 -0
- package/src/api/streaming-text.ts +129 -0
- package/src/api/streaming-types.ts +23 -0
- package/src/api/subscription-routes.ts +283 -0
- package/src/api/terminal-run-limits.ts +31 -0
- package/src/api/training-backend-check.ts +40 -0
- package/src/api/training-routes.ts +314 -0
- package/src/api/training-service-like.ts +46 -0
- package/src/api/trajectory-routes.ts +714 -0
- package/src/api/trigger-routes.ts +438 -0
- package/src/api/twitter-verify.ts +226 -0
- package/src/api/tx-service.ts +193 -0
- package/src/api/wallet-dex-prices.ts +206 -0
- package/src/api/wallet-evm-balance.ts +989 -0
- package/src/api/wallet-routes.ts +505 -0
- package/src/api/wallet-rpc.ts +523 -0
- package/src/api/wallet-trading-profile.ts +694 -0
- package/src/api/wallet.ts +745 -0
- package/src/api/whatsapp-routes.ts +282 -0
- package/src/api/zip-utils.ts +130 -0
- package/src/auth/anthropic.ts +63 -0
- package/src/auth/apply-stealth.ts +38 -0
- package/src/auth/claude-code-stealth.ts +141 -0
- package/src/auth/credentials.ts +226 -0
- package/src/auth/index.ts +18 -0
- package/src/auth/openai-codex.ts +94 -0
- package/src/auth/types.ts +24 -0
- package/src/awareness/registry.ts +220 -0
- package/src/bin.ts +10 -0
- package/src/cli/index.ts +36 -0
- package/src/cli/parse-duration.ts +43 -0
- package/src/cloud/auth.test.ts +370 -0
- package/src/cloud/auth.ts +176 -0
- package/src/cloud/backup.test.ts +150 -0
- package/src/cloud/backup.ts +50 -0
- package/src/cloud/base-url.ts +45 -0
- package/src/cloud/bridge-client.test.ts +481 -0
- package/src/cloud/bridge-client.ts +307 -0
- package/src/cloud/cloud-manager.test.ts +223 -0
- package/src/cloud/cloud-manager.ts +151 -0
- package/src/cloud/cloud-proxy.test.ts +122 -0
- package/src/cloud/cloud-proxy.ts +52 -0
- package/src/cloud/index.ts +23 -0
- package/src/cloud/reconnect.test.ts +178 -0
- package/src/cloud/reconnect.ts +108 -0
- package/src/cloud/validate-url.test.ts +147 -0
- package/src/cloud/validate-url.ts +176 -0
- package/src/config/character-schema.ts +44 -0
- package/src/config/config.ts +149 -0
- package/src/config/env-vars.ts +86 -0
- package/src/config/includes.ts +196 -0
- package/src/config/index.ts +15 -0
- package/src/config/object-utils.ts +10 -0
- package/src/config/paths.ts +92 -0
- package/src/config/plugin-auto-enable.ts +520 -0
- package/src/config/schema.ts +1342 -0
- package/src/config/telegram-custom-commands.ts +99 -0
- package/src/config/types.agent-defaults.ts +342 -0
- package/src/config/types.agents.ts +112 -0
- package/src/config/types.gateway.ts +243 -0
- package/src/config/types.hooks.ts +124 -0
- package/src/config/types.messages.ts +201 -0
- package/src/config/types.milady.ts +791 -0
- package/src/config/types.tools.ts +416 -0
- package/src/config/types.ts +7 -0
- package/src/config/zod-schema.agent-runtime.ts +777 -0
- package/src/config/zod-schema.core.ts +778 -0
- package/src/config/zod-schema.hooks.ts +139 -0
- package/src/config/zod-schema.providers-core.ts +1126 -0
- package/src/config/zod-schema.session.ts +98 -0
- package/src/config/zod-schema.ts +865 -0
- package/src/contracts/apps.ts +46 -0
- package/src/contracts/awareness.ts +56 -0
- package/src/contracts/config.ts +172 -0
- package/src/contracts/drop.ts +21 -0
- package/src/contracts/index.ts +8 -0
- package/src/contracts/onboarding.ts +592 -0
- package/src/contracts/permissions.ts +52 -0
- package/src/contracts/verification.ts +9 -0
- package/src/contracts/wallet.ts +503 -0
- package/src/diagnostics/integration-observability.ts +132 -0
- package/src/emotes/catalog.ts +655 -0
- package/src/external-modules.d.ts +7 -0
- package/src/hooks/discovery.test.ts +357 -0
- package/src/hooks/discovery.ts +231 -0
- package/src/hooks/eligibility.ts +146 -0
- package/src/hooks/hooks.test.ts +320 -0
- package/src/hooks/index.ts +8 -0
- package/src/hooks/loader.test.ts +418 -0
- package/src/hooks/loader.ts +256 -0
- package/src/hooks/registry.test.ts +168 -0
- package/src/hooks/registry.ts +74 -0
- package/src/hooks/types.ts +121 -0
- package/src/index.ts +19 -0
- package/src/onboarding-presets.ts +828 -0
- package/src/plugins/custom-rtmp/index.ts +40 -0
- package/src/providers/admin-trust.ts +76 -0
- package/src/providers/session-bridge.ts +143 -0
- package/src/providers/session-utils.ts +42 -0
- package/src/providers/simple-mode.ts +113 -0
- package/src/providers/ui-catalog.ts +135 -0
- package/src/providers/workspace-provider.ts +213 -0
- package/src/providers/workspace.ts +497 -0
- package/src/runtime/agent-event-service.ts +57 -0
- package/src/runtime/cloud-onboarding.test.ts +489 -0
- package/src/runtime/cloud-onboarding.ts +408 -0
- package/src/runtime/core-plugins.ts +53 -0
- package/src/runtime/custom-actions.ts +605 -0
- package/src/runtime/eliza.ts +4941 -0
- package/src/runtime/embedding-presets.ts +73 -0
- package/src/runtime/index.ts +8 -0
- package/src/runtime/milady-plugin.ts +180 -0
- package/src/runtime/onboarding-names.ts +76 -0
- package/src/runtime/release-plugin-policy.ts +119 -0
- package/src/runtime/restart.ts +59 -0
- package/src/runtime/trajectory-persistence.ts +2584 -0
- package/src/runtime/version.ts +6 -0
- package/src/security/audit-log.ts +222 -0
- package/src/security/network-policy.ts +91 -0
- package/src/server/index.ts +6 -0
- package/src/services/agent-export.ts +976 -0
- package/src/services/app-manager.ts +755 -0
- package/src/services/browser-capture.ts +215 -0
- package/src/services/coding-agent-context.ts +355 -0
- package/src/services/fallback-training-service.ts +196 -0
- package/src/services/index.ts +17 -0
- package/src/services/mcp-marketplace.ts +327 -0
- package/src/services/plugin-manager-types.ts +185 -0
- package/src/services/privy-wallets.ts +352 -0
- package/src/services/registry-client-app-meta.ts +201 -0
- package/src/services/registry-client-endpoints.ts +253 -0
- package/src/services/registry-client-local.ts +485 -0
- package/src/services/registry-client-network.ts +173 -0
- package/src/services/registry-client-queries.ts +176 -0
- package/src/services/registry-client-types.ts +104 -0
- package/src/services/registry-client.ts +366 -0
- package/src/services/remote-signing-service.ts +261 -0
- package/src/services/sandbox-engine.ts +753 -0
- package/src/services/sandbox-manager.ts +503 -0
- package/src/services/self-updater.ts +213 -0
- package/src/services/signal-pairing.ts +189 -0
- package/src/services/signing-policy.ts +230 -0
- package/src/services/skill-catalog-client.ts +195 -0
- package/src/services/skill-marketplace.ts +909 -0
- package/src/services/stream-manager.ts +707 -0
- package/src/services/tts-stream-bridge.ts +465 -0
- package/src/services/update-checker.ts +163 -0
- package/src/services/version-compat.ts +367 -0
- package/src/services/whatsapp-pairing.ts +279 -0
- package/src/shared/ui-catalog-prompt.ts +1158 -0
- package/src/test-support/process-helpers.ts +35 -0
- package/src/test-support/route-test-helpers.ts +113 -0
- package/src/test-support/test-helpers.ts +304 -0
- package/src/testing/index.ts +3 -0
- package/src/triggers/action.ts +342 -0
- package/src/triggers/runtime.ts +432 -0
- package/src/triggers/scheduling.ts +472 -0
- package/src/triggers/types.ts +133 -0
- package/src/types/app-hyperscape-routes-shim.d.ts +29 -0
- package/src/types/external-modules.d.ts +7 -0
- package/src/utils/exec-safety.ts +23 -0
- package/src/utils/number-parsing.ts +112 -0
- package/src/utils/spoken-text.ts +65 -0
- package/src/version-resolver.ts +60 -0
- package/test/api/agent-admin-routes.test.ts +160 -0
- package/test/api/agent-lifecycle-routes.test.ts +164 -0
- package/test/api/agent-transfer-routes.test.ts +136 -0
- package/test/api/apps-routes.test.ts +140 -0
- package/test/api/auth-routes.test.ts +160 -0
- package/test/api/bug-report-routes.test.ts +88 -0
- package/test/api/knowledge-routes.test.ts +73 -0
- package/test/api/lifecycle.test.ts +342 -0
- package/test/api/memory-routes.test.ts +74 -0
- package/test/api/models-routes.test.ts +112 -0
- package/test/api/nfa-routes.test.ts +78 -0
- package/test/api/permissions-routes.test.ts +185 -0
- package/test/api/registry-routes.test.ts +157 -0
- package/test/api/signal-routes.test.ts +113 -0
- package/test/api/subscription-routes.test.ts +90 -0
- package/test/api/trigger-routes.test.ts +87 -0
- package/test/api/wallet-routes.observability.test.ts +191 -0
- package/test/api/wallet-routes.test.ts +502 -0
- package/test/diagnostics/integration-observability.test.ts +135 -0
- package/test/security/audit-log.test.ts +229 -0
- package/test/security/network-policy.test.ts +143 -0
- package/test/services/version-compat.test.ts +127 -0
- package/tsconfig.build.json +21 -0
- package/tsconfig.json +19 -0
|
@@ -0,0 +1,439 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Stream control actions — agents can go live, go offline, switch
|
|
3
|
+
* destinations, speak via TTS, and manage overlay widgets.
|
|
4
|
+
*
|
|
5
|
+
* All actions hit the local Milady API (127.0.0.1:API_PORT).
|
|
6
|
+
*
|
|
7
|
+
* @module actions/stream-control
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
import type { Action } from "@elizaos/core";
|
|
11
|
+
|
|
12
|
+
const API_PORT = process.env.API_PORT || process.env.SERVER_PORT || "2138";
|
|
13
|
+
const BASE = `http://127.0.0.1:${API_PORT}`;
|
|
14
|
+
|
|
15
|
+
async function apiPost(
|
|
16
|
+
path: string,
|
|
17
|
+
body?: unknown,
|
|
18
|
+
): Promise<{ ok: boolean; status: number; data: unknown }> {
|
|
19
|
+
const res = await fetch(`${BASE}${path}`, {
|
|
20
|
+
method: "POST",
|
|
21
|
+
headers: { "Content-Type": "application/json" },
|
|
22
|
+
body: body !== undefined ? JSON.stringify(body) : undefined,
|
|
23
|
+
signal: AbortSignal.timeout(10_000),
|
|
24
|
+
});
|
|
25
|
+
let data: unknown = null;
|
|
26
|
+
try {
|
|
27
|
+
data = await res.json();
|
|
28
|
+
} catch {
|
|
29
|
+
/* ignore */
|
|
30
|
+
}
|
|
31
|
+
return { ok: res.ok, status: res.status, data };
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
async function apiGet(
|
|
35
|
+
path: string,
|
|
36
|
+
): Promise<{ ok: boolean; status: number; data: unknown }> {
|
|
37
|
+
const res = await fetch(`${BASE}${path}`, {
|
|
38
|
+
signal: AbortSignal.timeout(10_000),
|
|
39
|
+
});
|
|
40
|
+
let data: unknown = null;
|
|
41
|
+
try {
|
|
42
|
+
data = await res.json();
|
|
43
|
+
} catch {
|
|
44
|
+
/* ignore */
|
|
45
|
+
}
|
|
46
|
+
return { ok: res.ok, status: res.status, data };
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
// ---------------------------------------------------------------------------
|
|
50
|
+
// GO_LIVE
|
|
51
|
+
// ---------------------------------------------------------------------------
|
|
52
|
+
|
|
53
|
+
export const goLiveAction: Action = {
|
|
54
|
+
name: "GO_LIVE",
|
|
55
|
+
similes: [
|
|
56
|
+
"START_STREAM",
|
|
57
|
+
"BEGIN_STREAM",
|
|
58
|
+
"START_BROADCASTING",
|
|
59
|
+
"GO_LIVE_NOW",
|
|
60
|
+
],
|
|
61
|
+
description:
|
|
62
|
+
"Start the live stream, broadcasting to the active destination (Twitch, YouTube, Retake.tv, etc.).",
|
|
63
|
+
validate: async () => true,
|
|
64
|
+
|
|
65
|
+
handler: async () => {
|
|
66
|
+
try {
|
|
67
|
+
const result = await apiPost("/api/stream/live");
|
|
68
|
+
if (!result.ok) {
|
|
69
|
+
const msg =
|
|
70
|
+
(result.data as Record<string, unknown>)?.error ??
|
|
71
|
+
`HTTP ${result.status}`;
|
|
72
|
+
return { text: `Failed to start stream: ${msg}`, success: false };
|
|
73
|
+
}
|
|
74
|
+
const data = result.data as Record<string, unknown>;
|
|
75
|
+
return {
|
|
76
|
+
text: data.live
|
|
77
|
+
? "Stream is now live! 🔴"
|
|
78
|
+
: "Stream start requested but may not be live yet — check status.",
|
|
79
|
+
success: true,
|
|
80
|
+
};
|
|
81
|
+
} catch (err) {
|
|
82
|
+
return {
|
|
83
|
+
text: `Failed to start stream: ${err instanceof Error ? err.message : String(err)}`,
|
|
84
|
+
success: false,
|
|
85
|
+
};
|
|
86
|
+
}
|
|
87
|
+
},
|
|
88
|
+
parameters: [],
|
|
89
|
+
};
|
|
90
|
+
|
|
91
|
+
// ---------------------------------------------------------------------------
|
|
92
|
+
// GO_OFFLINE
|
|
93
|
+
// ---------------------------------------------------------------------------
|
|
94
|
+
|
|
95
|
+
export const goOfflineAction: Action = {
|
|
96
|
+
name: "GO_OFFLINE",
|
|
97
|
+
similes: ["STOP_STREAM", "END_STREAM", "END_BROADCAST", "STOP_BROADCASTING"],
|
|
98
|
+
description: "Stop the live stream and go offline.",
|
|
99
|
+
validate: async () => true,
|
|
100
|
+
|
|
101
|
+
handler: async () => {
|
|
102
|
+
try {
|
|
103
|
+
const result = await apiPost("/api/stream/offline");
|
|
104
|
+
if (!result.ok) {
|
|
105
|
+
const msg =
|
|
106
|
+
(result.data as Record<string, unknown>)?.error ??
|
|
107
|
+
`HTTP ${result.status}`;
|
|
108
|
+
return { text: `Failed to stop stream: ${msg}`, success: false };
|
|
109
|
+
}
|
|
110
|
+
return { text: "Stream stopped. Now offline.", success: true };
|
|
111
|
+
} catch (err) {
|
|
112
|
+
return {
|
|
113
|
+
text: `Failed to stop stream: ${err instanceof Error ? err.message : String(err)}`,
|
|
114
|
+
success: false,
|
|
115
|
+
};
|
|
116
|
+
}
|
|
117
|
+
},
|
|
118
|
+
parameters: [],
|
|
119
|
+
};
|
|
120
|
+
|
|
121
|
+
// ---------------------------------------------------------------------------
|
|
122
|
+
// SET_STREAM_DESTINATION
|
|
123
|
+
// ---------------------------------------------------------------------------
|
|
124
|
+
|
|
125
|
+
export const setStreamDestinationAction: Action = {
|
|
126
|
+
name: "SET_STREAM_DESTINATION",
|
|
127
|
+
similes: [
|
|
128
|
+
"SWITCH_STREAM_DESTINATION",
|
|
129
|
+
"CHANGE_CHANNEL",
|
|
130
|
+
"SWITCH_CHANNEL",
|
|
131
|
+
"SELECT_DESTINATION",
|
|
132
|
+
],
|
|
133
|
+
description:
|
|
134
|
+
"Switch the active streaming destination (e.g. switch from Twitch to YouTube). " +
|
|
135
|
+
"The stream must be offline before switching.",
|
|
136
|
+
validate: async () => true,
|
|
137
|
+
|
|
138
|
+
handler: async (_runtime, _message, _state, options) => {
|
|
139
|
+
try {
|
|
140
|
+
const params = (
|
|
141
|
+
options as { parameters?: Record<string, unknown> } | undefined
|
|
142
|
+
)?.parameters;
|
|
143
|
+
const destinationId =
|
|
144
|
+
typeof params?.destinationId === "string"
|
|
145
|
+
? params.destinationId.trim()
|
|
146
|
+
: "";
|
|
147
|
+
const destinationName =
|
|
148
|
+
typeof params?.destinationName === "string"
|
|
149
|
+
? params.destinationName.trim()
|
|
150
|
+
: "";
|
|
151
|
+
|
|
152
|
+
if (!destinationId && !destinationName) {
|
|
153
|
+
// List available destinations so the agent can choose
|
|
154
|
+
const listResult = await apiGet("/api/streaming/destinations");
|
|
155
|
+
if (!listResult.ok) {
|
|
156
|
+
return {
|
|
157
|
+
text: "Could not fetch destinations. API may be unavailable.",
|
|
158
|
+
success: false,
|
|
159
|
+
};
|
|
160
|
+
}
|
|
161
|
+
const data = listResult.data as Record<string, unknown>;
|
|
162
|
+
const dests = (data.destinations ?? []) as Array<{
|
|
163
|
+
id: string;
|
|
164
|
+
name: string;
|
|
165
|
+
}>;
|
|
166
|
+
if (dests.length === 0) {
|
|
167
|
+
return {
|
|
168
|
+
text: "No streaming destinations configured. Install a streaming plugin first.",
|
|
169
|
+
success: false,
|
|
170
|
+
};
|
|
171
|
+
}
|
|
172
|
+
const list = dests.map((d) => `- ${d.name} (id: ${d.id})`).join("\n");
|
|
173
|
+
return {
|
|
174
|
+
text: `Available destinations:\n${list}\n\nCall again with destinationId set.`,
|
|
175
|
+
success: false,
|
|
176
|
+
};
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
// Resolve by id or name
|
|
180
|
+
const listResult = await apiGet("/api/streaming/destinations");
|
|
181
|
+
const dests = (
|
|
182
|
+
listResult.ok
|
|
183
|
+
? ((listResult.data as Record<string, unknown>).destinations ?? [])
|
|
184
|
+
: []
|
|
185
|
+
) as Array<{ id: string; name: string }>;
|
|
186
|
+
|
|
187
|
+
const target =
|
|
188
|
+
dests.find((d) => d.id === destinationId) ??
|
|
189
|
+
dests.find(
|
|
190
|
+
(d) => d.name.toLowerCase() === destinationName.toLowerCase(),
|
|
191
|
+
);
|
|
192
|
+
|
|
193
|
+
if (!target) {
|
|
194
|
+
const names = dests.map((d) => d.name).join(", ") || "none";
|
|
195
|
+
return {
|
|
196
|
+
text: `Destination "${destinationId || destinationName}" not found. Available: ${names}`,
|
|
197
|
+
success: false,
|
|
198
|
+
};
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
const result = await apiPost("/api/streaming/destination", {
|
|
202
|
+
destinationId: target.id,
|
|
203
|
+
});
|
|
204
|
+
if (!result.ok) {
|
|
205
|
+
const msg =
|
|
206
|
+
(result.data as Record<string, unknown>)?.error ??
|
|
207
|
+
`HTTP ${result.status}`;
|
|
208
|
+
return { text: `Failed to switch destination: ${msg}`, success: false };
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
return {
|
|
212
|
+
text: `Switched streaming destination to ${target.name}.`,
|
|
213
|
+
success: true,
|
|
214
|
+
};
|
|
215
|
+
} catch (err) {
|
|
216
|
+
return {
|
|
217
|
+
text: `Failed to switch destination: ${err instanceof Error ? err.message : String(err)}`,
|
|
218
|
+
success: false,
|
|
219
|
+
};
|
|
220
|
+
}
|
|
221
|
+
},
|
|
222
|
+
|
|
223
|
+
parameters: [
|
|
224
|
+
{
|
|
225
|
+
name: "destinationId",
|
|
226
|
+
description:
|
|
227
|
+
"The destination ID (from /api/streaming/destinations). Use this or destinationName.",
|
|
228
|
+
required: false,
|
|
229
|
+
schema: { type: "string" as const },
|
|
230
|
+
},
|
|
231
|
+
{
|
|
232
|
+
name: "destinationName",
|
|
233
|
+
description:
|
|
234
|
+
'The destination name (e.g. "Twitch", "YouTube"). Case-insensitive.',
|
|
235
|
+
required: false,
|
|
236
|
+
schema: { type: "string" as const },
|
|
237
|
+
},
|
|
238
|
+
],
|
|
239
|
+
};
|
|
240
|
+
|
|
241
|
+
// ---------------------------------------------------------------------------
|
|
242
|
+
// SPEAK_ON_STREAM
|
|
243
|
+
// ---------------------------------------------------------------------------
|
|
244
|
+
|
|
245
|
+
export const speakOnStreamAction: Action = {
|
|
246
|
+
name: "SPEAK_ON_STREAM",
|
|
247
|
+
similes: ["SAY_ON_STREAM", "TTS_SPEAK", "READ_ALOUD", "STREAM_VOICE"],
|
|
248
|
+
description:
|
|
249
|
+
"Speak a message aloud on the stream using text-to-speech (TTS). " +
|
|
250
|
+
"The stream voice must be enabled in settings.",
|
|
251
|
+
validate: async () => true,
|
|
252
|
+
|
|
253
|
+
handler: async (_runtime, _message, _state, options) => {
|
|
254
|
+
try {
|
|
255
|
+
const params = (
|
|
256
|
+
options as { parameters?: Record<string, unknown> } | undefined
|
|
257
|
+
)?.parameters;
|
|
258
|
+
const text = typeof params?.text === "string" ? params.text.trim() : "";
|
|
259
|
+
|
|
260
|
+
if (!text) {
|
|
261
|
+
return {
|
|
262
|
+
text: "text parameter is required for SPEAK_ON_STREAM.",
|
|
263
|
+
success: false,
|
|
264
|
+
};
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
const result = await apiPost("/api/stream/voice/speak", { text });
|
|
268
|
+
if (!result.ok) {
|
|
269
|
+
const msg =
|
|
270
|
+
(result.data as Record<string, unknown>)?.error ??
|
|
271
|
+
`HTTP ${result.status}`;
|
|
272
|
+
return { text: `Failed to speak on stream: ${msg}`, success: false };
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
return { text: `Speaking on stream: "${text}"`, success: true };
|
|
276
|
+
} catch (err) {
|
|
277
|
+
return {
|
|
278
|
+
text: `Failed to speak: ${err instanceof Error ? err.message : String(err)}`,
|
|
279
|
+
success: false,
|
|
280
|
+
};
|
|
281
|
+
}
|
|
282
|
+
},
|
|
283
|
+
|
|
284
|
+
parameters: [
|
|
285
|
+
{
|
|
286
|
+
name: "text",
|
|
287
|
+
description: "The text to speak aloud on the stream.",
|
|
288
|
+
required: true,
|
|
289
|
+
schema: { type: "string" as const },
|
|
290
|
+
},
|
|
291
|
+
],
|
|
292
|
+
};
|
|
293
|
+
|
|
294
|
+
// ---------------------------------------------------------------------------
|
|
295
|
+
// MANAGE_OVERLAY_WIDGET
|
|
296
|
+
// ---------------------------------------------------------------------------
|
|
297
|
+
|
|
298
|
+
export const manageOverlayWidgetAction: Action = {
|
|
299
|
+
name: "MANAGE_OVERLAY_WIDGET",
|
|
300
|
+
similes: [
|
|
301
|
+
"TOGGLE_WIDGET",
|
|
302
|
+
"ENABLE_WIDGET",
|
|
303
|
+
"DISABLE_WIDGET",
|
|
304
|
+
"SHOW_OVERLAY",
|
|
305
|
+
"HIDE_OVERLAY",
|
|
306
|
+
],
|
|
307
|
+
description:
|
|
308
|
+
"Enable or disable a stream overlay widget (e.g. viewer count, alert popup, thought bubble, branding). " +
|
|
309
|
+
'Provide widgetType and action ("enable" or "disable"). Optionally provide destinationId for per-destination layouts.',
|
|
310
|
+
validate: async () => true,
|
|
311
|
+
|
|
312
|
+
handler: async (_runtime, _message, _state, options) => {
|
|
313
|
+
try {
|
|
314
|
+
const params = (
|
|
315
|
+
options as { parameters?: Record<string, unknown> } | undefined
|
|
316
|
+
)?.parameters;
|
|
317
|
+
const widgetType =
|
|
318
|
+
typeof params?.widgetType === "string" ? params.widgetType.trim() : "";
|
|
319
|
+
const action =
|
|
320
|
+
typeof params?.action === "string"
|
|
321
|
+
? params.action.trim().toLowerCase()
|
|
322
|
+
: "enable";
|
|
323
|
+
const destinationId =
|
|
324
|
+
typeof params?.destinationId === "string"
|
|
325
|
+
? params.destinationId.trim()
|
|
326
|
+
: undefined;
|
|
327
|
+
|
|
328
|
+
if (!widgetType) {
|
|
329
|
+
return {
|
|
330
|
+
text: "widgetType is required. Available types: viewer-count, alert-popup, action-ticker, thought-bubble, branding, custom-html, peon-hud, peon-glass, peon-sakura.",
|
|
331
|
+
success: false,
|
|
332
|
+
};
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
if (action !== "enable" && action !== "disable") {
|
|
336
|
+
return {
|
|
337
|
+
text: 'action must be "enable" or "disable".',
|
|
338
|
+
success: false,
|
|
339
|
+
};
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
// Fetch current layout
|
|
343
|
+
const qs = destinationId
|
|
344
|
+
? `?destination=${encodeURIComponent(destinationId)}`
|
|
345
|
+
: "";
|
|
346
|
+
const getResult = await apiGet(`/api/stream/overlay-layout${qs}`);
|
|
347
|
+
if (!getResult.ok) {
|
|
348
|
+
return {
|
|
349
|
+
text: `Could not fetch overlay layout: HTTP ${getResult.status}`,
|
|
350
|
+
success: false,
|
|
351
|
+
};
|
|
352
|
+
}
|
|
353
|
+
|
|
354
|
+
const data = getResult.data as Record<string, unknown>;
|
|
355
|
+
const layout = data.layout as {
|
|
356
|
+
version: 1;
|
|
357
|
+
name: string;
|
|
358
|
+
widgets: Array<{
|
|
359
|
+
id: string;
|
|
360
|
+
type: string;
|
|
361
|
+
enabled: boolean;
|
|
362
|
+
[k: string]: unknown;
|
|
363
|
+
}>;
|
|
364
|
+
};
|
|
365
|
+
|
|
366
|
+
if (!layout || !Array.isArray(layout.widgets)) {
|
|
367
|
+
return { text: "Could not parse overlay layout.", success: false };
|
|
368
|
+
}
|
|
369
|
+
|
|
370
|
+
const widget = layout.widgets.find((w) => w.type === widgetType);
|
|
371
|
+
if (!widget) {
|
|
372
|
+
const types = layout.widgets.map((w) => w.type).join(", ");
|
|
373
|
+
return {
|
|
374
|
+
text: `Widget type "${widgetType}" not found. Available: ${types}`,
|
|
375
|
+
success: false,
|
|
376
|
+
};
|
|
377
|
+
}
|
|
378
|
+
|
|
379
|
+
const enable = action === "enable";
|
|
380
|
+
if (widget.enabled === enable) {
|
|
381
|
+
return {
|
|
382
|
+
text: `Widget "${widgetType}" is already ${enable ? "enabled" : "disabled"}.`,
|
|
383
|
+
success: true,
|
|
384
|
+
};
|
|
385
|
+
}
|
|
386
|
+
|
|
387
|
+
// Mutate and save
|
|
388
|
+
const updated = {
|
|
389
|
+
...layout,
|
|
390
|
+
widgets: layout.widgets.map((w) =>
|
|
391
|
+
w.type === widgetType ? { ...w, enabled: enable } : w,
|
|
392
|
+
),
|
|
393
|
+
};
|
|
394
|
+
|
|
395
|
+
const saveResult = await apiPost(`/api/stream/overlay-layout${qs}`, {
|
|
396
|
+
layout: updated,
|
|
397
|
+
});
|
|
398
|
+
if (!saveResult.ok) {
|
|
399
|
+
return {
|
|
400
|
+
text: `Failed to save overlay layout: HTTP ${saveResult.status}`,
|
|
401
|
+
success: false,
|
|
402
|
+
};
|
|
403
|
+
}
|
|
404
|
+
|
|
405
|
+
return {
|
|
406
|
+
text: `Widget "${widgetType}" ${enable ? "enabled" : "disabled"} on stream overlay.`,
|
|
407
|
+
success: true,
|
|
408
|
+
};
|
|
409
|
+
} catch (err) {
|
|
410
|
+
return {
|
|
411
|
+
text: `Failed to manage widget: ${err instanceof Error ? err.message : String(err)}`,
|
|
412
|
+
success: false,
|
|
413
|
+
};
|
|
414
|
+
}
|
|
415
|
+
},
|
|
416
|
+
|
|
417
|
+
parameters: [
|
|
418
|
+
{
|
|
419
|
+
name: "widgetType",
|
|
420
|
+
description:
|
|
421
|
+
"Widget type to manage: viewer-count, alert-popup, action-ticker, thought-bubble, branding, custom-html, peon-hud, peon-glass, peon-sakura.",
|
|
422
|
+
required: true,
|
|
423
|
+
schema: { type: "string" as const },
|
|
424
|
+
},
|
|
425
|
+
{
|
|
426
|
+
name: "action",
|
|
427
|
+
description: '"enable" or "disable".',
|
|
428
|
+
required: true,
|
|
429
|
+
schema: { type: "string" as const },
|
|
430
|
+
},
|
|
431
|
+
{
|
|
432
|
+
name: "destinationId",
|
|
433
|
+
description:
|
|
434
|
+
"Optional destination ID for per-destination overlay layouts.",
|
|
435
|
+
required: false,
|
|
436
|
+
schema: { type: "string" as const },
|
|
437
|
+
},
|
|
438
|
+
],
|
|
439
|
+
};
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SWITCH_STREAM_SOURCE action — changes the content being captured and streamed.
|
|
3
|
+
*
|
|
4
|
+
* When triggered the action:
|
|
5
|
+
* 1. Validates the requested sourceType against the allowed set
|
|
6
|
+
* 2. Requires customUrl when sourceType is "custom-url"
|
|
7
|
+
* 3. POSTs to the local API to apply the new stream source
|
|
8
|
+
*
|
|
9
|
+
* All stream-switching logic is handled server-side — this action is a
|
|
10
|
+
* thin wrapper that validates inputs and forwards the request.
|
|
11
|
+
*
|
|
12
|
+
* @module actions/switch-stream-source
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
import type { Action, HandlerOptions } from "@elizaos/core";
|
|
16
|
+
|
|
17
|
+
/** API port for the stream source endpoint. */
|
|
18
|
+
const API_PORT = process.env.API_PORT || process.env.SERVER_PORT || "2138";
|
|
19
|
+
|
|
20
|
+
const VALID_SOURCE_TYPES = ["stream-tab", "game", "custom-url"] as const;
|
|
21
|
+
type ValidSourceType = (typeof VALID_SOURCE_TYPES)[number];
|
|
22
|
+
|
|
23
|
+
export const switchStreamSourceAction: Action = {
|
|
24
|
+
name: "SWITCH_STREAM_SOURCE",
|
|
25
|
+
|
|
26
|
+
similes: ["CHANGE_STREAM", "STREAM_GAME", "STREAM_URL", "SET_STREAM_SOURCE"],
|
|
27
|
+
|
|
28
|
+
description:
|
|
29
|
+
"Switches what content is being captured and streamed. " +
|
|
30
|
+
'Use "stream-tab" to capture the stream browser tab, "game" to capture a game window, ' +
|
|
31
|
+
'or "custom-url" to stream from a specific URL.',
|
|
32
|
+
|
|
33
|
+
validate: async () => true,
|
|
34
|
+
|
|
35
|
+
handler: async (_runtime, _message, _state, options) => {
|
|
36
|
+
try {
|
|
37
|
+
const params = (options as HandlerOptions | undefined)?.parameters;
|
|
38
|
+
|
|
39
|
+
// ── Extract parameters ───────────────────────────────────────────
|
|
40
|
+
const rawSourceType =
|
|
41
|
+
typeof params?.sourceType === "string"
|
|
42
|
+
? params.sourceType.trim()
|
|
43
|
+
: "stream-tab";
|
|
44
|
+
|
|
45
|
+
const sourceType: ValidSourceType = VALID_SOURCE_TYPES.includes(
|
|
46
|
+
rawSourceType as ValidSourceType,
|
|
47
|
+
)
|
|
48
|
+
? (rawSourceType as ValidSourceType)
|
|
49
|
+
: "stream-tab";
|
|
50
|
+
|
|
51
|
+
if (
|
|
52
|
+
!VALID_SOURCE_TYPES.includes(rawSourceType as ValidSourceType) &&
|
|
53
|
+
rawSourceType !== ""
|
|
54
|
+
) {
|
|
55
|
+
return {
|
|
56
|
+
text: `Invalid sourceType "${rawSourceType}". Must be one of: ${VALID_SOURCE_TYPES.join(", ")}.`,
|
|
57
|
+
success: false,
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
const customUrl =
|
|
62
|
+
typeof params?.customUrl === "string"
|
|
63
|
+
? params.customUrl.trim()
|
|
64
|
+
: undefined;
|
|
65
|
+
|
|
66
|
+
// ── Validate custom-url requirement ─────────────────────────────
|
|
67
|
+
if (sourceType === "custom-url" && !customUrl) {
|
|
68
|
+
return {
|
|
69
|
+
text: 'customUrl is required when sourceType is "custom-url".',
|
|
70
|
+
success: false,
|
|
71
|
+
};
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
// ── POST to stream source API ───────────────────────────────────
|
|
75
|
+
const response = await fetch(
|
|
76
|
+
`http://127.0.0.1:${API_PORT}/api/stream/source`,
|
|
77
|
+
{
|
|
78
|
+
method: "POST",
|
|
79
|
+
headers: { "Content-Type": "application/json" },
|
|
80
|
+
body: JSON.stringify({ sourceType, customUrl }),
|
|
81
|
+
signal: AbortSignal.timeout(10_000),
|
|
82
|
+
},
|
|
83
|
+
);
|
|
84
|
+
|
|
85
|
+
if (!response.ok) {
|
|
86
|
+
return {
|
|
87
|
+
text: `Failed to switch stream source (HTTP ${response.status}).`,
|
|
88
|
+
success: false,
|
|
89
|
+
};
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
// ── Format and return ────────────────────────────────────────────
|
|
93
|
+
const label =
|
|
94
|
+
sourceType === "custom-url"
|
|
95
|
+
? `${sourceType} (${customUrl})`
|
|
96
|
+
: sourceType;
|
|
97
|
+
|
|
98
|
+
return {
|
|
99
|
+
text: `Switched stream source to ${label}.`,
|
|
100
|
+
success: true,
|
|
101
|
+
};
|
|
102
|
+
} catch (err) {
|
|
103
|
+
return {
|
|
104
|
+
text: `Failed to switch stream source: ${err instanceof Error ? err.message : String(err)}`,
|
|
105
|
+
success: false,
|
|
106
|
+
};
|
|
107
|
+
}
|
|
108
|
+
},
|
|
109
|
+
|
|
110
|
+
parameters: [
|
|
111
|
+
{
|
|
112
|
+
name: "sourceType",
|
|
113
|
+
description:
|
|
114
|
+
'The stream source type to switch to: "stream-tab", "game", or "custom-url".',
|
|
115
|
+
required: true,
|
|
116
|
+
schema: { type: "string" as const },
|
|
117
|
+
},
|
|
118
|
+
{
|
|
119
|
+
name: "customUrl",
|
|
120
|
+
description:
|
|
121
|
+
'The URL to stream from. Required when sourceType is "custom-url".',
|
|
122
|
+
required: false,
|
|
123
|
+
schema: { type: "string" as const },
|
|
124
|
+
},
|
|
125
|
+
],
|
|
126
|
+
};
|