agent-world 0.12.3 → 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 +105 -17
- package/dist/cli/commands.d.ts +7 -1
- package/dist/cli/commands.js +27 -10
- package/dist/cli/hitl.d.ts +9 -2
- package/dist/cli/hitl.js +61 -20
- package/dist/cli/index.js +250 -96
- package/dist/cli/system-events.d.ts +27 -0
- package/dist/cli/system-events.js +63 -0
- package/dist/core/activity-tracker.d.ts +38 -2
- package/dist/core/activity-tracker.d.ts.map +1 -1
- package/dist/core/activity-tracker.js +62 -9
- 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 +28 -25
- package/dist/core/create-agent-tool.d.ts.map +1 -1
- package/dist/core/create-agent-tool.js +264 -141
- 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 +214 -38
- 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 -61
- package/dist/core/events/persistence.js.map +1 -1
- package/dist/core/events/publishers.d.ts +13 -16
- package/dist/core/events/publishers.d.ts.map +1 -1
- package/dist/core/events/publishers.js +54 -55
- 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 +68 -147
- 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 +73 -0
- package/dist/core/hitl-tool.d.ts.map +1 -0
- package/dist/core/hitl-tool.js +284 -0
- package/dist/core/hitl-tool.js.map +1 -0
- package/dist/core/hitl.d.ts +85 -8
- package/dist/core/hitl.d.ts.map +1 -1
- package/dist/core/hitl.js +375 -61
- package/dist/core/hitl.js.map +1 -1
- package/dist/core/index.d.ts +12 -7
- package/dist/core/index.d.ts.map +1 -1
- package/dist/core/index.js +11 -6
- package/dist/core/index.js.map +1 -1
- package/dist/core/llm-manager.d.ts +17 -0
- package/dist/core/llm-manager.d.ts.map +1 -1
- package/dist/core/llm-manager.js +335 -43
- 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 +41 -52
- package/dist/core/managers.d.ts.map +1 -1
- package/dist/core/managers.js +422 -533
- package/dist/core/managers.js.map +1 -1
- package/dist/core/mcp-server-registry.d.ts +19 -2
- package/dist/core/mcp-server-registry.d.ts.map +1 -1
- package/dist/core/mcp-server-registry.js +168 -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 +9 -2
- package/dist/core/tool-utils.d.ts.map +1 -1
- package/dist/core/tool-utils.js +122 -28
- package/dist/core/tool-utils.js.map +1 -1
- package/dist/core/types.d.ts +69 -36
- package/dist/core/types.d.ts.map +1 -1
- package/dist/core/types.js +3 -2
- package/dist/core/types.js.map +1 -1
- package/dist/core/utils.d.ts +16 -0
- package/dist/core/utils.d.ts.map +1 -1
- package/dist/core/utils.js +99 -24
- 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 +288 -58
- 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 +13 -2
- package/dist/server/sse-handler.js +194 -26
- 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-BO20H4xt.js +0 -96
- package/dist/public/assets/index-ETY7W5_S.css +0 -1
package/dist/cli/index.js
CHANGED
|
@@ -13,9 +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.
|
|
20
|
+
* - 2026-02-20: Enforced options-only HITL handling in interactive and pipeline modes.
|
|
16
21
|
* - 2026-02-14: Added interactive + pipeline HITL option response handling for generic approval requests.
|
|
17
22
|
* - 2026-02-11: Fixed tool-stream timeout: extendTimeout() resets idle timeout on streaming data
|
|
18
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`.
|
|
19
25
|
* - 2026-01-09: Added --streaming flag for explicit streaming control (overrides TTY auto-detection)
|
|
20
26
|
* - 2025-02-06: Prevented duplicate MESSAGE output when streaming already rendered agent responses
|
|
21
27
|
* - 2025-11-01: Added multi-world selection in loadWorldFromFile
|
|
@@ -76,14 +82,17 @@ import path from 'path';
|
|
|
76
82
|
import { fileURLToPath } from 'url';
|
|
77
83
|
import { program } from 'commander';
|
|
78
84
|
import readline from 'readline';
|
|
79
|
-
import { listWorlds, subscribeWorld,
|
|
85
|
+
import { listWorlds, deleteWorld, subscribeWorld, submitWorldHitlResponse, GitHubWorldImportError, stageGitHubWorldFromShorthand, createCategoryLogger, LLMProvider, enableStreaming, disableStreaming } from '../core/index.js';
|
|
80
86
|
import { EventType } from '../core/types.js';
|
|
81
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';
|
|
82
90
|
import { processCLIInput, displayChatMessages } from './commands.js';
|
|
83
91
|
import { createStreamingState, handleWorldEventWithStreaming, handleToolEvents, } from './stream.js';
|
|
84
92
|
import { configureLLMProvider } from '../core/llm-config.js';
|
|
85
93
|
import { createStatusLineManager, log as statusLog, } from './display.js';
|
|
86
|
-
import {
|
|
94
|
+
import { getSystemEventDisplayText } from './system-events.js';
|
|
95
|
+
import { markHitlRequestHandled, parseHitlPromptFromToolEvent, resolveHitlOptionSelectionInput, } from './hitl.js';
|
|
87
96
|
// Create CLI category logger after logger auto-initialization
|
|
88
97
|
const logger = createCategoryLogger('cli');
|
|
89
98
|
function createGlobalState() {
|
|
@@ -394,11 +403,87 @@ function printCLIResult(result) {
|
|
|
394
403
|
* @param rl - Readline interface for interactive mode (undefined for pipeline mode)
|
|
395
404
|
* @returns Map of event types to listener functions for cleanup
|
|
396
405
|
*/
|
|
397
|
-
function attachCLIListeners(world, streaming, globalState, activityMonitor, statusLine, rl) {
|
|
406
|
+
function attachCLIListeners(world, streaming, globalState, activityMonitor, statusLine, getSelectedChatId, rl) {
|
|
398
407
|
const listeners = new Map();
|
|
399
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
|
+
};
|
|
400
434
|
// World activity events
|
|
401
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
|
+
}
|
|
402
487
|
activityMonitor.handle(eventData);
|
|
403
488
|
// Only render activity progress in interactive mode
|
|
404
489
|
if (streaming && globalState && rl && statusLine) {
|
|
@@ -411,6 +496,9 @@ function attachCLIListeners(world, streaming, globalState, activityMonitor, stat
|
|
|
411
496
|
listeners.set(EventType.WORLD, worldListener);
|
|
412
497
|
// Message events
|
|
413
498
|
const messageListener = (eventData) => {
|
|
499
|
+
if (!isChatEventInScope(eventData?.chatId, false)) {
|
|
500
|
+
return;
|
|
501
|
+
}
|
|
414
502
|
if (eventData.content &&
|
|
415
503
|
typeof eventData.content === 'string' &&
|
|
416
504
|
eventData.content.includes('Success message sent'))
|
|
@@ -434,8 +522,14 @@ function attachCLIListeners(world, streaming, globalState, activityMonitor, stat
|
|
|
434
522
|
// SSE events (interactive mode only - pipeline mode uses non-streaming LLM calls)
|
|
435
523
|
if (streaming && globalState && rl && statusLine) {
|
|
436
524
|
const sseListener = (eventData) => {
|
|
437
|
-
|
|
438
|
-
|
|
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) {
|
|
439
533
|
activityMonitor.extendTimeout();
|
|
440
534
|
}
|
|
441
535
|
handleWorldEvent(EventType.SSE, eventData, streaming, globalState, activityMonitor, statusLine, rl)
|
|
@@ -445,9 +539,15 @@ function attachCLIListeners(world, streaming, globalState, activityMonitor, stat
|
|
|
445
539
|
listeners.set(EventType.SSE, sseListener);
|
|
446
540
|
}
|
|
447
541
|
else {
|
|
448
|
-
// Pipeline mode: listen for
|
|
542
|
+
// Pipeline mode: listen for shell stream events to extend timeout on long-running commands.
|
|
449
543
|
const sseTimeoutListener = (eventData) => {
|
|
450
|
-
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) {
|
|
451
551
|
activityMonitor.extendTimeout();
|
|
452
552
|
}
|
|
453
553
|
};
|
|
@@ -456,49 +556,7 @@ function attachCLIListeners(world, streaming, globalState, activityMonitor, stat
|
|
|
456
556
|
}
|
|
457
557
|
// System events
|
|
458
558
|
const systemListener = (eventData) => {
|
|
459
|
-
|
|
460
|
-
if (hitlRequest) {
|
|
461
|
-
hitlPromptChain = hitlPromptChain
|
|
462
|
-
.then(async () => {
|
|
463
|
-
if (streaming && globalState && rl && statusLine) {
|
|
464
|
-
globalState.hitlPromptActive = true;
|
|
465
|
-
try {
|
|
466
|
-
const selectedOptionId = await promptHitlOptionSelection(hitlRequest, statusLine, rl);
|
|
467
|
-
const result = submitWorldOptionResponse({
|
|
468
|
-
worldId: world.id,
|
|
469
|
-
requestId: hitlRequest.requestId,
|
|
470
|
-
optionId: selectedOptionId
|
|
471
|
-
});
|
|
472
|
-
if (!result.accepted) {
|
|
473
|
-
statusLine.pause();
|
|
474
|
-
console.log(boldRed(`Failed to submit approval response: ${result.reason || 'unknown error'}`));
|
|
475
|
-
statusLine.resume();
|
|
476
|
-
return;
|
|
477
|
-
}
|
|
478
|
-
statusLine.pause();
|
|
479
|
-
console.log(green(`Approved option: ${selectedOptionId}`));
|
|
480
|
-
statusLine.resume();
|
|
481
|
-
return;
|
|
482
|
-
}
|
|
483
|
-
finally {
|
|
484
|
-
globalState.hitlPromptActive = false;
|
|
485
|
-
}
|
|
486
|
-
}
|
|
487
|
-
// Pipeline/non-interactive mode: auto-respond with default option to avoid blocking.
|
|
488
|
-
const result = submitWorldOptionResponse({
|
|
489
|
-
worldId: world.id,
|
|
490
|
-
requestId: hitlRequest.requestId,
|
|
491
|
-
optionId: hitlRequest.defaultOptionId
|
|
492
|
-
});
|
|
493
|
-
if (!result.accepted) {
|
|
494
|
-
console.error(boldRed(`Failed to auto-respond HITL request: ${result.reason || 'unknown error'}`));
|
|
495
|
-
return;
|
|
496
|
-
}
|
|
497
|
-
console.log(`${gray('● system:')} Auto-selected HITL option "${hitlRequest.defaultOptionId}"`);
|
|
498
|
-
})
|
|
499
|
-
.catch((error) => {
|
|
500
|
-
console.error(boldRed(`Error handling HITL request: ${error instanceof Error ? error.message : String(error)}`));
|
|
501
|
-
});
|
|
559
|
+
if (!isChatEventInScope(eventData?.chatId, false)) {
|
|
502
560
|
return;
|
|
503
561
|
}
|
|
504
562
|
if (eventData.content &&
|
|
@@ -509,8 +567,11 @@ function attachCLIListeners(world, streaming, globalState, activityMonitor, stat
|
|
|
509
567
|
handleWorldEvent(EventType.SYSTEM, eventData, streaming, globalState, activityMonitor, statusLine, rl)
|
|
510
568
|
.catch(err => console.error('Error handling system event:', err));
|
|
511
569
|
}
|
|
512
|
-
else
|
|
513
|
-
|
|
570
|
+
else {
|
|
571
|
+
const systemText = getSystemEventDisplayText(eventData);
|
|
572
|
+
if (systemText) {
|
|
573
|
+
console.log(`${boldRed('● system:')} ${systemText}`);
|
|
574
|
+
}
|
|
514
575
|
}
|
|
515
576
|
};
|
|
516
577
|
world.eventEmitter.on(EventType.SYSTEM, systemListener);
|
|
@@ -535,6 +596,7 @@ async function runPipelineMode(options, messageFromArgs) {
|
|
|
535
596
|
let worldSubscription = null;
|
|
536
597
|
let cliListeners = null;
|
|
537
598
|
const activityMonitor = new WorldActivityMonitor();
|
|
599
|
+
const opikEnabledOverride = parseOptionalBoolean(options.opikEnabled);
|
|
538
600
|
try {
|
|
539
601
|
if (options.world) {
|
|
540
602
|
// Subscribe to world lifecycle but do not request forwarding callbacks
|
|
@@ -544,9 +606,11 @@ async function runPipelineMode(options, messageFromArgs) {
|
|
|
544
606
|
process.exit(1);
|
|
545
607
|
}
|
|
546
608
|
world = worldSubscription.world;
|
|
609
|
+
await attachOptionalOpikTracer(world, { source: 'cli', enabledOverride: opikEnabledOverride });
|
|
547
610
|
// Attach direct listeners to the world.eventEmitter for pipeline handling
|
|
548
611
|
// Note: Pipeline mode uses non-streaming LLM calls, so SSE events are not needed
|
|
549
|
-
|
|
612
|
+
const selectedChatId = String(world?.currentChatId || '').trim() || null;
|
|
613
|
+
cliListeners = attachCLIListeners(world, null, null, activityMonitor, null, () => selectedChatId);
|
|
550
614
|
}
|
|
551
615
|
// Execute command from --command option
|
|
552
616
|
if (options.command) {
|
|
@@ -555,7 +619,7 @@ async function runPipelineMode(options, messageFromArgs) {
|
|
|
555
619
|
process.exit(1);
|
|
556
620
|
}
|
|
557
621
|
const snapshot = activityMonitor.captureSnapshot();
|
|
558
|
-
const result = await processCLIInput(options.command, world, 'human');
|
|
622
|
+
const result = await processCLIInput(options.command, world, 'human', String(world?.currentChatId || '').trim() || null);
|
|
559
623
|
printCLIResult(result);
|
|
560
624
|
if (!options.command.startsWith('/') && world) {
|
|
561
625
|
try {
|
|
@@ -588,7 +652,7 @@ async function runPipelineMode(options, messageFromArgs) {
|
|
|
588
652
|
process.exit(1);
|
|
589
653
|
}
|
|
590
654
|
const snapshot = activityMonitor.captureSnapshot();
|
|
591
|
-
const result = await processCLIInput(messageFromArgs, world, 'human');
|
|
655
|
+
const result = await processCLIInput(messageFromArgs, world, 'human', String(world?.currentChatId || '').trim() || null);
|
|
592
656
|
printCLIResult(result);
|
|
593
657
|
try {
|
|
594
658
|
// Event-driven completion: wait for world idle state
|
|
@@ -619,7 +683,7 @@ async function runPipelineMode(options, messageFromArgs) {
|
|
|
619
683
|
process.exit(1);
|
|
620
684
|
}
|
|
621
685
|
const snapshot = activityMonitor.captureSnapshot();
|
|
622
|
-
const result = await processCLIInput(input.trim(), world, 'HUMAN');
|
|
686
|
+
const result = await processCLIInput(input.trim(), world, 'HUMAN', String(world?.currentChatId || '').trim() || null);
|
|
623
687
|
printCLIResult(result);
|
|
624
688
|
try {
|
|
625
689
|
// Event-driven completion: wait for world idle state
|
|
@@ -679,20 +743,26 @@ function cleanupWorldSubscription(worldState) {
|
|
|
679
743
|
* @param rl - Readline interface for interactive input
|
|
680
744
|
* @returns WorldState with subscription and world instance
|
|
681
745
|
*/
|
|
682
|
-
async function handleSubscribe(rootPath, worldName, streaming, globalState, activityMonitor, statusLine, rl) {
|
|
746
|
+
async function handleSubscribe(rootPath, worldName, streaming, globalState, activityMonitor, statusLine, opikEnabledOverride, rl) {
|
|
683
747
|
// Subscribe to world lifecycle but do not request forwarding callbacks
|
|
684
748
|
const subscription = await subscribeWorld(worldName, { isOpen: true });
|
|
685
749
|
if (!subscription)
|
|
686
750
|
throw new Error('Failed to load world');
|
|
687
751
|
const world = subscription.world;
|
|
752
|
+
await attachOptionalOpikTracer(world, { source: 'cli', enabledOverride: opikEnabledOverride });
|
|
688
753
|
// Store world in globalState for access in interactive event handlers.
|
|
689
754
|
if (globalState) {
|
|
690
755
|
globalState.world = world;
|
|
691
756
|
}
|
|
692
757
|
// Attach direct listeners to the world.eventEmitter for CLI handling
|
|
693
758
|
// Interactive mode needs all event types including SSE for streaming responses
|
|
694
|
-
|
|
695
|
-
|
|
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;
|
|
696
766
|
}
|
|
697
767
|
// Handle world events with streaming support
|
|
698
768
|
async function handleWorldEvent(eventType, eventData, streaming, globalState, activityMonitor, statusLine, rl) {
|
|
@@ -810,8 +880,18 @@ async function handleWorldEvent(eventType, eventData, streaming, globalState, ac
|
|
|
810
880
|
}
|
|
811
881
|
return;
|
|
812
882
|
}
|
|
813
|
-
if (
|
|
814
|
-
|
|
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
|
+
}
|
|
815
895
|
}
|
|
816
896
|
}
|
|
817
897
|
// World discovery and selection
|
|
@@ -876,9 +956,13 @@ async function selectWorld(rootPath, rl) {
|
|
|
876
956
|
// Load world from external file folder
|
|
877
957
|
async function loadWorldFromFile(currentRootPath, rl) {
|
|
878
958
|
const fs = await import('fs');
|
|
959
|
+
void currentRootPath;
|
|
960
|
+
let stagedGitHubWorld = null;
|
|
961
|
+
let resolvedSourcePath = '';
|
|
962
|
+
let importIsRequired = false;
|
|
879
963
|
// Get world folder path
|
|
880
|
-
const
|
|
881
|
-
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) => {
|
|
882
966
|
const trimmed = answer.trim();
|
|
883
967
|
if (trimmed === '') {
|
|
884
968
|
resolve(null);
|
|
@@ -888,28 +972,57 @@ async function loadWorldFromFile(currentRootPath, rl) {
|
|
|
888
972
|
}
|
|
889
973
|
});
|
|
890
974
|
});
|
|
891
|
-
if (!
|
|
975
|
+
if (!sourceInput) {
|
|
892
976
|
console.log(boldRed('Load cancelled.'));
|
|
893
977
|
return null;
|
|
894
978
|
}
|
|
895
|
-
// Validate folder exists
|
|
896
|
-
if (!fs.existsSync(folderPath)) {
|
|
897
|
-
console.log(boldRed(`Folder does not exist: ${folderPath}`));
|
|
898
|
-
return null;
|
|
899
|
-
}
|
|
900
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
|
+
}
|
|
901
1014
|
// Import necessary functions
|
|
902
1015
|
const { createStorage } = await import('../core/storage/storage-factory.js');
|
|
903
|
-
const {
|
|
1016
|
+
const { createStorageFromEnv } = await import('../core/storage/storage-factory.js');
|
|
904
1017
|
// Create storage instance for source folder
|
|
905
1018
|
const sourceStorage = await createStorage({
|
|
906
1019
|
type: 'file',
|
|
907
|
-
rootPath:
|
|
1020
|
+
rootPath: resolvedSourcePath
|
|
908
1021
|
});
|
|
909
1022
|
// List worlds in the source folder
|
|
910
1023
|
const worldsInFolder = await sourceStorage.listWorlds();
|
|
911
1024
|
if (worldsInFolder.length === 0) {
|
|
912
|
-
console.log(boldRed(`No worlds found in: ${
|
|
1025
|
+
console.log(boldRed(`No worlds found in: ${resolvedSourcePath}`));
|
|
913
1026
|
return null;
|
|
914
1027
|
}
|
|
915
1028
|
// Select world if multiple
|
|
@@ -957,20 +1070,25 @@ async function loadWorldFromFile(currentRootPath, rl) {
|
|
|
957
1070
|
const chats = await sourceStorage.listChats(worldData.id);
|
|
958
1071
|
console.log(` ${yellow('Chats:')} ${chats.length}`);
|
|
959
1072
|
// Ask if user wants to import
|
|
960
|
-
const shouldImport =
|
|
961
|
-
|
|
962
|
-
|
|
963
|
-
|
|
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
|
+
});
|
|
964
1080
|
});
|
|
965
|
-
});
|
|
966
1081
|
if (!shouldImport) {
|
|
967
1082
|
console.log(yellow('World loaded from external storage (not imported).'));
|
|
968
1083
|
// Return world name with external path to use that storage
|
|
969
|
-
return { worldName: worldData.
|
|
1084
|
+
return { worldName: worldData.id, externalPath: resolvedSourcePath };
|
|
970
1085
|
}
|
|
971
|
-
// Check if world already exists in
|
|
972
|
-
const
|
|
973
|
-
|
|
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) {
|
|
974
1092
|
// Confirm overwrite
|
|
975
1093
|
const shouldOverwrite = await new Promise((resolve) => {
|
|
976
1094
|
rl.question(`\n${boldYellow(`World '${worldData.name}' already exists. Overwrite?`)} ${boldMagenta('(yes/no):')} `, (answer) => {
|
|
@@ -981,17 +1099,18 @@ async function loadWorldFromFile(currentRootPath, rl) {
|
|
|
981
1099
|
if (!shouldOverwrite) {
|
|
982
1100
|
console.log(yellow('Import cancelled. Loading from external storage instead.'));
|
|
983
1101
|
// Return world name with external path to use that storage
|
|
984
|
-
return { worldName: worldData.
|
|
1102
|
+
return { worldName: worldData.id, externalPath: resolvedSourcePath };
|
|
985
1103
|
}
|
|
986
1104
|
// Delete existing world
|
|
987
|
-
await
|
|
988
|
-
|
|
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}'`));
|
|
989
1111
|
}
|
|
990
|
-
// Create storage instance for target
|
|
991
|
-
const targetStorage = await
|
|
992
|
-
type: 'file',
|
|
993
|
-
rootPath: currentRootPath
|
|
994
|
-
});
|
|
1112
|
+
// Create storage instance for active runtime target
|
|
1113
|
+
const targetStorage = await createStorageFromEnv();
|
|
995
1114
|
// Save world
|
|
996
1115
|
await targetStorage.saveWorld(worldData);
|
|
997
1116
|
// Save all agents
|
|
@@ -1031,12 +1150,29 @@ async function loadWorldFromFile(currentRootPath, rl) {
|
|
|
1031
1150
|
console.log(` ${yellow('Agents:')} ${agents.length}`);
|
|
1032
1151
|
console.log(` ${yellow('Chats:')} ${chats.length}`);
|
|
1033
1152
|
console.log(` ${yellow('Events:')} ${eventCount}`);
|
|
1034
|
-
return { worldName: worldData.
|
|
1153
|
+
return { worldName: worldData.id };
|
|
1035
1154
|
}
|
|
1036
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
|
+
}
|
|
1037
1168
|
console.log(boldRed(`Error loading world: ${error instanceof Error ? error.message : String(error)}`));
|
|
1038
1169
|
return null;
|
|
1039
1170
|
}
|
|
1171
|
+
finally {
|
|
1172
|
+
if (stagedGitHubWorld) {
|
|
1173
|
+
await stagedGitHubWorld.cleanup();
|
|
1174
|
+
}
|
|
1175
|
+
}
|
|
1040
1176
|
}
|
|
1041
1177
|
// Chat discovery and selection
|
|
1042
1178
|
async function selectChat(world, chats, currentChatId, rl) {
|
|
@@ -1141,6 +1277,7 @@ async function confirmOverwrite(message, rl) {
|
|
|
1141
1277
|
// Interactive mode: console-based interface
|
|
1142
1278
|
async function runInteractiveMode(options) {
|
|
1143
1279
|
const rootPath = options.root || DEFAULT_ROOT_PATH;
|
|
1280
|
+
const opikEnabledOverride = parseOptionalBoolean(options.opikEnabled);
|
|
1144
1281
|
const globalState = createGlobalState();
|
|
1145
1282
|
const streaming = createStreamingState();
|
|
1146
1283
|
const activityMonitor = new WorldActivityMonitor();
|
|
@@ -1162,7 +1299,7 @@ async function runInteractiveMode(options) {
|
|
|
1162
1299
|
try {
|
|
1163
1300
|
activityMonitor.reset();
|
|
1164
1301
|
statusLine.reset();
|
|
1165
|
-
worldState = await handleSubscribe(rootPath, options.world, streaming, globalState, activityMonitor, statusLine, rl);
|
|
1302
|
+
worldState = await handleSubscribe(rootPath, options.world, streaming, globalState, activityMonitor, statusLine, opikEnabledOverride, rl);
|
|
1166
1303
|
currentWorldName = options.world;
|
|
1167
1304
|
console.log(success(`Connected to world: ${currentWorldName}`));
|
|
1168
1305
|
if (worldState?.world) {
|
|
@@ -1188,7 +1325,7 @@ async function runInteractiveMode(options) {
|
|
|
1188
1325
|
try {
|
|
1189
1326
|
activityMonitor.reset();
|
|
1190
1327
|
statusLine.reset();
|
|
1191
|
-
worldState = await handleSubscribe(effectiveRootPath, selectedWorld.worldName, streaming, globalState, activityMonitor, statusLine, rl);
|
|
1328
|
+
worldState = await handleSubscribe(effectiveRootPath, selectedWorld.worldName, streaming, globalState, activityMonitor, statusLine, opikEnabledOverride, rl);
|
|
1192
1329
|
currentWorldName = selectedWorld.worldName;
|
|
1193
1330
|
console.log(success(`Connected to world: ${currentWorldName}`));
|
|
1194
1331
|
if (selectedWorld.externalPath) {
|
|
@@ -1216,7 +1353,7 @@ async function runInteractiveMode(options) {
|
|
|
1216
1353
|
console.log('');
|
|
1217
1354
|
// Display current chat messages after Quick Start tips
|
|
1218
1355
|
if (worldState?.world) {
|
|
1219
|
-
await displayChatMessages(worldState.world.id, worldState.
|
|
1356
|
+
await displayChatMessages(worldState.world.id, worldState.selectedChatId);
|
|
1220
1357
|
}
|
|
1221
1358
|
console.log(); // Empty line before prompt
|
|
1222
1359
|
rl.prompt();
|
|
@@ -1250,7 +1387,7 @@ async function runInteractiveMode(options) {
|
|
|
1250
1387
|
snapshot = activityMonitor.captureSnapshot();
|
|
1251
1388
|
}
|
|
1252
1389
|
try {
|
|
1253
|
-
const result = await processCLIInput(trimmedInput, worldState?.world || null, 'HUMAN');
|
|
1390
|
+
const result = await processCLIInput(trimmedInput, worldState?.world || null, 'HUMAN', worldState?.selectedChatId || null);
|
|
1254
1391
|
// Handle exit commands from result (redundant, but keep for safety)
|
|
1255
1392
|
if (result.data?.exit) {
|
|
1256
1393
|
if (isExiting)
|
|
@@ -1288,7 +1425,7 @@ async function runInteractiveMode(options) {
|
|
|
1288
1425
|
logger.debug(`Subscribing to world: ${selectedWorld.worldName}...`);
|
|
1289
1426
|
activityMonitor.reset();
|
|
1290
1427
|
statusLine.reset();
|
|
1291
|
-
worldState = await handleSubscribe(effectiveRootPath, selectedWorld.worldName, streaming, globalState, activityMonitor, statusLine, rl);
|
|
1428
|
+
worldState = await handleSubscribe(effectiveRootPath, selectedWorld.worldName, streaming, globalState, activityMonitor, statusLine, opikEnabledOverride, rl);
|
|
1292
1429
|
currentWorldName = selectedWorld.worldName;
|
|
1293
1430
|
console.log(success(`Connected to world: ${currentWorldName}`));
|
|
1294
1431
|
if (selectedWorld.externalPath) {
|
|
@@ -1297,7 +1434,7 @@ async function runInteractiveMode(options) {
|
|
|
1297
1434
|
if (worldState?.world) {
|
|
1298
1435
|
console.log(`${gray('Agents:')} ${yellow(String(worldState.world.agents?.size || 0))} ${gray('| Turn Limit:')} ${yellow(String(worldState.world.turnLimit || 'N/A'))}`);
|
|
1299
1436
|
// Display current chat messages
|
|
1300
|
-
await displayChatMessages(worldState.world.id, worldState.
|
|
1437
|
+
await displayChatMessages(worldState.world.id, worldState.selectedChatId);
|
|
1301
1438
|
}
|
|
1302
1439
|
}
|
|
1303
1440
|
catch (err) {
|
|
@@ -1335,6 +1472,7 @@ async function runInteractiveMode(options) {
|
|
|
1335
1472
|
// console.log(boldBlue('Refreshing world state...'));
|
|
1336
1473
|
const refreshedWorld = await worldState.subscription.refresh(rootPath);
|
|
1337
1474
|
worldState.world = refreshedWorld;
|
|
1475
|
+
worldState.selectedChatId = selectedChatId;
|
|
1338
1476
|
console.log(success('World state refreshed'));
|
|
1339
1477
|
}
|
|
1340
1478
|
}
|
|
@@ -1447,6 +1585,8 @@ async function runInteractiveMode(options) {
|
|
|
1447
1585
|
// Use the subscription's refresh method to properly destroy old world and create new
|
|
1448
1586
|
const refreshedWorld = await worldState.subscription.refresh(rootPath);
|
|
1449
1587
|
worldState.world = refreshedWorld;
|
|
1588
|
+
const refreshedChatId = String(result.data?.currentChatId || refreshedWorld?.currentChatId || '').trim();
|
|
1589
|
+
worldState.selectedChatId = refreshedChatId || worldState.selectedChatId;
|
|
1450
1590
|
console.log(success('World state refreshed'));
|
|
1451
1591
|
}
|
|
1452
1592
|
catch (err) {
|
|
@@ -1537,6 +1677,19 @@ function determineStreamingMode(streamingFlag, isTTY) {
|
|
|
1537
1677
|
// Auto-detect: enable streaming for interactive (TTY), disable for pipeline
|
|
1538
1678
|
return isTTY;
|
|
1539
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
|
+
}
|
|
1540
1693
|
// Main CLI entry point
|
|
1541
1694
|
async function main() {
|
|
1542
1695
|
// Configure LLM providers from environment variables at startup
|
|
@@ -1553,6 +1706,7 @@ async function main() {
|
|
|
1553
1706
|
.option('-c, --command <cmd>', 'Command to execute in pipeline mode')
|
|
1554
1707
|
.option('-l, --logLevel <level>', 'Set log level (trace, debug, info, warn, error)', 'error')
|
|
1555
1708
|
.option('--streaming', 'Enable streaming responses (default: auto-detected from TTY)')
|
|
1709
|
+
.option('--opik-enabled <true|false>', 'Override OPIK_ENABLED for this CLI run')
|
|
1556
1710
|
.option('-s, --server', 'Launch the server before running CLI')
|
|
1557
1711
|
.allowUnknownOption()
|
|
1558
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;
|