@yahaha-studio/kichi-forwarder 0.0.1-alpha.55 → 0.1.0-beta.1
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 +72 -0
- package/assets/kichi-cover.jpg +0 -0
- package/index.ts +5 -9
- package/openclaw.plugin.json +2 -2
- package/package.json +40 -24
- package/skills/kichi-forwarder/SKILL.md +11 -12
- package/skills/kichi-forwarder/references/error.md +4 -3
- package/skills/kichi-forwarder/references/install.md +6 -15
- package/src/config.ts +1 -3
- package/src/service.ts +41 -17
- package/src/types.ts +6 -7
- package/.claude/settings.local.json +0 -26
- package/.github/workflows/static.yml +0 -43
package/README.md
ADDED
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
# Kichi Forwarder
|
|
2
|
+
|
|
3
|
+

|
|
4
|
+
|
|
5
|
+
Kichi Forwarder brings your OpenClaw companion into Kichi.
|
|
6
|
+
|
|
7
|
+
It can show what your companion is doing, leave notes for you in Kichi, and recommend music while you work together.
|
|
8
|
+
|
|
9
|
+
> The world of Kichi opens for playtest soon.
|
|
10
|
+
|
|
11
|
+
## Highlights
|
|
12
|
+
|
|
13
|
+
- Bring your OpenClaw companion into Kichi
|
|
14
|
+
- Keep its visible state in sync while it works
|
|
15
|
+
- Let it leave notes for you in Kichi
|
|
16
|
+
- Let it recommend music in Kichi
|
|
17
|
+
|
|
18
|
+
## Install
|
|
19
|
+
|
|
20
|
+
Install from ClawHub:
|
|
21
|
+
|
|
22
|
+
```bash
|
|
23
|
+
openclaw plugins install clawhub:@yahaha-studio/kichi-forwarder
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
Install with the bare package name:
|
|
27
|
+
|
|
28
|
+
```bash
|
|
29
|
+
openclaw plugins install @yahaha-studio/kichi-forwarder
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
For bare package installs, OpenClaw tries ClawHub first and falls back to npm automatically.
|
|
33
|
+
|
|
34
|
+
## Get Started in Kichi
|
|
35
|
+
|
|
36
|
+
Kichi provides the install command and the connection details you need to connect a companion.
|
|
37
|
+
|
|
38
|
+
Get the `host` and `avatarId` from Kichi, then use them with `kichi_switch_host` and `kichi_join`.
|
|
39
|
+
|
|
40
|
+
## What Your Companion Can Do
|
|
41
|
+
|
|
42
|
+
- Connect to your chosen Kichi host and stay in sync while it works
|
|
43
|
+
- Show activity in Kichi with actions, bubbles, logs, and timers
|
|
44
|
+
- Leave notes for you on Kichi note boards
|
|
45
|
+
- Recommend music in Kichi as part of your daily routine
|
|
46
|
+
- React based on your current Kichi status before posting notes or music
|
|
47
|
+
|
|
48
|
+
## Quick Setup
|
|
49
|
+
|
|
50
|
+
1. Install the plugin.
|
|
51
|
+
2. Start OpenClaw with the plugin enabled.
|
|
52
|
+
3. Use `kichi_switch_host` and `kichi_join` to connect your companion to Kichi.
|
|
53
|
+
4. Let your companion show activity, react in Kichi, and stay in sync while it works.
|
|
54
|
+
5. Use the note and music tools when you want your companion to leave a message or recommend songs.
|
|
55
|
+
|
|
56
|
+
## Runtime State
|
|
57
|
+
|
|
58
|
+
The plugin stores runtime state in the OpenClaw user directory:
|
|
59
|
+
|
|
60
|
+
- Windows: `%USERPROFILE%\.openclaw\kichi-world\`
|
|
61
|
+
- Linux/macOS: `~/.openclaw/kichi-world/`
|
|
62
|
+
|
|
63
|
+
Important files:
|
|
64
|
+
|
|
65
|
+
- `state.json` stores the current host and `llmRuntimeEnabled`
|
|
66
|
+
- `hosts/<encoded-host>/identity.json` stores host-specific `avatarId` and `authKey`
|
|
67
|
+
|
|
68
|
+
## Notes
|
|
69
|
+
|
|
70
|
+
- This plugin runs inside OpenClaw and adds Kichi-specific companion behaviors.
|
|
71
|
+
- Host, `avatarId`, and `authKey` are managed through the plugin tool flow and local runtime state files.
|
|
72
|
+
- The plugin runs in-process with the OpenClaw Gateway, so install it only in environments you trust.
|
|
Binary file
|
package/index.ts
CHANGED
|
@@ -10,7 +10,6 @@ import type {
|
|
|
10
10
|
Album,
|
|
11
11
|
ClockAction,
|
|
12
12
|
ClockConfig,
|
|
13
|
-
KichiForwarderConfig,
|
|
14
13
|
KichiState,
|
|
15
14
|
KichiStaticConfig,
|
|
16
15
|
PomodoroPhase,
|
|
@@ -124,19 +123,18 @@ function normalizeStaticConfig(value: unknown): KichiStaticConfig {
|
|
|
124
123
|
function readState(): KichiState {
|
|
125
124
|
if (!fs.existsSync(STATE_PATH)) {
|
|
126
125
|
return {
|
|
127
|
-
currentHost: "focus.yahaha.com",
|
|
128
126
|
llmRuntimeEnabled: DEFAULT_LLM_RUNTIME_ENABLED,
|
|
129
127
|
};
|
|
130
128
|
}
|
|
131
129
|
const data = JSON.parse(fs.readFileSync(STATE_PATH, "utf-8")) as Partial<KichiState>;
|
|
132
|
-
if (typeof data.currentHost !== "string" || !data.currentHost.trim()) {
|
|
130
|
+
if (data.currentHost !== undefined && (typeof data.currentHost !== "string" || !data.currentHost.trim())) {
|
|
133
131
|
throw new Error(`Invalid currentHost in ${STATE_PATH}`);
|
|
134
132
|
}
|
|
135
133
|
if (typeof data.llmRuntimeEnabled !== "boolean") {
|
|
136
134
|
throw new Error(`Invalid llmRuntimeEnabled in ${STATE_PATH}`);
|
|
137
135
|
}
|
|
138
136
|
return {
|
|
139
|
-
currentHost: data.currentHost,
|
|
137
|
+
...(typeof data.currentHost === "string" ? { currentHost: data.currentHost } : {}),
|
|
140
138
|
llmRuntimeEnabled: data.llmRuntimeEnabled,
|
|
141
139
|
};
|
|
142
140
|
}
|
|
@@ -606,10 +604,8 @@ const plugin = {
|
|
|
606
604
|
api.registerService({
|
|
607
605
|
id: "kichi-forwarder",
|
|
608
606
|
start: (ctx) => {
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
) as KichiForwarderConfig;
|
|
612
|
-
service = new KichiForwarderService(cfg, api.logger);
|
|
607
|
+
parse(ctx.config.plugins?.entries?.["kichi-forwarder"]?.config);
|
|
608
|
+
service = new KichiForwarderService(api.logger);
|
|
613
609
|
return service.start();
|
|
614
610
|
},
|
|
615
611
|
stop: () => service?.stop(),
|
|
@@ -685,7 +681,7 @@ const plugin = {
|
|
|
685
681
|
properties: {
|
|
686
682
|
host: {
|
|
687
683
|
type: "string",
|
|
688
|
-
description: "Target Kichi host, for example
|
|
684
|
+
description: "Target Kichi host, for example your.kichi.host or 127.0.0.1",
|
|
689
685
|
},
|
|
690
686
|
},
|
|
691
687
|
required: ["host"],
|
package/openclaw.plugin.json
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"id": "kichi-forwarder",
|
|
3
3
|
"name": "Kichi Forwarder",
|
|
4
|
-
"description": "
|
|
5
|
-
"version": "0.0.1",
|
|
4
|
+
"description": "Native OpenClaw plugin for Kichi World with status sync, timers, notes, and music tools",
|
|
5
|
+
"version": "0.1.0-beta.1",
|
|
6
6
|
"author": "OpenClaw",
|
|
7
7
|
"skills": ["./skills/kichi-forwarder"],
|
|
8
8
|
"configSchema": {
|
package/package.json
CHANGED
|
@@ -1,24 +1,40 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "@yahaha-studio/kichi-forwarder",
|
|
3
|
-
"version": "0.0.1
|
|
4
|
-
"description": "
|
|
5
|
-
"type": "module",
|
|
6
|
-
"main": "index.ts",
|
|
7
|
-
"
|
|
8
|
-
"
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
"
|
|
14
|
-
"
|
|
15
|
-
|
|
16
|
-
"
|
|
17
|
-
"
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
"
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
1
|
+
{
|
|
2
|
+
"name": "@yahaha-studio/kichi-forwarder",
|
|
3
|
+
"version": "0.1.0-beta.1",
|
|
4
|
+
"description": "Native OpenClaw plugin for Kichi World with status sync, timers, notes, and music tools",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "index.ts",
|
|
7
|
+
"files": [
|
|
8
|
+
"README.md",
|
|
9
|
+
"assets/",
|
|
10
|
+
"config/",
|
|
11
|
+
"index.ts",
|
|
12
|
+
"openclaw.plugin.json",
|
|
13
|
+
"skills/",
|
|
14
|
+
"src/"
|
|
15
|
+
],
|
|
16
|
+
"openclaw": {
|
|
17
|
+
"extensions": [
|
|
18
|
+
"./index.ts"
|
|
19
|
+
],
|
|
20
|
+
"compat": {
|
|
21
|
+
"pluginApi": ">=2026.3.24",
|
|
22
|
+
"minGatewayVersion": "2026.3.24"
|
|
23
|
+
},
|
|
24
|
+
"build": {
|
|
25
|
+
"openclawVersion": "2026.3.24",
|
|
26
|
+
"pluginSdkVersion": "2026.3.24"
|
|
27
|
+
}
|
|
28
|
+
},
|
|
29
|
+
"publishConfig": {
|
|
30
|
+
"access": "public"
|
|
31
|
+
},
|
|
32
|
+
"dependencies": {
|
|
33
|
+
"ws": "^8.19.0"
|
|
34
|
+
},
|
|
35
|
+
"devDependencies": {
|
|
36
|
+
"@types/node": "^24.3.0",
|
|
37
|
+
"@types/ws": "^8.18.1",
|
|
38
|
+
"openclaw": "2026.3.24"
|
|
39
|
+
}
|
|
40
|
+
}
|
|
@@ -1,26 +1,25 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: kichi-forwarder
|
|
3
3
|
description: Use Kichi websocket tools for proactive task lifecycle sync (start/switch/milestone/end), activity updates, timer control, and note board workflows; prioritize explicit user Kichi requests and skip sync when the user opts out.
|
|
4
|
-
metadata: {"openclaw":{"skillKey":"kichi-forwarder","homepage":"https://github.com/
|
|
4
|
+
metadata: {"openclaw":{"skillKey":"kichi-forwarder","homepage":"https://github.com/Yahaha-Studio/kichi-forwarder"}}
|
|
5
5
|
---
|
|
6
6
|
|
|
7
7
|
# Kichi Forwarder
|
|
8
8
|
|
|
9
|
-
|
|
9
|
+
Kichi Forwarder provides websocket tools for connecting an OpenClaw agent to Kichi, syncing companion status, and handling Kichi notes, timers, and music workflows.
|
|
10
10
|
|
|
11
11
|
## Skill Files (Absolute URLs)
|
|
12
12
|
|
|
13
13
|
If this skill is loaded from a remote URL before local installation, use these files:
|
|
14
14
|
|
|
15
|
-
- `SKILL.md`: `https://
|
|
16
|
-
- `install.md`: `https://
|
|
17
|
-
- `error.md`: `https://
|
|
18
|
-
- `heartbeat.md`: `https://
|
|
15
|
+
- `SKILL.md`: `https://yahaha-studio.github.io/kichi-forwarder/SKILL.md`
|
|
16
|
+
- `install.md`: `https://yahaha-studio.github.io/kichi-forwarder/references/install.md`
|
|
17
|
+
- `error.md`: `https://yahaha-studio.github.io/kichi-forwarder/references/error.md`
|
|
18
|
+
- `heartbeat.md`: `https://yahaha-studio.github.io/kichi-forwarder/references/heartbeat.md`
|
|
19
19
|
|
|
20
20
|
## Host Rules
|
|
21
21
|
|
|
22
|
-
-
|
|
23
|
-
- If the user does not specify a host, use `focus.yahaha.com`.
|
|
22
|
+
- Install and connect requests include `host: <value>`.
|
|
24
23
|
|
|
25
24
|
## Runtime State
|
|
26
25
|
|
|
@@ -33,13 +32,13 @@ Runtime data lives under the user home directory:
|
|
|
33
32
|
|
|
34
33
|
When this skill is loaded from:
|
|
35
34
|
|
|
36
|
-
- `https://
|
|
35
|
+
- `https://yahaha-studio.github.io/kichi-forwarder/SKILL.md`
|
|
37
36
|
|
|
38
|
-
and the user asks to connect/install with `avatarId` and
|
|
37
|
+
and the user asks to connect/install with `avatarId` and `host`, do not invent a separate install flow in this file.
|
|
39
38
|
|
|
40
39
|
The install and join flow is defined only in:
|
|
41
40
|
|
|
42
|
-
- `https://
|
|
41
|
+
- `https://yahaha-studio.github.io/kichi-forwarder/references/install.md`
|
|
43
42
|
|
|
44
43
|
Read and follow that file before any tool call.
|
|
45
44
|
|
|
@@ -85,7 +84,7 @@ kichi_join(avatarId: "your-avatar-id", botName: "<from IDENTITY.md>", bio: "<fro
|
|
|
85
84
|
### kichi_switch_host
|
|
86
85
|
|
|
87
86
|
```text
|
|
88
|
-
kichi_switch_host(host: "
|
|
87
|
+
kichi_switch_host(host: "your.kichi.host")
|
|
89
88
|
```
|
|
90
89
|
|
|
91
90
|
- `host`: required
|
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
# Install Error Handling
|
|
2
2
|
|
|
3
|
-
If `openclaw plugins install
|
|
3
|
+
If `openclaw plugins install clawhub:@yahaha-studio/kichi-forwarder` 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
|
+
- Package resolution or visibility error: confirm the package name is exactly `@yahaha-studio/kichi-forwarder` and that the package is published and publicly available on ClawHub.
|
|
7
|
+
- Gateway compatibility error: update OpenClaw Gateway to a version compatible with this plugin package.
|
|
7
8
|
- File conflict (`EEXIST`): re-run the install command with `--force`.
|
|
8
9
|
- Network or registry error: check internet connectivity and retry.
|
|
9
10
|
|
|
10
|
-
After applying the fix, re-run `openclaw plugins install
|
|
11
|
+
After applying the fix, re-run `openclaw plugins install clawhub:@yahaha-studio/kichi-forwarder`.
|
|
@@ -1,9 +1,8 @@
|
|
|
1
|
-
# Install
|
|
1
|
+
# Install
|
|
2
2
|
|
|
3
3
|
## Host Rules
|
|
4
4
|
|
|
5
|
-
-
|
|
6
|
-
- If the user does not specify a host, use `focus.yahaha.com`.
|
|
5
|
+
- Install and connect requests include `host: <value>`.
|
|
7
6
|
|
|
8
7
|
## Runtime Files
|
|
9
8
|
|
|
@@ -14,7 +13,7 @@ Persist runtime state to `state.json`:
|
|
|
14
13
|
|
|
15
14
|
```json
|
|
16
15
|
{
|
|
17
|
-
"currentHost": "
|
|
16
|
+
"currentHost": "your.kichi.host",
|
|
18
17
|
"llmRuntimeEnabled": true
|
|
19
18
|
}
|
|
20
19
|
```
|
|
@@ -33,23 +32,15 @@ Save `avatarId` to the host-specific `identity.json` before using `kichi_join`:
|
|
|
33
32
|
## Install
|
|
34
33
|
|
|
35
34
|
```bash
|
|
36
|
-
openclaw plugins install
|
|
35
|
+
openclaw plugins install clawhub:@yahaha-studio/kichi-forwarder
|
|
37
36
|
```
|
|
38
37
|
|
|
39
38
|
## Remote URL Install Command Path (Non-skippable)
|
|
40
39
|
|
|
41
40
|
If the user asks:
|
|
42
41
|
|
|
43
|
-
- Default:
|
|
44
|
-
|
|
45
|
-
```text
|
|
46
|
-
Read https://xiaoxinshi001.github.io/yahaha_focus_forwarder_alpha/SKILL.md and connect me to Kichi World with avatarId: {avatarId}
|
|
47
|
-
```
|
|
48
|
-
|
|
49
|
-
- With explicit host:
|
|
50
|
-
|
|
51
42
|
```text
|
|
52
|
-
Read https://
|
|
43
|
+
Read https://yahaha-studio.github.io/kichi-forwarder/SKILL.md and connect me to Kichi World with avatarId: {avatarId} and host: {host}
|
|
53
44
|
```
|
|
54
45
|
|
|
55
46
|
## Command Execution Flow
|
|
@@ -59,7 +50,7 @@ When the user asks with one of the commands above, execute in this fixed order:
|
|
|
59
50
|
1. Read `install.md` and `heartbeat.md` from the published skill URLs before any tool call.
|
|
60
51
|
2. Parse `avatarId` from user text (`AvatarId`/`avatarId`, case-insensitive).
|
|
61
52
|
3. Resolve the host and write `state.json`.
|
|
62
|
-
4. Run `openclaw plugins install
|
|
53
|
+
4. Run `openclaw plugins install clawhub:@yahaha-studio/kichi-forwarder`.
|
|
63
54
|
5. Ensure the plugin is installed and enabled.
|
|
64
55
|
6. Update workspace `HEARTBEAT.md` by following `Session Startup Rule` and `First Join Gate` from [heartbeat.md](heartbeat.md).
|
|
65
56
|
7. If `HEARTBEAT.md` was not updated successfully, report setup as incomplete and stop immediately. Do not continue to `kichi_status` or `kichi_join`.
|
package/src/config.ts
CHANGED
|
@@ -1,8 +1,6 @@
|
|
|
1
1
|
import type { KichiForwarderConfig } from "./types.js";
|
|
2
2
|
|
|
3
|
-
const FIXED_CONFIG: KichiForwarderConfig = {
|
|
4
|
-
defaultHost: "focus.yahaha.com",
|
|
5
|
-
};
|
|
3
|
+
const FIXED_CONFIG: KichiForwarderConfig = {};
|
|
6
4
|
|
|
7
5
|
export function parse(_value: unknown): KichiForwarderConfig {
|
|
8
6
|
return FIXED_CONFIG;
|
package/src/service.ts
CHANGED
|
@@ -15,7 +15,6 @@ import type {
|
|
|
15
15
|
JoinAckPayload,
|
|
16
16
|
JoinPayload,
|
|
17
17
|
KichiConnectionStatus,
|
|
18
|
-
KichiForwarderConfig,
|
|
19
18
|
KichiIdentity,
|
|
20
19
|
KichiState,
|
|
21
20
|
LeaveAckPayload,
|
|
@@ -56,7 +55,7 @@ export class KichiForwarderService {
|
|
|
56
55
|
private stopped = false;
|
|
57
56
|
private reconnectTimeout: NodeJS.Timeout | null = null;
|
|
58
57
|
private identity: KichiIdentity | null = null;
|
|
59
|
-
private host: string;
|
|
58
|
+
private host: string | null = null;
|
|
60
59
|
private joinResolve: ((result: JoinResult) => void) | null = null;
|
|
61
60
|
private pendingRequests = new Map<
|
|
62
61
|
string,
|
|
@@ -68,15 +67,17 @@ export class KichiForwarderService {
|
|
|
68
67
|
}
|
|
69
68
|
>();
|
|
70
69
|
|
|
71
|
-
constructor(private
|
|
72
|
-
this.host = config.defaultHost;
|
|
73
|
-
}
|
|
70
|
+
constructor(private logger: Logger) {}
|
|
74
71
|
|
|
75
72
|
async start(): Promise<void> {
|
|
76
73
|
this.host = this.loadCurrentHost();
|
|
77
|
-
this.identity = this.loadIdentity();
|
|
74
|
+
this.identity = this.host ? this.loadIdentity() : null;
|
|
78
75
|
this.stopped = false;
|
|
79
|
-
this.
|
|
76
|
+
if (this.host) {
|
|
77
|
+
this.connect();
|
|
78
|
+
return;
|
|
79
|
+
}
|
|
80
|
+
this.logger.info("Kichi host is not configured yet; waiting for kichi_switch_host");
|
|
80
81
|
}
|
|
81
82
|
|
|
82
83
|
async stop(): Promise<void> {
|
|
@@ -107,6 +108,9 @@ export class KichiForwarderService {
|
|
|
107
108
|
bio: string,
|
|
108
109
|
tags: string[],
|
|
109
110
|
): Promise<JoinResult> {
|
|
111
|
+
if (!this.host) {
|
|
112
|
+
return { success: false, error: "No Kichi host configured. Run kichi_switch_host first." };
|
|
113
|
+
}
|
|
110
114
|
return new Promise((resolve) => {
|
|
111
115
|
this.identity = { avatarId };
|
|
112
116
|
this.saveIdentity();
|
|
@@ -251,14 +255,20 @@ export class KichiForwarderService {
|
|
|
251
255
|
hasValidIdentity(): boolean { return !!this.identity?.avatarId && !!this.identity?.authKey; }
|
|
252
256
|
|
|
253
257
|
getCurrentHost(): string {
|
|
254
|
-
return this.host;
|
|
258
|
+
return this.host ?? "";
|
|
255
259
|
}
|
|
256
260
|
|
|
257
261
|
getIdentityPath(): string {
|
|
262
|
+
if (!this.host) {
|
|
263
|
+
return "";
|
|
264
|
+
}
|
|
258
265
|
return path.join(this.getIdentityDir(), "identity.json");
|
|
259
266
|
}
|
|
260
267
|
|
|
261
268
|
readSavedAvatarId(): string | null {
|
|
269
|
+
if (!this.host) {
|
|
270
|
+
return null;
|
|
271
|
+
}
|
|
262
272
|
return this.loadIdentity()?.avatarId ?? null;
|
|
263
273
|
}
|
|
264
274
|
|
|
@@ -267,7 +277,9 @@ export class KichiForwarderService {
|
|
|
267
277
|
return {
|
|
268
278
|
accepted: false,
|
|
269
279
|
mode: "unavailable",
|
|
270
|
-
message:
|
|
280
|
+
message: this.host
|
|
281
|
+
? "Missing authKey. Run kichi_join first."
|
|
282
|
+
: "No Kichi host configured. Run kichi_switch_host first.",
|
|
271
283
|
};
|
|
272
284
|
}
|
|
273
285
|
|
|
@@ -306,10 +318,14 @@ export class KichiForwarderService {
|
|
|
306
318
|
}
|
|
307
319
|
|
|
308
320
|
getConnectionStatus(): KichiConnectionStatus {
|
|
321
|
+
const host = this.host ?? undefined;
|
|
309
322
|
return {
|
|
310
|
-
host
|
|
311
|
-
|
|
312
|
-
|
|
323
|
+
...(host ? {
|
|
324
|
+
host,
|
|
325
|
+
wsUrl: this.getWsUrl(),
|
|
326
|
+
identityPath: this.getIdentityPath(),
|
|
327
|
+
} : {}),
|
|
328
|
+
hostConfigured: !!host,
|
|
313
329
|
connected: this.isConnected(),
|
|
314
330
|
websocketState: this.getWebsocketState(),
|
|
315
331
|
hasIdentity: !!this.identity?.avatarId,
|
|
@@ -355,7 +371,7 @@ export class KichiForwarderService {
|
|
|
355
371
|
}
|
|
356
372
|
|
|
357
373
|
private connect(): void {
|
|
358
|
-
if (this.stopped) return;
|
|
374
|
+
if (this.stopped || !this.host) return;
|
|
359
375
|
|
|
360
376
|
const wsUrl = this.getWsUrl();
|
|
361
377
|
const ws = new WebSocket(wsUrl);
|
|
@@ -523,6 +539,9 @@ export class KichiForwarderService {
|
|
|
523
539
|
}
|
|
524
540
|
|
|
525
541
|
private loadIdentity(): KichiIdentity | null {
|
|
542
|
+
if (!this.host) {
|
|
543
|
+
return null;
|
|
544
|
+
}
|
|
526
545
|
try {
|
|
527
546
|
const identityPath = this.getIdentityPath();
|
|
528
547
|
if (!fs.existsSync(identityPath)) return null;
|
|
@@ -542,7 +561,7 @@ export class KichiForwarderService {
|
|
|
542
561
|
}
|
|
543
562
|
|
|
544
563
|
private saveIdentity(): void {
|
|
545
|
-
if (!this.identity?.avatarId) return;
|
|
564
|
+
if (!this.identity?.avatarId || !this.host) return;
|
|
546
565
|
try {
|
|
547
566
|
const identityDir = this.getIdentityDir();
|
|
548
567
|
const identityPath = this.getIdentityPath();
|
|
@@ -590,10 +609,16 @@ export class KichiForwarderService {
|
|
|
590
609
|
}
|
|
591
610
|
|
|
592
611
|
private getIdentityDir(): string {
|
|
612
|
+
if (!this.host) {
|
|
613
|
+
throw new Error("No Kichi host configured");
|
|
614
|
+
}
|
|
593
615
|
return path.join(HOSTS_DIR, encodeURIComponent(this.host));
|
|
594
616
|
}
|
|
595
617
|
|
|
596
618
|
private getWsUrl(): string {
|
|
619
|
+
if (!this.host) {
|
|
620
|
+
throw new Error("No Kichi host configured");
|
|
621
|
+
}
|
|
597
622
|
const protocol = this.isPlainIpHost(this.host) || this.host === "localhost" ? "ws" : "wss";
|
|
598
623
|
return `${protocol}://${this.host}:48870/ws/openclaw`;
|
|
599
624
|
}
|
|
@@ -604,11 +629,10 @@ export class KichiForwarderService {
|
|
|
604
629
|
|| /^[0-9a-f:]+$/i.test(host);
|
|
605
630
|
}
|
|
606
631
|
|
|
607
|
-
private loadCurrentHost(): string {
|
|
632
|
+
private loadCurrentHost(): string | null {
|
|
608
633
|
try {
|
|
609
634
|
if (!fs.existsSync(STATE_PATH)) {
|
|
610
|
-
|
|
611
|
-
return this.config.defaultHost;
|
|
635
|
+
return null;
|
|
612
636
|
}
|
|
613
637
|
const data = JSON.parse(fs.readFileSync(STATE_PATH, "utf-8")) as { currentHost?: unknown };
|
|
614
638
|
if (typeof data.currentHost === "string" && data.currentHost.trim()) {
|
package/src/types.ts
CHANGED
|
@@ -1,6 +1,4 @@
|
|
|
1
|
-
export type KichiForwarderConfig =
|
|
2
|
-
defaultHost: string;
|
|
3
|
-
};
|
|
1
|
+
export type KichiForwarderConfig = Record<string, never>;
|
|
4
2
|
|
|
5
3
|
export type PoseType = "stand" | "sit" | "lay" | "floor";
|
|
6
4
|
|
|
@@ -29,7 +27,7 @@ export type Album = {
|
|
|
29
27
|
};
|
|
30
28
|
|
|
31
29
|
export type KichiState = {
|
|
32
|
-
currentHost
|
|
30
|
+
currentHost?: string;
|
|
33
31
|
llmRuntimeEnabled: boolean;
|
|
34
32
|
};
|
|
35
33
|
|
|
@@ -39,9 +37,10 @@ export type KichiIdentity = {
|
|
|
39
37
|
};
|
|
40
38
|
|
|
41
39
|
export type KichiConnectionStatus = {
|
|
42
|
-
host
|
|
43
|
-
wsUrl
|
|
44
|
-
identityPath
|
|
40
|
+
host?: string;
|
|
41
|
+
wsUrl?: string;
|
|
42
|
+
identityPath?: string;
|
|
43
|
+
hostConfigured: boolean;
|
|
45
44
|
connected: boolean;
|
|
46
45
|
websocketState: "idle" | "connecting" | "open" | "closing" | "closed";
|
|
47
46
|
hasIdentity: boolean;
|
|
@@ -1,26 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"permissions": {
|
|
3
|
-
"allow": [
|
|
4
|
-
"WebSearch",
|
|
5
|
-
"WebFetch(domain:raw.githubusercontent.com)",
|
|
6
|
-
"WebFetch(domain:github.com)",
|
|
7
|
-
"Bash(curl:*)",
|
|
8
|
-
"Bash(python -c:*)",
|
|
9
|
-
"Bash(chcp 65001:*)",
|
|
10
|
-
"Bash(set:*)",
|
|
11
|
-
"Bash(python -u -c:*)",
|
|
12
|
-
"Bash(gh api:*)",
|
|
13
|
-
"WebFetch(domain:docs.openclaw.ai)",
|
|
14
|
-
"WebFetch(domain:openclawskill.cc)",
|
|
15
|
-
"WebFetch(domain:yingtu.ai)",
|
|
16
|
-
"WebFetch(domain:lumadock.com)",
|
|
17
|
-
"WebFetch(domain:dev.to)",
|
|
18
|
-
"WebFetch(domain:www.learnclawdbot.org)",
|
|
19
|
-
"Bash(gh auth status:*)",
|
|
20
|
-
"WebFetch(domain:playbooks.com)",
|
|
21
|
-
"WebFetch(domain:smithery.ai)",
|
|
22
|
-
"WebFetch(domain:lobehub.com)",
|
|
23
|
-
"WebFetch(domain:snyk.io)"
|
|
24
|
-
]
|
|
25
|
-
}
|
|
26
|
-
}
|
|
@@ -1,43 +0,0 @@
|
|
|
1
|
-
# Simple workflow for deploying static content to GitHub Pages
|
|
2
|
-
name: Deploy static content to Pages
|
|
3
|
-
|
|
4
|
-
on:
|
|
5
|
-
# Runs on pushes targeting the default branch
|
|
6
|
-
push:
|
|
7
|
-
branches: ["main"]
|
|
8
|
-
|
|
9
|
-
# Allows you to run this workflow manually from the Actions tab
|
|
10
|
-
workflow_dispatch:
|
|
11
|
-
|
|
12
|
-
# Sets permissions of the GITHUB_TOKEN to allow deployment to GitHub Pages
|
|
13
|
-
permissions:
|
|
14
|
-
contents: read
|
|
15
|
-
pages: write
|
|
16
|
-
id-token: write
|
|
17
|
-
|
|
18
|
-
# Allow only one concurrent deployment, skipping runs queued between the run in-progress and latest queued.
|
|
19
|
-
# However, do NOT cancel in-progress runs as we want to allow these production deployments to complete.
|
|
20
|
-
concurrency:
|
|
21
|
-
group: "pages"
|
|
22
|
-
cancel-in-progress: false
|
|
23
|
-
|
|
24
|
-
jobs:
|
|
25
|
-
# Single deploy job since we're just deploying
|
|
26
|
-
deploy:
|
|
27
|
-
environment:
|
|
28
|
-
name: github-pages
|
|
29
|
-
url: ${{ steps.deployment.outputs.page_url }}
|
|
30
|
-
runs-on: ubuntu-latest
|
|
31
|
-
steps:
|
|
32
|
-
- name: Checkout
|
|
33
|
-
uses: actions/checkout@v4
|
|
34
|
-
- name: Setup Pages
|
|
35
|
-
uses: actions/configure-pages@v5
|
|
36
|
-
- name: Upload artifact
|
|
37
|
-
uses: actions/upload-pages-artifact@v3
|
|
38
|
-
with:
|
|
39
|
-
# Upload entire repository
|
|
40
|
-
path: 'skills/kichi-forwarder'
|
|
41
|
-
- name: Deploy to GitHub Pages
|
|
42
|
-
id: deployment
|
|
43
|
-
uses: actions/deploy-pages@v4
|