@yahaha-studio/kichi-forwarder 0.1.2-beta.2 → 0.1.2-beta.21
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +6 -2
- package/dist/config/environments.json +5 -0
- package/dist/config/kichi-config.json +941 -0
- package/dist/index.js +1887 -0
- package/dist/src/config.js +4 -0
- package/dist/src/runtime-manager.js +121 -0
- package/dist/src/service.js +805 -0
- package/dist/src/types.js +1 -0
- package/index.ts +625 -158
- package/openclaw.plugin.json +18 -1
- package/package.json +16 -7
- package/skills/kichi-forwarder/SKILL.md +53 -17
- package/skills/kichi-forwarder/references/error.md +3 -11
- package/skills/kichi-forwarder/references/heartbeat.md +6 -14
- package/skills/kichi-forwarder/references/install.md +15 -37
- package/src/runtime-manager.ts +14 -2
- package/src/service.ts +190 -5
- package/src/types.ts +57 -2
package/src/service.ts
CHANGED
|
@@ -2,14 +2,21 @@ import WebSocket from "ws";
|
|
|
2
2
|
import * as fs from "fs";
|
|
3
3
|
import * as path from "path";
|
|
4
4
|
import { randomUUID } from "node:crypto";
|
|
5
|
-
import type {
|
|
5
|
+
import type { PluginLogger } from "openclaw/plugin-sdk";
|
|
6
6
|
import type {
|
|
7
7
|
ActionPlayback,
|
|
8
|
+
AvatarStatus,
|
|
9
|
+
BotMessageHistoryEntry,
|
|
10
|
+
BotMessagePayload,
|
|
11
|
+
BotMessageReceivedPayload,
|
|
8
12
|
ClockAction,
|
|
9
13
|
ClockConfig,
|
|
10
14
|
ClockPayload,
|
|
11
15
|
CreateMusicAlbumPayload,
|
|
12
16
|
CreateNotesBoardNotePayload,
|
|
17
|
+
GlanceAckPayload,
|
|
18
|
+
GlancePayload,
|
|
19
|
+
GlanceTarget,
|
|
13
20
|
HookNotifyPayload,
|
|
14
21
|
HookNotifyType,
|
|
15
22
|
IdlePlanContent,
|
|
@@ -30,6 +37,22 @@ import type {
|
|
|
30
37
|
|
|
31
38
|
const MAX_NOTEBOARD_TEXT_LENGTH = 200;
|
|
32
39
|
const DEFAULT_LLM_RUNTIME_ENABLED = true;
|
|
40
|
+
const DEFAULT_GLANCE_DURATION_SECONDS = 1.8;
|
|
41
|
+
const JOIN_SOURCE_FILE_NAME = "join-source.json";
|
|
42
|
+
const SMS_STATE_FILE_NAME = "sms-state.json";
|
|
43
|
+
|
|
44
|
+
type SmsState = {
|
|
45
|
+
lastActiveAt?: string;
|
|
46
|
+
lastMessageReceivedAt?: string;
|
|
47
|
+
date: string;
|
|
48
|
+
totalSent: number;
|
|
49
|
+
windows: {
|
|
50
|
+
morning: number;
|
|
51
|
+
afternoon: number;
|
|
52
|
+
evening: number;
|
|
53
|
+
};
|
|
54
|
+
lastTypes: string[];
|
|
55
|
+
};
|
|
33
56
|
|
|
34
57
|
type AckFailureResult = {
|
|
35
58
|
success: false;
|
|
@@ -59,6 +82,8 @@ type KichiForwarderServiceOptions = {
|
|
|
59
82
|
|
|
60
83
|
type ConnectReason = "startup" | "switch_host" | "reconnect";
|
|
61
84
|
|
|
85
|
+
export type BotMessageReceivedHandler = (service: KichiForwarderService, msg: BotMessageReceivedPayload) => void;
|
|
86
|
+
|
|
62
87
|
export class KichiForwarderService {
|
|
63
88
|
private ws: WebSocket | null = null;
|
|
64
89
|
private stopped = false;
|
|
@@ -77,9 +102,11 @@ export class KichiForwarderService {
|
|
|
77
102
|
timeout: NodeJS.Timeout;
|
|
78
103
|
}
|
|
79
104
|
>();
|
|
105
|
+
onBotMessageReceived: BotMessageReceivedHandler | null = null;
|
|
106
|
+
private cachedRoomContext: Record<string, unknown> | null = null;
|
|
80
107
|
|
|
81
108
|
constructor(
|
|
82
|
-
private logger:
|
|
109
|
+
private logger: PluginLogger,
|
|
83
110
|
private options: KichiForwarderServiceOptions,
|
|
84
111
|
) {}
|
|
85
112
|
|
|
@@ -88,6 +115,9 @@ export class KichiForwarderService {
|
|
|
88
115
|
this.environment = (state?.currentEnvironment as KichiEnvironment) ?? null;
|
|
89
116
|
if (this.environment) {
|
|
90
117
|
this.host = this.options.resolveEnvironmentHost(this.environment);
|
|
118
|
+
if (!this.host && this.environment === "test" && state?.testHost) {
|
|
119
|
+
this.host = state.testHost as string;
|
|
120
|
+
}
|
|
91
121
|
} else {
|
|
92
122
|
this.host = null;
|
|
93
123
|
}
|
|
@@ -128,6 +158,7 @@ export class KichiForwarderService {
|
|
|
128
158
|
botName: string,
|
|
129
159
|
bio: string,
|
|
130
160
|
tags: string[],
|
|
161
|
+
source: string,
|
|
131
162
|
): Promise<JoinResult> {
|
|
132
163
|
if (!this.host) {
|
|
133
164
|
return { success: false, error: "No Kichi host configured. Run kichi_switch_host first." };
|
|
@@ -143,7 +174,7 @@ export class KichiForwarderService {
|
|
|
143
174
|
this.identity = { avatarId };
|
|
144
175
|
this.saveIdentity();
|
|
145
176
|
this.joinResolve = resolve;
|
|
146
|
-
const payload: JoinPayload = { type: "join", avatarId, botName, bio, tags };
|
|
177
|
+
const payload: JoinPayload = { type: "join", avatarId, botName, bio, tags, source };
|
|
147
178
|
const sendJoin = () => this.ws?.send(JSON.stringify(payload));
|
|
148
179
|
if (this.ws?.readyState === WebSocket.OPEN) {
|
|
149
180
|
sendJoin();
|
|
@@ -160,7 +191,15 @@ export class KichiForwarderService {
|
|
|
160
191
|
});
|
|
161
192
|
}
|
|
162
193
|
|
|
163
|
-
sendStatus(
|
|
194
|
+
sendStatus(
|
|
195
|
+
poseType: PoseType | "",
|
|
196
|
+
action: string,
|
|
197
|
+
bubble: string,
|
|
198
|
+
log: string,
|
|
199
|
+
playback: ActionPlayback,
|
|
200
|
+
avatarStatus: AvatarStatus,
|
|
201
|
+
propId?: string,
|
|
202
|
+
): void {
|
|
164
203
|
if (!this.identity?.authKey || this.ws?.readyState !== WebSocket.OPEN) return;
|
|
165
204
|
const payload: StatusPayload = {
|
|
166
205
|
type: "status",
|
|
@@ -171,6 +210,8 @@ export class KichiForwarderService {
|
|
|
171
210
|
bubble,
|
|
172
211
|
log,
|
|
173
212
|
playback,
|
|
213
|
+
avatarStatus,
|
|
214
|
+
...(propId ? { propId } : {}),
|
|
174
215
|
};
|
|
175
216
|
this.ws.send(JSON.stringify(payload));
|
|
176
217
|
}
|
|
@@ -181,6 +222,8 @@ export class KichiForwarderService {
|
|
|
181
222
|
bubble: string,
|
|
182
223
|
log: string,
|
|
183
224
|
playback: ActionPlayback,
|
|
225
|
+
avatarStatus: AvatarStatus,
|
|
226
|
+
propId?: string,
|
|
184
227
|
): Promise<StatusAckPayload> {
|
|
185
228
|
if (!this.identity?.authKey || this.ws?.readyState !== WebSocket.OPEN) {
|
|
186
229
|
throw new Error("Kichi websocket is not connected");
|
|
@@ -195,6 +238,8 @@ export class KichiForwarderService {
|
|
|
195
238
|
bubble,
|
|
196
239
|
log,
|
|
197
240
|
playback,
|
|
241
|
+
avatarStatus,
|
|
242
|
+
...(propId ? { propId } : {}),
|
|
198
243
|
};
|
|
199
244
|
return this.sendRequest<StatusAckPayload>(payload, "status_ack", 5000);
|
|
200
245
|
}
|
|
@@ -210,6 +255,10 @@ export class KichiForwarderService {
|
|
|
210
255
|
this.ws.send(JSON.stringify(payload));
|
|
211
256
|
}
|
|
212
257
|
|
|
258
|
+
recordSmsLastMessageReceivedAt(): void {
|
|
259
|
+
this.updateSmsState({ lastMessageReceivedAt: new Date().toISOString() });
|
|
260
|
+
}
|
|
261
|
+
|
|
213
262
|
sendIdlePlan(payload: IdlePlanContent): boolean {
|
|
214
263
|
if (!this.identity?.authKey || this.ws?.readyState !== WebSocket.OPEN) return false;
|
|
215
264
|
const outboundPayload: IdlePlanPayload = {
|
|
@@ -249,6 +298,36 @@ export class KichiForwarderService {
|
|
|
249
298
|
return true;
|
|
250
299
|
}
|
|
251
300
|
|
|
301
|
+
async sendGlance(
|
|
302
|
+
target: GlanceTarget,
|
|
303
|
+
durationSeconds = DEFAULT_GLANCE_DURATION_SECONDS,
|
|
304
|
+
requestId?: string,
|
|
305
|
+
): Promise<GlanceAckPayload> {
|
|
306
|
+
const identity = this.requireIdentity();
|
|
307
|
+
if (!identity) {
|
|
308
|
+
throw new Error("Missing Kichi identity");
|
|
309
|
+
}
|
|
310
|
+
if (this.ws?.readyState !== WebSocket.OPEN) {
|
|
311
|
+
throw new Error("Kichi websocket is not connected");
|
|
312
|
+
}
|
|
313
|
+
if (target !== "camera") {
|
|
314
|
+
throw new Error("target must be camera");
|
|
315
|
+
}
|
|
316
|
+
if (!Number.isFinite(durationSeconds) || durationSeconds <= 0) {
|
|
317
|
+
throw new Error("duration must be a positive finite number");
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
const payload: GlancePayload = {
|
|
321
|
+
type: "kichi_glance",
|
|
322
|
+
requestId: requestId?.trim() || randomUUID(),
|
|
323
|
+
avatarId: identity.avatarId,
|
|
324
|
+
authKey: identity.authKey,
|
|
325
|
+
target,
|
|
326
|
+
duration: durationSeconds,
|
|
327
|
+
};
|
|
328
|
+
return this.sendRequest<GlanceAckPayload>(payload, "kichi_glance_ack", 5000);
|
|
329
|
+
}
|
|
330
|
+
|
|
252
331
|
async queryStatus(requestId?: string): Promise<QueryStatusResultPayload> {
|
|
253
332
|
const identity = this.requireIdentity();
|
|
254
333
|
if (!identity) {
|
|
@@ -261,7 +340,12 @@ export class KichiForwarderService {
|
|
|
261
340
|
avatarId: identity.avatarId,
|
|
262
341
|
authKey: identity.authKey,
|
|
263
342
|
};
|
|
264
|
-
|
|
343
|
+
const result = await this.sendRequest<QueryStatusResultPayload>(payload, "query_status_result");
|
|
344
|
+
this.updateSmsLastActiveAt();
|
|
345
|
+
if (result.RoomContext && typeof result.RoomContext === "object") {
|
|
346
|
+
this.cachedRoomContext = result.RoomContext as Record<string, unknown>;
|
|
347
|
+
}
|
|
348
|
+
return result;
|
|
265
349
|
}
|
|
266
350
|
|
|
267
351
|
createNotesBoardNote(propId: string, data: string): void {
|
|
@@ -316,8 +400,36 @@ export class KichiForwarderService {
|
|
|
316
400
|
return normalizedRequestId;
|
|
317
401
|
}
|
|
318
402
|
|
|
403
|
+
async sendBotMessage(
|
|
404
|
+
toAvatarId: string,
|
|
405
|
+
depth: number,
|
|
406
|
+
bubble: string,
|
|
407
|
+
options?: { poseType?: PoseType; action?: string; log?: string; playback?: ActionPlayback; history?: BotMessageHistoryEntry[] },
|
|
408
|
+
): Promise<Record<string, unknown>> {
|
|
409
|
+
if (!this.identity?.authKey || this.ws?.readyState !== WebSocket.OPEN) {
|
|
410
|
+
throw new Error("Kichi websocket is not connected");
|
|
411
|
+
}
|
|
412
|
+
const payload: BotMessagePayload = {
|
|
413
|
+
type: "bot_message",
|
|
414
|
+
avatarId: this.identity.avatarId,
|
|
415
|
+
authKey: this.identity.authKey,
|
|
416
|
+
toAvatarId,
|
|
417
|
+
depth,
|
|
418
|
+
bubble,
|
|
419
|
+
requestId: randomUUID(),
|
|
420
|
+
...(options?.poseType ? { poseType: options.poseType } : {}),
|
|
421
|
+
...(options?.action ? { action: options.action } : {}),
|
|
422
|
+
...(options?.playback ? { playback: options.playback } : {}),
|
|
423
|
+
...(options?.log ? { log: options.log } : {}),
|
|
424
|
+
...(options?.history?.length ? { history: options.history } : {}),
|
|
425
|
+
};
|
|
426
|
+
return this.sendRequest<Record<string, unknown>>(payload, "bot_message_ack", 5000);
|
|
427
|
+
}
|
|
428
|
+
|
|
319
429
|
isConnected(): boolean { return this.ws?.readyState === WebSocket.OPEN && !!this.identity?.authKey; }
|
|
320
430
|
|
|
431
|
+
getCachedRoomContext(): Record<string, unknown> | null { return this.cachedRoomContext; }
|
|
432
|
+
|
|
321
433
|
hasValidIdentity(): boolean { return !!this.identity?.avatarId && !!this.identity?.authKey; }
|
|
322
434
|
|
|
323
435
|
isLlmRuntimeEnabled(): boolean {
|
|
@@ -336,6 +448,29 @@ export class KichiForwarderService {
|
|
|
336
448
|
return this.options.runtimeDir;
|
|
337
449
|
}
|
|
338
450
|
|
|
451
|
+
getJoinSourcePath(): string {
|
|
452
|
+
return path.join(this.getKichiWorldRootDir(), JOIN_SOURCE_FILE_NAME);
|
|
453
|
+
}
|
|
454
|
+
|
|
455
|
+
readConfiguredJoinSource(): string | null {
|
|
456
|
+
const sourcePath = this.getJoinSourcePath();
|
|
457
|
+
if (!fs.existsSync(sourcePath)) {
|
|
458
|
+
return null;
|
|
459
|
+
}
|
|
460
|
+
|
|
461
|
+
const data = JSON.parse(fs.readFileSync(sourcePath, "utf-8")) as unknown;
|
|
462
|
+
if (!data || typeof data !== "object" || Array.isArray(data)) {
|
|
463
|
+
throw new Error(`${JOIN_SOURCE_FILE_NAME} must contain a JSON object`);
|
|
464
|
+
}
|
|
465
|
+
|
|
466
|
+
const source = (data as { source?: unknown }).source;
|
|
467
|
+
if (typeof source !== "string" || !source.trim()) {
|
|
468
|
+
throw new Error(`${JOIN_SOURCE_FILE_NAME} must contain a non-empty string source`);
|
|
469
|
+
}
|
|
470
|
+
|
|
471
|
+
return source.trim();
|
|
472
|
+
}
|
|
473
|
+
|
|
339
474
|
getStatePath(): string {
|
|
340
475
|
return path.join(this.options.runtimeDir, "state.json");
|
|
341
476
|
}
|
|
@@ -521,6 +656,7 @@ export class KichiForwarderService {
|
|
|
521
656
|
if (this.identity) {
|
|
522
657
|
this.identity.authKey = joinAck.authKey;
|
|
523
658
|
this.saveIdentity();
|
|
659
|
+
this.updateSmsLastActiveAt();
|
|
524
660
|
this.log("info", `joined as ${this.identity.avatarId}`);
|
|
525
661
|
}
|
|
526
662
|
this.joinResolve?.({ success: true, authKey: joinAck.authKey });
|
|
@@ -537,6 +673,10 @@ export class KichiForwarderService {
|
|
|
537
673
|
} else {
|
|
538
674
|
this.log("info", "left Kichi world");
|
|
539
675
|
}
|
|
676
|
+
} else if (msg.type === "bot_message_received") {
|
|
677
|
+
const payload = msg as BotMessageReceivedPayload;
|
|
678
|
+
this.log("info", `bot_message_received from=${payload.from} depth=${payload.depth} bubble="${payload.bubble}"`);
|
|
679
|
+
this.onBotMessageReceived?.(this, payload);
|
|
540
680
|
}
|
|
541
681
|
} catch (e) {
|
|
542
682
|
this.log("warn", `failed to parse message: ${e}`);
|
|
@@ -716,6 +856,14 @@ export class KichiForwarderService {
|
|
|
716
856
|
return path.join(this.options.runtimeDir, "hosts", encodeURIComponent(this.host));
|
|
717
857
|
}
|
|
718
858
|
|
|
859
|
+
private getSmsStatePath(): string {
|
|
860
|
+
return path.join(this.options.runtimeDir, SMS_STATE_FILE_NAME);
|
|
861
|
+
}
|
|
862
|
+
|
|
863
|
+
private getKichiWorldRootDir(): string {
|
|
864
|
+
return path.dirname(path.dirname(this.options.runtimeDir));
|
|
865
|
+
}
|
|
866
|
+
|
|
719
867
|
private getWsUrl(): string {
|
|
720
868
|
if (!this.host) {
|
|
721
869
|
throw new Error("No Kichi host configured");
|
|
@@ -734,14 +882,39 @@ export class KichiForwarderService {
|
|
|
734
882
|
|
|
735
883
|
private persistCurrentHost(host: string, environment?: KichiEnvironment): void {
|
|
736
884
|
const previousState = this.readStateFile();
|
|
885
|
+
const testHost = environment === "test" ? host : (previousState?.testHost ?? undefined);
|
|
737
886
|
const nextState: KichiState = {
|
|
738
887
|
...(environment ? { currentEnvironment: environment } : {}),
|
|
739
888
|
llmRuntimeEnabled: previousState?.llmRuntimeEnabled ?? DEFAULT_LLM_RUNTIME_ENABLED,
|
|
889
|
+
...(testHost ? { testHost } : {}),
|
|
740
890
|
};
|
|
741
891
|
fs.mkdirSync(this.options.runtimeDir, { recursive: true, mode: 0o700 });
|
|
742
892
|
fs.writeFileSync(this.getStatePath(), JSON.stringify(nextState, null, 2), { mode: 0o600 });
|
|
743
893
|
}
|
|
744
894
|
|
|
895
|
+
private updateSmsLastActiveAt(): void {
|
|
896
|
+
this.updateSmsState({ lastActiveAt: new Date().toISOString() });
|
|
897
|
+
}
|
|
898
|
+
|
|
899
|
+
private updateSmsState(patch: Partial<SmsState>): void {
|
|
900
|
+
try {
|
|
901
|
+
const now = new Date();
|
|
902
|
+
const previousState = this.readSmsStateFile();
|
|
903
|
+
const nextState: SmsState = {
|
|
904
|
+
date: now.toISOString().slice(0, 10),
|
|
905
|
+
totalSent: 0,
|
|
906
|
+
windows: { morning: 0, afternoon: 0, evening: 0 },
|
|
907
|
+
lastTypes: [],
|
|
908
|
+
...previousState,
|
|
909
|
+
...patch,
|
|
910
|
+
};
|
|
911
|
+
fs.mkdirSync(this.options.runtimeDir, { recursive: true, mode: 0o700 });
|
|
912
|
+
fs.writeFileSync(this.getSmsStatePath(), JSON.stringify(nextState, null, 2), { mode: 0o600 });
|
|
913
|
+
} catch (e) {
|
|
914
|
+
this.log("error", `failed to update sms state: ${e}`);
|
|
915
|
+
}
|
|
916
|
+
}
|
|
917
|
+
|
|
745
918
|
private readStateFile(): Partial<KichiState> | null {
|
|
746
919
|
const statePath = this.getStatePath();
|
|
747
920
|
if (!fs.existsSync(statePath)) {
|
|
@@ -754,6 +927,18 @@ export class KichiForwarderService {
|
|
|
754
927
|
return data as Partial<KichiState>;
|
|
755
928
|
}
|
|
756
929
|
|
|
930
|
+
private readSmsStateFile(): Partial<SmsState> | null {
|
|
931
|
+
const smsStatePath = this.getSmsStatePath();
|
|
932
|
+
if (!fs.existsSync(smsStatePath)) {
|
|
933
|
+
return null;
|
|
934
|
+
}
|
|
935
|
+
const data = JSON.parse(fs.readFileSync(smsStatePath, "utf-8")) as unknown;
|
|
936
|
+
if (!data || typeof data !== "object" || Array.isArray(data)) {
|
|
937
|
+
throw new Error(`Invalid SMS state payload in ${smsStatePath}`);
|
|
938
|
+
}
|
|
939
|
+
return data as Partial<SmsState>;
|
|
940
|
+
}
|
|
941
|
+
|
|
757
942
|
private clearReconnectTimeout(): void {
|
|
758
943
|
if (!this.reconnectTimeout) return;
|
|
759
944
|
clearTimeout(this.reconnectTimeout);
|
package/src/types.ts
CHANGED
|
@@ -2,6 +2,7 @@ export type KichiForwarderConfig = Record<string, never>;
|
|
|
2
2
|
|
|
3
3
|
export type PoseType = "stand" | "sit" | "lay" | "floor";
|
|
4
4
|
export type ActionPlaybackMode = "loop" | "once";
|
|
5
|
+
export type AvatarStatus = "Idle" | "Busy" | "Activities" | "Break";
|
|
5
6
|
export type ActionPlayback = {
|
|
6
7
|
mode: ActionPlaybackMode;
|
|
7
8
|
resumeAction?: string;
|
|
@@ -16,7 +17,9 @@ export type ActionResult = {
|
|
|
16
17
|
poseType: PoseType;
|
|
17
18
|
action: string;
|
|
18
19
|
bubble: string;
|
|
20
|
+
avatarStatus: AvatarStatus;
|
|
19
21
|
log?: string;
|
|
22
|
+
propId?: string;
|
|
20
23
|
};
|
|
21
24
|
|
|
22
25
|
export type KichiStaticConfig = {
|
|
@@ -43,6 +46,7 @@ export type KichiEnvironmentsConfig = Record<KichiEnvironment, string | null>;
|
|
|
43
46
|
export type KichiState = {
|
|
44
47
|
currentEnvironment?: KichiEnvironment;
|
|
45
48
|
llmRuntimeEnabled: boolean;
|
|
49
|
+
testHost?: string;
|
|
46
50
|
};
|
|
47
51
|
|
|
48
52
|
export type KichiIdentity = {
|
|
@@ -84,6 +88,7 @@ export type JoinPayload = {
|
|
|
84
88
|
botName: string;
|
|
85
89
|
bio: string;
|
|
86
90
|
tags: string[];
|
|
91
|
+
source: string;
|
|
87
92
|
};
|
|
88
93
|
|
|
89
94
|
export type JoinAckPayload = {
|
|
@@ -117,6 +122,8 @@ export type StatusPayload = {
|
|
|
117
122
|
bubble: string;
|
|
118
123
|
log: string;
|
|
119
124
|
playback: ActionPlayback;
|
|
125
|
+
avatarStatus: AvatarStatus;
|
|
126
|
+
propId?: string;
|
|
120
127
|
};
|
|
121
128
|
|
|
122
129
|
export type StatusAckPayload = {
|
|
@@ -124,9 +131,27 @@ export type StatusAckPayload = {
|
|
|
124
131
|
requestId: string;
|
|
125
132
|
poseType: PoseType | "";
|
|
126
133
|
action: string;
|
|
134
|
+
requestedPropId?: string;
|
|
127
135
|
warning?: string;
|
|
128
136
|
};
|
|
129
137
|
|
|
138
|
+
export type GlanceTarget = "camera";
|
|
139
|
+
|
|
140
|
+
export type GlancePayload = {
|
|
141
|
+
type: "kichi_glance";
|
|
142
|
+
requestId: string;
|
|
143
|
+
avatarId: string;
|
|
144
|
+
authKey: string;
|
|
145
|
+
target: GlanceTarget;
|
|
146
|
+
duration: number;
|
|
147
|
+
};
|
|
148
|
+
|
|
149
|
+
export type GlanceAckPayload = {
|
|
150
|
+
type: "kichi_glance_ack";
|
|
151
|
+
requestId: string;
|
|
152
|
+
target: GlanceTarget;
|
|
153
|
+
};
|
|
154
|
+
|
|
130
155
|
export type HookNotifyType = "message_received" | "before_send_message";
|
|
131
156
|
|
|
132
157
|
export type HookNotifyPayload = {
|
|
@@ -144,12 +169,14 @@ export type IdlePlanStageAction = {
|
|
|
144
169
|
durationSeconds: number;
|
|
145
170
|
bubble: string;
|
|
146
171
|
log?: string;
|
|
172
|
+
propId?: string;
|
|
147
173
|
};
|
|
148
174
|
|
|
149
175
|
export type IdlePlanStage = {
|
|
150
176
|
name: string;
|
|
151
177
|
purpose: string;
|
|
152
178
|
pomodoroPhase: IdlePlanPhase;
|
|
179
|
+
avatarStatus: AvatarStatus;
|
|
153
180
|
durationSeconds: number;
|
|
154
181
|
actions: IdlePlanStageAction[];
|
|
155
182
|
};
|
|
@@ -245,9 +272,7 @@ export type QueryStatusOwnerState = {
|
|
|
245
272
|
poseType?: string;
|
|
246
273
|
action?: string;
|
|
247
274
|
interactingItemName?: string;
|
|
248
|
-
desktopActivityCategory?: string;
|
|
249
275
|
desktopAppName?: string;
|
|
250
|
-
desktopSummary?: string;
|
|
251
276
|
};
|
|
252
277
|
|
|
253
278
|
export type QueryStatusNote = {
|
|
@@ -275,3 +300,33 @@ export type CreateMusicAlbumPayload = {
|
|
|
275
300
|
albumTitle: string;
|
|
276
301
|
musicTitles: string[];
|
|
277
302
|
};
|
|
303
|
+
|
|
304
|
+
export type BotMessageHistoryEntry = {
|
|
305
|
+
from: string;
|
|
306
|
+
fromName: string;
|
|
307
|
+
bubble: string;
|
|
308
|
+
};
|
|
309
|
+
|
|
310
|
+
export type BotMessagePayload = {
|
|
311
|
+
type: "bot_message";
|
|
312
|
+
avatarId: string;
|
|
313
|
+
authKey: string;
|
|
314
|
+
requestId: string;
|
|
315
|
+
toAvatarId: string;
|
|
316
|
+
depth: number;
|
|
317
|
+
poseType?: PoseType;
|
|
318
|
+
action?: string;
|
|
319
|
+
playback?: ActionPlayback;
|
|
320
|
+
bubble: string;
|
|
321
|
+
log?: string;
|
|
322
|
+
history?: BotMessageHistoryEntry[];
|
|
323
|
+
};
|
|
324
|
+
|
|
325
|
+
export type BotMessageReceivedPayload = {
|
|
326
|
+
type: "bot_message_received";
|
|
327
|
+
from: string;
|
|
328
|
+
fromName: string;
|
|
329
|
+
depth: number;
|
|
330
|
+
bubble: string;
|
|
331
|
+
history?: BotMessageHistoryEntry[];
|
|
332
|
+
};
|