agent-world 0.13.0 → 0.15.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 +90 -17
- package/dist/cli/commands.d.ts +7 -1
- package/dist/cli/commands.js +27 -10
- package/dist/cli/hitl.d.ts +4 -1
- package/dist/cli/hitl.js +55 -20
- package/dist/cli/index.js +249 -97
- package/dist/cli/system-events.d.ts +27 -0
- package/dist/cli/system-events.js +63 -0
- package/dist/core/activity-tracker.d.ts +26 -0
- package/dist/core/activity-tracker.d.ts.map +1 -1
- package/dist/core/activity-tracker.js +21 -4
- package/dist/core/activity-tracker.js.map +1 -1
- package/dist/core/anthropic-direct.d.ts +2 -0
- package/dist/core/anthropic-direct.d.ts.map +1 -1
- package/dist/core/anthropic-direct.js +43 -1
- package/dist/core/anthropic-direct.js.map +1 -1
- package/dist/core/chat-constants.d.ts +12 -0
- package/dist/core/chat-constants.d.ts.map +1 -1
- package/dist/core/chat-constants.js +5 -0
- package/dist/core/chat-constants.js.map +1 -1
- package/dist/core/create-agent-tool.d.ts +5 -0
- package/dist/core/create-agent-tool.d.ts.map +1 -1
- package/dist/core/create-agent-tool.js +57 -34
- package/dist/core/create-agent-tool.js.map +1 -1
- package/dist/core/events/index.d.ts +5 -2
- package/dist/core/events/index.d.ts.map +1 -1
- package/dist/core/events/index.js +5 -2
- package/dist/core/events/index.js.map +1 -1
- package/dist/core/events/memory-manager.d.ts +26 -1
- package/dist/core/events/memory-manager.d.ts.map +1 -1
- package/dist/core/events/memory-manager.js +877 -72
- package/dist/core/events/memory-manager.js.map +1 -1
- package/dist/core/events/orchestrator.d.ts +8 -0
- package/dist/core/events/orchestrator.d.ts.map +1 -1
- package/dist/core/events/orchestrator.js +203 -36
- package/dist/core/events/orchestrator.js.map +1 -1
- package/dist/core/events/persistence.d.ts +21 -14
- package/dist/core/events/persistence.d.ts.map +1 -1
- package/dist/core/events/persistence.js +100 -35
- package/dist/core/events/persistence.js.map +1 -1
- package/dist/core/events/publishers.d.ts +13 -7
- package/dist/core/events/publishers.d.ts.map +1 -1
- package/dist/core/events/publishers.js +53 -37
- package/dist/core/events/publishers.js.map +1 -1
- package/dist/core/events/subscribers.d.ts +17 -14
- package/dist/core/events/subscribers.d.ts.map +1 -1
- package/dist/core/events/subscribers.js +61 -148
- package/dist/core/events/subscribers.js.map +1 -1
- package/dist/core/events/title-scheduler.d.ts +27 -0
- package/dist/core/events/title-scheduler.d.ts.map +1 -0
- package/dist/core/events/title-scheduler.js +135 -0
- package/dist/core/events/title-scheduler.js.map +1 -0
- package/dist/core/events/tool-bridge-logging.d.ts +4 -1
- package/dist/core/events/tool-bridge-logging.d.ts.map +1 -1
- package/dist/core/events/tool-bridge-logging.js +112 -13
- package/dist/core/events/tool-bridge-logging.js.map +1 -1
- package/dist/core/events-metadata.d.ts.map +1 -1
- package/dist/core/events-metadata.js +8 -4
- package/dist/core/events-metadata.js.map +1 -1
- package/dist/core/export.d.ts +1 -1
- package/dist/core/export.d.ts.map +1 -1
- package/dist/core/export.js +2 -15
- package/dist/core/export.js.map +1 -1
- package/dist/core/feature-path-logging.d.ts +50 -0
- package/dist/core/feature-path-logging.d.ts.map +1 -0
- package/dist/core/feature-path-logging.js +130 -0
- package/dist/core/feature-path-logging.js.map +1 -0
- package/dist/core/file-tools.d.ts +57 -1
- package/dist/core/file-tools.d.ts.map +1 -1
- package/dist/core/file-tools.js +329 -29
- package/dist/core/file-tools.js.map +1 -1
- package/dist/core/google-direct.d.ts +6 -1
- package/dist/core/google-direct.d.ts.map +1 -1
- package/dist/core/google-direct.js +76 -7
- package/dist/core/google-direct.js.map +1 -1
- package/dist/core/heartbeat.d.ts +34 -0
- package/dist/core/heartbeat.d.ts.map +1 -0
- package/dist/core/heartbeat.js +153 -0
- package/dist/core/heartbeat.js.map +1 -0
- package/dist/core/hitl-tool.d.ts +6 -12
- package/dist/core/hitl-tool.d.ts.map +1 -1
- package/dist/core/hitl-tool.js +66 -88
- package/dist/core/hitl-tool.js.map +1 -1
- package/dist/core/hitl.d.ts +61 -4
- package/dist/core/hitl.d.ts.map +1 -1
- package/dist/core/hitl.js +324 -60
- package/dist/core/hitl.js.map +1 -1
- package/dist/core/index.d.ts +11 -7
- package/dist/core/index.d.ts.map +1 -1
- package/dist/core/index.js +10 -6
- package/dist/core/index.js.map +1 -1
- package/dist/core/llm-manager.d.ts +15 -0
- package/dist/core/llm-manager.d.ts.map +1 -1
- package/dist/core/llm-manager.js +325 -40
- package/dist/core/llm-manager.js.map +1 -1
- package/dist/core/load-skill-tool.d.ts +36 -3
- package/dist/core/load-skill-tool.d.ts.map +1 -1
- package/dist/core/load-skill-tool.js +807 -93
- package/dist/core/load-skill-tool.js.map +1 -1
- package/dist/core/logger.d.ts +14 -0
- package/dist/core/logger.d.ts.map +1 -1
- package/dist/core/logger.js +15 -0
- package/dist/core/logger.js.map +1 -1
- package/dist/core/managers.d.ts +18 -50
- package/dist/core/managers.d.ts.map +1 -1
- package/dist/core/managers.js +340 -502
- package/dist/core/managers.js.map +1 -1
- package/dist/core/mcp-server-registry.d.ts +16 -1
- package/dist/core/mcp-server-registry.d.ts.map +1 -1
- package/dist/core/mcp-server-registry.js +162 -12
- package/dist/core/mcp-server-registry.js.map +1 -1
- package/dist/core/message-cutoff.d.ts +29 -0
- package/dist/core/message-cutoff.d.ts.map +1 -0
- package/dist/core/message-cutoff.js +63 -0
- package/dist/core/message-cutoff.js.map +1 -0
- package/dist/core/message-edit-manager.d.ts +54 -0
- package/dist/core/message-edit-manager.d.ts.map +1 -0
- package/dist/core/message-edit-manager.js +602 -0
- package/dist/core/message-edit-manager.js.map +1 -0
- package/dist/core/message-prep.d.ts +2 -0
- package/dist/core/message-prep.d.ts.map +1 -1
- package/dist/core/message-prep.js +39 -12
- package/dist/core/message-prep.js.map +1 -1
- package/dist/core/message-processing-control.d.ts +1 -0
- package/dist/core/message-processing-control.d.ts.map +1 -1
- package/dist/core/message-processing-control.js +23 -6
- package/dist/core/message-processing-control.js.map +1 -1
- package/dist/core/openai-direct.d.ts +9 -3
- package/dist/core/openai-direct.d.ts.map +1 -1
- package/dist/core/openai-direct.js +267 -33
- package/dist/core/openai-direct.js.map +1 -1
- package/dist/core/optional-tracers/opik-runtime.d.ts +32 -0
- package/dist/core/optional-tracers/opik-runtime.d.ts.map +1 -0
- package/dist/core/optional-tracers/opik-runtime.js +141 -0
- package/dist/core/optional-tracers/opik-runtime.js.map +1 -0
- package/dist/core/queue-manager.d.ts +84 -0
- package/dist/core/queue-manager.d.ts.map +1 -0
- package/dist/core/queue-manager.js +814 -0
- package/dist/core/queue-manager.js.map +1 -0
- package/dist/core/reasoning-controls.d.ts +30 -0
- package/dist/core/reasoning-controls.d.ts.map +1 -0
- package/dist/core/reasoning-controls.js +118 -0
- package/dist/core/reasoning-controls.js.map +1 -0
- package/dist/core/reliability-config.d.ts +82 -0
- package/dist/core/reliability-config.d.ts.map +1 -0
- package/dist/core/reliability-config.js +106 -0
- package/dist/core/reliability-config.js.map +1 -0
- package/dist/core/reliability-runtime.d.ts +53 -0
- package/dist/core/reliability-runtime.d.ts.map +1 -0
- package/dist/core/reliability-runtime.js +92 -0
- package/dist/core/reliability-runtime.js.map +1 -0
- package/dist/core/security/guardrails.d.ts +21 -0
- package/dist/core/security/guardrails.d.ts.map +1 -0
- package/dist/core/security/guardrails.js +111 -0
- package/dist/core/security/guardrails.js.map +1 -0
- package/dist/core/send-message-tool.d.ts +79 -0
- package/dist/core/send-message-tool.d.ts.map +1 -0
- package/dist/core/send-message-tool.js +222 -0
- package/dist/core/send-message-tool.js.map +1 -0
- package/dist/core/shell-cmd-tool.d.ts +82 -1
- package/dist/core/shell-cmd-tool.d.ts.map +1 -1
- package/dist/core/shell-cmd-tool.js +854 -42
- package/dist/core/shell-cmd-tool.js.map +1 -1
- package/dist/core/skill-registry.d.ts +2 -0
- package/dist/core/skill-registry.d.ts.map +1 -1
- package/dist/core/skill-registry.js +52 -2
- package/dist/core/skill-registry.js.map +1 -1
- package/dist/core/storage/eventStorage/fileEventStorage.d.ts +5 -0
- package/dist/core/storage/eventStorage/fileEventStorage.d.ts.map +1 -1
- package/dist/core/storage/eventStorage/fileEventStorage.js +61 -0
- package/dist/core/storage/eventStorage/fileEventStorage.js.map +1 -1
- package/dist/core/storage/eventStorage/memoryEventStorage.d.ts +5 -0
- package/dist/core/storage/eventStorage/memoryEventStorage.d.ts.map +1 -1
- package/dist/core/storage/eventStorage/memoryEventStorage.js +34 -0
- package/dist/core/storage/eventStorage/memoryEventStorage.js.map +1 -1
- package/dist/core/storage/eventStorage/sqliteEventStorage.d.ts +1 -0
- package/dist/core/storage/eventStorage/sqliteEventStorage.d.ts.map +1 -1
- package/dist/core/storage/eventStorage/sqliteEventStorage.js +19 -2
- package/dist/core/storage/eventStorage/sqliteEventStorage.js.map +1 -1
- package/dist/core/storage/eventStorage/types.d.ts +6 -0
- package/dist/core/storage/eventStorage/types.d.ts.map +1 -1
- package/dist/core/storage/eventStorage/types.js +1 -0
- package/dist/core/storage/eventStorage/types.js.map +1 -1
- package/dist/core/storage/eventStorage/validation.d.ts.map +1 -1
- package/dist/core/storage/eventStorage/validation.js +2 -1
- package/dist/core/storage/eventStorage/validation.js.map +1 -1
- package/dist/core/storage/github-world-import.d.ts +84 -0
- package/dist/core/storage/github-world-import.d.ts.map +1 -0
- package/dist/core/storage/github-world-import.js +365 -0
- package/dist/core/storage/github-world-import.js.map +1 -0
- package/dist/core/storage/memory-storage.d.ts +19 -8
- package/dist/core/storage/memory-storage.d.ts.map +1 -1
- package/dist/core/storage/memory-storage.js +147 -49
- package/dist/core/storage/memory-storage.js.map +1 -1
- package/dist/core/storage/queue-storage.d.ts +1 -0
- package/dist/core/storage/queue-storage.d.ts.map +1 -1
- package/dist/core/storage/queue-storage.js +3 -2
- package/dist/core/storage/queue-storage.js.map +1 -1
- package/dist/core/storage/sqlite-storage.d.ts +14 -9
- package/dist/core/storage/sqlite-storage.d.ts.map +1 -1
- package/dist/core/storage/sqlite-storage.js +131 -154
- package/dist/core/storage/sqlite-storage.js.map +1 -1
- package/dist/core/storage/storage-factory.d.ts +3 -0
- package/dist/core/storage/storage-factory.d.ts.map +1 -1
- package/dist/core/storage/storage-factory.js +175 -89
- package/dist/core/storage/storage-factory.js.map +1 -1
- package/dist/core/storage/world-storage.d.ts +1 -1
- package/dist/core/storage/world-storage.d.ts.map +1 -1
- package/dist/core/storage/world-storage.js +5 -1
- package/dist/core/storage/world-storage.js.map +1 -1
- package/dist/core/storage-init.d.ts +11 -0
- package/dist/core/storage-init.d.ts.map +1 -0
- package/dist/core/storage-init.js +122 -0
- package/dist/core/storage-init.js.map +1 -0
- package/dist/core/subscription.d.ts +8 -1
- package/dist/core/subscription.d.ts.map +1 -1
- package/dist/core/subscription.js +130 -23
- package/dist/core/subscription.js.map +1 -1
- package/dist/core/tool-approval.d.ts +45 -0
- package/dist/core/tool-approval.d.ts.map +1 -0
- package/dist/core/tool-approval.js +223 -0
- package/dist/core/tool-approval.js.map +1 -0
- package/dist/core/tool-execution-envelope.d.ts +87 -0
- package/dist/core/tool-execution-envelope.d.ts.map +1 -0
- package/dist/core/tool-execution-envelope.js +168 -0
- package/dist/core/tool-execution-envelope.js.map +1 -0
- package/dist/core/tool-utils.d.ts +7 -2
- package/dist/core/tool-utils.d.ts.map +1 -1
- package/dist/core/tool-utils.js +81 -17
- package/dist/core/tool-utils.js.map +1 -1
- package/dist/core/types.d.ts +67 -19
- package/dist/core/types.d.ts.map +1 -1
- package/dist/core/types.js +3 -0
- package/dist/core/types.js.map +1 -1
- package/dist/core/utils.d.ts +7 -0
- package/dist/core/utils.d.ts.map +1 -1
- package/dist/core/utils.js +71 -21
- package/dist/core/utils.js.map +1 -1
- package/dist/core/web-fetch-tool.d.ts +72 -0
- package/dist/core/web-fetch-tool.d.ts.map +1 -0
- package/dist/core/web-fetch-tool.js +491 -0
- package/dist/core/web-fetch-tool.js.map +1 -0
- package/dist/core/world-registry.d.ts +84 -0
- package/dist/core/world-registry.d.ts.map +1 -0
- package/dist/core/world-registry.js +247 -0
- package/dist/core/world-registry.js.map +1 -0
- package/dist/public/assets/index-Be-1xtV-.js +104 -0
- package/dist/public/assets/index-tsDdiXDU.css +1 -0
- package/dist/public/index.html +2 -2
- package/dist/public/mcp-sandbox-proxy.html +148 -0
- package/dist/server/api.js +260 -18
- package/dist/server/error-response.d.ts +27 -0
- package/dist/server/error-response.js +77 -0
- package/dist/server/index.d.ts +2 -1
- package/dist/server/index.js +6 -2
- package/dist/server/sse-handler.d.ts +11 -1
- package/dist/server/sse-handler.js +194 -34
- package/migrations/0015_add_message_queue.sql +36 -0
- package/migrations/0016_add_world_heartbeat.sql +13 -0
- package/migrations/0017_add_title_provenance.sql +7 -0
- package/package.json +31 -10
- package/dist/public/assets/index-BW41BxMy.css +0 -1
- package/dist/public/assets/index-kO6UJFwK.js +0 -96
package/dist/cli/index.js
CHANGED
|
@@ -13,10 +13,15 @@
|
|
|
13
13
|
* - Work with loaded world without importing (uses external storage path)
|
|
14
14
|
*
|
|
15
15
|
* Changes:
|
|
16
|
+
* - 2026-03-06: Routed runtime chat selection through explicit CLI state; removed live listener/send fallback to `world.currentChatId`.
|
|
17
|
+
* - 2026-02-27: Added active-chat event scoping in CLI listeners to prevent cross-chat message/system/SSE/tool leakage.
|
|
18
|
+
* - 2026-02-25: Added fallback shorthand attempt `@awesome-agent-world/<input>` when a provided local path does not exist.
|
|
19
|
+
* - 2026-02-25: Added GitHub shorthand world source import support (`@awesome-agent-world/<world-name>`) with safe remote staging and automatic import mode.
|
|
16
20
|
* - 2026-02-20: Enforced options-only HITL handling in interactive and pipeline modes.
|
|
17
21
|
* - 2026-02-14: Added interactive + pipeline HITL option response handling for generic approval requests.
|
|
18
22
|
* - 2026-02-11: Fixed tool-stream timeout: extendTimeout() resets idle timeout on streaming data
|
|
19
23
|
* - 2026-02-11: Pipeline mode now listens for tool-stream SSE events to extend timeout
|
|
24
|
+
* - 2026-02-21: Extended timeout-refresh detection to include shell assistant-stream SSE events (`start`/`chunk`/`end` with `toolName='shell_cmd'`) in addition to legacy `tool-stream`.
|
|
20
25
|
* - 2026-01-09: Added --streaming flag for explicit streaming control (overrides TTY auto-detection)
|
|
21
26
|
* - 2025-02-06: Prevented duplicate MESSAGE output when streaming already rendered agent responses
|
|
22
27
|
* - 2025-11-01: Added multi-world selection in loadWorldFromFile
|
|
@@ -77,14 +82,17 @@ import path from 'path';
|
|
|
77
82
|
import { fileURLToPath } from 'url';
|
|
78
83
|
import { program } from 'commander';
|
|
79
84
|
import readline from 'readline';
|
|
80
|
-
import { listWorlds, subscribeWorld, submitWorldHitlResponse, createCategoryLogger, LLMProvider, enableStreaming, disableStreaming } from '../core/index.js';
|
|
85
|
+
import { listWorlds, deleteWorld, subscribeWorld, submitWorldHitlResponse, GitHubWorldImportError, stageGitHubWorldFromShorthand, createCategoryLogger, LLMProvider, enableStreaming, disableStreaming } from '../core/index.js';
|
|
81
86
|
import { EventType } from '../core/types.js';
|
|
82
87
|
import { getDefaultRootPath } from '../core/storage/storage-factory.js';
|
|
88
|
+
// Opik integration: optional tracer attach for CLI world subscriptions.
|
|
89
|
+
import { attachOptionalOpikTracer } from '../core/optional-tracers/opik-runtime.js';
|
|
83
90
|
import { processCLIInput, displayChatMessages } from './commands.js';
|
|
84
91
|
import { createStreamingState, handleWorldEventWithStreaming, handleToolEvents, } from './stream.js';
|
|
85
92
|
import { configureLLMProvider } from '../core/llm-config.js';
|
|
86
93
|
import { createStatusLineManager, log as statusLog, } from './display.js';
|
|
87
|
-
import {
|
|
94
|
+
import { getSystemEventDisplayText } from './system-events.js';
|
|
95
|
+
import { markHitlRequestHandled, parseHitlPromptFromToolEvent, resolveHitlOptionSelectionInput, } from './hitl.js';
|
|
88
96
|
// Create CLI category logger after logger auto-initialization
|
|
89
97
|
const logger = createCategoryLogger('cli');
|
|
90
98
|
function createGlobalState() {
|
|
@@ -395,11 +403,87 @@ function printCLIResult(result) {
|
|
|
395
403
|
* @param rl - Readline interface for interactive mode (undefined for pipeline mode)
|
|
396
404
|
* @returns Map of event types to listener functions for cleanup
|
|
397
405
|
*/
|
|
398
|
-
function attachCLIListeners(world, streaming, globalState, activityMonitor, statusLine, rl) {
|
|
406
|
+
function attachCLIListeners(world, streaming, globalState, activityMonitor, statusLine, getSelectedChatId, rl) {
|
|
399
407
|
const listeners = new Map();
|
|
400
408
|
let hitlPromptChain = Promise.resolve();
|
|
409
|
+
const handledHitlRequestIds = new Set();
|
|
410
|
+
const isChatEventInScope = (eventChatId, includeUnscopedWhenScoped = false) => {
|
|
411
|
+
const activeChatId = getSelectedChatId();
|
|
412
|
+
if (!activeChatId) {
|
|
413
|
+
return true;
|
|
414
|
+
}
|
|
415
|
+
if (eventChatId === undefined || eventChatId === null) {
|
|
416
|
+
return includeUnscopedWhenScoped;
|
|
417
|
+
}
|
|
418
|
+
const normalizedEventChatId = String(eventChatId).trim();
|
|
419
|
+
if (!normalizedEventChatId) {
|
|
420
|
+
return includeUnscopedWhenScoped;
|
|
421
|
+
}
|
|
422
|
+
return normalizedEventChatId === activeChatId;
|
|
423
|
+
};
|
|
424
|
+
const shouldHandleWorldEvent = (eventData) => {
|
|
425
|
+
const eventType = String(eventData?.type || '').trim().toLowerCase();
|
|
426
|
+
if (eventType === 'response-start' || eventType === 'response-end' || eventType === 'idle' || eventType === 'info') {
|
|
427
|
+
return isChatEventInScope(eventData?.chatId, true);
|
|
428
|
+
}
|
|
429
|
+
if (eventType.startsWith('tool-')) {
|
|
430
|
+
return isChatEventInScope(eventData?.chatId, false);
|
|
431
|
+
}
|
|
432
|
+
return isChatEventInScope(eventData?.chatId, true);
|
|
433
|
+
};
|
|
401
434
|
// World activity events
|
|
402
435
|
const worldListener = (eventData) => {
|
|
436
|
+
if (!shouldHandleWorldEvent(eventData)) {
|
|
437
|
+
return;
|
|
438
|
+
}
|
|
439
|
+
const hitlRequest = parseHitlPromptFromToolEvent(eventData);
|
|
440
|
+
if (hitlRequest) {
|
|
441
|
+
if (!markHitlRequestHandled(handledHitlRequestIds, hitlRequest.requestId)) {
|
|
442
|
+
return;
|
|
443
|
+
}
|
|
444
|
+
hitlPromptChain = hitlPromptChain
|
|
445
|
+
.then(async () => {
|
|
446
|
+
if (streaming && globalState && rl && statusLine) {
|
|
447
|
+
globalState.hitlPromptActive = true;
|
|
448
|
+
try {
|
|
449
|
+
const result = submitWorldHitlResponse({
|
|
450
|
+
worldId: world.id,
|
|
451
|
+
requestId: hitlRequest.requestId,
|
|
452
|
+
optionId: await promptHitlOptionSelection(hitlRequest, statusLine, rl),
|
|
453
|
+
chatId: hitlRequest.chatId,
|
|
454
|
+
});
|
|
455
|
+
if (!result.accepted) {
|
|
456
|
+
statusLine.pause();
|
|
457
|
+
console.log(boldRed(`Failed to submit approval response: ${result.reason || 'unknown error'}`));
|
|
458
|
+
statusLine.resume();
|
|
459
|
+
return;
|
|
460
|
+
}
|
|
461
|
+
statusLine.pause();
|
|
462
|
+
console.log(green('Submitted HITL option response.'));
|
|
463
|
+
statusLine.resume();
|
|
464
|
+
return;
|
|
465
|
+
}
|
|
466
|
+
finally {
|
|
467
|
+
globalState.hitlPromptActive = false;
|
|
468
|
+
}
|
|
469
|
+
}
|
|
470
|
+
const result = submitWorldHitlResponse({
|
|
471
|
+
worldId: world.id,
|
|
472
|
+
requestId: hitlRequest.requestId,
|
|
473
|
+
optionId: hitlRequest.defaultOptionId,
|
|
474
|
+
chatId: hitlRequest.chatId,
|
|
475
|
+
});
|
|
476
|
+
if (!result.accepted) {
|
|
477
|
+
console.error(boldRed(`Failed to auto-respond HITL request: ${result.reason || 'unknown error'}`));
|
|
478
|
+
return;
|
|
479
|
+
}
|
|
480
|
+
console.log(`${gray('● system:')} Auto-selected HITL option "${hitlRequest.defaultOptionId}"`);
|
|
481
|
+
})
|
|
482
|
+
.catch((error) => {
|
|
483
|
+
console.error(boldRed(`Error handling HITL request: ${error instanceof Error ? error.message : String(error)}`));
|
|
484
|
+
});
|
|
485
|
+
return;
|
|
486
|
+
}
|
|
403
487
|
activityMonitor.handle(eventData);
|
|
404
488
|
// Only render activity progress in interactive mode
|
|
405
489
|
if (streaming && globalState && rl && statusLine) {
|
|
@@ -412,6 +496,9 @@ function attachCLIListeners(world, streaming, globalState, activityMonitor, stat
|
|
|
412
496
|
listeners.set(EventType.WORLD, worldListener);
|
|
413
497
|
// Message events
|
|
414
498
|
const messageListener = (eventData) => {
|
|
499
|
+
if (!isChatEventInScope(eventData?.chatId, false)) {
|
|
500
|
+
return;
|
|
501
|
+
}
|
|
415
502
|
if (eventData.content &&
|
|
416
503
|
typeof eventData.content === 'string' &&
|
|
417
504
|
eventData.content.includes('Success message sent'))
|
|
@@ -435,8 +522,14 @@ function attachCLIListeners(world, streaming, globalState, activityMonitor, stat
|
|
|
435
522
|
// SSE events (interactive mode only - pipeline mode uses non-streaming LLM calls)
|
|
436
523
|
if (streaming && globalState && rl && statusLine) {
|
|
437
524
|
const sseListener = (eventData) => {
|
|
438
|
-
|
|
439
|
-
|
|
525
|
+
if (!isChatEventInScope(eventData?.chatId, false)) {
|
|
526
|
+
return;
|
|
527
|
+
}
|
|
528
|
+
// Extend timeout when long-running shell stream activity arrives.
|
|
529
|
+
const isLegacyToolStream = eventData.type === 'tool-stream';
|
|
530
|
+
const isShellAssistantStream = eventData.toolName === 'shell_cmd' &&
|
|
531
|
+
(eventData.type === 'start' || eventData.type === 'chunk' || eventData.type === 'end');
|
|
532
|
+
if (isLegacyToolStream || isShellAssistantStream) {
|
|
440
533
|
activityMonitor.extendTimeout();
|
|
441
534
|
}
|
|
442
535
|
handleWorldEvent(EventType.SSE, eventData, streaming, globalState, activityMonitor, statusLine, rl)
|
|
@@ -446,9 +539,15 @@ function attachCLIListeners(world, streaming, globalState, activityMonitor, stat
|
|
|
446
539
|
listeners.set(EventType.SSE, sseListener);
|
|
447
540
|
}
|
|
448
541
|
else {
|
|
449
|
-
// Pipeline mode: listen for
|
|
542
|
+
// Pipeline mode: listen for shell stream events to extend timeout on long-running commands.
|
|
450
543
|
const sseTimeoutListener = (eventData) => {
|
|
451
|
-
if (eventData
|
|
544
|
+
if (!isChatEventInScope(eventData?.chatId, false)) {
|
|
545
|
+
return;
|
|
546
|
+
}
|
|
547
|
+
const isLegacyToolStream = eventData.type === 'tool-stream';
|
|
548
|
+
const isShellAssistantStream = eventData.toolName === 'shell_cmd' &&
|
|
549
|
+
(eventData.type === 'start' || eventData.type === 'chunk' || eventData.type === 'end');
|
|
550
|
+
if (isLegacyToolStream || isShellAssistantStream) {
|
|
452
551
|
activityMonitor.extendTimeout();
|
|
453
552
|
}
|
|
454
553
|
};
|
|
@@ -457,50 +556,7 @@ function attachCLIListeners(world, streaming, globalState, activityMonitor, stat
|
|
|
457
556
|
}
|
|
458
557
|
// System events
|
|
459
558
|
const systemListener = (eventData) => {
|
|
460
|
-
|
|
461
|
-
if (hitlRequest) {
|
|
462
|
-
hitlPromptChain = hitlPromptChain
|
|
463
|
-
.then(async () => {
|
|
464
|
-
if (streaming && globalState && rl && statusLine) {
|
|
465
|
-
globalState.hitlPromptActive = true;
|
|
466
|
-
try {
|
|
467
|
-
const result = submitWorldHitlResponse({
|
|
468
|
-
worldId: world.id,
|
|
469
|
-
requestId: hitlRequest.requestId,
|
|
470
|
-
optionId: await promptHitlOptionSelection(hitlRequest, statusLine, rl),
|
|
471
|
-
chatId: hitlRequest.chatId,
|
|
472
|
-
});
|
|
473
|
-
if (!result.accepted) {
|
|
474
|
-
statusLine.pause();
|
|
475
|
-
console.log(boldRed(`Failed to submit approval response: ${result.reason || 'unknown error'}`));
|
|
476
|
-
statusLine.resume();
|
|
477
|
-
return;
|
|
478
|
-
}
|
|
479
|
-
statusLine.pause();
|
|
480
|
-
console.log(green('Submitted HITL option response.'));
|
|
481
|
-
statusLine.resume();
|
|
482
|
-
return;
|
|
483
|
-
}
|
|
484
|
-
finally {
|
|
485
|
-
globalState.hitlPromptActive = false;
|
|
486
|
-
}
|
|
487
|
-
}
|
|
488
|
-
// Pipeline/non-interactive mode: auto-respond with default option to avoid blocking.
|
|
489
|
-
const result = submitWorldHitlResponse({
|
|
490
|
-
worldId: world.id,
|
|
491
|
-
requestId: hitlRequest.requestId,
|
|
492
|
-
optionId: hitlRequest.defaultOptionId,
|
|
493
|
-
chatId: hitlRequest.chatId,
|
|
494
|
-
});
|
|
495
|
-
if (!result.accepted) {
|
|
496
|
-
console.error(boldRed(`Failed to auto-respond HITL request: ${result.reason || 'unknown error'}`));
|
|
497
|
-
return;
|
|
498
|
-
}
|
|
499
|
-
console.log(`${gray('● system:')} Auto-selected HITL option "${hitlRequest.defaultOptionId}"`);
|
|
500
|
-
})
|
|
501
|
-
.catch((error) => {
|
|
502
|
-
console.error(boldRed(`Error handling HITL request: ${error instanceof Error ? error.message : String(error)}`));
|
|
503
|
-
});
|
|
559
|
+
if (!isChatEventInScope(eventData?.chatId, false)) {
|
|
504
560
|
return;
|
|
505
561
|
}
|
|
506
562
|
if (eventData.content &&
|
|
@@ -511,8 +567,11 @@ function attachCLIListeners(world, streaming, globalState, activityMonitor, stat
|
|
|
511
567
|
handleWorldEvent(EventType.SYSTEM, eventData, streaming, globalState, activityMonitor, statusLine, rl)
|
|
512
568
|
.catch(err => console.error('Error handling system event:', err));
|
|
513
569
|
}
|
|
514
|
-
else
|
|
515
|
-
|
|
570
|
+
else {
|
|
571
|
+
const systemText = getSystemEventDisplayText(eventData);
|
|
572
|
+
if (systemText) {
|
|
573
|
+
console.log(`${boldRed('● system:')} ${systemText}`);
|
|
574
|
+
}
|
|
516
575
|
}
|
|
517
576
|
};
|
|
518
577
|
world.eventEmitter.on(EventType.SYSTEM, systemListener);
|
|
@@ -537,6 +596,7 @@ async function runPipelineMode(options, messageFromArgs) {
|
|
|
537
596
|
let worldSubscription = null;
|
|
538
597
|
let cliListeners = null;
|
|
539
598
|
const activityMonitor = new WorldActivityMonitor();
|
|
599
|
+
const opikEnabledOverride = parseOptionalBoolean(options.opikEnabled);
|
|
540
600
|
try {
|
|
541
601
|
if (options.world) {
|
|
542
602
|
// Subscribe to world lifecycle but do not request forwarding callbacks
|
|
@@ -546,9 +606,11 @@ async function runPipelineMode(options, messageFromArgs) {
|
|
|
546
606
|
process.exit(1);
|
|
547
607
|
}
|
|
548
608
|
world = worldSubscription.world;
|
|
609
|
+
await attachOptionalOpikTracer(world, { source: 'cli', enabledOverride: opikEnabledOverride });
|
|
549
610
|
// Attach direct listeners to the world.eventEmitter for pipeline handling
|
|
550
611
|
// Note: Pipeline mode uses non-streaming LLM calls, so SSE events are not needed
|
|
551
|
-
|
|
612
|
+
const selectedChatId = String(world?.currentChatId || '').trim() || null;
|
|
613
|
+
cliListeners = attachCLIListeners(world, null, null, activityMonitor, null, () => selectedChatId);
|
|
552
614
|
}
|
|
553
615
|
// Execute command from --command option
|
|
554
616
|
if (options.command) {
|
|
@@ -557,7 +619,7 @@ async function runPipelineMode(options, messageFromArgs) {
|
|
|
557
619
|
process.exit(1);
|
|
558
620
|
}
|
|
559
621
|
const snapshot = activityMonitor.captureSnapshot();
|
|
560
|
-
const result = await processCLIInput(options.command, world, 'human');
|
|
622
|
+
const result = await processCLIInput(options.command, world, 'human', String(world?.currentChatId || '').trim() || null);
|
|
561
623
|
printCLIResult(result);
|
|
562
624
|
if (!options.command.startsWith('/') && world) {
|
|
563
625
|
try {
|
|
@@ -590,7 +652,7 @@ async function runPipelineMode(options, messageFromArgs) {
|
|
|
590
652
|
process.exit(1);
|
|
591
653
|
}
|
|
592
654
|
const snapshot = activityMonitor.captureSnapshot();
|
|
593
|
-
const result = await processCLIInput(messageFromArgs, world, 'human');
|
|
655
|
+
const result = await processCLIInput(messageFromArgs, world, 'human', String(world?.currentChatId || '').trim() || null);
|
|
594
656
|
printCLIResult(result);
|
|
595
657
|
try {
|
|
596
658
|
// Event-driven completion: wait for world idle state
|
|
@@ -621,7 +683,7 @@ async function runPipelineMode(options, messageFromArgs) {
|
|
|
621
683
|
process.exit(1);
|
|
622
684
|
}
|
|
623
685
|
const snapshot = activityMonitor.captureSnapshot();
|
|
624
|
-
const result = await processCLIInput(input.trim(), world, 'HUMAN');
|
|
686
|
+
const result = await processCLIInput(input.trim(), world, 'HUMAN', String(world?.currentChatId || '').trim() || null);
|
|
625
687
|
printCLIResult(result);
|
|
626
688
|
try {
|
|
627
689
|
// Event-driven completion: wait for world idle state
|
|
@@ -681,20 +743,26 @@ function cleanupWorldSubscription(worldState) {
|
|
|
681
743
|
* @param rl - Readline interface for interactive input
|
|
682
744
|
* @returns WorldState with subscription and world instance
|
|
683
745
|
*/
|
|
684
|
-
async function handleSubscribe(rootPath, worldName, streaming, globalState, activityMonitor, statusLine, rl) {
|
|
746
|
+
async function handleSubscribe(rootPath, worldName, streaming, globalState, activityMonitor, statusLine, opikEnabledOverride, rl) {
|
|
685
747
|
// Subscribe to world lifecycle but do not request forwarding callbacks
|
|
686
748
|
const subscription = await subscribeWorld(worldName, { isOpen: true });
|
|
687
749
|
if (!subscription)
|
|
688
750
|
throw new Error('Failed to load world');
|
|
689
751
|
const world = subscription.world;
|
|
752
|
+
await attachOptionalOpikTracer(world, { source: 'cli', enabledOverride: opikEnabledOverride });
|
|
690
753
|
// Store world in globalState for access in interactive event handlers.
|
|
691
754
|
if (globalState) {
|
|
692
755
|
globalState.world = world;
|
|
693
756
|
}
|
|
694
757
|
// Attach direct listeners to the world.eventEmitter for CLI handling
|
|
695
758
|
// Interactive mode needs all event types including SSE for streaming responses
|
|
696
|
-
|
|
697
|
-
|
|
759
|
+
const worldState = {
|
|
760
|
+
subscription,
|
|
761
|
+
world,
|
|
762
|
+
selectedChatId: String(world.currentChatId || '').trim() || null,
|
|
763
|
+
};
|
|
764
|
+
attachCLIListeners(world, streaming, globalState, activityMonitor, statusLine, () => worldState.selectedChatId, rl);
|
|
765
|
+
return worldState;
|
|
698
766
|
}
|
|
699
767
|
// Handle world events with streaming support
|
|
700
768
|
async function handleWorldEvent(eventType, eventData, streaming, globalState, activityMonitor, statusLine, rl) {
|
|
@@ -812,8 +880,18 @@ async function handleWorldEvent(eventType, eventData, streaming, globalState, ac
|
|
|
812
880
|
}
|
|
813
881
|
return;
|
|
814
882
|
}
|
|
815
|
-
if (
|
|
816
|
-
|
|
883
|
+
if (eventType === 'system') {
|
|
884
|
+
const systemText = getSystemEventDisplayText(eventData);
|
|
885
|
+
if (systemText) {
|
|
886
|
+
statusLog(statusLine, `${boldRed('● system:')} ${systemText}`);
|
|
887
|
+
}
|
|
888
|
+
return;
|
|
889
|
+
}
|
|
890
|
+
if (eventType === 'world' && (eventData.message || eventData.content)) {
|
|
891
|
+
const worldText = getSystemEventDisplayText(eventData);
|
|
892
|
+
if (worldText) {
|
|
893
|
+
statusLog(statusLine, `${gray('[World]')} ${worldText}`);
|
|
894
|
+
}
|
|
817
895
|
}
|
|
818
896
|
}
|
|
819
897
|
// World discovery and selection
|
|
@@ -878,9 +956,13 @@ async function selectWorld(rootPath, rl) {
|
|
|
878
956
|
// Load world from external file folder
|
|
879
957
|
async function loadWorldFromFile(currentRootPath, rl) {
|
|
880
958
|
const fs = await import('fs');
|
|
959
|
+
void currentRootPath;
|
|
960
|
+
let stagedGitHubWorld = null;
|
|
961
|
+
let resolvedSourcePath = '';
|
|
962
|
+
let importIsRequired = false;
|
|
881
963
|
// Get world folder path
|
|
882
|
-
const
|
|
883
|
-
rl.question(`\n${boldMagenta('Enter path to world folder:')} `, (answer) => {
|
|
964
|
+
const sourceInput = await new Promise((resolve) => {
|
|
965
|
+
rl.question(`\n${boldMagenta('Enter path to world folder (or @awesome-agent-world/<world-name>):')} `, (answer) => {
|
|
884
966
|
const trimmed = answer.trim();
|
|
885
967
|
if (trimmed === '') {
|
|
886
968
|
resolve(null);
|
|
@@ -890,28 +972,57 @@ async function loadWorldFromFile(currentRootPath, rl) {
|
|
|
890
972
|
}
|
|
891
973
|
});
|
|
892
974
|
});
|
|
893
|
-
if (!
|
|
975
|
+
if (!sourceInput) {
|
|
894
976
|
console.log(boldRed('Load cancelled.'));
|
|
895
977
|
return null;
|
|
896
978
|
}
|
|
897
|
-
// Validate folder exists
|
|
898
|
-
if (!fs.existsSync(folderPath)) {
|
|
899
|
-
console.log(boldRed(`Folder does not exist: ${folderPath}`));
|
|
900
|
-
return null;
|
|
901
|
-
}
|
|
902
979
|
try {
|
|
980
|
+
if (sourceInput.startsWith('@')) {
|
|
981
|
+
stagedGitHubWorld = await stageGitHubWorldFromShorthand(sourceInput);
|
|
982
|
+
resolvedSourcePath = stagedGitHubWorld.stagingRootPath;
|
|
983
|
+
importIsRequired = true;
|
|
984
|
+
console.log(green(`Fetched world source from GitHub: ${sourceInput}`));
|
|
985
|
+
if (stagedGitHubWorld.source.commitSha) {
|
|
986
|
+
console.log(` ${yellow('Source commit:')} ${stagedGitHubWorld.source.commitSha}`);
|
|
987
|
+
}
|
|
988
|
+
}
|
|
989
|
+
else {
|
|
990
|
+
resolvedSourcePath = sourceInput;
|
|
991
|
+
if (!fs.existsSync(resolvedSourcePath)) {
|
|
992
|
+
const fallbackShorthand = `@awesome-agent-world/${sourceInput}`;
|
|
993
|
+
try {
|
|
994
|
+
stagedGitHubWorld = await stageGitHubWorldFromShorthand(fallbackShorthand);
|
|
995
|
+
resolvedSourcePath = stagedGitHubWorld.stagingRootPath;
|
|
996
|
+
importIsRequired = true;
|
|
997
|
+
console.log(yellow(`Folder does not exist locally: ${sourceInput}`));
|
|
998
|
+
console.log(green(`Trying GitHub shorthand: ${fallbackShorthand}`));
|
|
999
|
+
if (stagedGitHubWorld.source.commitSha) {
|
|
1000
|
+
console.log(` ${yellow('Source commit:')} ${stagedGitHubWorld.source.commitSha}`);
|
|
1001
|
+
}
|
|
1002
|
+
}
|
|
1003
|
+
catch (fallbackError) {
|
|
1004
|
+
if (!(fallbackError instanceof GitHubWorldImportError)) {
|
|
1005
|
+
throw fallbackError;
|
|
1006
|
+
}
|
|
1007
|
+
}
|
|
1008
|
+
}
|
|
1009
|
+
}
|
|
1010
|
+
if (!fs.existsSync(resolvedSourcePath)) {
|
|
1011
|
+
console.log(boldRed(`Folder does not exist: ${resolvedSourcePath}`));
|
|
1012
|
+
return null;
|
|
1013
|
+
}
|
|
903
1014
|
// Import necessary functions
|
|
904
1015
|
const { createStorage } = await import('../core/storage/storage-factory.js');
|
|
905
|
-
const {
|
|
1016
|
+
const { createStorageFromEnv } = await import('../core/storage/storage-factory.js');
|
|
906
1017
|
// Create storage instance for source folder
|
|
907
1018
|
const sourceStorage = await createStorage({
|
|
908
1019
|
type: 'file',
|
|
909
|
-
rootPath:
|
|
1020
|
+
rootPath: resolvedSourcePath
|
|
910
1021
|
});
|
|
911
1022
|
// List worlds in the source folder
|
|
912
1023
|
const worldsInFolder = await sourceStorage.listWorlds();
|
|
913
1024
|
if (worldsInFolder.length === 0) {
|
|
914
|
-
console.log(boldRed(`No worlds found in: ${
|
|
1025
|
+
console.log(boldRed(`No worlds found in: ${resolvedSourcePath}`));
|
|
915
1026
|
return null;
|
|
916
1027
|
}
|
|
917
1028
|
// Select world if multiple
|
|
@@ -959,20 +1070,25 @@ async function loadWorldFromFile(currentRootPath, rl) {
|
|
|
959
1070
|
const chats = await sourceStorage.listChats(worldData.id);
|
|
960
1071
|
console.log(` ${yellow('Chats:')} ${chats.length}`);
|
|
961
1072
|
// Ask if user wants to import
|
|
962
|
-
const shouldImport =
|
|
963
|
-
|
|
964
|
-
|
|
965
|
-
|
|
1073
|
+
const shouldImport = importIsRequired
|
|
1074
|
+
? true
|
|
1075
|
+
: await new Promise((resolve) => {
|
|
1076
|
+
rl.question(`\n${boldMagenta('Import this world to current storage?')} ${boldMagenta('(yes/no):')} `, (answer) => {
|
|
1077
|
+
const trimmed = answer.trim().toLowerCase();
|
|
1078
|
+
resolve(trimmed === 'yes' || trimmed === 'y');
|
|
1079
|
+
});
|
|
966
1080
|
});
|
|
967
|
-
});
|
|
968
1081
|
if (!shouldImport) {
|
|
969
1082
|
console.log(yellow('World loaded from external storage (not imported).'));
|
|
970
1083
|
// Return world name with external path to use that storage
|
|
971
|
-
return { worldName: worldData.
|
|
1084
|
+
return { worldName: worldData.id, externalPath: resolvedSourcePath };
|
|
972
1085
|
}
|
|
973
|
-
// Check if world already exists in
|
|
974
|
-
const
|
|
975
|
-
|
|
1086
|
+
// Check if world already exists in active runtime storage
|
|
1087
|
+
const existingWorlds = await listWorlds();
|
|
1088
|
+
const idConflict = existingWorlds.find((world) => String(world?.id || '') === String(worldData?.id || ''));
|
|
1089
|
+
const nameConflict = existingWorlds.find((world) => String(world?.name || '').trim().toLowerCase() === String(worldData?.name || '').trim().toLowerCase());
|
|
1090
|
+
const existingWorld = idConflict || nameConflict;
|
|
1091
|
+
if (existingWorld) {
|
|
976
1092
|
// Confirm overwrite
|
|
977
1093
|
const shouldOverwrite = await new Promise((resolve) => {
|
|
978
1094
|
rl.question(`\n${boldYellow(`World '${worldData.name}' already exists. Overwrite?`)} ${boldMagenta('(yes/no):')} `, (answer) => {
|
|
@@ -983,17 +1099,18 @@ async function loadWorldFromFile(currentRootPath, rl) {
|
|
|
983
1099
|
if (!shouldOverwrite) {
|
|
984
1100
|
console.log(yellow('Import cancelled. Loading from external storage instead.'));
|
|
985
1101
|
// Return world name with external path to use that storage
|
|
986
|
-
return { worldName: worldData.
|
|
1102
|
+
return { worldName: worldData.id, externalPath: resolvedSourcePath };
|
|
987
1103
|
}
|
|
988
1104
|
// Delete existing world
|
|
989
|
-
await
|
|
990
|
-
|
|
1105
|
+
const deleted = await deleteWorld(String(existingWorld.id));
|
|
1106
|
+
if (!deleted) {
|
|
1107
|
+
console.log(boldRed(`Failed to delete existing world '${existingWorld.id}' before import.`));
|
|
1108
|
+
return null;
|
|
1109
|
+
}
|
|
1110
|
+
console.log(green(`Deleted existing world '${existingWorld.name || existingWorld.id}'`));
|
|
991
1111
|
}
|
|
992
|
-
// Create storage instance for target
|
|
993
|
-
const targetStorage = await
|
|
994
|
-
type: 'file',
|
|
995
|
-
rootPath: currentRootPath
|
|
996
|
-
});
|
|
1112
|
+
// Create storage instance for active runtime target
|
|
1113
|
+
const targetStorage = await createStorageFromEnv();
|
|
997
1114
|
// Save world
|
|
998
1115
|
await targetStorage.saveWorld(worldData);
|
|
999
1116
|
// Save all agents
|
|
@@ -1033,12 +1150,29 @@ async function loadWorldFromFile(currentRootPath, rl) {
|
|
|
1033
1150
|
console.log(` ${yellow('Agents:')} ${agents.length}`);
|
|
1034
1151
|
console.log(` ${yellow('Chats:')} ${chats.length}`);
|
|
1035
1152
|
console.log(` ${yellow('Events:')} ${eventCount}`);
|
|
1036
|
-
return { worldName: worldData.
|
|
1153
|
+
return { worldName: worldData.id };
|
|
1037
1154
|
}
|
|
1038
1155
|
catch (error) {
|
|
1156
|
+
if (error instanceof GitHubWorldImportError) {
|
|
1157
|
+
console.log(boldRed(`Error loading world: ${error.message}`));
|
|
1158
|
+
const details = error.details || {};
|
|
1159
|
+
const owner = String(details.owner || '');
|
|
1160
|
+
const repo = String(details.repo || '');
|
|
1161
|
+
const branch = String(details.branch || '');
|
|
1162
|
+
const worldPath = String(details.worldPath || '');
|
|
1163
|
+
if (owner && repo && branch && worldPath) {
|
|
1164
|
+
console.log(` ${yellow('Resolved source:')} ${owner}/${repo}@${branch}:${worldPath}`);
|
|
1165
|
+
}
|
|
1166
|
+
return null;
|
|
1167
|
+
}
|
|
1039
1168
|
console.log(boldRed(`Error loading world: ${error instanceof Error ? error.message : String(error)}`));
|
|
1040
1169
|
return null;
|
|
1041
1170
|
}
|
|
1171
|
+
finally {
|
|
1172
|
+
if (stagedGitHubWorld) {
|
|
1173
|
+
await stagedGitHubWorld.cleanup();
|
|
1174
|
+
}
|
|
1175
|
+
}
|
|
1042
1176
|
}
|
|
1043
1177
|
// Chat discovery and selection
|
|
1044
1178
|
async function selectChat(world, chats, currentChatId, rl) {
|
|
@@ -1143,6 +1277,7 @@ async function confirmOverwrite(message, rl) {
|
|
|
1143
1277
|
// Interactive mode: console-based interface
|
|
1144
1278
|
async function runInteractiveMode(options) {
|
|
1145
1279
|
const rootPath = options.root || DEFAULT_ROOT_PATH;
|
|
1280
|
+
const opikEnabledOverride = parseOptionalBoolean(options.opikEnabled);
|
|
1146
1281
|
const globalState = createGlobalState();
|
|
1147
1282
|
const streaming = createStreamingState();
|
|
1148
1283
|
const activityMonitor = new WorldActivityMonitor();
|
|
@@ -1164,7 +1299,7 @@ async function runInteractiveMode(options) {
|
|
|
1164
1299
|
try {
|
|
1165
1300
|
activityMonitor.reset();
|
|
1166
1301
|
statusLine.reset();
|
|
1167
|
-
worldState = await handleSubscribe(rootPath, options.world, streaming, globalState, activityMonitor, statusLine, rl);
|
|
1302
|
+
worldState = await handleSubscribe(rootPath, options.world, streaming, globalState, activityMonitor, statusLine, opikEnabledOverride, rl);
|
|
1168
1303
|
currentWorldName = options.world;
|
|
1169
1304
|
console.log(success(`Connected to world: ${currentWorldName}`));
|
|
1170
1305
|
if (worldState?.world) {
|
|
@@ -1190,7 +1325,7 @@ async function runInteractiveMode(options) {
|
|
|
1190
1325
|
try {
|
|
1191
1326
|
activityMonitor.reset();
|
|
1192
1327
|
statusLine.reset();
|
|
1193
|
-
worldState = await handleSubscribe(effectiveRootPath, selectedWorld.worldName, streaming, globalState, activityMonitor, statusLine, rl);
|
|
1328
|
+
worldState = await handleSubscribe(effectiveRootPath, selectedWorld.worldName, streaming, globalState, activityMonitor, statusLine, opikEnabledOverride, rl);
|
|
1194
1329
|
currentWorldName = selectedWorld.worldName;
|
|
1195
1330
|
console.log(success(`Connected to world: ${currentWorldName}`));
|
|
1196
1331
|
if (selectedWorld.externalPath) {
|
|
@@ -1218,7 +1353,7 @@ async function runInteractiveMode(options) {
|
|
|
1218
1353
|
console.log('');
|
|
1219
1354
|
// Display current chat messages after Quick Start tips
|
|
1220
1355
|
if (worldState?.world) {
|
|
1221
|
-
await displayChatMessages(worldState.world.id, worldState.
|
|
1356
|
+
await displayChatMessages(worldState.world.id, worldState.selectedChatId);
|
|
1222
1357
|
}
|
|
1223
1358
|
console.log(); // Empty line before prompt
|
|
1224
1359
|
rl.prompt();
|
|
@@ -1252,7 +1387,7 @@ async function runInteractiveMode(options) {
|
|
|
1252
1387
|
snapshot = activityMonitor.captureSnapshot();
|
|
1253
1388
|
}
|
|
1254
1389
|
try {
|
|
1255
|
-
const result = await processCLIInput(trimmedInput, worldState?.world || null, 'HUMAN');
|
|
1390
|
+
const result = await processCLIInput(trimmedInput, worldState?.world || null, 'HUMAN', worldState?.selectedChatId || null);
|
|
1256
1391
|
// Handle exit commands from result (redundant, but keep for safety)
|
|
1257
1392
|
if (result.data?.exit) {
|
|
1258
1393
|
if (isExiting)
|
|
@@ -1290,7 +1425,7 @@ async function runInteractiveMode(options) {
|
|
|
1290
1425
|
logger.debug(`Subscribing to world: ${selectedWorld.worldName}...`);
|
|
1291
1426
|
activityMonitor.reset();
|
|
1292
1427
|
statusLine.reset();
|
|
1293
|
-
worldState = await handleSubscribe(effectiveRootPath, selectedWorld.worldName, streaming, globalState, activityMonitor, statusLine, rl);
|
|
1428
|
+
worldState = await handleSubscribe(effectiveRootPath, selectedWorld.worldName, streaming, globalState, activityMonitor, statusLine, opikEnabledOverride, rl);
|
|
1294
1429
|
currentWorldName = selectedWorld.worldName;
|
|
1295
1430
|
console.log(success(`Connected to world: ${currentWorldName}`));
|
|
1296
1431
|
if (selectedWorld.externalPath) {
|
|
@@ -1299,7 +1434,7 @@ async function runInteractiveMode(options) {
|
|
|
1299
1434
|
if (worldState?.world) {
|
|
1300
1435
|
console.log(`${gray('Agents:')} ${yellow(String(worldState.world.agents?.size || 0))} ${gray('| Turn Limit:')} ${yellow(String(worldState.world.turnLimit || 'N/A'))}`);
|
|
1301
1436
|
// Display current chat messages
|
|
1302
|
-
await displayChatMessages(worldState.world.id, worldState.
|
|
1437
|
+
await displayChatMessages(worldState.world.id, worldState.selectedChatId);
|
|
1303
1438
|
}
|
|
1304
1439
|
}
|
|
1305
1440
|
catch (err) {
|
|
@@ -1337,6 +1472,7 @@ async function runInteractiveMode(options) {
|
|
|
1337
1472
|
// console.log(boldBlue('Refreshing world state...'));
|
|
1338
1473
|
const refreshedWorld = await worldState.subscription.refresh(rootPath);
|
|
1339
1474
|
worldState.world = refreshedWorld;
|
|
1475
|
+
worldState.selectedChatId = selectedChatId;
|
|
1340
1476
|
console.log(success('World state refreshed'));
|
|
1341
1477
|
}
|
|
1342
1478
|
}
|
|
@@ -1449,6 +1585,8 @@ async function runInteractiveMode(options) {
|
|
|
1449
1585
|
// Use the subscription's refresh method to properly destroy old world and create new
|
|
1450
1586
|
const refreshedWorld = await worldState.subscription.refresh(rootPath);
|
|
1451
1587
|
worldState.world = refreshedWorld;
|
|
1588
|
+
const refreshedChatId = String(result.data?.currentChatId || refreshedWorld?.currentChatId || '').trim();
|
|
1589
|
+
worldState.selectedChatId = refreshedChatId || worldState.selectedChatId;
|
|
1452
1590
|
console.log(success('World state refreshed'));
|
|
1453
1591
|
}
|
|
1454
1592
|
catch (err) {
|
|
@@ -1539,6 +1677,19 @@ function determineStreamingMode(streamingFlag, isTTY) {
|
|
|
1539
1677
|
// Auto-detect: enable streaming for interactive (TTY), disable for pipeline
|
|
1540
1678
|
return isTTY;
|
|
1541
1679
|
}
|
|
1680
|
+
function parseOptionalBoolean(value) {
|
|
1681
|
+
if (!value) {
|
|
1682
|
+
return undefined;
|
|
1683
|
+
}
|
|
1684
|
+
const normalized = value.trim().toLowerCase();
|
|
1685
|
+
if (['true', '1', 'yes', 'on'].includes(normalized)) {
|
|
1686
|
+
return true;
|
|
1687
|
+
}
|
|
1688
|
+
if (['false', '0', 'no', 'off'].includes(normalized)) {
|
|
1689
|
+
return false;
|
|
1690
|
+
}
|
|
1691
|
+
return undefined;
|
|
1692
|
+
}
|
|
1542
1693
|
// Main CLI entry point
|
|
1543
1694
|
async function main() {
|
|
1544
1695
|
// Configure LLM providers from environment variables at startup
|
|
@@ -1555,6 +1706,7 @@ async function main() {
|
|
|
1555
1706
|
.option('-c, --command <cmd>', 'Command to execute in pipeline mode')
|
|
1556
1707
|
.option('-l, --logLevel <level>', 'Set log level (trace, debug, info, warn, error)', 'error')
|
|
1557
1708
|
.option('--streaming', 'Enable streaming responses (default: auto-detected from TTY)')
|
|
1709
|
+
.option('--opik-enabled <true|false>', 'Override OPIK_ENABLED for this CLI run')
|
|
1558
1710
|
.option('-s, --server', 'Launch the server before running CLI')
|
|
1559
1711
|
.allowUnknownOption()
|
|
1560
1712
|
.allowExcessArguments()
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CLI System Event Formatting Helpers
|
|
3
|
+
*
|
|
4
|
+
* Purpose:
|
|
5
|
+
* - Convert runtime `system` event payloads into readable CLI output text.
|
|
6
|
+
*
|
|
7
|
+
* Key Features:
|
|
8
|
+
* - Supports plain-string and structured-object system payloads.
|
|
9
|
+
* - Preserves important status families such as title updates and queue failures.
|
|
10
|
+
* - Keeps formatting pure so both interactive and pipeline paths share the same logic.
|
|
11
|
+
*
|
|
12
|
+
* Notes on Implementation:
|
|
13
|
+
* - Leaf helper with no terminal side effects.
|
|
14
|
+
* - Unknown payloads return `null` so callers can skip empty/noise events.
|
|
15
|
+
*
|
|
16
|
+
* Summary of Recent Changes:
|
|
17
|
+
* - 2026-03-12: Created for cross-client system-status parity.
|
|
18
|
+
*/
|
|
19
|
+
export interface CliSystemEventPayload {
|
|
20
|
+
message?: unknown;
|
|
21
|
+
content?: unknown;
|
|
22
|
+
eventType?: unknown;
|
|
23
|
+
type?: unknown;
|
|
24
|
+
title?: unknown;
|
|
25
|
+
[key: string]: unknown;
|
|
26
|
+
}
|
|
27
|
+
export declare function getSystemEventDisplayText(eventData: CliSystemEventPayload | null | undefined): string | null;
|