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
|
@@ -7,26 +7,28 @@
|
|
|
7
7
|
* Features:
|
|
8
8
|
* - Agent message subscription with automatic response processing
|
|
9
9
|
* - Tool message subscription with security checks
|
|
10
|
-
* - World message subscription
|
|
11
|
-
* - World activity listener
|
|
12
|
-
*
|
|
10
|
+
* - World message subscription: idempotent wrapper for world-level message listeners.
|
|
11
|
+
* - World activity listener: idempotent wrapper — no-op when setupEventPersistence has run;
|
|
12
|
+
* standalone fallback path delegates idle-title logic to title-scheduler.ts.
|
|
13
13
|
*
|
|
14
14
|
* Dependencies (Layer 6):
|
|
15
15
|
* - types.ts (Layer 1)
|
|
16
16
|
* - publishers.ts (Layer 3)
|
|
17
|
-
* - persistence.ts, memory-manager.ts (Layer 4)
|
|
17
|
+
* - persistence.ts, memory-manager.ts, title-scheduler.ts (Layer 4)
|
|
18
18
|
* - orchestrator.ts (Layer 5)
|
|
19
19
|
* - utils.ts, logger.ts
|
|
20
|
-
* - storage (runtime)
|
|
21
20
|
*
|
|
22
21
|
* Changes:
|
|
23
|
-
* - 2026-
|
|
24
|
-
* -
|
|
25
|
-
* - 2026-
|
|
26
|
-
* - 2026-
|
|
27
|
-
*
|
|
28
|
-
*
|
|
29
|
-
* -
|
|
22
|
+
* - 2026-03-10: Removed standalone world-message title scheduling so idle activity is the sole
|
|
23
|
+
* automatic chat-title trigger.
|
|
24
|
+
* - 2026-03-06: Removed `world.currentChatId` fallback from world-message title scheduling; chat-scoped handlers now require explicit `event.chatId`.
|
|
25
|
+
* - 2026-03-03: Removed private title-scheduling logic (moved to title-scheduler.ts Layer 4).
|
|
26
|
+
* subscribeWorldToMessages and setupWorldActivityListener are now idempotent wrappers that
|
|
27
|
+
* short-circuit when setupEventPersistence has already registered a combined handler.
|
|
28
|
+
* - 2026-02-28: Made world message subscription idempotent.
|
|
29
|
+
* - 2026-02-22: Persist incoming human messages to agent memory even when agents do not respond.
|
|
30
|
+
* - 2026-02-20: Publish chat-title update notifications as structured `system` events.
|
|
31
|
+
* - 2025-11-09: Extracted from events.ts for modular architecture.
|
|
30
32
|
*/
|
|
31
33
|
import type { World, Agent } from '../types.js';
|
|
32
34
|
/**
|
|
@@ -38,7 +40,8 @@ export declare function subscribeAgentToMessages(world: World, agent: Agent): ()
|
|
|
38
40
|
*/
|
|
39
41
|
export declare function subscribeWorldToMessages(world: World): () => void;
|
|
40
42
|
/**
|
|
41
|
-
* Setup world activity listener for chat title updates
|
|
42
|
-
*
|
|
43
|
+
* Setup world activity listener for idle-triggered chat title updates.
|
|
44
|
+
* Idempotent — returns existing cleanup handle if setupEventPersistence already registered
|
|
45
|
+
* a combined 'world' handler for this world.
|
|
43
46
|
*/
|
|
44
47
|
export declare function setupWorldActivityListener(world: World): () => void;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"subscribers.d.ts","sourceRoot":"","sources":["../../../core/events/subscribers.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"subscribers.d.ts","sourceRoot":"","sources":["../../../core/events/subscribers.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AAEH,OAAO,KAAK,EACV,KAAK,EACL,KAAK,EAEN,MAAM,aAAa,CAAC;AAkErB;;GAEG;AACH,wBAAgB,wBAAwB,CAAC,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,GAAG,MAAM,IAAI,CA4F/E;AAED;;GAEG;AACH,wBAAgB,wBAAwB,CAAC,KAAK,EAAE,KAAK,GAAG,MAAM,IAAI,CAmBjE;AAED;;;;GAIG;AACH,wBAAgB,0BAA0B,CAAC,KAAK,EAAE,KAAK,GAAG,MAAM,IAAI,CAsBnE"}
|
|
@@ -7,54 +7,37 @@
|
|
|
7
7
|
* Features:
|
|
8
8
|
* - Agent message subscription with automatic response processing
|
|
9
9
|
* - Tool message subscription with security checks
|
|
10
|
-
* - World message subscription
|
|
11
|
-
* - World activity listener
|
|
12
|
-
*
|
|
10
|
+
* - World message subscription: idempotent wrapper for world-level message listeners.
|
|
11
|
+
* - World activity listener: idempotent wrapper — no-op when setupEventPersistence has run;
|
|
12
|
+
* standalone fallback path delegates idle-title logic to title-scheduler.ts.
|
|
13
13
|
*
|
|
14
14
|
* Dependencies (Layer 6):
|
|
15
15
|
* - types.ts (Layer 1)
|
|
16
16
|
* - publishers.ts (Layer 3)
|
|
17
|
-
* - persistence.ts, memory-manager.ts (Layer 4)
|
|
17
|
+
* - persistence.ts, memory-manager.ts, title-scheduler.ts (Layer 4)
|
|
18
18
|
* - orchestrator.ts (Layer 5)
|
|
19
19
|
* - utils.ts, logger.ts
|
|
20
|
-
* - storage (runtime)
|
|
21
20
|
*
|
|
22
21
|
* Changes:
|
|
23
|
-
* - 2026-
|
|
24
|
-
* -
|
|
25
|
-
* - 2026-
|
|
26
|
-
* - 2026-
|
|
27
|
-
*
|
|
28
|
-
*
|
|
29
|
-
* -
|
|
22
|
+
* - 2026-03-10: Removed standalone world-message title scheduling so idle activity is the sole
|
|
23
|
+
* automatic chat-title trigger.
|
|
24
|
+
* - 2026-03-06: Removed `world.currentChatId` fallback from world-message title scheduling; chat-scoped handlers now require explicit `event.chatId`.
|
|
25
|
+
* - 2026-03-03: Removed private title-scheduling logic (moved to title-scheduler.ts Layer 4).
|
|
26
|
+
* subscribeWorldToMessages and setupWorldActivityListener are now idempotent wrappers that
|
|
27
|
+
* short-circuit when setupEventPersistence has already registered a combined handler.
|
|
28
|
+
* - 2026-02-28: Made world message subscription idempotent.
|
|
29
|
+
* - 2026-02-22: Persist incoming human messages to agent memory even when agents do not respond.
|
|
30
|
+
* - 2026-02-20: Publish chat-title update notifications as structured `system` events.
|
|
31
|
+
* - 2025-11-09: Extracted from events.ts for modular architecture.
|
|
30
32
|
*/
|
|
31
33
|
import { parseMessageContent } from '../message-prep.js';
|
|
32
34
|
import { extractParagraphBeginningMentions } from '../utils.js';
|
|
33
35
|
import { createCategoryLogger } from '../logger.js';
|
|
34
|
-
import {
|
|
35
|
-
import {
|
|
36
|
-
import { saveIncomingMessageToMemory, resetLLMCallCountIfNeeded, generateChatTitleFromMessages } from './memory-manager.js';
|
|
36
|
+
import { subscribeToMessages } from './publishers.js';
|
|
37
|
+
import { saveIncomingMessageToMemory, resetLLMCallCountIfNeeded } from './memory-manager.js';
|
|
37
38
|
import { processAgentMessage, shouldAgentRespond } from './orchestrator.js';
|
|
38
|
-
import {
|
|
39
|
+
import { isHumanSender, runIdleTitleUpdate, clearWorldTitleTimers } from './title-scheduler.js';
|
|
39
40
|
const loggerAgent = createCategoryLogger('agent');
|
|
40
|
-
const loggerChatTitle = createCategoryLogger('chattitle');
|
|
41
|
-
const titleGenerationInFlight = new Set();
|
|
42
|
-
const titleGenerationTimers = new Map();
|
|
43
|
-
// Storage wrapper instance - initialized lazily
|
|
44
|
-
let storageWrappers = null;
|
|
45
|
-
async function getStorageWrappers() {
|
|
46
|
-
if (!storageWrappers) {
|
|
47
|
-
storageWrappers = await createStorageWithWrappers();
|
|
48
|
-
}
|
|
49
|
-
return storageWrappers;
|
|
50
|
-
}
|
|
51
|
-
function getTitleGenerationKey(worldId, chatId) {
|
|
52
|
-
return `${worldId}:${chatId}`;
|
|
53
|
-
}
|
|
54
|
-
function isHumanSender(sender) {
|
|
55
|
-
const normalized = String(sender ?? '').trim().toLowerCase();
|
|
56
|
-
return normalized === 'human' || normalized.startsWith('user');
|
|
57
|
-
}
|
|
58
41
|
function toMentionToken(value) {
|
|
59
42
|
return String(value || '')
|
|
60
43
|
.trim()
|
|
@@ -96,91 +79,19 @@ function applyMainAgentMentionRouting(world, messageEvent) {
|
|
|
96
79
|
content: `@${mainAgent} ${messageEvent.content || ''}`.trim()
|
|
97
80
|
};
|
|
98
81
|
}
|
|
99
|
-
function scheduleNoActivityTitleUpdate(world, chatId, content) {
|
|
100
|
-
const key = getTitleGenerationKey(world.id, chatId);
|
|
101
|
-
const existingTimer = titleGenerationTimers.get(key);
|
|
102
|
-
if (existingTimer) {
|
|
103
|
-
clearTimeout(existingTimer);
|
|
104
|
-
}
|
|
105
|
-
const timer = setTimeout(async () => {
|
|
106
|
-
titleGenerationTimers.delete(key);
|
|
107
|
-
if (world.isProcessing) {
|
|
108
|
-
return;
|
|
109
|
-
}
|
|
110
|
-
await tryGenerateAndApplyTitle(world, chatId, content, 'message-no-activity');
|
|
111
|
-
}, 120);
|
|
112
|
-
titleGenerationTimers.set(key, timer);
|
|
113
|
-
}
|
|
114
|
-
async function commitChatTitleIfDefault(world, chatId, nextTitle) {
|
|
115
|
-
const storage = await getStorageWrappers();
|
|
116
|
-
if (typeof storage.updateChatNameIfCurrent === 'function') {
|
|
117
|
-
return storage.updateChatNameIfCurrent(world.id, chatId, NEW_CHAT_TITLE, nextTitle);
|
|
118
|
-
}
|
|
119
|
-
// Legacy fallback when storage backend does not provide compare-and-set helper.
|
|
120
|
-
const persistedChat = await storage.loadChatData(world.id, chatId);
|
|
121
|
-
if (!persistedChat || !isDefaultChatTitle(persistedChat.name)) {
|
|
122
|
-
return false;
|
|
123
|
-
}
|
|
124
|
-
const updated = await storage.updateChatData(world.id, chatId, { name: nextTitle });
|
|
125
|
-
return !!updated;
|
|
126
|
-
}
|
|
127
|
-
async function tryGenerateAndApplyTitle(world, targetChatId, content, source) {
|
|
128
|
-
const inFlightKey = getTitleGenerationKey(world.id, targetChatId);
|
|
129
|
-
if (titleGenerationInFlight.has(inFlightKey)) {
|
|
130
|
-
loggerChatTitle.debug('Skipping title update because generation is already in flight', {
|
|
131
|
-
worldId: world.id,
|
|
132
|
-
chatId: targetChatId,
|
|
133
|
-
source
|
|
134
|
-
});
|
|
135
|
-
return;
|
|
136
|
-
}
|
|
137
|
-
const chat = world.chats.get(targetChatId);
|
|
138
|
-
if (!chat || !isDefaultChatTitle(chat.name)) {
|
|
139
|
-
return;
|
|
140
|
-
}
|
|
141
|
-
titleGenerationInFlight.add(inFlightKey);
|
|
142
|
-
try {
|
|
143
|
-
const title = await generateChatTitleFromMessages(world, content, targetChatId);
|
|
144
|
-
if (!title) {
|
|
145
|
-
return;
|
|
146
|
-
}
|
|
147
|
-
// Re-check in-memory state before commit.
|
|
148
|
-
const currentChat = world.chats.get(targetChatId);
|
|
149
|
-
if (!currentChat || !isDefaultChatTitle(currentChat.name)) {
|
|
150
|
-
loggerChatTitle.debug('Skipping title commit because in-memory chat title is no longer default', {
|
|
151
|
-
worldId: world.id,
|
|
152
|
-
chatId: targetChatId,
|
|
153
|
-
source,
|
|
154
|
-
currentName: currentChat?.name
|
|
155
|
-
});
|
|
156
|
-
return;
|
|
157
|
-
}
|
|
158
|
-
const committed = await commitChatTitleIfDefault(world, targetChatId, title);
|
|
159
|
-
if (!committed) {
|
|
160
|
-
loggerChatTitle.debug('Skipping title commit because persisted chat title no longer matches default', {
|
|
161
|
-
worldId: world.id,
|
|
162
|
-
chatId: targetChatId,
|
|
163
|
-
source
|
|
164
|
-
});
|
|
165
|
-
return;
|
|
166
|
-
}
|
|
167
|
-
currentChat.name = title;
|
|
168
|
-
publishEvent(world, 'system', {
|
|
169
|
-
eventType: 'chat-title-updated',
|
|
170
|
-
chatId: targetChatId,
|
|
171
|
-
title,
|
|
172
|
-
source,
|
|
173
|
-
message: `Chat title updated: ${title}`,
|
|
174
|
-
}, targetChatId);
|
|
175
|
-
}
|
|
176
|
-
finally {
|
|
177
|
-
titleGenerationInFlight.delete(inFlightKey);
|
|
178
|
-
}
|
|
179
|
-
}
|
|
180
82
|
/**
|
|
181
83
|
* Agent subscription with automatic message processing
|
|
182
84
|
*/
|
|
183
85
|
export function subscribeAgentToMessages(world, agent) {
|
|
86
|
+
const existingUnsubscribe = world._agentUnsubscribers?.get(agent.id);
|
|
87
|
+
if (typeof existingUnsubscribe === 'function') {
|
|
88
|
+
try {
|
|
89
|
+
existingUnsubscribe();
|
|
90
|
+
}
|
|
91
|
+
catch {
|
|
92
|
+
// Best-effort cleanup before rebinding the same agent listener.
|
|
93
|
+
}
|
|
94
|
+
}
|
|
184
95
|
const handler = async (messageEvent) => {
|
|
185
96
|
const routedMessageEvent = applyMainAgentMentionRouting(world, messageEvent);
|
|
186
97
|
loggerAgent.debug('[subscribeAgentToMessages] ENTRY - Agent received message', {
|
|
@@ -222,12 +133,17 @@ export function subscribeAgentToMessages(world, agent) {
|
|
|
222
133
|
}
|
|
223
134
|
// Reset LLM call count if needed (for human/system messages)
|
|
224
135
|
await resetLLMCallCountIfNeeded(world, agent, routedMessageEvent);
|
|
136
|
+
const isIncomingHumanMessage = isHumanSender(routedMessageEvent.sender);
|
|
137
|
+
if (isIncomingHumanMessage) {
|
|
138
|
+
await saveIncomingMessageToMemory(world, agent, routedMessageEvent);
|
|
139
|
+
}
|
|
225
140
|
// Process message if agent should respond
|
|
226
141
|
loggerAgent.debug('Checking if agent should respond', { agentId: agent.id, sender: routedMessageEvent.sender });
|
|
227
142
|
const shouldRespond = await shouldAgentRespond(world, agent, routedMessageEvent);
|
|
228
143
|
if (shouldRespond) {
|
|
229
|
-
|
|
230
|
-
|
|
144
|
+
if (!isIncomingHumanMessage) {
|
|
145
|
+
await saveIncomingMessageToMemory(world, agent, routedMessageEvent);
|
|
146
|
+
}
|
|
231
147
|
loggerAgent.debug('Agent will respond - processing message', { agentId: agent.id, sender: routedMessageEvent.sender });
|
|
232
148
|
await processAgentMessage(world, agent, routedMessageEvent);
|
|
233
149
|
}
|
|
@@ -250,46 +166,43 @@ export function subscribeAgentToMessages(world, agent) {
|
|
|
250
166
|
* Subscribe world to messages with cleanup function
|
|
251
167
|
*/
|
|
252
168
|
export function subscribeWorldToMessages(world) {
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
return;
|
|
259
|
-
const chat = world.chats.get(targetChatId);
|
|
260
|
-
if (!chat || !isDefaultChatTitle(chat.name))
|
|
261
|
-
return;
|
|
262
|
-
scheduleNoActivityTitleUpdate(world, targetChatId, event.content || '');
|
|
169
|
+
if (typeof world._worldMessagesUnsubscriber === 'function') {
|
|
170
|
+
return world._worldMessagesUnsubscriber;
|
|
171
|
+
}
|
|
172
|
+
const unsubscribe = subscribeToMessages(world, (_event) => {
|
|
173
|
+
return;
|
|
263
174
|
});
|
|
175
|
+
const trackedUnsubscribe = () => {
|
|
176
|
+
unsubscribe();
|
|
177
|
+
clearWorldTitleTimers(world.id);
|
|
178
|
+
if (world._worldMessagesUnsubscriber === trackedUnsubscribe) {
|
|
179
|
+
world._worldMessagesUnsubscriber = undefined;
|
|
180
|
+
}
|
|
181
|
+
};
|
|
182
|
+
world._worldMessagesUnsubscriber = trackedUnsubscribe;
|
|
183
|
+
return trackedUnsubscribe;
|
|
264
184
|
}
|
|
265
185
|
/**
|
|
266
|
-
* Setup world activity listener for chat title updates
|
|
267
|
-
*
|
|
186
|
+
* Setup world activity listener for idle-triggered chat title updates.
|
|
187
|
+
* Idempotent — returns existing cleanup handle if setupEventPersistence already registered
|
|
188
|
+
* a combined 'world' handler for this world.
|
|
268
189
|
*/
|
|
269
190
|
export function setupWorldActivityListener(world) {
|
|
191
|
+
if (typeof world._activityListenerCleanup === 'function') {
|
|
192
|
+
return world._activityListenerCleanup;
|
|
193
|
+
}
|
|
194
|
+
// Standalone fallback: persistence is disabled, attach a lightweight idle handler.
|
|
270
195
|
const handler = async (event) => {
|
|
271
|
-
|
|
272
|
-
if (event.type === 'idle' && event.pendingOperations === 0) {
|
|
273
|
-
const targetChatId = world.currentChatId;
|
|
274
|
-
if (!targetChatId)
|
|
275
|
-
return;
|
|
276
|
-
try {
|
|
277
|
-
await tryGenerateAndApplyTitle(world, targetChatId, '', 'idle');
|
|
278
|
-
}
|
|
279
|
-
catch (err) {
|
|
280
|
-
loggerChatTitle.warn('Activity-based title update failed', { error: err instanceof Error ? err.message : err });
|
|
281
|
-
}
|
|
282
|
-
}
|
|
196
|
+
await runIdleTitleUpdate(world, event);
|
|
283
197
|
};
|
|
284
198
|
world.eventEmitter.on('world', handler);
|
|
285
|
-
|
|
199
|
+
const cleanup = () => {
|
|
286
200
|
world.eventEmitter.off('world', handler);
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
}
|
|
291
|
-
clearTimeout(timer);
|
|
292
|
-
titleGenerationTimers.delete(key);
|
|
201
|
+
clearWorldTitleTimers(world.id);
|
|
202
|
+
if (world._activityListenerCleanup === cleanup) {
|
|
203
|
+
world._activityListenerCleanup = undefined;
|
|
293
204
|
}
|
|
294
205
|
};
|
|
206
|
+
world._activityListenerCleanup = cleanup;
|
|
207
|
+
return cleanup;
|
|
295
208
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"subscribers.js","sourceRoot":"","sources":["../../../core/events/subscribers.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"subscribers.js","sourceRoot":"","sources":["../../../core/events/subscribers.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Title Scheduler Module
|
|
3
|
+
*
|
|
4
|
+
* Purpose:
|
|
5
|
+
* - Encapsulate all chat-title auto-generation logic (Layer 4).
|
|
6
|
+
* - Previously embedded in subscribers.ts (Layer 6); extracted so persistence.ts (Layer 4) can
|
|
7
|
+
* call title-scheduling directly without a cross-layer import violation.
|
|
8
|
+
*
|
|
9
|
+
* Key Features:
|
|
10
|
+
* - Idle-triggered title generation on world activity events.
|
|
11
|
+
* - In-flight deduplication and compare-and-set storage commit.
|
|
12
|
+
* - World teardown cleanup helper that preserves the listener contract.
|
|
13
|
+
*
|
|
14
|
+
* Implementation Notes:
|
|
15
|
+
* - All state (in-flight set, storage cache) is module-level to preserve
|
|
16
|
+
* singleton semantics previously in subscribers.ts.
|
|
17
|
+
*
|
|
18
|
+
* Recent Changes:
|
|
19
|
+
* - 2026-03-10: Removed the human-message debounce trigger so idle activity is the sole
|
|
20
|
+
* automatic chat-title generation entry point.
|
|
21
|
+
* - 2026-03-03: Extracted from subscribers.ts to eliminate duplicate world-level EventEmitter
|
|
22
|
+
* listeners (persistence + activity + title-scheduler each had their own handler per channel).
|
|
23
|
+
*/
|
|
24
|
+
import type { World } from '../types.js';
|
|
25
|
+
export declare function isHumanSender(sender?: string): boolean;
|
|
26
|
+
export declare function runIdleTitleUpdate(world: World, event: any): Promise<void>;
|
|
27
|
+
export declare function clearWorldTitleTimers(worldId: string): void;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"title-scheduler.d.ts","sourceRoot":"","sources":["../../../core/events/title-scheduler.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AAEH,OAAO,KAAK,EAAE,KAAK,EAAc,MAAM,aAAa,CAAC;AAuBrD,wBAAgB,aAAa,CAAC,MAAM,CAAC,EAAE,MAAM,GAAG,OAAO,CAGtD;AAED,wBAAsB,kBAAkB,CAAC,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,GAAG,GAAG,OAAO,CAAC,IAAI,CAAC,CAmBhF;AAED,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAE3D"}
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Title Scheduler Module
|
|
3
|
+
*
|
|
4
|
+
* Purpose:
|
|
5
|
+
* - Encapsulate all chat-title auto-generation logic (Layer 4).
|
|
6
|
+
* - Previously embedded in subscribers.ts (Layer 6); extracted so persistence.ts (Layer 4) can
|
|
7
|
+
* call title-scheduling directly without a cross-layer import violation.
|
|
8
|
+
*
|
|
9
|
+
* Key Features:
|
|
10
|
+
* - Idle-triggered title generation on world activity events.
|
|
11
|
+
* - In-flight deduplication and compare-and-set storage commit.
|
|
12
|
+
* - World teardown cleanup helper that preserves the listener contract.
|
|
13
|
+
*
|
|
14
|
+
* Implementation Notes:
|
|
15
|
+
* - All state (in-flight set, storage cache) is module-level to preserve
|
|
16
|
+
* singleton semantics previously in subscribers.ts.
|
|
17
|
+
*
|
|
18
|
+
* Recent Changes:
|
|
19
|
+
* - 2026-03-10: Removed the human-message debounce trigger so idle activity is the sole
|
|
20
|
+
* automatic chat-title generation entry point.
|
|
21
|
+
* - 2026-03-03: Extracted from subscribers.ts to eliminate duplicate world-level EventEmitter
|
|
22
|
+
* listeners (persistence + activity + title-scheduler each had their own handler per channel).
|
|
23
|
+
*/
|
|
24
|
+
import { createCategoryLogger } from '../logger.js';
|
|
25
|
+
import { createStorageWithWrappers } from '../storage/storage-factory.js';
|
|
26
|
+
import { generateChatTitleFromMessages } from './memory-manager.js';
|
|
27
|
+
import { publishEvent } from './publishers.js';
|
|
28
|
+
import { isDefaultChatTitle, NEW_CHAT_TITLE, TITLE_PROVENANCE_AUTO } from '../chat-constants.js';
|
|
29
|
+
const loggerChatTitle = createCategoryLogger('chattitle');
|
|
30
|
+
const titleGenerationInFlight = new Set();
|
|
31
|
+
let storageWrappers = null;
|
|
32
|
+
async function getStorageWrappers() {
|
|
33
|
+
if (!storageWrappers) {
|
|
34
|
+
storageWrappers = await createStorageWithWrappers();
|
|
35
|
+
}
|
|
36
|
+
return storageWrappers;
|
|
37
|
+
}
|
|
38
|
+
function getTitleGenerationKey(worldId, chatId) {
|
|
39
|
+
return `${worldId}:${chatId}`;
|
|
40
|
+
}
|
|
41
|
+
export function isHumanSender(sender) {
|
|
42
|
+
const normalized = String(sender ?? '').trim().toLowerCase();
|
|
43
|
+
return normalized === 'human' || normalized === 'world' || normalized.startsWith('user');
|
|
44
|
+
}
|
|
45
|
+
export async function runIdleTitleUpdate(world, event) {
|
|
46
|
+
if (event.type !== 'idle' || event.pendingOperations !== 0) {
|
|
47
|
+
return;
|
|
48
|
+
}
|
|
49
|
+
const targetChatIdRaw = typeof event?.chatId === 'string' ? event.chatId.trim() : '';
|
|
50
|
+
const targetChatId = targetChatIdRaw || null;
|
|
51
|
+
if (!targetChatId) {
|
|
52
|
+
loggerChatTitle.debug('Skipping idle title update due to missing chatId on activity event', {
|
|
53
|
+
worldId: world.id,
|
|
54
|
+
eventType: event?.type,
|
|
55
|
+
pendingOperations: event?.pendingOperations
|
|
56
|
+
});
|
|
57
|
+
return;
|
|
58
|
+
}
|
|
59
|
+
try {
|
|
60
|
+
await tryGenerateAndApplyTitle(world, targetChatId, '', 'idle');
|
|
61
|
+
}
|
|
62
|
+
catch (err) {
|
|
63
|
+
loggerChatTitle.warn('Activity-based title update failed', { error: err instanceof Error ? err.message : err });
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
export function clearWorldTitleTimers(worldId) {
|
|
67
|
+
void worldId;
|
|
68
|
+
}
|
|
69
|
+
async function commitChatTitleIfDefault(world, chatId, nextTitle) {
|
|
70
|
+
const storage = await getStorageWrappers();
|
|
71
|
+
if (typeof storage.updateChatNameIfCurrent === 'function') {
|
|
72
|
+
return storage.updateChatNameIfCurrent(world.id, chatId, NEW_CHAT_TITLE, nextTitle, TITLE_PROVENANCE_AUTO);
|
|
73
|
+
}
|
|
74
|
+
// Legacy fallback when storage backend does not provide compare-and-set helper.
|
|
75
|
+
const persistedChat = await storage.loadChatData(world.id, chatId);
|
|
76
|
+
if (!persistedChat || !isDefaultChatTitle(persistedChat.name)) {
|
|
77
|
+
return false;
|
|
78
|
+
}
|
|
79
|
+
const updated = await storage.updateChatData(world.id, chatId, { name: nextTitle, titleProvenance: TITLE_PROVENANCE_AUTO });
|
|
80
|
+
return !!updated;
|
|
81
|
+
}
|
|
82
|
+
async function tryGenerateAndApplyTitle(world, targetChatId, content, source) {
|
|
83
|
+
const inFlightKey = getTitleGenerationKey(world.id, targetChatId);
|
|
84
|
+
if (titleGenerationInFlight.has(inFlightKey)) {
|
|
85
|
+
loggerChatTitle.debug('Skipping title update because generation is already in flight', {
|
|
86
|
+
worldId: world.id,
|
|
87
|
+
chatId: targetChatId,
|
|
88
|
+
source
|
|
89
|
+
});
|
|
90
|
+
return;
|
|
91
|
+
}
|
|
92
|
+
const chat = world.chats.get(targetChatId);
|
|
93
|
+
if (!chat || !isDefaultChatTitle(chat.name)) {
|
|
94
|
+
return;
|
|
95
|
+
}
|
|
96
|
+
titleGenerationInFlight.add(inFlightKey);
|
|
97
|
+
try {
|
|
98
|
+
const title = await generateChatTitleFromMessages(world, content, targetChatId);
|
|
99
|
+
if (!title) {
|
|
100
|
+
return;
|
|
101
|
+
}
|
|
102
|
+
// Re-check in-memory state before commit.
|
|
103
|
+
const currentChat = world.chats.get(targetChatId);
|
|
104
|
+
if (!currentChat || !isDefaultChatTitle(currentChat.name)) {
|
|
105
|
+
loggerChatTitle.debug('Skipping title commit because in-memory chat title is no longer default', {
|
|
106
|
+
worldId: world.id,
|
|
107
|
+
chatId: targetChatId,
|
|
108
|
+
source,
|
|
109
|
+
currentName: currentChat?.name
|
|
110
|
+
});
|
|
111
|
+
return;
|
|
112
|
+
}
|
|
113
|
+
const committed = await commitChatTitleIfDefault(world, targetChatId, title);
|
|
114
|
+
if (!committed) {
|
|
115
|
+
loggerChatTitle.debug('Skipping title commit because persisted chat title no longer matches default', {
|
|
116
|
+
worldId: world.id,
|
|
117
|
+
chatId: targetChatId,
|
|
118
|
+
source
|
|
119
|
+
});
|
|
120
|
+
return;
|
|
121
|
+
}
|
|
122
|
+
currentChat.name = title;
|
|
123
|
+
currentChat.titleProvenance = TITLE_PROVENANCE_AUTO;
|
|
124
|
+
publishEvent(world, 'system', {
|
|
125
|
+
eventType: 'chat-title-updated',
|
|
126
|
+
chatId: targetChatId,
|
|
127
|
+
title,
|
|
128
|
+
source,
|
|
129
|
+
message: `Chat title updated: ${title}`,
|
|
130
|
+
}, targetChatId);
|
|
131
|
+
}
|
|
132
|
+
finally {
|
|
133
|
+
titleGenerationInFlight.delete(inFlightKey);
|
|
134
|
+
}
|
|
135
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"title-scheduler.js","sourceRoot":"","sources":["../../../core/events/title-scheduler.ts"],"names":[],"mappings":"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"}
|
|
@@ -6,7 +6,8 @@
|
|
|
6
6
|
* memory-manager to trace request/result/error handoff payloads.
|
|
7
7
|
*
|
|
8
8
|
* Key Features:
|
|
9
|
-
* -
|
|
9
|
+
* - Structured bridge logs through the core logger (`llm.tool.bridge`) for realtime log streaming
|
|
10
|
+
* - LOG_LLM_TOOL_BRIDGE supports explicit levels (`trace|debug|info|warn|error`) and boolean aliases (`1|true|on` => debug)
|
|
10
11
|
* - Simplified output showing only type, tool name, and truncated content (100-200 chars)
|
|
11
12
|
* - Safe JSON serialization with fallback to `String()`
|
|
12
13
|
*
|
|
@@ -15,6 +16,8 @@
|
|
|
15
16
|
* - Filters verbose metadata, keeps only essential debugging fields
|
|
16
17
|
*
|
|
17
18
|
* Changes:
|
|
19
|
+
* - 2026-02-28: Added canonical feature-path category emission (`tool.call.*`, `tool.continuation`) while preserving legacy bridge logging behavior.
|
|
20
|
+
* - 2026-02-27: Replaced ad-hoc `[LLM↔TOOLS]` console logging with structured category logger events.
|
|
18
21
|
* - 2026-02-16: Extracted shared tool-bridge logging utilities from orchestrator
|
|
19
22
|
* and memory-manager into a dedicated module.
|
|
20
23
|
* - 2026-02-17: Simplified logToolBridge to show only type, tool name, and truncated
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tool-bridge-logging.d.ts","sourceRoot":"","sources":["../../../core/events/tool-bridge-logging.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"tool-bridge-logging.d.ts","sourceRoot":"","sources":["../../../core/events/tool-bridge-logging.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AAmHH,wBAAgB,uBAAuB,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,CAM9D;AAED,wBAAgB,0BAA0B,IAAI,OAAO,CAEpD;AAcD,wBAAgB,aAAa,CAAC,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,GAAG,IAAI,CAoCvE;AAED,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,CAU3D"}
|