@yahaha-studio/kichi-forwarder 0.1.2-beta.6 → 0.1.2-beta.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,5 @@
1
+ {
2
+ "steam": "focus-wss.yahaha.com",
3
+ "steam-playtest": "focus-steam-playtest-wss-int.yahaha.com",
4
+ "test": null
5
+ }
@@ -0,0 +1,941 @@
1
+ {
2
+ "actions": {
3
+ "stand": [
4
+ {
5
+ "name": "High Five",
6
+ "playback": "once",
7
+ "resumeAction": "Idle Backup Hands"
8
+ },
9
+ {
10
+ "name": "Listen Music",
11
+ "playback": "loop"
12
+ },
13
+ {
14
+ "name": "Arm Stretch",
15
+ "playback": "once",
16
+ "resumeAction": "Idle Backup Hands"
17
+ },
18
+ {
19
+ "name": "Backbend Stretch",
20
+ "playback": "once",
21
+ "resumeAction": "Idle Backup Hands"
22
+ },
23
+ {
24
+ "name": "Making Selfie",
25
+ "playback": "once",
26
+ "resumeAction": "Idle Backup Hands"
27
+ },
28
+ {
29
+ "name": "Arms Crossed",
30
+ "playback": "loop"
31
+ },
32
+ {
33
+ "name": "Epiphany",
34
+ "playback": "once",
35
+ "resumeAction": "Idle Backup Hands"
36
+ },
37
+ {
38
+ "name": "Angry",
39
+ "playback": "loop"
40
+ },
41
+ {
42
+ "name": "Yay",
43
+ "playback": "once",
44
+ "resumeAction": "Idle Backup Hands"
45
+ },
46
+ {
47
+ "name": "Dance",
48
+ "playback": "loop"
49
+ },
50
+ {
51
+ "name": "Sing",
52
+ "playback": "loop"
53
+ },
54
+ {
55
+ "name": "Tired",
56
+ "playback": "loop"
57
+ },
58
+ {
59
+ "name": "Wait",
60
+ "playback": "loop"
61
+ },
62
+ {
63
+ "name": "Stand Phone Talk",
64
+ "playback": "loop"
65
+ },
66
+ {
67
+ "name": "Stand Phone Play",
68
+ "playback": "loop"
69
+ },
70
+ {
71
+ "name": "Curtsy",
72
+ "playback": "once",
73
+ "resumeAction": "Idle Backup Hands"
74
+ },
75
+ {
76
+ "name": "Stand Writing",
77
+ "playback": "loop"
78
+ },
79
+ {
80
+ "name": "Stand Drawing",
81
+ "playback": "loop"
82
+ },
83
+ {
84
+ "name": "Stand Play Guitar",
85
+ "playback": "loop"
86
+ },
87
+ {
88
+ "name": "Stand Typing with Keyboard",
89
+ "playback": "loop"
90
+ },
91
+ {
92
+ "name": "Cry",
93
+ "playback": "loop"
94
+ },
95
+ {
96
+ "name": "Dance with Joy",
97
+ "playback": "loop"
98
+ },
99
+ {
100
+ "name": "Float",
101
+ "playback": "loop"
102
+ },
103
+ {
104
+ "name": "Hand on Chest",
105
+ "playback": "loop"
106
+ },
107
+ {
108
+ "name": "Horse Stance",
109
+ "playback": "loop"
110
+ },
111
+ {
112
+ "name": "Idle Backup Hands",
113
+ "playback": "loop"
114
+ },
115
+ {
116
+ "name": "No",
117
+ "playback": "once",
118
+ "resumeAction": "Idle Backup Hands"
119
+ },
120
+ {
121
+ "name": "Panic",
122
+ "playback": "loop"
123
+ },
124
+ {
125
+ "name": "Playful Point Up",
126
+ "playback": "once",
127
+ "resumeAction": "Idle Backup Hands"
128
+ },
129
+ {
130
+ "name": "Rub Hands",
131
+ "playback": "loop"
132
+ },
133
+ {
134
+ "name": "Run Jump",
135
+ "playback": "once",
136
+ "resumeAction": "Idle Backup Hands"
137
+ },
138
+ {
139
+ "name": "Star Showing",
140
+ "playback": "once",
141
+ "resumeAction": "Idle Backup Hands"
142
+ },
143
+ {
144
+ "name": "Goofy Moves",
145
+ "playback": "loop"
146
+ },
147
+ {
148
+ "name": "Reading",
149
+ "playback": "loop"
150
+ }
151
+ ],
152
+ "sit": [
153
+ {
154
+ "name": "Typing with Keyboard",
155
+ "playback": "loop"
156
+ },
157
+ {
158
+ "name": "Thinking",
159
+ "playback": "loop"
160
+ },
161
+ {
162
+ "name": "Writing",
163
+ "playback": "loop"
164
+ },
165
+ {
166
+ "name": "Crazy",
167
+ "playback": "loop"
168
+ },
169
+ {
170
+ "name": "Hand Cramp",
171
+ "playback": "once",
172
+ "resumeAction": "Sit Nicely"
173
+ },
174
+ {
175
+ "name": "Dozing",
176
+ "playback": "loop"
177
+ },
178
+ {
179
+ "name": "Phone Talk",
180
+ "playback": "loop"
181
+ },
182
+ {
183
+ "name": "Situp with Arms Crossed",
184
+ "playback": "loop"
185
+ },
186
+ {
187
+ "name": "Situp with Cross Legs",
188
+ "playback": "loop"
189
+ },
190
+ {
191
+ "name": "Eating",
192
+ "playback": "loop"
193
+ },
194
+ {
195
+ "name": "Laze with Cross Legs",
196
+ "playback": "loop"
197
+ },
198
+ {
199
+ "name": "Sit with Arm Stretch",
200
+ "playback": "once",
201
+ "resumeAction": "Sit Nicely"
202
+ },
203
+ {
204
+ "name": "Drink",
205
+ "playback": "once",
206
+ "resumeAction": "Sit Nicely"
207
+ },
208
+ {
209
+ "name": "Sit with Making Selfie",
210
+ "playback": "once",
211
+ "resumeAction": "Sit Nicely"
212
+ },
213
+ {
214
+ "name": "Play Game",
215
+ "playback": "loop"
216
+ },
217
+ {
218
+ "name": "Situp Sleep",
219
+ "playback": "loop"
220
+ },
221
+ {
222
+ "name": "Sit Phone Play",
223
+ "playback": "loop"
224
+ },
225
+ {
226
+ "name": "Painting",
227
+ "playback": "loop"
228
+ },
229
+ {
230
+ "name": "Daze",
231
+ "playback": "loop"
232
+ },
233
+ {
234
+ "name": "Trace Circles",
235
+ "playback": "loop"
236
+ },
237
+ {
238
+ "name": "Reading",
239
+ "playback": "loop"
240
+ },
241
+ {
242
+ "name": "Contemplate",
243
+ "playback": "loop"
244
+ },
245
+ {
246
+ "name": "Chin Rest",
247
+ "playback": "loop"
248
+ },
249
+ {
250
+ "name": "Sleep with Table",
251
+ "playback": "loop"
252
+ },
253
+ {
254
+ "name": "Cute Chin Rest",
255
+ "playback": "loop"
256
+ },
257
+ {
258
+ "name": "Sit Nicely",
259
+ "playback": "loop"
260
+ },
261
+ {
262
+ "name": "Sit Play Guitar",
263
+ "playback": "loop"
264
+ },
265
+ {
266
+ "name": "Meditate",
267
+ "playback": "loop"
268
+ }
269
+ ],
270
+ "lay": [
271
+ {
272
+ "name": "Bend One Knee",
273
+ "playback": "loop"
274
+ },
275
+ {
276
+ "name": "Sleep Curl up Side way",
277
+ "playback": "loop"
278
+ },
279
+ {
280
+ "name": "Rest Chin",
281
+ "playback": "loop"
282
+ },
283
+ {
284
+ "name": "Lie Flat",
285
+ "playback": "loop"
286
+ },
287
+ {
288
+ "name": "Lie Face Down",
289
+ "playback": "loop"
290
+ },
291
+ {
292
+ "name": "Lie Side",
293
+ "playback": "loop"
294
+ },
295
+ {
296
+ "name": "Lay Writing",
297
+ "playback": "loop"
298
+ },
299
+ {
300
+ "name": "Lay Painting",
301
+ "playback": "loop"
302
+ },
303
+ {
304
+ "name": "Sleep Getup",
305
+ "playback": "once",
306
+ "resumeAction": "Lie Flat"
307
+ },
308
+ {
309
+ "name": "Starfish",
310
+ "playback": "loop"
311
+ },
312
+ {
313
+ "name": "Lie Side Play Phone",
314
+ "playback": "loop"
315
+ },
316
+ {
317
+ "name": "Prone Play Phone",
318
+ "playback": "loop"
319
+ },
320
+ {
321
+ "name": "Play Laptop",
322
+ "playback": "loop"
323
+ }
324
+ ],
325
+ "floor": [
326
+ {
327
+ "name": "Seiza",
328
+ "playback": "loop"
329
+ },
330
+ {
331
+ "name": "Cross Legged",
332
+ "playback": "loop"
333
+ },
334
+ {
335
+ "name": "Knee Hug",
336
+ "playback": "loop"
337
+ },
338
+ {
339
+ "name": "Writing",
340
+ "playback": "loop"
341
+ },
342
+ {
343
+ "name": "Painting",
344
+ "playback": "loop"
345
+ },
346
+ {
347
+ "name": "Floor Phone Play",
348
+ "playback": "loop"
349
+ },
350
+ {
351
+ "name": "Typing with Keyboard",
352
+ "playback": "loop"
353
+ },
354
+ {
355
+ "name": "Reading",
356
+ "playback": "loop"
357
+ },
358
+ {
359
+ "name": "Phone Talk",
360
+ "playback": "loop"
361
+ },
362
+ {
363
+ "name": "Phone Talk with Point",
364
+ "playback": "once",
365
+ "resumeAction": "Cross Legged"
366
+ },
367
+ {
368
+ "name": "Thinking",
369
+ "playback": "loop"
370
+ },
371
+ {
372
+ "name": "Yawn",
373
+ "playback": "once",
374
+ "resumeAction": "Cross Legged"
375
+ },
376
+ {
377
+ "name": "Chin Rest",
378
+ "playback": "loop"
379
+ },
380
+ {
381
+ "name": "Finger Tap Chin",
382
+ "playback": "loop"
383
+ },
384
+ {
385
+ "name": "Arm Stretch",
386
+ "playback": "once",
387
+ "resumeAction": "Cross Legged"
388
+ },
389
+ {
390
+ "name": "Crazy",
391
+ "playback": "loop"
392
+ },
393
+ {
394
+ "name": "Remorse",
395
+ "playback": "loop"
396
+ },
397
+ {
398
+ "name": "Tantrum",
399
+ "playback": "loop"
400
+ },
401
+ {
402
+ "name": "Squat",
403
+ "playback": "loop"
404
+ },
405
+ {
406
+ "name": "Cross Legs",
407
+ "playback": "loop"
408
+ },
409
+ {
410
+ "name": "Lean Sit",
411
+ "playback": "loop"
412
+ },
413
+ {
414
+ "name": "Playful Point up",
415
+ "playback": "once",
416
+ "resumeAction": "Cross Legged"
417
+ },
418
+ {
419
+ "name": "Swing Legs",
420
+ "playback": "loop"
421
+ },
422
+ {
423
+ "name": "Drained",
424
+ "playback": "loop"
425
+ },
426
+ {
427
+ "name": "Meditate",
428
+ "playback": "loop"
429
+ }
430
+ ]
431
+ },
432
+ "album": {
433
+ "albumCount": 10,
434
+ "trackCount": 58,
435
+ "track": [
436
+ {
437
+ "album": "Dusty Bookshelves",
438
+ "name": "A moment of calm",
439
+ "tags": [
440
+ "Gentle",
441
+ "Relaxing",
442
+ "Easy listening"
443
+ ]
444
+ },
445
+ {
446
+ "album": "Dusty Bookshelves",
447
+ "name": "Closed Love",
448
+ "tags": [
449
+ "Dark ",
450
+ "Magnificent"
451
+ ]
452
+ },
453
+ {
454
+ "album": "Dusty Bookshelves",
455
+ "name": "In That Mood",
456
+ "tags": [
457
+ "Lounge Bar Cafe",
458
+ "Relaxing"
459
+ ]
460
+ },
461
+ {
462
+ "album": "Dusty Bookshelves",
463
+ "name": "Let It Happen",
464
+ "tags": [
465
+ "Lounge Restaurant Cafe",
466
+ "Light"
467
+ ]
468
+ },
469
+ {
470
+ "album": "Dusty Bookshelves",
471
+ "name": "Memories forever",
472
+ "tags": [
473
+ "Moving",
474
+ "Gentle",
475
+ "Warm",
476
+ "Sad ballad"
477
+ ]
478
+ },
479
+ {
480
+ "album": "Dusty Bookshelves",
481
+ "name": "Outer Space",
482
+ "tags": [
483
+ "Space ",
484
+ "Magnificent"
485
+ ]
486
+ },
487
+ {
488
+ "album": "Dusty Bookshelves",
489
+ "name": "Spiritual world",
490
+ "tags": [
491
+ "Inorganic",
492
+ "Unrealistic",
493
+ "Simple"
494
+ ]
495
+ },
496
+ {
497
+ "album": "Late Night Coder",
498
+ "name": "Calm Time",
499
+ "tags": [
500
+ "Calm ",
501
+ "Gentle"
502
+ ]
503
+ },
504
+ {
505
+ "album": "Late Night Coder",
506
+ "name": "Counting the Stars",
507
+ "tags": [
508
+ "Gentle",
509
+ "Calm",
510
+ "Sleep",
511
+ "Night",
512
+ "Easy listening"
513
+ ]
514
+ },
515
+ {
516
+ "album": "Late Night Coder",
517
+ "name": "Deserted landscape",
518
+ "tags": [
519
+ "Inorganic",
520
+ "5 beats Polyrhythm"
521
+ ]
522
+ },
523
+ {
524
+ "album": "Late Night Coder",
525
+ "name": "Dog Days",
526
+ "tags": [
527
+ "Slightly dark",
528
+ "Drowsy"
529
+ ]
530
+ },
531
+ {
532
+ "album": "Late Night Coder",
533
+ "name": "It Was an Unpleasant Incident",
534
+ "tags": [
535
+ "Gentle",
536
+ "Slightly sad"
537
+ ]
538
+ },
539
+ {
540
+ "album": "Late Night Coder",
541
+ "name": "The Dark Eternal Night",
542
+ "tags": [
543
+ "Slightly dark",
544
+ "Eerie"
545
+ ]
546
+ },
547
+ {
548
+ "album": "Midnight Cyber-Transit",
549
+ "name": "Afterimage Metaphor",
550
+ "tags": [
551
+ "Sad ",
552
+ "Lonely",
553
+ "Transparent"
554
+ ]
555
+ },
556
+ {
557
+ "album": "Midnight Cyber-Transit",
558
+ "name": "I keep looking at the floor",
559
+ "tags": [
560
+ "Somewhat dark",
561
+ "Empty"
562
+ ]
563
+ },
564
+ {
565
+ "album": "Midnight Cyber-Transit",
566
+ "name": "Interstellar matter",
567
+ "tags": [
568
+ "Space ",
569
+ "Floating feeling"
570
+ ]
571
+ },
572
+ {
573
+ "album": "Midnight Cyber-Transit",
574
+ "name": "Special To Me",
575
+ "tags": [
576
+ "Bebop jazz",
577
+ "Light",
578
+ "Radio background music"
579
+ ]
580
+ },
581
+ {
582
+ "album": "Midnight Cyber-Transit",
583
+ "name": "Specification",
584
+ "tags": [
585
+ "Slightly happy",
586
+ "General"
587
+ ]
588
+ },
589
+ {
590
+ "album": "Morning Dew & Drip Coffee",
591
+ "name": "Daytime activities",
592
+ "tags": [
593
+ "General",
594
+ "Languid",
595
+ "Daytime"
596
+ ]
597
+ },
598
+ {
599
+ "album": "Morning Dew & Drip Coffee",
600
+ "name": "Enjoy the rest of your day",
601
+ "tags": [
602
+ "Comical",
603
+ "Cheerful",
604
+ "Fun",
605
+ "Simple"
606
+ ]
607
+ },
608
+ {
609
+ "album": "Morning Dew & Drip Coffee",
610
+ "name": "Entertainment Committee",
611
+ "tags": [
612
+ "Slightly bright",
613
+ "Relaxing"
614
+ ]
615
+ },
616
+ {
617
+ "album": "Morning Dew & Drip Coffee",
618
+ "name": "Heavy Rain",
619
+ "tags": [
620
+ "Inorganic",
621
+ "Mysterious"
622
+ ]
623
+ },
624
+ {
625
+ "album": "Morning Dew & Drip Coffee",
626
+ "name": "Lovely Day",
627
+ "tags": [
628
+ "Bright",
629
+ "Gentle",
630
+ "Calm"
631
+ ]
632
+ },
633
+ {
634
+ "album": "Morning Dew & Drip Coffee",
635
+ "name": "Relax in the shade",
636
+ "tags": [
637
+ "Bright",
638
+ "Kind",
639
+ "Warm",
640
+ "Fun",
641
+ "Relaxing"
642
+ ]
643
+ },
644
+ {
645
+ "album": "Morning Dew & Drip Coffee",
646
+ "name": "Spring is a nap",
647
+ "tags": [
648
+ "Relaxing",
649
+ "Gentle",
650
+ "Cheerful",
651
+ "Easy listening"
652
+ ]
653
+ },
654
+ {
655
+ "album": "Morning Dew & Drip Coffee",
656
+ "name": "Warm tea time",
657
+ "tags": [
658
+ "Slightly bright",
659
+ "Gentle",
660
+ "Ennui"
661
+ ]
662
+ },
663
+ {
664
+ "album": "Nostalgic Frequencies",
665
+ "name": "Full of Energy",
666
+ "tags": [
667
+ "Slightly bright",
668
+ "Uplifting",
669
+ "Medium tempo"
670
+ ]
671
+ },
672
+ {
673
+ "album": "Nostalgic Frequencies",
674
+ "name": "Someday in the Rain",
675
+ "tags": [
676
+ "Slightly bright",
677
+ "Moist"
678
+ ]
679
+ },
680
+ {
681
+ "album": "Nostalgic Frequencies",
682
+ "name": "Still in Love",
683
+ "tags": [
684
+ "Slightly sad"
685
+ ]
686
+ },
687
+ {
688
+ "album": "Nostalgic Frequencies",
689
+ "name": "Trace",
690
+ "tags": [
691
+ "Melancholic",
692
+ "Sentimental",
693
+ "Nostalgic"
694
+ ]
695
+ },
696
+ {
697
+ "album": "Nostalgic Frequencies",
698
+ "name": "Water Town",
699
+ "tags": [
700
+ "Slightly bright",
701
+ "Gentle",
702
+ "Simple"
703
+ ]
704
+ },
705
+ {
706
+ "album": "Overgrown Ruins",
707
+ "name": "Blank and Silence",
708
+ "tags": [
709
+ "Light",
710
+ "General purpose"
711
+ ]
712
+ },
713
+ {
714
+ "album": "Overgrown Ruins",
715
+ "name": "Darkness of the New Moon",
716
+ "tags": [
717
+ "Dark",
718
+ "Horror"
719
+ ]
720
+ },
721
+ {
722
+ "album": "Overgrown Ruins",
723
+ "name": "Flowers that Bloom in Sadness",
724
+ "tags": [
725
+ "Slightly dark ",
726
+ "Sad"
727
+ ]
728
+ },
729
+ {
730
+ "album": "Overgrown Ruins",
731
+ "name": "The Price of Mistakes",
732
+ "tags": [
733
+ "Sad",
734
+ "Painful",
735
+ "Serious",
736
+ "Flashback"
737
+ ]
738
+ },
739
+ {
740
+ "album": "Raindrops on the Windowpane",
741
+ "name": "A little love there",
742
+ "tags": [
743
+ "Gentle ",
744
+ "Slumber"
745
+ ]
746
+ },
747
+ {
748
+ "album": "Raindrops on the Windowpane",
749
+ "name": "Beside You",
750
+ "tags": [
751
+ "Moving",
752
+ "Gentle",
753
+ "Warm",
754
+ "Sad ballad"
755
+ ]
756
+ },
757
+ {
758
+ "album": "Raindrops on the Windowpane",
759
+ "name": "Blue Star",
760
+ "tags": [
761
+ "Calm",
762
+ "Night"
763
+ ]
764
+ },
765
+ {
766
+ "album": "Raindrops on the Windowpane",
767
+ "name": "I want to get to know you",
768
+ "tags": [
769
+ "Touching",
770
+ "Sad",
771
+ "Kind"
772
+ ]
773
+ },
774
+ {
775
+ "album": "Raindrops on the Windowpane",
776
+ "name": "Passing each other",
777
+ "tags": [
778
+ "Slightly dark",
779
+ "Calm",
780
+ "Weak"
781
+ ]
782
+ },
783
+ {
784
+ "album": "Raindrops on the Windowpane",
785
+ "name": "Pieces of a Dream",
786
+ "tags": [
787
+ "Lounge Bar Relaxation"
788
+ ]
789
+ },
790
+ {
791
+ "album": "Raindrops on the Windowpane",
792
+ "name": "Puzzle",
793
+ "tags": [
794
+ "Slightly dark",
795
+ "Calm"
796
+ ]
797
+ },
798
+ {
799
+ "album": "Raindrops on the Windowpane",
800
+ "name": "The meaning of tears",
801
+ "tags": [
802
+ "Touching ",
803
+ "Mellow"
804
+ ]
805
+ },
806
+ {
807
+ "album": "Sunday Laundry",
808
+ "name": "Abandoned cat in the Rain",
809
+ "tags": [
810
+ "Little dark",
811
+ "Lonely"
812
+ ]
813
+ },
814
+ {
815
+ "album": "Sunday Laundry",
816
+ "name": "Fairy Forest",
817
+ "tags": [
818
+ "Bright ",
819
+ "Fantasy ",
820
+ "Lively"
821
+ ]
822
+ },
823
+ {
824
+ "album": "Sunday Laundry",
825
+ "name": "In the sunlight filtering through the trees",
826
+ "tags": [
827
+ "Bright",
828
+ "Relaxed",
829
+ "Peaceful"
830
+ ]
831
+ },
832
+ {
833
+ "album": "Sunday Laundry",
834
+ "name": "Perfect Weather for a Walk",
835
+ "tags": [
836
+ "Cute",
837
+ "Bright",
838
+ "Simple",
839
+ "Fun",
840
+ "Relaxing"
841
+ ]
842
+ },
843
+ {
844
+ "album": "Sunday Laundry",
845
+ "name": "Rural Prairie",
846
+ "tags": [
847
+ "Bright",
848
+ "Pastoral",
849
+ "Gentle"
850
+ ]
851
+ },
852
+ {
853
+ "album": "Sunday Laundry",
854
+ "name": "Spring Classroom",
855
+ "tags": [
856
+ "Bright",
857
+ "Gentle"
858
+ ]
859
+ },
860
+ {
861
+ "album": "Sunset at the Pier",
862
+ "name": "Deep Sea Passage",
863
+ "tags": [
864
+ "Slightly bright",
865
+ "Inorganic"
866
+ ]
867
+ },
868
+ {
869
+ "album": "Sunset at the Pier",
870
+ "name": "Memory",
871
+ "tags": [
872
+ "Slightly dark",
873
+ "Magnificent"
874
+ ]
875
+ },
876
+ {
877
+ "album": "Sunset at the Pier",
878
+ "name": "Smiles and Tears",
879
+ "tags": [
880
+ "Slightly bright",
881
+ "Sad"
882
+ ]
883
+ },
884
+ {
885
+ "album": "Sunset at the Pier",
886
+ "name": "Surrounded by Silence",
887
+ "tags": [
888
+ "Gentle",
889
+ "Calm",
890
+ "Stylish",
891
+ "Easy listening"
892
+ ]
893
+ },
894
+ {
895
+ "album": "Zenith Garden",
896
+ "name": "Cold Sweat",
897
+ "tags": [
898
+ "Comical",
899
+ "Failure",
900
+ "Simple"
901
+ ]
902
+ },
903
+ {
904
+ "album": "Zenith Garden",
905
+ "name": "Hometown Sunset",
906
+ "tags": [
907
+ "Slightly dark",
908
+ "Gentle",
909
+ "Simple"
910
+ ]
911
+ },
912
+ {
913
+ "album": "Zenith Garden",
914
+ "name": "Nostalgia",
915
+ "tags": [
916
+ "Moving",
917
+ "Sad",
918
+ "Melancholy",
919
+ "Lonely"
920
+ ]
921
+ },
922
+ {
923
+ "album": "Zenith Garden",
924
+ "name": "Reverie",
925
+ "tags": [
926
+ "Slightly dark",
927
+ "Transparent"
928
+ ]
929
+ },
930
+ {
931
+ "album": "Zenith Garden",
932
+ "name": "Water Cave",
933
+ "tags": [
934
+ "Slightly dark",
935
+ "Inorganic",
936
+ "Transparent"
937
+ ]
938
+ }
939
+ ]
940
+ }
941
+ }
package/dist/index.js CHANGED
@@ -193,7 +193,7 @@ function resolveEnvironmentHost(environment) {
193
193
  }
