@yahaha-studio/kichi-forwarder 0.1.2-beta.2 → 0.1.2-beta.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,4 @@
1
+ const FIXED_CONFIG = {};
2
+ export function parse(_value) {
3
+ return FIXED_CONFIG;
4
+ }
@@ -0,0 +1,121 @@
1
+ import fs from "node:fs";
2
+ import os from "node:os";
3
+ import path from "node:path";
4
+ import { KichiForwarderService } from "./service.js";
5
+ const OPENCLAW_HOME_DIR = path.join(os.homedir(), ".openclaw");
6
+ const KICHI_WORLD_ROOT_DIR = path.join(OPENCLAW_HOME_DIR, "kichi-world");
7
+ const CANONICAL_AGENT_ROOT_DIR = path.join(KICHI_WORLD_ROOT_DIR, "agents");
8
+ export class KichiRuntimeManager {
9
+ logger;
10
+ services = new Map();
11
+ resolveEnvironmentHost = null;
12
+ botMessageHandler = null;
13
+ constructor(logger) {
14
+ this.logger = logger;
15
+ }
16
+ setBotMessageHandler(handler) {
17
+ this.botMessageHandler = handler;
18
+ for (const service of this.services.values()) {
19
+ service.onBotMessageReceived = handler;
20
+ }
21
+ }
22
+ setEnvironmentHostResolver(resolver) {
23
+ this.resolveEnvironmentHost = resolver;
24
+ }
25
+ getRuntime(locator) {
26
+ const agentId = this.resolveAgentId(locator);
27
+ if (!agentId) {
28
+ return null;
29
+ }
30
+ return this.services.get(agentId) ?? null;
31
+ }
32
+ resolveRuntimeAgentId(locator) {
33
+ return this.resolveAgentId(locator);
34
+ }
35
+ createRuntimeForAgent(agentId) {
36
+ const normalizedAgentId = this.normalizeAgentId(agentId);
37
+ if (!normalizedAgentId) {
38
+ throw new Error("Cannot create Kichi runtime without a valid agentId");
39
+ }
40
+ const existing = this.services.get(normalizedAgentId);
41
+ if (existing) {
42
+ return existing;
43
+ }
44
+ return this.createRuntime(normalizedAgentId);
45
+ }
46
+ initializeStartupRuntimes() {
47
+ const rootDir = CANONICAL_AGENT_ROOT_DIR;
48
+ if (!fs.existsSync(rootDir)) {
49
+ return;
50
+ }
51
+ for (const entry of fs.readdirSync(rootDir, { withFileTypes: true })) {
52
+ if (!entry.isDirectory()) {
53
+ continue;
54
+ }
55
+ const runtimeDir = path.join(rootDir, entry.name);
56
+ const statePath = path.join(runtimeDir, "state.json");
57
+ if (!fs.existsSync(statePath)) {
58
+ continue;
59
+ }
60
+ const agentId = decodeURIComponent(entry.name);
61
+ if (this.services.has(agentId)) {
62
+ continue;
63
+ }
64
+ this.createRuntime(agentId);
65
+ }
66
+ }
67
+ stopAll() {
68
+ for (const service of this.services.values()) {
69
+ service.stop();
70
+ }
71
+ this.services.clear();
72
+ }
73
+ resolveAgentId(locator) {
74
+ const directAgentId = this.normalizeAgentId(locator.ctxAgentId) ?? this.normalizeAgentId(locator.agentId);
75
+ const sessionAgentId = typeof locator.sessionKey === "string" && locator.sessionKey.trim()
76
+ ? this.parseAgentIdFromSessionKey(locator.sessionKey)
77
+ : null;
78
+ if (sessionAgentId) {
79
+ if (directAgentId && directAgentId !== sessionAgentId) {
80
+ this.logger.error(`[kichi] runtime scope mismatch: directAgentId=${directAgentId} sessionAgentId=${sessionAgentId} sessionKey=${locator.sessionKey}`);
81
+ }
82
+ this.logger.debug(`[kichi] resolved agent runtime from sessionKey: ${sessionAgentId}`);
83
+ return sessionAgentId;
84
+ }
85
+ return directAgentId;
86
+ }
87
+ normalizeAgentId(value) {
88
+ return typeof value === "string" && value.trim() ? value.trim() : null;
89
+ }
90
+ parseAgentIdFromSessionKey(sessionKey) {
91
+ const trimmed = sessionKey.trim();
92
+ const match = /^agent:([^:]+):/i.exec(trimmed);
93
+ if (!match) {
94
+ return null;
95
+ }
96
+ return this.normalizeAgentId(match[1]);
97
+ }
98
+ createRuntime(agentId) {
99
+ if (!this.resolveEnvironmentHost) {
100
+ throw new Error("Environment host resolver not set on KichiRuntimeManager");
101
+ }
102
+ const runtimeDir = this.getRuntimeDir(agentId);
103
+ fs.mkdirSync(runtimeDir, { recursive: true, mode: 0o700 });
104
+ const resolveEnvironmentHost = this.resolveEnvironmentHost;
105
+ const service = new KichiForwarderService(this.logger, {
106
+ agentId,
107
+ runtimeDir,
108
+ resolveEnvironmentHost,
109
+ });
110
+ if (this.botMessageHandler) {
111
+ service.onBotMessageReceived = this.botMessageHandler;
112
+ }
113
+ service.start();
114
+ this.services.set(agentId, service);
115
+ this.logger.debug(`[kichi:${agentId}] runtime initialized at ${runtimeDir}`);
116
+ return service;
117
+ }
118
+ getRuntimeDir(agentId) {
119
+ return path.join(CANONICAL_AGENT_ROOT_DIR, encodeURIComponent(agentId));
120
+ }
121
+ }