@yahaha-studio/kichi-forwarder 0.1.2-beta.12 → 0.1.2-beta.13
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/dist/index.js +18 -1
- package/dist/src/service.js +24 -2
- package/index.ts +17 -2
- package/openclaw.plugin.json +1 -1
- package/package.json +1 -1
- package/src/service.ts +30 -1
- package/src/types.ts +1 -0
package/dist/index.js
CHANGED
|
@@ -961,6 +961,10 @@ const plugin = {
|
|
|
961
961
|
description: "Optional list of OpenClaw self-perceived personality tags",
|
|
962
962
|
items: { type: "string" },
|
|
963
963
|
},
|
|
964
|
+
source: {
|
|
965
|
+
type: "string",
|
|
966
|
+
description: "Optional join source identifier. Defaults to Kichi World join-source.json, then openclaw.",
|
|
967
|
+
},
|
|
964
968
|
},
|
|
965
969
|
required: ["botName", "bio"],
|
|
966
970
|
},
|
|
@@ -974,6 +978,7 @@ const plugin = {
|
|
|
974
978
|
let avatarId = params?.avatarId;
|
|
975
979
|
const botName = params?.botName?.trim();
|
|
976
980
|
const bio = params?.bio?.trim();
|
|
981
|
+
const rawSource = params?.source;
|
|
977
982
|
const { tags, error: tagsError } = normalizeJoinTags(params?.tags);
|
|
978
983
|
if (!avatarId) {
|
|
979
984
|
avatarId = service.readSavedAvatarId() ?? undefined;
|
|
@@ -987,10 +992,22 @@ const plugin = {
|
|
|
987
992
|
if (!bio) {
|
|
988
993
|
return jsonResult({ success: false, error: "No bio" });
|
|
989
994
|
}
|
|
995
|
+
let source;
|
|
996
|
+
try {
|
|
997
|
+
source = rawSource === undefined
|
|
998
|
+
? service.readConfiguredJoinSource() ?? "openclaw"
|
|
999
|
+
: trimOptionalString(rawSource);
|
|
1000
|
+
}
|
|
1001
|
+
catch (err) {
|
|
1002
|
+
return jsonResult({ success: false, error: err instanceof Error ? err.message : String(err) });
|
|
1003
|
+
}
|
|
1004
|
+
if (!source) {
|
|
1005
|
+
return jsonResult({ success: false, error: "source must be a non-empty string" });
|
|
1006
|
+
}
|
|
990
1007
|
if (tagsError) {
|
|
991
1008
|
return jsonResult({ success: false, error: tagsError });
|
|
992
1009
|
}
|
|
993
|
-
const result = await service.join(avatarId, botName, bio, tags ?? []);
|
|
1010
|
+
const result = await service.join(avatarId, botName, bio, tags ?? [], source);
|
|
994
1011
|
if (result.success) {
|
|
995
1012
|
return jsonResult({ success: true, authKey: result.authKey });
|
|
996
1013
|
}
|
package/dist/src/service.js
CHANGED
|
@@ -4,6 +4,7 @@ import * as path from "path";
|
|
|
4
4
|
import { randomUUID } from "node:crypto";
|
|
5
5
|
const MAX_NOTEBOARD_TEXT_LENGTH = 200;
|
|
6
6
|
const DEFAULT_LLM_RUNTIME_ENABLED = true;
|
|
7
|
+
const JOIN_SOURCE_FILE_NAME = "join-source.json";
|
|
7
8
|
export class KichiForwarderService {
|
|
8
9
|
logger;
|
|
9
10
|
options;
|
|
@@ -63,7 +64,7 @@ export class KichiForwarderService {
|
|
|
63
64
|
}
|
|
64
65
|
return this.getConnectionStatus();
|
|
65
66
|
}
|
|
66
|
-
async join(avatarId, botName, bio, tags) {
|
|
67
|
+
async join(avatarId, botName, bio, tags, source) {
|
|
67
68
|
if (!this.host) {
|
|
68
69
|
return { success: false, error: "No Kichi host configured. Run kichi_switch_host first." };
|
|
69
70
|
}
|
|
@@ -78,7 +79,7 @@ export class KichiForwarderService {
|
|
|
78
79
|
this.identity = { avatarId };
|
|
79
80
|
this.saveIdentity();
|
|
80
81
|
this.joinResolve = resolve;
|
|
81
|
-
const payload = { type: "join", avatarId, botName, bio, tags };
|
|
82
|
+
const payload = { type: "join", avatarId, botName, bio, tags, source };
|
|
82
83
|
const sendJoin = () => this.ws?.send(JSON.stringify(payload));
|
|
83
84
|
if (this.ws?.readyState === WebSocket.OPEN) {
|
|
84
85
|
sendJoin();
|
|
@@ -274,6 +275,24 @@ export class KichiForwarderService {
|
|
|
274
275
|
getRuntimeDir() {
|
|
275
276
|
return this.options.runtimeDir;
|
|
276
277
|
}
|
|
278
|
+
getJoinSourcePath() {
|
|
279
|
+
return path.join(this.getKichiWorldRootDir(), JOIN_SOURCE_FILE_NAME);
|
|
280
|
+
}
|
|
281
|
+
readConfiguredJoinSource() {
|
|
282
|
+
const sourcePath = this.getJoinSourcePath();
|
|
283
|
+
if (!fs.existsSync(sourcePath)) {
|
|
284
|
+
return null;
|
|
285
|
+
}
|
|
286
|
+
const data = JSON.parse(fs.readFileSync(sourcePath, "utf-8"));
|
|
287
|
+
if (!data || typeof data !== "object" || Array.isArray(data)) {
|
|
288
|
+
throw new Error(`${JOIN_SOURCE_FILE_NAME} must contain a JSON object`);
|
|
289
|
+
}
|
|
290
|
+
const source = data.source;
|
|
291
|
+
if (typeof source !== "string" || !source.trim()) {
|
|
292
|
+
throw new Error(`${JOIN_SOURCE_FILE_NAME} must contain a non-empty string source`);
|
|
293
|
+
}
|
|
294
|
+
return source.trim();
|
|
295
|
+
}
|
|
277
296
|
getStatePath() {
|
|
278
297
|
return path.join(this.options.runtimeDir, "state.json");
|
|
279
298
|
}
|
|
@@ -621,6 +640,9 @@ export class KichiForwarderService {
|
|
|
621
640
|
}
|
|
622
641
|
return path.join(this.options.runtimeDir, "hosts", encodeURIComponent(this.host));
|
|
623
642
|
}
|
|
643
|
+
getKichiWorldRootDir() {
|
|
644
|
+
return path.dirname(path.dirname(this.options.runtimeDir));
|
|
645
|
+
}
|
|
624
646
|
getWsUrl() {
|
|
625
647
|
if (!this.host) {
|
|
626
648
|
throw new Error("No Kichi host configured");
|
package/index.ts
CHANGED
|
@@ -1179,6 +1179,10 @@ const plugin = {
|
|
|
1179
1179
|
description: "Optional list of OpenClaw self-perceived personality tags",
|
|
1180
1180
|
items: { type: "string" },
|
|
1181
1181
|
},
|
|
1182
|
+
source: {
|
|
1183
|
+
type: "string",
|
|
1184
|
+
description: "Optional join source identifier. Defaults to Kichi World join-source.json, then openclaw.",
|
|
1185
|
+
},
|
|
1182
1186
|
},
|
|
1183
1187
|
required: ["botName", "bio"],
|
|
1184
1188
|
},
|
|
@@ -1192,6 +1196,7 @@ const plugin = {
|
|
|
1192
1196
|
let avatarId = (params as { avatarId?: string } | null)?.avatarId;
|
|
1193
1197
|
const botName = (params as { botName?: string } | null)?.botName?.trim();
|
|
1194
1198
|
const bio = (params as { bio?: string } | null)?.bio?.trim();
|
|
1199
|
+
const rawSource = (params as { source?: unknown } | null)?.source;
|
|
1195
1200
|
const { tags, error: tagsError } = normalizeJoinTags(
|
|
1196
1201
|
(params as { tags?: unknown } | null)?.tags,
|
|
1197
1202
|
);
|
|
@@ -1207,10 +1212,21 @@ const plugin = {
|
|
|
1207
1212
|
if (!bio) {
|
|
1208
1213
|
return jsonResult({ success: false, error: "No bio" });
|
|
1209
1214
|
}
|
|
1215
|
+
let source: string | null | undefined;
|
|
1216
|
+
try {
|
|
1217
|
+
source = rawSource === undefined
|
|
1218
|
+
? service.readConfiguredJoinSource() ?? "openclaw"
|
|
1219
|
+
: trimOptionalString(rawSource);
|
|
1220
|
+
} catch (err) {
|
|
1221
|
+
return jsonResult({ success: false, error: err instanceof Error ? err.message : String(err) });
|
|
1222
|
+
}
|
|
1223
|
+
if (!source) {
|
|
1224
|
+
return jsonResult({ success: false, error: "source must be a non-empty string" });
|
|
1225
|
+
}
|
|
1210
1226
|
if (tagsError) {
|
|
1211
1227
|
return jsonResult({ success: false, error: tagsError });
|
|
1212
1228
|
}
|
|
1213
|
-
const result = await service.join(avatarId, botName, bio, tags ?? []);
|
|
1229
|
+
const result = await service.join(avatarId, botName, bio, tags ?? [], source);
|
|
1214
1230
|
if (result.success) {
|
|
1215
1231
|
return jsonResult({ success: true, authKey: result.authKey });
|
|
1216
1232
|
}
|
|
@@ -1979,4 +1995,3 @@ const plugin = {
|
|
|
1979
1995
|
};
|
|
1980
1996
|
|
|
1981
1997
|
export default plugin;
|
|
1982
|
-
|
package/openclaw.plugin.json
CHANGED
|
@@ -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.
|
|
5
|
+
"version": "0.1.2-beta.13",
|
|
6
6
|
"author": "OpenClaw",
|
|
7
7
|
"skills": ["./skills/kichi-forwarder"],
|
|
8
8
|
"contracts": {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@yahaha-studio/kichi-forwarder",
|
|
3
|
-
"version": "0.1.2-beta.
|
|
3
|
+
"version": "0.1.2-beta.13",
|
|
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",
|
package/src/service.ts
CHANGED
|
@@ -33,6 +33,7 @@ import type {
|
|
|
33
33
|
|
|
34
34
|
const MAX_NOTEBOARD_TEXT_LENGTH = 200;
|
|
35
35
|
const DEFAULT_LLM_RUNTIME_ENABLED = true;
|
|
36
|
+
const JOIN_SOURCE_FILE_NAME = "join-source.json";
|
|
36
37
|
|
|
37
38
|
type AckFailureResult = {
|
|
38
39
|
success: false;
|
|
@@ -138,6 +139,7 @@ export class KichiForwarderService {
|
|
|
138
139
|
botName: string,
|
|
139
140
|
bio: string,
|
|
140
141
|
tags: string[],
|
|
142
|
+
source: string,
|
|
141
143
|
): Promise<JoinResult> {
|
|
142
144
|
if (!this.host) {
|
|
143
145
|
return { success: false, error: "No Kichi host configured. Run kichi_switch_host first." };
|
|
@@ -153,7 +155,7 @@ export class KichiForwarderService {
|
|
|
153
155
|
this.identity = { avatarId };
|
|
154
156
|
this.saveIdentity();
|
|
155
157
|
this.joinResolve = resolve;
|
|
156
|
-
const payload: JoinPayload = { type: "join", avatarId, botName, bio, tags };
|
|
158
|
+
const payload: JoinPayload = { type: "join", avatarId, botName, bio, tags, source };
|
|
157
159
|
const sendJoin = () => this.ws?.send(JSON.stringify(payload));
|
|
158
160
|
if (this.ws?.readyState === WebSocket.OPEN) {
|
|
159
161
|
sendJoin();
|
|
@@ -381,6 +383,29 @@ export class KichiForwarderService {
|
|
|
381
383
|
return this.options.runtimeDir;
|
|
382
384
|
}
|
|
383
385
|
|
|
386
|
+
getJoinSourcePath(): string {
|
|
387
|
+
return path.join(this.getKichiWorldRootDir(), JOIN_SOURCE_FILE_NAME);
|
|
388
|
+
}
|
|
389
|
+
|
|
390
|
+
readConfiguredJoinSource(): string | null {
|
|
391
|
+
const sourcePath = this.getJoinSourcePath();
|
|
392
|
+
if (!fs.existsSync(sourcePath)) {
|
|
393
|
+
return null;
|
|
394
|
+
}
|
|
395
|
+
|
|
396
|
+
const data = JSON.parse(fs.readFileSync(sourcePath, "utf-8")) as unknown;
|
|
397
|
+
if (!data || typeof data !== "object" || Array.isArray(data)) {
|
|
398
|
+
throw new Error(`${JOIN_SOURCE_FILE_NAME} must contain a JSON object`);
|
|
399
|
+
}
|
|
400
|
+
|
|
401
|
+
const source = (data as { source?: unknown }).source;
|
|
402
|
+
if (typeof source !== "string" || !source.trim()) {
|
|
403
|
+
throw new Error(`${JOIN_SOURCE_FILE_NAME} must contain a non-empty string source`);
|
|
404
|
+
}
|
|
405
|
+
|
|
406
|
+
return source.trim();
|
|
407
|
+
}
|
|
408
|
+
|
|
384
409
|
getStatePath(): string {
|
|
385
410
|
return path.join(this.options.runtimeDir, "state.json");
|
|
386
411
|
}
|
|
@@ -765,6 +790,10 @@ export class KichiForwarderService {
|
|
|
765
790
|
return path.join(this.options.runtimeDir, "hosts", encodeURIComponent(this.host));
|
|
766
791
|
}
|
|
767
792
|
|
|
793
|
+
private getKichiWorldRootDir(): string {
|
|
794
|
+
return path.dirname(path.dirname(this.options.runtimeDir));
|
|
795
|
+
}
|
|
796
|
+
|
|
768
797
|
private getWsUrl(): string {
|
|
769
798
|
if (!this.host) {
|
|
770
799
|
throw new Error("No Kichi host configured");
|