@yahaha-studio/kichi-forwarder 0.1.2-beta.8 → 0.1.2-beta.9
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 +216 -159
- package/index.ts +112 -58
- package/openclaw.plugin.json +17 -1
- package/package.json +6 -6
package/dist/index.js
CHANGED
|
@@ -811,7 +811,7 @@ function buildKichiActionDescription(service) {
|
|
|
811
811
|
`lay actions: ${actions.lay.map((entry) => entry.name).join(", ")}`,
|
|
812
812
|
`floor actions: ${actions.floor.map((entry) => entry.name).join(", ")}`,
|
|
813
813
|
];
|
|
814
|
-
const roomContext = service
|
|
814
|
+
const roomContext = service?.getCachedRoomContext();
|
|
815
815
|
const poseableProps = roomContext?.PoseableProps;
|
|
816
816
|
if (Array.isArray(poseableProps) && poseableProps.length > 0) {
|
|
817
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.");
|
|
@@ -858,17 +858,6 @@ function buildKichiPrompt() {
|
|
|
858
858
|
"User opt-out, Kichi config/test work, and explicit pose requests take priority over sync.",
|
|
859
859
|
].join("\n");
|
|
860
860
|
}
|
|
861
|
-
function createAgentScopedTool(runtimeManager, factory) {
|
|
862
|
-
return (ctx) => {
|
|
863
|
-
const locator = resolveToolLocator(ctx);
|
|
864
|
-
const agentId = runtimeManager.resolveRuntimeAgentId(locator);
|
|
865
|
-
if (!agentId) {
|
|
866
|
-
throw new Error("Failed to resolve agent-scoped Kichi runtime");
|
|
867
|
-
}
|
|
868
|
-
const service = runtimeManager.getRuntime(locator) ?? runtimeManager.createRuntimeForAgent(agentId);
|
|
869
|
-
return factory(service, ctx);
|
|
870
|
-
};
|
|
871
|
-
}
|
|
872
861
|
const GLOBAL_RUNTIME_MANAGER_KEY = "__kichi_forwarder_runtime_manager__";
|
|
873
862
|
function getRuntimeManager(logger) {
|
|
874
863
|
const globalState = globalThis;
|
|
@@ -889,6 +878,11 @@ const plugin = {
|
|
|
889
878
|
configSchema: { parse },
|
|
890
879
|
register(api) {
|
|
891
880
|
const runtimeManager = getRuntimeManager(api.logger);
|
|
881
|
+
runtimeManager.setEnvironmentHostResolver((environment) => {
|
|
882
|
+
const config = loadEnvironmentsConfig();
|
|
883
|
+
const host = config[environment];
|
|
884
|
+
return typeof host === "string" && host.trim() ? host : null;
|
|
885
|
+
});
|
|
892
886
|
registerPluginHooks(api, runtimeManager);
|
|
893
887
|
const musicTitleEnum = getMusicTitleEnum();
|
|
894
888
|
runtimeManager.setBotMessageHandler((service, msg) => {
|
|
@@ -936,11 +930,6 @@ const plugin = {
|
|
|
936
930
|
id: "kichi-forwarder",
|
|
937
931
|
start: (ctx) => {
|
|
938
932
|
parse(ctx.config.plugins?.entries?.["kichi-forwarder"]?.config);
|
|
939
|
-
runtimeManager.setEnvironmentHostResolver((environment) => {
|
|
940
|
-
const config = loadEnvironmentsConfig();
|
|
941
|
-
const host = config[environment];
|
|
942
|
-
return typeof host === "string" && host.trim() ? host : null;
|
|
943
|
-
});
|
|
944
933
|
runtimeManager.initializeStartupRuntimes();
|
|
945
934
|
},
|
|
946
935
|
stop: () => {
|
|
@@ -951,7 +940,7 @@ const plugin = {
|
|
|
951
940
|
}
|
|
952
941
|
},
|
|
953
942
|
});
|
|
954
|
-
api.registerTool(
|
|
943
|
+
api.registerTool((ctx) => ({
|
|
955
944
|
name: "kichi_join",
|
|
956
945
|
label: "kichi_join",
|
|
957
946
|
description: "Join Kichi world with avatarId, the current bot name, a short bio, and personality tags",
|
|
@@ -976,6 +965,12 @@ const plugin = {
|
|
|
976
965
|
required: ["botName", "bio"],
|
|
977
966
|
},
|
|
978
967
|
execute: async (_toolCallId, params) => {
|
|
968
|
+
const locator = resolveToolLocator(ctx);
|
|
969
|
+
const agentId = runtimeManager.resolveRuntimeAgentId(locator);
|
|
970
|
+
if (!agentId) {
|
|
971
|
+
return jsonResult({ success: false, error: "Failed to resolve agent-scoped Kichi runtime" });
|
|
972
|
+
}
|
|
973
|
+
const service = runtimeManager.getRuntime(locator) ?? runtimeManager.createRuntimeForAgent(agentId);
|
|
979
974
|
let avatarId = params?.avatarId;
|
|
980
975
|
const botName = params?.botName?.trim();
|
|
981
976
|
const bio = params?.bio?.trim();
|
|
@@ -1007,54 +1002,58 @@ const plugin = {
|
|
|
1007
1002
|
...(failure.errorMessage ? { errorMessage: failure.errorMessage } : {}),
|
|
1008
1003
|
});
|
|
1009
1004
|
},
|
|
1010
|
-
}))
|
|
1011
|
-
api.registerTool((ctx) => {
|
|
1012
|
-
|
|
1013
|
-
|
|
1014
|
-
|
|
1015
|
-
|
|
1016
|
-
|
|
1017
|
-
|
|
1018
|
-
|
|
1019
|
-
|
|
1020
|
-
|
|
1021
|
-
|
|
1022
|
-
parameters: {
|
|
1023
|
-
type: "object",
|
|
1024
|
-
properties: {
|
|
1025
|
-
environment: {
|
|
1026
|
-
type: "string",
|
|
1027
|
-
enum: VALID_ENVIRONMENTS,
|
|
1028
|
-
description: "Target environment: steam, steam-playtest, or test",
|
|
1029
|
-
},
|
|
1005
|
+
}));
|
|
1006
|
+
api.registerTool((ctx) => ({
|
|
1007
|
+
name: "kichi_switch_host",
|
|
1008
|
+
label: "kichi_switch_host",
|
|
1009
|
+
description: "Switch Kichi runtime environment and reconnect immediately without restarting the gateway. Host is resolved from config/environments.json.",
|
|
1010
|
+
parameters: {
|
|
1011
|
+
type: "object",
|
|
1012
|
+
properties: {
|
|
1013
|
+
environment: {
|
|
1014
|
+
type: "string",
|
|
1015
|
+
enum: VALID_ENVIRONMENTS,
|
|
1016
|
+
description: "Target environment: steam, steam-playtest, or test",
|
|
1030
1017
|
},
|
|
1031
|
-
required: ["environment"],
|
|
1032
|
-
},
|
|
1033
|
-
execute: async (_toolCallId, params) => {
|
|
1034
|
-
const environment = params?.environment;
|
|
1035
|
-
if (!isKichiEnvironment(environment)) {
|
|
1036
|
-
return jsonResult({ success: false, error: `environment must be one of: ${VALID_ENVIRONMENTS.join(", ")}` });
|
|
1037
|
-
}
|
|
1038
|
-
const resolved = resolveEnvironmentHost(environment);
|
|
1039
|
-
if (resolved.error) {
|
|
1040
|
-
return jsonResult({ success: false, error: resolved.error });
|
|
1041
|
-
}
|
|
1042
|
-
const status = await service.switchHost(resolved.host, environment);
|
|
1043
|
-
return jsonResult({
|
|
1044
|
-
success: true,
|
|
1045
|
-
environment,
|
|
1046
|
-
host: resolved.host,
|
|
1047
|
-
status,
|
|
1048
|
-
});
|
|
1049
1018
|
},
|
|
1050
|
-
|
|
1051
|
-
|
|
1052
|
-
|
|
1019
|
+
required: ["environment"],
|
|
1020
|
+
},
|
|
1021
|
+
execute: async (_toolCallId, params) => {
|
|
1022
|
+
const locator = resolveToolLocator(ctx);
|
|
1023
|
+
const agentId = runtimeManager.resolveRuntimeAgentId(locator);
|
|
1024
|
+
if (!agentId) {
|
|
1025
|
+
return jsonResult({ success: false, error: "Failed to resolve agent-scoped Kichi runtime" });
|
|
1026
|
+
}
|
|
1027
|
+
const service = runtimeManager.getRuntime(locator) ?? runtimeManager.createRuntimeForAgent(agentId);
|
|
1028
|
+
const environment = params?.environment;
|
|
1029
|
+
if (!isKichiEnvironment(environment)) {
|
|
1030
|
+
return jsonResult({ success: false, error: `environment must be one of: ${VALID_ENVIRONMENTS.join(", ")}` });
|
|
1031
|
+
}
|
|
1032
|
+
const resolved = resolveEnvironmentHost(environment);
|
|
1033
|
+
if (resolved.error) {
|
|
1034
|
+
return jsonResult({ success: false, error: resolved.error });
|
|
1035
|
+
}
|
|
1036
|
+
const status = await service.switchHost(resolved.host, environment);
|
|
1037
|
+
return jsonResult({
|
|
1038
|
+
success: true,
|
|
1039
|
+
environment,
|
|
1040
|
+
host: resolved.host,
|
|
1041
|
+
status,
|
|
1042
|
+
});
|
|
1043
|
+
},
|
|
1044
|
+
}));
|
|
1045
|
+
api.registerTool((ctx) => ({
|
|
1053
1046
|
name: "kichi_rejoin",
|
|
1054
1047
|
label: "kichi_rejoin",
|
|
1055
1048
|
description: "Request an immediate rejoin attempt with saved avatarId/authKey. Rejoin is also sent automatically after reconnect.",
|
|
1056
1049
|
parameters: { type: "object", properties: {} },
|
|
1057
|
-
execute: async () => {
|
|
1050
|
+
execute: async (_toolCallId, _params) => {
|
|
1051
|
+
const locator = resolveToolLocator(ctx);
|
|
1052
|
+
const agentId = runtimeManager.resolveRuntimeAgentId(locator);
|
|
1053
|
+
if (!agentId) {
|
|
1054
|
+
return jsonResult({ success: false, error: "Failed to resolve agent-scoped Kichi runtime" });
|
|
1055
|
+
}
|
|
1056
|
+
const service = runtimeManager.getRuntime(locator) ?? runtimeManager.createRuntimeForAgent(agentId);
|
|
1058
1057
|
const result = service.requestRejoin();
|
|
1059
1058
|
return jsonResult({
|
|
1060
1059
|
success: result.accepted,
|
|
@@ -1062,13 +1061,19 @@ const plugin = {
|
|
|
1062
1061
|
status: service.getConnectionStatus(),
|
|
1063
1062
|
});
|
|
1064
1063
|
},
|
|
1065
|
-
}))
|
|
1066
|
-
api.registerTool(
|
|
1064
|
+
}));
|
|
1065
|
+
api.registerTool((ctx) => ({
|
|
1067
1066
|
name: "kichi_leave",
|
|
1068
1067
|
label: "kichi_leave",
|
|
1069
1068
|
description: "Leave Kichi world",
|
|
1070
1069
|
parameters: { type: "object", properties: {} },
|
|
1071
|
-
execute: async () => {
|
|
1070
|
+
execute: async (_toolCallId, _params) => {
|
|
1071
|
+
const locator = resolveToolLocator(ctx);
|
|
1072
|
+
const agentId = runtimeManager.resolveRuntimeAgentId(locator);
|
|
1073
|
+
if (!agentId) {
|
|
1074
|
+
return jsonResult({ success: false, error: "Failed to resolve agent-scoped Kichi runtime" });
|
|
1075
|
+
}
|
|
1076
|
+
const service = runtimeManager.getRuntime(locator) ?? runtimeManager.createRuntimeForAgent(agentId);
|
|
1072
1077
|
const result = await service.leave();
|
|
1073
1078
|
if (result.success) {
|
|
1074
1079
|
return jsonResult({ success: true });
|
|
@@ -1081,110 +1086,126 @@ const plugin = {
|
|
|
1081
1086
|
...(failure.errorMessage ? { errorMessage: failure.errorMessage } : {}),
|
|
1082
1087
|
});
|
|
1083
1088
|
},
|
|
1084
|
-
}))
|
|
1085
|
-
api.registerTool(
|
|
1089
|
+
}));
|
|
1090
|
+
api.registerTool((ctx) => ({
|
|
1086
1091
|
name: "kichi_connection_status",
|
|
1087
1092
|
label: "kichi_connection_status",
|
|
1088
1093
|
description: "Check WebSocket connection status and identity readiness only. Does NOT return room info, avatar state, or personnel — use kichi_query_status for that.",
|
|
1089
1094
|
parameters: { type: "object", properties: {} },
|
|
1090
|
-
execute: async () => {
|
|
1095
|
+
execute: async (_toolCallId, _params) => {
|
|
1096
|
+
const locator = resolveToolLocator(ctx);
|
|
1097
|
+
const agentId = runtimeManager.resolveRuntimeAgentId(locator);
|
|
1098
|
+
if (!agentId) {
|
|
1099
|
+
return jsonResult({ success: false, error: "Failed to resolve agent-scoped Kichi runtime" });
|
|
1100
|
+
}
|
|
1101
|
+
const service = runtimeManager.getRuntime(locator) ?? runtimeManager.createRuntimeForAgent(agentId);
|
|
1091
1102
|
return jsonResult({
|
|
1092
1103
|
success: true,
|
|
1093
1104
|
status: service.getConnectionStatus(),
|
|
1094
1105
|
});
|
|
1095
1106
|
},
|
|
1096
|
-
}))
|
|
1097
|
-
api.registerTool(
|
|
1098
|
-
|
|
1099
|
-
|
|
1100
|
-
|
|
1101
|
-
|
|
1102
|
-
|
|
1103
|
-
|
|
1104
|
-
|
|
1105
|
-
|
|
1106
|
-
|
|
1107
|
-
|
|
1108
|
-
|
|
1109
|
-
|
|
1110
|
-
|
|
1111
|
-
|
|
1112
|
-
|
|
1113
|
-
|
|
1114
|
-
|
|
1115
|
-
|
|
1116
|
-
|
|
1117
|
-
|
|
1118
|
-
|
|
1119
|
-
|
|
1120
|
-
|
|
1107
|
+
}));
|
|
1108
|
+
api.registerTool((ctx) => {
|
|
1109
|
+
const locator = resolveToolLocator(ctx);
|
|
1110
|
+
const existingService = runtimeManager.getRuntime(locator);
|
|
1111
|
+
return ({
|
|
1112
|
+
name: "kichi_action",
|
|
1113
|
+
label: "kichi_action",
|
|
1114
|
+
description: buildKichiActionDescription(existingService ?? undefined),
|
|
1115
|
+
parameters: {
|
|
1116
|
+
type: "object",
|
|
1117
|
+
properties: {
|
|
1118
|
+
poseType: { type: "string", description: "Pose type: stand, sit, lay, or floor" },
|
|
1119
|
+
action: {
|
|
1120
|
+
type: "string",
|
|
1121
|
+
description: "Action name for the selected pose (for example Sit Nicely, Typing with Keyboard, Reading, High Five, or Meditate)",
|
|
1122
|
+
},
|
|
1123
|
+
bubble: { type: "string", description: "Optional bubble text to display (max 5 words)" },
|
|
1124
|
+
log: {
|
|
1125
|
+
type: "string",
|
|
1126
|
+
description: "Short natural first-person sentence under 15 words. Match the language of the bubble and mention the current action and immediate focus.",
|
|
1127
|
+
},
|
|
1128
|
+
verify: {
|
|
1129
|
+
type: "boolean",
|
|
1130
|
+
description: "Set true ONLY when the user explicitly requests a pose or action. Omit during routine sync steps.",
|
|
1131
|
+
},
|
|
1132
|
+
propId: {
|
|
1133
|
+
type: "string",
|
|
1134
|
+
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.",
|
|
1135
|
+
},
|
|
1121
1136
|
},
|
|
1137
|
+
required: ["poseType", "action"],
|
|
1122
1138
|
},
|
|
1123
|
-
|
|
1124
|
-
|
|
1125
|
-
|
|
1126
|
-
|
|
1127
|
-
|
|
1128
|
-
|
|
1129
|
-
|
|
1130
|
-
|
|
1131
|
-
|
|
1132
|
-
success: false,
|
|
1133
|
-
|
|
1134
|
-
|
|
1135
|
-
|
|
1136
|
-
|
|
1137
|
-
|
|
1138
|
-
|
|
1139
|
-
|
|
1140
|
-
|
|
1141
|
-
|
|
1142
|
-
|
|
1143
|
-
|
|
1144
|
-
|
|
1145
|
-
|
|
1146
|
-
|
|
1147
|
-
|
|
1148
|
-
|
|
1149
|
-
|
|
1150
|
-
|
|
1151
|
-
|
|
1152
|
-
|
|
1153
|
-
|
|
1154
|
-
|
|
1155
|
-
|
|
1156
|
-
|
|
1157
|
-
|
|
1158
|
-
|
|
1159
|
-
|
|
1160
|
-
|
|
1161
|
-
|
|
1139
|
+
execute: async (_toolCallId, params) => {
|
|
1140
|
+
const locator = resolveToolLocator(ctx);
|
|
1141
|
+
const agentId = runtimeManager.resolveRuntimeAgentId(locator);
|
|
1142
|
+
if (!agentId) {
|
|
1143
|
+
return jsonResult({ success: false, error: "Failed to resolve agent-scoped Kichi runtime" });
|
|
1144
|
+
}
|
|
1145
|
+
const service = runtimeManager.getRuntime(locator) ?? runtimeManager.createRuntimeForAgent(agentId);
|
|
1146
|
+
const { poseType, action, bubble, log, verify, propId } = (params || {});
|
|
1147
|
+
if (!poseType || !action) {
|
|
1148
|
+
return jsonResult({ success: false, error: "poseType and action parameters are required" });
|
|
1149
|
+
}
|
|
1150
|
+
if (!["stand", "sit", "lay", "floor"].includes(poseType)) {
|
|
1151
|
+
return jsonResult({
|
|
1152
|
+
success: false,
|
|
1153
|
+
error: `Invalid poseType: ${poseType}. Must be stand, sit, lay, or floor`,
|
|
1154
|
+
});
|
|
1155
|
+
}
|
|
1156
|
+
if (!service.hasValidIdentity() || !service.isConnected()) {
|
|
1157
|
+
return jsonResult({ success: false, error: "Not connected to Kichi world" });
|
|
1158
|
+
}
|
|
1159
|
+
const normalizedPoseType = poseType;
|
|
1160
|
+
const poseActions = loadStaticConfig().actions[normalizedPoseType];
|
|
1161
|
+
const matched = poseActions.find((entry) => entry.name.toLowerCase() === action.toLowerCase());
|
|
1162
|
+
if (!matched) {
|
|
1163
|
+
return jsonResult({
|
|
1164
|
+
success: false,
|
|
1165
|
+
error: `Unknown action "${action}" for poseType "${poseType}"`,
|
|
1166
|
+
available: poseActions.map((entry) => entry.name),
|
|
1167
|
+
});
|
|
1168
|
+
}
|
|
1169
|
+
const bubbleText = typeof bubble === "string" && bubble.trim() ? bubble.trim() : matched.name;
|
|
1170
|
+
const logText = typeof log === "string" ? log.trim() : "";
|
|
1171
|
+
const playback = getActionPlayback(matched);
|
|
1172
|
+
if (verify) {
|
|
1173
|
+
try {
|
|
1174
|
+
const ack = await service.sendStatusVerified(normalizedPoseType, matched.name, bubbleText, logText, playback, propId);
|
|
1175
|
+
if (ack.warning) {
|
|
1176
|
+
return jsonResult({
|
|
1177
|
+
success: true,
|
|
1178
|
+
requested: { poseType: normalizedPoseType, action: matched.name },
|
|
1179
|
+
actual: { poseType: ack.poseType, action: ack.action },
|
|
1180
|
+
warning: ack.warning,
|
|
1181
|
+
});
|
|
1182
|
+
}
|
|
1183
|
+
}
|
|
1184
|
+
catch {
|
|
1185
|
+
// Server not updated or timeout — fall through to normal success
|
|
1162
1186
|
}
|
|
1163
1187
|
}
|
|
1164
|
-
|
|
1165
|
-
|
|
1188
|
+
else {
|
|
1189
|
+
sendStatusUpdate(service, {
|
|
1190
|
+
poseType: normalizedPoseType,
|
|
1191
|
+
action: matched.name,
|
|
1192
|
+
bubble: bubbleText,
|
|
1193
|
+
log: logText,
|
|
1194
|
+
propId,
|
|
1195
|
+
});
|
|
1166
1196
|
}
|
|
1167
|
-
|
|
1168
|
-
|
|
1169
|
-
sendStatusUpdate(service, {
|
|
1197
|
+
return jsonResult({
|
|
1198
|
+
success: true,
|
|
1170
1199
|
poseType: normalizedPoseType,
|
|
1171
1200
|
action: matched.name,
|
|
1172
1201
|
bubble: bubbleText,
|
|
1173
1202
|
log: logText,
|
|
1174
|
-
|
|
1203
|
+
playback,
|
|
1175
1204
|
});
|
|
1176
|
-
}
|
|
1177
|
-
|
|
1178
|
-
|
|
1179
|
-
|
|
1180
|
-
action: matched.name,
|
|
1181
|
-
bubble: bubbleText,
|
|
1182
|
-
log: logText,
|
|
1183
|
-
playback,
|
|
1184
|
-
});
|
|
1185
|
-
},
|
|
1186
|
-
})));
|
|
1187
|
-
api.registerTool(createAgentScopedTool(runtimeManager, (service) => ({
|
|
1205
|
+
},
|
|
1206
|
+
});
|
|
1207
|
+
});
|
|
1208
|
+
api.registerTool((ctx) => ({
|
|
1188
1209
|
name: "kichi_idle_plan",
|
|
1189
1210
|
label: "kichi_idle_plan",
|
|
1190
1211
|
description: buildKichiIdlePlanDescription(),
|
|
@@ -1268,6 +1289,12 @@ const plugin = {
|
|
|
1268
1289
|
required: ["heartbeatIntervalSeconds", "goal", "stages"],
|
|
1269
1290
|
},
|
|
1270
1291
|
execute: async (_toolCallId, params) => {
|
|
1292
|
+
const locator = resolveToolLocator(ctx);
|
|
1293
|
+
const agentId = runtimeManager.resolveRuntimeAgentId(locator);
|
|
1294
|
+
if (!agentId) {
|
|
1295
|
+
return jsonResult({ success: false, error: "Failed to resolve agent-scoped Kichi runtime" });
|
|
1296
|
+
}
|
|
1297
|
+
const service = runtimeManager.getRuntime(locator) ?? runtimeManager.createRuntimeForAgent(agentId);
|
|
1271
1298
|
const { idlePlan, error } = normalizeIdlePlan(params);
|
|
1272
1299
|
if (!idlePlan) {
|
|
1273
1300
|
return jsonResult({ success: false, error: error ?? "Invalid idle plan payload" });
|
|
@@ -1293,8 +1320,8 @@ const plugin = {
|
|
|
1293
1320
|
stages: idlePlan.stages,
|
|
1294
1321
|
});
|
|
1295
1322
|
},
|
|
1296
|
-
}))
|
|
1297
|
-
api.registerTool(
|
|
1323
|
+
}));
|
|
1324
|
+
api.registerTool((ctx) => ({
|
|
1298
1325
|
name: "kichi_clock",
|
|
1299
1326
|
label: "kichi_clock",
|
|
1300
1327
|
description: "Send clock commands to Kichi world. Supported actions are set and stop.",
|
|
@@ -1363,6 +1390,12 @@ const plugin = {
|
|
|
1363
1390
|
required: ["action"],
|
|
1364
1391
|
},
|
|
1365
1392
|
execute: async (_toolCallId, params) => {
|
|
1393
|
+
const locator = resolveToolLocator(ctx);
|
|
1394
|
+
const agentId = runtimeManager.resolveRuntimeAgentId(locator);
|
|
1395
|
+
if (!agentId) {
|
|
1396
|
+
return jsonResult({ success: false, error: "Failed to resolve agent-scoped Kichi runtime" });
|
|
1397
|
+
}
|
|
1398
|
+
const service = runtimeManager.getRuntime(locator) ?? runtimeManager.createRuntimeForAgent(agentId);
|
|
1366
1399
|
const { action, requestId, clock } = (params || {});
|
|
1367
1400
|
if (!isClockAction(action)) {
|
|
1368
1401
|
return jsonResult({
|
|
@@ -1396,8 +1429,8 @@ const plugin = {
|
|
|
1396
1429
|
...(normalizedClock ? { clock: normalizedClock } : {}),
|
|
1397
1430
|
});
|
|
1398
1431
|
},
|
|
1399
|
-
}))
|
|
1400
|
-
api.registerTool(
|
|
1432
|
+
}));
|
|
1433
|
+
api.registerTool((ctx) => ({
|
|
1401
1434
|
name: "kichi_query_status",
|
|
1402
1435
|
label: "kichi_query_status",
|
|
1403
1436
|
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.",
|
|
@@ -1411,6 +1444,12 @@ const plugin = {
|
|
|
1411
1444
|
},
|
|
1412
1445
|
},
|
|
1413
1446
|
execute: async (_toolCallId, params) => {
|
|
1447
|
+
const locator = resolveToolLocator(ctx);
|
|
1448
|
+
const agentId = runtimeManager.resolveRuntimeAgentId(locator);
|
|
1449
|
+
if (!agentId) {
|
|
1450
|
+
return jsonResult({ success: false, error: "Failed to resolve agent-scoped Kichi runtime" });
|
|
1451
|
+
}
|
|
1452
|
+
const service = runtimeManager.getRuntime(locator) ?? runtimeManager.createRuntimeForAgent(agentId);
|
|
1414
1453
|
const requestId = params?.requestId;
|
|
1415
1454
|
if (requestId !== undefined && typeof requestId !== "string") {
|
|
1416
1455
|
return jsonResult({ success: false, error: "requestId must be a string when provided" });
|
|
@@ -1429,8 +1468,8 @@ const plugin = {
|
|
|
1429
1468
|
});
|
|
1430
1469
|
}
|
|
1431
1470
|
},
|
|
1432
|
-
}))
|
|
1433
|
-
api.registerTool(
|
|
1471
|
+
}));
|
|
1472
|
+
api.registerTool((ctx) => ({
|
|
1434
1473
|
name: "kichi_music_album_create",
|
|
1435
1474
|
label: "kichi_music_album_create",
|
|
1436
1475
|
description: buildMusicAlbumToolDescription(),
|
|
@@ -1457,6 +1496,12 @@ const plugin = {
|
|
|
1457
1496
|
required: ["albumTitle", "musicTitles"],
|
|
1458
1497
|
},
|
|
1459
1498
|
execute: async (_toolCallId, params) => {
|
|
1499
|
+
const locator = resolveToolLocator(ctx);
|
|
1500
|
+
const agentId = runtimeManager.resolveRuntimeAgentId(locator);
|
|
1501
|
+
if (!agentId) {
|
|
1502
|
+
return jsonResult({ success: false, error: "Failed to resolve agent-scoped Kichi runtime" });
|
|
1503
|
+
}
|
|
1504
|
+
const service = runtimeManager.getRuntime(locator) ?? runtimeManager.createRuntimeForAgent(agentId);
|
|
1460
1505
|
const { requestId, albumTitle, musicTitles, } = (params || {});
|
|
1461
1506
|
if (requestId !== undefined && typeof requestId !== "string") {
|
|
1462
1507
|
return jsonResult({ success: false, error: "requestId must be a string when provided" });
|
|
@@ -1503,8 +1548,8 @@ const plugin = {
|
|
|
1503
1548
|
});
|
|
1504
1549
|
}
|
|
1505
1550
|
},
|
|
1506
|
-
}))
|
|
1507
|
-
api.registerTool(
|
|
1551
|
+
}));
|
|
1552
|
+
api.registerTool((ctx) => ({
|
|
1508
1553
|
name: "kichi_noteboard_create",
|
|
1509
1554
|
label: "kichi_noteboard_create",
|
|
1510
1555
|
description: "Create a new note on a specific Kichi note board. Prefer querying first so you can avoid duplicate posts and respect rate limits.",
|
|
@@ -1523,6 +1568,12 @@ const plugin = {
|
|
|
1523
1568
|
required: ["propId", "data"],
|
|
1524
1569
|
},
|
|
1525
1570
|
execute: async (_toolCallId, params) => {
|
|
1571
|
+
const locator = resolveToolLocator(ctx);
|
|
1572
|
+
const agentId = runtimeManager.resolveRuntimeAgentId(locator);
|
|
1573
|
+
if (!agentId) {
|
|
1574
|
+
return jsonResult({ success: false, error: "Failed to resolve agent-scoped Kichi runtime" });
|
|
1575
|
+
}
|
|
1576
|
+
const service = runtimeManager.getRuntime(locator) ?? runtimeManager.createRuntimeForAgent(agentId);
|
|
1526
1577
|
const { propId, data } = (params || {});
|
|
1527
1578
|
if (typeof propId !== "string" || !propId.trim()) {
|
|
1528
1579
|
return jsonResult({ success: false, error: "propId is required" });
|
|
@@ -1550,8 +1601,8 @@ const plugin = {
|
|
|
1550
1601
|
});
|
|
1551
1602
|
}
|
|
1552
1603
|
},
|
|
1553
|
-
}))
|
|
1554
|
-
api.registerTool(
|
|
1604
|
+
}));
|
|
1605
|
+
api.registerTool((ctx) => ({
|
|
1555
1606
|
name: "kichi_bot_message",
|
|
1556
1607
|
label: "kichi_bot_message",
|
|
1557
1608
|
description: "Send a message to another bot in the same Kichi world. The bubble is the visible message content. Do not repeat what has already been said in the conversation history. When targeting a specific bot by name, call kichi_query_status first to resolve their avatarId. Only use \"*\" when broadcasting to all bots without a specific target.",
|
|
@@ -1587,6 +1638,12 @@ const plugin = {
|
|
|
1587
1638
|
required: ["toAvatarId", "depth", "bubble"],
|
|
1588
1639
|
},
|
|
1589
1640
|
execute: async (_toolCallId, params) => {
|
|
1641
|
+
const locator = resolveToolLocator(ctx);
|
|
1642
|
+
const agentId = runtimeManager.resolveRuntimeAgentId(locator);
|
|
1643
|
+
if (!agentId) {
|
|
1644
|
+
return jsonResult({ success: false, error: "Failed to resolve agent-scoped Kichi runtime" });
|
|
1645
|
+
}
|
|
1646
|
+
const service = runtimeManager.getRuntime(locator) ?? runtimeManager.createRuntimeForAgent(agentId);
|
|
1590
1647
|
const { toAvatarId, depth, bubble, poseType, action, log } = (params || {});
|
|
1591
1648
|
if (typeof toAvatarId !== "string" || !toAvatarId.trim()) {
|
|
1592
1649
|
return jsonResult({ success: false, error: "toAvatarId is required" });
|
|
@@ -1618,7 +1675,7 @@ const plugin = {
|
|
|
1618
1675
|
return jsonResult({ success: false, error: `Failed to send bot message: ${error}` });
|
|
1619
1676
|
}
|
|
1620
1677
|
},
|
|
1621
|
-
}))
|
|
1678
|
+
}));
|
|
1622
1679
|
},
|
|
1623
1680
|
};
|
|
1624
1681
|
export default plugin;
|
package/index.ts
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import fs from "node:fs";
|
|
2
2
|
import { fileURLToPath } from "node:url";
|
|
3
3
|
import type {
|
|
4
|
-
AnyAgentTool,
|
|
5
4
|
OpenClawPluginApi,
|
|
6
5
|
} from "openclaw/plugin-sdk";
|
|
7
6
|
import type { OpenClawPluginToolContext } from "openclaw/plugin-sdk/core";
|
|
@@ -995,7 +994,7 @@ function formatActionList(actions: ActionDefinition[], playback: ActionPlayback[
|
|
|
995
994
|
.join(", ");
|
|
996
995
|
}
|
|
997
996
|
|
|
998
|
-
function buildKichiActionDescription(service
|
|
997
|
+
function buildKichiActionDescription(service?: KichiForwarderService): string {
|
|
999
998
|
const actions = loadStaticConfig().actions;
|
|
1000
999
|
const lines = [
|
|
1001
1000
|
"Directly control the avatar inside Kichi World.",
|
|
@@ -1008,7 +1007,7 @@ function buildKichiActionDescription(service: KichiForwarderService): string {
|
|
|
1008
1007
|
`floor actions: ${actions.floor.map((entry) => entry.name).join(", ")}`,
|
|
1009
1008
|
];
|
|
1010
1009
|
|
|
1011
|
-
const roomContext = service
|
|
1010
|
+
const roomContext = service?.getCachedRoomContext();
|
|
1012
1011
|
const poseableProps = roomContext?.PoseableProps;
|
|
1013
1012
|
if (Array.isArray(poseableProps) && poseableProps.length > 0) {
|
|
1014
1013
|
lines.push(
|
|
@@ -1064,20 +1063,6 @@ function buildKichiPrompt(): string {
|
|
|
1064
1063
|
].join("\n");
|
|
1065
1064
|
}
|
|
1066
1065
|
|
|
1067
|
-
function createAgentScopedTool(
|
|
1068
|
-
runtimeManager: KichiRuntimeManager,
|
|
1069
|
-
factory: (service: KichiForwarderService, ctx: OpenClawPluginToolContext) => AnyAgentTool,
|
|
1070
|
-
) {
|
|
1071
|
-
return (ctx: OpenClawPluginToolContext) => {
|
|
1072
|
-
const locator = resolveToolLocator(ctx);
|
|
1073
|
-
const agentId = runtimeManager.resolveRuntimeAgentId(locator);
|
|
1074
|
-
if (!agentId) {
|
|
1075
|
-
throw new Error("Failed to resolve agent-scoped Kichi runtime");
|
|
1076
|
-
}
|
|
1077
|
-
const service = runtimeManager.getRuntime(locator) ?? runtimeManager.createRuntimeForAgent(agentId);
|
|
1078
|
-
return factory(service, ctx);
|
|
1079
|
-
};
|
|
1080
|
-
}
|
|
1081
1066
|
|
|
1082
1067
|
const GLOBAL_RUNTIME_MANAGER_KEY = "__kichi_forwarder_runtime_manager__";
|
|
1083
1068
|
|
|
@@ -1107,6 +1092,13 @@ const plugin = {
|
|
|
1107
1092
|
|
|
1108
1093
|
register(api: OpenClawPluginApi) {
|
|
1109
1094
|
const runtimeManager = getRuntimeManager(api.logger);
|
|
1095
|
+
|
|
1096
|
+
runtimeManager.setEnvironmentHostResolver((environment) => {
|
|
1097
|
+
const config = loadEnvironmentsConfig();
|
|
1098
|
+
const host = config[environment];
|
|
1099
|
+
return typeof host === "string" && host.trim() ? host : null;
|
|
1100
|
+
});
|
|
1101
|
+
|
|
1110
1102
|
registerPluginHooks(api, runtimeManager);
|
|
1111
1103
|
const musicTitleEnum = getMusicTitleEnum();
|
|
1112
1104
|
|
|
@@ -1155,11 +1147,6 @@ const plugin = {
|
|
|
1155
1147
|
id: "kichi-forwarder",
|
|
1156
1148
|
start: (ctx) => {
|
|
1157
1149
|
parse(ctx.config.plugins?.entries?.["kichi-forwarder"]?.config);
|
|
1158
|
-
runtimeManager.setEnvironmentHostResolver((environment) => {
|
|
1159
|
-
const config = loadEnvironmentsConfig();
|
|
1160
|
-
const host = config[environment];
|
|
1161
|
-
return typeof host === "string" && host.trim() ? host : null;
|
|
1162
|
-
});
|
|
1163
1150
|
runtimeManager.initializeStartupRuntimes();
|
|
1164
1151
|
},
|
|
1165
1152
|
stop: () => {
|
|
@@ -1171,7 +1158,7 @@ const plugin = {
|
|
|
1171
1158
|
},
|
|
1172
1159
|
});
|
|
1173
1160
|
|
|
1174
|
-
api.registerTool(
|
|
1161
|
+
api.registerTool((ctx) => ({
|
|
1175
1162
|
name: "kichi_join",
|
|
1176
1163
|
label: "kichi_join",
|
|
1177
1164
|
description: "Join Kichi world with avatarId, the current bot name, a short bio, and personality tags",
|
|
@@ -1196,6 +1183,12 @@ const plugin = {
|
|
|
1196
1183
|
required: ["botName", "bio"],
|
|
1197
1184
|
},
|
|
1198
1185
|
execute: async (_toolCallId, params) => {
|
|
1186
|
+
const locator = resolveToolLocator(ctx);
|
|
1187
|
+
const agentId = runtimeManager.resolveRuntimeAgentId(locator);
|
|
1188
|
+
if (!agentId) {
|
|
1189
|
+
return jsonResult({ success: false, error: "Failed to resolve agent-scoped Kichi runtime" });
|
|
1190
|
+
}
|
|
1191
|
+
const service = runtimeManager.getRuntime(locator) ?? runtimeManager.createRuntimeForAgent(agentId);
|
|
1199
1192
|
let avatarId = (params as { avatarId?: string } | null)?.avatarId;
|
|
1200
1193
|
const botName = (params as { botName?: string } | null)?.botName?.trim();
|
|
1201
1194
|
const bio = (params as { bio?: string } | null)?.bio?.trim();
|
|
@@ -1229,16 +1222,9 @@ const plugin = {
|
|
|
1229
1222
|
...(failure.errorMessage ? { errorMessage: failure.errorMessage } : {}),
|
|
1230
1223
|
});
|
|
1231
1224
|
},
|
|
1232
|
-
}))
|
|
1225
|
+
}));
|
|
1233
1226
|
|
|
1234
|
-
api.registerTool((ctx
|
|
1235
|
-
const locator = resolveToolLocator(ctx);
|
|
1236
|
-
const agentId = runtimeManager.resolveRuntimeAgentId(locator);
|
|
1237
|
-
if (!agentId) {
|
|
1238
|
-
throw new Error("Failed to resolve agent-scoped Kichi runtime");
|
|
1239
|
-
}
|
|
1240
|
-
const service = runtimeManager.getRuntime(locator) ?? runtimeManager.createRuntimeForAgent(agentId);
|
|
1241
|
-
return ({
|
|
1227
|
+
api.registerTool((ctx) => ({
|
|
1242
1228
|
name: "kichi_switch_host",
|
|
1243
1229
|
label: "kichi_switch_host",
|
|
1244
1230
|
description:
|
|
@@ -1255,6 +1241,12 @@ const plugin = {
|
|
|
1255
1241
|
required: ["environment"],
|
|
1256
1242
|
},
|
|
1257
1243
|
execute: async (_toolCallId, params) => {
|
|
1244
|
+
const locator = resolveToolLocator(ctx);
|
|
1245
|
+
const agentId = runtimeManager.resolveRuntimeAgentId(locator);
|
|
1246
|
+
if (!agentId) {
|
|
1247
|
+
return jsonResult({ success: false, error: "Failed to resolve agent-scoped Kichi runtime" });
|
|
1248
|
+
}
|
|
1249
|
+
const service = runtimeManager.getRuntime(locator) ?? runtimeManager.createRuntimeForAgent(agentId);
|
|
1258
1250
|
const environment = (params as { environment?: unknown } | null)?.environment;
|
|
1259
1251
|
if (!isKichiEnvironment(environment)) {
|
|
1260
1252
|
return jsonResult({ success: false, error: `environment must be one of: ${VALID_ENVIRONMENTS.join(", ")}` });
|
|
@@ -1273,16 +1265,21 @@ const plugin = {
|
|
|
1273
1265
|
status,
|
|
1274
1266
|
});
|
|
1275
1267
|
},
|
|
1276
|
-
|
|
1277
|
-
});
|
|
1268
|
+
}));
|
|
1278
1269
|
|
|
1279
|
-
api.registerTool(
|
|
1270
|
+
api.registerTool((ctx) => ({
|
|
1280
1271
|
name: "kichi_rejoin",
|
|
1281
1272
|
label: "kichi_rejoin",
|
|
1282
1273
|
description:
|
|
1283
1274
|
"Request an immediate rejoin attempt with saved avatarId/authKey. Rejoin is also sent automatically after reconnect.",
|
|
1284
1275
|
parameters: { type: "object", properties: {} },
|
|
1285
|
-
execute: async () => {
|
|
1276
|
+
execute: async (_toolCallId, _params) => {
|
|
1277
|
+
const locator = resolveToolLocator(ctx);
|
|
1278
|
+
const agentId = runtimeManager.resolveRuntimeAgentId(locator);
|
|
1279
|
+
if (!agentId) {
|
|
1280
|
+
return jsonResult({ success: false, error: "Failed to resolve agent-scoped Kichi runtime" });
|
|
1281
|
+
}
|
|
1282
|
+
const service = runtimeManager.getRuntime(locator) ?? runtimeManager.createRuntimeForAgent(agentId);
|
|
1286
1283
|
const result = service.requestRejoin();
|
|
1287
1284
|
return jsonResult({
|
|
1288
1285
|
success: result.accepted,
|
|
@@ -1290,14 +1287,20 @@ const plugin = {
|
|
|
1290
1287
|
status: service.getConnectionStatus(),
|
|
1291
1288
|
});
|
|
1292
1289
|
},
|
|
1293
|
-
}))
|
|
1290
|
+
}));
|
|
1294
1291
|
|
|
1295
|
-
api.registerTool(
|
|
1292
|
+
api.registerTool((ctx) => ({
|
|
1296
1293
|
name: "kichi_leave",
|
|
1297
1294
|
label: "kichi_leave",
|
|
1298
1295
|
description: "Leave Kichi world",
|
|
1299
1296
|
parameters: { type: "object", properties: {} },
|
|
1300
|
-
execute: async () => {
|
|
1297
|
+
execute: async (_toolCallId, _params) => {
|
|
1298
|
+
const locator = resolveToolLocator(ctx);
|
|
1299
|
+
const agentId = runtimeManager.resolveRuntimeAgentId(locator);
|
|
1300
|
+
if (!agentId) {
|
|
1301
|
+
return jsonResult({ success: false, error: "Failed to resolve agent-scoped Kichi runtime" });
|
|
1302
|
+
}
|
|
1303
|
+
const service = runtimeManager.getRuntime(locator) ?? runtimeManager.createRuntimeForAgent(agentId);
|
|
1301
1304
|
const result = await service.leave();
|
|
1302
1305
|
if (result.success) {
|
|
1303
1306
|
return jsonResult({ success: true });
|
|
@@ -1310,25 +1313,34 @@ const plugin = {
|
|
|
1310
1313
|
...(failure.errorMessage ? { errorMessage: failure.errorMessage } : {}),
|
|
1311
1314
|
});
|
|
1312
1315
|
},
|
|
1313
|
-
}))
|
|
1316
|
+
}));
|
|
1314
1317
|
|
|
1315
|
-
api.registerTool(
|
|
1318
|
+
api.registerTool((ctx) => ({
|
|
1316
1319
|
name: "kichi_connection_status",
|
|
1317
1320
|
label: "kichi_connection_status",
|
|
1318
1321
|
description: "Check WebSocket connection status and identity readiness only. Does NOT return room info, avatar state, or personnel — use kichi_query_status for that.",
|
|
1319
1322
|
parameters: { type: "object", properties: {} },
|
|
1320
|
-
execute: async () => {
|
|
1323
|
+
execute: async (_toolCallId, _params) => {
|
|
1324
|
+
const locator = resolveToolLocator(ctx);
|
|
1325
|
+
const agentId = runtimeManager.resolveRuntimeAgentId(locator);
|
|
1326
|
+
if (!agentId) {
|
|
1327
|
+
return jsonResult({ success: false, error: "Failed to resolve agent-scoped Kichi runtime" });
|
|
1328
|
+
}
|
|
1329
|
+
const service = runtimeManager.getRuntime(locator) ?? runtimeManager.createRuntimeForAgent(agentId);
|
|
1321
1330
|
return jsonResult({
|
|
1322
1331
|
success: true,
|
|
1323
1332
|
status: service.getConnectionStatus(),
|
|
1324
1333
|
});
|
|
1325
1334
|
},
|
|
1326
|
-
}))
|
|
1335
|
+
}));
|
|
1327
1336
|
|
|
1328
|
-
api.registerTool(
|
|
1337
|
+
api.registerTool((ctx) => {
|
|
1338
|
+
const locator = resolveToolLocator(ctx);
|
|
1339
|
+
const existingService = runtimeManager.getRuntime(locator);
|
|
1340
|
+
return ({
|
|
1329
1341
|
name: "kichi_action",
|
|
1330
1342
|
label: "kichi_action",
|
|
1331
|
-
description: buildKichiActionDescription(
|
|
1343
|
+
description: buildKichiActionDescription(existingService ?? undefined),
|
|
1332
1344
|
parameters: {
|
|
1333
1345
|
type: "object",
|
|
1334
1346
|
properties: {
|
|
@@ -1357,6 +1369,12 @@ const plugin = {
|
|
|
1357
1369
|
required: ["poseType", "action"],
|
|
1358
1370
|
},
|
|
1359
1371
|
execute: async (_toolCallId, params) => {
|
|
1372
|
+
const locator = resolveToolLocator(ctx);
|
|
1373
|
+
const agentId = runtimeManager.resolveRuntimeAgentId(locator);
|
|
1374
|
+
if (!agentId) {
|
|
1375
|
+
return jsonResult({ success: false, error: "Failed to resolve agent-scoped Kichi runtime" });
|
|
1376
|
+
}
|
|
1377
|
+
const service = runtimeManager.getRuntime(locator) ?? runtimeManager.createRuntimeForAgent(agentId);
|
|
1360
1378
|
const { poseType, action, bubble, log, verify, propId } = (params || {}) as {
|
|
1361
1379
|
poseType?: string;
|
|
1362
1380
|
action?: string;
|
|
@@ -1428,8 +1446,8 @@ const plugin = {
|
|
|
1428
1446
|
playback,
|
|
1429
1447
|
});
|
|
1430
1448
|
},
|
|
1431
|
-
}))
|
|
1432
|
-
api.registerTool(
|
|
1449
|
+
})});
|
|
1450
|
+
api.registerTool((ctx) => ({
|
|
1433
1451
|
name: "kichi_idle_plan",
|
|
1434
1452
|
label: "kichi_idle_plan",
|
|
1435
1453
|
description: buildKichiIdlePlanDescription(),
|
|
@@ -1513,6 +1531,12 @@ const plugin = {
|
|
|
1513
1531
|
required: ["heartbeatIntervalSeconds", "goal", "stages"],
|
|
1514
1532
|
},
|
|
1515
1533
|
execute: async (_toolCallId, params) => {
|
|
1534
|
+
const locator = resolveToolLocator(ctx);
|
|
1535
|
+
const agentId = runtimeManager.resolveRuntimeAgentId(locator);
|
|
1536
|
+
if (!agentId) {
|
|
1537
|
+
return jsonResult({ success: false, error: "Failed to resolve agent-scoped Kichi runtime" });
|
|
1538
|
+
}
|
|
1539
|
+
const service = runtimeManager.getRuntime(locator) ?? runtimeManager.createRuntimeForAgent(agentId);
|
|
1516
1540
|
const { idlePlan, error } = normalizeIdlePlan(params);
|
|
1517
1541
|
if (!idlePlan) {
|
|
1518
1542
|
return jsonResult({ success: false, error: error ?? "Invalid idle plan payload" });
|
|
@@ -1538,8 +1562,8 @@ const plugin = {
|
|
|
1538
1562
|
stages: idlePlan.stages,
|
|
1539
1563
|
});
|
|
1540
1564
|
},
|
|
1541
|
-
}))
|
|
1542
|
-
api.registerTool(
|
|
1565
|
+
}));
|
|
1566
|
+
api.registerTool((ctx) => ({
|
|
1543
1567
|
name: "kichi_clock",
|
|
1544
1568
|
label: "kichi_clock",
|
|
1545
1569
|
description:
|
|
@@ -1609,6 +1633,12 @@ const plugin = {
|
|
|
1609
1633
|
required: ["action"],
|
|
1610
1634
|
},
|
|
1611
1635
|
execute: async (_toolCallId, params) => {
|
|
1636
|
+
const locator = resolveToolLocator(ctx);
|
|
1637
|
+
const agentId = runtimeManager.resolveRuntimeAgentId(locator);
|
|
1638
|
+
if (!agentId) {
|
|
1639
|
+
return jsonResult({ success: false, error: "Failed to resolve agent-scoped Kichi runtime" });
|
|
1640
|
+
}
|
|
1641
|
+
const service = runtimeManager.getRuntime(locator) ?? runtimeManager.createRuntimeForAgent(agentId);
|
|
1612
1642
|
const { action, requestId, clock } = (params || {}) as {
|
|
1613
1643
|
action?: unknown;
|
|
1614
1644
|
requestId?: unknown;
|
|
@@ -1650,9 +1680,9 @@ const plugin = {
|
|
|
1650
1680
|
...(normalizedClock ? { clock: normalizedClock } : {}),
|
|
1651
1681
|
});
|
|
1652
1682
|
},
|
|
1653
|
-
}))
|
|
1683
|
+
}));
|
|
1654
1684
|
|
|
1655
|
-
api.registerTool(
|
|
1685
|
+
api.registerTool((ctx) => ({
|
|
1656
1686
|
name: "kichi_query_status",
|
|
1657
1687
|
label: "kichi_query_status",
|
|
1658
1688
|
description:
|
|
@@ -1667,6 +1697,12 @@ const plugin = {
|
|
|
1667
1697
|
},
|
|
1668
1698
|
},
|
|
1669
1699
|
execute: async (_toolCallId, params) => {
|
|
1700
|
+
const locator = resolveToolLocator(ctx);
|
|
1701
|
+
const agentId = runtimeManager.resolveRuntimeAgentId(locator);
|
|
1702
|
+
if (!agentId) {
|
|
1703
|
+
return jsonResult({ success: false, error: "Failed to resolve agent-scoped Kichi runtime" });
|
|
1704
|
+
}
|
|
1705
|
+
const service = runtimeManager.getRuntime(locator) ?? runtimeManager.createRuntimeForAgent(agentId);
|
|
1670
1706
|
const requestId = (params as { requestId?: unknown } | null)?.requestId;
|
|
1671
1707
|
if (requestId !== undefined && typeof requestId !== "string") {
|
|
1672
1708
|
return jsonResult({ success: false, error: "requestId must be a string when provided" });
|
|
@@ -1687,9 +1723,9 @@ const plugin = {
|
|
|
1687
1723
|
});
|
|
1688
1724
|
}
|
|
1689
1725
|
},
|
|
1690
|
-
}))
|
|
1726
|
+
}));
|
|
1691
1727
|
|
|
1692
|
-
api.registerTool(
|
|
1728
|
+
api.registerTool((ctx) => ({
|
|
1693
1729
|
name: "kichi_music_album_create",
|
|
1694
1730
|
label: "kichi_music_album_create",
|
|
1695
1731
|
description: buildMusicAlbumToolDescription(),
|
|
@@ -1716,6 +1752,12 @@ const plugin = {
|
|
|
1716
1752
|
required: ["albumTitle", "musicTitles"],
|
|
1717
1753
|
},
|
|
1718
1754
|
execute: async (_toolCallId, params) => {
|
|
1755
|
+
const locator = resolveToolLocator(ctx);
|
|
1756
|
+
const agentId = runtimeManager.resolveRuntimeAgentId(locator);
|
|
1757
|
+
if (!agentId) {
|
|
1758
|
+
return jsonResult({ success: false, error: "Failed to resolve agent-scoped Kichi runtime" });
|
|
1759
|
+
}
|
|
1760
|
+
const service = runtimeManager.getRuntime(locator) ?? runtimeManager.createRuntimeForAgent(agentId);
|
|
1719
1761
|
const {
|
|
1720
1762
|
requestId,
|
|
1721
1763
|
albumTitle,
|
|
@@ -1776,9 +1818,9 @@ const plugin = {
|
|
|
1776
1818
|
});
|
|
1777
1819
|
}
|
|
1778
1820
|
},
|
|
1779
|
-
}))
|
|
1821
|
+
}));
|
|
1780
1822
|
|
|
1781
|
-
api.registerTool(
|
|
1823
|
+
api.registerTool((ctx) => ({
|
|
1782
1824
|
name: "kichi_noteboard_create",
|
|
1783
1825
|
label: "kichi_noteboard_create",
|
|
1784
1826
|
description:
|
|
@@ -1798,6 +1840,12 @@ const plugin = {
|
|
|
1798
1840
|
required: ["propId", "data"],
|
|
1799
1841
|
},
|
|
1800
1842
|
execute: async (_toolCallId, params) => {
|
|
1843
|
+
const locator = resolveToolLocator(ctx);
|
|
1844
|
+
const agentId = runtimeManager.resolveRuntimeAgentId(locator);
|
|
1845
|
+
if (!agentId) {
|
|
1846
|
+
return jsonResult({ success: false, error: "Failed to resolve agent-scoped Kichi runtime" });
|
|
1847
|
+
}
|
|
1848
|
+
const service = runtimeManager.getRuntime(locator) ?? runtimeManager.createRuntimeForAgent(agentId);
|
|
1801
1849
|
const { propId, data } = (params || {}) as {
|
|
1802
1850
|
propId?: unknown;
|
|
1803
1851
|
data?: unknown;
|
|
@@ -1828,9 +1876,9 @@ const plugin = {
|
|
|
1828
1876
|
});
|
|
1829
1877
|
}
|
|
1830
1878
|
},
|
|
1831
|
-
}))
|
|
1879
|
+
}));
|
|
1832
1880
|
|
|
1833
|
-
api.registerTool(
|
|
1881
|
+
api.registerTool((ctx) => ({
|
|
1834
1882
|
name: "kichi_bot_message",
|
|
1835
1883
|
label: "kichi_bot_message",
|
|
1836
1884
|
description:
|
|
@@ -1867,6 +1915,12 @@ const plugin = {
|
|
|
1867
1915
|
required: ["toAvatarId", "depth", "bubble"],
|
|
1868
1916
|
},
|
|
1869
1917
|
execute: async (_toolCallId, params) => {
|
|
1918
|
+
const locator = resolveToolLocator(ctx);
|
|
1919
|
+
const agentId = runtimeManager.resolveRuntimeAgentId(locator);
|
|
1920
|
+
if (!agentId) {
|
|
1921
|
+
return jsonResult({ success: false, error: "Failed to resolve agent-scoped Kichi runtime" });
|
|
1922
|
+
}
|
|
1923
|
+
const service = runtimeManager.getRuntime(locator) ?? runtimeManager.createRuntimeForAgent(agentId);
|
|
1870
1924
|
const { toAvatarId, depth, bubble, poseType, action, log } = (params || {}) as {
|
|
1871
1925
|
toAvatarId?: string;
|
|
1872
1926
|
depth?: number;
|
|
@@ -1904,7 +1958,7 @@ const plugin = {
|
|
|
1904
1958
|
return jsonResult({ success: false, error: `Failed to send bot message: ${error}` });
|
|
1905
1959
|
}
|
|
1906
1960
|
},
|
|
1907
|
-
}))
|
|
1961
|
+
}));
|
|
1908
1962
|
|
|
1909
1963
|
},
|
|
1910
1964
|
};
|
package/openclaw.plugin.json
CHANGED
|
@@ -2,9 +2,25 @@
|
|
|
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.9",
|
|
6
6
|
"author": "OpenClaw",
|
|
7
7
|
"skills": ["./skills/kichi-forwarder"],
|
|
8
|
+
"contracts": {
|
|
9
|
+
"tools": [
|
|
10
|
+
"kichi_join",
|
|
11
|
+
"kichi_switch_host",
|
|
12
|
+
"kichi_rejoin",
|
|
13
|
+
"kichi_leave",
|
|
14
|
+
"kichi_connection_status",
|
|
15
|
+
"kichi_action",
|
|
16
|
+
"kichi_idle_plan",
|
|
17
|
+
"kichi_clock",
|
|
18
|
+
"kichi_query_status",
|
|
19
|
+
"kichi_music_album_create",
|
|
20
|
+
"kichi_noteboard_create",
|
|
21
|
+
"kichi_bot_message"
|
|
22
|
+
]
|
|
23
|
+
},
|
|
8
24
|
"configSchema": {
|
|
9
25
|
"type": "object",
|
|
10
26
|
"additionalProperties": false,
|
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.9",
|
|
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",
|
|
@@ -22,12 +22,12 @@
|
|
|
22
22
|
"./dist/index.js"
|
|
23
23
|
],
|
|
24
24
|
"compat": {
|
|
25
|
-
"pluginApi": ">=2026.
|
|
26
|
-
"minGatewayVersion": "2026.
|
|
25
|
+
"pluginApi": ">=2026.4.25",
|
|
26
|
+
"minGatewayVersion": "2026.4.25"
|
|
27
27
|
},
|
|
28
28
|
"build": {
|
|
29
|
-
"openclawVersion": "2026.
|
|
30
|
-
"pluginSdkVersion": "2026.
|
|
29
|
+
"openclawVersion": "2026.5.7",
|
|
30
|
+
"pluginSdkVersion": "2026.5.7"
|
|
31
31
|
}
|
|
32
32
|
},
|
|
33
33
|
"scripts": {
|
|
@@ -43,7 +43,7 @@
|
|
|
43
43
|
"devDependencies": {
|
|
44
44
|
"@types/node": "^24.3.0",
|
|
45
45
|
"@types/ws": "^8.18.1",
|
|
46
|
-
"openclaw": "2026.
|
|
46
|
+
"openclaw": "2026.5.7",
|
|
47
47
|
"typescript": "^6.0.3"
|
|
48
48
|
}
|
|
49
49
|
}
|