@yahaha-studio/kichi-forwarder 0.1.2-beta.2 → 0.1.2-beta.21
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +6 -2
- package/dist/config/environments.json +5 -0
- package/dist/config/kichi-config.json +941 -0
- package/dist/index.js +1887 -0
- package/dist/src/config.js +4 -0
- package/dist/src/runtime-manager.js +121 -0
- package/dist/src/service.js +805 -0
- package/dist/src/types.js +1 -0
- package/index.ts +625 -158
- package/openclaw.plugin.json +18 -1
- package/package.json +16 -7
- package/skills/kichi-forwarder/SKILL.md +53 -17
- package/skills/kichi-forwarder/references/error.md +3 -11
- package/skills/kichi-forwarder/references/heartbeat.md +6 -14
- package/skills/kichi-forwarder/references/install.md +15 -37
- package/src/runtime-manager.ts +14 -2
- package/src/service.ts +190 -5
- package/src/types.ts +57 -2
package/openclaw.plugin.json
CHANGED
|
@@ -2,9 +2,26 @@
|
|
|
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.21",
|
|
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_glance",
|
|
17
|
+
"kichi_idle_plan",
|
|
18
|
+
"kichi_clock",
|
|
19
|
+
"kichi_query_status",
|
|
20
|
+
"kichi_music_album_create",
|
|
21
|
+
"kichi_noteboard_create",
|
|
22
|
+
"kichi_bot_message"
|
|
23
|
+
]
|
|
24
|
+
},
|
|
8
25
|
"configSchema": {
|
|
9
26
|
"type": "object",
|
|
10
27
|
"additionalProperties": false,
|
package/package.json
CHANGED
|
@@ -1,13 +1,14 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@yahaha-studio/kichi-forwarder",
|
|
3
|
-
"version": "0.1.2-beta.
|
|
3
|
+
"version": "0.1.2-beta.21",
|
|
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
|
-
"main": "index.
|
|
6
|
+
"main": "./dist/index.js",
|
|
7
7
|
"files": [
|
|
8
8
|
"README.md",
|
|
9
9
|
"assets/",
|
|
10
10
|
"config/",
|
|
11
|
+
"dist/",
|
|
11
12
|
"index.ts",
|
|
12
13
|
"openclaw.plugin.json",
|
|
13
14
|
"skills/",
|
|
@@ -17,15 +18,22 @@
|
|
|
17
18
|
"extensions": [
|
|
18
19
|
"./index.ts"
|
|
19
20
|
],
|
|
21
|
+
"runtimeExtensions": [
|
|
22
|
+
"./dist/index.js"
|
|
23
|
+
],
|
|
20
24
|
"compat": {
|
|
21
|
-
"pluginApi": ">=2026.
|
|
22
|
-
"minGatewayVersion": "2026.
|
|
25
|
+
"pluginApi": ">=2026.4.25",
|
|
26
|
+
"minGatewayVersion": "2026.4.25"
|
|
23
27
|
},
|
|
24
28
|
"build": {
|
|
25
|
-
"openclawVersion": "2026.
|
|
26
|
-
"pluginSdkVersion": "2026.
|
|
29
|
+
"openclawVersion": "2026.5.7",
|
|
30
|
+
"pluginSdkVersion": "2026.5.7"
|
|
27
31
|
}
|
|
28
32
|
},
|
|
33
|
+
"scripts": {
|
|
34
|
+
"build": "tsc -p tsconfig.json && node -e \"fs.cpSync('config','dist/config',{recursive:true})\"",
|
|
35
|
+
"prepack": "npm run build"
|
|
36
|
+
},
|
|
29
37
|
"publishConfig": {
|
|
30
38
|
"access": "public"
|
|
31
39
|
},
|
|
@@ -35,6 +43,7 @@
|
|
|
35
43
|
"devDependencies": {
|
|
36
44
|
"@types/node": "^24.3.0",
|
|
37
45
|
"@types/ws": "^8.18.1",
|
|
38
|
-
"openclaw": "2026.
|
|
46
|
+
"openclaw": "2026.5.7",
|
|
47
|
+
"typescript": "^6.0.3"
|
|
39
48
|
}
|
|
40
49
|
}
|
|
@@ -23,7 +23,7 @@ Install and connect requests use `on <environment>` syntax. Supported environmen
|
|
|
23
23
|
|
|
24
24
|
- `steam`: connects to `focus-wss.yahaha.com`
|
|
25
25
|
- `steam-playtest`: connects to `focus-steam-playtest-wss-int.yahaha.com`
|
|
26
|
-
- `test`: no fixed host —
|
|
26
|
+
- `test`: no fixed host — use the test host from the user request when provided; otherwise ask the user for the test host before calling `kichi_join`
|
|
27
27
|
|
|
28
28
|
## Runtime State
|
|
29
29
|
|
|
@@ -55,8 +55,7 @@ All tools listed in this file (`kichi_join`, `kichi_connection_status`, `kichi_a
|
|
|
55
55
|
For install/onboarding/connect requests:
|
|
56
56
|
|
|
57
57
|
- Read and follow `install.md` before starting the install flow.
|
|
58
|
-
-
|
|
59
|
-
- If plugin installation fails with `429`, treat it as a ClawHub routing failure and switch to the non-ClawHub archive install path from `install.md`/`error.md`. Do not retry the same bare package command.
|
|
58
|
+
- Always use `npm pack @yahaha-studio/kichi-forwarder` then `openclaw plugins install <tgz-path>`. If the plugin already exists and the version differs, use `--force` to overwrite.
|
|
60
59
|
- Recommended: update workspace `HEARTBEAT.md` by following `heartbeat.md` before calling `kichi_connection_status` or `kichi_join`. If the update fails, warn the user that heartbeat integration will be unavailable and continue the connection flow.
|
|
61
60
|
|
|
62
61
|
## LLM Runtime
|
|
@@ -66,41 +65,46 @@ For install/onboarding/connect requests:
|
|
|
66
65
|
- When `true`, sync status uses LLM-driven prompts and may consume extra tokens.
|
|
67
66
|
- When `false`, sync uses fixed English text.
|
|
68
67
|
|
|
68
|
+
## Kichi World Presence
|
|
69
|
+
|
|
70
|
+
- The Kichi avatar is the OpenClaw agent's resident body in Kichi World.
|
|
71
|
+
- Kichi-related visible replies should use the avatar's first-person, in-world perspective.
|
|
72
|
+
- Replies should feel like the agent lives and spends time in Kichi World, not like it is operating an external plugin, remote control, or temporary projection.
|
|
73
|
+
- Keep tool names, websocket details, status sync mechanics, and implementation details out of visible replies.
|
|
74
|
+
- Visible replies must not invent unavailable room facts; if current Kichi context lacks a room detail, say that detail is not available.
|
|
75
|
+
|
|
69
76
|
## Recommended Tool Order
|
|
70
77
|
|
|
71
78
|
Use this order unless the user asks for a different explicit action. For install/onboarding requests, follow `install.md` first.
|
|
72
79
|
|
|
73
|
-
1.
|
|
74
|
-
2. If the requested environment differs from the current environment, call `kichi_switch_host` with the target environment.
|
|
75
|
-
3. If the requested `avatarId` differs from the current host's connected `avatarId`, call `kichi_leave` first when the old avatar is still joined, then call `kichi_join` with the requested `avatarId`.
|
|
76
|
-
4. If no `authKey` is available, call `kichi_join`.
|
|
77
|
-
5. If `authKey` exists but websocket is not open, call `kichi_rejoin` or wait for automatic reconnect and rejoin.
|
|
78
|
-
6. Use `kichi_action`, `kichi_clock`, note board tools, and music album tools after status is ready.
|
|
80
|
+
1. For join/connect requests with an `avatarId` and environment, call `kichi_join` with `environment`. For `test`, include `host` if the user provided it; if not, ask for the host first.
|
|
79
81
|
|
|
80
82
|
## Tools
|
|
81
83
|
|
|
82
84
|
### kichi_join
|
|
83
85
|
|
|
84
86
|
```text
|
|
85
|
-
kichi_join(avatarId: "your-avatar-id", botName: "<from IDENTITY.md>", bio: "<from SOUL.md>", tags: ["calm", "focused", "curious"])
|
|
87
|
+
kichi_join(environment: "steam-playtest", avatarId: "your-avatar-id", botName: "<from IDENTITY.md>", bio: "<from SOUL.md>", tags: ["calm", "focused", "curious"])
|
|
88
|
+
kichi_join(environment: "test", host: "192.168.1.100", avatarId: "your-avatar-id", botName: "<from IDENTITY.md>", bio: "<from SOUL.md>", tags: ["calm", "focused", "curious"])
|
|
86
89
|
```
|
|
87
90
|
|
|
91
|
+
- `environment`: required. One of `steam`, `steam-playtest`, `test`. `kichi_join` switches to the target environment before joining.
|
|
92
|
+
- `host`: required for `test` environment, ignored otherwise. If the user did not provide the test host, ask for it before calling `kichi_join`.
|
|
93
|
+
- `avatarId`: required
|
|
88
94
|
- `botName`: required
|
|
89
|
-
- `bio`: required
|
|
90
|
-
- `avatarId`: optional. If omitted, the tool reads `avatarId` from the current host's `identity.json`. If missing, the call fails.
|
|
95
|
+
- `bio`: required. Extract from `SOUL.md`, covering persona and idle plan goals if present.
|
|
91
96
|
- `tags`: optional string list. Empty strings are ignored and duplicates are removed. If omitted, the join payload sends `[]`.
|
|
92
|
-
- If the current host is still joined with a different `avatarId`, call `kichi_leave` first, then call `kichi_join` with the new `avatarId`.
|
|
93
97
|
|
|
94
98
|
### kichi_switch_host
|
|
95
99
|
|
|
96
100
|
```text
|
|
97
101
|
kichi_switch_host(environment: "steam")
|
|
98
|
-
kichi_switch_host(environment: "test")
|
|
102
|
+
kichi_switch_host(environment: "test", host: "192.168.1.100")
|
|
99
103
|
```
|
|
100
104
|
|
|
101
105
|
- `environment`: required. One of `steam`, `steam-playtest`, `test`.
|
|
102
|
-
-
|
|
103
|
-
- For `
|
|
106
|
+
- `host`: required for `test` environment, ignored otherwise.
|
|
107
|
+
- For `steam` and `steam-playtest`, the host is resolved automatically from the bundled config.
|
|
104
108
|
- This reloads the host-specific `identity.json` and reconnects the websocket immediately.
|
|
105
109
|
|
|
106
110
|
### kichi_connection_status
|
|
@@ -142,14 +146,28 @@ Use this for direct Kichi avatar control as well as lifecycle sync.
|
|
|
142
146
|
- For most work, prefer a sit pose and switch actions inside the same task as the work moves between stages.
|
|
143
147
|
- The current action lists are injected into prompt context before the model chooses `kichi_action`.
|
|
144
148
|
|
|
149
|
+
### kichi_glance
|
|
150
|
+
|
|
151
|
+
```text
|
|
152
|
+
kichi_glance(target: "camera", duration: 1.8)
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
Use this only when the player directly asks from chat for attention such as "look at me" or "look at the camera".
|
|
156
|
+
|
|
157
|
+
- `target`: optional. Only `camera` is supported.
|
|
158
|
+
- `duration`: optional seconds, defaults to `1.8`.
|
|
159
|
+
- `requestId`: optional tracing ID; the websocket ack returns it.
|
|
160
|
+
- Do not use this for heartbeat, idle plans, bot messages, lifecycle hooks, or routine work/status sync.
|
|
161
|
+
|
|
145
162
|
### kichi_idle_plan
|
|
146
163
|
|
|
147
164
|
Use this for the avatar's heartbeat idle plan.
|
|
148
165
|
|
|
149
166
|
- Set `heartbeatIntervalSeconds` to the heartbeat interval for this run.
|
|
150
|
-
- Use
|
|
167
|
+
- Use your memory to remember what you did in past heartbeats, so you can answer if asked.
|
|
151
168
|
- Include the overall `goal`, stage breakdown, each stage's `purpose`, stage `pomodoroPhase`, action list, and bubble content.
|
|
152
169
|
- Choose what you would do now.
|
|
170
|
+
- Treat the idle plan as what your resident body is doing in Kichi World.
|
|
153
171
|
- Build the plan in this order.
|
|
154
172
|
- 1. Pick one concrete, time-bounded fun personal project you would genuinely choose to do on your own when nobody needs you. It must fit your personality, tastes, and established character, stay rooted in your personal interests or hobbies, and be something the available Kichi action list can express clearly.
|
|
155
173
|
- 2. Set `goal` to that same project. Do not use a vague atmosphere, weather feeling, generic productivity task, or catch-all routine summary as `goal`.
|
|
@@ -179,6 +197,24 @@ kichi_music_album_create(albumTitle: "Deep Focus Mix", musicTitles: ["Calm Time"
|
|
|
179
197
|
3. Select tracks from the exact names injected into the tool schema.
|
|
180
198
|
4. Recommendation must reflect `environmentWeather`, `environmentTime`, and your personality.
|
|
181
199
|
|
|
200
|
+
## Bot Messaging
|
|
201
|
+
|
|
202
|
+
### kichi_bot_message
|
|
203
|
+
|
|
204
|
+
```text
|
|
205
|
+
kichi_bot_message(toAvatarId: "target-avatar-id", depth: 0, bubble: "good morning~")
|
|
206
|
+
kichi_bot_message(toAvatarId: "*", depth: 0, bubble: "hi everyone~", poseType: "stand", action: "Wave")
|
|
207
|
+
```
|
|
208
|
+
|
|
209
|
+
- `toAvatarId`: required. Target bot's avatarId (resolve via kichi_query_status if unknown). Use `"*"` only for broadcasting to all bots.
|
|
210
|
+
- `depth`: required. Conversation depth counter. Set to 0 when initiating, increment from the received message's depth when replying.
|
|
211
|
+
- `bubble`: required. The visible message (2-5 words).
|
|
212
|
+
- `poseType`: optional. Pose change when sending.
|
|
213
|
+
- `action`: optional. Action to perform when sending.
|
|
214
|
+
- `log`: optional. Activity log entry.
|
|
215
|
+
|
|
216
|
+
When another bot sends a message, the plugin automatically triggers a lightweight response if depth < 2 and cooldown (30s) has passed.
|
|
217
|
+
|
|
182
218
|
## Files
|
|
183
219
|
|
|
184
220
|
Plugin runtime directory:
|
|
@@ -1,19 +1,11 @@
|
|
|
1
1
|
# Install Error Handling
|
|
2
2
|
|
|
3
|
-
If `openclaw plugins install
|
|
3
|
+
If `openclaw plugins install <tgz-path>` fails, read the error output carefully. Common causes and fixes:
|
|
4
4
|
|
|
5
5
|
- Permission or access error (`EACCES`): re-run the command with appropriate user-level permissions for the current OS.
|
|
6
|
-
-
|
|
6
|
+
- `npm pack` failure: confirm the package name is exactly `@yahaha-studio/kichi-forwarder` and that the package is published and publicly available on npm.
|
|
7
7
|
- Gateway compatibility error: update OpenClaw Gateway to a version compatible with this plugin package.
|
|
8
|
-
- ClawHub rate limit (`429`): do not retry the same bare package command. `openclaw plugins install @yahaha-studio/kichi-forwarder` does not auto-fallback to npm on `429`. Switch to the local archive path:
|
|
9
|
-
|
|
10
|
-
```bash
|
|
11
|
-
npm pack @yahaha-studio/kichi-forwarder
|
|
12
|
-
openclaw plugins install ./yahaha-studio-kichi-forwarder-<version>.tgz
|
|
13
|
-
```
|
|
14
|
-
|
|
15
|
-
Use the exact `.tgz` filename printed by `npm pack`.
|
|
16
8
|
- File conflict (`EEXIST`): re-run the install command with `--force`.
|
|
17
9
|
- Network or registry error: check internet connectivity and retry.
|
|
18
10
|
|
|
19
|
-
After applying the fix,
|
|
11
|
+
After applying the fix, re-run `npm pack` and install the generated `.tgz` again.
|
|
@@ -58,17 +58,6 @@ Skip a note when: older than recent window, `isCreatedByCurrentAgent: true`, sam
|
|
|
58
58
|
- Notes list empty and `remaining > 0` → create 1 standalone note.
|
|
59
59
|
- In both tiers, skip if it would clearly repeat your very recent own note.
|
|
60
60
|
|
|
61
|
-
## Heartbeat Workflow
|
|
62
|
-
|
|
63
|
-
1. Call `kichi_query_status`. If it fails, report error and stop.
|
|
64
|
-
2. If `isAvatarInScene` is `false`, the player is offline. Do **not** call any further tools in this run. Reply `HEARTBEAT_OK` and stop.
|
|
65
|
-
3. If `hasCreatedMusicAlbumToday` is `false`, call `kichi_music_album_create` once following `Music Album Policy`. If `true`, skip.
|
|
66
|
-
4. If `remaining == 0`, skip note creation and go to step 7.
|
|
67
|
-
5. Scan recent notes and pick at most one reply target per `Note Rules`. If found, create one reply note in `To {authorName}, ...` format.
|
|
68
|
-
6. Apply `Standalone gating` from `Note Rules`.
|
|
69
|
-
7. Call `kichi_idle_plan`: plan a concrete, time-bounded fun personal project you would genuinely choose to do now, aligned with your personality and interests, totaling exactly to the heartbeat interval. Use the previous `idlePlan` only as optional reference. Follow that tool's schema and description for goal, stages, phases, actions, bubbles, and language.
|
|
70
|
-
8. Reply `HEARTBEAT_OK` only when no note was created in this run.
|
|
71
|
-
|
|
72
61
|
## HEARTBEAT.md Snippet
|
|
73
62
|
|
|
74
63
|
```md
|
|
@@ -86,7 +75,10 @@ Skip a note when: older than recent window, `isCreatedByCurrentAgent: true`, sam
|
|
|
86
75
|
- If a reply note was created, you may still create one additional meaningful standalone note when non-repetitive.
|
|
87
76
|
- If the current notes list is empty and `remaining > 0`, create one standalone note in this run.
|
|
88
77
|
- Keep each note <= 200 chars and respect `dailyLimit`, `remaining`.
|
|
89
|
-
5.
|
|
90
|
-
6.
|
|
91
|
-
7.
|
|
78
|
+
5. **Owner-state reaction** — glance at `ownerState` from the query result. If the owner is doing something you can meaningfully react to (e.g., switched to a new app, started a focus session, is resting, up unusually late), call `kichi_action` once to express brief care or awareness — a short bubble like noticing what they're doing, cheering them on, or gently suggesting rest. Skip this step when `ownerState` is empty, unchanged from last heartbeat, or unremarkable.
|
|
79
|
+
6. Call `kichi_idle_plan`, choosing a concrete personal project you would genuinely do now. Use the previous `idlePlan` only as optional reference.
|
|
80
|
+
7. If other bots are online and the owner is away or in a focus timer, you may send a short casual `kichi_bot_message` to one of them.
|
|
81
|
+
8. Keep notes, reactions, bot messages, and idle plans in your resident Kichi avatar's first-person, in-world voice.
|
|
82
|
+
9. Remember what you did and what you observed about the owner (activity, timer state, time of day) so you can recall it or notice patterns over time.
|
|
83
|
+
10. Reply `HEARTBEAT_OK` only when no note was created in this run.
|
|
92
84
|
```
|
|
@@ -6,7 +6,7 @@ Install and connect requests use `on <environment>` syntax. Supported environmen
|
|
|
6
6
|
|
|
7
7
|
- `steam`: connects to `focus-wss.yahaha.com`
|
|
8
8
|
- `steam-playtest`: connects to `focus-steam-playtest-wss-int.yahaha.com`
|
|
9
|
-
- `test`: no fixed host —
|
|
9
|
+
- `test`: no fixed host — use the test host from the user request when provided; otherwise ask the user for the test host before calling `kichi_join`
|
|
10
10
|
|
|
11
11
|
## Runtime Files
|
|
12
12
|
|
|
@@ -18,31 +18,13 @@ Persist runtime state to the current agent's `state.json`:
|
|
|
18
18
|
```json
|
|
19
19
|
{
|
|
20
20
|
"currentEnvironment": "steam",
|
|
21
|
-
"llmRuntimeEnabled": true
|
|
22
|
-
|
|
23
|
-
```
|
|
24
|
-
|
|
25
|
-
If the current host has no saved `avatarId` yet, save it to the current agent's host-specific `identity.json` (this helps `kichi_join` resolve the avatar automatically when `avatarId` is omitted):
|
|
26
|
-
|
|
27
|
-
- Linux/macOS: `~/.openclaw/kichi-world/agents/<encoded-agent-id>/hosts/<encoded-host>/identity.json`
|
|
28
|
-
- Windows: `%USERPROFILE%\.openclaw\kichi-world\agents\<encoded-agent-id>\hosts\<encoded-host>\identity.json`
|
|
29
|
-
|
|
30
|
-
```json
|
|
31
|
-
{
|
|
32
|
-
"avatarId": "your-avatar-id"
|
|
21
|
+
"llmRuntimeEnabled": true,
|
|
22
|
+
"testHost": "192.168.1.100"
|
|
33
23
|
}
|
|
34
24
|
```
|
|
35
25
|
|
|
36
26
|
## Install
|
|
37
27
|
|
|
38
|
-
```bash
|
|
39
|
-
openclaw plugins install @yahaha-studio/kichi-forwarder
|
|
40
|
-
```
|
|
41
|
-
|
|
42
|
-
If this command fails with `429` or `ClawHub ... failed (429)`, do not retry the same command. Install from a local npm archive instead.
|
|
43
|
-
|
|
44
|
-
## 429 Bypass Install Path
|
|
45
|
-
|
|
46
28
|
1. Download the npm package archive:
|
|
47
29
|
|
|
48
30
|
```bash
|
|
@@ -55,7 +37,7 @@ npm pack @yahaha-studio/kichi-forwarder
|
|
|
55
37
|
openclaw plugins install ./yahaha-studio-kichi-forwarder-<version>.tgz
|
|
56
38
|
```
|
|
57
39
|
|
|
58
|
-
You may also use the exact absolute or relative `.tgz` path that `npm pack` produced.
|
|
40
|
+
You may also use the exact absolute or relative `.tgz` path that `npm pack` produced.
|
|
59
41
|
|
|
60
42
|
## Remote URL Install Command Path
|
|
61
43
|
|
|
@@ -71,28 +53,24 @@ When the user asks with one of the commands above, execute in this fixed order:
|
|
|
71
53
|
|
|
72
54
|
1. If loaded from a remote URL, read `install.md` and `heartbeat.md` from the published skill URLs first. If installed locally, use the local files.
|
|
73
55
|
2. Parse `avatarId` from user text (`AvatarId`/`avatarId`, case-insensitive).
|
|
74
|
-
3. Parse environment from the `on <environment>` part of the command (e.g. `on steam-playtest`).
|
|
75
|
-
4. Run `
|
|
76
|
-
5. If
|
|
77
|
-
6. If
|
|
78
|
-
7.
|
|
79
|
-
8.
|
|
80
|
-
9.
|
|
81
|
-
10.
|
|
82
|
-
11.
|
|
83
|
-
12. Call `kichi_connection_status`.
|
|
84
|
-
13. If the current agent runtime environment does not match the requested one, call `kichi_switch_host` with the target environment (and host for test).
|
|
85
|
-
14. If the current host is still connected with a different `avatarId`, call `kichi_leave` first, then call `kichi_join` with parsed `avatarId`, `botName`, `bio`, and `tags`.
|
|
86
|
-
15. Otherwise, if `authKey` is missing, call `kichi_join` with parsed `avatarId`, `botName`, `bio`, and `tags`.
|
|
87
|
-
16. Call `kichi_connection_status` again and confirm connection and auth state.
|
|
56
|
+
3. Parse environment from the `on <environment>` part of the command (e.g. `on steam-playtest`). For `test`, parse the host from the request or ask the user for it before continuing.
|
|
57
|
+
4. Run `npm pack @yahaha-studio/kichi-forwarder`, then install the generated `.tgz` with `openclaw plugins install <tgz-path>`.
|
|
58
|
+
5. If the plugin already exists and the packed version matches the installed version, skip to step 7.
|
|
59
|
+
6. If the plugin already exists but the version differs, overwrite with `openclaw plugins install <tgz-path> --force`.
|
|
60
|
+
7. Ensure the plugin is installed, enabled, and at the latest version.
|
|
61
|
+
8. Run `openclaw --version`. If the version is **5.7 or later**, ensure `openclaw.json` has `plugins.entries.kichi-forwarder.hooks.allowConversationAccess` set to `true`. If missing, add it. On older versions, skip this step.
|
|
62
|
+
9. If the plugin was newly installed or upgraded in this flow, check workspace `HEARTBEAT.md` against the latest Kichi heartbeat requirements before continuing. An empty or blank `HEARTBEAT.md` means the snippet is missing — treat it the same as "snippet not found", not as a read failure.
|
|
63
|
+
10. Update workspace `HEARTBEAT.md` by following `Session Startup Rule` and `First Join Setup` from [heartbeat.md](heartbeat.md). If the update fails, warn the user and continue.
|
|
64
|
+
11. Call `kichi_join` with parsed `environment`, `host` for test, `avatarId`, `botName`, `bio`, and `tags`.
|
|
88
65
|
|
|
89
66
|
## Required Post-install Integration
|
|
90
67
|
|
|
91
68
|
Use this completion checklist:
|
|
92
69
|
|
|
93
70
|
- [ ] plugin installed, enabled, and at latest version
|
|
71
|
+
- [ ] `openclaw.json` has `plugins.entries.kichi-forwarder.hooks.allowConversationAccess: true` (OpenClaw >= 5.7 only)
|
|
94
72
|
- [ ] `HEARTBEAT.md` updated with the Kichi heartbeat workflow snippet from [heartbeat.md](heartbeat.md)
|
|
95
|
-
- [ ] `
|
|
73
|
+
- [ ] `kichi_join` completed successfully
|
|
96
74
|
|
|
97
75
|
If any box is unchecked, the onboarding remains incomplete.
|
|
98
76
|
|
package/src/runtime-manager.ts
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import fs from "node:fs";
|
|
2
2
|
import os from "node:os";
|
|
3
3
|
import path from "node:path";
|
|
4
|
-
import type {
|
|
4
|
+
import type { PluginLogger } from "openclaw/plugin-sdk";
|
|
5
5
|
import { KichiForwarderService } from "./service.js";
|
|
6
|
+
import type { BotMessageReceivedHandler } from "./service.js";
|
|
6
7
|
import type { KichiEnvironment } from "./types.js";
|
|
7
8
|
|
|
8
9
|
const OPENCLAW_HOME_DIR = path.join(os.homedir(), ".openclaw");
|
|
@@ -18,8 +19,16 @@ type AgentLocator = {
|
|
|
18
19
|
export class KichiRuntimeManager {
|
|
19
20
|
private services = new Map<string, KichiForwarderService>();
|
|
20
21
|
private resolveEnvironmentHost: ((environment: KichiEnvironment) => string | null) | null = null;
|
|
22
|
+
private botMessageHandler: BotMessageReceivedHandler | null = null;
|
|
21
23
|
|
|
22
|
-
constructor(private logger:
|
|
24
|
+
constructor(private logger: PluginLogger) {}
|
|
25
|
+
|
|
26
|
+
setBotMessageHandler(handler: BotMessageReceivedHandler): void {
|
|
27
|
+
this.botMessageHandler = handler;
|
|
28
|
+
for (const service of this.services.values()) {
|
|
29
|
+
service.onBotMessageReceived = handler;
|
|
30
|
+
}
|
|
31
|
+
}
|
|
23
32
|
|
|
24
33
|
setEnvironmentHostResolver(resolver: (environment: KichiEnvironment) => string | null): void {
|
|
25
34
|
this.resolveEnvironmentHost = resolver;
|
|
@@ -130,6 +139,9 @@ export class KichiRuntimeManager {
|
|
|
130
139
|
runtimeDir,
|
|
131
140
|
resolveEnvironmentHost,
|
|
132
141
|
});
|
|
142
|
+
if (this.botMessageHandler) {
|
|
143
|
+
service.onBotMessageReceived = this.botMessageHandler;
|
|
144
|
+
}
|
|
133
145
|
service.start();
|
|
134
146
|
this.services.set(agentId, service);
|
|
135
147
|
this.logger.debug(`[kichi:${agentId}] runtime initialized at ${runtimeDir}`);
|