agent-world 0.12.2 → 0.13.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 (74) hide show
  1. package/README.md +15 -0
  2. package/dist/cli/hitl.d.ts +5 -1
  3. package/dist/cli/hitl.js +9 -3
  4. package/dist/cli/index.js +11 -9
  5. package/dist/core/activity-tracker.d.ts +12 -2
  6. package/dist/core/activity-tracker.d.ts.map +1 -1
  7. package/dist/core/activity-tracker.js +41 -5
  8. package/dist/core/activity-tracker.js.map +1 -1
  9. package/dist/core/create-agent-tool.d.ts +23 -25
  10. package/dist/core/create-agent-tool.d.ts.map +1 -1
  11. package/dist/core/create-agent-tool.js +241 -141
  12. package/dist/core/create-agent-tool.js.map +1 -1
  13. package/dist/core/events/memory-manager.js +1 -1
  14. package/dist/core/events/memory-manager.js.map +1 -1
  15. package/dist/core/events/orchestrator.d.ts.map +1 -1
  16. package/dist/core/events/orchestrator.js +14 -5
  17. package/dist/core/events/orchestrator.js.map +1 -1
  18. package/dist/core/events/persistence.d.ts +1 -1
  19. package/dist/core/events/persistence.d.ts.map +1 -1
  20. package/dist/core/events/persistence.js +1 -27
  21. package/dist/core/events/persistence.js.map +1 -1
  22. package/dist/core/events/publishers.d.ts +0 -9
  23. package/dist/core/events/publishers.d.ts.map +1 -1
  24. package/dist/core/events/publishers.js +10 -27
  25. package/dist/core/events/publishers.js.map +1 -1
  26. package/dist/core/events/subscribers.d.ts +1 -1
  27. package/dist/core/events/subscribers.d.ts.map +1 -1
  28. package/dist/core/events/subscribers.js +15 -7
  29. package/dist/core/events/subscribers.js.map +1 -1
  30. package/dist/core/hitl-tool.d.ts +79 -0
  31. package/dist/core/hitl-tool.d.ts.map +1 -0
  32. package/dist/core/hitl-tool.js +306 -0
  33. package/dist/core/hitl-tool.js.map +1 -0
  34. package/dist/core/hitl.d.ts +26 -6
  35. package/dist/core/hitl.d.ts.map +1 -1
  36. package/dist/core/hitl.js +82 -32
  37. package/dist/core/hitl.js.map +1 -1
  38. package/dist/core/index.d.ts +3 -2
  39. package/dist/core/index.d.ts.map +1 -1
  40. package/dist/core/index.js +3 -2
  41. package/dist/core/index.js.map +1 -1
  42. package/dist/core/llm-manager.d.ts +2 -0
  43. package/dist/core/llm-manager.d.ts.map +1 -1
  44. package/dist/core/llm-manager.js +16 -9
  45. package/dist/core/llm-manager.js.map +1 -1
  46. package/dist/core/managers.d.ts +24 -3
  47. package/dist/core/managers.d.ts.map +1 -1
  48. package/dist/core/managers.js +103 -52
  49. package/dist/core/managers.js.map +1 -1
  50. package/dist/core/mcp-server-registry.d.ts +3 -1
  51. package/dist/core/mcp-server-registry.d.ts.map +1 -1
  52. package/dist/core/mcp-server-registry.js +7 -1
  53. package/dist/core/mcp-server-registry.js.map +1 -1
  54. package/dist/core/tool-utils.d.ts +3 -1
  55. package/dist/core/tool-utils.d.ts.map +1 -1
  56. package/dist/core/tool-utils.js +55 -25
  57. package/dist/core/tool-utils.js.map +1 -1
  58. package/dist/core/types.d.ts +2 -17
  59. package/dist/core/types.d.ts.map +1 -1
  60. package/dist/core/types.js +0 -2
  61. package/dist/core/types.js.map +1 -1
  62. package/dist/core/utils.d.ts +9 -0
  63. package/dist/core/utils.d.ts.map +1 -1
  64. package/dist/core/utils.js +28 -3
  65. package/dist/core/utils.js.map +1 -1
  66. package/dist/public/assets/index-BW41BxMy.css +1 -0
  67. package/dist/public/assets/index-kO6UJFwK.js +96 -0
  68. package/dist/public/index.html +2 -2
  69. package/dist/server/api.js +29 -41
  70. package/dist/server/sse-handler.d.ts +3 -2
  71. package/dist/server/sse-handler.js +19 -11
  72. package/package.json +1 -1
  73. package/dist/public/assets/index-BO20H4xt.js +0 -96
  74. package/dist/public/assets/index-ETY7W5_S.css +0 -1
