@tokagent/tokagentos 2.0.29 → 2.0.30

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.
@@ -0,0 +1,2755 @@
1
+ /**
2
+ * Agent domain methods — lifecycle, auth, config, connectors, triggers,
3
+ * training, plugins, streaming/PTY, logs, character, permissions, updates.
4
+ */
5
+
6
+ import type {
7
+ AllPermissionsState,
8
+ OnboardingConnectorConfig as ConnectorConfig,
9
+ LinkedAccountConfig,
10
+ LinkedAccountProviderId,
11
+ OnboardingOptions,
12
+ PermissionState,
13
+ ServiceRouteAccountStrategy,
14
+ SubscriptionStatusResponse,
15
+ SystemPermissionId,
16
+ } from "@elizaos/shared";
17
+ import {
18
+ isElizaSettingsDebugEnabled,
19
+ sanitizeForSettingsDebug,
20
+ settingsDebugCloudSummary,
21
+ } from "@elizaos/shared";
22
+ import {
23
+ type AppBlockerInstalledApp,
24
+ type AppBlockerPermissionResult,
25
+ type AppBlockerStatusResult,
26
+ getAppBlockerPlugin,
27
+ getWebsiteBlockerPlugin,
28
+ type WebsiteBlockerPermissionResult,
29
+ type WebsiteBlockerStatusResult,
30
+ } from "../bridge/native-plugins";
31
+ import { TERMINAL_STATUSES } from "../chat/coding-agent-session-state";
32
+ import { ElizaClient } from "./client-base";
33
+ import type {
34
+ AgentAutomationMode,
35
+ AgentAutomationModeResponse,
36
+ AgentEventsResponse,
37
+ AgentSelfStatusSnapshot,
38
+ AgentStatus,
39
+ CharacterData,
40
+ CharacterHistoryResponse,
41
+ CodingAgentScratchWorkspace,
42
+ CodingAgentStatus,
43
+ CodingAgentTaskThread,
44
+ CodingAgentTaskThreadDetail,
45
+ ConfigSchemaResponse,
46
+ CorePluginsResponse,
47
+ CreateTriggerRequest,
48
+ ExperienceListQuery,
49
+ ExperienceListResponse,
50
+ ExperienceRecord,
51
+ ExperienceUpdateInput,
52
+ ExtensionStatus,
53
+ LogsFilter,
54
+ LogsResponse,
55
+ PluginInfo,
56
+ PluginMutationResult,
57
+ ProviderModelRecord,
58
+ RawPtySession,
59
+ RelationshipsActivityResponse,
60
+ RelationshipsGraphQuery,
61
+ RelationshipsGraphSnapshot,
62
+ RelationshipsGraphStats,
63
+ RelationshipsMergeCandidate,
64
+ RelationshipsPersonDetail,
65
+ RelationshipsPersonSummary,
66
+ RuntimeDebugSnapshot,
67
+ SecretInfo,
68
+ SecurityAuditFilter,
69
+ SecurityAuditResponse,
70
+ SecurityAuditStreamEvent,
71
+ StartTrainingOptions,
72
+ TradePermissionMode,
73
+ TradePermissionModeResponse,
74
+ TrainingDatasetRecord,
75
+ TrainingJobRecord,
76
+ TrainingModelRecord,
77
+ TrainingStatus,
78
+ TrainingTrajectoryDetail,
79
+ TrainingTrajectoryList,
80
+ TriggerEventDispatchResponse,
81
+ TriggerHealthSnapshot,
82
+ TriggerLastStatus,
83
+ TriggerRunRecord,
84
+ TriggerSummary,
85
+ UpdateStatus,
86
+ UpdateTriggerRequest,
87
+ } from "./client-types";
88
+ import {
89
+ mapPtySessionsToCodingAgentSessions,
90
+ mapTaskThreadsToCodingAgentSessions,
91
+ } from "./client-types";
92
+
93
+ // ---------------------------------------------------------------------------
94
+ // Module-level helpers
95
+ // ---------------------------------------------------------------------------
96
+
97
+ function clientSettingsDebug(): boolean {
98
+ let viteEnv: Record<string, unknown> | undefined;
99
+ try {
100
+ viteEnv = import.meta.env as Record<string, unknown>;
101
+ } catch {
102
+ viteEnv = undefined;
103
+ }
104
+ return isElizaSettingsDebugEnabled({
105
+ importMetaEnv: viteEnv,
106
+ env: typeof process !== "undefined" ? process.env : undefined,
107
+ });
108
+ }
109
+
110
+ const WEBSITE_BLOCKING_PERMISSION_ID = "website-blocking" as const;
111
+
112
+ function getNativeWebsiteBlockerPluginIfAvailable() {
113
+ const plugin = getWebsiteBlockerPlugin();
114
+ return typeof plugin.getStatus === "function" &&
115
+ typeof plugin.startBlock === "function" &&
116
+ typeof plugin.stopBlock === "function" &&
117
+ typeof plugin.checkPermissions === "function" &&
118
+ typeof plugin.requestPermissions === "function" &&
119
+ typeof plugin.openSettings === "function"
120
+ ? plugin
121
+ : null;
122
+ }
123
+
124
+ function getNativeAppBlockerPluginIfAvailable() {
125
+ const plugin = getAppBlockerPlugin();
126
+ return typeof plugin.getStatus === "function" &&
127
+ typeof plugin.checkPermissions === "function" &&
128
+ typeof plugin.requestPermissions === "function" &&
129
+ typeof plugin.getInstalledApps === "function" &&
130
+ typeof plugin.selectApps === "function" &&
131
+ typeof plugin.blockApps === "function" &&
132
+ typeof plugin.unblockApps === "function"
133
+ ? plugin
134
+ : null;
135
+ }
136
+
137
+ function mapWebsiteBlockerPermissionResult(
138
+ permission: WebsiteBlockerPermissionResult,
139
+ ): PermissionState {
140
+ return {
141
+ id: WEBSITE_BLOCKING_PERMISSION_ID,
142
+ status: permission.status,
143
+ canRequest: permission.canRequest,
144
+ reason: permission.reason,
145
+ lastChecked: Date.now(),
146
+ };
147
+ }
148
+
149
+ function mapWebsiteBlockerStatusToPermission(
150
+ status: WebsiteBlockerStatusResult,
151
+ ): PermissionState {
152
+ return {
153
+ id: WEBSITE_BLOCKING_PERMISSION_ID,
154
+ status:
155
+ status.permissionStatus ??
156
+ (status.available ? "granted" : "not-determined"),
157
+ canRequest: status.canRequestPermission ?? status.supportsElevationPrompt,
158
+ reason: status.reason,
159
+ lastChecked: Date.now(),
160
+ };
161
+ }
162
+
163
+ function logSettingsClient(
164
+ phase: string,
165
+ detail: Record<string, unknown>,
166
+ ): void {
167
+ if (!clientSettingsDebug()) return;
168
+ console.debug(
169
+ `[eliza][settings][client] ${phase}`,
170
+ sanitizeForSettingsDebug(detail),
171
+ );
172
+ }
173
+
174
+ const SETTINGS_MUTATION_TIMEOUT_MS = 30_000;
175
+
176
+ // ---------------------------------------------------------------------------
177
+ // Bootstrap exchange types
178
+ // ---------------------------------------------------------------------------
179
+
180
+ /** Successful response from POST /api/auth/bootstrap/exchange. */
181
+ export interface BootstrapExchangeSuccess {
182
+ ok: true;
183
+ sessionId: string;
184
+ expiresAt: number;
185
+ identityId: string;
186
+ }
187
+
188
+ /** Failure response from POST /api/auth/bootstrap/exchange. */
189
+ export interface BootstrapExchangeFailure {
190
+ ok: false;
191
+ status: 400 | 401 | 429 | 503;
192
+ error: string;
193
+ reason?: string;
194
+ }
195
+
196
+ export type BootstrapExchangeResult =
197
+ | BootstrapExchangeSuccess
198
+ | BootstrapExchangeFailure;
199
+
200
+ // ---------------------------------------------------------------------------
201
+ // Multi-account routes (WS3) — surfaced under `/api/accounts/*` and the
202
+ // per-provider `/api/providers/:providerId/strategy` endpoint. The on-disk
203
+ // `LinkedAccountConfig` records are joined with a `hasCredential` flag so
204
+ // the UI can spot orphan metadata.
205
+ // ---------------------------------------------------------------------------
206
+
207
+ export type AccountStrategy = ServiceRouteAccountStrategy;
208
+
209
+ export interface AccountWithCredentialFlag extends LinkedAccountConfig {
210
+ hasCredential: boolean;
211
+ }
212
+
213
+ export interface AccountsListProvider {
214
+ providerId: LinkedAccountProviderId;
215
+ strategy: AccountStrategy;
216
+ accounts: AccountWithCredentialFlag[];
217
+ }
218
+
219
+ export interface AccountsListResponse {
220
+ providers: AccountsListProvider[];
221
+ }
222
+
223
+ export interface AccountTestResult {
224
+ ok: boolean;
225
+ latencyMs?: number;
226
+ status?: number;
227
+ error?: string;
228
+ }
229
+
230
+ export interface AccountRefreshUsageResult {
231
+ account: LinkedAccountConfig;
232
+ source: "pool" | "inline-probe";
233
+ }
234
+
235
+ export interface AccountOAuthStartResult {
236
+ sessionId: string;
237
+ authUrl: string;
238
+ needsCodeSubmission: boolean;
239
+ }
240
+
241
+ // ---------------------------------------------------------------------------
242
+ // Declaration merging
243
+ // ---------------------------------------------------------------------------
244
+
245
+ declare module "./client-base" {
246
+ interface ElizaClient {
247
+ getStatus(): Promise<AgentStatus>;
248
+ getAgentSelfStatus(): Promise<AgentSelfStatusSnapshot>;
249
+ getRuntimeSnapshot(opts?: {
250
+ depth?: number;
251
+ maxArrayLength?: number;
252
+ maxObjectEntries?: number;
253
+ maxStringLength?: number;
254
+ }): Promise<RuntimeDebugSnapshot>;
255
+ setAutomationMode(
256
+ mode: "connectors-only" | "full",
257
+ ): Promise<{ mode: string }>;
258
+ setTradeMode(
259
+ mode: string,
260
+ ): Promise<{ ok: boolean; tradePermissionMode: string }>;
261
+ playEmote(emoteId: string): Promise<{ ok: boolean }>;
262
+ runTerminalCommand(command: string): Promise<{ ok: boolean }>;
263
+ getOnboardingStatus(): Promise<{
264
+ complete: boolean;
265
+ cloudProvisioned?: boolean;
266
+ }>;
267
+ getWalletKeys(): Promise<{
268
+ evmPrivateKey: string;
269
+ evmAddress: string;
270
+ solanaPrivateKey: string;
271
+ solanaAddress: string;
272
+ }>;
273
+ getWalletOsStoreStatus(): Promise<{
274
+ backend: string;
275
+ available: boolean;
276
+ readEnabled: boolean;
277
+ vaultId: string;
278
+ }>;
279
+ postWalletOsStoreAction(action: "migrate" | "delete"): Promise<{
280
+ ok: boolean;
281
+ migrated?: string[];
282
+ failed?: string[];
283
+ error?: string;
284
+ }>;
285
+ getAuthStatus(): Promise<{
286
+ required: boolean;
287
+ loginRequired?: boolean;
288
+ bootstrapRequired?: boolean;
289
+ localAccess?: boolean;
290
+ passwordConfigured?: boolean;
291
+ pairingEnabled: boolean;
292
+ expiresAt: number | null;
293
+ }>;
294
+ postBootstrapExchange(token: string): Promise<BootstrapExchangeResult>;
295
+ pair(code: string): Promise<{ token: string }>;
296
+ getOnboardingOptions(): Promise<OnboardingOptions>;
297
+ submitOnboarding(data: Record<string, unknown>): Promise<void>;
298
+ startAnthropicLogin(): Promise<{ authUrl: string }>;
299
+ exchangeAnthropicCode(code: string): Promise<{
300
+ success: boolean;
301
+ expiresAt?: string;
302
+ error?: string;
303
+ }>;
304
+ submitAnthropicSetupToken(token: string): Promise<{ success: boolean }>;
305
+ getSubscriptionStatus(): Promise<SubscriptionStatusResponse>;
306
+ deleteSubscription(provider: string): Promise<{ success: boolean }>;
307
+ switchProvider(
308
+ provider: string,
309
+ apiKey?: string,
310
+ primaryModel?: string,
311
+ ): Promise<{ success: boolean; provider: string; restarting: boolean }>;
312
+ startOpenAILogin(): Promise<{
313
+ authUrl: string;
314
+ state: string;
315
+ instructions: string;
316
+ }>;
317
+ exchangeOpenAICode(code: string): Promise<{
318
+ success: boolean;
319
+ expiresAt?: string;
320
+ accountId?: string;
321
+ error?: string;
322
+ }>;
323
+ startAgent(): Promise<AgentStatus>;
324
+ startAndWait(maxWaitMs?: number): Promise<AgentStatus>;
325
+ stopAgent(): Promise<AgentStatus>;
326
+ pauseAgent(): Promise<AgentStatus>;
327
+ resumeAgent(): Promise<AgentStatus>;
328
+ restartAgent(): Promise<AgentStatus>;
329
+ restartAndWait(maxWaitMs?: number): Promise<AgentStatus>;
330
+ resetAgent(): Promise<void>;
331
+ restart(): Promise<{ ok: boolean }>;
332
+ getConfig(): Promise<Record<string, unknown>>;
333
+ getConfigSchema(): Promise<ConfigSchemaResponse>;
334
+ updateConfig(
335
+ patch: Record<string, unknown>,
336
+ ): Promise<Record<string, unknown>>;
337
+ listAccounts(): Promise<AccountsListResponse>;
338
+ createApiKeyAccount(
339
+ providerId: LinkedAccountProviderId,
340
+ body: { label: string; apiKey: string },
341
+ ): Promise<LinkedAccountConfig>;
342
+ patchAccount(
343
+ providerId: LinkedAccountProviderId,
344
+ accountId: string,
345
+ body: Partial<{ label: string; enabled: boolean; priority: number }>,
346
+ ): Promise<LinkedAccountConfig>;
347
+ deleteAccount(
348
+ providerId: LinkedAccountProviderId,
349
+ accountId: string,
350
+ ): Promise<{ deleted: boolean }>;
351
+ testAccount(
352
+ providerId: LinkedAccountProviderId,
353
+ accountId: string,
354
+ ): Promise<AccountTestResult>;
355
+ refreshAccountUsage(
356
+ providerId: LinkedAccountProviderId,
357
+ accountId: string,
358
+ ): Promise<AccountRefreshUsageResult>;
359
+ startAccountOAuth(
360
+ providerId: LinkedAccountProviderId,
361
+ body: { label: string },
362
+ ): Promise<AccountOAuthStartResult>;
363
+ submitAccountOAuthCode(
364
+ providerId: LinkedAccountProviderId,
365
+ body: { sessionId: string; code: string },
366
+ ): Promise<{ accepted: boolean }>;
367
+ cancelAccountOAuth(
368
+ providerId: LinkedAccountProviderId,
369
+ body: { sessionId: string },
370
+ ): Promise<{ cancelled: boolean }>;
371
+ patchProviderStrategy(
372
+ providerId: LinkedAccountProviderId,
373
+ body: { strategy: AccountStrategy },
374
+ ): Promise<{
375
+ providerId: LinkedAccountProviderId;
376
+ strategy: AccountStrategy;
377
+ }>;
378
+ uploadCustomVrm(file: File): Promise<void>;
379
+ hasCustomVrm(): Promise<boolean>;
380
+ uploadCustomBackground(file: File): Promise<void>;
381
+ hasCustomBackground(): Promise<boolean>;
382
+ getConnectors(): Promise<{
383
+ connectors: Record<string, ConnectorConfig>;
384
+ }>;
385
+ saveConnector(
386
+ name: string,
387
+ config: ConnectorConfig,
388
+ ): Promise<{ connectors: Record<string, ConnectorConfig> }>;
389
+ deleteConnector(
390
+ name: string,
391
+ ): Promise<{ connectors: Record<string, ConnectorConfig> }>;
392
+ getTriggers(): Promise<{ triggers: TriggerSummary[] }>;
393
+ getTrigger(id: string): Promise<{ trigger: TriggerSummary }>;
394
+ createTrigger(
395
+ request: CreateTriggerRequest,
396
+ ): Promise<{ trigger: TriggerSummary }>;
397
+ updateTrigger(
398
+ id: string,
399
+ request: UpdateTriggerRequest,
400
+ ): Promise<{ trigger: TriggerSummary }>;
401
+ deleteTrigger(id: string): Promise<{ ok: boolean }>;
402
+ runTriggerNow(id: string): Promise<{
403
+ ok: boolean;
404
+ result: {
405
+ status: TriggerLastStatus;
406
+ error?: string;
407
+ taskDeleted: boolean;
408
+ };
409
+ trigger?: TriggerSummary;
410
+ }>;
411
+ getTriggerRuns(id: string): Promise<{ runs: TriggerRunRecord[] }>;
412
+ getTriggerRunOutput(
413
+ triggerId: string,
414
+ runId: string,
415
+ ): Promise<{
416
+ output: { text: string; truncated: boolean } | null;
417
+ status:
418
+ | "ready"
419
+ | "still_processing"
420
+ | "skipped"
421
+ | "no_output"
422
+ | "no_autonomy_room"
423
+ | "lookup_failed";
424
+ message?: string;
425
+ messageCount?: number;
426
+ segments?: Array<{
427
+ stage: "action" | "final";
428
+ action?: string;
429
+ text: string;
430
+ }>;
431
+ diagnostics?: {
432
+ memoriesInWindow: number;
433
+ agentId: string;
434
+ roomId: string;
435
+ windowStart: number;
436
+ windowEnd: number;
437
+ peek: Array<{
438
+ entityIdMatches: boolean;
439
+ source: string | null;
440
+ metadataType: unknown;
441
+ textPreview: string | null;
442
+ createdAt: number | null;
443
+ }>;
444
+ };
445
+ }>;
446
+ emitTriggerEvent(
447
+ eventKind: string,
448
+ payload?: Record<string, unknown>,
449
+ ): Promise<TriggerEventDispatchResponse>;
450
+ getTriggerHealth(): Promise<TriggerHealthSnapshot>;
451
+ getTrainingStatus(): Promise<TrainingStatus>;
452
+ listTrainingTrajectories(opts?: {
453
+ limit?: number;
454
+ offset?: number;
455
+ }): Promise<TrainingTrajectoryList>;
456
+ getTrainingTrajectory(
457
+ trajectoryId: string,
458
+ ): Promise<{ trajectory: TrainingTrajectoryDetail }>;
459
+ listTrainingDatasets(): Promise<{ datasets: TrainingDatasetRecord[] }>;
460
+ buildTrainingDataset(options?: {
461
+ limit?: number;
462
+ minLlmCallsPerTrajectory?: number;
463
+ }): Promise<{ dataset: TrainingDatasetRecord }>;
464
+ listTrainingJobs(): Promise<{ jobs: TrainingJobRecord[] }>;
465
+ startTrainingJob(
466
+ options?: StartTrainingOptions,
467
+ ): Promise<{ job: TrainingJobRecord }>;
468
+ getTrainingJob(jobId: string): Promise<{ job: TrainingJobRecord }>;
469
+ cancelTrainingJob(jobId: string): Promise<{ job: TrainingJobRecord }>;
470
+ listTrainingModels(): Promise<{ models: TrainingModelRecord[] }>;
471
+ importTrainingModelToOllama(
472
+ modelId: string,
473
+ options?: {
474
+ modelName?: string;
475
+ baseModel?: string;
476
+ ollamaUrl?: string;
477
+ },
478
+ ): Promise<{ model: TrainingModelRecord }>;
479
+ activateTrainingModel(
480
+ modelId: string,
481
+ providerModel?: string,
482
+ ): Promise<{
483
+ modelId: string;
484
+ providerModel: string;
485
+ needsRestart: boolean;
486
+ }>;
487
+ benchmarkTrainingModel(modelId: string): Promise<{
488
+ status: "passed" | "failed";
489
+ output: string;
490
+ }>;
491
+ getPlugins(): Promise<{ plugins: PluginInfo[] }>;
492
+ fetchModels(
493
+ provider: string,
494
+ refresh?: boolean,
495
+ ): Promise<{ provider: string; models: ProviderModelRecord[] }>;
496
+ getCorePlugins(): Promise<CorePluginsResponse>;
497
+ toggleCorePlugin(
498
+ npmName: string,
499
+ enabled: boolean,
500
+ ): Promise<PluginMutationResult>;
501
+ updatePlugin(
502
+ id: string,
503
+ config: Record<string, unknown>,
504
+ ): Promise<PluginMutationResult>;
505
+ setTavilyApiKey(apiKey: string): Promise<{ ok: boolean; restartScheduled: boolean }>;
506
+ getSecrets(): Promise<{ secrets: SecretInfo[] }>;
507
+ updateSecrets(
508
+ secrets: Record<string, string>,
509
+ ): Promise<{ ok: boolean; updated: string[] }>;
510
+ testPluginConnection(id: string): Promise<{
511
+ success: boolean;
512
+ pluginId: string;
513
+ message?: string;
514
+ error?: string;
515
+ durationMs: number;
516
+ }>;
517
+ getLogs(filter?: LogsFilter): Promise<LogsResponse>;
518
+ getSecurityAudit(
519
+ filter?: SecurityAuditFilter,
520
+ ): Promise<SecurityAuditResponse>;
521
+ streamSecurityAudit(
522
+ onEvent: (event: SecurityAuditStreamEvent) => void,
523
+ filter?: SecurityAuditFilter,
524
+ signal?: AbortSignal,
525
+ ): Promise<void>;
526
+ getAgentEvents(opts?: {
527
+ afterEventId?: string;
528
+ limit?: number;
529
+ runId?: string;
530
+ fromSeq?: number;
531
+ }): Promise<AgentEventsResponse>;
532
+ getExtensionStatus(): Promise<ExtensionStatus>;
533
+ getRelationshipsGraph(
534
+ query?: RelationshipsGraphQuery,
535
+ ): Promise<RelationshipsGraphSnapshot>;
536
+ getRelationshipsPeople(query?: RelationshipsGraphQuery): Promise<{
537
+ people: RelationshipsPersonSummary[];
538
+ stats: RelationshipsGraphStats;
539
+ }>;
540
+ getRelationshipsPerson(id: string): Promise<RelationshipsPersonDetail>;
541
+ getRelationshipsActivity(
542
+ limit?: number,
543
+ offset?: number,
544
+ ): Promise<RelationshipsActivityResponse>;
545
+ getRelationshipsCandidates(): Promise<RelationshipsMergeCandidate[]>;
546
+ acceptRelationshipsCandidate(
547
+ candidateId: string,
548
+ ): Promise<{ id: string; status: string }>;
549
+ rejectRelationshipsCandidate(
550
+ candidateId: string,
551
+ ): Promise<{ id: string; status: string }>;
552
+ proposeRelationshipsLink(
553
+ sourceEntityId: string,
554
+ targetEntityId: string,
555
+ evidence?: Record<string, unknown>,
556
+ ): Promise<{ id: string; status: string }>;
557
+ getCharacter(): Promise<{
558
+ character: CharacterData;
559
+ agentName: string;
560
+ }>;
561
+ getRandomName(): Promise<{ name: string }>;
562
+ generateCharacterField(
563
+ field: string,
564
+ context: {
565
+ name?: string;
566
+ system?: string;
567
+ bio?: string;
568
+ topics?: string[];
569
+ style?: { all?: string[]; chat?: string[]; post?: string[] };
570
+ postExamples?: string[];
571
+ },
572
+ mode?: "append" | "replace",
573
+ ): Promise<{ generated: string }>;
574
+ updateCharacter(
575
+ character: CharacterData,
576
+ ): Promise<{ ok: boolean; character: CharacterData; agentName: string }>;
577
+ listCharacterHistory(options?: {
578
+ limit?: number;
579
+ offset?: number;
580
+ }): Promise<CharacterHistoryResponse>;
581
+ listExperiences(
582
+ options?: ExperienceListQuery,
583
+ ): Promise<ExperienceListResponse>;
584
+ getExperience(id: string): Promise<{ experience: ExperienceRecord }>;
585
+ updateExperience(
586
+ id: string,
587
+ data: ExperienceUpdateInput,
588
+ ): Promise<{ experience: ExperienceRecord }>;
589
+ deleteExperience(id: string): Promise<{ ok: boolean }>;
590
+ getUpdateStatus(force?: boolean): Promise<UpdateStatus>;
591
+ setUpdateChannel(
592
+ channel: "stable" | "beta" | "nightly",
593
+ ): Promise<{ channel: string }>;
594
+ getAgentAutomationMode(): Promise<AgentAutomationModeResponse>;
595
+ setAgentAutomationMode(
596
+ mode: AgentAutomationMode,
597
+ ): Promise<AgentAutomationModeResponse>;
598
+ getTradePermissionMode(): Promise<TradePermissionModeResponse>;
599
+ setTradePermissionMode(
600
+ mode: TradePermissionMode,
601
+ ): Promise<TradePermissionModeResponse>;
602
+ getPermissions(): Promise<AllPermissionsState>;
603
+ getPermission(id: SystemPermissionId): Promise<PermissionState>;
604
+ requestPermission(id: SystemPermissionId): Promise<PermissionState>;
605
+ openPermissionSettings(id: SystemPermissionId): Promise<void>;
606
+ refreshPermissions(): Promise<AllPermissionsState>;
607
+ setShellEnabled(enabled: boolean): Promise<PermissionState>;
608
+ isShellEnabled(): Promise<boolean>;
609
+ getWebsiteBlockerStatus(): Promise<{
610
+ available: boolean;
611
+ active: boolean;
612
+ hostsFilePath: string | null;
613
+ endsAt: string | null;
614
+ websites: string[];
615
+ canUnblockEarly: boolean;
616
+ requiresElevation: boolean;
617
+ engine:
618
+ | "hosts-file"
619
+ | "vpn-dns"
620
+ | "network-extension"
621
+ | "content-blocker";
622
+ platform: string;
623
+ supportsElevationPrompt: boolean;
624
+ elevationPromptMethod:
625
+ | "osascript"
626
+ | "pkexec"
627
+ | "powershell-runas"
628
+ | "vpn-consent"
629
+ | "system-settings"
630
+ | null;
631
+ permissionStatus?: PermissionState["status"];
632
+ canRequestPermission?: boolean;
633
+ canOpenSystemSettings?: boolean;
634
+ reason?: string;
635
+ }>;
636
+ startWebsiteBlock(options: {
637
+ websites?: string[] | string;
638
+ durationMinutes?: number | string | null;
639
+ text?: string;
640
+ }): Promise<
641
+ | {
642
+ success: true;
643
+ endsAt: string | null;
644
+ request: {
645
+ websites: string[];
646
+ durationMinutes: number | null;
647
+ };
648
+ }
649
+ | {
650
+ success: false;
651
+ error: string;
652
+ status?: {
653
+ active: boolean;
654
+ endsAt: string | null;
655
+ websites: string[];
656
+ requiresElevation: boolean;
657
+ };
658
+ }
659
+ >;
660
+ stopWebsiteBlock(): Promise<
661
+ | {
662
+ success: true;
663
+ removed: boolean;
664
+ status: {
665
+ active: boolean;
666
+ endsAt: string | null;
667
+ websites: string[];
668
+ canUnblockEarly: boolean;
669
+ requiresElevation: boolean;
670
+ };
671
+ }
672
+ | {
673
+ success: false;
674
+ error: string;
675
+ status?: {
676
+ active: boolean;
677
+ endsAt: string | null;
678
+ websites: string[];
679
+ canUnblockEarly: boolean;
680
+ requiresElevation: boolean;
681
+ };
682
+ }
683
+ >;
684
+ getAppBlockerStatus(): Promise<AppBlockerStatusResult>;
685
+ checkAppBlockerPermissions(): Promise<AppBlockerPermissionResult>;
686
+ requestAppBlockerPermissions(): Promise<AppBlockerPermissionResult>;
687
+ getInstalledAppsToBlock(): Promise<{ apps: AppBlockerInstalledApp[] }>;
688
+ selectAppBlockerApps(): Promise<{
689
+ apps: AppBlockerInstalledApp[];
690
+ cancelled: boolean;
691
+ }>;
692
+ startAppBlock(options: {
693
+ appTokens?: string[];
694
+ packageNames?: string[];
695
+ durationMinutes?: number | null;
696
+ }): Promise<{
697
+ success: boolean;
698
+ endsAt: string | null;
699
+ blockedCount: number;
700
+ error?: string;
701
+ }>;
702
+ stopAppBlock(): Promise<{
703
+ success: boolean;
704
+ error?: string;
705
+ }>;
706
+ getCodingAgentStatus(): Promise<CodingAgentStatus | null>;
707
+ listCodingAgentTaskThreads(options?: {
708
+ includeArchived?: boolean;
709
+ status?: string;
710
+ search?: string;
711
+ limit?: number;
712
+ }): Promise<CodingAgentTaskThread[]>;
713
+ getCodingAgentTaskThread(
714
+ threadId: string,
715
+ ): Promise<CodingAgentTaskThreadDetail | null>;
716
+ archiveCodingAgentTaskThread(threadId: string): Promise<boolean>;
717
+ reopenCodingAgentTaskThread(threadId: string): Promise<boolean>;
718
+ stopCodingAgent(sessionId: string): Promise<boolean>;
719
+ listCodingAgentScratchWorkspaces(): Promise<CodingAgentScratchWorkspace[]>;
720
+ keepCodingAgentScratchWorkspace(sessionId: string): Promise<boolean>;
721
+ deleteCodingAgentScratchWorkspace(sessionId: string): Promise<boolean>;
722
+ promoteCodingAgentScratchWorkspace(
723
+ sessionId: string,
724
+ name?: string,
725
+ ): Promise<CodingAgentScratchWorkspace | null>;
726
+ spawnShellSession(workdir?: string): Promise<{ sessionId: string }>;
727
+ subscribePtyOutput(sessionId: string): void;
728
+ unsubscribePtyOutput(sessionId: string): void;
729
+ sendPtyInput(sessionId: string, data: string): void;
730
+ resizePty(sessionId: string, cols: number, rows: number): void;
731
+ getPtyBufferedOutput(sessionId: string): Promise<string>;
732
+ streamGoLive(): Promise<{
733
+ ok: boolean;
734
+ live: boolean;
735
+ rtmpUrl?: string;
736
+ inputMode?: string;
737
+ audioSource?: string;
738
+ message?: string;
739
+ destination?: string;
740
+ }>;
741
+ streamGoOffline(): Promise<{ ok: boolean; live: boolean }>;
742
+ streamStatus(): Promise<{
743
+ ok: boolean;
744
+ running: boolean;
745
+ ffmpegAlive: boolean;
746
+ uptime: number;
747
+ frameCount: number;
748
+ volume: number;
749
+ muted: boolean;
750
+ audioSource: string;
751
+ inputMode: string | null;
752
+ destination?: { id: string; name: string } | null;
753
+ }>;
754
+ getStreamingDestinations(): Promise<{
755
+ ok: boolean;
756
+ destinations: Array<{ id: string; name: string }>;
757
+ }>;
758
+ setActiveDestination(destinationId: string): Promise<{
759
+ ok: boolean;
760
+ destination?: { id: string; name: string };
761
+ }>;
762
+ setStreamVolume(
763
+ volume: number,
764
+ ): Promise<{ ok: boolean; volume: number; muted: boolean }>;
765
+ muteStream(): Promise<{ ok: boolean; muted: boolean; volume: number }>;
766
+ unmuteStream(): Promise<{ ok: boolean; muted: boolean; volume: number }>;
767
+ getStreamVoice(): Promise<{
768
+ ok: boolean;
769
+ enabled: boolean;
770
+ autoSpeak: boolean;
771
+ provider: string | null;
772
+ configuredProvider: string | null;
773
+ hasApiKey: boolean;
774
+ isSpeaking: boolean;
775
+ isAttached: boolean;
776
+ }>;
777
+ saveStreamVoice(settings: {
778
+ enabled?: boolean;
779
+ autoSpeak?: boolean;
780
+ provider?: string;
781
+ }): Promise<{
782
+ ok: boolean;
783
+ voice: { enabled: boolean; autoSpeak: boolean };
784
+ }>;
785
+ streamVoiceSpeak(text: string): Promise<{ ok: boolean; speaking: boolean }>;
786
+ getOverlayLayout(
787
+ destinationId?: string | null,
788
+ ): Promise<{ ok: boolean; layout: unknown; destinationId?: string }>;
789
+ saveOverlayLayout(
790
+ layout: unknown,
791
+ destinationId?: string | null,
792
+ ): Promise<{ ok: boolean; layout: unknown; destinationId?: string }>;
793
+ getStreamSource(): Promise<{
794
+ source: { type: string; url?: string };
795
+ }>;
796
+ setStreamSource(
797
+ sourceType: string,
798
+ customUrl?: string,
799
+ ): Promise<{ ok: boolean; source: { type: string; url?: string } }>;
800
+ getStreamSettings(): Promise<{
801
+ ok: boolean;
802
+ settings: { theme?: string; avatarIndex?: number };
803
+ }>;
804
+ saveStreamSettings(settings: {
805
+ theme?: string;
806
+ avatarIndex?: number;
807
+ }): Promise<{ ok: boolean; settings: unknown }>;
808
+ }
809
+ }
810
+
811
+ // ---------------------------------------------------------------------------
812
+ // Prototype augmentation
813
+ // ---------------------------------------------------------------------------
814
+
815
+ ElizaClient.prototype.getStatus = async function (this: ElizaClient) {
816
+ return this.fetch("/api/status");
817
+ };
818
+
819
+ ElizaClient.prototype.getAgentSelfStatus = async function (this: ElizaClient) {
820
+ return this.fetch("/api/agent/self-status");
821
+ };
822
+
823
+ ElizaClient.prototype.getRuntimeSnapshot = async function (
824
+ this: ElizaClient,
825
+ opts?,
826
+ ) {
827
+ const params = new URLSearchParams();
828
+ if (typeof opts?.depth === "number") params.set("depth", String(opts.depth));
829
+ if (typeof opts?.maxArrayLength === "number") {
830
+ params.set("maxArrayLength", String(opts.maxArrayLength));
831
+ }
832
+ if (typeof opts?.maxObjectEntries === "number") {
833
+ params.set("maxObjectEntries", String(opts.maxObjectEntries));
834
+ }
835
+ if (typeof opts?.maxStringLength === "number") {
836
+ params.set("maxStringLength", String(opts.maxStringLength));
837
+ }
838
+ const qs = params.toString();
839
+ return this.fetch(`/api/runtime${qs ? `?${qs}` : ""}`);
840
+ };
841
+
842
+ ElizaClient.prototype.setAutomationMode = async function (
843
+ this: ElizaClient,
844
+ mode,
845
+ ) {
846
+ return this.fetch("/api/permissions/automation-mode", {
847
+ method: "PUT",
848
+ body: JSON.stringify({ mode }),
849
+ });
850
+ };
851
+
852
+ ElizaClient.prototype.setTradeMode = async function (this: ElizaClient, mode) {
853
+ return this.fetch("/api/permissions/trade-mode", {
854
+ method: "PUT",
855
+ body: JSON.stringify({ mode }),
856
+ });
857
+ };
858
+
859
+ ElizaClient.prototype.playEmote = async function (this: ElizaClient, emoteId) {
860
+ return this.fetch("/api/emote", {
861
+ method: "POST",
862
+ body: JSON.stringify({ emoteId }),
863
+ });
864
+ };
865
+
866
+ ElizaClient.prototype.runTerminalCommand = async function (
867
+ this: ElizaClient,
868
+ command,
869
+ ) {
870
+ return this.fetch("/api/terminal/run", {
871
+ method: "POST",
872
+ body: JSON.stringify({ command }),
873
+ });
874
+ };
875
+
876
+ ElizaClient.prototype.getOnboardingStatus = async function (this: ElizaClient) {
877
+ return this.fetch("/api/onboarding/status");
878
+ };
879
+
880
+ ElizaClient.prototype.getWalletKeys = async function (this: ElizaClient) {
881
+ return this.fetch("/api/wallet/keys");
882
+ };
883
+
884
+ ElizaClient.prototype.getWalletOsStoreStatus = async function (
885
+ this: ElizaClient,
886
+ ) {
887
+ return this.fetch("/api/wallet/os-store");
888
+ };
889
+
890
+ ElizaClient.prototype.postWalletOsStoreAction = async function (
891
+ this: ElizaClient,
892
+ action,
893
+ ) {
894
+ return this.fetch("/api/wallet/os-store", {
895
+ method: "POST",
896
+ body: JSON.stringify({ action }),
897
+ });
898
+ };
899
+
900
+ ElizaClient.prototype.getAuthStatus = async function (this: ElizaClient) {
901
+ const maxRetries = 3;
902
+ const baseBackoffMs = 1000;
903
+ let lastErr: unknown;
904
+ for (let attempt = 0; attempt <= maxRetries; attempt++) {
905
+ try {
906
+ return await this.fetch("/api/auth/status");
907
+ } catch (err: unknown) {
908
+ const status = (err as Error & { status?: number })?.status;
909
+ if (status === 401) {
910
+ return { required: true, pairingEnabled: false, expiresAt: null };
911
+ }
912
+ if (status === 404) {
913
+ return { required: false, pairingEnabled: false, expiresAt: null };
914
+ }
915
+ lastErr = err;
916
+ if (attempt < maxRetries) {
917
+ await new Promise((r) => setTimeout(r, baseBackoffMs * 2 ** attempt));
918
+ }
919
+ }
920
+ }
921
+ throw lastErr;
922
+ };
923
+
924
+ ElizaClient.prototype.postBootstrapExchange = async function (
925
+ this: ElizaClient,
926
+ token: string,
927
+ ): Promise<BootstrapExchangeResult> {
928
+ // Use allowNonOk so 401/429/503 bodies are parsed rather than thrown.
929
+ const body = await this.fetch<{
930
+ sessionId?: string;
931
+ expiresAt?: number;
932
+ identityId?: string;
933
+ error?: string;
934
+ reason?: string;
935
+ }>(
936
+ "/api/auth/bootstrap/exchange",
937
+ {
938
+ method: "POST",
939
+ body: JSON.stringify({ token }),
940
+ },
941
+ { allowNonOk: true },
942
+ );
943
+
944
+ if (
945
+ typeof body.sessionId === "string" &&
946
+ typeof body.expiresAt === "number" &&
947
+ typeof body.identityId === "string"
948
+ ) {
949
+ return {
950
+ ok: true,
951
+ sessionId: body.sessionId,
952
+ expiresAt: body.expiresAt,
953
+ identityId: body.identityId,
954
+ };
955
+ }
956
+
957
+ // Map reason to an HTTP status bucket for the UI layer.
958
+ const reason = body.reason;
959
+ const status: 400 | 401 | 429 | 503 =
960
+ reason === "rate_limited"
961
+ ? 429
962
+ : reason === "db_unavailable" ||
963
+ reason === "missing_issuer_env" ||
964
+ reason === "missing_container_env"
965
+ ? 503
966
+ : reason === "missing_token"
967
+ ? 400
968
+ : 401;
969
+ return {
970
+ ok: false,
971
+ status,
972
+ error: body.error ?? "exchange_failed",
973
+ reason,
974
+ };
975
+ };
976
+
977
+ ElizaClient.prototype.pair = async function (this: ElizaClient, code) {
978
+ const res = await this.fetch<{ token: string }>("/api/auth/pair", {
979
+ method: "POST",
980
+ body: JSON.stringify({ code }),
981
+ });
982
+ return res;
983
+ };
984
+
985
+ ElizaClient.prototype.getOnboardingOptions = async function (
986
+ this: ElizaClient,
987
+ ) {
988
+ return this.fetch("/api/onboarding/options");
989
+ };
990
+
991
+ ElizaClient.prototype.submitOnboarding = async function (
992
+ this: ElizaClient,
993
+ data,
994
+ ) {
995
+ await this.fetch("/api/onboarding", {
996
+ method: "POST",
997
+ body: JSON.stringify(data),
998
+ });
999
+ };
1000
+
1001
+ ElizaClient.prototype.startAnthropicLogin = async function (this: ElizaClient) {
1002
+ return this.fetch("/api/subscription/anthropic/start", { method: "POST" });
1003
+ };
1004
+
1005
+ ElizaClient.prototype.exchangeAnthropicCode = async function (
1006
+ this: ElizaClient,
1007
+ code,
1008
+ ) {
1009
+ return this.fetch("/api/subscription/anthropic/exchange", {
1010
+ method: "POST",
1011
+ headers: { "Content-Type": "application/json" },
1012
+ body: JSON.stringify({ code }),
1013
+ });
1014
+ };
1015
+
1016
+ ElizaClient.prototype.submitAnthropicSetupToken = async function (
1017
+ this: ElizaClient,
1018
+ token,
1019
+ ) {
1020
+ return this.fetch("/api/subscription/anthropic/setup-token", {
1021
+ method: "POST",
1022
+ headers: { "Content-Type": "application/json" },
1023
+ body: JSON.stringify({ token }),
1024
+ });
1025
+ };
1026
+
1027
+ ElizaClient.prototype.getSubscriptionStatus = async function (
1028
+ this: ElizaClient,
1029
+ ) {
1030
+ return this.fetch<SubscriptionStatusResponse>("/api/subscription/status");
1031
+ };
1032
+
1033
+ ElizaClient.prototype.deleteSubscription = async function (
1034
+ this: ElizaClient,
1035
+ provider,
1036
+ ) {
1037
+ return this.fetch(`/api/subscription/${encodeURIComponent(provider)}`, {
1038
+ method: "DELETE",
1039
+ });
1040
+ };
1041
+
1042
+ ElizaClient.prototype.switchProvider = async function (
1043
+ this: ElizaClient,
1044
+ provider,
1045
+ apiKey?,
1046
+ primaryModel?,
1047
+ ) {
1048
+ logSettingsClient("POST /api/provider/switch → start", {
1049
+ baseUrl: this.getBaseUrl(),
1050
+ provider,
1051
+ hasApiKey: Boolean(apiKey?.trim()),
1052
+ apiKey,
1053
+ hasPrimaryModel: Boolean(primaryModel?.trim()),
1054
+ primaryModel,
1055
+ });
1056
+ const result = (await this.fetch("/api/provider/switch", {
1057
+ method: "POST",
1058
+ headers: { "Content-Type": "application/json" },
1059
+ body: JSON.stringify({
1060
+ provider,
1061
+ ...(apiKey ? { apiKey } : {}),
1062
+ ...(primaryModel ? { primaryModel } : {}),
1063
+ }),
1064
+ })) as { success: boolean; provider: string; restarting: boolean };
1065
+ logSettingsClient("POST /api/provider/switch ← ok", {
1066
+ baseUrl: this.getBaseUrl(),
1067
+ result,
1068
+ });
1069
+ return result;
1070
+ };
1071
+
1072
+ ElizaClient.prototype.startOpenAILogin = async function (this: ElizaClient) {
1073
+ return this.fetch("/api/subscription/openai/start", { method: "POST" });
1074
+ };
1075
+
1076
+ ElizaClient.prototype.exchangeOpenAICode = async function (
1077
+ this: ElizaClient,
1078
+ code,
1079
+ ) {
1080
+ return this.fetch("/api/subscription/openai/exchange", {
1081
+ method: "POST",
1082
+ headers: { "Content-Type": "application/json" },
1083
+ body: JSON.stringify({ code }),
1084
+ });
1085
+ };
1086
+
1087
+ ElizaClient.prototype.startAgent = async function (this: ElizaClient) {
1088
+ const res = await this.fetch<{ status: AgentStatus }>("/api/agent/start", {
1089
+ method: "POST",
1090
+ });
1091
+ return res.status;
1092
+ };
1093
+
1094
+ ElizaClient.prototype.stopAgent = async function (this: ElizaClient) {
1095
+ const res = await this.fetch<{ status: AgentStatus }>("/api/agent/stop", {
1096
+ method: "POST",
1097
+ });
1098
+ return res.status;
1099
+ };
1100
+
1101
+ ElizaClient.prototype.pauseAgent = async function (this: ElizaClient) {
1102
+ const res = await this.fetch<{ status: AgentStatus }>("/api/agent/pause", {
1103
+ method: "POST",
1104
+ });
1105
+ return res.status;
1106
+ };
1107
+
1108
+ ElizaClient.prototype.resumeAgent = async function (this: ElizaClient) {
1109
+ const res = await this.fetch<{ status: AgentStatus }>("/api/agent/resume", {
1110
+ method: "POST",
1111
+ });
1112
+ return res.status;
1113
+ };
1114
+
1115
+ ElizaClient.prototype.restartAgent = async function (this: ElizaClient) {
1116
+ try {
1117
+ const res = await this.fetch<{ status: AgentStatus }>(
1118
+ "/api/agent/restart",
1119
+ {
1120
+ method: "POST",
1121
+ },
1122
+ );
1123
+ return res.status;
1124
+ } catch {
1125
+ // Back-compat for older runtimes that still expose only the process-level
1126
+ // restart endpoint.
1127
+ await this.fetch<{ ok: boolean }>("/api/restart", { method: "POST" });
1128
+ return {
1129
+ state: "restarting",
1130
+ agentName: "Eliza",
1131
+ model: undefined,
1132
+ uptime: undefined,
1133
+ startedAt: undefined,
1134
+ };
1135
+ }
1136
+ };
1137
+
1138
+ ElizaClient.prototype.restartAndWait = async function (
1139
+ this: ElizaClient,
1140
+ maxWaitMs = 30000,
1141
+ ) {
1142
+ const t0 = Date.now();
1143
+ console.info("[eliza][reset][client] restartAndWait: begin", {
1144
+ baseUrl: this.getBaseUrl(),
1145
+ maxWaitMs,
1146
+ });
1147
+ try {
1148
+ await this.restartAgent();
1149
+ console.info("[eliza][reset][client] restartAndWait: restart accepted");
1150
+ } catch (e: unknown) {
1151
+ console.info(
1152
+ "[eliza][reset][client] restartAndWait: initial restart call failed (often 409 while restarting)",
1153
+ e,
1154
+ );
1155
+ }
1156
+ const start = Date.now();
1157
+ const interval = 1000;
1158
+ let pollN = 0;
1159
+ while (Date.now() - start < maxWaitMs) {
1160
+ await new Promise((r) => setTimeout(r, interval));
1161
+ pollN += 1;
1162
+ try {
1163
+ const status = await this.getStatus();
1164
+ if (status.state === "running") {
1165
+ console.info("[eliza][reset][client] restartAndWait: running", {
1166
+ pollN,
1167
+ waitedMs: Date.now() - t0,
1168
+ port: status.port,
1169
+ });
1170
+ return status;
1171
+ }
1172
+ if (pollN === 1 || pollN % 5 === 0) {
1173
+ console.debug("[eliza][reset][client] restartAndWait: poll", {
1174
+ pollN,
1175
+ state: status.state,
1176
+ waitedMs: Date.now() - t0,
1177
+ });
1178
+ }
1179
+ } catch (pollErr) {
1180
+ if (pollN === 1 || pollN % 5 === 0) {
1181
+ console.debug(
1182
+ "[eliza][reset][client] restartAndWait: getStatus error while polling",
1183
+ { pollN, waitedMs: Date.now() - t0 },
1184
+ pollErr,
1185
+ );
1186
+ }
1187
+ }
1188
+ }
1189
+ const final = await this.getStatus();
1190
+ console.warn(
1191
+ "[eliza][reset][client] restartAndWait: timed out — returning last status",
1192
+ {
1193
+ state: final.state,
1194
+ waitedMs: Date.now() - t0,
1195
+ maxWaitMs,
1196
+ },
1197
+ );
1198
+ return final;
1199
+ };
1200
+
1201
+ ElizaClient.prototype.resetAgent = async function (this: ElizaClient) {
1202
+ console.info("[eliza][reset][client] POST /api/agent/reset", {
1203
+ baseUrl: this.getBaseUrl(),
1204
+ });
1205
+ await this.fetch("/api/agent/reset", { method: "POST" });
1206
+ console.info("[eliza][reset][client] POST /api/agent/reset OK");
1207
+ };
1208
+
1209
+ ElizaClient.prototype.restart = async function (this: ElizaClient) {
1210
+ return this.fetch("/api/restart", { method: "POST" });
1211
+ };
1212
+
1213
+ ElizaClient.prototype.getConfig = async function (this: ElizaClient) {
1214
+ logSettingsClient("GET /api/config → start", {
1215
+ baseUrl: this.getBaseUrl(),
1216
+ });
1217
+ const r = (await this.fetch("/api/config")) as Record<string, unknown>;
1218
+ const cloud = r.cloud as Record<string, unknown> | undefined;
1219
+ logSettingsClient("GET /api/config ← ok", {
1220
+ baseUrl: this.getBaseUrl(),
1221
+ topKeys: Object.keys(r).sort(),
1222
+ cloud: settingsDebugCloudSummary(cloud),
1223
+ });
1224
+ return r;
1225
+ };
1226
+
1227
+ ElizaClient.prototype.getConfigSchema = async function (this: ElizaClient) {
1228
+ return this.fetch("/api/config/schema");
1229
+ };
1230
+
1231
+ ElizaClient.prototype.updateConfig = async function (this: ElizaClient, patch) {
1232
+ logSettingsClient("PUT /api/config → start", {
1233
+ baseUrl: this.getBaseUrl(),
1234
+ patch,
1235
+ });
1236
+ const out = (await this.fetch(
1237
+ "/api/config",
1238
+ {
1239
+ method: "PUT",
1240
+ headers: { "Content-Type": "application/json" },
1241
+ body: JSON.stringify(patch),
1242
+ },
1243
+ {
1244
+ timeoutMs: SETTINGS_MUTATION_TIMEOUT_MS,
1245
+ },
1246
+ )) as Record<string, unknown>;
1247
+ const cloud = out.cloud as Record<string, unknown> | undefined;
1248
+ logSettingsClient("PUT /api/config ← ok", {
1249
+ baseUrl: this.getBaseUrl(),
1250
+ topKeys: Object.keys(out).sort(),
1251
+ cloud: settingsDebugCloudSummary(cloud),
1252
+ });
1253
+ return out;
1254
+ };
1255
+
1256
+ ElizaClient.prototype.uploadCustomVrm = async function (
1257
+ this: ElizaClient,
1258
+ file,
1259
+ ) {
1260
+ const buf = await file.arrayBuffer();
1261
+ await this.fetch("/api/avatar/vrm", {
1262
+ method: "POST",
1263
+ headers: { "Content-Type": "application/octet-stream" },
1264
+ body: buf,
1265
+ });
1266
+ };
1267
+
1268
+ ElizaClient.prototype.hasCustomVrm = async function (this: ElizaClient) {
1269
+ try {
1270
+ const res = await this.rawRequest(
1271
+ "/api/avatar/vrm",
1272
+ { method: "HEAD" },
1273
+ { allowNonOk: true },
1274
+ );
1275
+ return res.ok;
1276
+ } catch {
1277
+ return false;
1278
+ }
1279
+ };
1280
+
1281
+ ElizaClient.prototype.uploadCustomBackground = async function (
1282
+ this: ElizaClient,
1283
+ file,
1284
+ ) {
1285
+ const buf = await file.arrayBuffer();
1286
+ await this.fetch("/api/avatar/background", {
1287
+ method: "POST",
1288
+ headers: { "Content-Type": "application/octet-stream" },
1289
+ body: buf,
1290
+ });
1291
+ };
1292
+
1293
+ ElizaClient.prototype.hasCustomBackground = async function (this: ElizaClient) {
1294
+ try {
1295
+ const res = await this.rawRequest(
1296
+ "/api/avatar/background",
1297
+ { method: "HEAD" },
1298
+ { allowNonOk: true },
1299
+ );
1300
+ return res.ok;
1301
+ } catch {
1302
+ return false;
1303
+ }
1304
+ };
1305
+
1306
+ ElizaClient.prototype.getConnectors = async function (this: ElizaClient) {
1307
+ return this.fetch("/api/connectors");
1308
+ };
1309
+
1310
+ ElizaClient.prototype.saveConnector = async function (
1311
+ this: ElizaClient,
1312
+ name,
1313
+ config,
1314
+ ) {
1315
+ return this.fetch("/api/connectors", {
1316
+ method: "POST",
1317
+ body: JSON.stringify({ name, config }),
1318
+ });
1319
+ };
1320
+
1321
+ ElizaClient.prototype.deleteConnector = async function (
1322
+ this: ElizaClient,
1323
+ name,
1324
+ ) {
1325
+ return this.fetch(`/api/connectors/${encodeURIComponent(name)}`, {
1326
+ method: "DELETE",
1327
+ });
1328
+ };
1329
+
1330
+ ElizaClient.prototype.getTriggers = async function (this: ElizaClient) {
1331
+ return this.fetch("/api/triggers");
1332
+ };
1333
+
1334
+ ElizaClient.prototype.getTrigger = async function (this: ElizaClient, id) {
1335
+ return this.fetch(`/api/triggers/${encodeURIComponent(id)}`);
1336
+ };
1337
+
1338
+ ElizaClient.prototype.createTrigger = async function (
1339
+ this: ElizaClient,
1340
+ request,
1341
+ ) {
1342
+ return this.fetch("/api/triggers", {
1343
+ method: "POST",
1344
+ body: JSON.stringify(request),
1345
+ });
1346
+ };
1347
+
1348
+ ElizaClient.prototype.updateTrigger = async function (
1349
+ this: ElizaClient,
1350
+ id,
1351
+ request,
1352
+ ) {
1353
+ return this.fetch(`/api/triggers/${encodeURIComponent(id)}`, {
1354
+ method: "PUT",
1355
+ body: JSON.stringify(request),
1356
+ });
1357
+ };
1358
+
1359
+ ElizaClient.prototype.deleteTrigger = async function (this: ElizaClient, id) {
1360
+ return this.fetch(`/api/triggers/${encodeURIComponent(id)}`, {
1361
+ method: "DELETE",
1362
+ });
1363
+ };
1364
+
1365
+ ElizaClient.prototype.runTriggerNow = async function (this: ElizaClient, id) {
1366
+ return this.fetch(`/api/triggers/${encodeURIComponent(id)}/execute`, {
1367
+ method: "POST",
1368
+ });
1369
+ };
1370
+
1371
+ ElizaClient.prototype.getTriggerRuns = async function (this: ElizaClient, id) {
1372
+ return this.fetch(`/api/triggers/${encodeURIComponent(id)}/runs`);
1373
+ };
1374
+
1375
+ ElizaClient.prototype.getTriggerRunOutput = async function (
1376
+ this: ElizaClient,
1377
+ triggerId: string,
1378
+ runId: string,
1379
+ ) {
1380
+ return this.fetch(
1381
+ `/api/triggers/${encodeURIComponent(triggerId)}/runs/${encodeURIComponent(runId)}/output`,
1382
+ );
1383
+ };
1384
+
1385
+ ElizaClient.prototype.emitTriggerEvent = async function (
1386
+ this: ElizaClient,
1387
+ eventKind,
1388
+ payload = {},
1389
+ ) {
1390
+ return this.fetch(`/api/triggers/events/${encodeURIComponent(eventKind)}`, {
1391
+ method: "POST",
1392
+ body: JSON.stringify({ payload }),
1393
+ });
1394
+ };
1395
+
1396
+ ElizaClient.prototype.getTriggerHealth = async function (this: ElizaClient) {
1397
+ return this.fetch("/api/triggers/health");
1398
+ };
1399
+
1400
+ ElizaClient.prototype.getTrainingStatus = async function (this: ElizaClient) {
1401
+ return this.fetch("/api/training/status");
1402
+ };
1403
+
1404
+ ElizaClient.prototype.listTrainingTrajectories = async function (
1405
+ this: ElizaClient,
1406
+ opts?,
1407
+ ) {
1408
+ const params = new URLSearchParams();
1409
+ if (typeof opts?.limit === "number") params.set("limit", String(opts.limit));
1410
+ if (typeof opts?.offset === "number")
1411
+ params.set("offset", String(opts.offset));
1412
+ const qs = params.toString();
1413
+ return this.fetch(`/api/training/trajectories${qs ? `?${qs}` : ""}`);
1414
+ };
1415
+
1416
+ ElizaClient.prototype.getTrainingTrajectory = async function (
1417
+ this: ElizaClient,
1418
+ trajectoryId,
1419
+ ) {
1420
+ return this.fetch(
1421
+ `/api/training/trajectories/${encodeURIComponent(trajectoryId)}`,
1422
+ );
1423
+ };
1424
+
1425
+ ElizaClient.prototype.listTrainingDatasets = async function (
1426
+ this: ElizaClient,
1427
+ ) {
1428
+ return this.fetch("/api/training/datasets");
1429
+ };
1430
+
1431
+ ElizaClient.prototype.buildTrainingDataset = async function (
1432
+ this: ElizaClient,
1433
+ options?,
1434
+ ) {
1435
+ return this.fetch("/api/training/datasets/build", {
1436
+ method: "POST",
1437
+ body: JSON.stringify(options ?? {}),
1438
+ });
1439
+ };
1440
+
1441
+ ElizaClient.prototype.listTrainingJobs = async function (this: ElizaClient) {
1442
+ return this.fetch("/api/training/jobs");
1443
+ };
1444
+
1445
+ ElizaClient.prototype.startTrainingJob = async function (
1446
+ this: ElizaClient,
1447
+ options?,
1448
+ ) {
1449
+ return this.fetch("/api/training/jobs", {
1450
+ method: "POST",
1451
+ body: JSON.stringify(options ?? {}),
1452
+ });
1453
+ };
1454
+
1455
+ ElizaClient.prototype.getTrainingJob = async function (
1456
+ this: ElizaClient,
1457
+ jobId,
1458
+ ) {
1459
+ return this.fetch(`/api/training/jobs/${encodeURIComponent(jobId)}`);
1460
+ };
1461
+
1462
+ ElizaClient.prototype.cancelTrainingJob = async function (
1463
+ this: ElizaClient,
1464
+ jobId,
1465
+ ) {
1466
+ return this.fetch(`/api/training/jobs/${encodeURIComponent(jobId)}/cancel`, {
1467
+ method: "POST",
1468
+ });
1469
+ };
1470
+
1471
+ ElizaClient.prototype.listTrainingModels = async function (this: ElizaClient) {
1472
+ return this.fetch("/api/training/models");
1473
+ };
1474
+
1475
+ ElizaClient.prototype.importTrainingModelToOllama = async function (
1476
+ this: ElizaClient,
1477
+ modelId,
1478
+ options?,
1479
+ ) {
1480
+ return this.fetch(
1481
+ `/api/training/models/${encodeURIComponent(modelId)}/import-ollama`,
1482
+ {
1483
+ method: "POST",
1484
+ body: JSON.stringify(options ?? {}),
1485
+ },
1486
+ );
1487
+ };
1488
+
1489
+ ElizaClient.prototype.activateTrainingModel = async function (
1490
+ this: ElizaClient,
1491
+ modelId,
1492
+ providerModel?,
1493
+ ) {
1494
+ return this.fetch(
1495
+ `/api/training/models/${encodeURIComponent(modelId)}/activate`,
1496
+ {
1497
+ method: "POST",
1498
+ body: JSON.stringify({ providerModel }),
1499
+ },
1500
+ );
1501
+ };
1502
+
1503
+ ElizaClient.prototype.benchmarkTrainingModel = async function (
1504
+ this: ElizaClient,
1505
+ modelId,
1506
+ ) {
1507
+ return this.fetch(
1508
+ `/api/training/models/${encodeURIComponent(modelId)}/benchmark`,
1509
+ { method: "POST" },
1510
+ );
1511
+ };
1512
+
1513
+ ElizaClient.prototype.getPlugins = async function (this: ElizaClient) {
1514
+ return this.fetch("/api/plugins");
1515
+ };
1516
+
1517
+ ElizaClient.prototype.fetchModels = async function (
1518
+ this: ElizaClient,
1519
+ provider,
1520
+ refresh = true,
1521
+ ) {
1522
+ const params = new URLSearchParams({ provider });
1523
+ if (refresh) params.set("refresh", "true");
1524
+ return this.fetch(`/api/models?${params.toString()}`);
1525
+ };
1526
+
1527
+ ElizaClient.prototype.getCorePlugins = async function (this: ElizaClient) {
1528
+ return this.fetch("/api/plugins/core");
1529
+ };
1530
+
1531
+ ElizaClient.prototype.toggleCorePlugin = async function (
1532
+ this: ElizaClient,
1533
+ npmName,
1534
+ enabled,
1535
+ ) {
1536
+ return this.fetch("/api/plugins/core/toggle", {
1537
+ method: "POST",
1538
+ body: JSON.stringify({ npmName, enabled }),
1539
+ });
1540
+ };
1541
+
1542
+ ElizaClient.prototype.updatePlugin = async function (
1543
+ this: ElizaClient,
1544
+ id,
1545
+ config,
1546
+ ) {
1547
+ logSettingsClient(`PUT /api/plugins/${id} → start`, {
1548
+ baseUrl: this.getBaseUrl(),
1549
+ body: config,
1550
+ });
1551
+ const result = (await this.fetch(
1552
+ `/api/plugins/${id}`,
1553
+ {
1554
+ method: "PUT",
1555
+ body: JSON.stringify(config),
1556
+ },
1557
+ {
1558
+ timeoutMs: SETTINGS_MUTATION_TIMEOUT_MS,
1559
+ },
1560
+ )) as PluginMutationResult;
1561
+ logSettingsClient(`PUT /api/plugins/${id} ← ok`, {
1562
+ baseUrl: this.getBaseUrl(),
1563
+ result,
1564
+ });
1565
+ return result;
1566
+ };
1567
+
1568
+ ElizaClient.prototype.setTavilyApiKey = async function (
1569
+ this: ElizaClient,
1570
+ apiKey: string,
1571
+ ) {
1572
+ return (await this.fetch("/api/integrations/tavily-key", {
1573
+ method: "PUT",
1574
+ body: JSON.stringify({ apiKey }),
1575
+ })) as { ok: boolean; restartScheduled: boolean };
1576
+ };
1577
+
1578
+ ElizaClient.prototype.getSecrets = async function (this: ElizaClient) {
1579
+ return this.fetch("/api/secrets");
1580
+ };
1581
+
1582
+ ElizaClient.prototype.updateSecrets = async function (
1583
+ this: ElizaClient,
1584
+ secrets,
1585
+ ) {
1586
+ logSettingsClient("PUT /api/secrets → start", {
1587
+ baseUrl: this.getBaseUrl(),
1588
+ secretMeta: Object.keys(secrets)
1589
+ .sort()
1590
+ .map((key) => ({
1591
+ key,
1592
+ hasValue: Boolean(secrets[key]),
1593
+ })),
1594
+ });
1595
+ const out = (await this.fetch("/api/secrets", {
1596
+ method: "PUT",
1597
+ body: JSON.stringify({ secrets }),
1598
+ })) as { ok: boolean; updated: string[] };
1599
+ logSettingsClient("PUT /api/secrets ← ok", {
1600
+ baseUrl: this.getBaseUrl(),
1601
+ out,
1602
+ });
1603
+ return out;
1604
+ };
1605
+
1606
+ ElizaClient.prototype.testPluginConnection = async function (
1607
+ this: ElizaClient,
1608
+ id,
1609
+ ) {
1610
+ return this.fetch(`/api/plugins/${encodeURIComponent(id)}/test`, {
1611
+ method: "POST",
1612
+ });
1613
+ };
1614
+
1615
+ ElizaClient.prototype.getLogs = async function (this: ElizaClient, filter?) {
1616
+ const params = new URLSearchParams();
1617
+ if (filter?.source) params.set("source", filter.source);
1618
+ if (filter?.level) params.set("level", filter.level);
1619
+ if (filter?.tag) params.set("tag", filter.tag);
1620
+ if (filter?.since) params.set("since", String(filter.since));
1621
+ const qs = params.toString();
1622
+ return this.fetch(`/api/logs${qs ? `?${qs}` : ""}`);
1623
+ };
1624
+
1625
+ // buildSecurityAuditParams is a private helper used only by agent audit methods
1626
+ function buildSecurityAuditParams(
1627
+ filter?: SecurityAuditFilter,
1628
+ includeStream = false,
1629
+ ): URLSearchParams {
1630
+ const params = new URLSearchParams();
1631
+ if (filter?.type) params.set("type", filter.type);
1632
+ if (filter?.severity) params.set("severity", filter.severity);
1633
+ if (filter?.since !== undefined) {
1634
+ const sinceValue =
1635
+ filter.since instanceof Date
1636
+ ? filter.since.toISOString()
1637
+ : String(filter.since);
1638
+ params.set("since", sinceValue);
1639
+ }
1640
+ if (filter?.limit !== undefined) params.set("limit", String(filter.limit));
1641
+ if (includeStream) params.set("stream", "1");
1642
+ return params;
1643
+ }
1644
+
1645
+ ElizaClient.prototype.getSecurityAudit = async function (
1646
+ this: ElizaClient,
1647
+ filter?,
1648
+ ) {
1649
+ const qs = buildSecurityAuditParams(filter).toString();
1650
+ return this.fetch(`/api/security/audit${qs ? `?${qs}` : ""}`);
1651
+ };
1652
+
1653
+ ElizaClient.prototype.streamSecurityAudit = async function (
1654
+ this: ElizaClient,
1655
+ onEvent,
1656
+ filter?,
1657
+ signal?,
1658
+ ) {
1659
+ if (!this.apiAvailable) {
1660
+ throw new Error("API not available (no HTTP origin)");
1661
+ }
1662
+
1663
+ const token = this.apiToken;
1664
+ const qs = buildSecurityAuditParams(filter, true).toString();
1665
+ const res = await fetch(
1666
+ `${this.baseUrl}/api/security/audit${qs ? `?${qs}` : ""}`,
1667
+ {
1668
+ method: "GET",
1669
+ headers: {
1670
+ Accept: "text/event-stream",
1671
+ ...(token ? { Authorization: `Bearer ${token}` } : {}),
1672
+ },
1673
+ signal,
1674
+ },
1675
+ );
1676
+
1677
+ if (!res.ok) {
1678
+ const body = (await res
1679
+ .json()
1680
+ .catch(() => ({ error: res.statusText }))) as Record<
1681
+ string,
1682
+ string
1683
+ > | null;
1684
+ const err = new Error(body?.error ?? `HTTP ${res.status}`);
1685
+ (err as Error & { status?: number }).status = res.status;
1686
+ throw err;
1687
+ }
1688
+
1689
+ if (!res.body) {
1690
+ throw new Error("Streaming not supported by this browser");
1691
+ }
1692
+
1693
+ const parsePayload = (payload: string) => {
1694
+ if (!payload) return;
1695
+ try {
1696
+ const parsed = JSON.parse(payload) as SecurityAuditStreamEvent;
1697
+ if (parsed.type === "snapshot" || parsed.type === "entry") {
1698
+ onEvent(parsed);
1699
+ }
1700
+ } catch {
1701
+ // Ignore malformed payloads to keep stream consumption resilient.
1702
+ }
1703
+ };
1704
+
1705
+ const decoder = new TextDecoder();
1706
+ const reader = res.body.getReader();
1707
+ let buffer = "";
1708
+
1709
+ const findSseEventBreak = (
1710
+ chunkBuffer: string,
1711
+ ): { index: number; length: number } | null => {
1712
+ const lfBreak = chunkBuffer.indexOf("\n\n");
1713
+ const crlfBreak = chunkBuffer.indexOf("\r\n\r\n");
1714
+ if (lfBreak === -1 && crlfBreak === -1) return null;
1715
+ if (lfBreak === -1) return { index: crlfBreak, length: 4 };
1716
+ if (crlfBreak === -1) return { index: lfBreak, length: 2 };
1717
+ return lfBreak < crlfBreak
1718
+ ? { index: lfBreak, length: 2 }
1719
+ : { index: crlfBreak, length: 4 };
1720
+ };
1721
+
1722
+ while (true) {
1723
+ const { done, value } = await reader.read();
1724
+ if (done) break;
1725
+
1726
+ buffer += decoder.decode(value, { stream: true });
1727
+ let eventBreak = findSseEventBreak(buffer);
1728
+ while (eventBreak) {
1729
+ const rawEvent = buffer.slice(0, eventBreak.index);
1730
+ buffer = buffer.slice(eventBreak.index + eventBreak.length);
1731
+ for (const line of rawEvent.split(/\r?\n/)) {
1732
+ if (!line.startsWith("data:")) continue;
1733
+ parsePayload(line.slice(5).trim());
1734
+ }
1735
+ eventBreak = findSseEventBreak(buffer);
1736
+ }
1737
+ }
1738
+
1739
+ if (buffer.trim()) {
1740
+ for (const line of buffer.split(/\r?\n/)) {
1741
+ if (!line.startsWith("data:")) continue;
1742
+ parsePayload(line.slice(5).trim());
1743
+ }
1744
+ }
1745
+ };
1746
+
1747
+ ElizaClient.prototype.getAgentEvents = async function (
1748
+ this: ElizaClient,
1749
+ opts?,
1750
+ ) {
1751
+ const params = new URLSearchParams();
1752
+ if (opts?.afterEventId) params.set("after", opts.afterEventId);
1753
+ if (typeof opts?.limit === "number") params.set("limit", String(opts.limit));
1754
+ if (opts?.runId) params.set("runId", opts.runId);
1755
+ if (typeof opts?.fromSeq === "number")
1756
+ params.set("fromSeq", String(Math.trunc(opts.fromSeq)));
1757
+ const qs = params.toString();
1758
+ return this.fetch(`/api/agent/events${qs ? `?${qs}` : ""}`);
1759
+ };
1760
+
1761
+ ElizaClient.prototype.getExtensionStatus = async function (this: ElizaClient) {
1762
+ return this.fetch("/api/extension/status");
1763
+ };
1764
+
1765
+ ElizaClient.prototype.getRelationshipsGraph = async function (
1766
+ this: ElizaClient,
1767
+ query,
1768
+ ) {
1769
+ const params = new URLSearchParams();
1770
+ if (query?.search) params.set("search", query.search);
1771
+ if (query?.platform) params.set("platform", query.platform);
1772
+ if (query?.scope) params.set("scope", query.scope);
1773
+ if (typeof query?.limit === "number")
1774
+ params.set("limit", String(query.limit));
1775
+ if (typeof query?.offset === "number")
1776
+ params.set("offset", String(query.offset));
1777
+ const qs = params.toString();
1778
+ const response = await this.fetch<{ data: RelationshipsGraphSnapshot }>(
1779
+ `/api/relationships/graph${qs ? `?${qs}` : ""}`,
1780
+ );
1781
+ return response.data;
1782
+ };
1783
+
1784
+ ElizaClient.prototype.getRelationshipsPeople = async function (
1785
+ this: ElizaClient,
1786
+ query,
1787
+ ) {
1788
+ const params = new URLSearchParams();
1789
+ if (query?.search) params.set("search", query.search);
1790
+ if (query?.platform) params.set("platform", query.platform);
1791
+ if (query?.scope) params.set("scope", query.scope);
1792
+ if (typeof query?.limit === "number")
1793
+ params.set("limit", String(query.limit));
1794
+ if (typeof query?.offset === "number")
1795
+ params.set("offset", String(query.offset));
1796
+ const qs = params.toString();
1797
+ const response = await this.fetch<{
1798
+ data: RelationshipsPersonSummary[];
1799
+ stats: RelationshipsGraphStats;
1800
+ }>(`/api/relationships/people${qs ? `?${qs}` : ""}`);
1801
+ return {
1802
+ people: response.data,
1803
+ stats: response.stats,
1804
+ };
1805
+ };
1806
+
1807
+ ElizaClient.prototype.getRelationshipsPerson = async function (
1808
+ this: ElizaClient,
1809
+ id,
1810
+ ) {
1811
+ const response = await this.fetch<{ data: RelationshipsPersonDetail }>(
1812
+ `/api/relationships/people/${encodeURIComponent(id)}`,
1813
+ );
1814
+ return response.data;
1815
+ };
1816
+
1817
+ ElizaClient.prototype.getRelationshipsActivity = async function (
1818
+ this: ElizaClient,
1819
+ limit?,
1820
+ offset?,
1821
+ ) {
1822
+ const params = new URLSearchParams();
1823
+ if (typeof limit === "number") params.set("limit", String(limit));
1824
+ if (typeof offset === "number") params.set("offset", String(offset));
1825
+ const qs = params.toString();
1826
+ return this.fetch<RelationshipsActivityResponse>(
1827
+ `/api/relationships/activity${qs ? `?${qs}` : ""}`,
1828
+ );
1829
+ };
1830
+
1831
+ ElizaClient.prototype.getRelationshipsCandidates = async function (
1832
+ this: ElizaClient,
1833
+ ) {
1834
+ const response = await this.fetch<{ data: RelationshipsMergeCandidate[] }>(
1835
+ "/api/relationships/candidates",
1836
+ );
1837
+ return response.data;
1838
+ };
1839
+
1840
+ ElizaClient.prototype.acceptRelationshipsCandidate = async function (
1841
+ this: ElizaClient,
1842
+ candidateId,
1843
+ ) {
1844
+ const response = await this.fetch<{ data: { id: string; status: string } }>(
1845
+ `/api/relationships/candidates/${encodeURIComponent(candidateId)}/accept`,
1846
+ { method: "POST" },
1847
+ );
1848
+ return response.data;
1849
+ };
1850
+
1851
+ ElizaClient.prototype.rejectRelationshipsCandidate = async function (
1852
+ this: ElizaClient,
1853
+ candidateId,
1854
+ ) {
1855
+ const response = await this.fetch<{ data: { id: string; status: string } }>(
1856
+ `/api/relationships/candidates/${encodeURIComponent(candidateId)}/reject`,
1857
+ { method: "POST" },
1858
+ );
1859
+ return response.data;
1860
+ };
1861
+
1862
+ ElizaClient.prototype.proposeRelationshipsLink = async function (
1863
+ this: ElizaClient,
1864
+ sourceEntityId,
1865
+ targetEntityId,
1866
+ evidence,
1867
+ ) {
1868
+ const response = await this.fetch<{ data: { id: string; status: string } }>(
1869
+ `/api/relationships/people/${encodeURIComponent(sourceEntityId)}/link`,
1870
+ {
1871
+ method: "POST",
1872
+ body: JSON.stringify({
1873
+ targetEntityId,
1874
+ evidence: evidence ?? {},
1875
+ }),
1876
+ headers: { "Content-Type": "application/json" },
1877
+ },
1878
+ );
1879
+ return response.data;
1880
+ };
1881
+
1882
+ ElizaClient.prototype.getCharacter = async function (this: ElizaClient) {
1883
+ return this.fetch("/api/character");
1884
+ };
1885
+
1886
+ ElizaClient.prototype.getRandomName = async function (this: ElizaClient) {
1887
+ return this.fetch("/api/character/random-name");
1888
+ };
1889
+
1890
+ ElizaClient.prototype.generateCharacterField = async function (
1891
+ this: ElizaClient,
1892
+ field,
1893
+ context,
1894
+ mode?,
1895
+ ) {
1896
+ return this.fetch("/api/character/generate", {
1897
+ method: "POST",
1898
+ body: JSON.stringify({ field, context, mode }),
1899
+ });
1900
+ };
1901
+
1902
+ ElizaClient.prototype.updateCharacter = async function (
1903
+ this: ElizaClient,
1904
+ character,
1905
+ ) {
1906
+ return this.fetch("/api/character", {
1907
+ method: "PUT",
1908
+ body: JSON.stringify(character),
1909
+ });
1910
+ };
1911
+
1912
+ ElizaClient.prototype.listCharacterHistory = async function (
1913
+ this: ElizaClient,
1914
+ options,
1915
+ ) {
1916
+ const params = new URLSearchParams();
1917
+ if (typeof options?.limit === "number") {
1918
+ params.set("limit", String(options.limit));
1919
+ }
1920
+ if (typeof options?.offset === "number") {
1921
+ params.set("offset", String(options.offset));
1922
+ }
1923
+ const qs = params.toString();
1924
+ return this.fetch(`/api/character/history${qs ? `?${qs}` : ""}`);
1925
+ };
1926
+
1927
+ ElizaClient.prototype.listExperiences = async function (
1928
+ this: ElizaClient,
1929
+ options,
1930
+ ) {
1931
+ const params = new URLSearchParams();
1932
+ const appendMulti = (key: string, value?: string | string[]) => {
1933
+ if (Array.isArray(value)) {
1934
+ value
1935
+ .map((item) => item.trim())
1936
+ .filter(Boolean)
1937
+ .forEach((item) => {
1938
+ params.append(key, item);
1939
+ });
1940
+ return;
1941
+ }
1942
+ if (typeof value === "string" && value.trim()) {
1943
+ params.append(key, value.trim());
1944
+ }
1945
+ };
1946
+
1947
+ if (typeof options?.limit === "number") {
1948
+ params.set("limit", String(options.limit));
1949
+ }
1950
+ if (typeof options?.offset === "number") {
1951
+ params.set("offset", String(options.offset));
1952
+ }
1953
+ appendMulti("type", options?.type);
1954
+ appendMulti("outcome", options?.outcome);
1955
+ appendMulti("domain", options?.domain);
1956
+ options?.tags
1957
+ ?.map((tag) => tag.trim())
1958
+ .filter(Boolean)
1959
+ .forEach((tag) => {
1960
+ params.append("tag", tag);
1961
+ });
1962
+ const qs = params.toString();
1963
+ const response = await this.fetch<{
1964
+ data: ExperienceRecord[];
1965
+ total: number;
1966
+ }>(`/api/character/experiences${qs ? `?${qs}` : ""}`);
1967
+ return {
1968
+ experiences: response.data,
1969
+ total: response.total,
1970
+ };
1971
+ };
1972
+
1973
+ ElizaClient.prototype.getExperience = async function (this: ElizaClient, id) {
1974
+ const response = await this.fetch<{ data: ExperienceRecord }>(
1975
+ `/api/character/experiences/${encodeURIComponent(id)}`,
1976
+ );
1977
+ return { experience: response.data };
1978
+ };
1979
+
1980
+ ElizaClient.prototype.updateExperience = async function (
1981
+ this: ElizaClient,
1982
+ id,
1983
+ data,
1984
+ ) {
1985
+ const response = await this.fetch<{ data: ExperienceRecord }>(
1986
+ `/api/character/experiences/${encodeURIComponent(id)}`,
1987
+ {
1988
+ method: "PATCH",
1989
+ body: JSON.stringify(data),
1990
+ },
1991
+ );
1992
+ return { experience: response.data };
1993
+ };
1994
+
1995
+ ElizaClient.prototype.deleteExperience = async function (
1996
+ this: ElizaClient,
1997
+ id,
1998
+ ) {
1999
+ return this.fetch(`/api/character/experiences/${encodeURIComponent(id)}`, {
2000
+ method: "DELETE",
2001
+ });
2002
+ };
2003
+
2004
+ ElizaClient.prototype.getUpdateStatus = async function (
2005
+ this: ElizaClient,
2006
+ force = false,
2007
+ ) {
2008
+ return this.fetch(`/api/update/status${force ? "?force=true" : ""}`);
2009
+ };
2010
+
2011
+ ElizaClient.prototype.setUpdateChannel = async function (
2012
+ this: ElizaClient,
2013
+ channel,
2014
+ ) {
2015
+ return this.fetch("/api/update/channel", {
2016
+ method: "PUT",
2017
+ body: JSON.stringify({ channel }),
2018
+ });
2019
+ };
2020
+
2021
+ ElizaClient.prototype.getAgentAutomationMode = async function (
2022
+ this: ElizaClient,
2023
+ ) {
2024
+ return this.fetch("/api/permissions/automation-mode");
2025
+ };
2026
+
2027
+ ElizaClient.prototype.setAgentAutomationMode = async function (
2028
+ this: ElizaClient,
2029
+ mode,
2030
+ ) {
2031
+ return this.fetch("/api/permissions/automation-mode", {
2032
+ method: "PUT",
2033
+ body: JSON.stringify({ mode }),
2034
+ });
2035
+ };
2036
+
2037
+ ElizaClient.prototype.getTradePermissionMode = async function (
2038
+ this: ElizaClient,
2039
+ ) {
2040
+ return this.fetch("/api/permissions/trade-mode");
2041
+ };
2042
+
2043
+ ElizaClient.prototype.setTradePermissionMode = async function (
2044
+ this: ElizaClient,
2045
+ mode,
2046
+ ) {
2047
+ return this.fetch("/api/permissions/trade-mode", {
2048
+ method: "PUT",
2049
+ body: JSON.stringify({ mode }),
2050
+ });
2051
+ };
2052
+
2053
+ ElizaClient.prototype.getPermissions = async function (this: ElizaClient) {
2054
+ const permissions = await this.fetch<AllPermissionsState>("/api/permissions");
2055
+ const plugin = getNativeWebsiteBlockerPluginIfAvailable();
2056
+ if (!plugin) {
2057
+ return permissions;
2058
+ }
2059
+
2060
+ const permission = mapWebsiteBlockerStatusToPermission(
2061
+ await plugin.getStatus(),
2062
+ );
2063
+ return {
2064
+ ...permissions,
2065
+ [WEBSITE_BLOCKING_PERMISSION_ID]: permission,
2066
+ };
2067
+ };
2068
+
2069
+ ElizaClient.prototype.getPermission = async function (this: ElizaClient, id) {
2070
+ if (id === WEBSITE_BLOCKING_PERMISSION_ID) {
2071
+ const plugin = getNativeWebsiteBlockerPluginIfAvailable();
2072
+ if (plugin) {
2073
+ return mapWebsiteBlockerStatusToPermission(await plugin.getStatus());
2074
+ }
2075
+ }
2076
+ return this.fetch(`/api/permissions/${id}`);
2077
+ };
2078
+
2079
+ ElizaClient.prototype.requestPermission = async function (
2080
+ this: ElizaClient,
2081
+ id,
2082
+ ) {
2083
+ if (id === WEBSITE_BLOCKING_PERMISSION_ID) {
2084
+ const plugin = getNativeWebsiteBlockerPluginIfAvailable();
2085
+ if (plugin) {
2086
+ return mapWebsiteBlockerPermissionResult(
2087
+ await plugin.requestPermissions(),
2088
+ );
2089
+ }
2090
+ }
2091
+ return this.fetch(`/api/permissions/${id}/request`, { method: "POST" });
2092
+ };
2093
+
2094
+ ElizaClient.prototype.openPermissionSettings = async function (
2095
+ this: ElizaClient,
2096
+ id,
2097
+ ) {
2098
+ if (id === WEBSITE_BLOCKING_PERMISSION_ID) {
2099
+ const plugin = getNativeWebsiteBlockerPluginIfAvailable();
2100
+ if (plugin) {
2101
+ await plugin.openSettings();
2102
+ return;
2103
+ }
2104
+ }
2105
+ await this.fetch(`/api/permissions/${id}/open-settings`, {
2106
+ method: "POST",
2107
+ });
2108
+ };
2109
+
2110
+ ElizaClient.prototype.refreshPermissions = async function (this: ElizaClient) {
2111
+ const permissions = await this.fetch<AllPermissionsState>(
2112
+ "/api/permissions/refresh",
2113
+ {
2114
+ method: "POST",
2115
+ },
2116
+ );
2117
+ const plugin = getNativeWebsiteBlockerPluginIfAvailable();
2118
+ if (!plugin) {
2119
+ return permissions;
2120
+ }
2121
+
2122
+ const permission = mapWebsiteBlockerStatusToPermission(
2123
+ await plugin.getStatus(),
2124
+ );
2125
+ return {
2126
+ ...permissions,
2127
+ [WEBSITE_BLOCKING_PERMISSION_ID]: permission,
2128
+ };
2129
+ };
2130
+
2131
+ ElizaClient.prototype.setShellEnabled = async function (
2132
+ this: ElizaClient,
2133
+ enabled,
2134
+ ) {
2135
+ return this.fetch("/api/permissions/shell", {
2136
+ method: "PUT",
2137
+ body: JSON.stringify({ enabled }),
2138
+ });
2139
+ };
2140
+
2141
+ ElizaClient.prototype.isShellEnabled = async function (this: ElizaClient) {
2142
+ const result = await this.fetch<{ enabled: boolean }>(
2143
+ "/api/permissions/shell",
2144
+ );
2145
+ return result.enabled;
2146
+ };
2147
+
2148
+ ElizaClient.prototype.getWebsiteBlockerStatus = async function (
2149
+ this: ElizaClient,
2150
+ ) {
2151
+ const plugin = getNativeWebsiteBlockerPluginIfAvailable();
2152
+ if (plugin) {
2153
+ return await plugin.getStatus();
2154
+ }
2155
+ return this.fetch("/api/website-blocker");
2156
+ };
2157
+
2158
+ ElizaClient.prototype.startWebsiteBlock = async function (
2159
+ this: ElizaClient,
2160
+ options,
2161
+ ) {
2162
+ const plugin = getNativeWebsiteBlockerPluginIfAvailable();
2163
+ if (plugin) {
2164
+ return await plugin.startBlock(options);
2165
+ }
2166
+ return this.fetch("/api/website-blocker", {
2167
+ method: "PUT",
2168
+ body: JSON.stringify(options),
2169
+ });
2170
+ };
2171
+
2172
+ ElizaClient.prototype.stopWebsiteBlock = async function (this: ElizaClient) {
2173
+ const plugin = getNativeWebsiteBlockerPluginIfAvailable();
2174
+ if (plugin) {
2175
+ return await plugin.stopBlock();
2176
+ }
2177
+ return this.fetch("/api/website-blocker", {
2178
+ method: "DELETE",
2179
+ });
2180
+ };
2181
+
2182
+ ElizaClient.prototype.getAppBlockerStatus = async function (this: ElizaClient) {
2183
+ const plugin = getNativeAppBlockerPluginIfAvailable();
2184
+ if (plugin) {
2185
+ return await plugin.getStatus();
2186
+ }
2187
+ return {
2188
+ available: false,
2189
+ active: false,
2190
+ platform: "web",
2191
+ engine: "none",
2192
+ blockedCount: 0,
2193
+ blockedPackageNames: [],
2194
+ endsAt: null,
2195
+ permissionStatus: "not-applicable",
2196
+ reason: "App blocking is only available on iPhone and Android builds.",
2197
+ } satisfies AppBlockerStatusResult;
2198
+ };
2199
+
2200
+ ElizaClient.prototype.checkAppBlockerPermissions = async function (
2201
+ this: ElizaClient,
2202
+ ) {
2203
+ const plugin = getNativeAppBlockerPluginIfAvailable();
2204
+ if (plugin) {
2205
+ return await plugin.checkPermissions();
2206
+ }
2207
+ return {
2208
+ status: "not-applicable",
2209
+ canRequest: false,
2210
+ reason: "App blocking is only available on iPhone and Android builds.",
2211
+ } satisfies AppBlockerPermissionResult;
2212
+ };
2213
+
2214
+ ElizaClient.prototype.requestAppBlockerPermissions = async function (
2215
+ this: ElizaClient,
2216
+ ) {
2217
+ const plugin = getNativeAppBlockerPluginIfAvailable();
2218
+ if (plugin) {
2219
+ return await plugin.requestPermissions();
2220
+ }
2221
+ return {
2222
+ status: "not-applicable",
2223
+ canRequest: false,
2224
+ reason: "App blocking is only available on iPhone and Android builds.",
2225
+ } satisfies AppBlockerPermissionResult;
2226
+ };
2227
+
2228
+ ElizaClient.prototype.getInstalledAppsToBlock = async function (
2229
+ this: ElizaClient,
2230
+ ) {
2231
+ const plugin = getNativeAppBlockerPluginIfAvailable();
2232
+ if (plugin) {
2233
+ return await plugin.getInstalledApps();
2234
+ }
2235
+ return { apps: [] as AppBlockerInstalledApp[] };
2236
+ };
2237
+
2238
+ ElizaClient.prototype.selectAppBlockerApps = async function (
2239
+ this: ElizaClient,
2240
+ ) {
2241
+ const plugin = getNativeAppBlockerPluginIfAvailable();
2242
+ if (plugin) {
2243
+ return await plugin.selectApps();
2244
+ }
2245
+ return {
2246
+ apps: [] as AppBlockerInstalledApp[],
2247
+ cancelled: true,
2248
+ };
2249
+ };
2250
+
2251
+ ElizaClient.prototype.startAppBlock = async function (
2252
+ this: ElizaClient,
2253
+ options,
2254
+ ) {
2255
+ const plugin = getNativeAppBlockerPluginIfAvailable();
2256
+ if (plugin) {
2257
+ return await plugin.blockApps(options);
2258
+ }
2259
+ return {
2260
+ success: false,
2261
+ endsAt: null,
2262
+ blockedCount: 0,
2263
+ error: "App blocking is only available on iPhone and Android builds.",
2264
+ };
2265
+ };
2266
+
2267
+ ElizaClient.prototype.stopAppBlock = async function (this: ElizaClient) {
2268
+ const plugin = getNativeAppBlockerPluginIfAvailable();
2269
+ if (plugin) {
2270
+ return await plugin.unblockApps();
2271
+ }
2272
+ return {
2273
+ success: false,
2274
+ error: "App blocking is only available on iPhone and Android builds.",
2275
+ };
2276
+ };
2277
+
2278
+ ElizaClient.prototype.getCodingAgentStatus = async function (
2279
+ this: ElizaClient,
2280
+ ) {
2281
+ try {
2282
+ const status = await this.fetch<CodingAgentStatus>(
2283
+ "/api/coding-agents/coordinator/status",
2284
+ );
2285
+ if (
2286
+ status &&
2287
+ (!status.tasks || status.tasks.length === 0) &&
2288
+ Array.isArray(status.taskThreads) &&
2289
+ status.taskThreads.length > 0
2290
+ ) {
2291
+ status.tasks = mapTaskThreadsToCodingAgentSessions(
2292
+ status.taskThreads,
2293
+ ).filter((task) => !TERMINAL_STATUSES.has(task.status));
2294
+ status.taskCount = status.tasks.length;
2295
+ }
2296
+ if (status && !status.tasks) {
2297
+ // Only fall back to the raw PTY session list when the coordinator
2298
+ // didn't return a tasks array at all (null/undefined). An empty
2299
+ // array means "no tasks" — no need to hit /api/coding-agents which
2300
+ // may not have a handler and would hang until timeout.
2301
+ try {
2302
+ const ptySessions =
2303
+ await this.fetch<RawPtySession[]>("/api/coding-agents");
2304
+ if (Array.isArray(ptySessions) && ptySessions.length > 0) {
2305
+ status.tasks = mapPtySessionsToCodingAgentSessions(ptySessions);
2306
+ status.taskCount = status.tasks.length;
2307
+ }
2308
+ } catch {
2309
+ // /api/coding-agents may not exist — ignore
2310
+ }
2311
+ }
2312
+ return status;
2313
+ } catch {
2314
+ return null;
2315
+ }
2316
+ };
2317
+
2318
+ ElizaClient.prototype.listCodingAgentTaskThreads = function (
2319
+ this: ElizaClient,
2320
+ options,
2321
+ ) {
2322
+ const params = new URLSearchParams();
2323
+ if (options?.includeArchived) params.set("includeArchived", "true");
2324
+ if (options?.status) params.set("status", options.status);
2325
+ if (options?.search) params.set("search", options.search);
2326
+ if (typeof options?.limit === "number" && options.limit > 0) {
2327
+ params.set("limit", String(options.limit));
2328
+ }
2329
+ const query = params.toString();
2330
+ return this.fetch<CodingAgentTaskThread[]>(
2331
+ `/api/coding-agents/coordinator/threads${query ? `?${query}` : ""}`,
2332
+ );
2333
+ };
2334
+
2335
+ ElizaClient.prototype.getCodingAgentTaskThread = function (
2336
+ this: ElizaClient,
2337
+ threadId,
2338
+ ) {
2339
+ return this.fetch<CodingAgentTaskThreadDetail>(
2340
+ `/api/coding-agents/coordinator/threads/${encodeURIComponent(threadId)}`,
2341
+ );
2342
+ };
2343
+
2344
+ ElizaClient.prototype.archiveCodingAgentTaskThread = async function (
2345
+ this: ElizaClient,
2346
+ threadId,
2347
+ ) {
2348
+ await this.fetch(
2349
+ `/api/coding-agents/coordinator/threads/${encodeURIComponent(threadId)}/archive`,
2350
+ { method: "POST" },
2351
+ );
2352
+ return true;
2353
+ };
2354
+
2355
+ ElizaClient.prototype.reopenCodingAgentTaskThread = async function (
2356
+ this: ElizaClient,
2357
+ threadId,
2358
+ ) {
2359
+ await this.fetch(
2360
+ `/api/coding-agents/coordinator/threads/${encodeURIComponent(threadId)}/reopen`,
2361
+ { method: "POST" },
2362
+ );
2363
+ return true;
2364
+ };
2365
+
2366
+ ElizaClient.prototype.stopCodingAgent = async function (
2367
+ this: ElizaClient,
2368
+ sessionId,
2369
+ ) {
2370
+ try {
2371
+ await this.fetch(
2372
+ `/api/coding-agents/${encodeURIComponent(sessionId)}/stop`,
2373
+ { method: "POST" },
2374
+ );
2375
+ return true;
2376
+ } catch {
2377
+ return false;
2378
+ }
2379
+ };
2380
+
2381
+ ElizaClient.prototype.listCodingAgentScratchWorkspaces = async function (
2382
+ this: ElizaClient,
2383
+ ) {
2384
+ try {
2385
+ return await this.fetch<CodingAgentScratchWorkspace[]>(
2386
+ "/api/coding-agents/scratch",
2387
+ );
2388
+ } catch (err) {
2389
+ console.warn(
2390
+ "[api-client] Failed to list coding agent scratch workspaces:",
2391
+ err,
2392
+ );
2393
+ return [];
2394
+ }
2395
+ };
2396
+
2397
+ ElizaClient.prototype.keepCodingAgentScratchWorkspace = async function (
2398
+ this: ElizaClient,
2399
+ sessionId,
2400
+ ) {
2401
+ try {
2402
+ await this.fetch(
2403
+ `/api/coding-agents/${encodeURIComponent(sessionId)}/scratch/keep`,
2404
+ { method: "POST" },
2405
+ );
2406
+ return true;
2407
+ } catch {
2408
+ return false;
2409
+ }
2410
+ };
2411
+
2412
+ ElizaClient.prototype.deleteCodingAgentScratchWorkspace = async function (
2413
+ this: ElizaClient,
2414
+ sessionId,
2415
+ ) {
2416
+ try {
2417
+ await this.fetch(
2418
+ `/api/coding-agents/${encodeURIComponent(sessionId)}/scratch/delete`,
2419
+ { method: "POST" },
2420
+ );
2421
+ return true;
2422
+ } catch {
2423
+ return false;
2424
+ }
2425
+ };
2426
+
2427
+ ElizaClient.prototype.promoteCodingAgentScratchWorkspace = async function (
2428
+ this: ElizaClient,
2429
+ sessionId,
2430
+ name?,
2431
+ ) {
2432
+ try {
2433
+ const response = await this.fetch<{
2434
+ success: boolean;
2435
+ scratch?: CodingAgentScratchWorkspace;
2436
+ }>(`/api/coding-agents/${encodeURIComponent(sessionId)}/scratch/promote`, {
2437
+ method: "POST",
2438
+ body: JSON.stringify(name ? { name } : {}),
2439
+ });
2440
+ return response.scratch ?? null;
2441
+ } catch {
2442
+ return null;
2443
+ }
2444
+ };
2445
+
2446
+ ElizaClient.prototype.spawnShellSession = async function (
2447
+ this: ElizaClient,
2448
+ workdir?: string,
2449
+ ) {
2450
+ const res = await this.fetch<{ sessionId: string }>(
2451
+ "/api/coding-agents/spawn",
2452
+ {
2453
+ method: "POST",
2454
+ body: JSON.stringify({
2455
+ agentType: "shell",
2456
+ ...(workdir ? { workdir } : {}),
2457
+ }),
2458
+ },
2459
+ );
2460
+ return { sessionId: res.sessionId };
2461
+ };
2462
+
2463
+ ElizaClient.prototype.subscribePtyOutput = function (
2464
+ this: ElizaClient,
2465
+ sessionId,
2466
+ ) {
2467
+ this.sendWsMessage({ type: "pty-subscribe", sessionId });
2468
+ };
2469
+
2470
+ ElizaClient.prototype.unsubscribePtyOutput = function (
2471
+ this: ElizaClient,
2472
+ sessionId,
2473
+ ) {
2474
+ this.sendWsMessage({ type: "pty-unsubscribe", sessionId });
2475
+ };
2476
+
2477
+ ElizaClient.prototype.sendPtyInput = function (
2478
+ this: ElizaClient,
2479
+ sessionId,
2480
+ data,
2481
+ ) {
2482
+ this.sendWsMessage({ type: "pty-input", sessionId, data });
2483
+ };
2484
+
2485
+ ElizaClient.prototype.resizePty = function (
2486
+ this: ElizaClient,
2487
+ sessionId,
2488
+ cols,
2489
+ rows,
2490
+ ) {
2491
+ this.sendWsMessage({ type: "pty-resize", sessionId, cols, rows });
2492
+ };
2493
+
2494
+ ElizaClient.prototype.getPtyBufferedOutput = async function (
2495
+ this: ElizaClient,
2496
+ sessionId,
2497
+ ) {
2498
+ try {
2499
+ const res = await this.fetch<{ output: string }>(
2500
+ `/api/coding-agents/${encodeURIComponent(sessionId)}/buffered-output`,
2501
+ );
2502
+ return res.output ?? "";
2503
+ } catch {
2504
+ return "";
2505
+ }
2506
+ };
2507
+
2508
+ ElizaClient.prototype.streamGoLive = async function (this: ElizaClient) {
2509
+ return this.fetch("/api/stream/live", { method: "POST" });
2510
+ };
2511
+
2512
+ ElizaClient.prototype.streamGoOffline = async function (this: ElizaClient) {
2513
+ return this.fetch("/api/stream/offline", { method: "POST" });
2514
+ };
2515
+
2516
+ ElizaClient.prototype.streamStatus = async function (this: ElizaClient) {
2517
+ return this.fetch("/api/stream/status");
2518
+ };
2519
+
2520
+ ElizaClient.prototype.getStreamingDestinations = async function (
2521
+ this: ElizaClient,
2522
+ ) {
2523
+ return this.fetch("/api/streaming/destinations");
2524
+ };
2525
+
2526
+ ElizaClient.prototype.setActiveDestination = async function (
2527
+ this: ElizaClient,
2528
+ destinationId,
2529
+ ) {
2530
+ return this.fetch("/api/streaming/destination", {
2531
+ method: "POST",
2532
+ body: JSON.stringify({ destinationId }),
2533
+ });
2534
+ };
2535
+
2536
+ ElizaClient.prototype.setStreamVolume = async function (
2537
+ this: ElizaClient,
2538
+ volume,
2539
+ ) {
2540
+ return this.fetch("/api/stream/volume", {
2541
+ method: "POST",
2542
+ body: JSON.stringify({ volume }),
2543
+ });
2544
+ };
2545
+
2546
+ ElizaClient.prototype.muteStream = async function (this: ElizaClient) {
2547
+ return this.fetch("/api/stream/mute", { method: "POST" });
2548
+ };
2549
+
2550
+ ElizaClient.prototype.unmuteStream = async function (this: ElizaClient) {
2551
+ return this.fetch("/api/stream/unmute", { method: "POST" });
2552
+ };
2553
+
2554
+ ElizaClient.prototype.getStreamVoice = async function (this: ElizaClient) {
2555
+ return this.fetch("/api/stream/voice");
2556
+ };
2557
+
2558
+ ElizaClient.prototype.saveStreamVoice = async function (
2559
+ this: ElizaClient,
2560
+ settings,
2561
+ ) {
2562
+ return this.fetch("/api/stream/voice", {
2563
+ method: "POST",
2564
+ body: JSON.stringify(settings),
2565
+ });
2566
+ };
2567
+
2568
+ ElizaClient.prototype.streamVoiceSpeak = async function (
2569
+ this: ElizaClient,
2570
+ text,
2571
+ ) {
2572
+ return this.fetch("/api/stream/voice/speak", {
2573
+ method: "POST",
2574
+ body: JSON.stringify({ text }),
2575
+ });
2576
+ };
2577
+
2578
+ ElizaClient.prototype.getOverlayLayout = async function (
2579
+ this: ElizaClient,
2580
+ destinationId?,
2581
+ ) {
2582
+ const qs = destinationId
2583
+ ? `?destination=${encodeURIComponent(destinationId)}`
2584
+ : "";
2585
+ return this.fetch(`/api/stream/overlay-layout${qs}`);
2586
+ };
2587
+
2588
+ ElizaClient.prototype.saveOverlayLayout = async function (
2589
+ this: ElizaClient,
2590
+ layout,
2591
+ destinationId?,
2592
+ ) {
2593
+ const qs = destinationId
2594
+ ? `?destination=${encodeURIComponent(destinationId)}`
2595
+ : "";
2596
+ return this.fetch(`/api/stream/overlay-layout${qs}`, {
2597
+ method: "POST",
2598
+ body: JSON.stringify({ layout }),
2599
+ });
2600
+ };
2601
+
2602
+ ElizaClient.prototype.getStreamSource = async function (this: ElizaClient) {
2603
+ return this.fetch("/api/stream/source");
2604
+ };
2605
+
2606
+ ElizaClient.prototype.setStreamSource = async function (
2607
+ this: ElizaClient,
2608
+ sourceType,
2609
+ customUrl?,
2610
+ ) {
2611
+ return this.fetch("/api/stream/source", {
2612
+ method: "POST",
2613
+ body: JSON.stringify({ sourceType, customUrl }),
2614
+ });
2615
+ };
2616
+
2617
+ ElizaClient.prototype.getStreamSettings = async function (this: ElizaClient) {
2618
+ return this.fetch("/api/stream/settings");
2619
+ };
2620
+
2621
+ ElizaClient.prototype.saveStreamSettings = async function (
2622
+ this: ElizaClient,
2623
+ settings,
2624
+ ) {
2625
+ return this.fetch("/api/stream/settings", {
2626
+ method: "POST",
2627
+ body: JSON.stringify({ settings }),
2628
+ });
2629
+ };
2630
+
2631
+ // ---------------------------------------------------------------------------
2632
+ // Multi-account routes (WS3)
2633
+ // ---------------------------------------------------------------------------
2634
+
2635
+ ElizaClient.prototype.listAccounts = async function (this: ElizaClient) {
2636
+ return this.fetch<AccountsListResponse>("/api/accounts");
2637
+ };
2638
+
2639
+ ElizaClient.prototype.createApiKeyAccount = async function (
2640
+ this: ElizaClient,
2641
+ providerId,
2642
+ body,
2643
+ ) {
2644
+ return this.fetch<LinkedAccountConfig>(
2645
+ `/api/accounts/${encodeURIComponent(providerId)}`,
2646
+ {
2647
+ method: "POST",
2648
+ body: JSON.stringify({ source: "api-key", ...body }),
2649
+ },
2650
+ );
2651
+ };
2652
+
2653
+ ElizaClient.prototype.patchAccount = async function (
2654
+ this: ElizaClient,
2655
+ providerId,
2656
+ accountId,
2657
+ body,
2658
+ ) {
2659
+ return this.fetch<LinkedAccountConfig>(
2660
+ `/api/accounts/${encodeURIComponent(providerId)}/${encodeURIComponent(accountId)}`,
2661
+ {
2662
+ method: "PATCH",
2663
+ body: JSON.stringify(body),
2664
+ },
2665
+ );
2666
+ };
2667
+
2668
+ ElizaClient.prototype.deleteAccount = async function (
2669
+ this: ElizaClient,
2670
+ providerId,
2671
+ accountId,
2672
+ ) {
2673
+ return this.fetch<{ deleted: boolean }>(
2674
+ `/api/accounts/${encodeURIComponent(providerId)}/${encodeURIComponent(accountId)}`,
2675
+ { method: "DELETE" },
2676
+ );
2677
+ };
2678
+
2679
+ ElizaClient.prototype.testAccount = async function (
2680
+ this: ElizaClient,
2681
+ providerId,
2682
+ accountId,
2683
+ ) {
2684
+ return this.fetch<AccountTestResult>(
2685
+ `/api/accounts/${encodeURIComponent(providerId)}/${encodeURIComponent(accountId)}/test`,
2686
+ { method: "POST" },
2687
+ );
2688
+ };
2689
+
2690
+ ElizaClient.prototype.refreshAccountUsage = async function (
2691
+ this: ElizaClient,
2692
+ providerId,
2693
+ accountId,
2694
+ ) {
2695
+ return this.fetch<AccountRefreshUsageResult>(
2696
+ `/api/accounts/${encodeURIComponent(providerId)}/${encodeURIComponent(accountId)}/refresh-usage`,
2697
+ { method: "POST" },
2698
+ );
2699
+ };
2700
+
2701
+ ElizaClient.prototype.startAccountOAuth = async function (
2702
+ this: ElizaClient,
2703
+ providerId,
2704
+ body,
2705
+ ) {
2706
+ return this.fetch<AccountOAuthStartResult>(
2707
+ `/api/accounts/${encodeURIComponent(providerId)}/oauth/start`,
2708
+ {
2709
+ method: "POST",
2710
+ body: JSON.stringify(body),
2711
+ },
2712
+ );
2713
+ };
2714
+
2715
+ ElizaClient.prototype.submitAccountOAuthCode = async function (
2716
+ this: ElizaClient,
2717
+ providerId,
2718
+ body,
2719
+ ) {
2720
+ return this.fetch<{ accepted: boolean }>(
2721
+ `/api/accounts/${encodeURIComponent(providerId)}/oauth/submit-code`,
2722
+ {
2723
+ method: "POST",
2724
+ body: JSON.stringify(body),
2725
+ },
2726
+ );
2727
+ };
2728
+
2729
+ ElizaClient.prototype.cancelAccountOAuth = async function (
2730
+ this: ElizaClient,
2731
+ providerId,
2732
+ body,
2733
+ ) {
2734
+ return this.fetch<{ cancelled: boolean }>(
2735
+ `/api/accounts/${encodeURIComponent(providerId)}/oauth/cancel`,
2736
+ {
2737
+ method: "POST",
2738
+ body: JSON.stringify(body),
2739
+ },
2740
+ );
2741
+ };
2742
+
2743
+ ElizaClient.prototype.patchProviderStrategy = async function (
2744
+ this: ElizaClient,
2745
+ providerId,
2746
+ body,
2747
+ ) {
2748
+ return this.fetch<{
2749
+ providerId: LinkedAccountProviderId;
2750
+ strategy: AccountStrategy;
2751
+ }>(`/api/providers/${encodeURIComponent(providerId)}/strategy`, {
2752
+ method: "PATCH",
2753
+ body: JSON.stringify(body),
2754
+ });
2755
+ };