@shuyhere/takotako 0.0.1
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/CONTRIBUTING.md +84 -0
- package/LICENSE +21 -0
- package/README.md +171 -0
- package/dist/agents/communication.d.ts +48 -0
- package/dist/agents/communication.d.ts.map +1 -0
- package/dist/agents/communication.js +123 -0
- package/dist/agents/communication.js.map +1 -0
- package/dist/agents/config.d.ts +52 -0
- package/dist/agents/config.d.ts.map +1 -0
- package/dist/agents/config.js +65 -0
- package/dist/agents/config.js.map +1 -0
- package/dist/agents/model-catalog.d.ts +49 -0
- package/dist/agents/model-catalog.d.ts.map +1 -0
- package/dist/agents/model-catalog.js +79 -0
- package/dist/agents/model-catalog.js.map +1 -0
- package/dist/agents/registry.d.ts +71 -0
- package/dist/agents/registry.d.ts.map +1 -0
- package/dist/agents/registry.js +297 -0
- package/dist/agents/registry.js.map +1 -0
- package/dist/agents/roles.d.ts +79 -0
- package/dist/agents/roles.d.ts.map +1 -0
- package/dist/agents/roles.js +174 -0
- package/dist/agents/roles.js.map +1 -0
- package/dist/agents/subagent.d.ts +124 -0
- package/dist/agents/subagent.d.ts.map +1 -0
- package/dist/agents/subagent.js +352 -0
- package/dist/agents/subagent.js.map +1 -0
- package/dist/agents/templates.d.ts +18 -0
- package/dist/agents/templates.d.ts.map +1 -0
- package/dist/agents/templates.js +341 -0
- package/dist/agents/templates.js.map +1 -0
- package/dist/agents/thread-binding.d.ts +77 -0
- package/dist/agents/thread-binding.d.ts.map +1 -0
- package/dist/agents/thread-binding.js +167 -0
- package/dist/agents/thread-binding.js.map +1 -0
- package/dist/auth/agent-profiles.d.ts +46 -0
- package/dist/auth/agent-profiles.d.ts.map +1 -0
- package/dist/auth/agent-profiles.js +97 -0
- package/dist/auth/agent-profiles.js.map +1 -0
- package/dist/auth/allow-from.d.ts +27 -0
- package/dist/auth/allow-from.d.ts.map +1 -0
- package/dist/auth/allow-from.js +118 -0
- package/dist/auth/allow-from.js.map +1 -0
- package/dist/auth/oauth.d.ts +66 -0
- package/dist/auth/oauth.d.ts.map +1 -0
- package/dist/auth/oauth.js +253 -0
- package/dist/auth/oauth.js.map +1 -0
- package/dist/auth/storage.d.ts +69 -0
- package/dist/auth/storage.d.ts.map +1 -0
- package/dist/auth/storage.js +157 -0
- package/dist/auth/storage.js.map +1 -0
- package/dist/cache/file-cache.d.ts +68 -0
- package/dist/cache/file-cache.d.ts.map +1 -0
- package/dist/cache/file-cache.js +176 -0
- package/dist/cache/file-cache.js.map +1 -0
- package/dist/cache/manager.d.ts +69 -0
- package/dist/cache/manager.d.ts.map +1 -0
- package/dist/cache/manager.js +117 -0
- package/dist/cache/manager.js.map +1 -0
- package/dist/cache/symbol-index.d.ts +75 -0
- package/dist/cache/symbol-index.d.ts.map +1 -0
- package/dist/cache/symbol-index.js +267 -0
- package/dist/cache/symbol-index.js.map +1 -0
- package/dist/cache/tool-cache.d.ts +75 -0
- package/dist/cache/tool-cache.d.ts.map +1 -0
- package/dist/cache/tool-cache.js +173 -0
- package/dist/cache/tool-cache.js.map +1 -0
- package/dist/channels/channel.d.ts +156 -0
- package/dist/channels/channel.d.ts.map +1 -0
- package/dist/channels/channel.js +25 -0
- package/dist/channels/channel.js.map +1 -0
- package/dist/channels/cli.d.ts +35 -0
- package/dist/channels/cli.d.ts.map +1 -0
- package/dist/channels/cli.js +94 -0
- package/dist/channels/cli.js.map +1 -0
- package/dist/channels/delivery-queue.d.ts +31 -0
- package/dist/channels/delivery-queue.d.ts.map +1 -0
- package/dist/channels/delivery-queue.js +127 -0
- package/dist/channels/delivery-queue.js.map +1 -0
- package/dist/channels/discord.d.ts +124 -0
- package/dist/channels/discord.d.ts.map +1 -0
- package/dist/channels/discord.js +664 -0
- package/dist/channels/discord.js.map +1 -0
- package/dist/channels/retry.d.ts +31 -0
- package/dist/channels/retry.d.ts.map +1 -0
- package/dist/channels/retry.js +94 -0
- package/dist/channels/retry.js.map +1 -0
- package/dist/channels/telegram.d.ts +69 -0
- package/dist/channels/telegram.d.ts.map +1 -0
- package/dist/channels/telegram.js +499 -0
- package/dist/channels/telegram.js.map +1 -0
- package/dist/channels/tui.d.ts +42 -0
- package/dist/channels/tui.d.ts.map +1 -0
- package/dist/channels/tui.js +126 -0
- package/dist/channels/tui.js.map +1 -0
- package/dist/cli/acp.d.ts +10 -0
- package/dist/cli/acp.d.ts.map +1 -0
- package/dist/cli/acp.js +69 -0
- package/dist/cli/acp.js.map +1 -0
- package/dist/cli/audit.d.ts +11 -0
- package/dist/cli/audit.d.ts.map +1 -0
- package/dist/cli/audit.js +55 -0
- package/dist/cli/audit.js.map +1 -0
- package/dist/cli/cache.d.ts +10 -0
- package/dist/cli/cache.d.ts.map +1 -0
- package/dist/cli/cache.js +77 -0
- package/dist/cli/cache.js.map +1 -0
- package/dist/cli/config.d.ts +5 -0
- package/dist/cli/config.d.ts.map +1 -0
- package/dist/cli/config.js +168 -0
- package/dist/cli/config.js.map +1 -0
- package/dist/cli/cron.d.ts +5 -0
- package/dist/cli/cron.d.ts.map +1 -0
- package/dist/cli/cron.js +192 -0
- package/dist/cli/cron.js.map +1 -0
- package/dist/cli/extensions.d.ts +5 -0
- package/dist/cli/extensions.d.ts.map +1 -0
- package/dist/cli/extensions.js +53 -0
- package/dist/cli/extensions.js.map +1 -0
- package/dist/cli/logs.d.ts +5 -0
- package/dist/cli/logs.d.ts.map +1 -0
- package/dist/cli/logs.js +49 -0
- package/dist/cli/logs.js.map +1 -0
- package/dist/cli/memory.d.ts +5 -0
- package/dist/cli/memory.d.ts.map +1 -0
- package/dist/cli/memory.js +78 -0
- package/dist/cli/memory.js.map +1 -0
- package/dist/cli/message.d.ts +5 -0
- package/dist/cli/message.d.ts.map +1 -0
- package/dist/cli/message.js +69 -0
- package/dist/cli/message.js.map +1 -0
- package/dist/cli/service.d.ts +14 -0
- package/dist/cli/service.d.ts.map +1 -0
- package/dist/cli/service.js +181 -0
- package/dist/cli/service.js.map +1 -0
- package/dist/cli/symphony.d.ts +5 -0
- package/dist/cli/symphony.d.ts.map +1 -0
- package/dist/cli/symphony.js +114 -0
- package/dist/cli/symphony.js.map +1 -0
- package/dist/cli/update.d.ts +5 -0
- package/dist/cli/update.d.ts.map +1 -0
- package/dist/cli/update.js +48 -0
- package/dist/cli/update.js.map +1 -0
- package/dist/commands/channel-setup.d.ts +31 -0
- package/dist/commands/channel-setup.d.ts.map +1 -0
- package/dist/commands/channel-setup.js +138 -0
- package/dist/commands/channel-setup.js.map +1 -0
- package/dist/commands/dispatch.d.ts +48 -0
- package/dist/commands/dispatch.d.ts.map +1 -0
- package/dist/commands/dispatch.js +68 -0
- package/dist/commands/dispatch.js.map +1 -0
- package/dist/commands/model-picker.d.ts +16 -0
- package/dist/commands/model-picker.d.ts.map +1 -0
- package/dist/commands/model-picker.js +120 -0
- package/dist/commands/model-picker.js.map +1 -0
- package/dist/commands/parser.d.ts +32 -0
- package/dist/commands/parser.d.ts.map +1 -0
- package/dist/commands/parser.js +39 -0
- package/dist/commands/parser.js.map +1 -0
- package/dist/commands/registry.d.ts +76 -0
- package/dist/commands/registry.d.ts.map +1 -0
- package/dist/commands/registry.js +351 -0
- package/dist/commands/registry.js.map +1 -0
- package/dist/commands/skill-commands.d.ts +35 -0
- package/dist/commands/skill-commands.d.ts.map +1 -0
- package/dist/commands/skill-commands.js +61 -0
- package/dist/commands/skill-commands.js.map +1 -0
- package/dist/config/resolve.d.ts +25 -0
- package/dist/config/resolve.d.ts.map +1 -0
- package/dist/config/resolve.js +289 -0
- package/dist/config/resolve.js.map +1 -0
- package/dist/config/schema.d.ts +520 -0
- package/dist/config/schema.d.ts.map +1 -0
- package/dist/config/schema.js +123 -0
- package/dist/config/schema.js.map +1 -0
- package/dist/core/agent-loop.d.ts +137 -0
- package/dist/core/agent-loop.d.ts.map +1 -0
- package/dist/core/agent-loop.js +700 -0
- package/dist/core/agent-loop.js.map +1 -0
- package/dist/core/audit.d.ts +87 -0
- package/dist/core/audit.d.ts.map +1 -0
- package/dist/core/audit.js +224 -0
- package/dist/core/audit.js.map +1 -0
- package/dist/core/bootstrap.d.ts +23 -0
- package/dist/core/bootstrap.d.ts.map +1 -0
- package/dist/core/bootstrap.js +162 -0
- package/dist/core/bootstrap.js.map +1 -0
- package/dist/core/context.d.ts +44 -0
- package/dist/core/context.d.ts.map +1 -0
- package/dist/core/context.js +65 -0
- package/dist/core/context.js.map +1 -0
- package/dist/core/cron.d.ts +111 -0
- package/dist/core/cron.d.ts.map +1 -0
- package/dist/core/cron.js +284 -0
- package/dist/core/cron.js.map +1 -0
- package/dist/core/exec-approvals.d.ts +50 -0
- package/dist/core/exec-approvals.d.ts.map +1 -0
- package/dist/core/exec-approvals.js +187 -0
- package/dist/core/exec-approvals.js.map +1 -0
- package/dist/core/heartbeat.d.ts +71 -0
- package/dist/core/heartbeat.d.ts.map +1 -0
- package/dist/core/heartbeat.js +214 -0
- package/dist/core/heartbeat.js.map +1 -0
- package/dist/core/message-queue.d.ts +60 -0
- package/dist/core/message-queue.d.ts.map +1 -0
- package/dist/core/message-queue.js +182 -0
- package/dist/core/message-queue.js.map +1 -0
- package/dist/core/network-policy.d.ts +39 -0
- package/dist/core/network-policy.d.ts.map +1 -0
- package/dist/core/network-policy.js +121 -0
- package/dist/core/network-policy.js.map +1 -0
- package/dist/core/progress.d.ts +48 -0
- package/dist/core/progress.d.ts.map +1 -0
- package/dist/core/progress.js +81 -0
- package/dist/core/progress.js.map +1 -0
- package/dist/core/prompt.d.ts +105 -0
- package/dist/core/prompt.d.ts.map +1 -0
- package/dist/core/prompt.js +411 -0
- package/dist/core/prompt.js.map +1 -0
- package/dist/core/pruning.d.ts +40 -0
- package/dist/core/pruning.d.ts.map +1 -0
- package/dist/core/pruning.js +165 -0
- package/dist/core/pruning.js.map +1 -0
- package/dist/core/rate-limiter.d.ts +64 -0
- package/dist/core/rate-limiter.d.ts.map +1 -0
- package/dist/core/rate-limiter.js +142 -0
- package/dist/core/rate-limiter.js.map +1 -0
- package/dist/core/reactions.d.ts +31 -0
- package/dist/core/reactions.d.ts.map +1 -0
- package/dist/core/reactions.js +67 -0
- package/dist/core/reactions.js.map +1 -0
- package/dist/core/retry-queue.d.ts +56 -0
- package/dist/core/retry-queue.d.ts.map +1 -0
- package/dist/core/retry-queue.js +106 -0
- package/dist/core/retry-queue.js.map +1 -0
- package/dist/core/sanitizer.d.ts +38 -0
- package/dist/core/sanitizer.d.ts.map +1 -0
- package/dist/core/sanitizer.js +181 -0
- package/dist/core/sanitizer.js.map +1 -0
- package/dist/core/secret-scanner.d.ts +39 -0
- package/dist/core/secret-scanner.d.ts.map +1 -0
- package/dist/core/secret-scanner.js +96 -0
- package/dist/core/secret-scanner.js.map +1 -0
- package/dist/core/secrets.d.ts +38 -0
- package/dist/core/secrets.d.ts.map +1 -0
- package/dist/core/secrets.js +137 -0
- package/dist/core/secrets.js.map +1 -0
- package/dist/core/security.d.ts +58 -0
- package/dist/core/security.d.ts.map +1 -0
- package/dist/core/security.js +120 -0
- package/dist/core/security.js.map +1 -0
- package/dist/core/self-awareness.d.ts +19 -0
- package/dist/core/self-awareness.d.ts.map +1 -0
- package/dist/core/self-awareness.js +124 -0
- package/dist/core/self-awareness.js.map +1 -0
- package/dist/core/session-init.d.ts +34 -0
- package/dist/core/session-init.d.ts.map +1 -0
- package/dist/core/session-init.js +68 -0
- package/dist/core/session-init.js.map +1 -0
- package/dist/core/streaming.d.ts +82 -0
- package/dist/core/streaming.d.ts.map +1 -0
- package/dist/core/streaming.js +264 -0
- package/dist/core/streaming.js.map +1 -0
- package/dist/core/symphony/orchestrator.d.ts +61 -0
- package/dist/core/symphony/orchestrator.d.ts.map +1 -0
- package/dist/core/symphony/orchestrator.js +476 -0
- package/dist/core/symphony/orchestrator.js.map +1 -0
- package/dist/core/symphony/status.d.ts +11 -0
- package/dist/core/symphony/status.d.ts.map +1 -0
- package/dist/core/symphony/status.js +133 -0
- package/dist/core/symphony/status.js.map +1 -0
- package/dist/core/symphony/types.d.ts +84 -0
- package/dist/core/symphony/types.d.ts.map +1 -0
- package/dist/core/symphony/types.js +5 -0
- package/dist/core/symphony/types.js.map +1 -0
- package/dist/core/symphony/workflow.d.ts +18 -0
- package/dist/core/symphony/workflow.d.ts.map +1 -0
- package/dist/core/symphony/workflow.js +149 -0
- package/dist/core/symphony/workflow.js.map +1 -0
- package/dist/core/symphony/workspace.d.ts +24 -0
- package/dist/core/symphony/workspace.d.ts.map +1 -0
- package/dist/core/symphony/workspace.js +94 -0
- package/dist/core/symphony/workspace.js.map +1 -0
- package/dist/core/thinking.d.ts +27 -0
- package/dist/core/thinking.d.ts.map +1 -0
- package/dist/core/thinking.js +83 -0
- package/dist/core/thinking.js.map +1 -0
- package/dist/core/thread-bindings.d.ts +47 -0
- package/dist/core/thread-bindings.d.ts.map +1 -0
- package/dist/core/thread-bindings.js +94 -0
- package/dist/core/thread-bindings.js.map +1 -0
- package/dist/core/timezone.d.ts +28 -0
- package/dist/core/timezone.d.ts.map +1 -0
- package/dist/core/timezone.js +72 -0
- package/dist/core/timezone.js.map +1 -0
- package/dist/core/tool-loop-detector.d.ts +41 -0
- package/dist/core/tool-loop-detector.d.ts.map +1 -0
- package/dist/core/tool-loop-detector.js +83 -0
- package/dist/core/tool-loop-detector.js.map +1 -0
- package/dist/core/tool-validator.d.ts +44 -0
- package/dist/core/tool-validator.d.ts.map +1 -0
- package/dist/core/tool-validator.js +175 -0
- package/dist/core/tool-validator.js.map +1 -0
- package/dist/core/typing.d.ts +25 -0
- package/dist/core/typing.d.ts.map +1 -0
- package/dist/core/typing.js +48 -0
- package/dist/core/typing.js.map +1 -0
- package/dist/core/usage-tracker.d.ts +66 -0
- package/dist/core/usage-tracker.d.ts.map +1 -0
- package/dist/core/usage-tracker.js +163 -0
- package/dist/core/usage-tracker.js.map +1 -0
- package/dist/daemon/commands.d.ts +16 -0
- package/dist/daemon/commands.d.ts.map +1 -0
- package/dist/daemon/commands.js +445 -0
- package/dist/daemon/commands.js.map +1 -0
- package/dist/daemon/pid.d.ts +30 -0
- package/dist/daemon/pid.d.ts.map +1 -0
- package/dist/daemon/pid.js +62 -0
- package/dist/daemon/pid.js.map +1 -0
- package/dist/doctor/checks/browser.d.ts +9 -0
- package/dist/doctor/checks/browser.d.ts.map +1 -0
- package/dist/doctor/checks/browser.js +54 -0
- package/dist/doctor/checks/browser.js.map +1 -0
- package/dist/doctor/checks/channels.d.ts +9 -0
- package/dist/doctor/checks/channels.d.ts.map +1 -0
- package/dist/doctor/checks/channels.js +90 -0
- package/dist/doctor/checks/channels.js.map +1 -0
- package/dist/doctor/checks/config.d.ts +10 -0
- package/dist/doctor/checks/config.d.ts.map +1 -0
- package/dist/doctor/checks/config.js +89 -0
- package/dist/doctor/checks/config.js.map +1 -0
- package/dist/doctor/checks/memory.d.ts +10 -0
- package/dist/doctor/checks/memory.d.ts.map +1 -0
- package/dist/doctor/checks/memory.js +82 -0
- package/dist/doctor/checks/memory.js.map +1 -0
- package/dist/doctor/checks/permissions.d.ts +9 -0
- package/dist/doctor/checks/permissions.d.ts.map +1 -0
- package/dist/doctor/checks/permissions.js +53 -0
- package/dist/doctor/checks/permissions.js.map +1 -0
- package/dist/doctor/checks/providers.d.ts +10 -0
- package/dist/doctor/checks/providers.d.ts.map +1 -0
- package/dist/doctor/checks/providers.js +93 -0
- package/dist/doctor/checks/providers.js.map +1 -0
- package/dist/doctor/checks/sessions.d.ts +10 -0
- package/dist/doctor/checks/sessions.d.ts.map +1 -0
- package/dist/doctor/checks/sessions.js +86 -0
- package/dist/doctor/checks/sessions.js.map +1 -0
- package/dist/doctor/doctor.d.ts +35 -0
- package/dist/doctor/doctor.d.ts.map +1 -0
- package/dist/doctor/doctor.js +51 -0
- package/dist/doctor/doctor.js.map +1 -0
- package/dist/doctor/repairs.d.ts +14 -0
- package/dist/doctor/repairs.d.ts.map +1 -0
- package/dist/doctor/repairs.js +34 -0
- package/dist/doctor/repairs.js.map +1 -0
- package/dist/gateway/compaction.d.ts +63 -0
- package/dist/gateway/compaction.d.ts.map +1 -0
- package/dist/gateway/compaction.js +235 -0
- package/dist/gateway/compaction.js.map +1 -0
- package/dist/gateway/gateway.d.ts +94 -0
- package/dist/gateway/gateway.d.ts.map +1 -0
- package/dist/gateway/gateway.js +466 -0
- package/dist/gateway/gateway.js.map +1 -0
- package/dist/gateway/lock.d.ts +24 -0
- package/dist/gateway/lock.d.ts.map +1 -0
- package/dist/gateway/lock.js +88 -0
- package/dist/gateway/lock.js.map +1 -0
- package/dist/gateway/protocol.d.ts +117 -0
- package/dist/gateway/protocol.d.ts.map +1 -0
- package/dist/gateway/protocol.js +5 -0
- package/dist/gateway/protocol.js.map +1 -0
- package/dist/gateway/session.d.ts +123 -0
- package/dist/gateway/session.d.ts.map +1 -0
- package/dist/gateway/session.js +573 -0
- package/dist/gateway/session.js.map +1 -0
- package/dist/hooks/hooks.d.ts +18 -0
- package/dist/hooks/hooks.d.ts.map +1 -0
- package/dist/hooks/hooks.js +45 -0
- package/dist/hooks/hooks.js.map +1 -0
- package/dist/hooks/types.d.ts +112 -0
- package/dist/hooks/types.d.ts.map +1 -0
- package/dist/hooks/types.js +23 -0
- package/dist/hooks/types.js.map +1 -0
- package/dist/index.d.ts +27 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +2900 -0
- package/dist/index.js.map +1 -0
- package/dist/media/storage.d.ts +25 -0
- package/dist/media/storage.d.ts.map +1 -0
- package/dist/media/storage.js +97 -0
- package/dist/media/storage.js.map +1 -0
- package/dist/memory/embeddings.d.ts +46 -0
- package/dist/memory/embeddings.d.ts.map +1 -0
- package/dist/memory/embeddings.js +118 -0
- package/dist/memory/embeddings.js.map +1 -0
- package/dist/memory/hybrid.d.ts +35 -0
- package/dist/memory/hybrid.d.ts.map +1 -0
- package/dist/memory/hybrid.js +156 -0
- package/dist/memory/hybrid.js.map +1 -0
- package/dist/memory/markdown.d.ts +48 -0
- package/dist/memory/markdown.d.ts.map +1 -0
- package/dist/memory/markdown.js +228 -0
- package/dist/memory/markdown.js.map +1 -0
- package/dist/memory/store.d.ts +88 -0
- package/dist/memory/store.d.ts.map +1 -0
- package/dist/memory/store.js +21 -0
- package/dist/memory/store.js.map +1 -0
- package/dist/memory/vector.d.ts +24 -0
- package/dist/memory/vector.d.ts.map +1 -0
- package/dist/memory/vector.js +63 -0
- package/dist/memory/vector.js.map +1 -0
- package/dist/mods/mod.d.ts +100 -0
- package/dist/mods/mod.d.ts.map +1 -0
- package/dist/mods/mod.js +242 -0
- package/dist/mods/mod.js.map +1 -0
- package/dist/onboard/channels.d.ts +12 -0
- package/dist/onboard/channels.d.ts.map +1 -0
- package/dist/onboard/channels.js +283 -0
- package/dist/onboard/channels.js.map +1 -0
- package/dist/onboard/models.d.ts +13 -0
- package/dist/onboard/models.d.ts.map +1 -0
- package/dist/onboard/models.js +491 -0
- package/dist/onboard/models.js.map +1 -0
- package/dist/onboard/onboard.d.ts +12 -0
- package/dist/onboard/onboard.d.ts.map +1 -0
- package/dist/onboard/onboard.js +1137 -0
- package/dist/onboard/onboard.js.map +1 -0
- package/dist/providers/anthropic.d.ts +83 -0
- package/dist/providers/anthropic.d.ts.map +1 -0
- package/dist/providers/anthropic.js +583 -0
- package/dist/providers/anthropic.js.map +1 -0
- package/dist/providers/failover.d.ts +46 -0
- package/dist/providers/failover.d.ts.map +1 -0
- package/dist/providers/failover.js +149 -0
- package/dist/providers/failover.js.map +1 -0
- package/dist/providers/litellm.d.ts +38 -0
- package/dist/providers/litellm.d.ts.map +1 -0
- package/dist/providers/litellm.js +349 -0
- package/dist/providers/litellm.js.map +1 -0
- package/dist/providers/openai.d.ts +28 -0
- package/dist/providers/openai.d.ts.map +1 -0
- package/dist/providers/openai.js +321 -0
- package/dist/providers/openai.js.map +1 -0
- package/dist/providers/prompt-cache.d.ts +50 -0
- package/dist/providers/prompt-cache.d.ts.map +1 -0
- package/dist/providers/prompt-cache.js +96 -0
- package/dist/providers/prompt-cache.js.map +1 -0
- package/dist/providers/provider.d.ts +173 -0
- package/dist/providers/provider.d.ts.map +1 -0
- package/dist/providers/provider.js +22 -0
- package/dist/providers/provider.js.map +1 -0
- package/dist/sandbox/config.d.ts +42 -0
- package/dist/sandbox/config.d.ts.map +1 -0
- package/dist/sandbox/config.js +20 -0
- package/dist/sandbox/config.js.map +1 -0
- package/dist/sandbox/container.d.ts +71 -0
- package/dist/sandbox/container.d.ts.map +1 -0
- package/dist/sandbox/container.js +193 -0
- package/dist/sandbox/container.js.map +1 -0
- package/dist/sandbox/sandbox.d.ts +82 -0
- package/dist/sandbox/sandbox.d.ts.map +1 -0
- package/dist/sandbox/sandbox.js +176 -0
- package/dist/sandbox/sandbox.js.map +1 -0
- package/dist/skills/channel-loader.d.ts +18 -0
- package/dist/skills/channel-loader.d.ts.map +1 -0
- package/dist/skills/channel-loader.js +35 -0
- package/dist/skills/channel-loader.js.map +1 -0
- package/dist/skills/extension-loader.d.ts +15 -0
- package/dist/skills/extension-loader.d.ts.map +1 -0
- package/dist/skills/extension-loader.js +63 -0
- package/dist/skills/extension-loader.js.map +1 -0
- package/dist/skills/extension-registry.d.ts +32 -0
- package/dist/skills/extension-registry.d.ts.map +1 -0
- package/dist/skills/extension-registry.js +57 -0
- package/dist/skills/extension-registry.js.map +1 -0
- package/dist/skills/extensions.d.ts +91 -0
- package/dist/skills/extensions.d.ts.map +1 -0
- package/dist/skills/extensions.js +14 -0
- package/dist/skills/extensions.js.map +1 -0
- package/dist/skills/loader.d.ts +64 -0
- package/dist/skills/loader.d.ts.map +1 -0
- package/dist/skills/loader.js +382 -0
- package/dist/skills/loader.js.map +1 -0
- package/dist/skills/marketplace.d.ts +56 -0
- package/dist/skills/marketplace.d.ts.map +1 -0
- package/dist/skills/marketplace.js +183 -0
- package/dist/skills/marketplace.js.map +1 -0
- package/dist/skills/types.d.ts +94 -0
- package/dist/skills/types.d.ts.map +1 -0
- package/dist/skills/types.js +9 -0
- package/dist/skills/types.js.map +1 -0
- package/dist/tools/acp-sessions.d.ts +89 -0
- package/dist/tools/acp-sessions.d.ts.map +1 -0
- package/dist/tools/acp-sessions.js +391 -0
- package/dist/tools/acp-sessions.js.map +1 -0
- package/dist/tools/acp.d.ts +18 -0
- package/dist/tools/acp.d.ts.map +1 -0
- package/dist/tools/acp.js +102 -0
- package/dist/tools/acp.js.map +1 -0
- package/dist/tools/agent-tools.d.ts +24 -0
- package/dist/tools/agent-tools.d.ts.map +1 -0
- package/dist/tools/agent-tools.js +611 -0
- package/dist/tools/agent-tools.js.map +1 -0
- package/dist/tools/browser.d.ts +26 -0
- package/dist/tools/browser.d.ts.map +1 -0
- package/dist/tools/browser.js +242 -0
- package/dist/tools/browser.js.map +1 -0
- package/dist/tools/comms.d.ts +8 -0
- package/dist/tools/comms.d.ts.map +1 -0
- package/dist/tools/comms.js +39 -0
- package/dist/tools/comms.js.map +1 -0
- package/dist/tools/cron-tools.d.ts +9 -0
- package/dist/tools/cron-tools.d.ts.map +1 -0
- package/dist/tools/cron-tools.js +117 -0
- package/dist/tools/cron-tools.js.map +1 -0
- package/dist/tools/exec-safety.d.ts +71 -0
- package/dist/tools/exec-safety.d.ts.map +1 -0
- package/dist/tools/exec-safety.js +141 -0
- package/dist/tools/exec-safety.js.map +1 -0
- package/dist/tools/exec.d.ts +24 -0
- package/dist/tools/exec.d.ts.map +1 -0
- package/dist/tools/exec.js +191 -0
- package/dist/tools/exec.js.map +1 -0
- package/dist/tools/fs.d.ts +15 -0
- package/dist/tools/fs.d.ts.map +1 -0
- package/dist/tools/fs.js +249 -0
- package/dist/tools/fs.js.map +1 -0
- package/dist/tools/git.d.ts +9 -0
- package/dist/tools/git.d.ts.map +1 -0
- package/dist/tools/git.js +56 -0
- package/dist/tools/git.js.map +1 -0
- package/dist/tools/image.d.ts +15 -0
- package/dist/tools/image.d.ts.map +1 -0
- package/dist/tools/image.js +106 -0
- package/dist/tools/image.js.map +1 -0
- package/dist/tools/introspect.d.ts +22 -0
- package/dist/tools/introspect.d.ts.map +1 -0
- package/dist/tools/introspect.js +223 -0
- package/dist/tools/introspect.js.map +1 -0
- package/dist/tools/memory.d.ts +11 -0
- package/dist/tools/memory.d.ts.map +1 -0
- package/dist/tools/memory.js +101 -0
- package/dist/tools/memory.js.map +1 -0
- package/dist/tools/message.d.ts +24 -0
- package/dist/tools/message.d.ts.map +1 -0
- package/dist/tools/message.js +205 -0
- package/dist/tools/message.js.map +1 -0
- package/dist/tools/model.d.ts +14 -0
- package/dist/tools/model.d.ts.map +1 -0
- package/dist/tools/model.js +62 -0
- package/dist/tools/model.js.map +1 -0
- package/dist/tools/policy.d.ts +101 -0
- package/dist/tools/policy.d.ts.map +1 -0
- package/dist/tools/policy.js +168 -0
- package/dist/tools/policy.js.map +1 -0
- package/dist/tools/registry.d.ts +52 -0
- package/dist/tools/registry.d.ts.map +1 -0
- package/dist/tools/registry.js +154 -0
- package/dist/tools/registry.js.map +1 -0
- package/dist/tools/search.d.ts +10 -0
- package/dist/tools/search.d.ts.map +1 -0
- package/dist/tools/search.js +78 -0
- package/dist/tools/search.js.map +1 -0
- package/dist/tools/session.d.ts +13 -0
- package/dist/tools/session.d.ts.map +1 -0
- package/dist/tools/session.js +142 -0
- package/dist/tools/session.js.map +1 -0
- package/dist/tools/spawn.d.ts +10 -0
- package/dist/tools/spawn.d.ts.map +1 -0
- package/dist/tools/spawn.js +72 -0
- package/dist/tools/spawn.js.map +1 -0
- package/dist/tools/symphony.d.ts +12 -0
- package/dist/tools/symphony.d.ts.map +1 -0
- package/dist/tools/symphony.js +142 -0
- package/dist/tools/symphony.js.map +1 -0
- package/dist/tools/system-tools.d.ts +11 -0
- package/dist/tools/system-tools.d.ts.map +1 -0
- package/dist/tools/system-tools.js +39 -0
- package/dist/tools/system-tools.js.map +1 -0
- package/dist/tools/tool.d.ts +119 -0
- package/dist/tools/tool.d.ts.map +1 -0
- package/dist/tools/tool.js +29 -0
- package/dist/tools/tool.js.map +1 -0
- package/dist/tools/web.d.ts +10 -0
- package/dist/tools/web.d.ts.map +1 -0
- package/dist/tools/web.js +105 -0
- package/dist/tools/web.js.map +1 -0
- package/dist/tui/App.d.ts +43 -0
- package/dist/tui/App.d.ts.map +1 -0
- package/dist/tui/App.js +265 -0
- package/dist/tui/App.js.map +1 -0
- package/dist/tui/bridge.d.ts +40 -0
- package/dist/tui/bridge.d.ts.map +1 -0
- package/dist/tui/bridge.js +29 -0
- package/dist/tui/bridge.js.map +1 -0
- package/dist/tui/components/Header.d.ts +14 -0
- package/dist/tui/components/Header.d.ts.map +1 -0
- package/dist/tui/components/Header.js +7 -0
- package/dist/tui/components/Header.js.map +1 -0
- package/dist/tui/components/InputBar.d.ts +10 -0
- package/dist/tui/components/InputBar.d.ts.map +1 -0
- package/dist/tui/components/InputBar.js +121 -0
- package/dist/tui/components/InputBar.js.map +1 -0
- package/dist/tui/components/MessageList.d.ts +18 -0
- package/dist/tui/components/MessageList.d.ts.map +1 -0
- package/dist/tui/components/MessageList.js +34 -0
- package/dist/tui/components/MessageList.js.map +1 -0
- package/dist/tui/components/Spinner.d.ts +9 -0
- package/dist/tui/components/Spinner.d.ts.map +1 -0
- package/dist/tui/components/Spinner.js +18 -0
- package/dist/tui/components/Spinner.js.map +1 -0
- package/dist/tui/components/StatusBar.d.ts +16 -0
- package/dist/tui/components/StatusBar.d.ts.map +1 -0
- package/dist/tui/components/StatusBar.js +15 -0
- package/dist/tui/components/StatusBar.js.map +1 -0
- package/dist/tui/components/ToolCallBox.d.ts +12 -0
- package/dist/tui/components/ToolCallBox.d.ts.map +1 -0
- package/dist/tui/components/ToolCallBox.js +12 -0
- package/dist/tui/components/ToolCallBox.js.map +1 -0
- package/dist/tui/theme.d.ts +58 -0
- package/dist/tui/theme.d.ts.map +1 -0
- package/dist/tui/theme.js +80 -0
- package/dist/tui/theme.js.map +1 -0
- package/dist/utils/logger.d.ts +16 -0
- package/dist/utils/logger.d.ts.map +1 -0
- package/dist/utils/logger.js +70 -0
- package/dist/utils/logger.js.map +1 -0
- package/docs/DEVELOPMENT.md +74 -0
- package/docs/INSTALL.md +161 -0
- package/docs/USAGE.md +94 -0
- package/docs/architecture.md +128 -0
- package/docs/channels.md +140 -0
- package/docs/configuration.md +209 -0
- package/docs/io-system.md +430 -0
- package/docs/providers.md +99 -0
- package/docs/skill-channels.md +113 -0
- package/docs/skills.md +246 -0
- package/package.json +89 -0
- package/skills/acp-router/SKILL.md +41 -0
- package/skills/acp-router/tools/acp-router.mjs +239 -0
- package/skills/find-skills/SKILL.md +133 -0
- package/skills/security-audit/SKILL.md +181 -0
- package/skills/security-audit/audit.sh +67 -0
- package/skills/skill-creator/SKILL.md +479 -0
- package/skills/skill-security-audit/.clawhub/origin.json +7 -0
- package/skills/skill-security-audit/SKILL.md +196 -0
- package/skills/skill-security-audit/_meta.json +6 -0
- package/skills/skill-security-audit/references/prompt-injection-patterns.md +276 -0
- package/skills/skill-security-audit/references/vulnerability-patterns.md +348 -0
- package/skills/symphony/README.md +53 -0
- package/skills/symphony/SKILL.md +75 -0
- package/skills/symphony/tools/symphony-orchestrator.ts +8 -0
- package/tako.example.json +33 -0
|
@@ -0,0 +1,700 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Agent loop — the CPU cycle.
|
|
3
|
+
*
|
|
4
|
+
* 1. Message arrives (from any Channel)
|
|
5
|
+
* 2. Session resolved (or created)
|
|
6
|
+
* 3. Context assembled (system prompt + dynamic skill injection + history + memory)
|
|
7
|
+
* 4. Provider.chat() called (streaming)
|
|
8
|
+
* 5. Tool calls executed (if any)
|
|
9
|
+
* 6. Response streamed back through Channel
|
|
10
|
+
* 7. Session persisted
|
|
11
|
+
* 8. Memory updated (if needed)
|
|
12
|
+
*/
|
|
13
|
+
import { buildSessionInitContext } from './session-init.js';
|
|
14
|
+
import { ResponseStreamer } from './streaming.js';
|
|
15
|
+
import { isToolAllowed, getRole } from '../agents/roles.js';
|
|
16
|
+
import { scanSecrets, checkRateLimit, sanitizeInput, getToolValidator } from './security.js';
|
|
17
|
+
import { parseCommand } from '../commands/parser.js';
|
|
18
|
+
import { dispatchSkillCommand } from '../commands/dispatch.js';
|
|
19
|
+
const DEFAULT_LOOP_CONFIG = {
|
|
20
|
+
timeout: 600,
|
|
21
|
+
maxToolCalls: 50,
|
|
22
|
+
maxTurns: 20,
|
|
23
|
+
maxOutputChars: 50_000,
|
|
24
|
+
};
|
|
25
|
+
export class AgentLoop {
|
|
26
|
+
config;
|
|
27
|
+
deps;
|
|
28
|
+
constructor(deps, config) {
|
|
29
|
+
this.deps = deps;
|
|
30
|
+
this.config = { ...DEFAULT_LOOP_CONFIG, ...config };
|
|
31
|
+
}
|
|
32
|
+
/** Switch the active model at runtime. */
|
|
33
|
+
setModel(modelRef) {
|
|
34
|
+
this.deps.model = modelRef;
|
|
35
|
+
}
|
|
36
|
+
/** Get the current active model. */
|
|
37
|
+
getModel() {
|
|
38
|
+
return this.deps.model ?? 'anthropic/claude-sonnet-4-6';
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Sanitize messages for API compatibility:
|
|
42
|
+
* - Merge consecutive user messages (some APIs reject this)
|
|
43
|
+
* - Ensure conversation doesn't end with assistant (prefill rejection)
|
|
44
|
+
* - Strip empty messages
|
|
45
|
+
* - Repair tool_use/tool_result pairing (Anthropic requires each tool_result
|
|
46
|
+
* to have a matching tool_use in the previous assistant message)
|
|
47
|
+
*/
|
|
48
|
+
sanitizeMessages(messages) {
|
|
49
|
+
const result = [];
|
|
50
|
+
for (const msg of messages) {
|
|
51
|
+
// Skip empty text messages
|
|
52
|
+
if (typeof msg.content === 'string' && !msg.content.trim() && msg.role !== 'system')
|
|
53
|
+
continue;
|
|
54
|
+
// Merge consecutive user messages
|
|
55
|
+
const prev = result[result.length - 1];
|
|
56
|
+
if (prev && prev.role === 'user' && msg.role === 'user'
|
|
57
|
+
&& typeof prev.content === 'string' && typeof msg.content === 'string') {
|
|
58
|
+
prev.content = prev.content + '\n' + msg.content;
|
|
59
|
+
continue;
|
|
60
|
+
}
|
|
61
|
+
result.push({ ...msg });
|
|
62
|
+
}
|
|
63
|
+
// Strip trailing assistant messages (prevents "prefill" errors)
|
|
64
|
+
while (result.length > 0 && result[result.length - 1].role === 'assistant') {
|
|
65
|
+
result.pop();
|
|
66
|
+
}
|
|
67
|
+
// Repair tool_use/tool_result pairing
|
|
68
|
+
return this.repairToolPairing(result);
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* Repair tool_use/tool_result pairing in message history.
|
|
72
|
+
* Anthropic requires every tool_result to have a matching tool_use
|
|
73
|
+
* in the preceding assistant message, and vice versa.
|
|
74
|
+
*
|
|
75
|
+
* Based on reference runtime's repairToolUseResultPairing pattern.
|
|
76
|
+
*/
|
|
77
|
+
repairToolPairing(messages) {
|
|
78
|
+
const result = [];
|
|
79
|
+
for (let i = 0; i < messages.length; i++) {
|
|
80
|
+
const msg = messages[i];
|
|
81
|
+
if (msg.role !== 'assistant' || typeof msg.content === 'string') {
|
|
82
|
+
// For tool results, verify they have a matching tool_use in a preceding assistant
|
|
83
|
+
if (msg.role === 'tool' && msg.tool_call_id) {
|
|
84
|
+
// Check if there's a matching tool_use in the previous assistant message
|
|
85
|
+
const prevAssistant = [...result].reverse().find((m) => m.role === 'assistant');
|
|
86
|
+
if (prevAssistant && Array.isArray(prevAssistant.content)) {
|
|
87
|
+
const hasMatch = prevAssistant.content.some((p) => p.type === 'tool_use' && p.id === msg.tool_call_id);
|
|
88
|
+
if (!hasMatch) {
|
|
89
|
+
// Orphan tool_result — drop it
|
|
90
|
+
continue;
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
result.push(msg);
|
|
95
|
+
continue;
|
|
96
|
+
}
|
|
97
|
+
// Assistant message with content blocks — check for tool_use blocks
|
|
98
|
+
const toolUseIds = new Set();
|
|
99
|
+
if (Array.isArray(msg.content)) {
|
|
100
|
+
for (const part of msg.content) {
|
|
101
|
+
if (part.type === 'tool_use') {
|
|
102
|
+
toolUseIds.add(part.id);
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
result.push(msg);
|
|
107
|
+
if (toolUseIds.size === 0)
|
|
108
|
+
continue;
|
|
109
|
+
// Collect subsequent tool results that match these tool_use IDs.
|
|
110
|
+
// Scan past interleaved user messages — they can appear between
|
|
111
|
+
// tool_use and tool_result when the message queue delivers a new
|
|
112
|
+
// user message while a tool call is in flight.
|
|
113
|
+
const foundIds = new Set();
|
|
114
|
+
const deferredUserMessages = [];
|
|
115
|
+
let j = i + 1;
|
|
116
|
+
while (j < messages.length) {
|
|
117
|
+
const candidate = messages[j];
|
|
118
|
+
if (candidate.role === 'tool') {
|
|
119
|
+
if (candidate.tool_call_id && toolUseIds.has(candidate.tool_call_id)) {
|
|
120
|
+
foundIds.add(candidate.tool_call_id);
|
|
121
|
+
result.push(candidate);
|
|
122
|
+
}
|
|
123
|
+
// Drop orphan tool results that don't match any tool_use
|
|
124
|
+
j++;
|
|
125
|
+
}
|
|
126
|
+
else if (candidate.role === 'user' && foundIds.size < toolUseIds.size) {
|
|
127
|
+
// User message arrived mid-tool-execution — defer it until after tool results
|
|
128
|
+
deferredUserMessages.push(candidate);
|
|
129
|
+
j++;
|
|
130
|
+
}
|
|
131
|
+
else {
|
|
132
|
+
break;
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
// Add synthetic results for any tool_use without a matching result
|
|
136
|
+
for (const id of toolUseIds) {
|
|
137
|
+
if (!foundIds.has(id)) {
|
|
138
|
+
const toolUse = msg.content.find((p) => p.type === 'tool_use' && p.id === id);
|
|
139
|
+
const name = toolUse && 'name' in toolUse ? toolUse.name : 'unknown';
|
|
140
|
+
result.push({
|
|
141
|
+
role: 'tool',
|
|
142
|
+
content: `[Tool result missing — ${name} was called but no result was recorded]`,
|
|
143
|
+
tool_call_id: id,
|
|
144
|
+
});
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
// Re-insert any deferred user messages after tool results
|
|
148
|
+
for (const deferred of deferredUserMessages) {
|
|
149
|
+
result.push(deferred);
|
|
150
|
+
}
|
|
151
|
+
// Skip the tool results (and deferred messages) we already processed
|
|
152
|
+
i = j - 1;
|
|
153
|
+
}
|
|
154
|
+
return result;
|
|
155
|
+
}
|
|
156
|
+
/**
|
|
157
|
+
* Run the agent loop for a single turn.
|
|
158
|
+
* Yields text chunks as they stream from the provider.
|
|
159
|
+
* Dynamically injects matching skill instructions based on the user message.
|
|
160
|
+
*/
|
|
161
|
+
/** Set the active channel for typing/reactions (call before run). */
|
|
162
|
+
setChannel(channel) {
|
|
163
|
+
this.deps.channel = channel;
|
|
164
|
+
}
|
|
165
|
+
async *run(session, userMessage, attachments) {
|
|
166
|
+
const { provider, toolRegistry, promptBuilder, contextManager, hooks, skillLoader } = this.deps;
|
|
167
|
+
// 1. Fire agent_start hook
|
|
168
|
+
if (hooks) {
|
|
169
|
+
await hooks.emit('agent_start', {
|
|
170
|
+
event: 'agent_start',
|
|
171
|
+
sessionId: session.id,
|
|
172
|
+
data: { userMessage },
|
|
173
|
+
timestamp: Date.now(),
|
|
174
|
+
});
|
|
175
|
+
}
|
|
176
|
+
// 1a. Rate limiting check
|
|
177
|
+
const authorId = session.metadata?.authorId;
|
|
178
|
+
const channelId = session.metadata?.channelId;
|
|
179
|
+
if (authorId && channelId) {
|
|
180
|
+
const rateLimitMsg = checkRateLimit(authorId, channelId);
|
|
181
|
+
if (rateLimitMsg) {
|
|
182
|
+
yield rateLimitMsg;
|
|
183
|
+
return;
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
// 1a2. Input sanitization
|
|
187
|
+
const sanitized_input = sanitizeInput(userMessage);
|
|
188
|
+
if (sanitized_input.blocked) {
|
|
189
|
+
yield 'Your message was blocked by security policy.';
|
|
190
|
+
return;
|
|
191
|
+
}
|
|
192
|
+
userMessage = sanitized_input.text;
|
|
193
|
+
// 1a3. Start typing indicator
|
|
194
|
+
const chatId = session.metadata?.channelTarget ?? session.metadata?.channelId ?? session.id;
|
|
195
|
+
if (this.deps.typingManager && this.deps.channel) {
|
|
196
|
+
this.deps.typingManager.start(this.deps.channel, chatId);
|
|
197
|
+
}
|
|
198
|
+
// 1b. React with 👀 (received)
|
|
199
|
+
const messageId = session.metadata?.messageId;
|
|
200
|
+
if (this.deps.reactionManager && this.deps.channel && messageId) {
|
|
201
|
+
await this.deps.reactionManager.react(this.deps.channel, chatId, messageId, 'received');
|
|
202
|
+
}
|
|
203
|
+
// 1c. Check if message is a command
|
|
204
|
+
const parsed = parseCommand(userMessage);
|
|
205
|
+
if (parsed) {
|
|
206
|
+
// /think <level> — set thinking level for this session
|
|
207
|
+
if (parsed.command === 'think' && this.deps.thinkingManager) {
|
|
208
|
+
const levels = ['off', 'minimal', 'low', 'medium', 'high', 'xhigh'];
|
|
209
|
+
const level = parsed.args.trim().toLowerCase();
|
|
210
|
+
if (levels.includes(level)) {
|
|
211
|
+
this.deps.thinkingManager.setLevel(session.id, level);
|
|
212
|
+
this.deps.typingManager?.stop(chatId);
|
|
213
|
+
yield `Thinking level set to **${level}** for this session.`;
|
|
214
|
+
return;
|
|
215
|
+
}
|
|
216
|
+
this.deps.typingManager?.stop(chatId);
|
|
217
|
+
yield `Invalid thinking level. Use one of: ${levels.join(', ')}`;
|
|
218
|
+
return;
|
|
219
|
+
}
|
|
220
|
+
// Built-in commands (/help, /status, etc.)
|
|
221
|
+
if (this.deps.commandRegistry) {
|
|
222
|
+
const builtinResult = await this.deps.commandRegistry.handle(userMessage, {
|
|
223
|
+
channelId: session.metadata?.channelId ?? '',
|
|
224
|
+
authorId: session.metadata?.authorId ?? '',
|
|
225
|
+
authorName: session.metadata?.authorName ?? '',
|
|
226
|
+
session,
|
|
227
|
+
agentId: this.deps.agentId ?? '',
|
|
228
|
+
});
|
|
229
|
+
if (builtinResult !== null) {
|
|
230
|
+
this.deps.typingManager?.stop(chatId);
|
|
231
|
+
yield builtinResult;
|
|
232
|
+
return;
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
// Skill commands
|
|
236
|
+
if (this.deps.skillCommandSpecs && this.deps.skillCommandSpecs.length > 0 && skillLoader) {
|
|
237
|
+
const dispatchCtx = {
|
|
238
|
+
toolRegistry,
|
|
239
|
+
skillLoader,
|
|
240
|
+
toolContext: {
|
|
241
|
+
sessionId: session.id,
|
|
242
|
+
workDir: this.deps.workspaceRoot ?? process.cwd(),
|
|
243
|
+
workspaceRoot: this.deps.workspaceRoot ?? process.cwd(),
|
|
244
|
+
agentId: this.deps.agentId,
|
|
245
|
+
agentRole: this.deps.agentRole ?? 'admin',
|
|
246
|
+
},
|
|
247
|
+
};
|
|
248
|
+
const result = await dispatchSkillCommand(parsed, this.deps.skillCommandSpecs, dispatchCtx);
|
|
249
|
+
if (result.kind === 'tool-result') {
|
|
250
|
+
this.deps.typingManager?.stop(chatId);
|
|
251
|
+
yield result.response ?? '';
|
|
252
|
+
return;
|
|
253
|
+
}
|
|
254
|
+
if (result.kind === 'skill-inject') {
|
|
255
|
+
// Rewrite userMessage with the args and inject skill instructions below
|
|
256
|
+
userMessage = result.forwardMessage ?? userMessage;
|
|
257
|
+
// We'll inject the skill instructions when building the system prompt
|
|
258
|
+
// Store it so the prompt builder can pick it up
|
|
259
|
+
session.metadata = {
|
|
260
|
+
...session.metadata,
|
|
261
|
+
_injectedSkillInstructions: result.instructions,
|
|
262
|
+
_injectedSkillName: result.skillName,
|
|
263
|
+
};
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
// 1d. Transition reaction to processing
|
|
268
|
+
if (this.deps.reactionManager && this.deps.channel && messageId) {
|
|
269
|
+
await this.deps.reactionManager.transition(this.deps.channel, chatId, messageId, 'received', 'processing');
|
|
270
|
+
}
|
|
271
|
+
// 2. Build system prompt
|
|
272
|
+
if (hooks) {
|
|
273
|
+
await hooks.emit('before_prompt_build', {
|
|
274
|
+
event: 'before_prompt_build',
|
|
275
|
+
sessionId: session.id,
|
|
276
|
+
data: {},
|
|
277
|
+
timestamp: Date.now(),
|
|
278
|
+
});
|
|
279
|
+
}
|
|
280
|
+
// Inject self-awareness context into prompt builder
|
|
281
|
+
promptBuilder.setTools(toolRegistry.getActiveTools());
|
|
282
|
+
if (skillLoader) {
|
|
283
|
+
promptBuilder.setSkills(skillLoader.getAll());
|
|
284
|
+
}
|
|
285
|
+
if (this.deps.model) {
|
|
286
|
+
promptBuilder.setModel(this.deps.model);
|
|
287
|
+
}
|
|
288
|
+
if (this.deps.workspaceRoot) {
|
|
289
|
+
promptBuilder.setWorkingDir(this.deps.workspaceRoot);
|
|
290
|
+
}
|
|
291
|
+
// Inject timezone context
|
|
292
|
+
if (this.deps.timezoneManager) {
|
|
293
|
+
promptBuilder.setTimezoneContext(this.deps.timezoneManager.getContextString());
|
|
294
|
+
}
|
|
295
|
+
let systemPrompt = await promptBuilder.build({ mode: 'full' });
|
|
296
|
+
// Dynamic skill injection: check trigger conditions against the user message
|
|
297
|
+
if (skillLoader) {
|
|
298
|
+
const matchingSkills = skillLoader.getMatchingSkills(userMessage);
|
|
299
|
+
for (const skill of matchingSkills) {
|
|
300
|
+
// Avoid duplicating instructions already in the base prompt
|
|
301
|
+
const snippet = skill.instructions.slice(0, 100);
|
|
302
|
+
if (!systemPrompt.includes(snippet)) {
|
|
303
|
+
systemPrompt += `\n\n---\n\n# Skill: ${skill.manifest.name}\n\n${skill.instructions}`;
|
|
304
|
+
}
|
|
305
|
+
}
|
|
306
|
+
}
|
|
307
|
+
// Inject skill instructions from command dispatch (if applicable)
|
|
308
|
+
const injectedInstructions = session.metadata?._injectedSkillInstructions;
|
|
309
|
+
const injectedSkillName = session.metadata?._injectedSkillName;
|
|
310
|
+
if (injectedInstructions && injectedSkillName) {
|
|
311
|
+
const snippet = injectedInstructions.slice(0, 100);
|
|
312
|
+
if (!systemPrompt.includes(snippet)) {
|
|
313
|
+
systemPrompt += `\n\n---\n\n# Skill: ${injectedSkillName}\n\n${injectedInstructions}`;
|
|
314
|
+
}
|
|
315
|
+
// Clean up metadata
|
|
316
|
+
delete session.metadata?._injectedSkillInstructions;
|
|
317
|
+
delete session.metadata?._injectedSkillName;
|
|
318
|
+
}
|
|
319
|
+
// 3. Append user message to session (with image attachments as content blocks)
|
|
320
|
+
const imageAttachments = attachments?.filter((a) => (a.type === 'image' || a.mimeType?.startsWith('image/')) && a.url) ?? [];
|
|
321
|
+
if (imageAttachments.length > 0) {
|
|
322
|
+
// Download images and convert to base64 for provider compatibility
|
|
323
|
+
const imageParts = [];
|
|
324
|
+
for (const a of imageAttachments) {
|
|
325
|
+
try {
|
|
326
|
+
const resp = await fetch(a.url);
|
|
327
|
+
if (resp.ok) {
|
|
328
|
+
const buffer = Buffer.from(await resp.arrayBuffer());
|
|
329
|
+
const mediaType = a.mimeType || resp.headers.get('content-type') || 'image/png';
|
|
330
|
+
imageParts.push({
|
|
331
|
+
type: 'image_base64',
|
|
332
|
+
media_type: mediaType,
|
|
333
|
+
data: buffer.toString('base64'),
|
|
334
|
+
});
|
|
335
|
+
}
|
|
336
|
+
else {
|
|
337
|
+
console.warn(`[agent-loop] Failed to fetch image ${a.url}: HTTP ${resp.status}`);
|
|
338
|
+
}
|
|
339
|
+
}
|
|
340
|
+
catch (err) {
|
|
341
|
+
console.warn(`[agent-loop] Failed to fetch image ${a.url}:`, err instanceof Error ? err.message : err);
|
|
342
|
+
}
|
|
343
|
+
}
|
|
344
|
+
if (imageParts.length > 0) {
|
|
345
|
+
const contentParts = [
|
|
346
|
+
{ type: 'text', text: userMessage || 'What is in this image?' },
|
|
347
|
+
...imageParts,
|
|
348
|
+
];
|
|
349
|
+
session.messages.push({ role: 'user', content: contentParts });
|
|
350
|
+
}
|
|
351
|
+
else {
|
|
352
|
+
session.messages.push({ role: 'user', content: userMessage });
|
|
353
|
+
}
|
|
354
|
+
}
|
|
355
|
+
else {
|
|
356
|
+
session.messages.push({ role: 'user', content: userMessage });
|
|
357
|
+
}
|
|
358
|
+
// 4. Assemble context
|
|
359
|
+
const messages = [
|
|
360
|
+
{ role: 'system', content: systemPrompt },
|
|
361
|
+
...session.messages,
|
|
362
|
+
];
|
|
363
|
+
// 5. Get tool definitions
|
|
364
|
+
const tools = toolRegistry.getActiveTools().map((t) => ({
|
|
365
|
+
name: t.name,
|
|
366
|
+
description: t.description,
|
|
367
|
+
parameters: t.parameters,
|
|
368
|
+
}));
|
|
369
|
+
// 6. Agent loop (may iterate if tool calls occur)
|
|
370
|
+
let turns = 0;
|
|
371
|
+
while (turns < this.config.maxTurns) {
|
|
372
|
+
turns++;
|
|
373
|
+
if (contextManager.needsCompaction(messages) && this.deps.compactor) {
|
|
374
|
+
const compactionResult = await this.deps.compactor.checkAndCompact(session);
|
|
375
|
+
// Rebuild messages array from compacted session
|
|
376
|
+
messages.length = 0;
|
|
377
|
+
messages.push({ role: 'system', content: systemPrompt }, ...session.messages);
|
|
378
|
+
// Inject session init context after compaction
|
|
379
|
+
if (compactionResult && this.deps.progressTracker) {
|
|
380
|
+
const initContext = await buildSessionInitContext(this.deps.progressTracker, this.deps.sessionInitConfig);
|
|
381
|
+
const initMsg = { role: 'system', content: initContext };
|
|
382
|
+
session.messages.push(initMsg);
|
|
383
|
+
messages.push(initMsg);
|
|
384
|
+
}
|
|
385
|
+
}
|
|
386
|
+
const model = this.deps.model ?? 'anthropic/claude-sonnet-4-6';
|
|
387
|
+
// Sanitize messages: merge consecutive same-role messages for API compatibility
|
|
388
|
+
const sanitized = this.sanitizeMessages(messages);
|
|
389
|
+
let fullText = '';
|
|
390
|
+
let pendingToolCalls = [];
|
|
391
|
+
const turnStartMs = Date.now();
|
|
392
|
+
let lastUsage;
|
|
393
|
+
// Set up streaming if a channel is available and streaming is enabled
|
|
394
|
+
const streamingCfg = this.deps.streamingConfig;
|
|
395
|
+
const channelRef = session.metadata?.channelRef;
|
|
396
|
+
const channelTarget = session.metadata?.channelTarget;
|
|
397
|
+
// reference runtime-style default: streaming off unless explicitly enabled in config
|
|
398
|
+
const streamEnabled = streamingCfg?.enabled === true && channelRef && channelTarget;
|
|
399
|
+
let streamer;
|
|
400
|
+
if (streamEnabled) {
|
|
401
|
+
const maxLen = channelRef.id === 'telegram' ? 4096 : 2000;
|
|
402
|
+
streamer = new ResponseStreamer({
|
|
403
|
+
enabled: true,
|
|
404
|
+
minChunkSize: streamingCfg?.minChunkSize ?? 50,
|
|
405
|
+
flushIntervalMs: streamingCfg?.flushIntervalMs ?? 500,
|
|
406
|
+
maxMessageLength: maxLen,
|
|
407
|
+
}, { channelId: channelTarget, channel: channelRef });
|
|
408
|
+
}
|
|
409
|
+
// Collect chunks — only yield text to caller on final turn (no tool calls)
|
|
410
|
+
const chunks = [];
|
|
411
|
+
try {
|
|
412
|
+
for await (const chunk of provider.chat({
|
|
413
|
+
model,
|
|
414
|
+
messages: sanitized,
|
|
415
|
+
tools: tools.length > 0 ? tools : undefined,
|
|
416
|
+
stream: true,
|
|
417
|
+
...(this.config.maxTokens != null && { max_tokens: this.config.maxTokens }),
|
|
418
|
+
})) {
|
|
419
|
+
if (chunk.text) {
|
|
420
|
+
fullText += chunk.text;
|
|
421
|
+
chunks.push(chunk.text);
|
|
422
|
+
// Push to streamer for real-time delivery
|
|
423
|
+
if (streamer) {
|
|
424
|
+
await streamer.push(chunk.text);
|
|
425
|
+
}
|
|
426
|
+
}
|
|
427
|
+
if (chunk.tool_calls) {
|
|
428
|
+
pendingToolCalls.push(...chunk.tool_calls);
|
|
429
|
+
}
|
|
430
|
+
if (chunk.done && chunk.usage) {
|
|
431
|
+
lastUsage = chunk.usage;
|
|
432
|
+
}
|
|
433
|
+
}
|
|
434
|
+
}
|
|
435
|
+
catch (err) {
|
|
436
|
+
// Cancel streamer on error
|
|
437
|
+
if (streamer)
|
|
438
|
+
await streamer.cancel();
|
|
439
|
+
// All model providers failed — enqueue for retry if available
|
|
440
|
+
if (this.deps.retryQueue) {
|
|
441
|
+
this.deps.retryQueue.enqueue({
|
|
442
|
+
userMessage,
|
|
443
|
+
sessionId: session.id,
|
|
444
|
+
channelId: session.metadata?.channelId,
|
|
445
|
+
messageId: session.metadata?.messageId,
|
|
446
|
+
channel: session.metadata?.channelRef,
|
|
447
|
+
});
|
|
448
|
+
}
|
|
449
|
+
this.deps.typingManager?.stop(chatId);
|
|
450
|
+
// Transition reaction to failed
|
|
451
|
+
if (this.deps.reactionManager && this.deps.channel && messageId) {
|
|
452
|
+
await this.deps.reactionManager.transition(this.deps.channel, chatId, messageId, 'processing', 'failed');
|
|
453
|
+
}
|
|
454
|
+
throw err;
|
|
455
|
+
}
|
|
456
|
+
// Finish streaming for this turn (flush remaining buffer)
|
|
457
|
+
if (streamer) {
|
|
458
|
+
await streamer.finish();
|
|
459
|
+
}
|
|
460
|
+
// Record usage for this turn
|
|
461
|
+
if (this.deps.usageTracker && lastUsage) {
|
|
462
|
+
const cachedTokens = (lastUsage.cache_read_input_tokens ?? 0);
|
|
463
|
+
this.deps.usageTracker.record({
|
|
464
|
+
sessionId: session.id,
|
|
465
|
+
model,
|
|
466
|
+
provider: model.includes('/') ? model.split('/')[0] : 'unknown',
|
|
467
|
+
timestamp: Date.now(),
|
|
468
|
+
inputTokens: lastUsage.prompt_tokens,
|
|
469
|
+
outputTokens: lastUsage.completion_tokens,
|
|
470
|
+
cachedTokens,
|
|
471
|
+
totalTokens: lastUsage.total_tokens,
|
|
472
|
+
durationMs: Date.now() - turnStartMs,
|
|
473
|
+
});
|
|
474
|
+
}
|
|
475
|
+
// Scan model output for secrets before yielding
|
|
476
|
+
if (fullText) {
|
|
477
|
+
const scannedText = scanSecrets(fullText);
|
|
478
|
+
if (scannedText !== fullText) {
|
|
479
|
+
// Rebuild chunks from scanned text
|
|
480
|
+
chunks.length = 0;
|
|
481
|
+
chunks.push(scannedText);
|
|
482
|
+
fullText = scannedText;
|
|
483
|
+
}
|
|
484
|
+
}
|
|
485
|
+
// Only yield text from the final turn (no pending tool calls).
|
|
486
|
+
// Intermediate turns often repeat the same intro text before each tool call,
|
|
487
|
+
// which clutters the output. The final turn has the actual response.
|
|
488
|
+
if (pendingToolCalls.length === 0 && !fullText && turns > 1) {
|
|
489
|
+
// Final turn after tool calls produced no text — yield a minimal acknowledgment
|
|
490
|
+
// so the user isn't left with silence.
|
|
491
|
+
console.warn(`[agent-loop] Turn ${turns}: no text after tool calls (${chunks.length} chunks, fullText empty)`);
|
|
492
|
+
if (!streamer)
|
|
493
|
+
yield '✅ Done.';
|
|
494
|
+
}
|
|
495
|
+
if (pendingToolCalls.length === 0 && !streamer) {
|
|
496
|
+
let emitted = 0;
|
|
497
|
+
for (const c of chunks) {
|
|
498
|
+
const remaining = this.config.maxOutputChars - emitted;
|
|
499
|
+
if (remaining <= 0) {
|
|
500
|
+
yield '\n\n[Output truncated — response exceeded character limit]';
|
|
501
|
+
break;
|
|
502
|
+
}
|
|
503
|
+
const accepted = c.length <= remaining ? c : c.slice(0, remaining);
|
|
504
|
+
yield accepted;
|
|
505
|
+
emitted += accepted.length;
|
|
506
|
+
if (accepted.length < c.length) {
|
|
507
|
+
yield '\n\n[Output truncated — response exceeded character limit]';
|
|
508
|
+
break;
|
|
509
|
+
}
|
|
510
|
+
}
|
|
511
|
+
}
|
|
512
|
+
// Append assistant message to session history.
|
|
513
|
+
// For intermediate turns (with tool calls), strip the preamble text to prevent
|
|
514
|
+
// context pollution — the model sees its own repeated intros and reinforces them.
|
|
515
|
+
// Only keep tool_use blocks in intermediate turns; final turn keeps full text.
|
|
516
|
+
if (fullText || pendingToolCalls.length > 0) {
|
|
517
|
+
const contentParts = [];
|
|
518
|
+
if (pendingToolCalls.length > 0) {
|
|
519
|
+
// Intermediate turn: replace verbose preamble with a short marker.
|
|
520
|
+
// This prevents the model from seeing N copies of "I'll help you..." in context.
|
|
521
|
+
contentParts.push({ type: 'text', text: '[Calling tools]' });
|
|
522
|
+
}
|
|
523
|
+
else if (fullText) {
|
|
524
|
+
contentParts.push({ type: 'text', text: fullText });
|
|
525
|
+
}
|
|
526
|
+
for (const tc of pendingToolCalls) {
|
|
527
|
+
contentParts.push({ type: 'tool_use', id: tc.id, name: tc.name, input: tc.input });
|
|
528
|
+
}
|
|
529
|
+
const assistantMsg = {
|
|
530
|
+
role: 'assistant',
|
|
531
|
+
content: pendingToolCalls.length > 0 ? contentParts : fullText,
|
|
532
|
+
};
|
|
533
|
+
session.messages.push(assistantMsg);
|
|
534
|
+
messages.push(assistantMsg);
|
|
535
|
+
}
|
|
536
|
+
if (pendingToolCalls.length === 0)
|
|
537
|
+
break;
|
|
538
|
+
// Execute tool calls
|
|
539
|
+
const roleName = this.deps.agentRole ?? 'admin';
|
|
540
|
+
const role = getRole(roleName);
|
|
541
|
+
const toolCtx = {
|
|
542
|
+
sessionId: session.id,
|
|
543
|
+
workDir: this.deps.workspaceRoot ?? process.cwd(),
|
|
544
|
+
workspaceRoot: this.deps.workspaceRoot ?? process.cwd(),
|
|
545
|
+
agentId: this.deps.agentId,
|
|
546
|
+
agentRole: roleName,
|
|
547
|
+
channelType: session.metadata?.channelType,
|
|
548
|
+
channelTarget: session.metadata?.channelTarget,
|
|
549
|
+
channel: session.metadata?.channelRef,
|
|
550
|
+
};
|
|
551
|
+
for (const tc of pendingToolCalls) {
|
|
552
|
+
// Check for tool loops before execution
|
|
553
|
+
if (this.deps.toolLoopDetector) {
|
|
554
|
+
const loopWarning = this.deps.toolLoopDetector.recordAndCheck(session.id, tc.name, (tc.input ?? {}));
|
|
555
|
+
if (loopWarning) {
|
|
556
|
+
const loopMsg = { role: 'system', content: loopWarning };
|
|
557
|
+
session.messages.push(loopMsg);
|
|
558
|
+
messages.push(loopMsg);
|
|
559
|
+
const toolMsg = {
|
|
560
|
+
role: 'tool',
|
|
561
|
+
content: loopWarning,
|
|
562
|
+
tool_call_id: tc.id,
|
|
563
|
+
};
|
|
564
|
+
session.messages.push(toolMsg);
|
|
565
|
+
messages.push(toolMsg);
|
|
566
|
+
continue;
|
|
567
|
+
}
|
|
568
|
+
}
|
|
569
|
+
// Check role-based permissions before execution
|
|
570
|
+
if (role && !isToolAllowed(role, tc.name)) {
|
|
571
|
+
const deniedResult = {
|
|
572
|
+
output: `Permission denied: agent role "${roleName}" cannot use tool "${tc.name}"`,
|
|
573
|
+
success: false,
|
|
574
|
+
};
|
|
575
|
+
if (hooks) {
|
|
576
|
+
await hooks.emit('after_tool_call', {
|
|
577
|
+
event: 'after_tool_call',
|
|
578
|
+
sessionId: session.id,
|
|
579
|
+
data: { toolName: tc.name, result: deniedResult },
|
|
580
|
+
timestamp: Date.now(),
|
|
581
|
+
});
|
|
582
|
+
}
|
|
583
|
+
const toolMsg = {
|
|
584
|
+
role: 'tool',
|
|
585
|
+
content: deniedResult.output,
|
|
586
|
+
tool_call_id: tc.id,
|
|
587
|
+
};
|
|
588
|
+
session.messages.push(toolMsg);
|
|
589
|
+
messages.push(toolMsg);
|
|
590
|
+
continue;
|
|
591
|
+
}
|
|
592
|
+
if (hooks) {
|
|
593
|
+
await hooks.emit('before_tool_call', {
|
|
594
|
+
event: 'before_tool_call',
|
|
595
|
+
sessionId: session.id,
|
|
596
|
+
data: { toolName: tc.name, params: tc.input },
|
|
597
|
+
timestamp: Date.now(),
|
|
598
|
+
});
|
|
599
|
+
}
|
|
600
|
+
// Validate tool arguments before execution
|
|
601
|
+
const validator = getToolValidator();
|
|
602
|
+
if (validator && tc.input && typeof tc.input === 'object') {
|
|
603
|
+
const input = tc.input;
|
|
604
|
+
// Validate path arguments
|
|
605
|
+
if (typeof input.path === 'string') {
|
|
606
|
+
const pathCheck = validator.validatePath(input.path, toolCtx.workDir, ['write', 'edit', 'apply_patch'].includes(tc.name));
|
|
607
|
+
if (!pathCheck.allowed) {
|
|
608
|
+
const toolMsg = {
|
|
609
|
+
role: 'tool',
|
|
610
|
+
content: `Blocked: ${pathCheck.blockReason}`,
|
|
611
|
+
tool_call_id: tc.id,
|
|
612
|
+
};
|
|
613
|
+
session.messages.push(toolMsg);
|
|
614
|
+
messages.push(toolMsg);
|
|
615
|
+
continue;
|
|
616
|
+
}
|
|
617
|
+
}
|
|
618
|
+
// Validate command arguments
|
|
619
|
+
if (typeof input.command === 'string' && ['exec', 'process'].includes(tc.name)) {
|
|
620
|
+
const cmdCheck = validator.validateCommand(input.command);
|
|
621
|
+
if (!cmdCheck.allowed) {
|
|
622
|
+
const toolMsg = {
|
|
623
|
+
role: 'tool',
|
|
624
|
+
content: `Blocked: ${cmdCheck.blockReason}`,
|
|
625
|
+
tool_call_id: tc.id,
|
|
626
|
+
};
|
|
627
|
+
session.messages.push(toolMsg);
|
|
628
|
+
messages.push(toolMsg);
|
|
629
|
+
continue;
|
|
630
|
+
}
|
|
631
|
+
}
|
|
632
|
+
// Validate URL arguments
|
|
633
|
+
if (typeof input.url === 'string' && ['web_fetch', 'browser_navigate'].includes(tc.name)) {
|
|
634
|
+
const urlCheck = validator.validateUrl(input.url);
|
|
635
|
+
if (!urlCheck.allowed) {
|
|
636
|
+
const toolMsg = {
|
|
637
|
+
role: 'tool',
|
|
638
|
+
content: `Blocked: ${urlCheck.blockReason}`,
|
|
639
|
+
tool_call_id: tc.id,
|
|
640
|
+
};
|
|
641
|
+
session.messages.push(toolMsg);
|
|
642
|
+
messages.push(toolMsg);
|
|
643
|
+
continue;
|
|
644
|
+
}
|
|
645
|
+
}
|
|
646
|
+
}
|
|
647
|
+
const tool = toolRegistry.getTool(tc.name);
|
|
648
|
+
let result;
|
|
649
|
+
try {
|
|
650
|
+
if (tool) {
|
|
651
|
+
result = await tool.execute(tc.input, toolCtx);
|
|
652
|
+
}
|
|
653
|
+
else {
|
|
654
|
+
result = { output: `Unknown tool: ${tc.name}`, success: false };
|
|
655
|
+
}
|
|
656
|
+
}
|
|
657
|
+
catch (err) {
|
|
658
|
+
result = {
|
|
659
|
+
output: `Error executing ${tc.name}: ${err instanceof Error ? err.message : String(err)}`,
|
|
660
|
+
success: false,
|
|
661
|
+
error: err instanceof Error ? err.message : String(err),
|
|
662
|
+
};
|
|
663
|
+
}
|
|
664
|
+
if (hooks) {
|
|
665
|
+
await hooks.emit('after_tool_call', {
|
|
666
|
+
event: 'after_tool_call',
|
|
667
|
+
sessionId: session.id,
|
|
668
|
+
data: { toolName: tc.name, result },
|
|
669
|
+
timestamp: Date.now(),
|
|
670
|
+
});
|
|
671
|
+
}
|
|
672
|
+
const toolMsg = {
|
|
673
|
+
role: 'tool',
|
|
674
|
+
content: result.output,
|
|
675
|
+
tool_call_id: tc.id,
|
|
676
|
+
};
|
|
677
|
+
session.messages.push(toolMsg);
|
|
678
|
+
messages.push(toolMsg);
|
|
679
|
+
}
|
|
680
|
+
pendingToolCalls = [];
|
|
681
|
+
}
|
|
682
|
+
// Stop typing indicator
|
|
683
|
+
this.deps.typingManager?.stop(chatId);
|
|
684
|
+
// Transition reaction to completed
|
|
685
|
+
if (this.deps.reactionManager && this.deps.channel && messageId) {
|
|
686
|
+
await this.deps.reactionManager.transition(this.deps.channel, chatId, messageId, 'processing', 'completed');
|
|
687
|
+
}
|
|
688
|
+
// Clear tool loop history for this session turn
|
|
689
|
+
this.deps.toolLoopDetector?.clearSession(session.id);
|
|
690
|
+
if (hooks) {
|
|
691
|
+
await hooks.emit('agent_end', {
|
|
692
|
+
event: 'agent_end',
|
|
693
|
+
sessionId: session.id,
|
|
694
|
+
data: { turns },
|
|
695
|
+
timestamp: Date.now(),
|
|
696
|
+
});
|
|
697
|
+
}
|
|
698
|
+
}
|
|
699
|
+
}
|
|
700
|
+
//# sourceMappingURL=agent-loop.js.map
|