@@ -10,8 +10,8 @@
10
10
  <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
11
11
  <link rel="preload" as="style" href="https://fonts.googleapis.com/css2?family=Short+Stack&display=block">
12
12
  <link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Short+Stack&display=block">
13
- <script type="module" crossorigin src="/assets/index-BO20H4xt.js"></script>
14
- <link rel="stylesheet" crossorigin href="/assets/index-ETY7W5_S.css">
13
+ <script type="module" crossorigin src="/assets/index-kO6UJFwK.js"></script>
14
+ <link rel="stylesheet" crossorigin href="/assets/index-BW41BxMy.css">
15
15
  </head>
16
16
 
17
17
  <body class="doodle">
@@ -5,7 +5,7 @@
5
5
  * Supports world/agent/chat management with optimized serialization and error handling.
6
6
  *
7
7
  * Changes:
8
- * - 2026-02-19: Added chat branch endpoint `POST /worlds/:worldName/chats/:chatId/branch/:messageId` for web branching UX.
8
+ * - 2026-02-20: Enforced options-only HITL response endpoint `POST /worlds/:worldName/hitl/respond` (`optionId` required).
9
9
  * - 2026-02-14: Added HITL option response endpoint `POST /worlds/:worldName/hitl/respond` for web/CLI approval submissions.
10
10
  * - 2026-02-13: Added core-managed message edit endpoint `PUT /worlds/:worldName/messages/:messageId`
11
11
  * - Delegates edit/remove/resubmit flow to `core.editUserMessage` for cross-client consistency
@@ -51,7 +51,7 @@ import { z } from 'zod';
51
51
  import { createSSEHandler } from './sse-handler.js';
52
52
  import { createWorld, listWorlds, createCategoryLogger, publishMessage, enableStreaming, disableStreaming,
53
53
  // core managers (function-based)
54
- getWorld, updateWorld, deleteWorld, createAgent, getAgent, updateAgent, deleteAgent, listChats, newChat, restoreChat, deleteChat as deleteChatCore, clearAgentMemory, listAgents as listAgentsCore, getMemory as coreGetMemory, exportWorldToMarkdown, removeMessagesFrom, branchChatFromMessage, editUserMessage, stopMessageProcessing, submitWorldOptionResponse, EventType } from '../core/index.js';
54
+ getWorld, updateWorld, deleteWorld, createAgent, getAgent, updateAgent, deleteAgent, listChats, newChat, restoreChat, deleteChat as deleteChatCore, clearAgentMemory, listAgents as listAgentsCore, getMemory as coreGetMemory, exportWorldToMarkdown, removeMessagesFrom, editUserMessage, stopMessageProcessing, submitWorldHitlResponse, EventType } from '../core/index.js';
55
55
  import { subscribeWorld } from '../core/index.js';
56
56
  import { listMCPServers, restartMCPServer, getMCPSystemHealth, getMCPRegistryStats } from '../core/mcp-server-registry.js';
57
57
  // Function-specific loggers for granular debugging control
@@ -692,11 +692,18 @@ async function handleStreamingChat(req, res, worldName, message, sender, chatId)
692
692
  const world = subscription.world;
693
693
  // Create SSE handler - automatically sets up headers, listeners, and cleanup
694
694
  const sseHandler = createSSEHandler(req, res, world, 'chat', chatId);
695
- // Clean up subscription when the HTTP response finishes to prevent stale world
695
+ // Clean up subscription when the HTTP response closes/finishes to prevent stale world
696
696
  // instances from accumulating in activeSubscribedWorlds.
