agent-world 0.11.1 → 0.12.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 (267) hide show
  1. package/README.md +17 -7
  2. package/dist/cli/commands.d.ts +109 -0
  3. package/dist/cli/commands.js +2024 -0
  4. package/dist/cli/display.d.ts +124 -0
  5. package/dist/cli/display.js +381 -0
  6. package/dist/cli/hitl.d.ts +33 -0
  7. package/dist/cli/hitl.js +81 -0
  8. package/dist/cli/index.d.ts +2 -0
  9. package/dist/cli/stream.d.ts +41 -0
  10. package/dist/cli/stream.js +222 -0
  11. package/dist/core/activity-tracker.d.ts +16 -0
  12. package/dist/core/activity-tracker.d.ts.map +1 -0
  13. package/dist/core/activity-tracker.js +91 -0
  14. package/dist/core/activity-tracker.js.map +1 -0
  15. package/dist/core/ai-commands.d.ts +16 -0
  16. package/dist/core/ai-commands.d.ts.map +1 -0
  17. package/dist/core/ai-commands.js +24 -0
  18. package/dist/core/ai-commands.js.map +1 -0
  19. package/dist/core/ai-sdk-patch.d.ts +24 -0
  20. package/dist/core/ai-sdk-patch.d.ts.map +1 -0
  21. package/dist/core/ai-sdk-patch.js +169 -0
  22. package/dist/core/ai-sdk-patch.js.map +1 -0
  23. package/dist/core/anthropic-direct.d.ts +52 -0
  24. package/dist/core/anthropic-direct.d.ts.map +1 -0
  25. package/dist/core/anthropic-direct.js +301 -0
  26. package/dist/core/anthropic-direct.js.map +1 -0
  27. package/dist/core/approval-cache.d.ts +104 -0
  28. package/dist/core/approval-cache.d.ts.map +1 -0
  29. package/dist/core/approval-cache.js +150 -0
  30. package/dist/core/approval-cache.js.map +1 -0
  31. package/dist/core/chat-constants.d.ts +20 -0
  32. package/dist/core/chat-constants.d.ts.map +1 -0
  33. package/dist/core/chat-constants.js +22 -0
  34. package/dist/core/chat-constants.js.map +1 -0
  35. package/dist/core/create-agent-tool.d.ts +66 -0
  36. package/dist/core/create-agent-tool.d.ts.map +1 -0
  37. package/dist/core/create-agent-tool.js +212 -0
  38. package/dist/core/create-agent-tool.js.map +1 -0
  39. package/dist/core/events/approval-checker.d.ts +61 -0
  40. package/dist/core/events/approval-checker.d.ts.map +1 -0
  41. package/dist/core/events/approval-checker.js +226 -0
  42. package/dist/core/events/approval-checker.js.map +1 -0
  43. package/dist/core/events/index.d.ts +25 -0
  44. package/dist/core/events/index.d.ts.map +1 -0
  45. package/dist/core/events/index.js +30 -0
  46. package/dist/core/events/index.js.map +1 -0
  47. package/dist/core/events/memory-manager.d.ts +73 -0
  48. package/dist/core/events/memory-manager.d.ts.map +1 -0
  49. package/dist/core/events/memory-manager.js +1218 -0
  50. package/dist/core/events/memory-manager.js.map +1 -0
  51. package/dist/core/events/mention-logic.d.ts +39 -0
  52. package/dist/core/events/mention-logic.d.ts.map +1 -0
  53. package/dist/core/events/mention-logic.js +163 -0
  54. package/dist/core/events/mention-logic.js.map +1 -0
  55. package/dist/core/events/orchestrator.d.ts +69 -0
  56. package/dist/core/events/orchestrator.d.ts.map +1 -0
  57. package/dist/core/events/orchestrator.js +883 -0
  58. package/dist/core/events/orchestrator.js.map +1 -0
  59. package/dist/core/events/persistence.d.ts +41 -0
  60. package/dist/core/events/persistence.d.ts.map +1 -0
  61. package/dist/core/events/persistence.js +296 -0
  62. package/dist/core/events/persistence.js.map +1 -0
  63. package/dist/core/events/publishers.d.ts +81 -0
  64. package/dist/core/events/publishers.d.ts.map +1 -0
  65. package/dist/core/events/publishers.js +272 -0
  66. package/dist/core/events/publishers.js.map +1 -0
  67. package/dist/core/events/subscribers.d.ts +45 -0
  68. package/dist/core/events/subscribers.d.ts.map +1 -0
  69. package/dist/core/events/subscribers.js +288 -0
  70. package/dist/core/events/subscribers.js.map +1 -0
  71. package/dist/core/events/tool-bridge-logging.d.ts +28 -0
  72. package/dist/core/events/tool-bridge-logging.d.ts.map +1 -0
  73. package/dist/core/events/tool-bridge-logging.js +94 -0
  74. package/dist/core/events/tool-bridge-logging.js.map +1 -0
  75. package/dist/core/events-metadata.d.ts +72 -0
  76. package/dist/core/events-metadata.d.ts.map +1 -0
  77. package/dist/core/events-metadata.js +167 -0
  78. package/dist/core/events-metadata.js.map +1 -0
  79. package/dist/core/events.d.ts +186 -0
  80. package/dist/core/events.d.ts.map +1 -0
  81. package/dist/core/events.js +1248 -0
  82. package/dist/core/events.js.map +1 -0
  83. package/dist/core/export.d.ts +106 -0
  84. package/dist/core/export.d.ts.map +1 -0
  85. package/dist/core/export.js +705 -0
  86. package/dist/core/export.js.map +1 -0
  87. package/dist/core/file-tools.d.ts +114 -0
  88. package/dist/core/file-tools.d.ts.map +1 -0
  89. package/dist/core/file-tools.js +370 -0
  90. package/dist/core/file-tools.js.map +1 -0
  91. package/dist/core/google-direct.d.ts +58 -0
  92. package/dist/core/google-direct.d.ts.map +1 -0
  93. package/dist/core/google-direct.js +298 -0
  94. package/dist/core/google-direct.js.map +1 -0
  95. package/dist/core/hitl.d.ts +54 -0
  96. package/dist/core/hitl.d.ts.map +1 -0
  97. package/dist/core/hitl.js +153 -0
  98. package/dist/core/hitl.js.map +1 -0
  99. package/dist/core/index.d.ts +59 -0
  100. package/dist/core/index.d.ts.map +1 -0
  101. package/dist/core/index.js +70 -0
  102. package/dist/core/index.js.map +1 -0
  103. package/dist/core/llm-config.d.ts +128 -0
  104. package/dist/core/llm-config.d.ts.map +1 -0
  105. package/dist/core/llm-config.js +164 -0
  106. package/dist/core/llm-config.js.map +1 -0
  107. package/dist/core/llm-manager.d.ts +163 -0
  108. package/dist/core/llm-manager.d.ts.map +1 -0
  109. package/dist/core/llm-manager.js +669 -0
  110. package/dist/core/llm-manager.js.map +1 -0
  111. package/dist/core/load-skill-tool.d.ts +55 -0
  112. package/dist/core/load-skill-tool.d.ts.map +1 -0
  113. package/dist/core/load-skill-tool.js +468 -0
  114. package/dist/core/load-skill-tool.js.map +1 -0
  115. package/dist/core/logger.d.ts +88 -0
  116. package/dist/core/logger.d.ts.map +1 -0
  117. package/dist/core/logger.js +358 -0
  118. package/dist/core/logger.js.map +1 -0
  119. package/dist/core/managers.d.ts +131 -0
  120. package/dist/core/managers.d.ts.map +1 -0
  121. package/dist/core/managers.js +1223 -0
  122. package/dist/core/managers.js.map +1 -0
  123. package/dist/core/mcp-server-registry.d.ts +304 -0
  124. package/dist/core/mcp-server-registry.d.ts.map +1 -0
  125. package/dist/core/mcp-server-registry.js +1769 -0
  126. package/dist/core/mcp-server-registry.js.map +1 -0
  127. package/dist/core/mcp-tools.d.ts +56 -0
  128. package/dist/core/mcp-tools.d.ts.map +1 -0
  129. package/dist/core/mcp-tools.js +186 -0
  130. package/dist/core/mcp-tools.js.map +1 -0
  131. package/dist/core/message-prep.d.ts +81 -0
  132. package/dist/core/message-prep.d.ts.map +1 -0
  133. package/dist/core/message-prep.js +223 -0
  134. package/dist/core/message-prep.js.map +1 -0
  135. package/dist/core/message-processing-control.d.ts +54 -0
  136. package/dist/core/message-processing-control.d.ts.map +1 -0
  137. package/dist/core/message-processing-control.js +139 -0
  138. package/dist/core/message-processing-control.js.map +1 -0
  139. package/dist/core/openai-direct.d.ts +80 -0
  140. package/dist/core/openai-direct.d.ts.map +1 -0
  141. package/dist/core/openai-direct.js +374 -0
  142. package/dist/core/openai-direct.js.map +1 -0
  143. package/dist/core/shell-cmd-tool.d.ts +235 -0
  144. package/dist/core/shell-cmd-tool.d.ts.map +1 -0
  145. package/dist/core/shell-cmd-tool.js +1157 -0
  146. package/dist/core/shell-cmd-tool.js.map +1 -0
  147. package/dist/core/shell-process-registry.d.ts +88 -0
  148. package/dist/core/shell-process-registry.d.ts.map +1 -0
  149. package/dist/core/shell-process-registry.js +309 -0
  150. package/dist/core/shell-process-registry.js.map +1 -0
  151. package/dist/core/skill-registry.d.ts +75 -0
  152. package/dist/core/skill-registry.d.ts.map +1 -0
  153. package/dist/core/skill-registry.js +369 -0
  154. package/dist/core/skill-registry.js.map +1 -0
  155. package/dist/core/skill-script-runner.d.ts +89 -0
  156. package/dist/core/skill-script-runner.d.ts.map +1 -0
  157. package/dist/core/skill-script-runner.js +274 -0
  158. package/dist/core/skill-script-runner.js.map +1 -0
  159. package/dist/core/skill-selector.d.ts +65 -0
  160. package/dist/core/skill-selector.d.ts.map +1 -0
  161. package/dist/core/skill-selector.js +190 -0
  162. package/dist/core/skill-selector.js.map +1 -0
  163. package/dist/core/skill-settings.d.ts +20 -0
  164. package/dist/core/skill-settings.d.ts.map +1 -0
  165. package/dist/core/skill-settings.js +40 -0
  166. package/dist/core/skill-settings.js.map +1 -0
  167. package/dist/core/storage/agent-storage.d.ts +134 -0
  168. package/dist/core/storage/agent-storage.d.ts.map +1 -0
  169. package/dist/core/storage/agent-storage.js +498 -0
  170. package/dist/core/storage/agent-storage.js.map +1 -0
  171. package/dist/core/storage/eventStorage/fileEventStorage.d.ts +100 -0
  172. package/dist/core/storage/eventStorage/fileEventStorage.d.ts.map +1 -0
  173. package/dist/core/storage/eventStorage/fileEventStorage.js +494 -0
  174. package/dist/core/storage/eventStorage/fileEventStorage.js.map +1 -0
  175. package/dist/core/storage/eventStorage/index.d.ts +31 -0
  176. package/dist/core/storage/eventStorage/index.d.ts.map +1 -0
  177. package/dist/core/storage/eventStorage/index.js +31 -0
  178. package/dist/core/storage/eventStorage/index.js.map +1 -0
  179. package/dist/core/storage/eventStorage/memoryEventStorage.d.ts +87 -0
  180. package/dist/core/storage/eventStorage/memoryEventStorage.d.ts.map +1 -0
  181. package/dist/core/storage/eventStorage/memoryEventStorage.js +244 -0
  182. package/dist/core/storage/eventStorage/memoryEventStorage.js.map +1 -0
  183. package/dist/core/storage/eventStorage/sqliteEventStorage.d.ts +45 -0
  184. package/dist/core/storage/eventStorage/sqliteEventStorage.d.ts.map +1 -0
  185. package/dist/core/storage/eventStorage/sqliteEventStorage.js +301 -0
  186. package/dist/core/storage/eventStorage/sqliteEventStorage.js.map +1 -0
  187. package/dist/core/storage/eventStorage/types.d.ts +142 -0
  188. package/dist/core/storage/eventStorage/types.d.ts.map +1 -0
  189. package/dist/core/storage/eventStorage/types.js +43 -0
  190. package/dist/core/storage/eventStorage/types.js.map +1 -0
  191. package/dist/core/storage/eventStorage/validation.d.ts +30 -0
  192. package/dist/core/storage/eventStorage/validation.d.ts.map +1 -0
  193. package/dist/core/storage/eventStorage/validation.js +68 -0
  194. package/dist/core/storage/eventStorage/validation.js.map +1 -0
  195. package/dist/core/storage/legacy-migrations.d.ts +45 -0
  196. package/dist/core/storage/legacy-migrations.d.ts.map +1 -0
  197. package/dist/core/storage/legacy-migrations.js +295 -0
  198. package/dist/core/storage/legacy-migrations.js.map +1 -0
  199. package/dist/core/storage/memory-storage.d.ts +105 -0
  200. package/dist/core/storage/memory-storage.d.ts.map +1 -0
  201. package/dist/core/storage/memory-storage.js +415 -0
  202. package/dist/core/storage/memory-storage.js.map +1 -0
  203. package/dist/core/storage/migration-runner.d.ts +96 -0
  204. package/dist/core/storage/migration-runner.d.ts.map +1 -0
  205. package/dist/core/storage/migration-runner.js +306 -0
  206. package/dist/core/storage/migration-runner.js.map +1 -0
  207. package/dist/core/storage/queue-storage.d.ts +147 -0
  208. package/dist/core/storage/queue-storage.d.ts.map +1 -0
  209. package/dist/core/storage/queue-storage.js +290 -0
  210. package/dist/core/storage/queue-storage.js.map +1 -0
  211. package/dist/core/storage/skill-storage.d.ts +136 -0
  212. package/dist/core/storage/skill-storage.d.ts.map +1 -0
  213. package/dist/core/storage/skill-storage.js +474 -0
  214. package/dist/core/storage/skill-storage.js.map +1 -0
  215. package/dist/core/storage/sqlite-schema.d.ts +95 -0
  216. package/dist/core/storage/sqlite-schema.d.ts.map +1 -0
  217. package/dist/core/storage/sqlite-schema.js +156 -0
  218. package/dist/core/storage/sqlite-schema.js.map +1 -0
  219. package/dist/core/storage/sqlite-storage.d.ts +146 -0
  220. package/dist/core/storage/sqlite-storage.d.ts.map +1 -0
  221. package/dist/core/storage/sqlite-storage.js +709 -0
  222. package/dist/core/storage/sqlite-storage.js.map +1 -0
  223. package/dist/core/storage/storage-factory.d.ts +61 -0
  224. package/dist/core/storage/storage-factory.d.ts.map +1 -0
  225. package/dist/core/storage/storage-factory.js +794 -0
  226. package/dist/core/storage/storage-factory.js.map +1 -0
  227. package/dist/core/storage/validation.d.ts +36 -0
  228. package/dist/core/storage/validation.d.ts.map +1 -0
  229. package/dist/core/storage/validation.js +79 -0
  230. package/dist/core/storage/validation.js.map +1 -0
  231. package/dist/core/storage/world-storage.d.ts +114 -0
  232. package/dist/core/storage/world-storage.d.ts.map +1 -0
  233. package/dist/core/storage/world-storage.js +378 -0
  234. package/dist/core/storage/world-storage.js.map +1 -0
  235. package/dist/core/subscription.d.ts +43 -0
  236. package/dist/core/subscription.d.ts.map +1 -0
  237. package/dist/core/subscription.js +227 -0
  238. package/dist/core/subscription.js.map +1 -0
  239. package/dist/core/tool-utils.d.ts +80 -0
  240. package/dist/core/tool-utils.d.ts.map +1 -0
  241. package/dist/core/tool-utils.js +273 -0
  242. package/dist/core/tool-utils.js.map +1 -0
  243. package/dist/core/types.d.ts +595 -0
  244. package/dist/core/types.d.ts.map +1 -0
  245. package/dist/core/types.js +158 -0
  246. package/dist/core/types.js.map +1 -0
  247. package/dist/core/utils.d.ts +138 -0
  248. package/dist/core/utils.d.ts.map +1 -0
  249. package/dist/core/utils.js +478 -0
  250. package/dist/core/utils.js.map +1 -0
  251. package/dist/core/world-class.d.ts +43 -0
  252. package/dist/core/world-class.d.ts.map +1 -0
  253. package/dist/core/world-class.js +90 -0
  254. package/dist/core/world-class.js.map +1 -0
  255. package/dist/index.d.ts +18 -0
  256. package/dist/public/assets/agent-sprites-DJFgj-zP.png +0 -0
  257. package/dist/public/assets/border-KHK37r8y.svg +83 -0
  258. package/dist/public/assets/index-C9kPXL6G.css +1 -0
  259. package/dist/public/assets/index-DOQEHGWt.js +96 -0
  260. package/dist/public/index.html +21 -0
  261. package/dist/server/api.d.ts +2 -0
  262. package/dist/server/api.js +1124 -0
  263. package/dist/server/index.d.ts +29 -0
  264. package/dist/server/sse-handler.d.ts +62 -0
  265. package/dist/server/sse-handler.js +234 -0
  266. package/package.json +15 -3
  267. package/scripts/launch-electron.js +0 -58
