@m1kad0/hannah-proto 4.5.0 → 4.6.1

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.
Files changed (53) hide show
  1. package/README.md +21 -0
  2. package/dist/compat_interceptor.js +6 -6
  3. package/dist/compat_versions.js +176 -88
  4. package/dist/descriptor.binpb +0 -0
  5. package/dist/index.d.ts +1 -0
  6. package/dist/index.js +2 -1
  7. package/dist/v1/activity_log.d.ts +60 -0
  8. package/dist/v1/activity_log.js +453 -0
  9. package/dist/v1/agent.d.ts +433 -0
  10. package/dist/v1/agent.js +2527 -0
  11. package/dist/v1/automation.d.ts +54 -0
  12. package/dist/v1/automation.js +303 -0
  13. package/dist/v1/car_state.d.ts +72 -0
  14. package/dist/v1/car_state.js +516 -0
  15. package/dist/v1/channel.d.ts +102 -0
  16. package/dist/v1/channel.js +587 -0
  17. package/dist/v1/control.d.ts +383 -0
  18. package/dist/v1/control.js +3879 -0
  19. package/dist/v1/device_control_menu.d.ts +88 -0
  20. package/dist/v1/device_control_menu.js +629 -0
  21. package/dist/v1/event_stream.d.ts +63 -0
  22. package/dist/v1/event_stream.js +494 -0
  23. package/dist/v1/hannah.d.ts +1644 -0
  24. package/dist/v1/hannah.js +968 -0
  25. package/dist/v1/index.d.ts +22 -0
  26. package/dist/v1/index.js +58 -0
  27. package/dist/v1/infrastructure.d.ts +98 -0
  28. package/dist/v1/infrastructure.js +652 -0
  29. package/dist/v1/logging.d.ts +189 -0
  30. package/dist/v1/logging.js +775 -0
  31. package/dist/v1/messages.d.ts +56 -0
  32. package/dist/v1/messages.js +398 -0
  33. package/dist/v1/satellite.d.ts +90 -0
  34. package/dist/v1/satellite.js +637 -0
  35. package/dist/v1/satellite_provisioning.d.ts +33 -0
  36. package/dist/v1/satellite_provisioning.js +84 -0
  37. package/dist/v1/satellite_proxy.d.ts +100 -0
  38. package/dist/v1/satellite_proxy.js +546 -0
  39. package/dist/v1/shared.d.ts +54 -0
  40. package/dist/v1/shared.js +249 -0
  41. package/dist/v1/speaker_enrollment.d.ts +44 -0
  42. package/dist/v1/speaker_enrollment.js +157 -0
  43. package/dist/v1/timer_admin.d.ts +42 -0
  44. package/dist/v1/timer_admin.js +273 -0
  45. package/dist/v1/timer_service.d.ts +133 -0
  46. package/dist/v1/timer_service.js +945 -0
  47. package/dist/v1/user_registry.d.ts +187 -0
  48. package/dist/v1/user_registry.js +1612 -0
  49. package/dist/v1/wakeword_capture.d.ts +101 -0
  50. package/dist/v1/wakeword_capture.js +611 -0
  51. package/dist/v1/weather.d.ts +81 -0
  52. package/dist/v1/weather.js +366 -0
  53. package/package.json +1 -1