697
- res.on('finish', () => {
698
- subscription?.unsubscribe();
699
- });
697
+ let subscriptionCleanedUp = false;
698
+ const cleanupSubscription = () => {
699
+ if (subscriptionCleanedUp) {
700
+ return;
701
+ }
702
+ subscriptionCleanedUp = true;
703
+ void subscription.unsubscribe();
704
+ };
705
+ res.on('finish', cleanupSubscription);
706
+ res.on('close', cleanupSubscription);
700
707
  try {
701
708
  // Publish message - events will be automatically streamed
702
709
  publishMessage(world, message, sender, chatId);
@@ -801,6 +808,14 @@ router.put('/worlds/:worldName/messages/:messageId', validateWorld, async (req,
801
808
  return;
802
809
  }
803
810
  const sseHandler = createSSEHandler(req, res, subscription.world, 'edit', chatId);
811
+ let subscriptionCleanedUp = false;
812
+ const cleanupSubscription = () => {
813
+ if (subscriptionCleanedUp) {
814
+ return;
815
+ }
816
+ subscriptionCleanedUp = true;
817
+ void subscription.unsubscribe();
818
+ };
804
819
  const finalizeWithError = (message, data) => {
805
820
  sseHandler.sendSSE({
806
821
  type: 'error',
@@ -809,13 +824,12 @@ router.put('/worlds/:worldName/messages/:messageId', validateWorld, async (req,
809
824
  });
810
825
  setTimeout(() => {
811
826
  sseHandler.endResponse();
812
- subscription?.unsubscribe();
827
+ cleanupSubscription();
813
828
  }, 500);
814
829
  };
815
- // Clean up subscription when the HTTP response finishes.
816
- res.on('finish', () => {
817
- subscription?.unsubscribe();
818
- });
830
+ // Clean up subscription when the HTTP response closes/finishes.
831
+ res.on('finish', cleanupSubscription);
832
+ res.on('close', cleanupSubscription);
819
833
  // Pass subscription.world so editUserMessage emits on the same eventEmitter
820
834
  // that the SSE handler is listening on, avoiding stale-world mismatch.
821
835
  const result = await editUserMessage(worldCtx.id, messageId, newContent, chatId, subscription.world);
@@ -921,11 +935,12 @@ router.post('/worlds/:worldName/hitl/respond', validateWorld, async (req, res) =
921
935
  return;
922
936
  }
923
937
  const worldCtx = req.worldCtx;
924
- const { requestId, optionId } = validation.data;
925
- const result = submitWorldOptionResponse({
938
+ const { requestId, optionId, chatId } = validation.data;
939
+ const result = submitWorldHitlResponse({
926
940
  worldId: worldCtx.id,
927
941
  requestId,
928
- optionId
942
+ optionId,
943
+ ...(chatId !== undefined ? { chatId } : {}),
929
944
  });
930
945
  res.json(result);
931
946
  }
@@ -1016,33 +1031,6 @@ router.post('/worlds/:worldName/chats', validateWorld, async (req, res) => {
1016
1031
  sendError(res, 500, 'Failed to create new chat', 'NEW_CHAT_ERROR');
1017
1032
  }
1018
1033
  });
1019
- router.post('/worlds/:worldName/chats/:chatId/branch/:messageId', validateWorld, async (req, res) => {
1020
- try {
1021
- const { chatId, messageId } = req.params;
1022
- const worldCtx = req.worldCtx;
1023
- if (!(await chatExists(worldCtx, chatId))) {
1024
- sendError(res, 404, 'Chat not found', 'CHAT_NOT_FOUND');
1025
- return;
1026
- }
1027
- const result = await branchChatFromMessage(worldCtx.id, chatId, messageId);
1028
- res.json({
1029
- success: true,
1030
- world: serializeWorld(result.world),
1031
- chatId: result.newChatId,
1032
- copiedMessageCount: result.copiedMessageCount,
1033
- });
1034
- }
1035
- catch (error) {
1036
- const errorMessage = error instanceof Error ? error.message : String(error);
1037
- const isNotFound = errorMessage.includes('not found');
1038
- const isClientValidationError = errorMessage.includes('required') ||
1039
- errorMessage.includes('Can only branch from assistant messages.') ||
1040
- errorMessage.includes('Message not found in source chat');
1041
- const status = isNotFound ? 404 : (isClientValidationError ? 400 : 500);
1042
- const code = isNotFound ? 'CHAT_BRANCH_NOT_FOUND' : 'CHAT_BRANCH_ERROR';
1043
- sendError(res, status, errorMessage || 'Failed to branch chat', code);
1044
- }
1045
- });
1046
1034
  router.post('/worlds/:worldName/setChat/:chatId', validateWorld, async (req, res) => {
1047
1035
  try {
1048
1036
  const { chatId } = req.params;
@@ -5,10 +5,9 @@
5
5
  *
6
6
  * Features:
7
7
  * - Sets up SSE response headers and connection
8
- * - Wires world event listeners (MESSAGE, SSE, SYSTEM, WORLD, CRUD)
8
+ * - Wires world event listeners (MESSAGE, SSE, SYSTEM, WORLD)
9
9
  * - Handles world activity state tracking (response-start, idle)
10
10
  * - Forwards tool events (tool-start, tool-result, tool-error, tool-progress) as SSE events
11
- * - Forwards CRUD events so frontends can refresh world/agent state in real time
12
11
  * - Automatic stream completion when world becomes idle
13
12
  * - Timeout fallback (60s) if world never becomes idle
14
13
  * - Proper cleanup on client disconnect or stream end
@@ -30,6 +29,8 @@
30
29
  * ```
31
30
  *
32
31
  * Created: 2025-11-10 - Extracted from api.ts for reusability
32
+ * Updated: 2026-02-20 - Removed stale legacy event-channel SSE forwarding from this handler.
33
+ * Updated: 2026-02-20 - Keep `hitl-option-request` system events bypassing strict chat scope filtering so HITL prompts are always delivered.
33
34
  * Updated: 2026-02-11 - Extended fallback timeout on tool-stream events to prevent premature timeout
34
35
  * Updated: 2026-02-08 - Removed manual tool-intervention SSE commentary and kept generic tool_call forwarding
35
36
  * Updated: 2025-11-10 - Added tool event forwarding to SSE channel
@@ -5,10 +5,9 @@
5
5
  *
6
6
  * Features:
7
7
  * - Sets up SSE response headers and connection
8
- * - Wires world event listeners (MESSAGE, SSE, SYSTEM, WORLD, CRUD)
8
+ * - Wires world event listeners (MESSAGE, SSE, SYSTEM, WORLD)
9
9
  * - Handles world activity state tracking (response-start, idle)
10
10
  * - Forwards tool events (tool-start, tool-result, tool-error, tool-progress) as SSE events
11
- * - Forwards CRUD events so frontends can refresh world/agent state in real time
12
11
  * - Automatic stream completion when world becomes idle
13
12
  * - Timeout fallback (60s) if world never becomes idle
14
13
  * - Proper cleanup on client disconnect or stream end
@@ -30,6 +29,8 @@
30
29
  * ```
31
30
  *
32
31
  * Created: 2025-11-10 - Extracted from api.ts for reusability
32
+ * Updated: 2026-02-20 - Removed stale legacy event-channel SSE forwarding from this handler.
33
+ * Updated: 2026-02-20 - Keep `hitl-option-request` system events bypassing strict chat scope filtering so HITL prompts are always delivered.
33
34
  * Updated: 2026-02-11 - Extended fallback timeout on tool-stream events to prevent premature timeout
34
35
  * Updated: 2026-02-08 - Removed manual tool-intervention SSE commentary and kept generic tool_call forwarding
35
36
  * Updated: 2025-11-10 - Added tool event forwarding to SSE channel
@@ -123,6 +124,20 @@ export function createSSEHandler(req, res, world, context = 'sse', scopedChatId)
123
124
  const normalizedEventChatId = eventChatId === null ? null : String(eventChatId);
124
125
  return normalizedEventChatId === normalizedScopedChatId;
125
126
  };
127
+ const isHitlRequestEvent = (eventData) => {
128
+ if (!eventData)
129
+ return false;
130
+ const content = eventData.content;
131
+ if (content && typeof content === 'object') {
132
+ const eventType = String(content.eventType || '').trim();
133
+ return eventType === 'hitl-option-request';
134
+ }
135
+ if (typeof content === 'string') {
136
+ const eventType = content.trim();
137
+ return eventType === 'hitl-option-request';
138
+ }
139
+ return false;
140
+ };
126
141
  // Attach direct listeners to world.eventEmitter
127
142
  const worldListener = (eventData) => {
128
143
  // Check if this is a tool event (tool-start, tool-result, tool-error, tool-progress)
@@ -205,21 +220,14 @@ export function createSSEHandler(req, res, world, context = 'sse', scopedChatId)
205
220
  world.eventEmitter.on(EventType.SSE, sseListener);
206
221
  listeners.set(EventType.SSE, sseListener);
207
222
  const systemListener = (eventData) => {
208
- if (!isChatEventInScope(eventData?.chatId, true)) {
223
+ const isHitlRequest = isHitlRequestEvent(eventData);
224
+ if (!isHitlRequest && !isChatEventInScope(eventData?.chatId, true)) {
209
225
  return;
210
226
  }
211
227
  sendSSE({ type: EventType.SYSTEM, data: eventData });
212
228
  };
213
229
  world.eventEmitter.on(EventType.SYSTEM, systemListener);
214
230
  listeners.set(EventType.SYSTEM, systemListener);
215
- const crudListener = (eventData) => {
216
- if (!isChatEventInScope(eventData?.chatId, true)) {
217
- return;
218
- }
219
- sendSSE({ type: EventType.CRUD, data: eventData });
220
- };
221
- world.eventEmitter.on(EventType.CRUD, crudListener);
222
- listeners.set(EventType.CRUD, crudListener);
223
231
  // Cleanup function to remove all listeners
224
232
  const cleanupListeners = () => {
225
233
  for (const [eventType, listener] of listeners.entries()) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "agent-world",
3
- "version": "0.12.2",
3
+ "version": "0.13.0",
4
4
  "main": "dist/index.js",
5
5
  "types": "dist/index.d.ts",
6
6
  "exports": {