@@ -0,0 +1,378 @@
1
+ /**
2
+ * World Storage Module - File I/O Operations for World Data and Chat Operations
3
+ *
4
+ * Logger Category: storage.query
5
+ * Purpose: World and chat data file I/O operations
6
+ *
7
+ * Enable with: LOG_STORAGE_QUERY=debug npm run server
8
+ *
9
+ * What you'll see:
10
+ * - World config saves and loads
11
+ * - Chat data operations
12
+ * - Memory aggregation queries
13
+ * - File operation errors
14
+ *
15
+ * Features:
16
+ * - World configuration persistence to config.json with flattened structure
17
+ * - Complete chat operations with file-based storage (chats directory)
18
+ * - Cross-agent memory aggregation for world-level chat sessions
19
+ * - Kebab-case directory naming from world names
20
+ * - Clean separation of storage data from runtime objects
21
+ * - Handles World serialization without EventEmitter and agents Map
22
+ * - Complete isolation from other internal modules
23
+ * - Explicit rootPath parameter handling (no environment variables)
24
+ * - Cascade deletion for data integrity (world → agents/chats, chat → messages)
25
+ *
26
+ * Core Functions:
27
+ * - saveWorld: Save world config.json with flat structure (excludes runtime properties: eventEmitter, agents, chats, eventStorage, _eventPersistenceCleanup)
28
+ * - loadWorld: Load world configuration from file
29
+ * - deleteWorld: Remove world directory and all contents (cascades to agents and chats)
30
+ * - listWorlds: Scan and load all worlds in root directory
31
+ * - worldExists: Check if world directory exists
32
+ *
33
+ * Changes:
34
+ * - 2026-02-13: Added compare-and-set chat title helper (`updateChatNameIfCurrent`) for safer concurrent title commits.
35
+ * - 2025-11-01: Explicitly exclude runtime properties (eventEmitter, agents, chats, eventStorage, _eventPersistenceCleanup) from saveWorld
36
+ * - getWorldDir: Get world directory path
37
+ * - ensureWorldDirectory: Create world directory structure
38
+ *
39
+ * Chat Functions:
40
+ * - saveChatData: Save complete chat data with metadata and content
41
+ * - loadChatData: Load complete chat data with Date reconstruction
42
+ * - deleteChatData: Remove chat files and cascade delete associated messages from agent memory
43
+ * - listChatHistories: List all chat metadata for a world
44
+ * - updateChatData: Update existing chat with partial data
45
+ * - getMemory: Aggregate memory across all agents for chat sessions
46
+ *
47
+ * Version: 2.1.0 - Added cascade deletion for chat operations
48
+ * Date: 2025-10-30
49
+ * Version: 2.2.0 - Updated to structured logging (storage.query)
50
+ * Date: 2025-10-31
51
+ */
52
+ import { promises as fs } from 'fs';
53
+ import * as path from 'path';
54
+ import { toKebabCase } from '../utils.js';
55
+ import { createCategoryLogger } from '../logger.js';
56
+ import { listAgents, loadAgent, deleteMemoryByChatId } from './agent-storage.js';
57
+ const logger = createCategoryLogger('storage.query');
58
+ // Extract readdir and exists from fs for convenience
59
+ const { readdir, access } = fs;
60
+ const exists = async (path) => {
61
+ try {
62
+ await access(path);
63
+ return true;
64
+ }
65
+ catch {
66
+ return false;
67
+ }
68
+ };
69
+ /**
70
+ * File utility functions
71
+ */
72
+ async function writeJsonFile(filePath, data) {
73
+ await fs.writeFile(filePath, JSON.stringify(data, null, 2), 'utf8');
74
+ }
75
+ async function readJsonFile(filePath) {
76
+ const content = await fs.readFile(filePath, 'utf8');
77
+ return JSON.parse(content);
78
+ }
79
+ /**
80
+ * World directory and file path utilities
81
+ */
82
+ export function getWorldDir(rootPath, worldId) {
83
+ const normalizedWorldId = toKebabCase(worldId);
84
+ return path.join(rootPath, normalizedWorldId);
85
+ }
86
+ export async function ensureWorldDirectory(root, worldId) {
87
+ const worldDir = getWorldDir(root, worldId);
88
+ await fs.mkdir(worldDir, { recursive: true });
89
+ }
90
+ /**
91
+ * Check if world exists on disk
92
+ */
93
+ export async function worldExists(root, worldId) {
94
+ try {
95
+ const worldDir = getWorldDir(root, worldId);
96
+ const configPath = path.join(worldDir, 'config.json');
97
+ await fs.access(configPath);
98
+ return true;
99
+ }
100
+ catch {
101
+ return false;
102
+ }
103
+ }
104
+ /**
105
+ * Save world to disk
106
+ */
107
+ export async function saveWorld(root, worldData) {
108
+ await ensureWorldDirectory(root, worldData.id);
109
+ const worldDir = getWorldDir(root, worldData.id);
110
+ const configPath = path.join(worldDir, 'config.json');
111
+ const mcpConfigPath = path.join(worldDir, 'mcp.json');
112
+ // Exclude runtime properties and mcpConfig from config.json
113
+ const { mcpConfig, eventEmitter, agents, chats, eventStorage, _eventPersistenceCleanup, ...configData } = worldData;
114
+ // Save main config without runtime properties
115
+ await writeJsonFile(configPath, configData);
116
+ // Save mcpConfig to separate file if it exists
117
+ if (mcpConfig !== undefined && mcpConfig !== null) {
118
+ try {
119
+ // Validate that mcpConfig is valid JSON
120
+ const parsedConfig = JSON.parse(mcpConfig);
121
+ await writeJsonFile(mcpConfigPath, parsedConfig);
122
+ }
123
+ catch (error) {
124
+ // If mcpConfig is not valid JSON, save it as-is (could be a string)
125
+ await writeJsonFile(mcpConfigPath, { config: mcpConfig });
126
+ }
127
+ }
128
+ else {
129
+ // Remove mcp.json if mcpConfig is null/undefined
130
+ try {
131
+ await fs.unlink(mcpConfigPath);
132
+ }
133
+ catch {
134
+ // File might not exist, ignore error
135
+ }
136
+ }
137
+ }
138
+ /**
139
+ * Load world from disk
140
+ */
141
+ export async function loadWorld(root, worldId) {
142
+ try {
143
+ const worldDir = getWorldDir(root, worldId);
144
+ const configPath = path.join(worldDir, 'config.json');
145
+ const mcpConfigPath = path.join(worldDir, 'mcp.json');
146
+ const worldData = await readJsonFile(configPath);
147
+ // Reconstruct Date objects
148
+ if (worldData.createdAt)
149
+ worldData.createdAt = new Date(worldData.createdAt);
150
+ if (worldData.lastUpdated)
151
+ worldData.lastUpdated = new Date(worldData.lastUpdated);
152
+ // Load mcpConfig from separate file if it exists
153
+ try {
154
+ const mcpData = await readJsonFile(mcpConfigPath);
155
+ // If mcpData has a 'config' field, it was stored as a wrapped string
156
+ if (mcpData && typeof mcpData === 'object' && 'config' in mcpData) {
157
+ worldData.mcpConfig = mcpData.config;
158
+ }
159
+ else {
160
+ // Otherwise, stringify the JSON object
161
+ worldData.mcpConfig = JSON.stringify(mcpData);
162
+ }
163
+ }
164
+ catch {
165
+ // mcp.json doesn't exist or can't be read, set to null for backward compatibility
166
+ worldData.mcpConfig = null;
167
+ }
168
+ return worldData;
169
+ }
170
+ catch {
171
+ return null;
172
+ }
173
+ }
174
+ /**
175
+ * Delete world from disk
176
+ */
177
+ export async function deleteWorld(root, worldId) {
178
+ try {
179
+ const worldDir = getWorldDir(root, worldId);
180
+ await fs.rm(worldDir, { recursive: true, force: true });
181
+ return true;
182
+ }
183
+ catch {
184
+ return false;
185
+ }
186
+ }
187
+ /**
188
+ * List all worlds in root directory
189
+ */
190
+ export async function listWorlds(root) {
191
+ try {
192
+ const entries = await fs.readdir(root, { withFileTypes: true });
193
+ const worlds = [];
194
+ for (const entry of entries) {
195
+ if (entry.isDirectory()) {
196
+ const worldData = await loadWorld(root, entry.name);
197
+ if (worldData) {
198
+ worlds.push(worldData);
199
+ }
200
+ }
201
+ }
202
+ return worlds.sort((a, b) => new Date(b.lastUpdated).getTime() - new Date(a.lastUpdated).getTime());
203
+ }
204
+ catch {
205
+ return [];
206
+ }
207
+ }
208
+ /**
209
+ * Chat directory and file path utilities
210
+ */
211
+ export function getChatDir(rootPath, worldId) {
212
+ const worldDir = getWorldDir(rootPath, worldId);
213
+ return path.join(worldDir, 'chats');
214
+ }
215
+ export function getChatFilePath(rootPath, worldId, chatId) {
216
+ const chatDir = getChatDir(rootPath, worldId);
217
+ return path.join(chatDir, `${chatId}.json`);
218
+ }
219
+ export async function ensureChatDirectory(rootPath, worldId) {
220
+ const chatDir = getChatDir(rootPath, worldId);
221
+ await fs.mkdir(chatDir, { recursive: true });
222
+ }
223
+ /**
224
+ * Save chat data (metadata + content) to disk
225
+ */
226
+ export async function saveChatData(rootPath, worldId, chatData) {
227
+ await ensureChatDirectory(rootPath, worldId);
228
+ // Save the complete ChatData object
229
+ const chatPath = getChatFilePath(rootPath, worldId, chatData.id);
230
+ await writeJsonFile(chatPath, chatData);
231
+ }
232
+ /**
233
+ * Load chat data (metadata + content) from disk
234
+ */
235
+ export async function loadChatData(rootPath, worldId, chatId) {
236
+ try {
237
+ const chatPath = getChatFilePath(rootPath, worldId, chatId);
238
+ const chatData = await readJsonFile(chatPath);
239
+ // Reconstruct Date objects
240
+ if (chatData.createdAt)
241
+ chatData.createdAt = new Date(chatData.createdAt);
242
+ if (chatData.updatedAt)
243
+ chatData.updatedAt = new Date(chatData.updatedAt);
244
+ return chatData;
245
+ }
246
+ catch (error) {
247
+ logger.error('Failed to load chat data', {
248
+ error: error instanceof Error ? error.message : String(error),
249
+ worldId,
250
+ chatId
251
+ });
252
+ return null;
253
+ }
254
+ }
255
+ /**
256
+ * Update chat data on disk
257
+ */
258
+ export async function updateChatData(rootPath, worldId, chatId, updates) {
259
+ const chatData = await loadChatData(rootPath, worldId, chatId);
260
+ if (!chatData)
261
+ return null;
262
+ // Apply updates to metadata
263
+ if (updates.name !== undefined)
264
+ chatData.name = updates.name;
265
+ if (updates.description !== undefined)
266
+ chatData.description = updates.description;
267
+ // Update timestamps
268
+ chatData.updatedAt = new Date();
269
+ await saveChatData(rootPath, worldId, chatData);
270
+ return chatData;
271
+ }
272
+ /**
273
+ * Compare-and-set chat name on disk.
274
+ * Updates name only when the current name exactly matches expectedName.
275
+ */
276
+ export async function updateChatNameIfCurrent(rootPath, worldId, chatId, expectedName, nextName) {
277
+ const chatData = await loadChatData(rootPath, worldId, chatId);
278
+ if (!chatData)
279
+ return false;
280
+ if (chatData.name !== expectedName)
281
+ return false;
282
+ chatData.name = nextName;
283
+ chatData.updatedAt = new Date();
284
+ await saveChatData(rootPath, worldId, chatData);
285
+ return true;
286
+ }
287
+ /**
288
+ * Delete chat data from disk with cascade deletion of associated messages
289
+ */
290
+ export async function deleteChatData(rootPath, worldId, chatId) {
291
+ try {
292
+ // Delete the chat file
293
+ const chatPath = getChatFilePath(rootPath, worldId, chatId);
294
+ await fs.unlink(chatPath);
295
+ // Cascade delete: Remove all agent memory messages with this chatId
296
+ await deleteMemoryByChatId(rootPath, worldId, chatId);
297
+ return true;
298
+ }
299
+ catch {
300
+ return false;
301
+ }
302
+ }
303
+ /**
304
+ * List chat histories (metadata only)
305
+ */
306
+ export async function listChatHistories(rootPath, worldId) {
307
+ try {
308
+ const chatDir = getChatDir(rootPath, worldId);
309
+ if (!await exists(chatDir)) {
310
+ return [];
311
+ }
312
+ const files = await readdir(chatDir);
313
+ const chatFiles = files.filter((file) => file.endsWith('.json'));
314
+ const chats = [];
315
+ for (const file of chatFiles) {
316
+ const chatId = file.replace('.json', '');
317
+ const chatData = await loadChatData(rootPath, worldId, chatId);
318
+ if (chatData) {
319
+ // Extract just the metadata
320
+ const chatInfo = {
321
+ id: chatData.id,
322
+ worldId: worldId,
323
+ name: chatData.name,
324
+ description: chatData.description,
325
+ createdAt: chatData.createdAt,
326
+ updatedAt: chatData.updatedAt,
327
+ messageCount: chatData.messageCount,
328
+ };
329
+ chats.push(chatInfo);
330
+ }
331
+ }
332
+ return chats.sort((a, b) => new Date(b.updatedAt).getTime() - new Date(a.updatedAt).getTime());
333
+ }
334
+ catch (error) {
335
+ logger.error('Failed to list chat histories', {
336
+ error: error instanceof Error ? error.message : String(error),
337
+ worldId
338
+ });
339
+ return [];
340
+ }
341
+ }
342
+ /**
343
+ * Get aggregated memory across all agents for a given chat
344
+ * Filters messages by chatId and includes agentId for proper message attribution
345
+ */
346
+ export async function getMemory(rootPath, worldId, chatId) {
347
+ try {
348
+ const agents = await listAgents(rootPath, worldId);
349
+ const messages = [];
350
+ for (const agent of agents) {
351
+ const fullAgent = await loadAgent(rootPath, worldId, agent.id);
352
+ const mem = fullAgent?.memory || [];
353
+ for (const m of mem) {
354
+ if (!chatId || m.chatId === chatId) {
355
+ // Ensure agentId is included in the message
356
+ const messageWithAgentId = { ...m, agentId: agent.id };
357
+ messages.push(messageWithAgentId);
358
+ }
359
+ }
360
+ }
361
+ // Sort by createdAt ascending
362
+ messages.sort((a, b) => {
363
+ const at = a.createdAt ? new Date(a.createdAt).getTime() : 0;
364
+ const bt = b.createdAt ? new Date(b.createdAt).getTime() : 0;
365
+ return at - bt;
366
+ });
367
+ return messages;
368
+ }
369
+ catch (error) {
370
+ logger.error('Failed to get aggregated memory', {
371
+ error: error instanceof Error ? error.message : String(error),
372
+ worldId,
373
+ chatId
374
+ });
375
+ return [];
376
+ }
377
+ }
378
+ //# sourceMappingURL=world-storage.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"world-storage.js","sourceRoot":"","sources":["../../../core/storage/world-storage.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,43 @@
1
+ /**
2
+ * World Subscription Runtime
3
+ *
4
+ * Features:
5
+ * - Manages world lifecycle subscriptions and realtime event forwarding.
6
+ * - Registers message/world/sse/system listeners for subscribed clients.
7
+ * - Tracks active world runtimes for core operations that need the live emitter.
8
+ *
9
+ * Implementation Notes:
10
+ * - Keeps forwarding listeners optional based on client callback capabilities.
11
+ * - Uses world-id keyed runtime tracking with safe register/unregister semantics.
12
+ *
13
+ * Recent Changes:
14
+ * - 2026-02-14: Added active runtime world tracking and `getActiveSubscribedWorld()` for core edit-message resubmission to publish on live emitters.
15
+ */
16
+ import { World } from './types.js';
17
+ import { type LogLevel } from './logger.js';
18
+ export interface LogStreamEvent {
19
+ level: LogLevel;
20
+ category: string;
21
+ message: string;
22
+ timestamp: string;
23
+ data?: any;
24
+ messageId: string;
25
+ }
26
+ export interface ClientConnection {
27
+ isOpen: boolean;
28
+ onWorldEvent?: (eventType: string, eventData: any) => void;
29
+ onError?: (error: string) => void;
30
+ onLog?: (logEvent: LogStreamEvent) => void;
31
+ }
32
+ export interface WorldSubscription {
33
+ world: World;
34
+ unsubscribe: () => Promise<void>;
35
+ refresh: () => Promise<World>;
36
+ destroy: () => Promise<void>;
37
+ }
38
+ export declare function getActiveSubscribedWorld(worldIdentifier: string): World | null;
39
+ export declare function startWorld(world: World, client: ClientConnection): Promise<WorldSubscription>;
40
+ export declare function subscribeWorld(worldIdentifier: string, client: ClientConnection): Promise<WorldSubscription | null>;
41
+ export declare function setupWorldEventListeners(world: World, client: ClientConnection): Map<string, (...args: any[]) => void>;
42
+ export declare function cleanupWorldSubscription(world: World, worldEventListeners: Map<string, (...args: any[]) => void>): Promise<void>;
43
+ //# sourceMappingURL=subscription.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"subscription.d.ts","sourceRoot":"","sources":["../../core/subscription.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,OAAO,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AAEnC,OAAO,EAAwB,KAAK,QAAQ,EAAwB,MAAM,aAAa,CAAC;AAYxF,MAAM,WAAW,cAAc;IAC7B,KAAK,EAAE,QAAQ,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;IAClB,IAAI,CAAC,EAAE,GAAG,CAAC;IACX,SAAS,EAAE,MAAM,CAAC;CACnB;AAGD,MAAM,WAAW,gBAAgB;IAC/B,MAAM,EAAE,OAAO,CAAC;IAChB,YAAY,CAAC,EAAE,CAAC,SAAS,EAAE,MAAM,EAAE,SAAS,EAAE,GAAG,KAAK,IAAI,CAAC;IAC3D,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IAClC,KAAK,CAAC,EAAE,CAAC,QAAQ,EAAE,cAAc,KAAK,IAAI,CAAC;CAC5C;AAGD,MAAM,WAAW,iBAAiB;IAChC,KAAK,EAAE,KAAK,CAAC;IACb,WAAW,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IACjC,OAAO,EAAE,MAAM,OAAO,CAAC,KAAK,CAAC,CAAC;IAC9B,OAAO,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;CAC9B;AAwBD,wBAAgB,wBAAwB,CAAC,eAAe,EAAE,MAAM,GAAG,KAAK,GAAG,IAAI,CAW9E;AAGD,wBAAsB,UAAU,CAAC,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE,gBAAgB,GAAG,OAAO,CAAC,iBAAiB,CAAC,CAwFnG;AAGD,wBAAsB,cAAc,CAClC,eAAe,EAAE,MAAM,EACvB,MAAM,EAAE,gBAAgB,GACvB,OAAO,CAAC,iBAAiB,GAAG,IAAI,CAAC,CAmCnC;AAGD,wBAAgB,wBAAwB,CAAC,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE,gBAAgB,GAAG,GAAG,CAAC,MAAM,EAAE,CAAC,GAAG,IAAI,EAAE,GAAG,EAAE,KAAK,IAAI,CAAC,CAiDtH;AAGD,wBAAsB,wBAAwB,CAAC,KAAK,EAAE,KAAK,EAAE,mBAAmB,EAAE,GAAG,CAAC,MAAM,EAAE,CAAC,GAAG,IAAI,EAAE,GAAG,EAAE,KAAK,IAAI,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC,CAetI"}
@@ -0,0 +1,227 @@
1
+ /**
2
+ * World Subscription Runtime
3
+ *
4
+ * Features:
5
+ * - Manages world lifecycle subscriptions and realtime event forwarding.
6
+ * - Registers message/world/sse/system listeners for subscribed clients.
7
+ * - Tracks active world runtimes for core operations that need the live emitter.
8
+ *
9
+ * Implementation Notes:
10
+ * - Keeps forwarding listeners optional based on client callback capabilities.
11
+ * - Uses world-id keyed runtime tracking with safe register/unregister semantics.
12
+ *
13
+ * Recent Changes:
14
+ * - 2026-02-14: Added active runtime world tracking and `getActiveSubscribedWorld()` for core edit-message resubmission to publish on live emitters.
15
+ */
16
+ import { getWorld } from './managers.js';
17
+ import { createCategoryLogger, addLogStreamCallback } from './logger.js';
18
+ import { subscribeAgentToMessages, subscribeWorldToMessages } from './events/index.js';
19
+ function toKebabCase(name) {
20
+ return name.toLowerCase().replace(/[^a-z0-9]/g, '-').replace(/-+/g, '-').replace(/^-|-$/g, '');
21
+ }
22
+ // Create subscription category logger (part of core functionality)
23
+ const logger = createCategoryLogger('world.subscription');
24
+ const activeSubscribedWorlds = new Map();
25
+ function registerActiveSubscribedWorld(world) {
26
+ const worldId = String(world?.id || '').trim();
27
+ if (!worldId)
28
+ return;
29
+ const existing = activeSubscribedWorlds.get(worldId) ?? new Set();
30
+ existing.add(world);
31
+ activeSubscribedWorlds.set(worldId, existing);
32
+ }
33
+ function unregisterActiveSubscribedWorld(world) {
34
+ const worldId = String(world?.id || '').trim();
35
+ if (!worldId)
36
+ return;
37
+ const existing = activeSubscribedWorlds.get(worldId);
38
+ if (!existing)
39
+ return;
40
+ existing.delete(world);
41
+ if (existing.size === 0) {
42
+ activeSubscribedWorlds.delete(worldId);
43
+ }
44
+ }
45
+ export function getActiveSubscribedWorld(worldIdentifier) {
46
+ const resolvedWorldId = toKebabCase(String(worldIdentifier || '').trim());
47
+ if (!resolvedWorldId)
48
+ return null;
49
+ const activeWorldSet = activeSubscribedWorlds.get(resolvedWorldId);
50
+ if (!activeWorldSet || activeWorldSet.size === 0)
51
+ return null;
52
+ for (const world of activeWorldSet.values()) {
53
+ return world;
54
+ }
55
+ return null;
56
+ }
57
+ // Start world with event listeners - extracted from subscribeWorld
58
+ export async function startWorld(world, client) {
59
+ // Only set up forwarding listeners when the client actually wants them.
60
+ let worldEventListeners = new Map();
61
+ if (client && (client.onWorldEvent || client.onLog)) {
62
+ worldEventListeners = setupWorldEventListeners(world, client);
63
+ }
64
+ let currentWorld = world;
65
+ registerActiveSubscribedWorld(currentWorld);
66
+ // Subscribe all loaded agents to world messages (moved from getFullWorld)
67
+ for (const agent of currentWorld.agents.values()) {
68
+ subscribeAgentToMessages(currentWorld, agent);
69
+ }
70
+ subscribeWorldToMessages(currentWorld);
71
+ // Helper function to destroy current world instance
72
+ const destroyCurrentWorld = async () => {
73
+ if (currentWorld) {
74
+ unregisterActiveSubscribedWorld(currentWorld);
75
+ // Clean up all event listeners
76
+ await cleanupWorldSubscription(currentWorld, worldEventListeners);
77
+ // Remove all listeners from the EventEmitter to prevent memory leaks
78
+ currentWorld.eventEmitter.removeAllListeners();
79
+ // Clear agents map references
80
+ currentWorld.agents.clear();
81
+ logger.debug('World instance destroyed', { worldId: currentWorld.id });
82
+ }
83
+ };
84
+ // Return subscription object with cleanup methods
85
+ return {
86
+ get world() {
87
+ if (!currentWorld) {
88
+ throw new Error('World subscription has been destroyed');
89
+ }
90
+ return currentWorld;
91
+ },
92
+ unsubscribe: async () => {
93
+ await destroyCurrentWorld();
94
+ currentWorld = null;
95
+ },
96
+ destroy: async () => {
97
+ await destroyCurrentWorld();
98
+ currentWorld = null;
99
+ },
100
+ refresh: async () => {
101
+ const worldId = currentWorld?.id || '';
102
+ logger.debug('Refreshing world subscription', { worldId });
103
+ // Destroy the old world instance completely
104
+ await destroyCurrentWorld();
105
+ // Create a completely new world instance
106
+ const refreshedWorld = await getWorld(worldId);
107
+ if (!refreshedWorld) {
108
+ throw new Error(`Failed to refresh world: ${worldId}`);
109
+ }
110
+ // Update current references
111
+ currentWorld = refreshedWorld;
112
+ registerActiveSubscribedWorld(currentWorld);
113
+ // Set up new event listeners on the fresh world only if client wants forwarding
114
+ if (client && (client.onWorldEvent || client.onLog)) {
115
+ worldEventListeners = setupWorldEventListeners(currentWorld, client);
116
+ }
117
+ else {
118
+ worldEventListeners = new Map();
119
+ }
120
+ // Subscribe all loaded agents to world messages (moved from getFullWorld)
121
+ for (const agent of currentWorld.agents.values()) {
122
+ subscribeAgentToMessages(currentWorld, agent);
123
+ }
124
+ logger.debug('World subscription refreshed', {
125
+ worldId: currentWorld.id,
126
+ agentCount: currentWorld.agents.size
127
+ });
128
+ return currentWorld;
129
+ }
130
+ };
131
+ }
132
+ // World subscription management
133
+ export async function subscribeWorld(worldIdentifier, client) {
134
+ try {
135
+ // Load world using core manager (convert to kebab-case internally)
136
+ const worldId = toKebabCase(worldIdentifier);
137
+ const currentWorld = await getWorld(worldId);
138
+ if (!currentWorld) {
139
+ if (client.onError) {
140
+ client.onError(`World not found: ${worldIdentifier}`);
141
+ }
142
+ return null;
143
+ }
144
+ // MCP servers will be started on-demand in getMCPToolsForWorld()
145
+ if (currentWorld.mcpConfig) {
146
+ logger.debug(`World ${worldId} has MCP config - servers will start on-demand`);
147
+ }
148
+ // Use startWorld function to create the subscription
149
+ const subscription = await startWorld(currentWorld, client);
150
+ // MCP servers use connection pooling and will be cleaned up automatically
151
+ // when the Express app shuts down
152
+ return subscription;
153
+ }
154
+ catch (error) {
155
+ logger.error('World subscription failed', {
156
+ worldIdentifier,
157
+ error: error instanceof Error ? error.message : error
158
+ });
159
+ if (client.onError) {
160
+ client.onError(`Failed to subscribe to world: ${error instanceof Error ? error.message : error}`);
161
+ }
162
+ return null;
163
+ }
164
+ }
165
+ // Set up event listeners for world events with client connection forwarding
166
+ export function setupWorldEventListeners(world, client) {
167
+ const listeners = new Map();
168
+ // System events
169
+ const systemListener = (eventData) => {
170
+ if (client.onWorldEvent) {
171
+ client.onWorldEvent('system', eventData);
172
+ }
173
+ };
174
+ world.eventEmitter.on('system', systemListener);
175
+ listeners.set('system', systemListener);
176
+ // Message events
177
+ const messageListener = (eventData) => {
178
+ if (client.onWorldEvent) {
179
+ client.onWorldEvent('message', eventData);
180
+ }
181
+ };
182
+ world.eventEmitter.on('message', messageListener);
183
+ listeners.set('message', messageListener);
184
+ // SSE events
185
+ const sseListener = (eventData) => {
186
+ if (client.onWorldEvent) {
187
+ client.onWorldEvent('sse', eventData);
188
+ }
189
+ };
190
+ world.eventEmitter.on('sse', sseListener);
191
+ listeners.set('sse', sseListener);
192
+ // World events (includes activity tracking)
193
+ // Note: 'world' channel receives WorldActivityEventPayload for activity tracking
194
+ const worldActivityListener = (eventData) => {
195
+ if (client.onWorldEvent) {
196
+ client.onWorldEvent('world', eventData);
197
+ }
198
+ };
199
+ world.eventEmitter.on('world', worldActivityListener);
200
+ listeners.set('world', worldActivityListener);
201
+ // Log streaming - set up if client has onLog callback
202
+ if (client.onLog) {
203
+ const logUnsubscribe = addLogStreamCallback((logEvent) => {
204
+ client.onLog(logEvent);
205
+ });
206
+ listeners.set('logStream', logUnsubscribe);
207
+ }
208
+ return listeners;
209
+ }
210
+ // Clean up world subscription and event listeners
211
+ export async function cleanupWorldSubscription(world, worldEventListeners) {
212
+ try {
213
+ // Remove all event listeners
214
+ for (const [eventType, listener] of worldEventListeners.entries()) {
215
+ world.eventEmitter.removeListener(eventType, listener);
216
+ }
217
+ worldEventListeners.clear();
218
+ logger.debug('World subscription cleanup completed', { worldId: world.id });
219
+ }
220
+ catch (error) {
221
+ logger.error('World subscription cleanup failed', {
222
+ worldId: world.id,
223
+ error: error instanceof Error ? error.message : error
224
+ });
225
+ }
226
+ }
227
+ //# sourceMappingURL=subscription.js.map