homaruscc 0.2.0

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.
Files changed (171) hide show
  1. package/.env.example +8 -0
  2. package/LICENSE +21 -0
  3. package/README.md +307 -0
  4. package/bin/event-loop +60 -0
  5. package/config.example.json +55 -0
  6. package/dist/agent-registry.d.ts +38 -0
  7. package/dist/agent-registry.d.ts.map +1 -0
  8. package/dist/agent-registry.js +207 -0
  9. package/dist/agent-registry.js.map +1 -0
  10. package/dist/backend.d.ts +3 -0
  11. package/dist/backend.d.ts.map +1 -0
  12. package/dist/backend.js +59 -0
  13. package/dist/backend.js.map +1 -0
  14. package/dist/browser-service.d.ts +19 -0
  15. package/dist/browser-service.d.ts.map +1 -0
  16. package/dist/browser-service.js +101 -0
  17. package/dist/browser-service.js.map +1 -0
  18. package/dist/channel-adapter.d.ts +22 -0
  19. package/dist/channel-adapter.d.ts.map +1 -0
  20. package/dist/channel-adapter.js +62 -0
  21. package/dist/channel-adapter.js.map +1 -0
  22. package/dist/channel-manager.d.ts +18 -0
  23. package/dist/channel-manager.d.ts.map +1 -0
  24. package/dist/channel-manager.js +73 -0
  25. package/dist/channel-manager.js.map +1 -0
  26. package/dist/compaction-manager.d.ts +23 -0
  27. package/dist/compaction-manager.d.ts.map +1 -0
  28. package/dist/compaction-manager.js +135 -0
  29. package/dist/compaction-manager.js.map +1 -0
  30. package/dist/config.d.ts +21 -0
  31. package/dist/config.d.ts.map +1 -0
  32. package/dist/config.js +169 -0
  33. package/dist/config.js.map +1 -0
  34. package/dist/dashboard-adapter.d.ts +17 -0
  35. package/dist/dashboard-adapter.d.ts.map +1 -0
  36. package/dist/dashboard-adapter.js +41 -0
  37. package/dist/dashboard-adapter.js.map +1 -0
  38. package/dist/dashboard-server.d.ts +29 -0
  39. package/dist/dashboard-server.d.ts.map +1 -0
  40. package/dist/dashboard-server.js +381 -0
  41. package/dist/dashboard-server.js.map +1 -0
  42. package/dist/embedding-provider.d.ts +28 -0
  43. package/dist/embedding-provider.d.ts.map +1 -0
  44. package/dist/embedding-provider.js +91 -0
  45. package/dist/embedding-provider.js.map +1 -0
  46. package/dist/event-bus.d.ts +18 -0
  47. package/dist/event-bus.d.ts.map +1 -0
  48. package/dist/event-bus.js +41 -0
  49. package/dist/event-bus.js.map +1 -0
  50. package/dist/event-queue.d.ts +18 -0
  51. package/dist/event-queue.d.ts.map +1 -0
  52. package/dist/event-queue.js +68 -0
  53. package/dist/event-queue.js.map +1 -0
  54. package/dist/homaruscc.d.ts +69 -0
  55. package/dist/homaruscc.d.ts.map +1 -0
  56. package/dist/homaruscc.js +337 -0
  57. package/dist/homaruscc.js.map +1 -0
  58. package/dist/identity-manager.d.ts +36 -0
  59. package/dist/identity-manager.d.ts.map +1 -0
  60. package/dist/identity-manager.js +142 -0
  61. package/dist/identity-manager.js.map +1 -0
  62. package/dist/mcp-proxy.d.ts +3 -0
  63. package/dist/mcp-proxy.d.ts.map +1 -0
  64. package/dist/mcp-proxy.js +259 -0
  65. package/dist/mcp-proxy.js.map +1 -0
  66. package/dist/mcp-resources.d.ts +10 -0
  67. package/dist/mcp-resources.d.ts.map +1 -0
  68. package/dist/mcp-resources.js +67 -0
  69. package/dist/mcp-resources.js.map +1 -0
  70. package/dist/mcp-server.d.ts +3 -0
  71. package/dist/mcp-server.d.ts.map +1 -0
  72. package/dist/mcp-server.js +169 -0
  73. package/dist/mcp-server.js.map +1 -0
  74. package/dist/mcp-tools.d.ts +14 -0
  75. package/dist/mcp-tools.d.ts.map +1 -0
  76. package/dist/mcp-tools.js +408 -0
  77. package/dist/mcp-tools.js.map +1 -0
  78. package/dist/memory-index.d.ts +79 -0
  79. package/dist/memory-index.d.ts.map +1 -0
  80. package/dist/memory-index.js +437 -0
  81. package/dist/memory-index.js.map +1 -0
  82. package/dist/session-checkpoint.d.ts +22 -0
  83. package/dist/session-checkpoint.d.ts.map +1 -0
  84. package/dist/session-checkpoint.js +100 -0
  85. package/dist/session-checkpoint.js.map +1 -0
  86. package/dist/skill-manager.d.ts +26 -0
  87. package/dist/skill-manager.d.ts.map +1 -0
  88. package/dist/skill-manager.js +156 -0
  89. package/dist/skill-manager.js.map +1 -0
  90. package/dist/skill-transport.d.ts +45 -0
  91. package/dist/skill-transport.d.ts.map +1 -0
  92. package/dist/skill-transport.js +111 -0
  93. package/dist/skill-transport.js.map +1 -0
  94. package/dist/skill.d.ts +22 -0
  95. package/dist/skill.d.ts.map +1 -0
  96. package/dist/skill.js +106 -0
  97. package/dist/skill.js.map +1 -0
  98. package/dist/telegram-adapter.d.ts +43 -0
  99. package/dist/telegram-adapter.d.ts.map +1 -0
  100. package/dist/telegram-adapter.js +188 -0
  101. package/dist/telegram-adapter.js.map +1 -0
  102. package/dist/timer-service.d.ts +30 -0
  103. package/dist/timer-service.d.ts.map +1 -0
  104. package/dist/timer-service.js +176 -0
  105. package/dist/timer-service.js.map +1 -0
  106. package/dist/tool-registry.d.ts +30 -0
  107. package/dist/tool-registry.d.ts.map +1 -0
  108. package/dist/tool-registry.js +108 -0
  109. package/dist/tool-registry.js.map +1 -0
  110. package/dist/tools/bash.d.ts +3 -0
  111. package/dist/tools/bash.d.ts.map +1 -0
  112. package/dist/tools/bash.js +67 -0
  113. package/dist/tools/bash.js.map +1 -0
  114. package/dist/tools/browser.d.ts +4 -0
  115. package/dist/tools/browser.d.ts.map +1 -0
  116. package/dist/tools/browser.js +138 -0
  117. package/dist/tools/browser.js.map +1 -0
  118. package/dist/tools/edit.d.ts +3 -0
  119. package/dist/tools/edit.d.ts.map +1 -0
  120. package/dist/tools/edit.js +47 -0
  121. package/dist/tools/edit.js.map +1 -0
  122. package/dist/tools/git.d.ts +3 -0
  123. package/dist/tools/git.d.ts.map +1 -0
  124. package/dist/tools/git.js +105 -0
  125. package/dist/tools/git.js.map +1 -0
  126. package/dist/tools/glob.d.ts +3 -0
  127. package/dist/tools/glob.d.ts.map +1 -0
  128. package/dist/tools/glob.js +84 -0
  129. package/dist/tools/glob.js.map +1 -0
  130. package/dist/tools/grep.d.ts +3 -0
  131. package/dist/tools/grep.d.ts.map +1 -0
  132. package/dist/tools/grep.js +168 -0
  133. package/dist/tools/grep.js.map +1 -0
  134. package/dist/tools/index.d.ts +6 -0
  135. package/dist/tools/index.d.ts.map +1 -0
  136. package/dist/tools/index.js +46 -0
  137. package/dist/tools/index.js.map +1 -0
  138. package/dist/tools/memory.d.ts +4 -0
  139. package/dist/tools/memory.d.ts.map +1 -0
  140. package/dist/tools/memory.js +64 -0
  141. package/dist/tools/memory.js.map +1 -0
  142. package/dist/tools/read.d.ts +3 -0
  143. package/dist/tools/read.d.ts.map +1 -0
  144. package/dist/tools/read.js +50 -0
  145. package/dist/tools/read.js.map +1 -0
  146. package/dist/tools/web-fetch.d.ts +3 -0
  147. package/dist/tools/web-fetch.d.ts.map +1 -0
  148. package/dist/tools/web-fetch.js +51 -0
  149. package/dist/tools/web-fetch.js.map +1 -0
  150. package/dist/tools/web-search.d.ts +3 -0
  151. package/dist/tools/web-search.d.ts.map +1 -0
  152. package/dist/tools/web-search.js +65 -0
  153. package/dist/tools/web-search.js.map +1 -0
  154. package/dist/tools/write.d.ts +3 -0
  155. package/dist/tools/write.d.ts.map +1 -0
  156. package/dist/tools/write.js +32 -0
  157. package/dist/tools/write.js.map +1 -0
  158. package/dist/transcript-logger.d.ts +23 -0
  159. package/dist/transcript-logger.d.ts.map +1 -0
  160. package/dist/transcript-logger.js +101 -0
  161. package/dist/transcript-logger.js.map +1 -0
  162. package/dist/types.d.ts +190 -0
  163. package/dist/types.d.ts.map +1 -0
  164. package/dist/types.js +14 -0
  165. package/dist/types.js.map +1 -0
  166. package/identity.example/disagreements.md +9 -0
  167. package/identity.example/preferences.md +11 -0
  168. package/identity.example/soul.md +12 -0
  169. package/identity.example/state.md +21 -0
  170. package/identity.example/user.md +14 -0
  171. package/package.json +60 -0