@@ -0,0 +1,1644 @@
1
+ import { type CallOptions, type ChannelCredentials, Client, type ClientDuplexStream, type ClientOptions, type ClientReadableStream, type ClientUnaryCall, type handleBidiStreamingCall, type handleServerStreamingCall, type handleUnaryCall, type Metadata, type ServiceError, type UntypedServiceImplementation } from "@grpc/grpc-js";
2
+ import { ActivityAudioChunk, ListActivityLogRequest, ListActivityLogResponse, StreamActivityAudioRequest } from "./activity_log";
3
+ import { AgentCommand, AgentMessage, AgentNotification } from "./agent";
4
+ import { AutomationCommand, AutomationMessage } from "./automation";
5
+ import { CarStateResponse, GetAllCarStatesResponse } from "./car_state";
6
+ import { ChannelCommand, ChannelMessage, GetChannelsResponse } from "./channel";
7
+ import { AnnounceRequest, CreateAlarmRequest, CreateAlarmResponse, CreateBleTagRequest, CreateBleTagResponse, CreateCarRequest, CreateCarResponse, CreateGroupRequest, CreatePresenceSourceRequest, CreatePresenceSourceResponse, CreateTriggerRequest, DeleteAlarmRequest, DeleteBleTagRequest, DeleteCarRequest, DeleteGroupRequest, DeletePresenceSourceRequest, DeleteTriggerRequest, GetAlarmsResponse, GetBleTagsResponse, GetCarsResponse, GetGroupsResponse, GetPresenceSourcesResponse, GetRoomsResponse, GetSettingsResponse, GetTriggersResponse, SetGroupSatellitesRequest, SubmitTextRequest, SubmitTextResponse, SubmitVoiceRequest, SubmitVoiceResponse, UpdateAlarmRequest, UpdateBleTagRequest, UpdateCarRequest, UpdateConfigRequest, UpdateGroupRequest, UpdatePresenceSourceRequest, UpdateTriggerRequest } from "./control";
8
+ import { ControlDeviceRequest, GetDevicesResponse } from "./device_control_menu";
9
+ import { EventFilter, HannahEvent, TriggerFirmwareUpdateRequest, TriggerSatelliteRestartRequest } from "./event_stream";
10
+ import { InfrastructureFilter, InfrastructureMessage, LogCollectorCommand, LogCollectorMessage } from "./infrastructure";
11
+ import { CreateMessageRequest, DeleteMessageRequest, ListMessagesRequest, ListMessagesResponse } from "./messages";
12
+ import { DeleteSatelliteRequest, GetSatellitesResponse, SetSatelliteDisplayNameRequest, SetSatelliteOwnerRequest, SetSatelliteRoomRequest, SetSatelliteSmalltalkFollowupRequest } from "./satellite";
13
+ import { ProvisionSatelliteRequest } from "./satellite_provisioning";
14
+ import { ProxyCommand, ProxyHeartbeat, SatelliteRegistration, SubmitSatelliteAudioRequest, SubmitSatelliteAudioResponse } from "./satellite_proxy";
15
+ import { Empty, StatusResponse } from "./shared";
16
+ import { EnrollVoiceprintRequest, StartVoiceEnrollmentRequest } from "./speaker_enrollment";
17
+ import { DeleteTimerRequest, GetTimersRequest, GetTimersResponse } from "./timer_admin";
18
+ import { TimerCommand, TimerMessage } from "./timer_service";
19
+ import { CreateLinkTokenRequest, CreateLinkTokenResponse, CreateUserRequest, CreateUserResponse, DeleteUserRequest, GetResidentsResponse, GetUserRequest, GetUsersRequest, GetUsersResponse, LinkAccountRequest, LoginRequest, SetAutomationRequest, SetSystemMessagesRequest, SetTrustLevelRequest, UnlinkAccountRequest, UpdateUserRequest, UserResponse } from "./user_registry";
20
+ import { CaptureCommand, CollectorMessage, SatelliteAudioChunk, SatelliteCaptureRequest, SatelliteCaptureResponse, TriggerPlinkRequest } from "./wakeword_capture";
21
+ export declare const protobufPackage = "hannah.v1";
22
+ export type HannahServiceService = typeof HannahServiceService;
23
+ export declare const HannahServiceService: {
24
+ /** --- User Registry --- */
25
+ readonly getUsers: {
26
+ readonly path: "/hannah.v1.HannahService/GetUsers";
27
+ readonly requestStream: false;
28
+ readonly responseStream: false;
29
+ readonly requestSerialize: (value: GetUsersRequest) => Buffer;
30
+ readonly requestDeserialize: (value: Buffer) => GetUsersRequest;
31
+ readonly responseSerialize: (value: GetUsersResponse) => Buffer;
32
+ readonly responseDeserialize: (value: Buffer) => GetUsersResponse;
33
+ };
34
+ readonly getUser: {
35
+ readonly path: "/hannah.v1.HannahService/GetUser";
36
+ readonly requestStream: false;
37
+ readonly responseStream: false;
38
+ readonly requestSerialize: (value: GetUserRequest) => Buffer;
39
+ readonly requestDeserialize: (value: Buffer) => GetUserRequest;
40
+ readonly responseSerialize: (value: UserResponse) => Buffer;
41
+ readonly responseDeserialize: (value: Buffer) => UserResponse;
42
+ };
43
+ readonly linkAccount: {
44
+ readonly path: "/hannah.v1.HannahService/LinkAccount";
45
+ readonly requestStream: false;
46
+ readonly responseStream: false;
47
+ readonly requestSerialize: (value: LinkAccountRequest) => Buffer;
48
+ readonly requestDeserialize: (value: Buffer) => LinkAccountRequest;
49
+ readonly responseSerialize: (value: StatusResponse) => Buffer;
50
+ readonly responseDeserialize: (value: Buffer) => StatusResponse;
51
+ };
52
+ readonly unlinkAccount: {
53
+ readonly path: "/hannah.v1.HannahService/UnlinkAccount";
54
+ readonly requestStream: false;
55
+ readonly responseStream: false;
56
+ readonly requestSerialize: (value: UnlinkAccountRequest) => Buffer;
57
+ readonly requestDeserialize: (value: Buffer) => UnlinkAccountRequest;
58
+ readonly responseSerialize: (value: StatusResponse) => Buffer;
59
+ readonly responseDeserialize: (value: Buffer) => StatusResponse;
60
+ };
61
+ /**
62
+ * One-time token for linking an account via the service's adapter (e.g. Telegram deep link).
63
+ * Redeemed by the adapter over ChannelConnect.
64
+ */
65
+ readonly createLinkToken: {
66
+ readonly path: "/hannah.v1.HannahService/CreateLinkToken";
67
+ readonly requestStream: false;
68
+ readonly responseStream: false;
69
+ readonly requestSerialize: (value: CreateLinkTokenRequest) => Buffer;
70
+ readonly requestDeserialize: (value: Buffer) => CreateLinkTokenRequest;
71
+ readonly responseSerialize: (value: CreateLinkTokenResponse) => Buffer;
72
+ readonly responseDeserialize: (value: Buffer) => CreateLinkTokenResponse;
73
+ };
74
+ readonly setTrustLevel: {
75
+ readonly path: "/hannah.v1.HannahService/SetTrustLevel";
76
+ readonly requestStream: false;
77
+ readonly responseStream: false;
78
+ readonly requestSerialize: (value: SetTrustLevelRequest) => Buffer;
79
+ readonly requestDeserialize: (value: Buffer) => SetTrustLevelRequest;
80
+ readonly responseSerialize: (value: StatusResponse) => Buffer;
81
+ readonly responseDeserialize: (value: Buffer) => StatusResponse;
82
+ };
83
+ readonly setSystemMessages: {
84
+ readonly path: "/hannah.v1.HannahService/SetSystemMessages";
85
+ readonly requestStream: false;
86
+ readonly responseStream: false;
87
+ readonly requestSerialize: (value: SetSystemMessagesRequest) => Buffer;
88
+ readonly requestDeserialize: (value: Buffer) => SetSystemMessagesRequest;
89
+ readonly responseSerialize: (value: StatusResponse) => Buffer;
90
+ readonly responseDeserialize: (value: Buffer) => StatusResponse;
91
+ };
92
+ /**
93
+ * Enable/disable an automation service (e.g. "telegram_autoresponder") for a user.
94
+ * Pushes a live update to any connected AutomationConnect stream registered for it.
95
+ */
96
+ readonly setAutomation: {
97
+ readonly path: "/hannah.v1.HannahService/SetAutomation";
98
+ readonly requestStream: false;
99
+ readonly responseStream: false;
100
+ readonly requestSerialize: (value: SetAutomationRequest) => Buffer;
101
+ readonly requestDeserialize: (value: Buffer) => SetAutomationRequest;
102
+ readonly responseSerialize: (value: StatusResponse) => Buffer;
103
+ readonly responseDeserialize: (value: Buffer) => StatusResponse;
104
+ };
105
+ readonly login: {
106
+ readonly path: "/hannah.v1.HannahService/Login";
107
+ readonly requestStream: false;
108
+ readonly responseStream: false;
109
+ readonly requestSerialize: (value: LoginRequest) => Buffer;
110
+ readonly requestDeserialize: (value: Buffer) => LoginRequest;
111
+ readonly responseSerialize: (value: UserResponse) => Buffer;
112
+ readonly responseDeserialize: (value: Buffer) => UserResponse;
113
+ };
114
+ /** --- User-Verwaltung (Admin-UI, #27 Phase 6) --- */
115
+ readonly createUser: {
116
+ readonly path: "/hannah.v1.HannahService/CreateUser";
117
+ readonly requestStream: false;
118
+ readonly responseStream: false;
119
+ readonly requestSerialize: (value: CreateUserRequest) => Buffer;
120
+ readonly requestDeserialize: (value: Buffer) => CreateUserRequest;
121
+ readonly responseSerialize: (value: CreateUserResponse) => Buffer;
122
+ readonly responseDeserialize: (value: Buffer) => CreateUserResponse;
123
+ };
124
+ readonly updateUser: {
125
+ readonly path: "/hannah.v1.HannahService/UpdateUser";
126
+ readonly requestStream: false;
127
+ readonly responseStream: false;
128
+ readonly requestSerialize: (value: UpdateUserRequest) => Buffer;
129
+ readonly requestDeserialize: (value: Buffer) => UpdateUserRequest;
130
+ readonly responseSerialize: (value: StatusResponse) => Buffer;
131
+ readonly responseDeserialize: (value: Buffer) => StatusResponse;
132
+ };
133
+ readonly deleteUser: {
134
+ readonly path: "/hannah.v1.HannahService/DeleteUser";
135
+ readonly requestStream: false;
136
+ readonly responseStream: false;
137
+ readonly requestSerialize: (value: DeleteUserRequest) => Buffer;
138
+ readonly requestDeserialize: (value: Buffer) => DeleteUserRequest;
139
+ readonly responseSerialize: (value: StatusResponse) => Buffer;
140
+ readonly responseDeserialize: (value: Buffer) => StatusResponse;
141
+ };
142
+ /** Residents (Roomies/Guests/Pets) aus dem ioBroker-Adapter-Cache — fürs "Resident verknüpfen"-Dropdown. */
143
+ readonly getResidents: {
144
+ readonly path: "/hannah.v1.HannahService/GetResidents";
145
+ readonly requestStream: false;
146
+ readonly responseStream: false;
147
+ readonly requestSerialize: (value: Empty) => Buffer;
148
+ readonly requestDeserialize: (value: Buffer) => Empty;
149
+ readonly responseSerialize: (value: GetResidentsResponse) => Buffer;
150
+ readonly responseDeserialize: (value: Buffer) => GetResidentsResponse;
151
+ };
152
+ /**
153
+ * --- Device Control Menu ---
154
+ * Returns all rooms and devices with current state — for building control menus.
155
+ */
156
+ readonly getDevices: {
157
+ readonly path: "/hannah.v1.HannahService/GetDevices";
158
+ readonly requestStream: false;
159
+ readonly responseStream: false;
160
+ readonly requestSerialize: (value: Empty) => Buffer;
161
+ readonly requestDeserialize: (value: Buffer) => Empty;
162
+ readonly responseSerialize: (value: GetDevicesResponse) => Buffer;
163
+ readonly responseDeserialize: (value: Buffer) => GetDevicesResponse;
164
+ };
165
+ /** Directly set a device state (bypasses NLU). Trust level check is done by the caller. */
166
+ readonly controlDevice: {
167
+ readonly path: "/hannah.v1.HannahService/ControlDevice";
168
+ readonly requestStream: false;
169
+ readonly responseStream: false;
170
+ readonly requestSerialize: (value: ControlDeviceRequest) => Buffer;
171
+ readonly requestDeserialize: (value: Buffer) => ControlDeviceRequest;
172
+ readonly responseSerialize: (value: StatusResponse) => Buffer;
173
+ readonly responseDeserialize: (value: Buffer) => StatusResponse;
174
+ };
175
+ /**
176
+ * --- Control ---
177
+ * Submit a plain-text command; Hannah processes it through NLU and returns the answer.
178
+ */
179
+ readonly submitText: {
180
+ readonly path: "/hannah.v1.HannahService/SubmitText";
181
+ readonly requestStream: false;
182
+ readonly responseStream: false;
183
+ readonly requestSerialize: (value: SubmitTextRequest) => Buffer;
184
+ readonly requestDeserialize: (value: Buffer) => SubmitTextRequest;
185
+ readonly responseSerialize: (value: SubmitTextResponse) => Buffer;
186
+ readonly responseDeserialize: (value: Buffer) => SubmitTextResponse;
187
+ };
188
+ /** Submit a voice message (OGG/Opus bytes); Hannah does STT → NLU → TTS and returns the result. */
189
+ readonly submitVoice: {
190
+ readonly path: "/hannah.v1.HannahService/SubmitVoice";
191
+ readonly requestStream: false;
192
+ readonly responseStream: false;
193
+ readonly requestSerialize: (value: SubmitVoiceRequest) => Buffer;
194
+ readonly requestDeserialize: (value: Buffer) => SubmitVoiceRequest;
195
+ readonly responseSerialize: (value: SubmitVoiceResponse) => Buffer;
196
+ readonly responseDeserialize: (value: Buffer) => SubmitVoiceResponse;
197
+ };
198
+ /** Send a TTS announcement to one satellite or all ("all"). */
199
+ readonly announce: {
200
+ readonly path: "/hannah.v1.HannahService/Announce";
201
+ readonly requestStream: false;
202
+ readonly responseStream: false;
203
+ readonly requestSerialize: (value: AnnounceRequest) => Buffer;
204
+ readonly requestDeserialize: (value: Buffer) => AnnounceRequest;
205
+ readonly responseSerialize: (value: StatusResponse) => Buffer;
206
+ readonly responseDeserialize: (value: Buffer) => StatusResponse;
207
+ };
208
+ /**
209
+ * Send a notification from ioBroker to Hannah. Returns ok=true when queued.
210
+ * direct=true: skip LLM reformulation. severity: "alert"|"notify"|"info".
211
+ */
212
+ readonly notify: {
213
+ readonly path: "/hannah.v1.HannahService/Notify";
214
+ readonly requestStream: false;
215
+ readonly responseStream: false;
216
+ readonly requestSerialize: (value: AgentNotification) => Buffer;
217
+ readonly requestDeserialize: (value: Buffer) => AgentNotification;
218
+ readonly responseSerialize: (value: StatusResponse) => Buffer;
219
+ readonly responseDeserialize: (value: Buffer) => StatusResponse;
220
+ };
221
+ /** List all known satellites (DB + live status merged). */
222
+ readonly getSatellites: {
223
+ readonly path: "/hannah.v1.HannahService/GetSatellites";
224
+ readonly requestStream: false;
225
+ readonly responseStream: false;
226
+ readonly requestSerialize: (value: Empty) => Buffer;
227
+ readonly requestDeserialize: (value: Buffer) => Empty;
228
+ readonly responseSerialize: (value: GetSatellitesResponse) => Buffer;
229
+ readonly responseDeserialize: (value: Buffer) => GetSatellitesResponse;
230
+ };
231
+ /** --- Satellites (Admin-UI, #27 Phase 2) --- */
232
+ readonly setSatelliteRoom: {
233
+ readonly path: "/hannah.v1.HannahService/SetSatelliteRoom";
234
+ readonly requestStream: false;
235
+ readonly responseStream: false;
236
+ readonly requestSerialize: (value: SetSatelliteRoomRequest) => Buffer;
237
+ readonly requestDeserialize: (value: Buffer) => SetSatelliteRoomRequest;
238
+ readonly responseSerialize: (value: StatusResponse) => Buffer;
239
+ readonly responseDeserialize: (value: Buffer) => StatusResponse;
240
+ };
241
+ readonly setSatelliteDisplayName: {
242
+ readonly path: "/hannah.v1.HannahService/SetSatelliteDisplayName";
243
+ readonly requestStream: false;
244
+ readonly responseStream: false;
245
+ readonly requestSerialize: (value: SetSatelliteDisplayNameRequest) => Buffer;
246
+ readonly requestDeserialize: (value: Buffer) => SetSatelliteDisplayNameRequest;
247
+ readonly responseSerialize: (value: StatusResponse) => Buffer;
248
+ readonly responseDeserialize: (value: Buffer) => StatusResponse;
249
+ };
250
+ /** Assign a satellite to a Person (User), independent of its room. #31 */
251
+ readonly setSatelliteOwner: {
252
+ readonly path: "/hannah.v1.HannahService/SetSatelliteOwner";
253
+ readonly requestStream: false;
254
+ readonly responseStream: false;
255
+ readonly requestSerialize: (value: SetSatelliteOwnerRequest) => Buffer;
256
+ readonly requestDeserialize: (value: Buffer) => SetSatelliteOwnerRequest;
257
+ readonly responseSerialize: (value: StatusResponse) => Buffer;
258
+ readonly responseDeserialize: (value: Buffer) => StatusResponse;
259
+ };
260
+ /**
261
+ * Toggle whether the satellite's mic reopens after a Smalltalk answer instead of
262
+ * waiting for wake-word/PTT again (silence-timeout lives in the satellite firmware). #158
263
+ */
264
+ readonly setSatelliteSmalltalkFollowup: {
265
+ readonly path: "/hannah.v1.HannahService/SetSatelliteSmalltalkFollowup";
266
+ readonly requestStream: false;
267
+ readonly responseStream: false;
268
+ readonly requestSerialize: (value: SetSatelliteSmalltalkFollowupRequest) => Buffer;
269
+ readonly requestDeserialize: (value: Buffer) => SetSatelliteSmalltalkFollowupRequest;
270
+ readonly responseSerialize: (value: StatusResponse) => Buffer;
271
+ readonly responseDeserialize: (value: Buffer) => StatusResponse;
272
+ };
273
+ /** Delete existing satellite */
274
+ readonly deleteSatellite: {
275
+ readonly path: "/hannah.v1.HannahService/DeleteSatellite";
276
+ readonly requestStream: false;
277
+ readonly responseStream: false;
278
+ readonly requestSerialize: (value: DeleteSatelliteRequest) => Buffer;
279
+ readonly requestDeserialize: (value: Buffer) => DeleteSatelliteRequest;
280
+ readonly responseSerialize: (value: StatusResponse) => Buffer;
281
+ readonly responseDeserialize: (value: Buffer) => StatusResponse;
282
+ };
283
+ /** --- Rooms/Groups (Admin-UI, #27 Phase 1) --- */
284
+ readonly getRooms: {
285
+ readonly path: "/hannah.v1.HannahService/GetRooms";
286
+ readonly requestStream: false;
287
+ readonly responseStream: false;
288
+ readonly requestSerialize: (value: Empty) => Buffer;
289
+ readonly requestDeserialize: (value: Buffer) => Empty;
290
+ readonly responseSerialize: (value: GetRoomsResponse) => Buffer;
291
+ readonly responseDeserialize: (value: Buffer) => GetRoomsResponse;
292
+ };
293
+ readonly getGroups: {
294
+ readonly path: "/hannah.v1.HannahService/GetGroups";
295
+ readonly requestStream: false;
296
+ readonly responseStream: false;
297
+ readonly requestSerialize: (value: Empty) => Buffer;
298
+ readonly requestDeserialize: (value: Buffer) => Empty;
299
+ readonly responseSerialize: (value: GetGroupsResponse) => Buffer;
300
+ readonly responseDeserialize: (value: Buffer) => GetGroupsResponse;
301
+ };
302
+ readonly createGroup: {
303
+ readonly path: "/hannah.v1.HannahService/CreateGroup";
304
+ readonly requestStream: false;
305
+ readonly responseStream: false;
306
+ readonly requestSerialize: (value: CreateGroupRequest) => Buffer;
307
+ readonly requestDeserialize: (value: Buffer) => CreateGroupRequest;
308
+ readonly responseSerialize: (value: StatusResponse) => Buffer;
309
+ readonly responseDeserialize: (value: Buffer) => StatusResponse;
310
+ };
311
+ readonly updateGroup: {
312
+ readonly path: "/hannah.v1.HannahService/UpdateGroup";
313
+ readonly requestStream: false;
314
+ readonly responseStream: false;
315
+ readonly requestSerialize: (value: UpdateGroupRequest) => Buffer;
316
+ readonly requestDeserialize: (value: Buffer) => UpdateGroupRequest;
317
+ readonly responseSerialize: (value: StatusResponse) => Buffer;
318
+ readonly responseDeserialize: (value: Buffer) => StatusResponse;
319
+ };
320
+ readonly deleteGroup: {
321
+ readonly path: "/hannah.v1.HannahService/DeleteGroup";
322
+ readonly requestStream: false;
323
+ readonly responseStream: false;
324
+ readonly requestSerialize: (value: DeleteGroupRequest) => Buffer;
325
+ readonly requestDeserialize: (value: Buffer) => DeleteGroupRequest;
326
+ readonly responseSerialize: (value: StatusResponse) => Buffer;
327
+ readonly responseDeserialize: (value: Buffer) => StatusResponse;
328
+ };
329
+ readonly setGroupSatellites: {
330
+ readonly path: "/hannah.v1.HannahService/SetGroupSatellites";
331
+ readonly requestStream: false;
332
+ readonly responseStream: false;
333
+ readonly requestSerialize: (value: SetGroupSatellitesRequest) => Buffer;
334
+ readonly requestDeserialize: (value: Buffer) => SetGroupSatellitesRequest;
335
+ readonly responseSerialize: (value: StatusResponse) => Buffer;
336
+ readonly responseDeserialize: (value: Buffer) => StatusResponse;
337
+ };
338
+ /** --- Triggers (Admin-UI, #28) --- */
339
+ readonly getTriggers: {
340
+ readonly path: "/hannah.v1.HannahService/GetTriggers";
341
+ readonly requestStream: false;
342
+ readonly responseStream: false;
343
+ readonly requestSerialize: (value: Empty) => Buffer;
344
+ readonly requestDeserialize: (value: Buffer) => Empty;
345
+ readonly responseSerialize: (value: GetTriggersResponse) => Buffer;
346
+ readonly responseDeserialize: (value: Buffer) => GetTriggersResponse;
347
+ };
348
+ readonly createTrigger: {
349
+ readonly path: "/hannah.v1.HannahService/CreateTrigger";
350
+ readonly requestStream: false;
351
+ readonly responseStream: false;
352
+ readonly requestSerialize: (value: CreateTriggerRequest) => Buffer;
353
+ readonly requestDeserialize: (value: Buffer) => CreateTriggerRequest;
354
+ readonly responseSerialize: (value: StatusResponse) => Buffer;
355
+ readonly responseDeserialize: (value: Buffer) => StatusResponse;
356
+ };
357
+ readonly updateTrigger: {
358
+ readonly path: "/hannah.v1.HannahService/UpdateTrigger";
359
+ readonly requestStream: false;
360
+ readonly responseStream: false;
361
+ readonly requestSerialize: (value: UpdateTriggerRequest) => Buffer;
362
+ readonly requestDeserialize: (value: Buffer) => UpdateTriggerRequest;
363
+ readonly responseSerialize: (value: StatusResponse) => Buffer;
364
+ readonly responseDeserialize: (value: Buffer) => StatusResponse;
365
+ };
366
+ readonly deleteTrigger: {
367
+ readonly path: "/hannah.v1.HannahService/DeleteTrigger";
368
+ readonly requestStream: false;
369
+ readonly responseStream: false;
370
+ readonly requestSerialize: (value: DeleteTriggerRequest) => Buffer;
371
+ readonly requestDeserialize: (value: Buffer) => DeleteTriggerRequest;
372
+ readonly responseSerialize: (value: StatusResponse) => Buffer;
373
+ readonly responseDeserialize: (value: Buffer) => StatusResponse;
374
+ };
375
+ /** --- Alarms (Wecker, #4) --- */
376
+ readonly getAlarms: {
377
+ readonly path: "/hannah.v1.HannahService/GetAlarms";
378
+ readonly requestStream: false;
379
+ readonly responseStream: false;
380
+ readonly requestSerialize: (value: Empty) => Buffer;
381
+ readonly requestDeserialize: (value: Buffer) => Empty;
382
+ readonly responseSerialize: (value: GetAlarmsResponse) => Buffer;
383
+ readonly responseDeserialize: (value: Buffer) => GetAlarmsResponse;
384
+ };
385
+ readonly createAlarm: {
386
+ readonly path: "/hannah.v1.HannahService/CreateAlarm";
387
+ readonly requestStream: false;
388
+ readonly responseStream: false;
389
+ readonly requestSerialize: (value: CreateAlarmRequest) => Buffer;
390
+ readonly requestDeserialize: (value: Buffer) => CreateAlarmRequest;
391
+ readonly responseSerialize: (value: CreateAlarmResponse) => Buffer;
392
+ readonly responseDeserialize: (value: Buffer) => CreateAlarmResponse;
393
+ };
394
+ readonly updateAlarm: {
395
+ readonly path: "/hannah.v1.HannahService/UpdateAlarm";
396
+ readonly requestStream: false;
397
+ readonly responseStream: false;
398
+ readonly requestSerialize: (value: UpdateAlarmRequest) => Buffer;
399
+ readonly requestDeserialize: (value: Buffer) => UpdateAlarmRequest;
400
+ readonly responseSerialize: (value: StatusResponse) => Buffer;
401
+ readonly responseDeserialize: (value: Buffer) => StatusResponse;
402
+ };
403
+ readonly deleteAlarm: {
404
+ readonly path: "/hannah.v1.HannahService/DeleteAlarm";
405
+ readonly requestStream: false;
406
+ readonly responseStream: false;
407
+ readonly requestSerialize: (value: DeleteAlarmRequest) => Buffer;
408
+ readonly requestDeserialize: (value: Buffer) => DeleteAlarmRequest;
409
+ readonly responseSerialize: (value: StatusResponse) => Buffer;
410
+ readonly responseDeserialize: (value: Buffer) => StatusResponse;
411
+ };
412
+ /**
413
+ * --- Settings (Admin-UI, #27 Phase 5) ---
414
+ * CreateSetting/DeleteSetting wurden mit #115 entfernt: ble.tags/cars haben jetzt
415
+ * eigene Modelle+CRUD (unten), nlu/iobroker.state_names/llm.system_prompt sind immer
416
+ * vorab bekannt/geseedet — es gibt keinen verbleibenden Bedarf, neue Settings anzulegen.
417
+ */
418
+ readonly getSettings: {
419
+ readonly path: "/hannah.v1.HannahService/GetSettings";
420
+ readonly requestStream: false;
421
+ readonly responseStream: false;
422
+ readonly requestSerialize: (value: Empty) => Buffer;
423
+ readonly requestDeserialize: (value: Buffer) => Empty;
424
+ readonly responseSerialize: (value: GetSettingsResponse) => Buffer;
425
+ readonly responseDeserialize: (value: Buffer) => GetSettingsResponse;
426
+ };
427
+ readonly updateConfig: {
428
+ readonly path: "/hannah.v1.HannahService/UpdateConfig";
429
+ readonly requestStream: false;
430
+ readonly responseStream: false;
431
+ readonly requestSerialize: (value: UpdateConfigRequest) => Buffer;
432
+ readonly requestDeserialize: (value: Buffer) => UpdateConfigRequest;
433
+ readonly responseSerialize: (value: StatusResponse) => Buffer;
434
+ readonly responseDeserialize: (value: Buffer) => StatusResponse;
435
+ };
436
+ /** --- BLE Tags (Admin-UI, #115 — eigenes Modell statt Settings-JSON-Blob) --- */
437
+ readonly getBleTags: {
438
+ readonly path: "/hannah.v1.HannahService/GetBleTags";
439
+ readonly requestStream: false;
440
+ readonly responseStream: false;
441
+ readonly requestSerialize: (value: Empty) => Buffer;
442
+ readonly requestDeserialize: (value: Buffer) => Empty;
443
+ readonly responseSerialize: (value: GetBleTagsResponse) => Buffer;
444
+ readonly responseDeserialize: (value: Buffer) => GetBleTagsResponse;
445
+ };
446
+ readonly createBleTag: {
447
+ readonly path: "/hannah.v1.HannahService/CreateBleTag";
448
+ readonly requestStream: false;
449
+ readonly responseStream: false;
450
+ readonly requestSerialize: (value: CreateBleTagRequest) => Buffer;
451
+ readonly requestDeserialize: (value: Buffer) => CreateBleTagRequest;
452
+ readonly responseSerialize: (value: CreateBleTagResponse) => Buffer;
453
+ readonly responseDeserialize: (value: Buffer) => CreateBleTagResponse;
454
+ };
455
+ readonly updateBleTag: {
456
+ readonly path: "/hannah.v1.HannahService/UpdateBleTag";
457
+ readonly requestStream: false;
458
+ readonly responseStream: false;
459
+ readonly requestSerialize: (value: UpdateBleTagRequest) => Buffer;
460
+ readonly requestDeserialize: (value: Buffer) => UpdateBleTagRequest;
461
+ readonly responseSerialize: (value: StatusResponse) => Buffer;
462
+ readonly responseDeserialize: (value: Buffer) => StatusResponse;
463
+ };
464
+ readonly deleteBleTag: {
465
+ readonly path: "/hannah.v1.HannahService/DeleteBleTag";
466
+ readonly requestStream: false;
467
+ readonly responseStream: false;
468
+ readonly requestSerialize: (value: DeleteBleTagRequest) => Buffer;
469
+ readonly requestDeserialize: (value: Buffer) => DeleteBleTagRequest;
470
+ readonly responseSerialize: (value: StatusResponse) => Buffer;
471
+ readonly responseDeserialize: (value: Buffer) => StatusResponse;
472
+ };
473
+ /** --- Presence Sources (Admin-UI, hannah#294 — presence fusion) --- */
474
+ readonly getPresenceSources: {
475
+ readonly path: "/hannah.v1.HannahService/GetPresenceSources";
476
+ readonly requestStream: false;
477
+ readonly responseStream: false;
478
+ readonly requestSerialize: (value: Empty) => Buffer;
479
+ readonly requestDeserialize: (value: Buffer) => Empty;
480
+ readonly responseSerialize: (value: GetPresenceSourcesResponse) => Buffer;
481
+ readonly responseDeserialize: (value: Buffer) => GetPresenceSourcesResponse;
482
+ };
483
+ readonly createPresenceSource: {
484
+ readonly path: "/hannah.v1.HannahService/CreatePresenceSource";
485
+ readonly requestStream: false;
486
+ readonly responseStream: false;
487
+ readonly requestSerialize: (value: CreatePresenceSourceRequest) => Buffer;
488
+ readonly requestDeserialize: (value: Buffer) => CreatePresenceSourceRequest;
489
+ readonly responseSerialize: (value: CreatePresenceSourceResponse) => Buffer;
490
+ readonly responseDeserialize: (value: Buffer) => CreatePresenceSourceResponse;
491
+ };
492
+ readonly updatePresenceSource: {
493
+ readonly path: "/hannah.v1.HannahService/UpdatePresenceSource";
494
+ readonly requestStream: false;
495
+ readonly responseStream: false;
496
+ readonly requestSerialize: (value: UpdatePresenceSourceRequest) => Buffer;
497
+ readonly requestDeserialize: (value: Buffer) => UpdatePresenceSourceRequest;
498
+ readonly responseSerialize: (value: StatusResponse) => Buffer;
499
+ readonly responseDeserialize: (value: Buffer) => StatusResponse;
500
+ };
501
+ readonly deletePresenceSource: {
502
+ readonly path: "/hannah.v1.HannahService/DeletePresenceSource";
503
+ readonly requestStream: false;
504
+ readonly responseStream: false;
505
+ readonly requestSerialize: (value: DeletePresenceSourceRequest) => Buffer;
506
+ readonly requestDeserialize: (value: Buffer) => DeletePresenceSourceRequest;
507
+ readonly responseSerialize: (value: StatusResponse) => Buffer;
508
+ readonly responseDeserialize: (value: Buffer) => StatusResponse;
509
+ };
510
+ /** --- Cars (Admin-UI, #115 — eigenes Modell + user_to_car-Pivot statt Settings-JSON-Blob) --- */
511
+ readonly getCars: {
512
+ readonly path: "/hannah.v1.HannahService/GetCars";
513
+ readonly requestStream: false;
514
+ readonly responseStream: false;
515
+ readonly requestSerialize: (value: Empty) => Buffer;
516
+ readonly requestDeserialize: (value: Buffer) => Empty;
517
+ readonly responseSerialize: (value: GetCarsResponse) => Buffer;
518
+ readonly responseDeserialize: (value: Buffer) => GetCarsResponse;
519
+ };
520
+ readonly createCar: {
521
+ readonly path: "/hannah.v1.HannahService/CreateCar";
522
+ readonly requestStream: false;
523
+ readonly responseStream: false;
524
+ readonly requestSerialize: (value: CreateCarRequest) => Buffer;
525
+ readonly requestDeserialize: (value: Buffer) => CreateCarRequest;
526
+ readonly responseSerialize: (value: CreateCarResponse) => Buffer;
527
+ readonly responseDeserialize: (value: Buffer) => CreateCarResponse;
528
+ };
529
+ readonly updateCar: {
530
+ readonly path: "/hannah.v1.HannahService/UpdateCar";
531
+ readonly requestStream: false;
532
+ readonly responseStream: false;
533
+ readonly requestSerialize: (value: UpdateCarRequest) => Buffer;
534
+ readonly requestDeserialize: (value: Buffer) => UpdateCarRequest;
535
+ readonly responseSerialize: (value: StatusResponse) => Buffer;
536
+ readonly responseDeserialize: (value: Buffer) => StatusResponse;
537
+ };
538
+ readonly deleteCar: {
539
+ readonly path: "/hannah.v1.HannahService/DeleteCar";
540
+ readonly requestStream: false;
541
+ readonly responseStream: false;
542
+ readonly requestSerialize: (value: DeleteCarRequest) => Buffer;
543
+ readonly requestDeserialize: (value: Buffer) => DeleteCarRequest;
544
+ readonly responseSerialize: (value: StatusResponse) => Buffer;
545
+ readonly responseDeserialize: (value: Buffer) => StatusResponse;
546
+ };
547
+ /**
548
+ * --- Car state (Live-VW-Connect-Status, unabhängig von der Car-Konfiguration oben) ---
549
+ * Returns the current cached car state (available=false if no data received yet).
550
+ */
551
+ readonly getCarState: {
552
+ readonly path: "/hannah.v1.HannahService/GetCarState";
553
+ readonly requestStream: false;
554
+ readonly responseStream: false;
555
+ readonly requestSerialize: (value: Empty) => Buffer;
556
+ readonly requestDeserialize: (value: Buffer) => Empty;
557
+ readonly responseSerialize: (value: CarStateResponse) => Buffer;
558
+ readonly responseDeserialize: (value: Buffer) => CarStateResponse;
559
+ };
560
+ /** Returns all tracked car states (one per configured car). */
561
+ readonly getAllCarStates: {
562
+ readonly path: "/hannah.v1.HannahService/GetAllCarStates";
563
+ readonly requestStream: false;
564
+ readonly responseStream: false;
565
+ readonly requestSerialize: (value: Empty) => Buffer;
566
+ readonly requestDeserialize: (value: Buffer) => Empty;
567
+ readonly responseSerialize: (value: GetAllCarStatesResponse) => Buffer;
568
+ readonly responseDeserialize: (value: Buffer) => GetAllCarStatesResponse;
569
+ };
570
+ /**
571
+ * --- Event stream ---
572
+ * Opens a server-side stream; Hannah pushes events as they occur.
573
+ * Pass event_types to filter (empty = all events).
574
+ * Known event types: "car.parked", "resident.arrived", "resident.departed", "satellite.firmware"
575
+ */
576
+ readonly subscribeEvents: {
577
+ readonly path: "/hannah.v1.HannahService/SubscribeEvents";
578
+ readonly requestStream: false;
579
+ readonly responseStream: true;
580
+ readonly requestSerialize: (value: EventFilter) => Buffer;
581
+ readonly requestDeserialize: (value: Buffer) => EventFilter;
582
+ readonly responseSerialize: (value: HannahEvent) => Buffer;
583
+ readonly responseDeserialize: (value: Buffer) => HannahEvent;
584
+ };
585
+ /**
586
+ * --- Firmware Manager ---
587
+ * Trigger an immediate OTA update for a satellite (bypasses residents check).
588
+ */
589
+ readonly triggerFirmwareUpdate: {
590
+ readonly path: "/hannah.v1.HannahService/TriggerFirmwareUpdate";
591
+ readonly requestStream: false;
592
+ readonly responseStream: false;
593
+ readonly requestSerialize: (value: TriggerFirmwareUpdateRequest) => Buffer;
594
+ readonly requestDeserialize: (value: Buffer) => TriggerFirmwareUpdateRequest;
595
+ readonly responseSerialize: (value: StatusResponse) => Buffer;
596
+ readonly responseDeserialize: (value: Buffer) => StatusResponse;
597
+ };
598
+ /**
599
+ * Trigger an ordered remote restart (esp_restart()) of a satellite over MQTT.
600
+ * Diagnostic/rejuvenation tool for suspected resource exhaustion (heap fragmentation
601
+ * after long uptime) — works even when the satellite's OTA/webserver no longer
602
+ * respond, since MQTT stays alive in that failure mode.
603
+ */
604
+ readonly triggerSatelliteRestart: {
605
+ readonly path: "/hannah.v1.HannahService/TriggerSatelliteRestart";
606
+ readonly requestStream: false;
607
+ readonly responseStream: false;
608
+ readonly requestSerialize: (value: TriggerSatelliteRestartRequest) => Buffer;
609
+ readonly requestDeserialize: (value: Buffer) => TriggerSatelliteRestartRequest;
610
+ readonly responseSerialize: (value: StatusResponse) => Buffer;
611
+ readonly responseDeserialize: (value: Buffer) => StatusResponse;
612
+ };
613
+ /**
614
+ * --- Wakeword Capture ---
615
+ * Put a satellite in audio-capture mode for wakeword training data collection.
616
+ * While captured: wakeword detection is suspended, speaker is muted, DND is active.
617
+ * Hannah relays raw PCM chunks from the satellite to the collector via StreamSatelliteAudio.
618
+ * The stream stays open until the collector disconnects; Hannah then auto-releases the satellite.
619
+ */
620
+ readonly requestSatelliteCapture: {
621
+ readonly path: "/hannah.v1.HannahService/RequestSatelliteCapture";
622
+ readonly requestStream: false;
623
+ readonly responseStream: false;
624
+ readonly requestSerialize: (value: SatelliteCaptureRequest) => Buffer;
625
+ readonly requestDeserialize: (value: Buffer) => SatelliteCaptureRequest;
626
+ readonly responseSerialize: (value: SatelliteCaptureResponse) => Buffer;
627
+ readonly responseDeserialize: (value: Buffer) => SatelliteCaptureResponse;
628
+ };
629
+ readonly releaseSatelliteCapture: {
630
+ readonly path: "/hannah.v1.HannahService/ReleaseSatelliteCapture";
631
+ readonly requestStream: false;
632
+ readonly responseStream: false;
633
+ readonly requestSerialize: (value: SatelliteCaptureRequest) => Buffer;
634
+ readonly requestDeserialize: (value: Buffer) => SatelliteCaptureRequest;
635
+ readonly responseSerialize: (value: StatusResponse) => Buffer;
636
+ readonly responseDeserialize: (value: Buffer) => StatusResponse;
637
+ };
638
+ readonly streamSatelliteAudio: {
639
+ readonly path: "/hannah.v1.HannahService/StreamSatelliteAudio";
640
+ readonly requestStream: false;
641
+ readonly responseStream: true;
642
+ readonly requestSerialize: (value: SatelliteCaptureRequest) => Buffer;
643
+ readonly requestDeserialize: (value: Buffer) => SatelliteCaptureRequest;
644
+ readonly responseSerialize: (value: SatelliteAudioChunk) => Buffer;
645
+ readonly responseDeserialize: (value: Buffer) => SatelliteAudioChunk;
646
+ };
647
+ /**
648
+ * Play a plink sound on the satellite, then hold virtual PTT for record_duration seconds.
649
+ * Returns after PTT is released — Collector calls this in a loop for guided hey-hannah collection.
650
+ */
651
+ readonly triggerPlink: {
652
+ readonly path: "/hannah.v1.HannahService/TriggerPlink";
653
+ readonly requestStream: false;
654
+ readonly responseStream: false;
655
+ readonly requestSerialize: (value: TriggerPlinkRequest) => Buffer;
656
+ readonly requestDeserialize: (value: Buffer) => TriggerPlinkRequest;
657
+ readonly responseSerialize: (value: StatusResponse) => Buffer;
658
+ readonly responseDeserialize: (value: Buffer) => StatusResponse;
659
+ };
660
+ /**
661
+ * Bidirectional stream between the Collector and Hannah Core, analogous to TimerConnect.
662
+ * The Collector initiates and holds the connection open; Hannah pushes CaptureCommands
663
+ * down to start/stop satellite captures instead of the Collector polling for them.
664
+ */
665
+ readonly collectorConnect: {
666
+ readonly path: "/hannah.v1.HannahService/CollectorConnect";
667
+ readonly requestStream: true;
668
+ readonly responseStream: true;
669
+ readonly requestSerialize: (value: CollectorMessage) => Buffer;
670
+ readonly requestDeserialize: (value: Buffer) => CollectorMessage;
671
+ readonly responseSerialize: (value: CaptureCommand) => Buffer;
672
+ readonly responseDeserialize: (value: Buffer) => CaptureCommand;
673
+ };
674
+ /**
675
+ * Unary trigger for external callers (e.g. WebUI) that can't hold a CollectorConnect
676
+ * stream themselves — Hannah relays the command over its own CollectorConnect stream
677
+ * to the connected Collector. Fails with ok=false if no Collector is connected.
678
+ */
679
+ readonly triggerCollectorCapture: {
680
+ readonly path: "/hannah.v1.HannahService/TriggerCollectorCapture";
681
+ readonly requestStream: false;
682
+ readonly responseStream: false;
683
+ readonly requestSerialize: (value: CaptureCommand) => Buffer;
684
+ readonly requestDeserialize: (value: Buffer) => CaptureCommand;
685
+ readonly responseSerialize: (value: StatusResponse) => Buffer;
686
+ readonly responseDeserialize: (value: Buffer) => StatusResponse;
687
+ };
688
+ /**
689
+ * --- Satellite Proxy (Go gRPC proxy) ---
690
+ * Bidirectional keepalive stream. Proxy sends heartbeats; Hannah sends TTS
691
+ * audio commands back (for announcements). While this stream is open, Hannah
692
+ * disables its own UDP server. If the stream drops, Hannah re-enables UDP.
693
+ */
694
+ readonly registerProxy: {
695
+ readonly path: "/hannah.v1.HannahService/RegisterProxy";
696
+ readonly requestStream: true;
697
+ readonly responseStream: true;
698
+ readonly requestSerialize: (value: ProxyHeartbeat) => Buffer;
699
+ readonly requestDeserialize: (value: Buffer) => ProxyHeartbeat;
700
+ readonly responseSerialize: (value: ProxyCommand) => Buffer;
701
+ readonly responseDeserialize: (value: Buffer) => ProxyCommand;
702
+ };
703
+ /**
704
+ * Submit a complete satellite audio session for processing.
705
+ * Hannah runs the full pipeline (STT → NLU → TTS → MQTT status) and returns
706
+ * the result so the proxy can play TTS audio back to the satellite.
707
+ */
708
+ readonly submitSatelliteAudio: {
709
+ readonly path: "/hannah.v1.HannahService/SubmitSatelliteAudio";
710
+ readonly requestStream: false;
711
+ readonly responseStream: false;
712
+ readonly requestSerialize: (value: SubmitSatelliteAudioRequest) => Buffer;
713
+ readonly requestDeserialize: (value: Buffer) => SubmitSatelliteAudioRequest;
714
+ readonly responseSerialize: (value: SubmitSatelliteAudioResponse) => Buffer;
715
+ readonly responseDeserialize: (value: Buffer) => SubmitSatelliteAudioResponse;
716
+ };
717
+ /**
718
+ * Notify Hannah that a satellite registered or disconnected via the proxy.
719
+ * Hannah updates its room registry (hannah/rooms MQTT) immediately.
720
+ */
721
+ readonly notifySatelliteRegistered: {
722
+ readonly path: "/hannah.v1.HannahService/NotifySatelliteRegistered";
723
+ readonly requestStream: false;
724
+ readonly responseStream: false;
725
+ readonly requestSerialize: (value: SatelliteRegistration) => Buffer;
726
+ readonly requestDeserialize: (value: Buffer) => SatelliteRegistration;
727
+ readonly responseSerialize: (value: StatusResponse) => Buffer;
728
+ readonly responseDeserialize: (value: Buffer) => StatusResponse;
729
+ };
730
+ readonly notifySatelliteGone: {
731
+ readonly path: "/hannah.v1.HannahService/NotifySatelliteGone";
732
+ readonly requestStream: false;
733
+ readonly responseStream: false;
734
+ readonly requestSerialize: (value: SatelliteRegistration) => Buffer;
735
+ readonly requestDeserialize: (value: Buffer) => SatelliteRegistration;
736
+ readonly responseSerialize: (value: StatusResponse) => Buffer;
737
+ readonly responseDeserialize: (value: Buffer) => StatusResponse;
738
+ };
739
+ /**
740
+ * --- Satellite Provisioning ---
741
+ * Called by the ioBroker adapter before WebFlash to pre-register a seed + display name + room.
742
+ * When the satellite first connects with that seed, Hannah links serial → pre-config and clears the seed.
743
+ */
744
+ readonly provisionSatellite: {
745
+ readonly path: "/hannah.v1.HannahService/ProvisionSatellite";
746
+ readonly requestStream: false;
747
+ readonly responseStream: false;
748
+ readonly requestSerialize: (value: ProvisionSatelliteRequest) => Buffer;
749
+ readonly requestDeserialize: (value: Buffer) => ProvisionSatelliteRequest;
750
+ readonly responseSerialize: (value: StatusResponse) => Buffer;
751
+ readonly responseDeserialize: (value: Buffer) => StatusResponse;
752
+ };
753
+ /**
754
+ * --- Speaker Enrollment ---
755
+ * Trigger a guided voice-enrollment dialog for user_id at satellite_id (hannah#8);
756
+ * Core orchestrates the dialog itself. EnrollVoiceprint stays available as the
757
+ * low-level "store one already-captured sample" call — kept for now (additive,
758
+ * no hard cut) until hannah#8 confirms Core no longer needs it as an external RPC.
759
+ */
760
+ readonly startVoiceEnrollment: {
761
+ readonly path: "/hannah.v1.HannahService/StartVoiceEnrollment";
762
+ readonly requestStream: false;
763
+ readonly responseStream: false;
764
+ readonly requestSerialize: (value: StartVoiceEnrollmentRequest) => Buffer;
765
+ readonly requestDeserialize: (value: Buffer) => StartVoiceEnrollmentRequest;
766
+ readonly responseSerialize: (value: StatusResponse) => Buffer;
767
+ readonly responseDeserialize: (value: Buffer) => StatusResponse;
768
+ };
769
+ readonly enrollVoiceprint: {
770
+ readonly path: "/hannah.v1.HannahService/EnrollVoiceprint";
771
+ readonly requestStream: false;
772
+ readonly responseStream: false;
773
+ readonly requestSerialize: (value: EnrollVoiceprintRequest) => Buffer;
774
+ readonly requestDeserialize: (value: Buffer) => EnrollVoiceprintRequest;
775
+ readonly responseSerialize: (value: StatusResponse) => Buffer;
776
+ readonly responseDeserialize: (value: Buffer) => StatusResponse;
777
+ };
778
+ /**
779
+ * --- Timer Service ---
780
+ * Bidirectional stream between the Hannah Timer Service and Hannah Core.
781
+ * The Timer Service initiates the connection; if Hannah restarts, the service reconnects.
782
+ * Hannah sends timer commands (create, cancel, list); the service fires events when timers expire.
783
+ */
784
+ readonly timerConnect: {
785
+ readonly path: "/hannah.v1.HannahService/TimerConnect";
786
+ readonly requestStream: true;
787
+ readonly responseStream: true;
788
+ readonly requestSerialize: (value: TimerMessage) => Buffer;
789
+ readonly requestDeserialize: (value: Buffer) => TimerMessage;
790
+ readonly responseSerialize: (value: TimerCommand) => Buffer;
791
+ readonly responseDeserialize: (value: Buffer) => TimerCommand;
792
+ };
793
+ /**
794
+ * --- Timer Admin ---
795
+ * Query and cancel timers independent of the TimerConnect stream — e.g. for an
796
+ * Admin-UI or Telegram bot listing/cancelling a user's active timers.
797
+ */
798
+ readonly getTimers: {
799
+ readonly path: "/hannah.v1.HannahService/GetTimers";
800
+ readonly requestStream: false;
801
+ readonly responseStream: false;
802
+ readonly requestSerialize: (value: GetTimersRequest) => Buffer;
803
+ readonly requestDeserialize: (value: Buffer) => GetTimersRequest;
804
+ readonly responseSerialize: (value: GetTimersResponse) => Buffer;
805
+ readonly responseDeserialize: (value: Buffer) => GetTimersResponse;
806
+ };
807
+ readonly deleteTimer: {
808
+ readonly path: "/hannah.v1.HannahService/DeleteTimer";
809
+ readonly requestStream: false;
810
+ readonly responseStream: false;
811
+ readonly requestSerialize: (value: DeleteTimerRequest) => Buffer;
812
+ readonly requestDeserialize: (value: Buffer) => DeleteTimerRequest;
813
+ readonly responseSerialize: (value: StatusResponse) => Buffer;
814
+ readonly responseDeserialize: (value: Buffer) => StatusResponse;
815
+ };
816
+ /**
817
+ * --- ioBroker Agent ---
818
+ * Single bidirectional stream between the HannahAgent ioBroker adapter and Hannah Core.
819
+ * The adapter pushes state updates (device states, presence, text commands);
820
+ * Hannah pushes device-control commands and on-demand state-subscription requests back.
821
+ * The adapter initiates the connection; if Hannah restarts, the adapter reconnects.
822
+ */
823
+ readonly agentConnect: {
824
+ readonly path: "/hannah.v1.HannahService/AgentConnect";
825
+ readonly requestStream: true;
826
+ readonly responseStream: true;
827
+ readonly requestSerialize: (value: AgentMessage) => Buffer;
828
+ readonly requestDeserialize: (value: Buffer) => AgentMessage;
829
+ readonly responseSerialize: (value: AgentCommand) => Buffer;
830
+ readonly responseDeserialize: (value: Buffer) => AgentCommand;
831
+ };
832
+ /**
833
+ * --- Automations ---
834
+ * Bidirectional stream for external automation services (e.g. telegram_autoresponder).
835
+ * The service sends an AutomationRegister identifying itself, then Hannah replies with
836
+ * an AutomationSnapshot (all users with it currently enabled) followed by live
837
+ * AutomationStateChanged deltas as users toggle it via SetAutomation/voice.
838
+ * Chosen over SubscribeEvents so a reconnecting service always gets a fresh snapshot
839
+ * instead of missing state changes that happened while it was offline.
840
+ */
841
+ readonly automationConnect: {
842
+ readonly path: "/hannah.v1.HannahService/AutomationConnect";
843
+ readonly requestStream: true;
844
+ readonly responseStream: true;
845
+ readonly requestSerialize: (value: AutomationMessage) => Buffer;
846
+ readonly requestDeserialize: (value: Buffer) => AutomationMessage;
847
+ readonly responseSerialize: (value: AutomationCommand) => Buffer;
848
+ readonly responseDeserialize: (value: Buffer) => AutomationCommand;
849
+ };
850
+ /**
851
+ * --- Channels ---
852
+ * Bidirectional stream for channel adapters (e.g. the Telegram service). The adapter
853
+ * sends a ChannelRegister and keeps the stream open; it counts as available exactly as
854
+ * long as the stream is open. A second registration for the same service replaces the
855
+ * first. Link tokens (CreateLinkToken) are redeemed over this stream.
856
+ */
857
+ readonly channelConnect: {
858
+ readonly path: "/hannah.v1.HannahService/ChannelConnect";
859
+ readonly requestStream: true;
860
+ readonly responseStream: true;
861
+ readonly requestSerialize: (value: ChannelMessage) => Buffer;
862
+ readonly requestDeserialize: (value: Buffer) => ChannelMessage;
863
+ readonly responseSerialize: (value: ChannelCommand) => Buffer;
864
+ readonly responseDeserialize: (value: Buffer) => ChannelCommand;
865
+ };
866
+ /** Currently connected channel adapters and whether they support account linking. */
867
+ readonly getChannels: {
868
+ readonly path: "/hannah.v1.HannahService/GetChannels";
869
+ readonly requestStream: false;
870
+ readonly responseStream: false;
871
+ readonly requestSerialize: (value: Empty) => Buffer;
872
+ readonly requestDeserialize: (value: Buffer) => Empty;
873
+ readonly responseSerialize: (value: GetChannelsResponse) => Buffer;
874
+ readonly responseDeserialize: (value: Buffer) => GetChannelsResponse;
875
+ };
876
+ /**
877
+ * --- Infrastructure ---
878
+ * Service discovery for components: Hannah sends an InfrastructureSnapshot of all
879
+ * currently available infrastructure services (e.g. the log collector) right after
880
+ * subscribing, followed by ServiceAvailable/ServiceUnavailable deltas.
881
+ */
882
+ readonly subscribeInfrastructure: {
883
+ readonly path: "/hannah.v1.HannahService/SubscribeInfrastructure";
884
+ readonly requestStream: false;
885
+ readonly responseStream: true;
886
+ readonly requestSerialize: (value: InfrastructureFilter) => Buffer;
887
+ readonly requestDeserialize: (value: Buffer) => InfrastructureFilter;
888
+ readonly responseSerialize: (value: InfrastructureMessage) => Buffer;
889
+ readonly responseDeserialize: (value: Buffer) => InfrastructureMessage;
890
+ };
891
+ /**
892
+ * Bidirectional stream for the log collector. The collector sends a LogCollectorRegister
893
+ * and keeps the stream open; it counts as available exactly as long as the stream is
894
+ * open, and a second registration for the same instance replaces the first (same
895
+ * semantics as ChannelConnect). Not related to CollectorConnect (wakeword capture).
896
+ */
897
+ readonly logCollectorConnect: {
898
+ readonly path: "/hannah.v1.HannahService/LogCollectorConnect";
899
+ readonly requestStream: true;
900
+ readonly responseStream: true;
901
+ readonly requestSerialize: (value: LogCollectorMessage) => Buffer;
902
+ readonly requestDeserialize: (value: Buffer) => LogCollectorMessage;
903
+ readonly responseSerialize: (value: LogCollectorCommand) => Buffer;
904
+ readonly responseDeserialize: (value: Buffer) => LogCollectorCommand;
905
+ };
906
+ /**
907
+ * --- Activity Log ---
908
+ * Read access to the Activity Log (#220) for external consumers (WebUI). List returns
909
+ * full entry detail inline (transcript, intent + intent_meta, answer text) with
910
+ * cursor-based pagination; audio is fetched separately, decoded server-side from the
911
+ * stored WAV and streamed as raw PCM chunks.
912
+ */
913
+ readonly listActivityLog: {
914
+ readonly path: "/hannah.v1.HannahService/ListActivityLog";
915
+ readonly requestStream: false;
916
+ readonly responseStream: false;
917
+ readonly requestSerialize: (value: ListActivityLogRequest) => Buffer;
918
+ readonly requestDeserialize: (value: Buffer) => ListActivityLogRequest;
919
+ readonly responseSerialize: (value: ListActivityLogResponse) => Buffer;
920
+ readonly responseDeserialize: (value: Buffer) => ListActivityLogResponse;
921
+ };
922
+ readonly streamActivityAudio: {
923
+ readonly path: "/hannah.v1.HannahService/StreamActivityAudio";
924
+ readonly requestStream: false;
925
+ readonly responseStream: true;
926
+ readonly requestSerialize: (value: StreamActivityAudioRequest) => Buffer;
927
+ readonly requestDeserialize: (value: Buffer) => StreamActivityAudioRequest;
928
+ readonly responseSerialize: (value: ActivityAudioChunk) => Buffer;
929
+ readonly responseDeserialize: (value: Buffer) => ActivityAudioChunk;
930
+ };
931
+ /** --- Messages (passive per-user mailbox, third notification type) --- */
932
+ readonly createMessage: {
933
+ readonly path: "/hannah.v1.HannahService/CreateMessage";
934
+ readonly requestStream: false;
935
+ readonly responseStream: false;
936
+ readonly requestSerialize: (value: CreateMessageRequest) => Buffer;
937
+ readonly requestDeserialize: (value: Buffer) => CreateMessageRequest;
938
+ readonly responseSerialize: (value: StatusResponse) => Buffer;
939
+ readonly responseDeserialize: (value: Buffer) => StatusResponse;
940
+ };
941
+ readonly listMessages: {
942
+ readonly path: "/hannah.v1.HannahService/ListMessages";
943
+ readonly requestStream: false;
944
+ readonly responseStream: false;
945
+ readonly requestSerialize: (value: ListMessagesRequest) => Buffer;
946
+ readonly requestDeserialize: (value: Buffer) => ListMessagesRequest;
947
+ readonly responseSerialize: (value: ListMessagesResponse) => Buffer;
948
+ readonly responseDeserialize: (value: Buffer) => ListMessagesResponse;
949
+ };
950
+ readonly deleteMessage: {
951
+ readonly path: "/hannah.v1.HannahService/DeleteMessage";
952
+ readonly requestStream: false;
953
+ readonly responseStream: false;
954
+ readonly requestSerialize: (value: DeleteMessageRequest) => Buffer;
955
+ readonly requestDeserialize: (value: Buffer) => DeleteMessageRequest;
956
+ readonly responseSerialize: (value: StatusResponse) => Buffer;
957
+ readonly responseDeserialize: (value: Buffer) => StatusResponse;
958
+ };
959
+ };
960
+ export interface HannahServiceServer extends UntypedServiceImplementation {
961
+ /** --- User Registry --- */
962
+ getUsers: handleUnaryCall<GetUsersRequest, GetUsersResponse>;
963
+ getUser: handleUnaryCall<GetUserRequest, UserResponse>;
964
+ linkAccount: handleUnaryCall<LinkAccountRequest, StatusResponse>;
965
+ unlinkAccount: handleUnaryCall<UnlinkAccountRequest, StatusResponse>;
966
+ /**
967
+ * One-time token for linking an account via the service's adapter (e.g. Telegram deep link).
968
+ * Redeemed by the adapter over ChannelConnect.
969
+ */
970
+ createLinkToken: handleUnaryCall<CreateLinkTokenRequest, CreateLinkTokenResponse>;
971
+ setTrustLevel: handleUnaryCall<SetTrustLevelRequest, StatusResponse>;
972
+ setSystemMessages: handleUnaryCall<SetSystemMessagesRequest, StatusResponse>;
973
+ /**
974
+ * Enable/disable an automation service (e.g. "telegram_autoresponder") for a user.
975
+ * Pushes a live update to any connected AutomationConnect stream registered for it.
976
+ */
977
+ setAutomation: handleUnaryCall<SetAutomationRequest, StatusResponse>;
978
+ login: handleUnaryCall<LoginRequest, UserResponse>;
979
+ /** --- User-Verwaltung (Admin-UI, #27 Phase 6) --- */
980
+ createUser: handleUnaryCall<CreateUserRequest, CreateUserResponse>;
981
+ updateUser: handleUnaryCall<UpdateUserRequest, StatusResponse>;
982
+ deleteUser: handleUnaryCall<DeleteUserRequest, StatusResponse>;
983
+ /** Residents (Roomies/Guests/Pets) aus dem ioBroker-Adapter-Cache — fürs "Resident verknüpfen"-Dropdown. */
984
+ getResidents: handleUnaryCall<Empty, GetResidentsResponse>;
985
+ /**
986
+ * --- Device Control Menu ---
987
+ * Returns all rooms and devices with current state — for building control menus.
988
+ */
989
+ getDevices: handleUnaryCall<Empty, GetDevicesResponse>;
990
+ /** Directly set a device state (bypasses NLU). Trust level check is done by the caller. */
991
+ controlDevice: handleUnaryCall<ControlDeviceRequest, StatusResponse>;
992
+ /**
993
+ * --- Control ---
994
+ * Submit a plain-text command; Hannah processes it through NLU and returns the answer.
995
+ */
996
+ submitText: handleUnaryCall<SubmitTextRequest, SubmitTextResponse>;
997
+ /** Submit a voice message (OGG/Opus bytes); Hannah does STT → NLU → TTS and returns the result. */
998
+ submitVoice: handleUnaryCall<SubmitVoiceRequest, SubmitVoiceResponse>;
999
+ /** Send a TTS announcement to one satellite or all ("all"). */
1000
+ announce: handleUnaryCall<AnnounceRequest, StatusResponse>;
1001
+ /**
1002
+ * Send a notification from ioBroker to Hannah. Returns ok=true when queued.
1003
+ * direct=true: skip LLM reformulation. severity: "alert"|"notify"|"info".
1004
+ */
1005
+ notify: handleUnaryCall<AgentNotification, StatusResponse>;
1006
+ /** List all known satellites (DB + live status merged). */
1007
+ getSatellites: handleUnaryCall<Empty, GetSatellitesResponse>;
1008
+ /** --- Satellites (Admin-UI, #27 Phase 2) --- */
1009
+ setSatelliteRoom: handleUnaryCall<SetSatelliteRoomRequest, StatusResponse>;
1010
+ setSatelliteDisplayName: handleUnaryCall<SetSatelliteDisplayNameRequest, StatusResponse>;
1011
+ /** Assign a satellite to a Person (User), independent of its room. #31 */
1012
+ setSatelliteOwner: handleUnaryCall<SetSatelliteOwnerRequest, StatusResponse>;
1013
+ /**
1014
+ * Toggle whether the satellite's mic reopens after a Smalltalk answer instead of
1015
+ * waiting for wake-word/PTT again (silence-timeout lives in the satellite firmware). #158
1016
+ */
1017
+ setSatelliteSmalltalkFollowup: handleUnaryCall<SetSatelliteSmalltalkFollowupRequest, StatusResponse>;
1018
+ /** Delete existing satellite */
1019
+ deleteSatellite: handleUnaryCall<DeleteSatelliteRequest, StatusResponse>;
1020
+ /** --- Rooms/Groups (Admin-UI, #27 Phase 1) --- */
1021
+ getRooms: handleUnaryCall<Empty, GetRoomsResponse>;
1022
+ getGroups: handleUnaryCall<Empty, GetGroupsResponse>;
1023
+ createGroup: handleUnaryCall<CreateGroupRequest, StatusResponse>;
1024
+ updateGroup: handleUnaryCall<UpdateGroupRequest, StatusResponse>;
1025
+ deleteGroup: handleUnaryCall<DeleteGroupRequest, StatusResponse>;
1026
+ setGroupSatellites: handleUnaryCall<SetGroupSatellitesRequest, StatusResponse>;
1027
+ /** --- Triggers (Admin-UI, #28) --- */
1028
+ getTriggers: handleUnaryCall<Empty, GetTriggersResponse>;
1029
+ createTrigger: handleUnaryCall<CreateTriggerRequest, StatusResponse>;
1030
+ updateTrigger: handleUnaryCall<UpdateTriggerRequest, StatusResponse>;
1031
+ deleteTrigger: handleUnaryCall<DeleteTriggerRequest, StatusResponse>;
1032
+ /** --- Alarms (Wecker, #4) --- */
1033
+ getAlarms: handleUnaryCall<Empty, GetAlarmsResponse>;
1034
+ createAlarm: handleUnaryCall<CreateAlarmRequest, CreateAlarmResponse>;
1035
+ updateAlarm: handleUnaryCall<UpdateAlarmRequest, StatusResponse>;
1036
+ deleteAlarm: handleUnaryCall<DeleteAlarmRequest, StatusResponse>;
1037
+ /**
1038
+ * --- Settings (Admin-UI, #27 Phase 5) ---
1039
+ * CreateSetting/DeleteSetting wurden mit #115 entfernt: ble.tags/cars haben jetzt
1040
+ * eigene Modelle+CRUD (unten), nlu/iobroker.state_names/llm.system_prompt sind immer
1041
+ * vorab bekannt/geseedet — es gibt keinen verbleibenden Bedarf, neue Settings anzulegen.
1042
+ */
1043
+ getSettings: handleUnaryCall<Empty, GetSettingsResponse>;
1044
+ updateConfig: handleUnaryCall<UpdateConfigRequest, StatusResponse>;
1045
+ /** --- BLE Tags (Admin-UI, #115 — eigenes Modell statt Settings-JSON-Blob) --- */
1046
+ getBleTags: handleUnaryCall<Empty, GetBleTagsResponse>;
1047
+ createBleTag: handleUnaryCall<CreateBleTagRequest, CreateBleTagResponse>;
1048
+ updateBleTag: handleUnaryCall<UpdateBleTagRequest, StatusResponse>;
1049
+ deleteBleTag: handleUnaryCall<DeleteBleTagRequest, StatusResponse>;
1050
+ /** --- Presence Sources (Admin-UI, hannah#294 — presence fusion) --- */
1051
+ getPresenceSources: handleUnaryCall<Empty, GetPresenceSourcesResponse>;
1052
+ createPresenceSource: handleUnaryCall<CreatePresenceSourceRequest, CreatePresenceSourceResponse>;
1053
+ updatePresenceSource: handleUnaryCall<UpdatePresenceSourceRequest, StatusResponse>;
1054
+ deletePresenceSource: handleUnaryCall<DeletePresenceSourceRequest, StatusResponse>;
1055
+ /** --- Cars (Admin-UI, #115 — eigenes Modell + user_to_car-Pivot statt Settings-JSON-Blob) --- */
1056
+ getCars: handleUnaryCall<Empty, GetCarsResponse>;
1057
+ createCar: handleUnaryCall<CreateCarRequest, CreateCarResponse>;
1058
+ updateCar: handleUnaryCall<UpdateCarRequest, StatusResponse>;
1059
+ deleteCar: handleUnaryCall<DeleteCarRequest, StatusResponse>;
1060
+ /**
1061
+ * --- Car state (Live-VW-Connect-Status, unabhängig von der Car-Konfiguration oben) ---
1062
+ * Returns the current cached car state (available=false if no data received yet).
1063
+ */
1064
+ getCarState: handleUnaryCall<Empty, CarStateResponse>;
1065
+ /** Returns all tracked car states (one per configured car). */
1066
+ getAllCarStates: handleUnaryCall<Empty, GetAllCarStatesResponse>;
1067
+ /**
1068
+ * --- Event stream ---
1069
+ * Opens a server-side stream; Hannah pushes events as they occur.
1070
+ * Pass event_types to filter (empty = all events).
1071
+ * Known event types: "car.parked", "resident.arrived", "resident.departed", "satellite.firmware"
1072
+ */
1073
+ subscribeEvents: handleServerStreamingCall<EventFilter, HannahEvent>;
1074
+ /**
1075
+ * --- Firmware Manager ---
1076
+ * Trigger an immediate OTA update for a satellite (bypasses residents check).
1077
+ */
1078
+ triggerFirmwareUpdate: handleUnaryCall<TriggerFirmwareUpdateRequest, StatusResponse>;
1079
+ /**
1080
+ * Trigger an ordered remote restart (esp_restart()) of a satellite over MQTT.
1081
+ * Diagnostic/rejuvenation tool for suspected resource exhaustion (heap fragmentation
1082
+ * after long uptime) — works even when the satellite's OTA/webserver no longer
1083
+ * respond, since MQTT stays alive in that failure mode.
1084
+ */
1085
+ triggerSatelliteRestart: handleUnaryCall<TriggerSatelliteRestartRequest, StatusResponse>;
1086
+ /**
1087
+ * --- Wakeword Capture ---
1088
+ * Put a satellite in audio-capture mode for wakeword training data collection.
1089
+ * While captured: wakeword detection is suspended, speaker is muted, DND is active.
1090
+ * Hannah relays raw PCM chunks from the satellite to the collector via StreamSatelliteAudio.
1091
+ * The stream stays open until the collector disconnects; Hannah then auto-releases the satellite.
1092
+ */
1093
+ requestSatelliteCapture: handleUnaryCall<SatelliteCaptureRequest, SatelliteCaptureResponse>;
1094
+ releaseSatelliteCapture: handleUnaryCall<SatelliteCaptureRequest, StatusResponse>;
1095
+ streamSatelliteAudio: handleServerStreamingCall<SatelliteCaptureRequest, SatelliteAudioChunk>;
1096
+ /**
1097
+ * Play a plink sound on the satellite, then hold virtual PTT for record_duration seconds.
1098
+ * Returns after PTT is released — Collector calls this in a loop for guided hey-hannah collection.
1099
+ */
1100
+ triggerPlink: handleUnaryCall<TriggerPlinkRequest, StatusResponse>;
1101
+ /**
1102
+ * Bidirectional stream between the Collector and Hannah Core, analogous to TimerConnect.
1103
+ * The Collector initiates and holds the connection open; Hannah pushes CaptureCommands
1104
+ * down to start/stop satellite captures instead of the Collector polling for them.
1105
+ */
1106
+ collectorConnect: handleBidiStreamingCall<CollectorMessage, CaptureCommand>;
1107
+ /**
1108
+ * Unary trigger for external callers (e.g. WebUI) that can't hold a CollectorConnect
1109
+ * stream themselves — Hannah relays the command over its own CollectorConnect stream
1110
+ * to the connected Collector. Fails with ok=false if no Collector is connected.
1111
+ */
1112
+ triggerCollectorCapture: handleUnaryCall<CaptureCommand, StatusResponse>;
1113
+ /**
1114
+ * --- Satellite Proxy (Go gRPC proxy) ---
1115
+ * Bidirectional keepalive stream. Proxy sends heartbeats; Hannah sends TTS
1116
+ * audio commands back (for announcements). While this stream is open, Hannah
1117
+ * disables its own UDP server. If the stream drops, Hannah re-enables UDP.
1118
+ */
1119
+ registerProxy: handleBidiStreamingCall<ProxyHeartbeat, ProxyCommand>;
1120
+ /**
1121
+ * Submit a complete satellite audio session for processing.
1122
+ * Hannah runs the full pipeline (STT → NLU → TTS → MQTT status) and returns
1123
+ * the result so the proxy can play TTS audio back to the satellite.
1124
+ */
1125
+ submitSatelliteAudio: handleUnaryCall<SubmitSatelliteAudioRequest, SubmitSatelliteAudioResponse>;
1126
+ /**
1127
+ * Notify Hannah that a satellite registered or disconnected via the proxy.
1128
+ * Hannah updates its room registry (hannah/rooms MQTT) immediately.
1129
+ */
1130
+ notifySatelliteRegistered: handleUnaryCall<SatelliteRegistration, StatusResponse>;
1131
+ notifySatelliteGone: handleUnaryCall<SatelliteRegistration, StatusResponse>;
1132
+ /**
1133
+ * --- Satellite Provisioning ---
1134
+ * Called by the ioBroker adapter before WebFlash to pre-register a seed + display name + room.
1135
+ * When the satellite first connects with that seed, Hannah links serial → pre-config and clears the seed.
1136
+ */
1137
+ provisionSatellite: handleUnaryCall<ProvisionSatelliteRequest, StatusResponse>;
1138
+ /**
1139
+ * --- Speaker Enrollment ---
1140
+ * Trigger a guided voice-enrollment dialog for user_id at satellite_id (hannah#8);
1141
+ * Core orchestrates the dialog itself. EnrollVoiceprint stays available as the
1142
+ * low-level "store one already-captured sample" call — kept for now (additive,
1143
+ * no hard cut) until hannah#8 confirms Core no longer needs it as an external RPC.
1144
+ */
1145
+ startVoiceEnrollment: handleUnaryCall<StartVoiceEnrollmentRequest, StatusResponse>;
1146
+ enrollVoiceprint: handleUnaryCall<EnrollVoiceprintRequest, StatusResponse>;
1147
+ /**
1148
+ * --- Timer Service ---
1149
+ * Bidirectional stream between the Hannah Timer Service and Hannah Core.
1150
+ * The Timer Service initiates the connection; if Hannah restarts, the service reconnects.
1151
+ * Hannah sends timer commands (create, cancel, list); the service fires events when timers expire.
1152
+ */
1153
+ timerConnect: handleBidiStreamingCall<TimerMessage, TimerCommand>;
1154
+ /**
1155
+ * --- Timer Admin ---
1156
+ * Query and cancel timers independent of the TimerConnect stream — e.g. for an
1157
+ * Admin-UI or Telegram bot listing/cancelling a user's active timers.
1158
+ */
1159
+ getTimers: handleUnaryCall<GetTimersRequest, GetTimersResponse>;
1160
+ deleteTimer: handleUnaryCall<DeleteTimerRequest, StatusResponse>;
1161
+ /**
1162
+ * --- ioBroker Agent ---
1163
+ * Single bidirectional stream between the HannahAgent ioBroker adapter and Hannah Core.
1164
+ * The adapter pushes state updates (device states, presence, text commands);
1165
+ * Hannah pushes device-control commands and on-demand state-subscription requests back.
1166
+ * The adapter initiates the connection; if Hannah restarts, the adapter reconnects.
1167
+ */
1168
+ agentConnect: handleBidiStreamingCall<AgentMessage, AgentCommand>;
1169
+ /**
1170
+ * --- Automations ---
1171
+ * Bidirectional stream for external automation services (e.g. telegram_autoresponder).
1172
+ * The service sends an AutomationRegister identifying itself, then Hannah replies with
1173
+ * an AutomationSnapshot (all users with it currently enabled) followed by live
1174
+ * AutomationStateChanged deltas as users toggle it via SetAutomation/voice.
1175
+ * Chosen over SubscribeEvents so a reconnecting service always gets a fresh snapshot
1176
+ * instead of missing state changes that happened while it was offline.
1177
+ */
1178
+ automationConnect: handleBidiStreamingCall<AutomationMessage, AutomationCommand>;
1179
+ /**
1180
+ * --- Channels ---
1181
+ * Bidirectional stream for channel adapters (e.g. the Telegram service). The adapter
1182
+ * sends a ChannelRegister and keeps the stream open; it counts as available exactly as
1183
+ * long as the stream is open. A second registration for the same service replaces the
1184
+ * first. Link tokens (CreateLinkToken) are redeemed over this stream.
1185
+ */
1186
+ channelConnect: handleBidiStreamingCall<ChannelMessage, ChannelCommand>;
1187
+ /** Currently connected channel adapters and whether they support account linking. */
1188
+ getChannels: handleUnaryCall<Empty, GetChannelsResponse>;
1189
+ /**
1190
+ * --- Infrastructure ---
1191
+ * Service discovery for components: Hannah sends an InfrastructureSnapshot of all
1192
+ * currently available infrastructure services (e.g. the log collector) right after
1193
+ * subscribing, followed by ServiceAvailable/ServiceUnavailable deltas.
1194
+ */
1195
+ subscribeInfrastructure: handleServerStreamingCall<InfrastructureFilter, InfrastructureMessage>;
1196
+ /**
1197
+ * Bidirectional stream for the log collector. The collector sends a LogCollectorRegister
1198
+ * and keeps the stream open; it counts as available exactly as long as the stream is
1199
+ * open, and a second registration for the same instance replaces the first (same
1200
+ * semantics as ChannelConnect). Not related to CollectorConnect (wakeword capture).
1201
+ */
1202
+ logCollectorConnect: handleBidiStreamingCall<LogCollectorMessage, LogCollectorCommand>;
1203
+ /**
1204
+ * --- Activity Log ---
1205
+ * Read access to the Activity Log (#220) for external consumers (WebUI). List returns
1206
+ * full entry detail inline (transcript, intent + intent_meta, answer text) with
1207
+ * cursor-based pagination; audio is fetched separately, decoded server-side from the
1208
+ * stored WAV and streamed as raw PCM chunks.
1209
+ */
1210
+ listActivityLog: handleUnaryCall<ListActivityLogRequest, ListActivityLogResponse>;
1211
+ streamActivityAudio: handleServerStreamingCall<StreamActivityAudioRequest, ActivityAudioChunk>;
1212
+ /** --- Messages (passive per-user mailbox, third notification type) --- */
1213
+ createMessage: handleUnaryCall<CreateMessageRequest, StatusResponse>;
1214
+ listMessages: handleUnaryCall<ListMessagesRequest, ListMessagesResponse>;
1215
+ deleteMessage: handleUnaryCall<DeleteMessageRequest, StatusResponse>;
1216
+ }
1217
+ export interface HannahServiceClient extends Client {
1218
+ /** --- User Registry --- */
1219
+ getUsers(request: GetUsersRequest, callback: (error: ServiceError | null, response: GetUsersResponse) => void): ClientUnaryCall;
1220
+ getUsers(request: GetUsersRequest, metadata: Metadata, callback: (error: ServiceError | null, response: GetUsersResponse) => void): ClientUnaryCall;
1221
+ getUsers(request: GetUsersRequest, metadata: Metadata, options: Partial<CallOptions>, callback: (error: ServiceError | null, response: GetUsersResponse) => void): ClientUnaryCall;
1222
+ getUser(request: GetUserRequest, callback: (error: ServiceError | null, response: UserResponse) => void): ClientUnaryCall;
1223
+ getUser(request: GetUserRequest, metadata: Metadata, callback: (error: ServiceError | null, response: UserResponse) => void): ClientUnaryCall;
1224
+ getUser(request: GetUserRequest, metadata: Metadata, options: Partial<CallOptions>, callback: (error: ServiceError | null, response: UserResponse) => void): ClientUnaryCall;
1225
+ linkAccount(request: LinkAccountRequest, callback: (error: ServiceError | null, response: StatusResponse) => void): ClientUnaryCall;
1226
+ linkAccount(request: LinkAccountRequest, metadata: Metadata, callback: (error: ServiceError | null, response: StatusResponse) => void): ClientUnaryCall;
1227
+ linkAccount(request: LinkAccountRequest, metadata: Metadata, options: Partial<CallOptions>, callback: (error: ServiceError | null, response: StatusResponse) => void): ClientUnaryCall;
1228
+ unlinkAccount(request: UnlinkAccountRequest, callback: (error: ServiceError | null, response: StatusResponse) => void): ClientUnaryCall;
1229
+ unlinkAccount(request: UnlinkAccountRequest, metadata: Metadata, callback: (error: ServiceError | null, response: StatusResponse) => void): ClientUnaryCall;
1230
+ unlinkAccount(request: UnlinkAccountRequest, metadata: Metadata, options: Partial<CallOptions>, callback: (error: ServiceError | null, response: StatusResponse) => void): ClientUnaryCall;
1231
+ /**
1232
+ * One-time token for linking an account via the service's adapter (e.g. Telegram deep link).
1233
+ * Redeemed by the adapter over ChannelConnect.
1234
+ */
1235
+ createLinkToken(request: CreateLinkTokenRequest, callback: (error: ServiceError | null, response: CreateLinkTokenResponse) => void): ClientUnaryCall;
1236
+ createLinkToken(request: CreateLinkTokenRequest, metadata: Metadata, callback: (error: ServiceError | null, response: CreateLinkTokenResponse) => void): ClientUnaryCall;
1237
+ createLinkToken(request: CreateLinkTokenRequest, metadata: Metadata, options: Partial<CallOptions>, callback: (error: ServiceError | null, response: CreateLinkTokenResponse) => void): ClientUnaryCall;
1238
+ setTrustLevel(request: SetTrustLevelRequest, callback: (error: ServiceError | null, response: StatusResponse) => void): ClientUnaryCall;
1239
+ setTrustLevel(request: SetTrustLevelRequest, metadata: Metadata, callback: (error: ServiceError | null, response: StatusResponse) => void): ClientUnaryCall;
1240
+ setTrustLevel(request: SetTrustLevelRequest, metadata: Metadata, options: Partial<CallOptions>, callback: (error: ServiceError | null, response: StatusResponse) => void): ClientUnaryCall;
1241
+ setSystemMessages(request: SetSystemMessagesRequest, callback: (error: ServiceError | null, response: StatusResponse) => void): ClientUnaryCall;
1242
+ setSystemMessages(request: SetSystemMessagesRequest, metadata: Metadata, callback: (error: ServiceError | null, response: StatusResponse) => void): ClientUnaryCall;
1243
+ setSystemMessages(request: SetSystemMessagesRequest, metadata: Metadata, options: Partial<CallOptions>, callback: (error: ServiceError | null, response: StatusResponse) => void): ClientUnaryCall;
1244
+ /**
1245
+ * Enable/disable an automation service (e.g. "telegram_autoresponder") for a user.
1246
+ * Pushes a live update to any connected AutomationConnect stream registered for it.
1247
+ */
1248
+ setAutomation(request: SetAutomationRequest, callback: (error: ServiceError | null, response: StatusResponse) => void): ClientUnaryCall;
1249
+ setAutomation(request: SetAutomationRequest, metadata: Metadata, callback: (error: ServiceError | null, response: StatusResponse) => void): ClientUnaryCall;
1250
+ setAutomation(request: SetAutomationRequest, metadata: Metadata, options: Partial<CallOptions>, callback: (error: ServiceError | null, response: StatusResponse) => void): ClientUnaryCall;
1251
+ login(request: LoginRequest, callback: (error: ServiceError | null, response: UserResponse) => void): ClientUnaryCall;
1252
+ login(request: LoginRequest, metadata: Metadata, callback: (error: ServiceError | null, response: UserResponse) => void): ClientUnaryCall;
1253
+ login(request: LoginRequest, metadata: Metadata, options: Partial<CallOptions>, callback: (error: ServiceError | null, response: UserResponse) => void): ClientUnaryCall;
1254
+ /** --- User-Verwaltung (Admin-UI, #27 Phase 6) --- */
1255
+ createUser(request: CreateUserRequest, callback: (error: ServiceError | null, response: CreateUserResponse) => void): ClientUnaryCall;
1256
+ createUser(request: CreateUserRequest, metadata: Metadata, callback: (error: ServiceError | null, response: CreateUserResponse) => void): ClientUnaryCall;
1257
+ createUser(request: CreateUserRequest, metadata: Metadata, options: Partial<CallOptions>, callback: (error: ServiceError | null, response: CreateUserResponse) => void): ClientUnaryCall;
1258
+ updateUser(request: UpdateUserRequest, callback: (error: ServiceError | null, response: StatusResponse) => void): ClientUnaryCall;
1259
+ updateUser(request: UpdateUserRequest, metadata: Metadata, callback: (error: ServiceError | null, response: StatusResponse) => void): ClientUnaryCall;
1260
+ updateUser(request: UpdateUserRequest, metadata: Metadata, options: Partial<CallOptions>, callback: (error: ServiceError | null, response: StatusResponse) => void): ClientUnaryCall;
1261
+ deleteUser(request: DeleteUserRequest, callback: (error: ServiceError | null, response: StatusResponse) => void): ClientUnaryCall;
1262
+ deleteUser(request: DeleteUserRequest, metadata: Metadata, callback: (error: ServiceError | null, response: StatusResponse) => void): ClientUnaryCall;
1263
+ deleteUser(request: DeleteUserRequest, metadata: Metadata, options: Partial<CallOptions>, callback: (error: ServiceError | null, response: StatusResponse) => void): ClientUnaryCall;
1264
+ /** Residents (Roomies/Guests/Pets) aus dem ioBroker-Adapter-Cache — fürs "Resident verknüpfen"-Dropdown. */
1265
+ getResidents(request: Empty, callback: (error: ServiceError | null, response: GetResidentsResponse) => void): ClientUnaryCall;
1266
+ getResidents(request: Empty, metadata: Metadata, callback: (error: ServiceError | null, response: GetResidentsResponse) => void): ClientUnaryCall;
1267
+ getResidents(request: Empty, metadata: Metadata, options: Partial<CallOptions>, callback: (error: ServiceError | null, response: GetResidentsResponse) => void): ClientUnaryCall;
1268
+ /**
1269
+ * --- Device Control Menu ---
1270
+ * Returns all rooms and devices with current state — for building control menus.
1271
+ */
1272
+ getDevices(request: Empty, callback: (error: ServiceError | null, response: GetDevicesResponse) => void): ClientUnaryCall;
1273
+ getDevices(request: Empty, metadata: Metadata, callback: (error: ServiceError | null, response: GetDevicesResponse) => void): ClientUnaryCall;
1274
+ getDevices(request: Empty, metadata: Metadata, options: Partial<CallOptions>, callback: (error: ServiceError | null, response: GetDevicesResponse) => void): ClientUnaryCall;
1275
+ /** Directly set a device state (bypasses NLU). Trust level check is done by the caller. */
1276
+ controlDevice(request: ControlDeviceRequest, callback: (error: ServiceError | null, response: StatusResponse) => void): ClientUnaryCall;
1277
+ controlDevice(request: ControlDeviceRequest, metadata: Metadata, callback: (error: ServiceError | null, response: StatusResponse) => void): ClientUnaryCall;
1278
+ controlDevice(request: ControlDeviceRequest, metadata: Metadata, options: Partial<CallOptions>, callback: (error: ServiceError | null, response: StatusResponse) => void): ClientUnaryCall;
1279
+ /**
1280
+ * --- Control ---
1281
+ * Submit a plain-text command; Hannah processes it through NLU and returns the answer.
1282
+ */
1283
+ submitText(request: SubmitTextRequest, callback: (error: ServiceError | null, response: SubmitTextResponse) => void): ClientUnaryCall;
1284
+ submitText(request: SubmitTextRequest, metadata: Metadata, callback: (error: ServiceError | null, response: SubmitTextResponse) => void): ClientUnaryCall;
1285
+ submitText(request: SubmitTextRequest, metadata: Metadata, options: Partial<CallOptions>, callback: (error: ServiceError | null, response: SubmitTextResponse) => void): ClientUnaryCall;
1286
+ /** Submit a voice message (OGG/Opus bytes); Hannah does STT → NLU → TTS and returns the result. */
1287
+ submitVoice(request: SubmitVoiceRequest, callback: (error: ServiceError | null, response: SubmitVoiceResponse) => void): ClientUnaryCall;
1288
+ submitVoice(request: SubmitVoiceRequest, metadata: Metadata, callback: (error: ServiceError | null, response: SubmitVoiceResponse) => void): ClientUnaryCall;
1289
+ submitVoice(request: SubmitVoiceRequest, metadata: Metadata, options: Partial<CallOptions>, callback: (error: ServiceError | null, response: SubmitVoiceResponse) => void): ClientUnaryCall;
1290
+ /** Send a TTS announcement to one satellite or all ("all"). */
1291
+ announce(request: AnnounceRequest, callback: (error: ServiceError | null, response: StatusResponse) => void): ClientUnaryCall;
1292
+ announce(request: AnnounceRequest, metadata: Metadata, callback: (error: ServiceError | null, response: StatusResponse) => void): ClientUnaryCall;
1293
+ announce(request: AnnounceRequest, metadata: Metadata, options: Partial<CallOptions>, callback: (error: ServiceError | null, response: StatusResponse) => void): ClientUnaryCall;
1294
+ /**
1295
+ * Send a notification from ioBroker to Hannah. Returns ok=true when queued.
1296
+ * direct=true: skip LLM reformulation. severity: "alert"|"notify"|"info".
1297
+ */
1298
+ notify(request: AgentNotification, callback: (error: ServiceError | null, response: StatusResponse) => void): ClientUnaryCall;
1299
+ notify(request: AgentNotification, metadata: Metadata, callback: (error: ServiceError | null, response: StatusResponse) => void): ClientUnaryCall;
1300
+ notify(request: AgentNotification, metadata: Metadata, options: Partial<CallOptions>, callback: (error: ServiceError | null, response: StatusResponse) => void): ClientUnaryCall;
1301
+ /** List all known satellites (DB + live status merged). */
1302
+ getSatellites(request: Empty, callback: (error: ServiceError | null, response: GetSatellitesResponse) => void): ClientUnaryCall;
1303
+ getSatellites(request: Empty, metadata: Metadata, callback: (error: ServiceError | null, response: GetSatellitesResponse) => void): ClientUnaryCall;
1304
+ getSatellites(request: Empty, metadata: Metadata, options: Partial<CallOptions>, callback: (error: ServiceError | null, response: GetSatellitesResponse) => void): ClientUnaryCall;
1305
+ /** --- Satellites (Admin-UI, #27 Phase 2) --- */
1306
+ setSatelliteRoom(request: SetSatelliteRoomRequest, callback: (error: ServiceError | null, response: StatusResponse) => void): ClientUnaryCall;
1307
+ setSatelliteRoom(request: SetSatelliteRoomRequest, metadata: Metadata, callback: (error: ServiceError | null, response: StatusResponse) => void): ClientUnaryCall;
1308
+ setSatelliteRoom(request: SetSatelliteRoomRequest, metadata: Metadata, options: Partial<CallOptions>, callback: (error: ServiceError | null, response: StatusResponse) => void): ClientUnaryCall;
1309
+ setSatelliteDisplayName(request: SetSatelliteDisplayNameRequest, callback: (error: ServiceError | null, response: StatusResponse) => void): ClientUnaryCall;
1310
+ setSatelliteDisplayName(request: SetSatelliteDisplayNameRequest, metadata: Metadata, callback: (error: ServiceError | null, response: StatusResponse) => void): ClientUnaryCall;
1311
+ setSatelliteDisplayName(request: SetSatelliteDisplayNameRequest, metadata: Metadata, options: Partial<CallOptions>, callback: (error: ServiceError | null, response: StatusResponse) => void): ClientUnaryCall;
1312
+ /** Assign a satellite to a Person (User), independent of its room. #31 */
1313
+ setSatelliteOwner(request: SetSatelliteOwnerRequest, callback: (error: ServiceError | null, response: StatusResponse) => void): ClientUnaryCall;
1314
+ setSatelliteOwner(request: SetSatelliteOwnerRequest, metadata: Metadata, callback: (error: ServiceError | null, response: StatusResponse) => void): ClientUnaryCall;
1315
+ setSatelliteOwner(request: SetSatelliteOwnerRequest, metadata: Metadata, options: Partial<CallOptions>, callback: (error: ServiceError | null, response: StatusResponse) => void): ClientUnaryCall;
1316
+ /**
1317
+ * Toggle whether the satellite's mic reopens after a Smalltalk answer instead of
1318
+ * waiting for wake-word/PTT again (silence-timeout lives in the satellite firmware). #158
1319
+ */
1320
+ setSatelliteSmalltalkFollowup(request: SetSatelliteSmalltalkFollowupRequest, callback: (error: ServiceError | null, response: StatusResponse) => void): ClientUnaryCall;
1321
+ setSatelliteSmalltalkFollowup(request: SetSatelliteSmalltalkFollowupRequest, metadata: Metadata, callback: (error: ServiceError | null, response: StatusResponse) => void): ClientUnaryCall;
1322
+ setSatelliteSmalltalkFollowup(request: SetSatelliteSmalltalkFollowupRequest, metadata: Metadata, options: Partial<CallOptions>, callback: (error: ServiceError | null, response: StatusResponse) => void): ClientUnaryCall;
1323
+ /** Delete existing satellite */
1324
+ deleteSatellite(request: DeleteSatelliteRequest, callback: (error: ServiceError | null, response: StatusResponse) => void): ClientUnaryCall;
1325
+ deleteSatellite(request: DeleteSatelliteRequest, metadata: Metadata, callback: (error: ServiceError | null, response: StatusResponse) => void): ClientUnaryCall;
1326
+ deleteSatellite(request: DeleteSatelliteRequest, metadata: Metadata, options: Partial<CallOptions>, callback: (error: ServiceError | null, response: StatusResponse) => void): ClientUnaryCall;
1327
+ /** --- Rooms/Groups (Admin-UI, #27 Phase 1) --- */
1328
+ getRooms(request: Empty, callback: (error: ServiceError | null, response: GetRoomsResponse) => void): ClientUnaryCall;
1329
+ getRooms(request: Empty, metadata: Metadata, callback: (error: ServiceError | null, response: GetRoomsResponse) => void): ClientUnaryCall;
1330
+ getRooms(request: Empty, metadata: Metadata, options: Partial<CallOptions>, callback: (error: ServiceError | null, response: GetRoomsResponse) => void): ClientUnaryCall;
1331
+ getGroups(request: Empty, callback: (error: ServiceError | null, response: GetGroupsResponse) => void): ClientUnaryCall;
1332
+ getGroups(request: Empty, metadata: Metadata, callback: (error: ServiceError | null, response: GetGroupsResponse) => void): ClientUnaryCall;
1333
+ getGroups(request: Empty, metadata: Metadata, options: Partial<CallOptions>, callback: (error: ServiceError | null, response: GetGroupsResponse) => void): ClientUnaryCall;
1334
+ createGroup(request: CreateGroupRequest, callback: (error: ServiceError | null, response: StatusResponse) => void): ClientUnaryCall;
1335
+ createGroup(request: CreateGroupRequest, metadata: Metadata, callback: (error: ServiceError | null, response: StatusResponse) => void): ClientUnaryCall;
1336
+ createGroup(request: CreateGroupRequest, metadata: Metadata, options: Partial<CallOptions>, callback: (error: ServiceError | null, response: StatusResponse) => void): ClientUnaryCall;
1337
+ updateGroup(request: UpdateGroupRequest, callback: (error: ServiceError | null, response: StatusResponse) => void): ClientUnaryCall;
1338
+ updateGroup(request: UpdateGroupRequest, metadata: Metadata, callback: (error: ServiceError | null, response: StatusResponse) => void): ClientUnaryCall;
1339
+ updateGroup(request: UpdateGroupRequest, metadata: Metadata, options: Partial<CallOptions>, callback: (error: ServiceError | null, response: StatusResponse) => void): ClientUnaryCall;
1340
+ deleteGroup(request: DeleteGroupRequest, callback: (error: ServiceError | null, response: StatusResponse) => void): ClientUnaryCall;
1341
+ deleteGroup(request: DeleteGroupRequest, metadata: Metadata, callback: (error: ServiceError | null, response: StatusResponse) => void): ClientUnaryCall;
1342
+ deleteGroup(request: DeleteGroupRequest, metadata: Metadata, options: Partial<CallOptions>, callback: (error: ServiceError | null, response: StatusResponse) => void): ClientUnaryCall;
1343
+ setGroupSatellites(request: SetGroupSatellitesRequest, callback: (error: ServiceError | null, response: StatusResponse) => void): ClientUnaryCall;
1344
+ setGroupSatellites(request: SetGroupSatellitesRequest, metadata: Metadata, callback: (error: ServiceError | null, response: StatusResponse) => void): ClientUnaryCall;
1345
+ setGroupSatellites(request: SetGroupSatellitesRequest, metadata: Metadata, options: Partial<CallOptions>, callback: (error: ServiceError | null, response: StatusResponse) => void): ClientUnaryCall;
1346
+ /** --- Triggers (Admin-UI, #28) --- */
1347
+ getTriggers(request: Empty, callback: (error: ServiceError | null, response: GetTriggersResponse) => void): ClientUnaryCall;
1348
+ getTriggers(request: Empty, metadata: Metadata, callback: (error: ServiceError | null, response: GetTriggersResponse) => void): ClientUnaryCall;
1349
+ getTriggers(request: Empty, metadata: Metadata, options: Partial<CallOptions>, callback: (error: ServiceError | null, response: GetTriggersResponse) => void): ClientUnaryCall;
1350
+ createTrigger(request: CreateTriggerRequest, callback: (error: ServiceError | null, response: StatusResponse) => void): ClientUnaryCall;
1351
+ createTrigger(request: CreateTriggerRequest, metadata: Metadata, callback: (error: ServiceError | null, response: StatusResponse) => void): ClientUnaryCall;
1352
+ createTrigger(request: CreateTriggerRequest, metadata: Metadata, options: Partial<CallOptions>, callback: (error: ServiceError | null, response: StatusResponse) => void): ClientUnaryCall;
1353
+ updateTrigger(request: UpdateTriggerRequest, callback: (error: ServiceError | null, response: StatusResponse) => void): ClientUnaryCall;
1354
+ updateTrigger(request: UpdateTriggerRequest, metadata: Metadata, callback: (error: ServiceError | null, response: StatusResponse) => void): ClientUnaryCall;
1355
+ updateTrigger(request: UpdateTriggerRequest, metadata: Metadata, options: Partial<CallOptions>, callback: (error: ServiceError | null, response: StatusResponse) => void): ClientUnaryCall;
1356
+ deleteTrigger(request: DeleteTriggerRequest, callback: (error: ServiceError | null, response: StatusResponse) => void): ClientUnaryCall;
1357
+ deleteTrigger(request: DeleteTriggerRequest, metadata: Metadata, callback: (error: ServiceError | null, response: StatusResponse) => void): ClientUnaryCall;
1358
+ deleteTrigger(request: DeleteTriggerRequest, metadata: Metadata, options: Partial<CallOptions>, callback: (error: ServiceError | null, response: StatusResponse) => void): ClientUnaryCall;
1359
+ /** --- Alarms (Wecker, #4) --- */
1360
+ getAlarms(request: Empty, callback: (error: ServiceError | null, response: GetAlarmsResponse) => void): ClientUnaryCall;
1361
+ getAlarms(request: Empty, metadata: Metadata, callback: (error: ServiceError | null, response: GetAlarmsResponse) => void): ClientUnaryCall;
1362
+ getAlarms(request: Empty, metadata: Metadata, options: Partial<CallOptions>, callback: (error: ServiceError | null, response: GetAlarmsResponse) => void): ClientUnaryCall;
1363
+ createAlarm(request: CreateAlarmRequest, callback: (error: ServiceError | null, response: CreateAlarmResponse) => void): ClientUnaryCall;
1364
+ createAlarm(request: CreateAlarmRequest, metadata: Metadata, callback: (error: ServiceError | null, response: CreateAlarmResponse) => void): ClientUnaryCall;
1365
+ createAlarm(request: CreateAlarmRequest, metadata: Metadata, options: Partial<CallOptions>, callback: (error: ServiceError | null, response: CreateAlarmResponse) => void): ClientUnaryCall;
1366
+ updateAlarm(request: UpdateAlarmRequest, callback: (error: ServiceError | null, response: StatusResponse) => void): ClientUnaryCall;
1367
+ updateAlarm(request: UpdateAlarmRequest, metadata: Metadata, callback: (error: ServiceError | null, response: StatusResponse) => void): ClientUnaryCall;
1368
+ updateAlarm(request: UpdateAlarmRequest, metadata: Metadata, options: Partial<CallOptions>, callback: (error: ServiceError | null, response: StatusResponse) => void): ClientUnaryCall;
1369
+ deleteAlarm(request: DeleteAlarmRequest, callback: (error: ServiceError | null, response: StatusResponse) => void): ClientUnaryCall;
1370
+ deleteAlarm(request: DeleteAlarmRequest, metadata: Metadata, callback: (error: ServiceError | null, response: StatusResponse) => void): ClientUnaryCall;
1371
+ deleteAlarm(request: DeleteAlarmRequest, metadata: Metadata, options: Partial<CallOptions>, callback: (error: ServiceError | null, response: StatusResponse) => void): ClientUnaryCall;
1372
+ /**
1373
+ * --- Settings (Admin-UI, #27 Phase 5) ---
1374
+ * CreateSetting/DeleteSetting wurden mit #115 entfernt: ble.tags/cars haben jetzt
1375
+ * eigene Modelle+CRUD (unten), nlu/iobroker.state_names/llm.system_prompt sind immer
1376
+ * vorab bekannt/geseedet — es gibt keinen verbleibenden Bedarf, neue Settings anzulegen.
1377
+ */
1378
+ getSettings(request: Empty, callback: (error: ServiceError | null, response: GetSettingsResponse) => void): ClientUnaryCall;
1379
+ getSettings(request: Empty, metadata: Metadata, callback: (error: ServiceError | null, response: GetSettingsResponse) => void): ClientUnaryCall;
1380
+ getSettings(request: Empty, metadata: Metadata, options: Partial<CallOptions>, callback: (error: ServiceError | null, response: GetSettingsResponse) => void): ClientUnaryCall;
1381
+ updateConfig(request: UpdateConfigRequest, callback: (error: ServiceError | null, response: StatusResponse) => void): ClientUnaryCall;
1382
+ updateConfig(request: UpdateConfigRequest, metadata: Metadata, callback: (error: ServiceError | null, response: StatusResponse) => void): ClientUnaryCall;
1383
+ updateConfig(request: UpdateConfigRequest, metadata: Metadata, options: Partial<CallOptions>, callback: (error: ServiceError | null, response: StatusResponse) => void): ClientUnaryCall;
1384
+ /** --- BLE Tags (Admin-UI, #115 — eigenes Modell statt Settings-JSON-Blob) --- */
1385
+ getBleTags(request: Empty, callback: (error: ServiceError | null, response: GetBleTagsResponse) => void): ClientUnaryCall;
1386
+ getBleTags(request: Empty, metadata: Metadata, callback: (error: ServiceError | null, response: GetBleTagsResponse) => void): ClientUnaryCall;
1387
+ getBleTags(request: Empty, metadata: Metadata, options: Partial<CallOptions>, callback: (error: ServiceError | null, response: GetBleTagsResponse) => void): ClientUnaryCall;
1388
+ createBleTag(request: CreateBleTagRequest, callback: (error: ServiceError | null, response: CreateBleTagResponse) => void): ClientUnaryCall;
1389
+ createBleTag(request: CreateBleTagRequest, metadata: Metadata, callback: (error: ServiceError | null, response: CreateBleTagResponse) => void): ClientUnaryCall;
1390
+ createBleTag(request: CreateBleTagRequest, metadata: Metadata, options: Partial<CallOptions>, callback: (error: ServiceError | null, response: CreateBleTagResponse) => void): ClientUnaryCall;
1391
+ updateBleTag(request: UpdateBleTagRequest, callback: (error: ServiceError | null, response: StatusResponse) => void): ClientUnaryCall;
1392
+ updateBleTag(request: UpdateBleTagRequest, metadata: Metadata, callback: (error: ServiceError | null, response: StatusResponse) => void): ClientUnaryCall;
1393
+ updateBleTag(request: UpdateBleTagRequest, metadata: Metadata, options: Partial<CallOptions>, callback: (error: ServiceError | null, response: StatusResponse) => void): ClientUnaryCall;
1394
+ deleteBleTag(request: DeleteBleTagRequest, callback: (error: ServiceError | null, response: StatusResponse) => void): ClientUnaryCall;
1395
+ deleteBleTag(request: DeleteBleTagRequest, metadata: Metadata, callback: (error: ServiceError | null, response: StatusResponse) => void): ClientUnaryCall;
1396
+ deleteBleTag(request: DeleteBleTagRequest, metadata: Metadata, options: Partial<CallOptions>, callback: (error: ServiceError | null, response: StatusResponse) => void): ClientUnaryCall;
1397
+ /** --- Presence Sources (Admin-UI, hannah#294 — presence fusion) --- */
1398
+ getPresenceSources(request: Empty, callback: (error: ServiceError | null, response: GetPresenceSourcesResponse) => void): ClientUnaryCall;
1399
+ getPresenceSources(request: Empty, metadata: Metadata, callback: (error: ServiceError | null, response: GetPresenceSourcesResponse) => void): ClientUnaryCall;
1400
+ getPresenceSources(request: Empty, metadata: Metadata, options: Partial<CallOptions>, callback: (error: ServiceError | null, response: GetPresenceSourcesResponse) => void): ClientUnaryCall;
1401
+ createPresenceSource(request: CreatePresenceSourceRequest, callback: (error: ServiceError | null, response: CreatePresenceSourceResponse) => void): ClientUnaryCall;
1402
+ createPresenceSource(request: CreatePresenceSourceRequest, metadata: Metadata, callback: (error: ServiceError | null, response: CreatePresenceSourceResponse) => void): ClientUnaryCall;
1403
+ createPresenceSource(request: CreatePresenceSourceRequest, metadata: Metadata, options: Partial<CallOptions>, callback: (error: ServiceError | null, response: CreatePresenceSourceResponse) => void): ClientUnaryCall;
1404
+ updatePresenceSource(request: UpdatePresenceSourceRequest, callback: (error: ServiceError | null, response: StatusResponse) => void): ClientUnaryCall;
1405
+ updatePresenceSource(request: UpdatePresenceSourceRequest, metadata: Metadata, callback: (error: ServiceError | null, response: StatusResponse) => void): ClientUnaryCall;
1406
+ updatePresenceSource(request: UpdatePresenceSourceRequest, metadata: Metadata, options: Partial<CallOptions>, callback: (error: ServiceError | null, response: StatusResponse) => void): ClientUnaryCall;
1407
+ deletePresenceSource(request: DeletePresenceSourceRequest, callback: (error: ServiceError | null, response: StatusResponse) => void): ClientUnaryCall;
1408
+ deletePresenceSource(request: DeletePresenceSourceRequest, metadata: Metadata, callback: (error: ServiceError | null, response: StatusResponse) => void): ClientUnaryCall;
1409
+ deletePresenceSource(request: DeletePresenceSourceRequest, metadata: Metadata, options: Partial<CallOptions>, callback: (error: ServiceError | null, response: StatusResponse) => void): ClientUnaryCall;
1410
+ /** --- Cars (Admin-UI, #115 — eigenes Modell + user_to_car-Pivot statt Settings-JSON-Blob) --- */
1411
+ getCars(request: Empty, callback: (error: ServiceError | null, response: GetCarsResponse) => void): ClientUnaryCall;
1412
+ getCars(request: Empty, metadata: Metadata, callback: (error: ServiceError | null, response: GetCarsResponse) => void): ClientUnaryCall;
1413
+ getCars(request: Empty, metadata: Metadata, options: Partial<CallOptions>, callback: (error: ServiceError | null, response: GetCarsResponse) => void): ClientUnaryCall;
1414
+ createCar(request: CreateCarRequest, callback: (error: ServiceError | null, response: CreateCarResponse) => void): ClientUnaryCall;
1415
+ createCar(request: CreateCarRequest, metadata: Metadata, callback: (error: ServiceError | null, response: CreateCarResponse) => void): ClientUnaryCall;
1416
+ createCar(request: CreateCarRequest, metadata: Metadata, options: Partial<CallOptions>, callback: (error: ServiceError | null, response: CreateCarResponse) => void): ClientUnaryCall;
1417
+ updateCar(request: UpdateCarRequest, callback: (error: ServiceError | null, response: StatusResponse) => void): ClientUnaryCall;
1418
+ updateCar(request: UpdateCarRequest, metadata: Metadata, callback: (error: ServiceError | null, response: StatusResponse) => void): ClientUnaryCall;
1419
+ updateCar(request: UpdateCarRequest, metadata: Metadata, options: Partial<CallOptions>, callback: (error: ServiceError | null, response: StatusResponse) => void): ClientUnaryCall;
1420
+ deleteCar(request: DeleteCarRequest, callback: (error: ServiceError | null, response: StatusResponse) => void): ClientUnaryCall;
1421
+ deleteCar(request: DeleteCarRequest, metadata: Metadata, callback: (error: ServiceError | null, response: StatusResponse) => void): ClientUnaryCall;
1422
+ deleteCar(request: DeleteCarRequest, metadata: Metadata, options: Partial<CallOptions>, callback: (error: ServiceError | null, response: StatusResponse) => void): ClientUnaryCall;
1423
+ /**
1424
+ * --- Car state (Live-VW-Connect-Status, unabhängig von der Car-Konfiguration oben) ---
1425
+ * Returns the current cached car state (available=false if no data received yet).
1426
+ */
1427
+ getCarState(request: Empty, callback: (error: ServiceError | null, response: CarStateResponse) => void): ClientUnaryCall;
1428
+ getCarState(request: Empty, metadata: Metadata, callback: (error: ServiceError | null, response: CarStateResponse) => void): ClientUnaryCall;
1429
+ getCarState(request: Empty, metadata: Metadata, options: Partial<CallOptions>, callback: (error: ServiceError | null, response: CarStateResponse) => void): ClientUnaryCall;
1430
+ /** Returns all tracked car states (one per configured car). */
1431
+ getAllCarStates(request: Empty, callback: (error: ServiceError | null, response: GetAllCarStatesResponse) => void): ClientUnaryCall;
1432
+ getAllCarStates(request: Empty, metadata: Metadata, callback: (error: ServiceError | null, response: GetAllCarStatesResponse) => void): ClientUnaryCall;
1433
+ getAllCarStates(request: Empty, metadata: Metadata, options: Partial<CallOptions>, callback: (error: ServiceError | null, response: GetAllCarStatesResponse) => void): ClientUnaryCall;
1434
+ /**
1435
+ * --- Event stream ---
1436
+ * Opens a server-side stream; Hannah pushes events as they occur.
1437
+ * Pass event_types to filter (empty = all events).
1438
+ * Known event types: "car.parked", "resident.arrived", "resident.departed", "satellite.firmware"
1439
+ */
1440
+ subscribeEvents(request: EventFilter, options?: Partial<CallOptions>): ClientReadableStream<HannahEvent>;
1441
+ subscribeEvents(request: EventFilter, metadata?: Metadata, options?: Partial<CallOptions>): ClientReadableStream<HannahEvent>;
1442
+ /**
1443
+ * --- Firmware Manager ---
1444
+ * Trigger an immediate OTA update for a satellite (bypasses residents check).
1445
+ */
1446
+ triggerFirmwareUpdate(request: TriggerFirmwareUpdateRequest, callback: (error: ServiceError | null, response: StatusResponse) => void): ClientUnaryCall;
1447
+ triggerFirmwareUpdate(request: TriggerFirmwareUpdateRequest, metadata: Metadata, callback: (error: ServiceError | null, response: StatusResponse) => void): ClientUnaryCall;
1448
+ triggerFirmwareUpdate(request: TriggerFirmwareUpdateRequest, metadata: Metadata, options: Partial<CallOptions>, callback: (error: ServiceError | null, response: StatusResponse) => void): ClientUnaryCall;
1449
+ /**
1450
+ * Trigger an ordered remote restart (esp_restart()) of a satellite over MQTT.
1451
+ * Diagnostic/rejuvenation tool for suspected resource exhaustion (heap fragmentation
1452
+ * after long uptime) — works even when the satellite's OTA/webserver no longer
1453
+ * respond, since MQTT stays alive in that failure mode.
1454
+ */
1455
+ triggerSatelliteRestart(request: TriggerSatelliteRestartRequest, callback: (error: ServiceError | null, response: StatusResponse) => void): ClientUnaryCall;
1456
+ triggerSatelliteRestart(request: TriggerSatelliteRestartRequest, metadata: Metadata, callback: (error: ServiceError | null, response: StatusResponse) => void): ClientUnaryCall;
1457
+ triggerSatelliteRestart(request: TriggerSatelliteRestartRequest, metadata: Metadata, options: Partial<CallOptions>, callback: (error: ServiceError | null, response: StatusResponse) => void): ClientUnaryCall;
1458
+ /**
1459
+ * --- Wakeword Capture ---
1460
+ * Put a satellite in audio-capture mode for wakeword training data collection.
1461
+ * While captured: wakeword detection is suspended, speaker is muted, DND is active.
1462
+ * Hannah relays raw PCM chunks from the satellite to the collector via StreamSatelliteAudio.
1463
+ * The stream stays open until the collector disconnects; Hannah then auto-releases the satellite.
1464
+ */
1465
+ requestSatelliteCapture(request: SatelliteCaptureRequest, callback: (error: ServiceError | null, response: SatelliteCaptureResponse) => void): ClientUnaryCall;
1466
+ requestSatelliteCapture(request: SatelliteCaptureRequest, metadata: Metadata, callback: (error: ServiceError | null, response: SatelliteCaptureResponse) => void): ClientUnaryCall;
1467
+ requestSatelliteCapture(request: SatelliteCaptureRequest, metadata: Metadata, options: Partial<CallOptions>, callback: (error: ServiceError | null, response: SatelliteCaptureResponse) => void): ClientUnaryCall;
1468
+ releaseSatelliteCapture(request: SatelliteCaptureRequest, callback: (error: ServiceError | null, response: StatusResponse) => void): ClientUnaryCall;
1469
+ releaseSatelliteCapture(request: SatelliteCaptureRequest, metadata: Metadata, callback: (error: ServiceError | null, response: StatusResponse) => void): ClientUnaryCall;
1470
+ releaseSatelliteCapture(request: SatelliteCaptureRequest, metadata: Metadata, options: Partial<CallOptions>, callback: (error: ServiceError | null, response: StatusResponse) => void): ClientUnaryCall;
1471
+ streamSatelliteAudio(request: SatelliteCaptureRequest, options?: Partial<CallOptions>): ClientReadableStream<SatelliteAudioChunk>;
1472
+ streamSatelliteAudio(request: SatelliteCaptureRequest, metadata?: Metadata, options?: Partial<CallOptions>): ClientReadableStream<SatelliteAudioChunk>;
1473
+ /**
1474
+ * Play a plink sound on the satellite, then hold virtual PTT for record_duration seconds.
1475
+ * Returns after PTT is released — Collector calls this in a loop for guided hey-hannah collection.
1476
+ */
1477
+ triggerPlink(request: TriggerPlinkRequest, callback: (error: ServiceError | null, response: StatusResponse) => void): ClientUnaryCall;
1478
+ triggerPlink(request: TriggerPlinkRequest, metadata: Metadata, callback: (error: ServiceError | null, response: StatusResponse) => void): ClientUnaryCall;
1479
+ triggerPlink(request: TriggerPlinkRequest, metadata: Metadata, options: Partial<CallOptions>, callback: (error: ServiceError | null, response: StatusResponse) => void): ClientUnaryCall;
1480
+ /**
1481
+ * Bidirectional stream between the Collector and Hannah Core, analogous to TimerConnect.
1482
+ * The Collector initiates and holds the connection open; Hannah pushes CaptureCommands
1483
+ * down to start/stop satellite captures instead of the Collector polling for them.
1484
+ */
1485
+ collectorConnect(): ClientDuplexStream<CollectorMessage, CaptureCommand>;
1486
+ collectorConnect(options: Partial<CallOptions>): ClientDuplexStream<CollectorMessage, CaptureCommand>;
1487
+ collectorConnect(metadata: Metadata, options?: Partial<CallOptions>): ClientDuplexStream<CollectorMessage, CaptureCommand>;
1488
+ /**
1489
+ * Unary trigger for external callers (e.g. WebUI) that can't hold a CollectorConnect
1490
+ * stream themselves — Hannah relays the command over its own CollectorConnect stream
1491
+ * to the connected Collector. Fails with ok=false if no Collector is connected.
1492
+ */
1493
+ triggerCollectorCapture(request: CaptureCommand, callback: (error: ServiceError | null, response: StatusResponse) => void): ClientUnaryCall;
1494
+ triggerCollectorCapture(request: CaptureCommand, metadata: Metadata, callback: (error: ServiceError | null, response: StatusResponse) => void): ClientUnaryCall;
1495
+ triggerCollectorCapture(request: CaptureCommand, metadata: Metadata, options: Partial<CallOptions>, callback: (error: ServiceError | null, response: StatusResponse) => void): ClientUnaryCall;
1496
+ /**
1497
+ * --- Satellite Proxy (Go gRPC proxy) ---
1498
+ * Bidirectional keepalive stream. Proxy sends heartbeats; Hannah sends TTS
1499
+ * audio commands back (for announcements). While this stream is open, Hannah
1500
+ * disables its own UDP server. If the stream drops, Hannah re-enables UDP.
1501
+ */
1502
+ registerProxy(): ClientDuplexStream<ProxyHeartbeat, ProxyCommand>;
1503
+ registerProxy(options: Partial<CallOptions>): ClientDuplexStream<ProxyHeartbeat, ProxyCommand>;
1504
+ registerProxy(metadata: Metadata, options?: Partial<CallOptions>): ClientDuplexStream<ProxyHeartbeat, ProxyCommand>;
1505
+ /**
1506
+ * Submit a complete satellite audio session for processing.
1507
+ * Hannah runs the full pipeline (STT → NLU → TTS → MQTT status) and returns
1508
+ * the result so the proxy can play TTS audio back to the satellite.
1509
+ */
1510
+ submitSatelliteAudio(request: SubmitSatelliteAudioRequest, callback: (error: ServiceError | null, response: SubmitSatelliteAudioResponse) => void): ClientUnaryCall;
1511
+ submitSatelliteAudio(request: SubmitSatelliteAudioRequest, metadata: Metadata, callback: (error: ServiceError | null, response: SubmitSatelliteAudioResponse) => void): ClientUnaryCall;
1512
+ submitSatelliteAudio(request: SubmitSatelliteAudioRequest, metadata: Metadata, options: Partial<CallOptions>, callback: (error: ServiceError | null, response: SubmitSatelliteAudioResponse) => void): ClientUnaryCall;
1513
+ /**
1514
+ * Notify Hannah that a satellite registered or disconnected via the proxy.
1515
+ * Hannah updates its room registry (hannah/rooms MQTT) immediately.
1516
+ */
1517
+ notifySatelliteRegistered(request: SatelliteRegistration, callback: (error: ServiceError | null, response: StatusResponse) => void): ClientUnaryCall;
1518
+ notifySatelliteRegistered(request: SatelliteRegistration, metadata: Metadata, callback: (error: ServiceError | null, response: StatusResponse) => void): ClientUnaryCall;
1519
+ notifySatelliteRegistered(request: SatelliteRegistration, metadata: Metadata, options: Partial<CallOptions>, callback: (error: ServiceError | null, response: StatusResponse) => void): ClientUnaryCall;
1520
+ notifySatelliteGone(request: SatelliteRegistration, callback: (error: ServiceError | null, response: StatusResponse) => void): ClientUnaryCall;
1521
+ notifySatelliteGone(request: SatelliteRegistration, metadata: Metadata, callback: (error: ServiceError | null, response: StatusResponse) => void): ClientUnaryCall;
1522
+ notifySatelliteGone(request: SatelliteRegistration, metadata: Metadata, options: Partial<CallOptions>, callback: (error: ServiceError | null, response: StatusResponse) => void): ClientUnaryCall;
1523
+ /**
1524
+ * --- Satellite Provisioning ---
1525
+ * Called by the ioBroker adapter before WebFlash to pre-register a seed + display name + room.
1526
+ * When the satellite first connects with that seed, Hannah links serial → pre-config and clears the seed.
1527
+ */
1528
+ provisionSatellite(request: ProvisionSatelliteRequest, callback: (error: ServiceError | null, response: StatusResponse) => void): ClientUnaryCall;
1529
+ provisionSatellite(request: ProvisionSatelliteRequest, metadata: Metadata, callback: (error: ServiceError | null, response: StatusResponse) => void): ClientUnaryCall;
1530
+ provisionSatellite(request: ProvisionSatelliteRequest, metadata: Metadata, options: Partial<CallOptions>, callback: (error: ServiceError | null, response: StatusResponse) => void): ClientUnaryCall;
1531
+ /**
1532
+ * --- Speaker Enrollment ---
1533
+ * Trigger a guided voice-enrollment dialog for user_id at satellite_id (hannah#8);
1534
+ * Core orchestrates the dialog itself. EnrollVoiceprint stays available as the
1535
+ * low-level "store one already-captured sample" call — kept for now (additive,
1536
+ * no hard cut) until hannah#8 confirms Core no longer needs it as an external RPC.
1537
+ */
1538
+ startVoiceEnrollment(request: StartVoiceEnrollmentRequest, callback: (error: ServiceError | null, response: StatusResponse) => void): ClientUnaryCall;
1539
+ startVoiceEnrollment(request: StartVoiceEnrollmentRequest, metadata: Metadata, callback: (error: ServiceError | null, response: StatusResponse) => void): ClientUnaryCall;
1540
+ startVoiceEnrollment(request: StartVoiceEnrollmentRequest, metadata: Metadata, options: Partial<CallOptions>, callback: (error: ServiceError | null, response: StatusResponse) => void): ClientUnaryCall;
1541
+ enrollVoiceprint(request: EnrollVoiceprintRequest, callback: (error: ServiceError | null, response: StatusResponse) => void): ClientUnaryCall;
1542
+ enrollVoiceprint(request: EnrollVoiceprintRequest, metadata: Metadata, callback: (error: ServiceError | null, response: StatusResponse) => void): ClientUnaryCall;
1543
+ enrollVoiceprint(request: EnrollVoiceprintRequest, metadata: Metadata, options: Partial<CallOptions>, callback: (error: ServiceError | null, response: StatusResponse) => void): ClientUnaryCall;
1544
+ /**
1545
+ * --- Timer Service ---
1546
+ * Bidirectional stream between the Hannah Timer Service and Hannah Core.
1547
+ * The Timer Service initiates the connection; if Hannah restarts, the service reconnects.
1548
+ * Hannah sends timer commands (create, cancel, list); the service fires events when timers expire.
1549
+ */
1550
+ timerConnect(): ClientDuplexStream<TimerMessage, TimerCommand>;
1551
+ timerConnect(options: Partial<CallOptions>): ClientDuplexStream<TimerMessage, TimerCommand>;
1552
+ timerConnect(metadata: Metadata, options?: Partial<CallOptions>): ClientDuplexStream<TimerMessage, TimerCommand>;
1553
+ /**
1554
+ * --- Timer Admin ---
1555
+ * Query and cancel timers independent of the TimerConnect stream — e.g. for an
1556
+ * Admin-UI or Telegram bot listing/cancelling a user's active timers.
1557
+ */
1558
+ getTimers(request: GetTimersRequest, callback: (error: ServiceError | null, response: GetTimersResponse) => void): ClientUnaryCall;
1559
+ getTimers(request: GetTimersRequest, metadata: Metadata, callback: (error: ServiceError | null, response: GetTimersResponse) => void): ClientUnaryCall;
1560
+ getTimers(request: GetTimersRequest, metadata: Metadata, options: Partial<CallOptions>, callback: (error: ServiceError | null, response: GetTimersResponse) => void): ClientUnaryCall;
1561
+ deleteTimer(request: DeleteTimerRequest, callback: (error: ServiceError | null, response: StatusResponse) => void): ClientUnaryCall;
1562
+ deleteTimer(request: DeleteTimerRequest, metadata: Metadata, callback: (error: ServiceError | null, response: StatusResponse) => void): ClientUnaryCall;
1563
+ deleteTimer(request: DeleteTimerRequest, metadata: Metadata, options: Partial<CallOptions>, callback: (error: ServiceError | null, response: StatusResponse) => void): ClientUnaryCall;
1564
+ /**
1565
+ * --- ioBroker Agent ---
1566
+ * Single bidirectional stream between the HannahAgent ioBroker adapter and Hannah Core.
1567
+ * The adapter pushes state updates (device states, presence, text commands);
1568
+ * Hannah pushes device-control commands and on-demand state-subscription requests back.
1569
+ * The adapter initiates the connection; if Hannah restarts, the adapter reconnects.
1570
+ */
1571
+ agentConnect(): ClientDuplexStream<AgentMessage, AgentCommand>;
1572
+ agentConnect(options: Partial<CallOptions>): ClientDuplexStream<AgentMessage, AgentCommand>;
1573
+ agentConnect(metadata: Metadata, options?: Partial<CallOptions>): ClientDuplexStream<AgentMessage, AgentCommand>;
1574
+ /**
1575
+ * --- Automations ---
1576
+ * Bidirectional stream for external automation services (e.g. telegram_autoresponder).
1577
+ * The service sends an AutomationRegister identifying itself, then Hannah replies with
1578
+ * an AutomationSnapshot (all users with it currently enabled) followed by live
1579
+ * AutomationStateChanged deltas as users toggle it via SetAutomation/voice.
1580
+ * Chosen over SubscribeEvents so a reconnecting service always gets a fresh snapshot
1581
+ * instead of missing state changes that happened while it was offline.
1582
+ */
1583
+ automationConnect(): ClientDuplexStream<AutomationMessage, AutomationCommand>;
1584
+ automationConnect(options: Partial<CallOptions>): ClientDuplexStream<AutomationMessage, AutomationCommand>;
1585
+ automationConnect(metadata: Metadata, options?: Partial<CallOptions>): ClientDuplexStream<AutomationMessage, AutomationCommand>;
1586
+ /**
1587
+ * --- Channels ---
1588
+ * Bidirectional stream for channel adapters (e.g. the Telegram service). The adapter
1589
+ * sends a ChannelRegister and keeps the stream open; it counts as available exactly as
1590
+ * long as the stream is open. A second registration for the same service replaces the
1591
+ * first. Link tokens (CreateLinkToken) are redeemed over this stream.
1592
+ */
1593
+ channelConnect(): ClientDuplexStream<ChannelMessage, ChannelCommand>;
1594
+ channelConnect(options: Partial<CallOptions>): ClientDuplexStream<ChannelMessage, ChannelCommand>;
1595
+ channelConnect(metadata: Metadata, options?: Partial<CallOptions>): ClientDuplexStream<ChannelMessage, ChannelCommand>;
1596
+ /** Currently connected channel adapters and whether they support account linking. */
1597
+ getChannels(request: Empty, callback: (error: ServiceError | null, response: GetChannelsResponse) => void): ClientUnaryCall;
1598
+ getChannels(request: Empty, metadata: Metadata, callback: (error: ServiceError | null, response: GetChannelsResponse) => void): ClientUnaryCall;
1599
+ getChannels(request: Empty, metadata: Metadata, options: Partial<CallOptions>, callback: (error: ServiceError | null, response: GetChannelsResponse) => void): ClientUnaryCall;
1600
+ /**
1601
+ * --- Infrastructure ---
1602
+ * Service discovery for components: Hannah sends an InfrastructureSnapshot of all
1603
+ * currently available infrastructure services (e.g. the log collector) right after
1604
+ * subscribing, followed by ServiceAvailable/ServiceUnavailable deltas.
1605
+ */
1606
+ subscribeInfrastructure(request: InfrastructureFilter, options?: Partial<CallOptions>): ClientReadableStream<InfrastructureMessage>;
1607
+ subscribeInfrastructure(request: InfrastructureFilter, metadata?: Metadata, options?: Partial<CallOptions>): ClientReadableStream<InfrastructureMessage>;
1608
+ /**
1609
+ * Bidirectional stream for the log collector. The collector sends a LogCollectorRegister
1610
+ * and keeps the stream open; it counts as available exactly as long as the stream is
1611
+ * open, and a second registration for the same instance replaces the first (same
1612
+ * semantics as ChannelConnect). Not related to CollectorConnect (wakeword capture).
1613
+ */
1614
+ logCollectorConnect(): ClientDuplexStream<LogCollectorMessage, LogCollectorCommand>;
1615
+ logCollectorConnect(options: Partial<CallOptions>): ClientDuplexStream<LogCollectorMessage, LogCollectorCommand>;
1616
+ logCollectorConnect(metadata: Metadata, options?: Partial<CallOptions>): ClientDuplexStream<LogCollectorMessage, LogCollectorCommand>;
1617
+ /**
1618
+ * --- Activity Log ---
1619
+ * Read access to the Activity Log (#220) for external consumers (WebUI). List returns
1620
+ * full entry detail inline (transcript, intent + intent_meta, answer text) with
1621
+ * cursor-based pagination; audio is fetched separately, decoded server-side from the
1622
+ * stored WAV and streamed as raw PCM chunks.
1623
+ */
1624
+ listActivityLog(request: ListActivityLogRequest, callback: (error: ServiceError | null, response: ListActivityLogResponse) => void): ClientUnaryCall;
1625
+ listActivityLog(request: ListActivityLogRequest, metadata: Metadata, callback: (error: ServiceError | null, response: ListActivityLogResponse) => void): ClientUnaryCall;
1626
+ listActivityLog(request: ListActivityLogRequest, metadata: Metadata, options: Partial<CallOptions>, callback: (error: ServiceError | null, response: ListActivityLogResponse) => void): ClientUnaryCall;
1627
+ streamActivityAudio(request: StreamActivityAudioRequest, options?: Partial<CallOptions>): ClientReadableStream<ActivityAudioChunk>;
1628
+ streamActivityAudio(request: StreamActivityAudioRequest, metadata?: Metadata, options?: Partial<CallOptions>): ClientReadableStream<ActivityAudioChunk>;
1629
+ /** --- Messages (passive per-user mailbox, third notification type) --- */
1630
+ createMessage(request: CreateMessageRequest, callback: (error: ServiceError | null, response: StatusResponse) => void): ClientUnaryCall;
1631
+ createMessage(request: CreateMessageRequest, metadata: Metadata, callback: (error: ServiceError | null, response: StatusResponse) => void): ClientUnaryCall;
1632
+ createMessage(request: CreateMessageRequest, metadata: Metadata, options: Partial<CallOptions>, callback: (error: ServiceError | null, response: StatusResponse) => void): ClientUnaryCall;
1633
+ listMessages(request: ListMessagesRequest, callback: (error: ServiceError | null, response: ListMessagesResponse) => void): ClientUnaryCall;
1634
+ listMessages(request: ListMessagesRequest, metadata: Metadata, callback: (error: ServiceError | null, response: ListMessagesResponse) => void): ClientUnaryCall;
1635
+ listMessages(request: ListMessagesRequest, metadata: Metadata, options: Partial<CallOptions>, callback: (error: ServiceError | null, response: ListMessagesResponse) => void): ClientUnaryCall;
1636
+ deleteMessage(request: DeleteMessageRequest, callback: (error: ServiceError | null, response: StatusResponse) => void): ClientUnaryCall;
1637
+ deleteMessage(request: DeleteMessageRequest, metadata: Metadata, callback: (error: ServiceError | null, response: StatusResponse) => void): ClientUnaryCall;
1638
+ deleteMessage(request: DeleteMessageRequest, metadata: Metadata, options: Partial<CallOptions>, callback: (error: ServiceError | null, response: StatusResponse) => void): ClientUnaryCall;
1639
+ }
1640
+ export declare const HannahServiceClient: {
1641
+ new (address: string, credentials: ChannelCredentials, options?: Partial<ClientOptions>): HannahServiceClient;
1642
+ service: typeof HannahServiceService;
1643
+ serviceName: string;
1644
+ };