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.
- package/README.md +17 -7
- package/dist/cli/commands.d.ts +109 -0
- package/dist/cli/commands.js +2024 -0
- package/dist/cli/display.d.ts +124 -0
- package/dist/cli/display.js +381 -0
- package/dist/cli/hitl.d.ts +33 -0
- package/dist/cli/hitl.js +81 -0
- package/dist/cli/index.d.ts +2 -0
- package/dist/cli/stream.d.ts +41 -0
- package/dist/cli/stream.js +222 -0
- package/dist/core/activity-tracker.d.ts +16 -0
- package/dist/core/activity-tracker.d.ts.map +1 -0
- package/dist/core/activity-tracker.js +91 -0
- package/dist/core/activity-tracker.js.map +1 -0
- package/dist/core/ai-commands.d.ts +16 -0
- package/dist/core/ai-commands.d.ts.map +1 -0
- package/dist/core/ai-commands.js +24 -0
- package/dist/core/ai-commands.js.map +1 -0
- package/dist/core/ai-sdk-patch.d.ts +24 -0
- package/dist/core/ai-sdk-patch.d.ts.map +1 -0
- package/dist/core/ai-sdk-patch.js +169 -0
- package/dist/core/ai-sdk-patch.js.map +1 -0
- package/dist/core/anthropic-direct.d.ts +52 -0
- package/dist/core/anthropic-direct.d.ts.map +1 -0
- package/dist/core/anthropic-direct.js +301 -0
- package/dist/core/anthropic-direct.js.map +1 -0
- package/dist/core/approval-cache.d.ts +104 -0
- package/dist/core/approval-cache.d.ts.map +1 -0
- package/dist/core/approval-cache.js +150 -0
- package/dist/core/approval-cache.js.map +1 -0
- package/dist/core/chat-constants.d.ts +20 -0
- package/dist/core/chat-constants.d.ts.map +1 -0
- package/dist/core/chat-constants.js +22 -0
- package/dist/core/chat-constants.js.map +1 -0
- package/dist/core/create-agent-tool.d.ts +66 -0
- package/dist/core/create-agent-tool.d.ts.map +1 -0
- package/dist/core/create-agent-tool.js +212 -0
- package/dist/core/create-agent-tool.js.map +1 -0
- package/dist/core/events/approval-checker.d.ts +61 -0
- package/dist/core/events/approval-checker.d.ts.map +1 -0
- package/dist/core/events/approval-checker.js +226 -0
- package/dist/core/events/approval-checker.js.map +1 -0
- package/dist/core/events/index.d.ts +25 -0
- package/dist/core/events/index.d.ts.map +1 -0
- package/dist/core/events/index.js +30 -0
- package/dist/core/events/index.js.map +1 -0
- package/dist/core/events/memory-manager.d.ts +73 -0
- package/dist/core/events/memory-manager.d.ts.map +1 -0
- package/dist/core/events/memory-manager.js +1218 -0
- package/dist/core/events/memory-manager.js.map +1 -0
- package/dist/core/events/mention-logic.d.ts +39 -0
- package/dist/core/events/mention-logic.d.ts.map +1 -0
- package/dist/core/events/mention-logic.js +163 -0
- package/dist/core/events/mention-logic.js.map +1 -0
- package/dist/core/events/orchestrator.d.ts +69 -0
- package/dist/core/events/orchestrator.d.ts.map +1 -0
- package/dist/core/events/orchestrator.js +883 -0
- package/dist/core/events/orchestrator.js.map +1 -0
- package/dist/core/events/persistence.d.ts +41 -0
- package/dist/core/events/persistence.d.ts.map +1 -0
- package/dist/core/events/persistence.js +296 -0
- package/dist/core/events/persistence.js.map +1 -0
- package/dist/core/events/publishers.d.ts +81 -0
- package/dist/core/events/publishers.d.ts.map +1 -0
- package/dist/core/events/publishers.js +272 -0
- package/dist/core/events/publishers.js.map +1 -0
- package/dist/core/events/subscribers.d.ts +45 -0
- package/dist/core/events/subscribers.d.ts.map +1 -0
- package/dist/core/events/subscribers.js +288 -0
- package/dist/core/events/subscribers.js.map +1 -0
- package/dist/core/events/tool-bridge-logging.d.ts +28 -0
- package/dist/core/events/tool-bridge-logging.d.ts.map +1 -0
- package/dist/core/events/tool-bridge-logging.js +94 -0
- package/dist/core/events/tool-bridge-logging.js.map +1 -0
- package/dist/core/events-metadata.d.ts +72 -0
- package/dist/core/events-metadata.d.ts.map +1 -0
- package/dist/core/events-metadata.js +167 -0
- package/dist/core/events-metadata.js.map +1 -0
- package/dist/core/events.d.ts +186 -0
- package/dist/core/events.d.ts.map +1 -0
- package/dist/core/events.js +1248 -0
- package/dist/core/events.js.map +1 -0
- package/dist/core/export.d.ts +106 -0
- package/dist/core/export.d.ts.map +1 -0
- package/dist/core/export.js +705 -0
- package/dist/core/export.js.map +1 -0
- package/dist/core/file-tools.d.ts +114 -0
- package/dist/core/file-tools.d.ts.map +1 -0
- package/dist/core/file-tools.js +370 -0
- package/dist/core/file-tools.js.map +1 -0
- package/dist/core/google-direct.d.ts +58 -0
- package/dist/core/google-direct.d.ts.map +1 -0
- package/dist/core/google-direct.js +298 -0
- package/dist/core/google-direct.js.map +1 -0
- package/dist/core/hitl.d.ts +54 -0
- package/dist/core/hitl.d.ts.map +1 -0
- package/dist/core/hitl.js +153 -0
- package/dist/core/hitl.js.map +1 -0
- package/dist/core/index.d.ts +59 -0
- package/dist/core/index.d.ts.map +1 -0
- package/dist/core/index.js +70 -0
- package/dist/core/index.js.map +1 -0
- package/dist/core/llm-config.d.ts +128 -0
- package/dist/core/llm-config.d.ts.map +1 -0
- package/dist/core/llm-config.js +164 -0
- package/dist/core/llm-config.js.map +1 -0
- package/dist/core/llm-manager.d.ts +163 -0
- package/dist/core/llm-manager.d.ts.map +1 -0
- package/dist/core/llm-manager.js +669 -0
- package/dist/core/llm-manager.js.map +1 -0
- package/dist/core/load-skill-tool.d.ts +55 -0
- package/dist/core/load-skill-tool.d.ts.map +1 -0
- package/dist/core/load-skill-tool.js +468 -0
- package/dist/core/load-skill-tool.js.map +1 -0
- package/dist/core/logger.d.ts +88 -0
- package/dist/core/logger.d.ts.map +1 -0
- package/dist/core/logger.js +358 -0
- package/dist/core/logger.js.map +1 -0
- package/dist/core/managers.d.ts +131 -0
- package/dist/core/managers.d.ts.map +1 -0
- package/dist/core/managers.js +1223 -0
- package/dist/core/managers.js.map +1 -0
- package/dist/core/mcp-server-registry.d.ts +304 -0
- package/dist/core/mcp-server-registry.d.ts.map +1 -0
- package/dist/core/mcp-server-registry.js +1769 -0
- package/dist/core/mcp-server-registry.js.map +1 -0
- package/dist/core/mcp-tools.d.ts +56 -0
- package/dist/core/mcp-tools.d.ts.map +1 -0
- package/dist/core/mcp-tools.js +186 -0
- package/dist/core/mcp-tools.js.map +1 -0
- package/dist/core/message-prep.d.ts +81 -0
- package/dist/core/message-prep.d.ts.map +1 -0
- package/dist/core/message-prep.js +223 -0
- package/dist/core/message-prep.js.map +1 -0
- package/dist/core/message-processing-control.d.ts +54 -0
- package/dist/core/message-processing-control.d.ts.map +1 -0
- package/dist/core/message-processing-control.js +139 -0
- package/dist/core/message-processing-control.js.map +1 -0
- package/dist/core/openai-direct.d.ts +80 -0
- package/dist/core/openai-direct.d.ts.map +1 -0
- package/dist/core/openai-direct.js +374 -0
- package/dist/core/openai-direct.js.map +1 -0
- package/dist/core/shell-cmd-tool.d.ts +235 -0
- package/dist/core/shell-cmd-tool.d.ts.map +1 -0
- package/dist/core/shell-cmd-tool.js +1157 -0
- package/dist/core/shell-cmd-tool.js.map +1 -0
- package/dist/core/shell-process-registry.d.ts +88 -0
- package/dist/core/shell-process-registry.d.ts.map +1 -0
- package/dist/core/shell-process-registry.js +309 -0
- package/dist/core/shell-process-registry.js.map +1 -0
- package/dist/core/skill-registry.d.ts +75 -0
- package/dist/core/skill-registry.d.ts.map +1 -0
- package/dist/core/skill-registry.js +369 -0
- package/dist/core/skill-registry.js.map +1 -0
- package/dist/core/skill-script-runner.d.ts +89 -0
- package/dist/core/skill-script-runner.d.ts.map +1 -0
- package/dist/core/skill-script-runner.js +274 -0
- package/dist/core/skill-script-runner.js.map +1 -0
- package/dist/core/skill-selector.d.ts +65 -0
- package/dist/core/skill-selector.d.ts.map +1 -0
- package/dist/core/skill-selector.js +190 -0
- package/dist/core/skill-selector.js.map +1 -0
- package/dist/core/skill-settings.d.ts +20 -0
- package/dist/core/skill-settings.d.ts.map +1 -0
- package/dist/core/skill-settings.js +40 -0
- package/dist/core/skill-settings.js.map +1 -0
- package/dist/core/storage/agent-storage.d.ts +134 -0
- package/dist/core/storage/agent-storage.d.ts.map +1 -0
- package/dist/core/storage/agent-storage.js +498 -0
- package/dist/core/storage/agent-storage.js.map +1 -0
- package/dist/core/storage/eventStorage/fileEventStorage.d.ts +100 -0
- package/dist/core/storage/eventStorage/fileEventStorage.d.ts.map +1 -0
- package/dist/core/storage/eventStorage/fileEventStorage.js +494 -0
- package/dist/core/storage/eventStorage/fileEventStorage.js.map +1 -0
- package/dist/core/storage/eventStorage/index.d.ts +31 -0
- package/dist/core/storage/eventStorage/index.d.ts.map +1 -0
- package/dist/core/storage/eventStorage/index.js +31 -0
- package/dist/core/storage/eventStorage/index.js.map +1 -0
- package/dist/core/storage/eventStorage/memoryEventStorage.d.ts +87 -0
- package/dist/core/storage/eventStorage/memoryEventStorage.d.ts.map +1 -0
- package/dist/core/storage/eventStorage/memoryEventStorage.js +244 -0
- package/dist/core/storage/eventStorage/memoryEventStorage.js.map +1 -0
- package/dist/core/storage/eventStorage/sqliteEventStorage.d.ts +45 -0
- package/dist/core/storage/eventStorage/sqliteEventStorage.d.ts.map +1 -0
- package/dist/core/storage/eventStorage/sqliteEventStorage.js +301 -0
- package/dist/core/storage/eventStorage/sqliteEventStorage.js.map +1 -0
- package/dist/core/storage/eventStorage/types.d.ts +142 -0
- package/dist/core/storage/eventStorage/types.d.ts.map +1 -0
- package/dist/core/storage/eventStorage/types.js +43 -0
- package/dist/core/storage/eventStorage/types.js.map +1 -0
- package/dist/core/storage/eventStorage/validation.d.ts +30 -0
- package/dist/core/storage/eventStorage/validation.d.ts.map +1 -0
- package/dist/core/storage/eventStorage/validation.js +68 -0
- package/dist/core/storage/eventStorage/validation.js.map +1 -0
- package/dist/core/storage/legacy-migrations.d.ts +45 -0
- package/dist/core/storage/legacy-migrations.d.ts.map +1 -0
- package/dist/core/storage/legacy-migrations.js +295 -0
- package/dist/core/storage/legacy-migrations.js.map +1 -0
- package/dist/core/storage/memory-storage.d.ts +105 -0
- package/dist/core/storage/memory-storage.d.ts.map +1 -0
- package/dist/core/storage/memory-storage.js +415 -0
- package/dist/core/storage/memory-storage.js.map +1 -0
- package/dist/core/storage/migration-runner.d.ts +96 -0
- package/dist/core/storage/migration-runner.d.ts.map +1 -0
- package/dist/core/storage/migration-runner.js +306 -0
- package/dist/core/storage/migration-runner.js.map +1 -0
- package/dist/core/storage/queue-storage.d.ts +147 -0
- package/dist/core/storage/queue-storage.d.ts.map +1 -0
- package/dist/core/storage/queue-storage.js +290 -0
- package/dist/core/storage/queue-storage.js.map +1 -0
- package/dist/core/storage/skill-storage.d.ts +136 -0
- package/dist/core/storage/skill-storage.d.ts.map +1 -0
- package/dist/core/storage/skill-storage.js +474 -0
- package/dist/core/storage/skill-storage.js.map +1 -0
- package/dist/core/storage/sqlite-schema.d.ts +95 -0
- package/dist/core/storage/sqlite-schema.d.ts.map +1 -0
- package/dist/core/storage/sqlite-schema.js +156 -0
- package/dist/core/storage/sqlite-schema.js.map +1 -0
- package/dist/core/storage/sqlite-storage.d.ts +146 -0
- package/dist/core/storage/sqlite-storage.d.ts.map +1 -0
- package/dist/core/storage/sqlite-storage.js +709 -0
- package/dist/core/storage/sqlite-storage.js.map +1 -0
- package/dist/core/storage/storage-factory.d.ts +61 -0
- package/dist/core/storage/storage-factory.d.ts.map +1 -0
- package/dist/core/storage/storage-factory.js +794 -0
- package/dist/core/storage/storage-factory.js.map +1 -0
- package/dist/core/storage/validation.d.ts +36 -0
- package/dist/core/storage/validation.d.ts.map +1 -0
- package/dist/core/storage/validation.js +79 -0
- package/dist/core/storage/validation.js.map +1 -0
- package/dist/core/storage/world-storage.d.ts +114 -0
- package/dist/core/storage/world-storage.d.ts.map +1 -0
- package/dist/core/storage/world-storage.js +378 -0
- package/dist/core/storage/world-storage.js.map +1 -0
- package/dist/core/subscription.d.ts +43 -0
- package/dist/core/subscription.d.ts.map +1 -0
- package/dist/core/subscription.js +227 -0
- package/dist/core/subscription.js.map +1 -0
- package/dist/core/tool-utils.d.ts +80 -0
- package/dist/core/tool-utils.d.ts.map +1 -0
- package/dist/core/tool-utils.js +273 -0
- package/dist/core/tool-utils.js.map +1 -0
- package/dist/core/types.d.ts +595 -0
- package/dist/core/types.d.ts.map +1 -0
- package/dist/core/types.js +158 -0
- package/dist/core/types.js.map +1 -0
- package/dist/core/utils.d.ts +138 -0
- package/dist/core/utils.d.ts.map +1 -0
- package/dist/core/utils.js +478 -0
- package/dist/core/utils.js.map +1 -0
- package/dist/core/world-class.d.ts +43 -0
- package/dist/core/world-class.d.ts.map +1 -0
- package/dist/core/world-class.js +90 -0
- package/dist/core/world-class.js.map +1 -0
- package/dist/index.d.ts +18 -0
- package/dist/public/assets/agent-sprites-DJFgj-zP.png +0 -0
- package/dist/public/assets/border-KHK37r8y.svg +83 -0
- package/dist/public/assets/index-C9kPXL6G.css +1 -0
- package/dist/public/assets/index-DOQEHGWt.js +96 -0
- package/dist/public/index.html +21 -0
- package/dist/server/api.d.ts +2 -0
- package/dist/server/api.js +1124 -0
- package/dist/server/index.d.ts +29 -0
- package/dist/server/sse-handler.d.ts +62 -0
- package/dist/server/sse-handler.js +234 -0
- package/package.json +15 -3
- package/scripts/launch-electron.js +0 -58
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* Web Server - Express.js HTTP Server with REST API and SSE
|
|
4
|
+
*
|
|
5
|
+
* Features:
|
|
6
|
+
* - Express server with CORS, static files, and modular API routing
|
|
7
|
+
* - Environment-based LLM provider configuration
|
|
8
|
+
* - Category-based logging with configurable levels
|
|
9
|
+
* - Health check endpoint and proper error handling
|
|
10
|
+
* - Environment Variables: Automatically loads .env file for API keys and configuration
|
|
11
|
+
* - Controlled startup behavior for direct execution vs imported usage
|
|
12
|
+
* - Optional browser auto-open and process signal handler registration
|
|
13
|
+
*
|
|
14
|
+
* Configuration: AGENT_WORLD_DATA_PATH, LOG_LEVEL, LLM provider keys
|
|
15
|
+
* Endpoints: /health + API routes from ./api.ts
|
|
16
|
+
*
|
|
17
|
+
* Recent Changes:
|
|
18
|
+
* - 2026-02-08: Fixed auto-run detection to only trigger on direct execution
|
|
19
|
+
* - 2026-02-08: Made browser auto-open configurable via AGENT_WORLD_AUTO_OPEN env var
|
|
20
|
+
* - 2026-02-08: Prevented duplicate process signal handler registration using WeakSet
|
|
21
|
+
* - 2026-02-08: Added shutdown guard to prevent race conditions during graceful shutdown
|
|
22
|
+
*/
|
|
23
|
+
import { Server } from 'http';
|
|
24
|
+
type StartWebServerOptions = {
|
|
25
|
+
openBrowser?: boolean;
|
|
26
|
+
registerProcessHandlers?: boolean;
|
|
27
|
+
};
|
|
28
|
+
export declare function startWebServer(port?: number, host?: string, options?: StartWebServerOptions): Promise<Server>;
|
|
29
|
+
export {};
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SSE Event Handler - Reusable Server-Sent Events Logic
|
|
3
|
+
*
|
|
4
|
+
* Purpose: Centralized SSE streaming logic for world events
|
|
5
|
+
*
|
|
6
|
+
* Features:
|
|
7
|
+
* - Sets up SSE response headers and connection
|
|
8
|
+
* - Wires world event listeners (MESSAGE, SSE, SYSTEM, WORLD)
|
|
9
|
+
* - Handles world activity state tracking (response-start, idle)
|
|
10
|
+
* - Forwards tool events (tool-start, tool-result, tool-error, tool-progress) as SSE events
|
|
11
|
+
* - Automatic stream completion when world becomes idle
|
|
12
|
+
* - Timeout fallback (60s) if world never becomes idle
|
|
13
|
+
* - Proper cleanup on client disconnect or stream end
|
|
14
|
+
*
|
|
15
|
+
* Event Routing:
|
|
16
|
+
* - 'world' channel carries both WorldActivityEvent and WorldToolEvent types
|
|
17
|
+
* - WorldActivityEvent (response-start, idle, response-end) → manages stream lifecycle
|
|
18
|
+
* - WorldToolEvent (tool-start, tool-result, tool-error, tool-progress) → forwarded as SSE events
|
|
19
|
+
*
|
|
20
|
+
* Usage:
|
|
21
|
+
* ```typescript
|
|
22
|
+
* const handler = createSSEHandler(req, res, world, 'chat');
|
|
23
|
+
*
|
|
24
|
+
* // Publish your event (message, tool result, etc.)
|
|
25
|
+
* publishMessage(world, message, sender);
|
|
26
|
+
*
|
|
27
|
+
* // Optional: Send custom event
|
|
28
|
+
* handler.sendSSE({ type: 'custom', data: {...} });
|
|
29
|
+
* ```
|
|
30
|
+
*
|
|
31
|
+
* Created: 2025-11-10 - Extracted from api.ts for reusability
|
|
32
|
+
* Updated: 2026-02-11 - Extended fallback timeout on tool-stream events to prevent premature timeout
|
|
33
|
+
* Updated: 2026-02-08 - Removed manual tool-intervention SSE commentary and kept generic tool_call forwarding
|
|
34
|
+
* Updated: 2025-11-10 - Added tool event forwarding to SSE channel
|
|
35
|
+
*/
|
|
36
|
+
import { Request, Response } from 'express';
|
|
37
|
+
import { World } from '../core/index.js';
|
|
38
|
+
export interface SSEHandler {
|
|
39
|
+
/**
|
|
40
|
+
* Send a Server-Sent Event to the client
|
|
41
|
+
* @param data - Data object to send (will be JSON stringified)
|
|
42
|
+
*/
|
|
43
|
+
sendSSE: (data: any) => void;
|
|
44
|
+
/**
|
|
45
|
+
* Manually end the SSE response
|
|
46
|
+
*/
|
|
47
|
+
endResponse: () => void;
|
|
48
|
+
/**
|
|
49
|
+
* Check if the response has ended
|
|
50
|
+
*/
|
|
51
|
+
isEnded: () => boolean;
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Create and configure an SSE handler for streaming world events
|
|
55
|
+
*
|
|
56
|
+
* @param req - Express request object
|
|
57
|
+
* @param res - Express response object
|
|
58
|
+
* @param world - World instance to listen to
|
|
59
|
+
* @param context - Context label for logging (e.g., 'chat', 'tool-result')
|
|
60
|
+
* @returns SSEHandler interface with sendSSE, endResponse, and isEnded methods
|
|
61
|
+
*/
|
|
62
|
+
export declare function createSSEHandler(req: Request, res: Response, world: World, context?: string, scopedChatId?: string | null): SSEHandler;
|
|
@@ -0,0 +1,234 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SSE Event Handler - Reusable Server-Sent Events Logic
|
|
3
|
+
*
|
|
4
|
+
* Purpose: Centralized SSE streaming logic for world events
|
|
5
|
+
*
|
|
6
|
+
* Features:
|
|
7
|
+
* - Sets up SSE response headers and connection
|
|
8
|
+
* - Wires world event listeners (MESSAGE, SSE, SYSTEM, WORLD)
|
|
9
|
+
* - Handles world activity state tracking (response-start, idle)
|
|
10
|
+
* - Forwards tool events (tool-start, tool-result, tool-error, tool-progress) as SSE events
|
|
11
|
+
* - Automatic stream completion when world becomes idle
|
|
12
|
+
* - Timeout fallback (60s) if world never becomes idle
|
|
13
|
+
* - Proper cleanup on client disconnect or stream end
|
|
14
|
+
*
|
|
15
|
+
* Event Routing:
|
|
16
|
+
* - 'world' channel carries both WorldActivityEvent and WorldToolEvent types
|
|
17
|
+
* - WorldActivityEvent (response-start, idle, response-end) → manages stream lifecycle
|
|
18
|
+
* - WorldToolEvent (tool-start, tool-result, tool-error, tool-progress) → forwarded as SSE events
|
|
19
|
+
*
|
|
20
|
+
* Usage:
|
|
21
|
+
* ```typescript
|
|
22
|
+
* const handler = createSSEHandler(req, res, world, 'chat');
|
|
23
|
+
*
|
|
24
|
+
* // Publish your event (message, tool result, etc.)
|
|
25
|
+
* publishMessage(world, message, sender);
|
|
26
|
+
*
|
|
27
|
+
* // Optional: Send custom event
|
|
28
|
+
* handler.sendSSE({ type: 'custom', data: {...} });
|
|
29
|
+
* ```
|
|
30
|
+
*
|
|
31
|
+
* Created: 2025-11-10 - Extracted from api.ts for reusability
|
|
32
|
+
* Updated: 2026-02-11 - Extended fallback timeout on tool-stream events to prevent premature timeout
|
|
33
|
+
* Updated: 2026-02-08 - Removed manual tool-intervention SSE commentary and kept generic tool_call forwarding
|
|
34
|
+
* Updated: 2025-11-10 - Added tool event forwarding to SSE channel
|
|
35
|
+
*/
|
|
36
|
+
import { createCategoryLogger, EventType } from '../core/index.js';
|
|
37
|
+
const loggerStream = createCategoryLogger('api.stream');
|
|
38
|
+
// Timeout constants for streaming (fallback only)
|
|
39
|
+
const STREAM_TIMEOUT_NO_EVENTS_MS = 15000;
|
|
40
|
+
/**
|
|
41
|
+
* Create and configure an SSE handler for streaming world events
|
|
42
|
+
*
|
|
43
|
+
* @param req - Express request object
|
|
44
|
+
* @param res - Express response object
|
|
45
|
+
* @param world - World instance to listen to
|
|
46
|
+
* @param context - Context label for logging (e.g., 'chat', 'tool-result')
|
|
47
|
+
* @returns SSEHandler interface with sendSSE, endResponse, and isEnded methods
|
|
48
|
+
*/
|
|
49
|
+
export function createSSEHandler(req, res, world, context = 'sse', scopedChatId) {
|
|
50
|
+
// Set SSE headers
|
|
51
|
+
res.setHeader('Content-Type', 'text/event-stream');
|
|
52
|
+
res.setHeader('Cache-Control', 'no-cache');
|
|
53
|
+
res.setHeader('Connection', 'keep-alive');
|
|
54
|
+
res.setHeader('Access-Control-Allow-Origin', '*');
|
|
55
|
+
res.setHeader('Access-Control-Allow-Headers', 'Cache-Control');
|
|
56
|
+
let timeoutTimer;
|
|
57
|
+
let hasReceivedEvents = false;
|
|
58
|
+
let isResponseEnded = false;
|
|
59
|
+
let lastEventTime = Date.now();
|
|
60
|
+
let awaitingWorldIdle = false;
|
|
61
|
+
const startTimeoutFallback = () => {
|
|
62
|
+
if (timeoutTimer)
|
|
63
|
+
clearTimeout(timeoutTimer);
|
|
64
|
+
if (isResponseEnded)
|
|
65
|
+
return;
|
|
66
|
+
// Fallback timeout - only used if world never becomes idle
|
|
67
|
+
timeoutTimer = setTimeout(() => {
|
|
68
|
+
if (!isResponseEnded) {
|
|
69
|
+
const timeSinceLastEvent = Date.now() - lastEventTime;
|
|
70
|
+
loggerStream.debug(`[${context}] Streaming timeout fallback triggered: timeSinceLastEvent=${timeSinceLastEvent}ms, awaitingWorldIdle=${awaitingWorldIdle}`);
|
|
71
|
+
if (!hasReceivedEvents && timeSinceLastEvent >= STREAM_TIMEOUT_NO_EVENTS_MS) {
|
|
72
|
+
loggerStream.debug(`[${context}] Ending stream: no events received within ${STREAM_TIMEOUT_NO_EVENTS_MS}ms`);
|
|
73
|
+
endResponse();
|
|
74
|
+
}
|
|
75
|
+
else if (timeSinceLastEvent >= 60000) {
|
|
76
|
+
// 60 second absolute timeout as fallback
|
|
77
|
+
loggerStream.debug(`[${context}] Ending stream: absolute timeout (60s) reached`);
|
|
78
|
+
endResponse();
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
}, 60000);
|
|
82
|
+
};
|
|
83
|
+
const endResponse = () => {
|
|
84
|
+
if (isResponseEnded)
|
|
85
|
+
return;
|
|
86
|
+
isResponseEnded = true;
|
|
87
|
+
if (timeoutTimer) {
|
|
88
|
+
clearTimeout(timeoutTimer);
|
|
89
|
+
timeoutTimer = undefined;
|
|
90
|
+
}
|
|
91
|
+
loggerStream.debug(`[${context}] Ending SSE response. Stats: events=${hasReceivedEvents}, awaitingWorldIdle=${awaitingWorldIdle}`);
|
|
92
|
+
try {
|
|
93
|
+
if (!res.destroyed) {
|
|
94
|
+
res.end();
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
catch (error) {
|
|
98
|
+
loggerStream.debug(`[${context}] Error ending response (likely already closed):`, error);
|
|
99
|
+
}
|
|
100
|
+
};
|
|
101
|
+
const sendSSE = (data) => {
|
|
102
|
+
if (isResponseEnded || res.destroyed)
|
|
103
|
+
return;
|
|
104
|
+
try {
|
|
105
|
+
const jsonData = typeof data === 'string' ? data : JSON.stringify(data);
|
|
106
|
+
res.write(`data: ${jsonData}\n\n`);
|
|
107
|
+
hasReceivedEvents = true;
|
|
108
|
+
lastEventTime = Date.now();
|
|
109
|
+
}
|
|
110
|
+
catch (error) {
|
|
111
|
+
loggerStream.debug(`[${context}] Error writing SSE data:`, error);
|
|
112
|
+
endResponse();
|
|
113
|
+
}
|
|
114
|
+
};
|
|
115
|
+
const listeners = new Map();
|
|
116
|
+
const normalizedScopedChatId = scopedChatId === undefined ? undefined : (scopedChatId === null ? null : String(scopedChatId));
|
|
117
|
+
const isChatEventInScope = (eventChatId, includeUnscopedWhenScoped = false) => {
|
|
118
|
+
if (normalizedScopedChatId === undefined)
|
|
119
|
+
return true;
|
|
120
|
+
if (eventChatId === undefined)
|
|
121
|
+
return includeUnscopedWhenScoped;
|
|
122
|
+
const normalizedEventChatId = eventChatId === null ? null : String(eventChatId);
|
|
123
|
+
return normalizedEventChatId === normalizedScopedChatId;
|
|
124
|
+
};
|
|
125
|
+
// Attach direct listeners to world.eventEmitter
|
|
126
|
+
const worldListener = (eventData) => {
|
|
127
|
+
// Check if this is a tool event (tool-start, tool-result, tool-error, tool-progress)
|
|
128
|
+
const isToolEvent = eventData?.type && ['tool-start', 'tool-result', 'tool-error', 'tool-progress'].includes(eventData.type);
|
|
129
|
+
if (isToolEvent) {
|
|
130
|
+
if (!isChatEventInScope(eventData?.chatId, false)) {
|
|
131
|
+
return;
|
|
132
|
+
}
|
|
133
|
+
// Forward tool events as SSE events for frontend consumption
|
|
134
|
+
sendSSE({
|
|
135
|
+
type: EventType.SSE,
|
|
136
|
+
data: {
|
|
137
|
+
type: eventData.type,
|
|
138
|
+
messageId: eventData.messageId,
|
|
139
|
+
agentName: eventData.agentName,
|
|
140
|
+
toolExecution: eventData.toolExecution,
|
|
141
|
+
chatId: eventData.chatId
|
|
142
|
+
}
|
|
143
|
+
});
|
|
144
|
+
return;
|
|
145
|
+
}
|
|
146
|
+
// Handle world activity events for stream completion
|
|
147
|
+
if (eventData?.type === 'response-start') {
|
|
148
|
+
awaitingWorldIdle = true;
|
|
149
|
+
loggerStream.debug(`[${context}] World processing started`, {
|
|
150
|
+
activityId: eventData.activityId,
|
|
151
|
+
source: eventData.source
|
|
152
|
+
});
|
|
153
|
+
}
|
|
154
|
+
else if (eventData?.type === 'idle' && awaitingWorldIdle) {
|
|
155
|
+
loggerStream.debug(`[${context}] World idle detected, ending stream`, {
|
|
156
|
+
activityId: eventData.activityId
|
|
157
|
+
});
|
|
158
|
+
// Stream all pending events, then end
|
|
159
|
+
sendSSE({ type: EventType.WORLD, data: eventData });
|
|
160
|
+
// Give a small delay for any final events to be sent
|
|
161
|
+
setTimeout(() => {
|
|
162
|
+
endResponse();
|
|
163
|
+
}, 500);
|
|
164
|
+
return;
|
|
165
|
+
}
|
|
166
|
+
if (isChatEventInScope(eventData?.chatId, true)) {
|
|
167
|
+
sendSSE({ type: EventType.WORLD, data: eventData });
|
|
168
|
+
}
|
|
169
|
+
};
|
|
170
|
+
world.eventEmitter.on(EventType.WORLD, worldListener);
|
|
171
|
+
listeners.set(EventType.WORLD, worldListener);
|
|
172
|
+
const messageListener = (eventData) => {
|
|
173
|
+
if (!isChatEventInScope(eventData?.chatId, false)) {
|
|
174
|
+
return;
|
|
175
|
+
}
|
|
176
|
+
// Enhance message event data with structured format
|
|
177
|
+
// CRITICAL: replyToMessageId must be included for frontend threading display
|
|
178
|
+
// Include tool_calls to preserve complete assistant tool-call context on the client.
|
|
179
|
+
const messageData = {
|
|
180
|
+
type: 'message',
|
|
181
|
+
sender: eventData.sender,
|
|
182
|
+
content: eventData.content,
|
|
183
|
+
messageId: eventData.messageId,
|
|
184
|
+
chatId: eventData.chatId,
|
|
185
|
+
replyToMessageId: eventData.replyToMessageId,
|
|
186
|
+
createdAt: eventData.timestamp || new Date().toISOString(),
|
|
187
|
+
role: eventData.role,
|
|
188
|
+
tool_calls: eventData.tool_calls
|
|
189
|
+
};
|
|
190
|
+
sendSSE({ type: EventType.MESSAGE, data: messageData });
|
|
191
|
+
};
|
|
192
|
+
world.eventEmitter.on(EventType.MESSAGE, messageListener);
|
|
193
|
+
listeners.set(EventType.MESSAGE, messageListener);
|
|
194
|
+
const sseListener = (eventData) => {
|
|
195
|
+
if (!isChatEventInScope(eventData?.chatId, false)) {
|
|
196
|
+
return;
|
|
197
|
+
}
|
|
198
|
+
// Extend fallback timeout when tool-stream data arrives (keeps long-running tools alive)
|
|
199
|
+
if (eventData.type === 'tool-stream') {
|
|
200
|
+
startTimeoutFallback();
|
|
201
|
+
}
|
|
202
|
+
sendSSE({ type: EventType.SSE, data: eventData });
|
|
203
|
+
};
|
|
204
|
+
world.eventEmitter.on(EventType.SSE, sseListener);
|
|
205
|
+
listeners.set(EventType.SSE, sseListener);
|
|
206
|
+
const systemListener = (eventData) => {
|
|
207
|
+
if (!isChatEventInScope(eventData?.chatId, true)) {
|
|
208
|
+
return;
|
|
209
|
+
}
|
|
210
|
+
sendSSE({ type: EventType.SYSTEM, data: eventData });
|
|
211
|
+
};
|
|
212
|
+
world.eventEmitter.on(EventType.SYSTEM, systemListener);
|
|
213
|
+
listeners.set(EventType.SYSTEM, systemListener);
|
|
214
|
+
// Cleanup function to remove all listeners
|
|
215
|
+
const cleanupListeners = () => {
|
|
216
|
+
for (const [eventType, listener] of listeners.entries()) {
|
|
217
|
+
world.eventEmitter.removeListener(eventType, listener);
|
|
218
|
+
}
|
|
219
|
+
listeners.clear();
|
|
220
|
+
};
|
|
221
|
+
// Handle client disconnect
|
|
222
|
+
req.on('close', () => {
|
|
223
|
+
loggerStream.debug(`[${context}] Client disconnected, cleaning up`);
|
|
224
|
+
cleanupListeners();
|
|
225
|
+
endResponse();
|
|
226
|
+
});
|
|
227
|
+
// Start the fallback timeout
|
|
228
|
+
startTimeoutFallback();
|
|
229
|
+
return {
|
|
230
|
+
sendSSE,
|
|
231
|
+
endResponse,
|
|
232
|
+
isEnded: () => isResponseEnded
|
|
233
|
+
};
|
|
234
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "agent-world",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.12.0",
|
|
4
4
|
"main": "dist/index.js",
|
|
5
5
|
"types": "dist/index.d.ts",
|
|
6
6
|
"exports": {
|
|
@@ -20,7 +20,7 @@
|
|
|
20
20
|
"web"
|
|
21
21
|
],
|
|
22
22
|
"bin": {
|
|
23
|
-
"agent-world": "
|
|
23
|
+
"agent-world": "dist/server/index.js",
|
|
24
24
|
"agent-world-cli": "dist/cli/index.js",
|
|
25
25
|
"agent-world-server": "dist/server/index.js"
|
|
26
26
|
},
|
|
@@ -38,7 +38,7 @@
|
|
|
38
38
|
"build": "npm run build --workspace=core && tsc --project tsconfig.build.json && npm run build --workspace=web",
|
|
39
39
|
"build:core": "npm run build --workspace=core",
|
|
40
40
|
"build:core:watch": "npm run build --workspace=core -- --watch --preserveWatchOutput",
|
|
41
|
-
"check": "tsc --noEmit --project tsconfig.build.json && npm run check --workspace=core && npm run check --workspace=web",
|
|
41
|
+
"check": "tsc --noEmit --project tsconfig.build.json && npm run check --workspace=core && npm run check --workspace=web && npm run main:build --prefix electron",
|
|
42
42
|
"server:dev": "npx tsx server/index.ts",
|
|
43
43
|
"server:watch": "npx tsx --watch server/index.ts",
|
|
44
44
|
"server:start": "node dist/server/index.js",
|
|
@@ -67,11 +67,23 @@
|
|
|
67
67
|
"author": "",
|
|
68
68
|
"license": "ISC",
|
|
69
69
|
"dependencies": {
|
|
70
|
+
"@anthropic-ai/sdk": "^0.71.2",
|
|
71
|
+
"@google/generative-ai": "^0.24.1",
|
|
72
|
+
"@modelcontextprotocol/sdk": "^1.26.0",
|
|
70
73
|
"chalk": "^5.5.0",
|
|
71
74
|
"cors": "^2.8.5",
|
|
75
|
+
"dotenv": "^17.2.3",
|
|
72
76
|
"enquirer": "^2.4.1",
|
|
73
77
|
"express": "^4.22.1",
|
|
78
|
+
"events": "^3.3.0",
|
|
79
|
+
"fast-glob": "^3.3.3",
|
|
80
|
+
"nanoid": "^5.1.5",
|
|
74
81
|
"open": "^11.0.0",
|
|
82
|
+
"openai": "^6.15.0",
|
|
83
|
+
"pino": "^10.0.0",
|
|
84
|
+
"pino-pretty": "^13.1.3",
|
|
85
|
+
"sqlite3": "^5.1.7",
|
|
86
|
+
"zod": "^4.2.1",
|
|
75
87
|
"tsx": "^4.21.0"
|
|
76
88
|
},
|
|
77
89
|
"devDependencies": {
|
|
@@ -1,58 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* Launch Electron App - Simple launcher for agent-world desktop app
|
|
5
|
-
*
|
|
6
|
-
* Purpose:
|
|
7
|
-
* - Launch the Electron desktop app when running `agent-world` command
|
|
8
|
-
* - Ensures necessary builds exist before launching
|
|
9
|
-
*
|
|
10
|
-
* Features:
|
|
11
|
-
* - Checks for core build
|
|
12
|
-
* - Launches Electron app
|
|
13
|
-
* - Provides helpful error messages if builds are missing
|
|
14
|
-
*
|
|
15
|
-
* Implementation Notes:
|
|
16
|
-
* - Used as bin entry point in package.json
|
|
17
|
-
* - Replaces CLI as default when running `agent-world` command
|
|
18
|
-
*/
|
|
19
|
-
|
|
20
|
-
import { spawn } from 'node:child_process';
|
|
21
|
-
import { fileURLToPath } from 'node:url';
|
|
22
|
-
import path from 'node:path';
|
|
23
|
-
import fs from 'node:fs';
|
|
24
|
-
|
|
25
|
-
const __filename = fileURLToPath(import.meta.url);
|
|
26
|
-
const __dirname = path.dirname(__filename);
|
|
27
|
-
const projectRoot = path.resolve(__dirname, '..');
|
|
28
|
-
|
|
29
|
-
// Check if core build exists
|
|
30
|
-
const coreIndexPath = path.join(projectRoot, 'dist', 'core', 'index.js');
|
|
31
|
-
if (!fs.existsSync(coreIndexPath)) {
|
|
32
|
-
console.error('Error: Core build not found. Please run: npm run build');
|
|
33
|
-
process.exit(1);
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
// Check if electron directory exists
|
|
37
|
-
const electronPath = path.join(projectRoot, 'electron');
|
|
38
|
-
if (!fs.existsSync(electronPath)) {
|
|
39
|
-
console.error('Error: Electron app not found.');
|
|
40
|
-
process.exit(1);
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
// Launch Electron app
|
|
44
|
-
const electronMainPath = path.join(electronPath, 'main.js');
|
|
45
|
-
const electronProcess = spawn('npx', ['electron', electronMainPath], {
|
|
46
|
-
cwd: projectRoot,
|
|
47
|
-
stdio: 'inherit',
|
|
48
|
-
env: { ...process.env }
|
|
49
|
-
});
|
|
50
|
-
|
|
51
|
-
electronProcess.on('error', (error) => {
|
|
52
|
-
console.error('Failed to launch Electron app:', error);
|
|
53
|
-
process.exit(1);
|
|
54
|
-
});
|
|
55
|
-
|
|
56
|
-
electronProcess.on('exit', (code) => {
|
|
57
|
-
process.exit(code || 0);
|
|
58
|
-
});
|