@@ -0,0 +1,142 @@
1
+ // CRC: crc-IdentityManager.md | Seq: seq-startup.md
2
+ // Identity manager — from HomarUS
3
+ import { readFileSync, existsSync, readdirSync } from "node:fs";
4
+ import { resolve, join } from "node:path";
5
+ export class IdentityManager {
6
+ soulContent = "";
7
+ userContent = "";
8
+ stateContent = "";
9
+ overlays = new Map();
10
+ workspaceFiles = new Map();
11
+ identityDir;
12
+ workspaceDir;
13
+ logger;
14
+ constructor(logger, identityDir, workspaceDir) {
15
+ this.logger = logger;
16
+ this.identityDir = identityDir;
17
+ this.workspaceDir = workspaceDir;
18
+ }
19
+ load() {
20
+ this.soulContent = this.readFile(resolve(this.identityDir, "soul.md"));
21
+ this.userContent = this.readFile(resolve(this.identityDir, "user.md"));
22
+ this.stateContent = this.readFile(resolve(this.identityDir, "state.md"));
23
+ this.loadOverlays();
24
+ this.loadWorkspaceFiles();
25
+ this.logger.info("Identity loaded", {
26
+ hasSoul: this.soulContent.length > 0,
27
+ hasUser: this.userContent.length > 0,
28
+ hasState: this.stateContent.length > 0,
29
+ overlays: this.overlays.size,
30
+ workspaceFiles: this.workspaceFiles.size,
31
+ });
32
+ }
33
+ reload() {
34
+ this.overlays.clear();
35
+ this.workspaceFiles.clear();
36
+ this.load();
37
+ }
38
+ buildSystemPrompt(options = {}) {
39
+ const parts = [];
40
+ if (this.soulContent)
41
+ parts.push(this.soulContent);
42
+ if (this.userContent)
43
+ parts.push(this.userContent);
44
+ if (this.stateContent)
45
+ parts.push(this.stateContent);
46
+ if (options.channel) {
47
+ const overlay = this.overlays.get(options.channel);
48
+ if (overlay)
49
+ parts.push(overlay);
50
+ }
51
+ if (options.taskOverlay) {
52
+ const overlay = this.overlays.get(options.taskOverlay);
53
+ if (overlay)
54
+ parts.push(overlay);
55
+ }
56
+ for (const [name, content] of this.workspaceFiles) {
57
+ if (content)
58
+ parts.push(`## ${name}\n${content}`);
59
+ }
60
+ if (options.taskPrompt)
61
+ parts.push(options.taskPrompt);
62
+ return parts.join("\n\n---\n\n");
63
+ }
64
+ getSoul() {
65
+ return this.soulContent;
66
+ }
67
+ getUser() {
68
+ return this.userContent;
69
+ }
70
+ getAgentState() {
71
+ return this.stateContent;
72
+ }
73
+ // R149: Compressed identity digest (~200 tokens) for normal event wakes
74
+ /**
75
+ * Returns a compressed identity digest (~200 tokens) for normal event wakes.
76
+ * Extracts name, core behavioral rules, and current mood — enough for
77
+ * personality consistency without the full 3K token payload.
78
+ */
79
+ getDigest() {
80
+ const lines = [];
81
+ // Extract name from soul
82
+ const nameMatch = this.soulContent.match(/\*\*Name:\s*(\w+)\*\*/);
83
+ if (nameMatch)
84
+ lines.push(`You are ${nameMatch[1]}.`);
85
+ // Extract Vibe section (key behavioral rules)
86
+ const vibeMatch = this.soulContent.match(/## Vibe\n\n([\s\S]*?)(?=\n##|\n---)/);
87
+ if (vibeMatch)
88
+ lines.push(vibeMatch[1].trim());
89
+ // Extract current mood/state summary (first paragraph of state.md)
90
+ if (this.stateContent) {
91
+ const moodMatch = this.stateContent.match(/## Last Session\n\n([\s\S]*?)(?=\n##)/);
92
+ if (moodMatch)
93
+ lines.push("Last session: " + moodMatch[1].trim());
94
+ }
95
+ return lines.join("\n\n");
96
+ }
97
+ getOverlay(name) {
98
+ return this.overlays.get(name);
99
+ }
100
+ getWorkspaceFile(name) {
101
+ return this.workspaceFiles.get(name);
102
+ }
103
+ listOverlays() {
104
+ return [...this.overlays.keys()];
105
+ }
106
+ loadOverlays() {
107
+ const overlayDir = resolve(this.identityDir, "overlays");
108
+ if (!existsSync(overlayDir))
109
+ return;
110
+ for (const file of readdirSync(overlayDir)) {
111
+ if (!file.endsWith(".md"))
112
+ continue;
113
+ const name = file.replace(/\.md$/, "");
114
+ const content = this.readFile(join(overlayDir, file));
115
+ if (content)
116
+ this.overlays.set(name, content);
117
+ }
118
+ }
119
+ loadWorkspaceFiles() {
120
+ if (!existsSync(this.workspaceDir))
121
+ return;
122
+ for (const file of readdirSync(this.workspaceDir)) {
123
+ if (!file.endsWith(".md"))
124
+ continue;
125
+ const content = this.readFile(join(this.workspaceDir, file));
126
+ if (content)
127
+ this.workspaceFiles.set(file, content);
128
+ }
129
+ }
130
+ readFile(path) {
131
+ if (!existsSync(path))
132
+ return "";
133
+ try {
134
+ return readFileSync(path, "utf-8").trim();
135
+ }
136
+ catch (err) {
137
+ this.logger.warn("Failed to read identity file", { path, error: String(err) });
138
+ return "";
139
+ }
140
+ }
141
+ }
142
+ //# sourceMappingURL=identity-manager.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"identity-manager.js","sourceRoot":"","sources":["../src/identity-manager.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env node
2
+ export {};
3
+ //# sourceMappingURL=mcp-proxy.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mcp-proxy.d.ts","sourceRoot":"","sources":["../src/mcp-proxy.ts"],"names":[],"mappings":""}
@@ -0,0 +1,259 @@
1
+ #!/usr/bin/env node
2
+ // CRC: crc-McpProxy.md | Seq: seq-startup.md
3
+ // Thin MCP proxy — stdio transport forwarding to backend HTTP API.
4
+ // Never restarts. Backend can be restarted via restart_backend tool.
5
+ import { spawn } from "node:child_process";
6
+ import { resolve } from "node:path";
7
+ import { Server } from "@modelcontextprotocol/sdk/server/index.js";
8
+ import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
9
+ import { CallToolRequestSchema, ListToolsRequestSchema, ListResourcesRequestSchema, ReadResourceRequestSchema, } from "@modelcontextprotocol/sdk/types.js";
10
+ import WebSocket from "ws";
11
+ const BACKEND_PORT = parseInt(process.env.HOMARUSCC_PORT ?? "3120", 10);
12
+ const BACKEND_URL = `http://localhost:${BACKEND_PORT}`;
13
+ const WS_URL = `ws://localhost:${BACKEND_PORT}`;
14
+ const TOOL_CALL_TIMEOUT = 130_000; // 130s — covers wait_for_event's 120s max
15
+ // --- Logger (stderr only, stdout is MCP protocol) ---
16
+ function log(level, msg, meta) {
17
+ process.stderr.write(`[${level}] [proxy] ${msg} ${meta ? JSON.stringify(meta) : ""}\n`);
18
+ }
19
+ // --- Backend process manager ---
20
+ class BackendManager {
21
+ child = null;
22
+ backendScript;
23
+ constructor() {
24
+ this.backendScript = resolve(import.meta.dirname ?? __dirname, "backend.js");
25
+ }
26
+ async spawn() {
27
+ if (this.child)
28
+ return;
29
+ log("INFO", "Spawning backend process", { script: this.backendScript });
30
+ const env = { ...process.env };
31
+ if (BACKEND_PORT !== 3120) {
32
+ // Pass port through to backend via dashboard config
33
+ // Backend reads from config, but we ensure consistency
34
+ }
35
+ this.child = spawn("node", [this.backendScript], {
36
+ stdio: ["ignore", "ignore", "pipe"],
37
+ env,
38
+ });
39
+ // Pipe backend stderr through to our stderr
40
+ this.child.stderr?.on("data", (data) => {
41
+ process.stderr.write(data);
42
+ });
43
+ this.child.on("exit", (code, signal) => {
44
+ log("WARN", "Backend process exited", { code, signal });
45
+ this.child = null;
46
+ });
47
+ // Wait for backend to become healthy
48
+ await this.waitForHealthy();
49
+ }
50
+ async restart() {
51
+ log("INFO", "Restarting backend...");
52
+ await this.stop();
53
+ await this.spawn();
54
+ log("INFO", "Backend restarted successfully");
55
+ }
56
+ async stop() {
57
+ if (!this.child)
58
+ return;
59
+ const child = this.child;
60
+ this.child = null;
61
+ return new Promise((resolve) => {
62
+ const timeout = setTimeout(() => {
63
+ log("WARN", "Backend didn't exit gracefully, killing");
64
+ child.kill("SIGKILL");
65
+ resolve();
66
+ }, 5000);
67
+ child.on("exit", () => {
68
+ clearTimeout(timeout);
69
+ resolve();
70
+ });
71
+ child.kill("SIGTERM");
72
+ });
73
+ }
74
+ async waitForHealthy() {
75
+ const deadline = Date.now() + 30_000;
76
+ while (Date.now() < deadline) {
77
+ try {
78
+ const res = await fetch(`${BACKEND_URL}/api/health`);
79
+ if (res.ok) {
80
+ log("INFO", "Backend is healthy");
81
+ return;
82
+ }
83
+ }
84
+ catch {
85
+ // Not ready yet
86
+ }
87
+ await new Promise((r) => setTimeout(r, 200));
88
+ }
89
+ throw new Error("Backend failed to become healthy within 30s");
90
+ }
91
+ }
92
+ // --- HTTP forwarding helpers ---
93
+ async function forwardToolCall(name, args) {
94
+ try {
95
+ const res = await fetch(`${BACKEND_URL}/api/tool-call`, {
96
+ method: "POST",
97
+ headers: { "Content-Type": "application/json" },
98
+ body: JSON.stringify({ name, args }),
99
+ signal: AbortSignal.timeout(TOOL_CALL_TIMEOUT),
100
+ });
101
+ return await res.json();
102
+ }
103
+ catch (err) {
104
+ return {
105
+ content: [{ type: "text", text: `Backend unavailable: ${String(err)}. Use restart_backend to restart.` }],
106
+ isError: true,
107
+ };
108
+ }
109
+ }
110
+ async function fetchJson(path) {
111
+ const res = await fetch(`${BACKEND_URL}${path}`);
112
+ return await res.json();
113
+ }
114
+ // --- WebSocket notification relay ---
115
+ function connectNotificationWs(mcpServer) {
116
+ let ws = null;
117
+ let reconnectTimer = null;
118
+ function connect() {
119
+ try {
120
+ ws = new WebSocket(WS_URL);
121
+ }
122
+ catch {
123
+ scheduleReconnect();
124
+ return;
125
+ }
126
+ ws.on("open", () => {
127
+ log("INFO", "WebSocket connected to backend");
128
+ });
129
+ ws.on("message", (data) => {
130
+ try {
131
+ const msg = JSON.parse(data.toString());
132
+ if (msg.type === "event") {
133
+ const event = msg.payload;
134
+ mcpServer.notification({
135
+ method: `notifications/homaruscc/${event.type}`,
136
+ params: {
137
+ type: event.type,
138
+ source: event.source,
139
+ payload: event.payload,
140
+ timestamp: event.timestamp,
141
+ eventId: event.id,
142
+ },
143
+ }).catch(() => { });
144
+ }
145
+ }
146
+ catch {
147
+ // Ignore malformed messages
148
+ }
149
+ });
150
+ ws.on("close", () => {
151
+ log("INFO", "WebSocket disconnected from backend");
152
+ ws = null;
153
+ scheduleReconnect();
154
+ });
155
+ ws.on("error", () => {
156
+ ws?.close();
157
+ });
158
+ }
159
+ function scheduleReconnect() {
160
+ if (reconnectTimer)
161
+ return;
162
+ reconnectTimer = setTimeout(() => {
163
+ reconnectTimer = null;
164
+ connect();
165
+ }, 2000);
166
+ }
167
+ connect();
168
+ // Return cleanup function (unused for now, but available)
169
+ return;
170
+ }
171
+ // --- restart_backend tool definition ---
172
+ const restartBackendTool = {
173
+ name: "restart_backend",
174
+ description: "Restart the HomarUScc backend process. Use after code changes or if the backend becomes unresponsive.",
175
+ inputSchema: { type: "object", properties: {} },
176
+ };
177
+ // --- Main ---
178
+ async function main() {
179
+ const backend = new BackendManager();
180
+ // Spawn backend first
181
+ await backend.spawn();
182
+ // Create MCP server
183
+ const server = new Server({ name: "homaruscc", version: "0.1.0" }, { capabilities: { tools: {}, resources: {} } });
184
+ // Connect WebSocket for event notifications
185
+ connectNotificationWs(server);
186
+ // --- MCP handlers ---
187
+ server.setRequestHandler(ListToolsRequestSchema, async () => {
188
+ try {
189
+ const tools = await fetchJson("/api/tool-list");
190
+ return { tools: [...tools, restartBackendTool] };
191
+ }
192
+ catch {
193
+ return { tools: [restartBackendTool] };
194
+ }
195
+ });
196
+ server.setRequestHandler(CallToolRequestSchema, async (request) => {
197
+ const { name, arguments: args } = request.params;
198
+ if (name === "restart_backend") {
199
+ try {
200
+ await backend.restart();
201
+ // Reconnect WebSocket (will auto-reconnect on close)
202
+ connectNotificationWs(server);
203
+ return { content: [{ type: "text", text: "Backend restarted successfully." }] };
204
+ }
205
+ catch (err) {
206
+ return {
207
+ content: [{ type: "text", text: `Failed to restart backend: ${String(err)}` }],
208
+ isError: true,
209
+ };
210
+ }
211
+ }
212
+ return await forwardToolCall(name, (args ?? {}));
213
+ });
214
+ server.setRequestHandler(ListResourcesRequestSchema, async () => {
215
+ try {
216
+ const resources = await fetchJson("/api/resource-list");
217
+ return { resources };
218
+ }
219
+ catch {
220
+ return { resources: [] };
221
+ }
222
+ });
223
+ server.setRequestHandler(ReadResourceRequestSchema, async (request) => {
224
+ const { uri } = request.params;
225
+ try {
226
+ const res = await fetch(`${BACKEND_URL}/api/resource`, {
227
+ method: "POST",
228
+ headers: { "Content-Type": "application/json" },
229
+ body: JSON.stringify({ uri }),
230
+ });
231
+ if (!res.ok) {
232
+ throw new Error(`Backend returned ${res.status}`);
233
+ }
234
+ const data = await res.json();
235
+ return { contents: [data] };
236
+ }
237
+ catch (err) {
238
+ throw new Error(`Backend unavailable: ${String(err)}. Use restart_backend to restart.`);
239
+ }
240
+ });
241
+ // Connect MCP transport
242
+ const transport = new StdioServerTransport();
243
+ await server.connect(transport);
244
+ log("INFO", "MCP proxy connected via stdio");
245
+ // Graceful shutdown
246
+ const shutdown = async () => {
247
+ log("INFO", "Proxy shutting down...");
248
+ await backend.stop();
249
+ await server.close();
250
+ process.exit(0);
251
+ };
252
+ process.on("SIGINT", shutdown);
253
+ process.on("SIGTERM", shutdown);
254
+ }
255
+ main().catch((err) => {
256
+ process.stderr.write(`[FATAL] [proxy] ${String(err)}\n`);
257
+ process.exit(1);
258
+ });
259
+ //# sourceMappingURL=mcp-proxy.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mcp-proxy.js","sourceRoot":"","sources":["../src/mcp-proxy.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,10 @@
1
+ import type { HomarUScc } from "./homaruscc.js";
2
+ export interface McpResourceDef {
3
+ uri: string;
4
+ name: string;
5
+ description: string;
6
+ mimeType: string;
7
+ handler: () => Promise<string>;
8
+ }
9
+ export declare function createMcpResources(loop: HomarUScc): McpResourceDef[];
10
+ //# sourceMappingURL=mcp-resources.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mcp-resources.d.ts","sourceRoot":"","sources":["../src/mcp-resources.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAEhD,MAAM,WAAW,cAAc;IAC7B,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,OAAO,CAAC,MAAM,CAAC,CAAC;CAChC;AAED,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,SAAS,GAAG,cAAc,EAAE,CA+DpE"}
@@ -0,0 +1,67 @@
1
+ export function createMcpResources(loop) {
2
+ return [
3
+ {
4
+ uri: "identity://soul",
5
+ name: "Soul Identity",
6
+ description: "Current soul.md content — core identity and personality",
7
+ mimeType: "text/markdown",
8
+ async handler() {
9
+ return loop.getIdentityManager().getSoul() || "(no soul.md configured)";
10
+ },
11
+ },
12
+ {
13
+ uri: "identity://user",
14
+ name: "User Profile",
15
+ description: "Current user.md content — user preferences and context",
16
+ mimeType: "text/markdown",
17
+ async handler() {
18
+ return loop.getIdentityManager().getUser() || "(no user.md configured)";
19
+ },
20
+ },
21
+ {
22
+ uri: "identity://state",
23
+ name: "Agent State",
24
+ description: "Current state.md — agent mood, recent session context, emotional continuity",
25
+ mimeType: "text/markdown",
26
+ async handler() {
27
+ return loop.getIdentityManager().getAgentState() || "(no state.md — first session)";
28
+ },
29
+ },
30
+ {
31
+ uri: "config://current",
32
+ name: "Current Config",
33
+ description: "Current configuration (secrets redacted)",
34
+ mimeType: "application/json",
35
+ async handler() {
36
+ const config = loop.getConfig().getAll();
37
+ // Redact sensitive fields
38
+ const redacted = JSON.parse(JSON.stringify(config));
39
+ const channels = redacted.channels;
40
+ if (channels) {
41
+ for (const ch of Object.values(channels)) {
42
+ if (ch.token)
43
+ ch.token = "***";
44
+ }
45
+ }
46
+ const memory = redacted.memory;
47
+ if (memory?.embedding) {
48
+ const emb = memory.embedding;
49
+ if (emb.apiKey)
50
+ emb.apiKey = "***";
51
+ }
52
+ return JSON.stringify(redacted, null, 2);
53
+ },
54
+ },
55
+ {
56
+ uri: "events://recent",
57
+ name: "Recent Events",
58
+ description: "Last N events from the event loop",
59
+ mimeType: "application/json",
60
+ async handler() {
61
+ const events = loop.getEventHistory().slice(-20);
62
+ return JSON.stringify(events, null, 2);
63
+ },
64
+ },
65
+ ];
66
+ }
67
+ //# sourceMappingURL=mcp-resources.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mcp-resources.js","sourceRoot":"","sources":["../src/mcp-resources.ts"],"names":[],"mappings":"AAYA,MAAM,UAAU,kBAAkB,CAAC,IAAe;IAChD,OAAO;QACL;YACE,GAAG,EAAE,iBAAiB;YACtB,IAAI,EAAE,eAAe;YACrB,WAAW,EAAE,yDAAyD;YACtE,QAAQ,EAAE,eAAe;YACzB,KAAK,CAAC,OAAO;gBACX,OAAO,IAAI,CAAC,kBAAkB,EAAE,CAAC,OAAO,EAAE,IAAI,yBAAyB,CAAC;YAC1E,CAAC;SACF;QACD;YACE,GAAG,EAAE,iBAAiB;YACtB,IAAI,EAAE,cAAc;YACpB,WAAW,EAAE,wDAAwD;YACrE,QAAQ,EAAE,eAAe;YACzB,KAAK,CAAC,OAAO;gBACX,OAAO,IAAI,CAAC,kBAAkB,EAAE,CAAC,OAAO,EAAE,IAAI,yBAAyB,CAAC;YAC1E,CAAC;SACF;QACD;YACE,GAAG,EAAE,kBAAkB;YACvB,IAAI,EAAE,aAAa;YACnB,WAAW,EAAE,6EAA6E;YAC1F,QAAQ,EAAE,eAAe;YACzB,KAAK,CAAC,OAAO;gBACX,OAAO,IAAI,CAAC,kBAAkB,EAAE,CAAC,aAAa,EAAE,IAAI,+BAA+B,CAAC;YACtF,CAAC;SACF;QACD;YACE,GAAG,EAAE,kBAAkB;YACvB,IAAI,EAAE,gBAAgB;YACtB,WAAW,EAAE,0CAA0C;YACvD,QAAQ,EAAE,kBAAkB;YAC5B,KAAK,CAAC,OAAO;gBACX,MAAM,MAAM,GAAG,IAAI,CAAC,SAAS,EAAE,CAAC,MAAM,EAAE,CAAC;gBACzC,0BAA0B;gBAC1B,MAAM,QAAQ,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,CAA4B,CAAC;gBAC/E,MAAM,QAAQ,GAAG,QAAQ,CAAC,QAA+D,CAAC;gBAC1F,IAAI,QAAQ,EAAE,CAAC;oBACb,KAAK,MAAM,EAAE,IAAI,MAAM,CAAC,MAAM,CAAC,QAAQ,CAAC,EAAE,CAAC;wBACzC,IAAI,EAAE,CAAC,KAAK;4BAAE,EAAE,CAAC,KAAK,GAAG,KAAK,CAAC;oBACjC,CAAC;gBACH,CAAC;gBACD,MAAM,MAAM,GAAG,QAAQ,CAAC,MAA6D,CAAC;gBACtF,IAAI,MAAM,EAAE,SAAS,EAAE,CAAC;oBACtB,MAAM,GAAG,GAAG,MAAM,CAAC,SAAoC,CAAC;oBACxD,IAAI,GAAG,CAAC,MAAM;wBAAE,GAAG,CAAC,MAAM,GAAG,KAAK,CAAC;gBACrC,CAAC;gBACD,OAAO,IAAI,CAAC,SAAS,CAAC,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC;YAC3C,CAAC;SACF;QACD;YACE,GAAG,EAAE,iBAAiB;YACtB,IAAI,EAAE,eAAe;YACrB,WAAW,EAAE,mCAAmC;YAChD,QAAQ,EAAE,kBAAkB;YAC5B,KAAK,CAAC,OAAO;gBACX,MAAM,MAAM,GAAG,IAAI,CAAC,eAAe,EAAE,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC;gBACjD,OAAO,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC;YACzC,CAAC;SACF;KACF,CAAC;AACJ,CAAC"}
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env node
2
+ export {};
3
+ //# sourceMappingURL=mcp-server.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mcp-server.d.ts","sourceRoot":"","sources":["../src/mcp-server.ts"],"names":[],"mappings":""}