194
194
  function sendStatusUpdate(service, status) {
195
195
  const actionDefinition = getActionDefinition(status.poseType, status.action);
196
- service.sendStatus(status.poseType, actionDefinition.name, status.bubble || status.action, typeof status.log === "string" ? status.log.trim() : "", getActionPlayback(actionDefinition));
196
+ service.sendStatus(status.poseType, actionDefinition.name, status.bubble || status.action, typeof status.log === "string" ? status.log.trim() : "", getActionPlayback(actionDefinition), status.propId);
197
197
  }
198
198
  function syncFixedStatus(service, status) {
199
199
  if (!service.hasValidIdentity() || !service.isConnected()) {
@@ -557,6 +557,7 @@ function normalizeIdlePlan(value) {
557
557
  const actionDurationSeconds = rawAction.durationSeconds;
558
558
  const bubble = rawAction.bubble;
559
559
  const log = rawAction.log;
560
+ const propId = rawAction.propId;
560
561
  if (!["stand", "sit", "lay", "floor"].includes(String(poseType))) {
561
562
  return {
562
563
  error: `stages[${stageIndex}].actions[${actionIndex}].poseType must be stand, sit, lay, or floor`,
@@ -601,6 +602,7 @@ function normalizeIdlePlan(value) {
601
602
  durationSeconds: actionDurationSeconds,
602
603
  bubble: bubble.trim(),
603
604
  ...(typeof log === "string" && log.trim() ? { log: log.trim() } : {}),
605
+ ...(typeof propId === "string" && propId.trim() ? { propId: propId.trim() } : {}),
604
606
  });
605
607
  }
606
608
  if (stageActionDurationSeconds !== durationSeconds) {
@@ -797,9 +799,9 @@ function formatActionList(actions, playback) {
797
799
  .map((entry) => entry.name)
798
800
  .join(", ");
799
801
  }
800
- function buildKichiActionDescription() {
802
+ function buildKichiActionDescription(service) {
801
803
  const actions = loadStaticConfig().actions;
802
- return [
804
+ const lines = [
803
805
  "Directly control the avatar inside Kichi World.",
804
806
  "Use this whenever the user explicitly asks you to make the Kichi avatar sit down, stand up, lie down, floor-sit, type, read, meditate, celebrate, or perform another listed animation.",
805
807
  "For most work, prefer a sit pose and switch actions as the task moves between stages.",
@@ -808,7 +810,13 @@ function buildKichiActionDescription() {
808
810
  `sit actions: ${actions.sit.map((entry) => entry.name).join(", ")}`,
809
811
  `lay actions: ${actions.lay.map((entry) => entry.name).join(", ")}`,
810
812
  `floor actions: ${actions.floor.map((entry) => entry.name).join(", ")}`,
811
- ].join("\n");
813
+ ];
814
+ const roomContext = service.getCachedRoomContext();
815
+ const poseableProps = roomContext?.PoseableProps;
816
+ if (Array.isArray(poseableProps) && poseableProps.length > 0) {
817
+ lines.push("", "Cached RoomContext.PoseableProps (from last kichi_query_status):", JSON.stringify(poseableProps), "When using a sit or lay pose, pick the propId whose DisplayName best matches the current task context and whose OccupancyState is not fully_occupied. If no prop fits, omit propId.");
818
+ }
819
+ return lines.join("\n");
812
820
  }
813
821
  function buildKichiIdlePlanDescription() {
814
822
  const actions = loadStaticConfig().actions;
@@ -1089,7 +1097,7 @@ const plugin = {
1089
1097
  api.registerTool(createAgentScopedTool(runtimeManager, (service) => ({
1090
1098
  name: "kichi_action",
1091
1099
  label: "kichi_action",
1092
- description: buildKichiActionDescription(),
1100
+ description: buildKichiActionDescription(service),
1093
1101
  parameters: {
1094
1102
  type: "object",
1095
1103
  properties: {
@@ -1107,11 +1115,15 @@ const plugin = {
1107
1115
  type: "boolean",
1108
1116
  description: "Set true ONLY when the user explicitly requests a pose or action. Omit during routine sync steps.",
1109
1117
  },
1118
+ propId: {
1119
+ type: "string",
1120
+ description: "Optional poseable prop ID from RoomContext.PoseableProps (obtained via kichi_query_status or cached). When specified, the avatar is seated at this prop; when omitted, the server picks the nearest available prop.",
1121
+ },
1110
1122
  },
1111
1123
  required: ["poseType", "action"],
1112
1124
  },
1113
1125
  execute: async (_toolCallId, params) => {
1114
- const { poseType, action, bubble, log, verify } = (params || {});
1126
+ const { poseType, action, bubble, log, verify, propId } = (params || {});
1115
1127
  if (!poseType || !action) {
1116
1128
  return jsonResult({ success: false, error: "poseType and action parameters are required" });
1117
1129
  }
@@ -1139,7 +1151,7 @@ const plugin = {
1139
1151
  const playback = getActionPlayback(matched);
1140
1152
  if (verify) {
1141
1153
  try {
1142
- const ack = await service.sendStatusVerified(normalizedPoseType, matched.name, bubbleText, logText, playback);
1154
+ const ack = await service.sendStatusVerified(normalizedPoseType, matched.name, bubbleText, logText, playback, propId);
1143
1155
  if (ack.warning) {
1144
1156
  return jsonResult({
1145
1157
  success: true,
@@ -1159,6 +1171,7 @@ const plugin = {
1159
1171
  action: matched.name,
1160
1172
  bubble: bubbleText,
1161
1173
  log: logText,
1174
+ propId,
1162
1175
  });
1163
1176
  }
1164
1177
  return jsonResult({
@@ -1239,6 +1252,10 @@ const plugin = {
1239
1252
  type: "string",
1240
1253
  description: "Optional log content for this action. Use the same language as the current conversation.",
1241
1254
  },
1255
+ propId: {
1256
+ type: "string",
1257
+ description: "Optional poseable prop ID from RoomContext.PoseableProps. When specified, the avatar is seated at this prop.",
1258
+ },
1242
1259
  },
1243
1260
  required: ["poseType", "action", "durationSeconds", "bubble"],
1244
1261
  },
@@ -1383,7 +1400,7 @@ const plugin = {
1383
1400
  api.registerTool(createAgentScopedTool(runtimeManager, (service) => ({
1384
1401
  name: "kichi_query_status",
1385
1402
  label: "kichi_query_status",
1386
- description: "Query Kichi room and avatar status — includes room personnel, notes, ownerState, idlePlan, weather/time, timer snapshot, daily note quota, and `hasCreatedMusicAlbumToday`. Use this when the user asks to check kichi status, room status, or who is in the room. Also use this before creating a new note or daily recommended music album. For heartbeat planning, use the returned idlePlan as reference when shaping the next idle plan.",
1403
+ description: "Query Kichi room and avatar status — includes room personnel, notes, ownerState, idlePlan, weather/time, timer snapshot, daily note quota, `hasCreatedMusicAlbumToday`, and RoomContext.PoseableProps (poseable props with PropId, DisplayName, SupportedPoseTypes, OccupancyState). The PoseableProps list is cached internally so that kichi_action can reference a propId during regular work sync without re-querying. Use this when the user asks to check kichi status, room status, or who is in the room. Also use this before creating a new note or daily recommended music album. For heartbeat planning, use the returned idlePlan as reference when shaping the next idle plan.",
1387
1404
  parameters: {
1388
1405
  type: "object",
1389
1406
  properties: {
@@ -17,6 +17,7 @@ export class KichiForwarderService {
17
17
  joinResolve = null;
18
18
  pendingRequests = new Map();
19
19
  onBotMessageReceived = null;
20
+ cachedRoomContext = null;
20
21
  constructor(logger, options) {
21
22
  this.logger = logger;
22
23
  this.options = options;
@@ -91,7 +92,7 @@ export class KichiForwarderService {
91
92
  }, 10000);
92
93
  });
93
94
  }
94
- sendStatus(poseType, action, bubble, log, playback) {
95
+ sendStatus(poseType, action, bubble, log, playback, propId) {
95
96
  if (!this.identity?.authKey || this.ws?.readyState !== WebSocket.OPEN)
96
97
  return;
97
98
  const payload = {
@@ -103,10 +104,11 @@ export class KichiForwarderService {
103
104
  bubble,
104
105
  log,
105
106
  playback,
107
+ ...(propId ? { propId } : {}),
106
108
  };
107
109
  this.ws.send(JSON.stringify(payload));
108
110
  }
109
- async sendStatusVerified(poseType, action, bubble, log, playback) {
111
+ async sendStatusVerified(poseType, action, bubble, log, playback, propId) {
110
112
  if (!this.identity?.authKey || this.ws?.readyState !== WebSocket.OPEN) {
111
113
  throw new Error("Kichi websocket is not connected");
112
114
  }
@@ -120,6 +122,7 @@ export class KichiForwarderService {
120
122
  bubble,
121
123
  log,
122
124
  playback,
125
+ ...(propId ? { propId } : {}),
123
126
  };
124
127
  return this.sendRequest(payload, "status_ack", 5000);
125
128
  }
@@ -181,7 +184,11 @@ export class KichiForwarderService {
181
184
  avatarId: identity.avatarId,
182
185
  authKey: identity.authKey,
183
186
  };
184
- return this.sendRequest(payload, "query_status_result");
187
+ const result = await this.sendRequest(payload, "query_status_result");
188
+ if (result.RoomContext && typeof result.RoomContext === "object") {
189
+ this.cachedRoomContext = result.RoomContext;
190
+ }
191
+ return result;
185
192
  }
186
193
  createNotesBoardNote(propId, data) {
187
194
  const identity = this.requireIdentity();
@@ -250,6 +257,7 @@ export class KichiForwarderService {
250
257
  return this.sendRequest(payload, "bot_message_ack", 5000);
251
258
  }
252
259
  isConnected() { return this.ws?.readyState === WebSocket.OPEN && !!this.identity?.authKey; }
260
+ getCachedRoomContext() { return this.cachedRoomContext; }
253
261
  hasValidIdentity() { return !!this.identity?.avatarId && !!this.identity?.authKey; }
254
262
  isLlmRuntimeEnabled() {
255
263
  return this.readStateFile()?.llmRuntimeEnabled ?? DEFAULT_LLM_RUNTIME_ENABLED;
package/index.ts CHANGED
@@ -264,6 +264,7 @@ function sendStatusUpdate(service: KichiForwarderService, status: ActionResult):
264
264
  status.bubble || status.action,
265
265
  typeof status.log === "string" ? status.log.trim() : "",
266
266
  getActionPlayback(actionDefinition),
267
+ status.propId,
267
268
  );
268
269
  }
269
270
 
@@ -712,6 +713,7 @@ function normalizeIdlePlan(value: unknown): { idlePlan?: IdlePlan; error?: strin
712
713
  const actionDurationSeconds = rawAction.durationSeconds;
713
714
  const bubble = rawAction.bubble;
714
715
  const log = rawAction.log;
716
+ const propId = rawAction.propId;
715
717
 
716
718
  if (!["stand", "sit", "lay", "floor"].includes(String(poseType))) {
717
719
  return {
@@ -759,6 +761,7 @@ function normalizeIdlePlan(value: unknown): { idlePlan?: IdlePlan; error?: strin
759
761
  durationSeconds: actionDurationSeconds,
760
762
  bubble: bubble.trim(),
761
763
  ...(typeof log === "string" && log.trim() ? { log: log.trim() } : {}),
764
+ ...(typeof propId === "string" && propId.trim() ? { propId: propId.trim() } : {}),
762
765
  });
763
766
  }
764
767
 
@@ -992,9 +995,9 @@ function formatActionList(actions: ActionDefinition[], playback: ActionPlayback[
992
995
  .join(", ");
993
996
  }
994
997
 
995
- function buildKichiActionDescription(): string {
998
+ function buildKichiActionDescription(service: KichiForwarderService): string {
996
999
  const actions = loadStaticConfig().actions;
997
- return [
1000
+ const lines = [
998
1001
  "Directly control the avatar inside Kichi World.",
999
1002
  "Use this whenever the user explicitly asks you to make the Kichi avatar sit down, stand up, lie down, floor-sit, type, read, meditate, celebrate, or perform another listed animation.",
1000
1003
  "For most work, prefer a sit pose and switch actions as the task moves between stages.",
@@ -1003,7 +1006,20 @@ function buildKichiActionDescription(): string {
1003
1006
  `sit actions: ${actions.sit.map((entry) => entry.name).join(", ")}`,
1004
1007
  `lay actions: ${actions.lay.map((entry) => entry.name).join(", ")}`,
1005
1008
  `floor actions: ${actions.floor.map((entry) => entry.name).join(", ")}`,
1006
- ].join("\n");
1009
+ ];
1010
+
1011
+ const roomContext = service.getCachedRoomContext();
1012
+ const poseableProps = roomContext?.PoseableProps;
1013
+ if (Array.isArray(poseableProps) && poseableProps.length > 0) {
1014
+ lines.push(
1015
+ "",
1016
+ "Cached RoomContext.PoseableProps (from last kichi_query_status):",
1017
+ JSON.stringify(poseableProps),
1018
+ "When using a sit or lay pose, pick the propId whose DisplayName best matches the current task context and whose OccupancyState is not fully_occupied. If no prop fits, omit propId.",
1019
+ );
1020
+ }
1021
+
1022
+ return lines.join("\n");
1007
1023
  }
1008
1024
 
1009
1025
  function buildKichiIdlePlanDescription(): string {
@@ -1312,7 +1328,7 @@ const plugin = {
1312
1328
  api.registerTool(createAgentScopedTool(runtimeManager, (service) => ({
1313
1329
  name: "kichi_action",
1314
1330
  label: "kichi_action",
1315
- description: buildKichiActionDescription(),
1331
+ description: buildKichiActionDescription(service),
1316
1332
  parameters: {
1317
1333
  type: "object",
1318
1334
  properties: {
@@ -1332,16 +1348,22 @@ const plugin = {
1332
1348
  description:
1333
1349
  "Set true ONLY when the user explicitly requests a pose or action. Omit during routine sync steps.",
1334
1350
  },
1351
+ propId: {
1352
+ type: "string",
1353
+ description:
1354
+ "Optional poseable prop ID from RoomContext.PoseableProps (obtained via kichi_query_status or cached). When specified, the avatar is seated at this prop; when omitted, the server picks the nearest available prop.",
1355
+ },
1335
1356
  },
1336
1357
  required: ["poseType", "action"],
1337
1358
  },
1338
1359
  execute: async (_toolCallId, params) => {
1339
- const { poseType, action, bubble, log, verify } = (params || {}) as {
1360
+ const { poseType, action, bubble, log, verify, propId } = (params || {}) as {
1340
1361
  poseType?: string;
1341
1362
  action?: string;
1342
1363
  bubble?: string;
1343
1364
  log?: string;
1344
1365
  verify?: boolean;
1366
+ propId?: string;
1345
1367
  };
1346
1368
  if (!poseType || !action) {
1347
1369
  return jsonResult({ success: false, error: "poseType and action parameters are required" });
@@ -1374,7 +1396,7 @@ const plugin = {
1374
1396
  if (verify) {
1375
1397
  try {
1376
1398
  const ack = await service.sendStatusVerified(
1377
- normalizedPoseType, matched.name, bubbleText, logText, playback,
1399
+ normalizedPoseType, matched.name, bubbleText, logText, playback, propId,
1378
1400
  );
1379
1401
  if (ack.warning) {
1380
1402
  return jsonResult({
@@ -1393,6 +1415,7 @@ const plugin = {
1393
1415
  action: matched.name,
1394
1416
  bubble: bubbleText,
1395
1417
  log: logText,
1418
+ propId,
1396
1419
  });
1397
1420
  }
1398
1421
 
@@ -1474,6 +1497,10 @@ const plugin = {
1474
1497
  type: "string",
1475
1498
  description: "Optional log content for this action. Use the same language as the current conversation.",
1476
1499
  },
1500
+ propId: {
1501
+ type: "string",
1502
+ description: "Optional poseable prop ID from RoomContext.PoseableProps. When specified, the avatar is seated at this prop.",
1503
+ },
1477
1504
  },
1478
1505
  required: ["poseType", "action", "durationSeconds", "bubble"],
1479
1506
  },
@@ -1629,7 +1656,7 @@ const plugin = {
1629
1656
  name: "kichi_query_status",
1630
1657
  label: "kichi_query_status",
1631
1658
  description:
1632
- "Query Kichi room and avatar status — includes room personnel, notes, ownerState, idlePlan, weather/time, timer snapshot, daily note quota, and `hasCreatedMusicAlbumToday`. Use this when the user asks to check kichi status, room status, or who is in the room. Also use this before creating a new note or daily recommended music album. For heartbeat planning, use the returned idlePlan as reference when shaping the next idle plan.",
1659
+ "Query Kichi room and avatar status — includes room personnel, notes, ownerState, idlePlan, weather/time, timer snapshot, daily note quota, `hasCreatedMusicAlbumToday`, and RoomContext.PoseableProps (poseable props with PropId, DisplayName, SupportedPoseTypes, OccupancyState). The PoseableProps list is cached internally so that kichi_action can reference a propId during regular work sync without re-querying. Use this when the user asks to check kichi status, room status, or who is in the room. Also use this before creating a new note or daily recommended music album. For heartbeat planning, use the returned idlePlan as reference when shaping the next idle plan.",
1633
1660
  parameters: {
1634
1661
  type: "object",
1635
1662
  properties: {
@@ -2,7 +2,7 @@
2
2
  "id": "kichi-forwarder",
3
3
  "name": "Kichi Forwarder",
4
4
  "description": "Native OpenClaw plugin for Kichi World with direct avatar control, status sync, timers, notes, and music tools",
5
- "version": "0.1.2-beta.6",
5
+ "version": "0.1.2-beta.8",
6
6
  "author": "OpenClaw",
7
7
  "skills": ["./skills/kichi-forwarder"],
8
8
  "configSchema": {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@yahaha-studio/kichi-forwarder",
3
- "version": "0.1.2-beta.6",
3
+ "version": "0.1.2-beta.8",
4
4
  "description": "Native OpenClaw plugin for Kichi World with direct avatar control, status sync, timers, notes, and music tools",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -31,7 +31,7 @@
31
31
  }
32
32
  },
33
33
  "scripts": {
34
- "build": "tsc -p tsconfig.json",
34
+ "build": "tsc -p tsconfig.json && node -e \"fs.cpSync('config','dist/config',{recursive:true})\"",
35
35
  "prepack": "npm run build"
36
36
  },
37
37
  "publishConfig": {
package/src/service.ts CHANGED
@@ -83,6 +83,7 @@ export class KichiForwarderService {
83
83
  }
84
84
  >();
85
85
  onBotMessageReceived: BotMessageReceivedHandler | null = null;
86
+ private cachedRoomContext: Record<string, unknown> | null = null;
86
87
 
87
88
  constructor(
88
89
  private logger: PluginLogger,
@@ -166,7 +167,7 @@ export class KichiForwarderService {
166
167
  });
167
168
  }
168
169
 
169
- sendStatus(poseType: PoseType | "", action: string, bubble: string, log: string, playback: ActionPlayback): void {
170
+ sendStatus(poseType: PoseType | "", action: string, bubble: string, log: string, playback: ActionPlayback, propId?: string): void {
170
171
  if (!this.identity?.authKey || this.ws?.readyState !== WebSocket.OPEN) return;
171
172
  const payload: StatusPayload = {
172
173
  type: "status",
@@ -177,6 +178,7 @@ export class KichiForwarderService {
177
178
  bubble,
178
179
  log,
179
180
  playback,
181
+ ...(propId ? { propId } : {}),
180
182
  };
181
183
  this.ws.send(JSON.stringify(payload));
182
184
  }
@@ -187,6 +189,7 @@ export class KichiForwarderService {
187
189
  bubble: string,
188
190
  log: string,
189
191
  playback: ActionPlayback,
192
+ propId?: string,
190
193
  ): Promise<StatusAckPayload> {
191
194
  if (!this.identity?.authKey || this.ws?.readyState !== WebSocket.OPEN) {
192
195
  throw new Error("Kichi websocket is not connected");
@@ -201,6 +204,7 @@ export class KichiForwarderService {
201
204
  bubble,
202
205
  log,
203
206
  playback,
207
+ ...(propId ? { propId } : {}),
204
208
  };
205
209
  return this.sendRequest<StatusAckPayload>(payload, "status_ack", 5000);
206
210
  }
@@ -267,7 +271,11 @@ export class KichiForwarderService {
267
271
  avatarId: identity.avatarId,
268
272
  authKey: identity.authKey,
269
273
  };
270
- return this.sendRequest<QueryStatusResultPayload>(payload, "query_status_result");
274
+ const result = await this.sendRequest<QueryStatusResultPayload>(payload, "query_status_result");
275
+ if (result.RoomContext && typeof result.RoomContext === "object") {
276
+ this.cachedRoomContext = result.RoomContext as Record<string, unknown>;
277
+ }
278
+ return result;
271
279
  }
272
280
 
273
281
  createNotesBoardNote(propId: string, data: string): void {
@@ -350,6 +358,8 @@ export class KichiForwarderService {
350
358
 
351
359
  isConnected(): boolean { return this.ws?.readyState === WebSocket.OPEN && !!this.identity?.authKey; }
352
360
 
361
+ getCachedRoomContext(): Record<string, unknown> | null { return this.cachedRoomContext; }
362
+
353
363
  hasValidIdentity(): boolean { return !!this.identity?.avatarId && !!this.identity?.authKey; }
354
364
 
355
365
  isLlmRuntimeEnabled(): boolean {
package/src/types.ts CHANGED
@@ -17,6 +17,7 @@ export type ActionResult = {
17
17
  action: string;
18
18
  bubble: string;
19
19
  log?: string;
20
+ propId?: string;
20
21
  };
21
22
 
22
23
  export type KichiStaticConfig = {
@@ -117,6 +118,7 @@ export type StatusPayload = {
117
118
  bubble: string;
118
119
  log: string;
119
120
  playback: ActionPlayback;
121
+ propId?: string;
120
122
  };
121
123
 
122
124
  export type StatusAckPayload = {
@@ -124,6 +126,7 @@ export type StatusAckPayload = {
124
126
  requestId: string;
125
127
  poseType: PoseType | "";
126
128
  action: string;
129
+ requestedPropId?: string;
127
130
  warning?: string;
128
131
  };
129
132
 
@@ -144,6 +147,7 @@ export type IdlePlanStageAction = {
144
147
  durationSeconds: number;
145
148
  bubble: string;
146
149
  log?: string;
150
+ propId?: string;
147
151
  };
148
152
 
149
153
  export type IdlePlanStage = {