@roj-ai/sdk 0.1.3 → 0.1.4
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/dist/bootstrap.js +191 -0
- package/dist/bootstrap.js.map +1 -0
- package/dist/builtin-events.js +8 -0
- package/dist/builtin-events.js.map +1 -0
- package/dist/bun-platform/fs.js +39 -0
- package/dist/bun-platform/fs.js.map +1 -0
- package/dist/bun-platform/index.js +18 -0
- package/dist/bun-platform/index.js.map +1 -0
- package/dist/bun-platform/process.js +21 -0
- package/dist/bun-platform/process.js.map +1 -0
- package/dist/config.js +54 -0
- package/dist/config.js.map +1 -0
- package/dist/config.test.js +155 -0
- package/dist/config.test.js.map +1 -0
- package/dist/core/agent-loop.integration.test.js +414 -0
- package/dist/core/agent-loop.integration.test.js.map +1 -0
- package/dist/core/agents/agent-config.test.js +194 -0
- package/dist/core/agents/agent-config.test.js.map +1 -0
- package/dist/core/agents/agent-roles.js +25 -0
- package/dist/core/agents/agent-roles.js.map +1 -0
- package/dist/core/agents/agent-shutdown.test.js +180 -0
- package/dist/core/agents/agent-shutdown.test.js.map +1 -0
- package/dist/core/agents/agent.js +1205 -0
- package/dist/core/agents/agent.js.map +1 -0
- package/dist/core/agents/agent.test.js +313 -0
- package/dist/core/agents/agent.test.js.map +1 -0
- package/dist/core/agents/communicator.js +13 -0
- package/dist/core/agents/communicator.js.map +1 -0
- package/dist/core/agents/config.js +5 -0
- package/dist/core/agents/config.js.map +1 -0
- package/dist/core/agents/context.js +2 -0
- package/dist/core/agents/context.js.map +1 -0
- package/dist/core/agents/debounce.js +74 -0
- package/dist/core/agents/debounce.js.map +1 -0
- package/dist/core/agents/handler-events.test.js +115 -0
- package/dist/core/agents/handler-events.test.js.map +1 -0
- package/dist/core/agents/index.js +2 -0
- package/dist/core/agents/index.js.map +1 -0
- package/dist/core/agents/response-sanitizer.js +46 -0
- package/dist/core/agents/response-sanitizer.js.map +1 -0
- package/dist/core/agents/response-sanitizer.test.js +101 -0
- package/dist/core/agents/response-sanitizer.test.js.map +1 -0
- package/dist/core/agents/retry.js +105 -0
- package/dist/core/agents/retry.js.map +1 -0
- package/dist/core/agents/schema.js +39 -0
- package/dist/core/agents/schema.js.map +1 -0
- package/dist/core/agents/state.js +90 -0
- package/dist/core/agents/state.js.map +1 -0
- package/dist/core/context/state.js +23 -0
- package/dist/core/context/state.js.map +1 -0
- package/dist/core/errors.js +38 -0
- package/dist/core/errors.js.map +1 -0
- package/dist/core/event-sourcing.integration.test.js +154 -0
- package/dist/core/event-sourcing.integration.test.js.map +1 -0
- package/dist/core/events/base-event-store.js +201 -0
- package/dist/core/events/base-event-store.js.map +1 -0
- package/dist/core/events/event-store.js +26 -0
- package/dist/core/events/event-store.js.map +1 -0
- package/dist/core/events/file.js +320 -0
- package/dist/core/events/file.js.map +1 -0
- package/dist/core/events/file.test.js +284 -0
- package/dist/core/events/file.test.js.map +1 -0
- package/dist/core/events/index.js +3 -0
- package/dist/core/events/index.js.map +1 -0
- package/dist/core/events/memory.js +101 -0
- package/dist/core/events/memory.js.map +1 -0
- package/dist/core/events/memory.test.js +502 -0
- package/dist/core/events/memory.test.js.map +1 -0
- package/dist/core/events/metadata-utils.js +107 -0
- package/dist/core/events/metadata-utils.js.map +1 -0
- package/dist/core/events/test-helpers.js +15 -0
- package/dist/core/events/test-helpers.js.map +1 -0
- package/dist/core/events/types.js +21 -0
- package/dist/core/events/types.js.map +1 -0
- package/dist/core/file-store/file-store.js +250 -0
- package/dist/core/file-store/file-store.js.map +1 -0
- package/dist/core/file-store/types.js +7 -0
- package/dist/core/file-store/types.js.map +1 -0
- package/dist/core/image/image-processor.js +106 -0
- package/dist/core/image/image-processor.js.map +1 -0
- package/dist/core/image/image-processor.test.js +171 -0
- package/dist/core/image/image-processor.test.js.map +1 -0
- package/dist/core/image/index.js +4 -0
- package/dist/core/image/index.js.map +1 -0
- package/dist/core/image/noop-resizer.js +6 -0
- package/dist/core/image/noop-resizer.js.map +1 -0
- package/dist/core/image/types.js +2 -0
- package/dist/core/image/types.js.map +1 -0
- package/dist/core/image/vips-resizer.js +100 -0
- package/dist/core/image/vips-resizer.js.map +1 -0
- package/dist/core/image/vips-resizer.test.js +324 -0
- package/dist/core/image/vips-resizer.test.js.map +1 -0
- package/dist/core/llm/anthropic.js +396 -0
- package/dist/core/llm/anthropic.js.map +1 -0
- package/dist/core/llm/anthropic.test.js +434 -0
- package/dist/core/llm/anthropic.test.js.map +1 -0
- package/dist/core/llm/cache-breakpoints.js +37 -0
- package/dist/core/llm/cache-breakpoints.js.map +1 -0
- package/dist/core/llm/cache-live.test.js +137 -0
- package/dist/core/llm/cache-live.test.js.map +1 -0
- package/dist/core/llm/index.js +9 -0
- package/dist/core/llm/index.js.map +1 -0
- package/dist/core/llm/llm-log-types.js +12 -0
- package/dist/core/llm/llm-log-types.js.map +1 -0
- package/dist/core/llm/logger.js +241 -0
- package/dist/core/llm/logger.js.map +1 -0
- package/dist/core/llm/logger.test.js +228 -0
- package/dist/core/llm/logger.test.js.map +1 -0
- package/dist/core/llm/logging-provider.js +49 -0
- package/dist/core/llm/logging-provider.js.map +1 -0
- package/dist/core/llm/middleware.js +114 -0
- package/dist/core/llm/middleware.js.map +1 -0
- package/dist/core/llm/mock.js +186 -0
- package/dist/core/llm/mock.js.map +1 -0
- package/dist/core/llm/mock.test.js +318 -0
- package/dist/core/llm/mock.test.js.map +1 -0
- package/dist/core/llm/openrouter-mapping.test.js +125 -0
- package/dist/core/llm/openrouter-mapping.test.js.map +1 -0
- package/dist/core/llm/openrouter.js +298 -0
- package/dist/core/llm/openrouter.js.map +1 -0
- package/dist/core/llm/openrouter.test.js +377 -0
- package/dist/core/llm/openrouter.test.js.map +1 -0
- package/dist/core/llm/provider-integration.test.js +350 -0
- package/dist/core/llm/provider-integration.test.js.map +1 -0
- package/dist/core/llm/provider.js +18 -0
- package/dist/core/llm/provider.js.map +1 -0
- package/dist/core/llm/routing-provider.js +52 -0
- package/dist/core/llm/routing-provider.js.map +1 -0
- package/dist/core/llm/routing-provider.test.js +94 -0
- package/dist/core/llm/routing-provider.test.js.map +1 -0
- package/dist/core/llm/schema.js +31 -0
- package/dist/core/llm/schema.js.map +1 -0
- package/dist/core/llm/snapshot-fetch.js +122 -0
- package/dist/core/llm/snapshot-fetch.js.map +1 -0
- package/dist/core/llm/snapshot-middleware.js +142 -0
- package/dist/core/llm/snapshot-middleware.js.map +1 -0
- package/dist/core/llm/snapshot-middleware.test.js +144 -0
- package/dist/core/llm/snapshot-middleware.test.js.map +1 -0
- package/dist/core/llm/state.js +48 -0
- package/dist/core/llm/state.js.map +1 -0
- package/dist/core/llm/tokens.js +40 -0
- package/dist/core/llm/tokens.js.map +1 -0
- package/dist/core/multi-agent.integration.test.js +298 -0
- package/dist/core/multi-agent.integration.test.js.map +1 -0
- package/dist/core/plugin-hooks.integration.test.js +344 -0
- package/dist/core/plugin-hooks.integration.test.js.map +1 -0
- package/dist/core/plugins/hook-types.js +5 -0
- package/dist/core/plugins/hook-types.js.map +1 -0
- package/dist/core/plugins/index.js +5 -0
- package/dist/core/plugins/index.js.map +1 -0
- package/dist/core/plugins/plugin-builder.js +321 -0
- package/dist/core/plugins/plugin-builder.js.map +1 -0
- package/dist/core/preset/config.js +54 -0
- package/dist/core/preset/config.js.map +1 -0
- package/dist/core/preset/index.js +6 -0
- package/dist/core/preset/index.js.map +1 -0
- package/dist/core/preset/preset-builder.js +63 -0
- package/dist/core/preset/preset-builder.js.map +1 -0
- package/dist/core/session-lifecycle.integration.test.js +159 -0
- package/dist/core/session-lifecycle.integration.test.js.map +1 -0
- package/dist/core/sessions/apply-event.js +41 -0
- package/dist/core/sessions/apply-event.js.map +1 -0
- package/dist/core/sessions/context.js +2 -0
- package/dist/core/sessions/context.js.map +1 -0
- package/dist/core/sessions/fork-utils.js +42 -0
- package/dist/core/sessions/fork-utils.js.map +1 -0
- package/dist/core/sessions/fork-utils.test.js +129 -0
- package/dist/core/sessions/fork-utils.test.js.map +1 -0
- package/dist/core/sessions/reducer.js +55 -0
- package/dist/core/sessions/reducer.js.map +1 -0
- package/dist/core/sessions/schema.js +66 -0
- package/dist/core/sessions/schema.js.map +1 -0
- package/dist/core/sessions/session-environment.js +2 -0
- package/dist/core/sessions/session-environment.js.map +1 -0
- package/dist/core/sessions/session-manager.js +650 -0
- package/dist/core/sessions/session-manager.js.map +1 -0
- package/dist/core/sessions/session-store.js +118 -0
- package/dist/core/sessions/session-store.js.map +1 -0
- package/dist/core/sessions/session.js +675 -0
- package/dist/core/sessions/session.js.map +1 -0
- package/dist/core/sessions/session.test.js +1095 -0
- package/dist/core/sessions/session.test.js.map +1 -0
- package/dist/core/sessions/state.js +377 -0
- package/dist/core/sessions/state.js.map +1 -0
- package/dist/core/system.js +66 -0
- package/dist/core/system.js.map +1 -0
- package/dist/core/tools/context.js +2 -0
- package/dist/core/tools/context.js.map +1 -0
- package/dist/core/tools/definition.js +4 -0
- package/dist/core/tools/definition.js.map +1 -0
- package/dist/core/tools/executor.js +82 -0
- package/dist/core/tools/executor.js.map +1 -0
- package/dist/core/tools/executor.test.js +143 -0
- package/dist/core/tools/executor.test.js.map +1 -0
- package/dist/core/tools/index.js +4 -0
- package/dist/core/tools/index.js.map +1 -0
- package/dist/core/tools/schema.js +20 -0
- package/dist/core/tools/schema.js.map +1 -0
- package/dist/core/tools/state.js +29 -0
- package/dist/core/tools/state.js.map +1 -0
- package/dist/index.js +70 -0
- package/dist/index.js.map +1 -0
- package/dist/lib/json/index.js +5 -0
- package/dist/lib/json/index.js.map +1 -0
- package/dist/lib/logger/console.js +147 -0
- package/dist/lib/logger/console.js.map +1 -0
- package/dist/lib/logger/console.test.js +258 -0
- package/dist/lib/logger/console.test.js.map +1 -0
- package/dist/lib/logger/file.js +54 -0
- package/dist/lib/logger/file.js.map +1 -0
- package/dist/lib/logger/index.js +4 -0
- package/dist/lib/logger/index.js.map +1 -0
- package/dist/lib/logger/logger.js +28 -0
- package/dist/lib/logger/logger.js.map +1 -0
- package/dist/lib/logger/ring-buffer.js +61 -0
- package/dist/lib/logger/ring-buffer.js.map +1 -0
- package/dist/lib/logger/tee.js +43 -0
- package/dist/lib/logger/tee.js.map +1 -0
- package/dist/lib/mime.js +22 -0
- package/dist/lib/mime.js.map +1 -0
- package/dist/lib/never.js +4 -0
- package/dist/lib/never.js.map +1 -0
- package/dist/lib/utils/hash.js +35 -0
- package/dist/lib/utils/hash.js.map +1 -0
- package/dist/lib/utils/result.js +21 -0
- package/dist/lib/utils/result.js.map +1 -0
- package/dist/platform/fs.js +8 -0
- package/dist/platform/fs.js.map +1 -0
- package/dist/platform/index.js +9 -0
- package/dist/platform/index.js.map +1 -0
- package/dist/platform/process.js +8 -0
- package/dist/platform/process.js.map +1 -0
- package/dist/plugins/agent-status/plugin.js +77 -0
- package/dist/plugins/agent-status/plugin.js.map +1 -0
- package/dist/plugins/agents/agents.integration.test.js +683 -0
- package/dist/plugins/agents/agents.integration.test.js.map +1 -0
- package/dist/plugins/agents/index.js +2 -0
- package/dist/plugins/agents/index.js.map +1 -0
- package/dist/plugins/agents/plugin.js +199 -0
- package/dist/plugins/agents/plugin.js.map +1 -0
- package/dist/plugins/context-compact/context-compact.integration.test.js +174 -0
- package/dist/plugins/context-compact/context-compact.integration.test.js.map +1 -0
- package/dist/plugins/context-compact/context-compactor.js +238 -0
- package/dist/plugins/context-compact/context-compactor.js.map +1 -0
- package/dist/plugins/context-compact/context-compactor.test.js +763 -0
- package/dist/plugins/context-compact/context-compactor.test.js.map +1 -0
- package/dist/plugins/context-compact/history-offloader.js +42 -0
- package/dist/plugins/context-compact/history-offloader.js.map +1 -0
- package/dist/plugins/context-compact/history-offloader.test.js +77 -0
- package/dist/plugins/context-compact/history-offloader.test.js.map +1 -0
- package/dist/plugins/context-compact/index.js +4 -0
- package/dist/plugins/context-compact/index.js.map +1 -0
- package/dist/plugins/context-compact/plugin.js +37 -0
- package/dist/plugins/context-compact/plugin.js.map +1 -0
- package/dist/plugins/filesystem/filesystem.integration.test.js +411 -0
- package/dist/plugins/filesystem/filesystem.integration.test.js.map +1 -0
- package/dist/plugins/filesystem/helpers.js +170 -0
- package/dist/plugins/filesystem/helpers.js.map +1 -0
- package/dist/plugins/filesystem/index.js +3 -0
- package/dist/plugins/filesystem/index.js.map +1 -0
- package/dist/plugins/filesystem/listing.js +247 -0
- package/dist/plugins/filesystem/listing.js.map +1 -0
- package/dist/plugins/filesystem/plugin.js +364 -0
- package/dist/plugins/filesystem/plugin.js.map +1 -0
- package/dist/plugins/filesystem/schema.js +2 -0
- package/dist/plugins/filesystem/schema.js.map +1 -0
- package/dist/plugins/git-status/index.js +2 -0
- package/dist/plugins/git-status/index.js.map +1 -0
- package/dist/plugins/git-status/plugin.js +144 -0
- package/dist/plugins/git-status/plugin.js.map +1 -0
- package/dist/plugins/limits-guard/config.js +5 -0
- package/dist/plugins/limits-guard/config.js.map +1 -0
- package/dist/plugins/limits-guard/index.js +3 -0
- package/dist/plugins/limits-guard/index.js.map +1 -0
- package/dist/plugins/limits-guard/limit-guard.js +125 -0
- package/dist/plugins/limits-guard/limit-guard.js.map +1 -0
- package/dist/plugins/limits-guard/limit-guard.test.js +121 -0
- package/dist/plugins/limits-guard/limit-guard.test.js.map +1 -0
- package/dist/plugins/limits-guard/limits-guard.integration.test.js +378 -0
- package/dist/plugins/limits-guard/limits-guard.integration.test.js.map +1 -0
- package/dist/plugins/limits-guard/plugin.js +240 -0
- package/dist/plugins/limits-guard/plugin.js.map +1 -0
- package/dist/plugins/llm-debug/index.js +2 -0
- package/dist/plugins/llm-debug/index.js.map +1 -0
- package/dist/plugins/llm-debug/llm-debug.integration.test.js +157 -0
- package/dist/plugins/llm-debug/llm-debug.integration.test.js.map +1 -0
- package/dist/plugins/llm-debug/plugin.js +148 -0
- package/dist/plugins/llm-debug/plugin.js.map +1 -0
- package/dist/plugins/logs/index.js +2 -0
- package/dist/plugins/logs/index.js.map +1 -0
- package/dist/plugins/logs/plugin.js +38 -0
- package/dist/plugins/logs/plugin.js.map +1 -0
- package/dist/plugins/mailbox/helpers.js +66 -0
- package/dist/plugins/mailbox/helpers.js.map +1 -0
- package/dist/plugins/mailbox/index.js +9 -0
- package/dist/plugins/mailbox/index.js.map +1 -0
- package/dist/plugins/mailbox/mailbox.integration.test.js +605 -0
- package/dist/plugins/mailbox/mailbox.integration.test.js.map +1 -0
- package/dist/plugins/mailbox/plugin.js +204 -0
- package/dist/plugins/mailbox/plugin.js.map +1 -0
- package/dist/plugins/mailbox/prompts.js +93 -0
- package/dist/plugins/mailbox/prompts.js.map +1 -0
- package/dist/plugins/mailbox/query.js +38 -0
- package/dist/plugins/mailbox/query.js.map +1 -0
- package/dist/plugins/mailbox/schema.js +32 -0
- package/dist/plugins/mailbox/schema.js.map +1 -0
- package/dist/plugins/mailbox/state.js +41 -0
- package/dist/plugins/mailbox/state.js.map +1 -0
- package/dist/plugins/resources/index.js +4 -0
- package/dist/plugins/resources/index.js.map +1 -0
- package/dist/plugins/resources/manifest.js +20 -0
- package/dist/plugins/resources/manifest.js.map +1 -0
- package/dist/plugins/resources/plugin.js +171 -0
- package/dist/plugins/resources/plugin.js.map +1 -0
- package/dist/plugins/resources/post-inject.js +32 -0
- package/dist/plugins/resources/post-inject.js.map +1 -0
- package/dist/plugins/resources/state.js +16 -0
- package/dist/plugins/resources/state.js.map +1 -0
- package/dist/plugins/result-eviction/index.js +2 -0
- package/dist/plugins/result-eviction/index.js.map +1 -0
- package/dist/plugins/result-eviction/plugin.js +43 -0
- package/dist/plugins/result-eviction/plugin.js.map +1 -0
- package/dist/plugins/result-eviction/result-eviction.integration.test.js +217 -0
- package/dist/plugins/result-eviction/result-eviction.integration.test.js.map +1 -0
- package/dist/plugins/services/plugin.js +453 -0
- package/dist/plugins/services/plugin.js.map +1 -0
- package/dist/plugins/services/port-pool.js +70 -0
- package/dist/plugins/services/port-pool.js.map +1 -0
- package/dist/plugins/services/prompt.js +40 -0
- package/dist/plugins/services/prompt.js.map +1 -0
- package/dist/plugins/services/schema.js +9 -0
- package/dist/plugins/services/schema.js.map +1 -0
- package/dist/plugins/services/service.js +470 -0
- package/dist/plugins/services/service.js.map +1 -0
- package/dist/plugins/services/services.integration.test.js +485 -0
- package/dist/plugins/services/services.integration.test.js.map +1 -0
- package/dist/plugins/session-lifecycle/index.js +2 -0
- package/dist/plugins/session-lifecycle/index.js.map +1 -0
- package/dist/plugins/session-lifecycle/plugin.js +273 -0
- package/dist/plugins/session-lifecycle/plugin.js.map +1 -0
- package/dist/plugins/session-lifecycle/session-lifecycle.integration.test.js +498 -0
- package/dist/plugins/session-lifecycle/session-lifecycle.integration.test.js.map +1 -0
- package/dist/plugins/session-state/plugin.js +159 -0
- package/dist/plugins/session-state/plugin.js.map +1 -0
- package/dist/plugins/session-stats/index.js +3 -0
- package/dist/plugins/session-stats/index.js.map +1 -0
- package/dist/plugins/session-stats/plugin.js +81 -0
- package/dist/plugins/session-stats/plugin.js.map +1 -0
- package/dist/plugins/shell/executor.js +339 -0
- package/dist/plugins/shell/executor.js.map +1 -0
- package/dist/plugins/shell/index.js +6 -0
- package/dist/plugins/shell/index.js.map +1 -0
- package/dist/plugins/shell/plugin.js +66 -0
- package/dist/plugins/shell/plugin.js.map +1 -0
- package/dist/plugins/shell/shell.integration.test.js +234 -0
- package/dist/plugins/shell/shell.integration.test.js.map +1 -0
- package/dist/plugins/shell/shell.test.js +236 -0
- package/dist/plugins/shell/shell.test.js.map +1 -0
- package/dist/plugins/skills/discovery.js +205 -0
- package/dist/plugins/skills/discovery.js.map +1 -0
- package/dist/plugins/skills/discovery.test.js +312 -0
- package/dist/plugins/skills/discovery.test.js.map +1 -0
- package/dist/plugins/skills/index.js +12 -0
- package/dist/plugins/skills/index.js.map +1 -0
- package/dist/plugins/skills/plugin.js +293 -0
- package/dist/plugins/skills/plugin.js.map +1 -0
- package/dist/plugins/skills/prompts.js +70 -0
- package/dist/plugins/skills/prompts.js.map +1 -0
- package/dist/plugins/skills/schema.js +18 -0
- package/dist/plugins/skills/schema.js.map +1 -0
- package/dist/plugins/skills/skills.integration.test.js +475 -0
- package/dist/plugins/skills/skills.integration.test.js.map +1 -0
- package/dist/plugins/snapshotting/index.js +3 -0
- package/dist/plugins/snapshotting/index.js.map +1 -0
- package/dist/plugins/snapshotting/jj-snapshotter.js +106 -0
- package/dist/plugins/snapshotting/jj-snapshotter.js.map +1 -0
- package/dist/plugins/snapshotting/plugin.js +28 -0
- package/dist/plugins/snapshotting/plugin.js.map +1 -0
- package/dist/plugins/snapshotting/snapshotter.js +2 -0
- package/dist/plugins/snapshotting/snapshotter.js.map +1 -0
- package/dist/plugins/todo/index.js +7 -0
- package/dist/plugins/todo/index.js.map +1 -0
- package/dist/plugins/todo/plugin.js +319 -0
- package/dist/plugins/todo/plugin.js.map +1 -0
- package/dist/plugins/todo/prompts.js +54 -0
- package/dist/plugins/todo/prompts.js.map +1 -0
- package/dist/plugins/todo/schema.js +18 -0
- package/dist/plugins/todo/schema.js.map +1 -0
- package/dist/plugins/todo/todo.integration.test.js +605 -0
- package/dist/plugins/todo/todo.integration.test.js.map +1 -0
- package/dist/plugins/uploads/index.js +8 -0
- package/dist/plugins/uploads/index.js.map +1 -0
- package/dist/plugins/uploads/plugin.js +346 -0
- package/dist/plugins/uploads/plugin.js.map +1 -0
- package/dist/plugins/uploads/preprocessor.js +44 -0
- package/dist/plugins/uploads/preprocessor.js.map +1 -0
- package/dist/plugins/uploads/preprocessors/image-classifier.js +127 -0
- package/dist/plugins/uploads/preprocessors/image-classifier.js.map +1 -0
- package/dist/plugins/uploads/preprocessors/index.js +7 -0
- package/dist/plugins/uploads/preprocessors/index.js.map +1 -0
- package/dist/plugins/uploads/preprocessors/markitdown-preprocessor.js +204 -0
- package/dist/plugins/uploads/preprocessors/markitdown-preprocessor.js.map +1 -0
- package/dist/plugins/uploads/preprocessors/zip-preprocessor.js +172 -0
- package/dist/plugins/uploads/preprocessors/zip-preprocessor.js.map +1 -0
- package/dist/plugins/uploads/schema.js +20 -0
- package/dist/plugins/uploads/schema.js.map +1 -0
- package/dist/plugins/uploads/state.js +22 -0
- package/dist/plugins/uploads/state.js.map +1 -0
- package/dist/plugins/uploads/uploads.integration.test.js +496 -0
- package/dist/plugins/uploads/uploads.integration.test.js.map +1 -0
- package/dist/plugins/user-chat/index.js +5 -0
- package/dist/plugins/user-chat/index.js.map +1 -0
- package/dist/plugins/user-chat/plugin.js +544 -0
- package/dist/plugins/user-chat/plugin.js.map +1 -0
- package/dist/plugins/user-chat/prompts.js +29 -0
- package/dist/plugins/user-chat/prompts.js.map +1 -0
- package/dist/plugins/user-chat/schema.js +46 -0
- package/dist/plugins/user-chat/schema.js.map +1 -0
- package/dist/plugins/user-chat/user-chat.integration.test.js +668 -0
- package/dist/plugins/user-chat/user-chat.integration.test.js.map +1 -0
- package/dist/plugins/workers/context.js +143 -0
- package/dist/plugins/workers/context.js.map +1 -0
- package/dist/plugins/workers/definition.js +30 -0
- package/dist/plugins/workers/definition.js.map +1 -0
- package/dist/plugins/workers/index.js +7 -0
- package/dist/plugins/workers/index.js.map +1 -0
- package/dist/plugins/workers/plugin.js +578 -0
- package/dist/plugins/workers/plugin.js.map +1 -0
- package/dist/plugins/workers/worker.js +18 -0
- package/dist/plugins/workers/worker.js.map +1 -0
- package/dist/plugins/workers/workers.integration.test.js +629 -0
- package/dist/plugins/workers/workers.integration.test.js.map +1 -0
- package/dist/prompts/base.js +239 -0
- package/dist/prompts/base.js.map +1 -0
- package/dist/prompts/builder.js +131 -0
- package/dist/prompts/builder.js.map +1 -0
- package/dist/prompts/index.js +20 -0
- package/dist/prompts/index.js.map +1 -0
- package/dist/prompts/macros.js +26 -0
- package/dist/prompts/macros.js.map +1 -0
- package/dist/prompts/macros.test.js +80 -0
- package/dist/prompts/macros.test.js.map +1 -0
- package/dist/testing/bootstrap-for-testing.js +28 -0
- package/dist/testing/bootstrap-for-testing.js.map +1 -0
- package/dist/testing/index.js +7 -0
- package/dist/testing/index.js.map +1 -0
- package/dist/testing/node-platform.js +65 -0
- package/dist/testing/node-platform.js.map +1 -0
- package/dist/testing/notification-collector.js +82 -0
- package/dist/testing/notification-collector.js.map +1 -0
- package/dist/testing/preset-helpers.js +37 -0
- package/dist/testing/preset-helpers.js.map +1 -0
- package/dist/testing/test-harness.js +226 -0
- package/dist/testing/test-harness.js.map +1 -0
- package/dist/testing/test-harness.test.js +51 -0
- package/dist/testing/test-harness.test.js.map +1 -0
- package/dist/testing/wait-helpers.js +64 -0
- package/dist/testing/wait-helpers.js.map +1 -0
- package/dist/transport/adapter/client-adapter.js +64 -0
- package/dist/transport/adapter/client-adapter.js.map +1 -0
- package/dist/transport/adapter/index.js +24 -0
- package/dist/transport/adapter/index.js.map +1 -0
- package/dist/transport/adapter/server-adapter.js +73 -0
- package/dist/transport/adapter/server-adapter.js.map +1 -0
- package/dist/transport/adapter/types.js +8 -0
- package/dist/transport/adapter/types.js.map +1 -0
- package/dist/transport/http/app.js +86 -0
- package/dist/transport/http/app.js.map +1 -0
- package/dist/transport/http/index.js +6 -0
- package/dist/transport/http/index.js.map +1 -0
- package/dist/transport/http/middleware/bearer-auth.js +33 -0
- package/dist/transport/http/middleware/bearer-auth.js.map +1 -0
- package/dist/transport/http/middleware/error-handler.js +56 -0
- package/dist/transport/http/middleware/error-handler.js.map +1 -0
- package/dist/transport/http/routes/files.js +237 -0
- package/dist/transport/http/routes/files.js.map +1 -0
- package/dist/transport/http/routes/resources.js +77 -0
- package/dist/transport/http/routes/resources.js.map +1 -0
- package/dist/transport/http/routes/rpc.integration.test.js +189 -0
- package/dist/transport/http/routes/rpc.integration.test.js.map +1 -0
- package/dist/transport/http/routes/rpc.js +110 -0
- package/dist/transport/http/routes/rpc.js.map +1 -0
- package/dist/transport/http/routes/rpc.test.js +316 -0
- package/dist/transport/http/routes/rpc.test.js.map +1 -0
- package/dist/transport/http/routes/upload.js +205 -0
- package/dist/transport/http/routes/upload.js.map +1 -0
- package/dist/transport/rpc/index.js +7 -0
- package/dist/transport/rpc/index.js.map +1 -0
- package/dist/transport/rpc/methods.js +8 -0
- package/dist/transport/rpc/methods.js.map +1 -0
- package/dist/user-config.js +14 -0
- package/dist/user-config.js.map +1 -0
- package/package.json +47 -57
|
@@ -0,0 +1,629 @@
|
|
|
1
|
+
import { describe, expect, it } from 'bun:test';
|
|
2
|
+
import z from 'zod/v4';
|
|
3
|
+
import { MockLLMProvider } from '../../core/llm/mock.js';
|
|
4
|
+
import { selectPluginState } from '../../core/sessions/reducer.js';
|
|
5
|
+
import { ToolCallId } from '../../core/tools/schema.js';
|
|
6
|
+
import { Err, Ok } from '../../lib/utils/result.js';
|
|
7
|
+
import { createTestPreset, TestHarness } from '../../testing/index.js';
|
|
8
|
+
import { createWorkerDefinition, workerEvents, workerPlugin } from './index.js';
|
|
9
|
+
// ============================================================================
|
|
10
|
+
// Test Worker Definitions
|
|
11
|
+
// ============================================================================
|
|
12
|
+
/** A simple worker that completes immediately with a result. */
|
|
13
|
+
const immediateWorker = createWorkerDefinition('immediate', 'Completes immediately', z.object({ value: z.string() }), {
|
|
14
|
+
initialState: () => ({ count: 0 }),
|
|
15
|
+
reduce: (state, event) => {
|
|
16
|
+
if (event.type === 'increment')
|
|
17
|
+
return { count: state.count + 1 };
|
|
18
|
+
return state;
|
|
19
|
+
},
|
|
20
|
+
execute: async (config) => {
|
|
21
|
+
return Ok({
|
|
22
|
+
status: 'done',
|
|
23
|
+
summary: `Processed: ${config.value}`,
|
|
24
|
+
});
|
|
25
|
+
},
|
|
26
|
+
});
|
|
27
|
+
/** A worker that fails with an error. */
|
|
28
|
+
const failingWorker = createWorkerDefinition('failing', 'Always fails', z.object({}), {
|
|
29
|
+
initialState: () => ({}),
|
|
30
|
+
reduce: (state) => state,
|
|
31
|
+
execute: async () => {
|
|
32
|
+
return Err({ message: 'Worker error', resumable: true });
|
|
33
|
+
},
|
|
34
|
+
});
|
|
35
|
+
/** A worker that throws an exception. */
|
|
36
|
+
const throwingWorker = createWorkerDefinition('throwing', 'Throws exception', z.object({}), {
|
|
37
|
+
initialState: () => ({}),
|
|
38
|
+
reduce: (state) => state,
|
|
39
|
+
execute: async () => {
|
|
40
|
+
throw new Error('Unexpected crash');
|
|
41
|
+
},
|
|
42
|
+
});
|
|
43
|
+
/** A worker that emits sub-events before completing. */
|
|
44
|
+
const emittingWorker = createWorkerDefinition('emitting', 'Emits sub-events', z.object({}), {
|
|
45
|
+
initialState: () => ({ items: [] }),
|
|
46
|
+
reduce: (state, event) => {
|
|
47
|
+
if (event.type === 'item_added' && event.item) {
|
|
48
|
+
return { items: [...state.items, event.item] };
|
|
49
|
+
}
|
|
50
|
+
return state;
|
|
51
|
+
},
|
|
52
|
+
execute: async (_config, ctx) => {
|
|
53
|
+
await ctx.emit({ type: 'item_added', item: 'alpha' });
|
|
54
|
+
await ctx.emit({ type: 'item_added', item: 'beta' });
|
|
55
|
+
return Ok({ status: 'done', summary: 'Emitted 2 items' });
|
|
56
|
+
},
|
|
57
|
+
});
|
|
58
|
+
/** A deferred worker that waits for cancellation. */
|
|
59
|
+
function createDeferredWorker() {
|
|
60
|
+
let resolveWorker;
|
|
61
|
+
const started = new Promise((r) => {
|
|
62
|
+
resolveWorker = undefined; // placeholder
|
|
63
|
+
void r; // will be set below
|
|
64
|
+
});
|
|
65
|
+
let startedResolve;
|
|
66
|
+
const startedPromise = new Promise((r) => {
|
|
67
|
+
startedResolve = r;
|
|
68
|
+
});
|
|
69
|
+
const worker = createWorkerDefinition('deferred', 'Waits until cancelled or resolved', z.object({}), {
|
|
70
|
+
initialState: () => ({}),
|
|
71
|
+
reduce: (state) => state,
|
|
72
|
+
execute: async (_config, ctx) => {
|
|
73
|
+
startedResolve();
|
|
74
|
+
// Poll for cancellation
|
|
75
|
+
while (ctx.shouldContinue()) {
|
|
76
|
+
await new Promise((r) => setTimeout(r, 10));
|
|
77
|
+
}
|
|
78
|
+
return Ok({ status: 'cancelled', summary: 'Worker was cancelled' });
|
|
79
|
+
},
|
|
80
|
+
});
|
|
81
|
+
return { worker, started: startedPromise };
|
|
82
|
+
}
|
|
83
|
+
/** A worker that writes a file. */
|
|
84
|
+
const artifactWorker = createWorkerDefinition('artifact', 'Writes files', z.object({}), {
|
|
85
|
+
initialState: () => ({}),
|
|
86
|
+
reduce: (state) => state,
|
|
87
|
+
execute: async (_config, ctx) => {
|
|
88
|
+
await ctx.files.write('output.html', '<h1>Hello</h1>');
|
|
89
|
+
return Ok({ status: 'done', summary: 'Wrote file' });
|
|
90
|
+
},
|
|
91
|
+
});
|
|
92
|
+
/** A worker that notifies the agent. */
|
|
93
|
+
const notifyingWorker = createWorkerDefinition('notifying', 'Notifies agent', z.object({}), {
|
|
94
|
+
initialState: () => ({}),
|
|
95
|
+
reduce: (state) => state,
|
|
96
|
+
execute: async (_config, ctx) => {
|
|
97
|
+
await ctx.notifyAgent('Progress update: 50%');
|
|
98
|
+
return Ok({ status: 'done', summary: 'Notified agent' });
|
|
99
|
+
},
|
|
100
|
+
});
|
|
101
|
+
/** A worker with command support. */
|
|
102
|
+
const commandWorker = createWorkerDefinition('commandable', 'Supports commands', z.object({}), {
|
|
103
|
+
commands: {
|
|
104
|
+
update_config: {
|
|
105
|
+
description: 'Update config',
|
|
106
|
+
schema: z.object({ key: z.string() }),
|
|
107
|
+
},
|
|
108
|
+
},
|
|
109
|
+
initialState: () => ({ commandsReceived: 0 }),
|
|
110
|
+
reduce: (state, event) => {
|
|
111
|
+
if (event.type === 'command_received')
|
|
112
|
+
return { commandsReceived: state.commandsReceived + 1 };
|
|
113
|
+
return state;
|
|
114
|
+
},
|
|
115
|
+
execute: async (_config, ctx) => {
|
|
116
|
+
// Wait a bit for commands to arrive
|
|
117
|
+
while (ctx.shouldContinue()) {
|
|
118
|
+
await new Promise((r) => setTimeout(r, 10));
|
|
119
|
+
}
|
|
120
|
+
return Ok({ status: 'done', summary: 'Done' });
|
|
121
|
+
},
|
|
122
|
+
handleCommand: async (cmd, ctx) => {
|
|
123
|
+
await ctx.emit({ type: 'command_received' });
|
|
124
|
+
return Ok(`Command ${cmd.command} handled`);
|
|
125
|
+
},
|
|
126
|
+
});
|
|
127
|
+
// ============================================================================
|
|
128
|
+
// Helpers
|
|
129
|
+
// ============================================================================
|
|
130
|
+
const allWorkers = [immediateWorker, failingWorker, throwingWorker, emittingWorker, artifactWorker, notifyingWorker, commandWorker];
|
|
131
|
+
function createWorkersPreset(overrides) {
|
|
132
|
+
return createTestPreset({
|
|
133
|
+
...overrides,
|
|
134
|
+
plugins: [
|
|
135
|
+
workerPlugin.configure({ workers: allWorkers }),
|
|
136
|
+
...(overrides?.plugins ?? []),
|
|
137
|
+
],
|
|
138
|
+
});
|
|
139
|
+
}
|
|
140
|
+
function createWorkersHarness(options) {
|
|
141
|
+
return new TestHarness({ ...options, systemPlugins: [workerPlugin] });
|
|
142
|
+
}
|
|
143
|
+
// ============================================================================
|
|
144
|
+
// Tests
|
|
145
|
+
// ============================================================================
|
|
146
|
+
describe('workers plugin', () => {
|
|
147
|
+
// =========================================================================
|
|
148
|
+
// Worker spawning
|
|
149
|
+
// =========================================================================
|
|
150
|
+
describe('worker spawning', () => {
|
|
151
|
+
it('agent calls worker_immediate_start → worker_started event → worker in state', async () => {
|
|
152
|
+
const harness = createWorkersHarness({
|
|
153
|
+
presets: [createWorkersPreset()],
|
|
154
|
+
llmProvider: MockLLMProvider.withSequence([
|
|
155
|
+
{
|
|
156
|
+
toolCalls: [{
|
|
157
|
+
id: ToolCallId('tc1'),
|
|
158
|
+
name: 'worker_immediate_start',
|
|
159
|
+
input: { value: 'test-data' },
|
|
160
|
+
}],
|
|
161
|
+
},
|
|
162
|
+
{ content: 'Done', toolCalls: [] },
|
|
163
|
+
]),
|
|
164
|
+
});
|
|
165
|
+
const session = await harness.createSession('test');
|
|
166
|
+
await session.sendAndWaitForIdle('Start worker');
|
|
167
|
+
const startedEvents = await session.getEventsByType(workerEvents, 'worker_started');
|
|
168
|
+
expect(startedEvents).toHaveLength(1);
|
|
169
|
+
expect(startedEvents[0].workerType).toBe('immediate');
|
|
170
|
+
expect(startedEvents[0].config).toEqual({ value: 'test-data' });
|
|
171
|
+
await harness.shutdown();
|
|
172
|
+
});
|
|
173
|
+
it('spawn non-existent worker type → error returned to LLM', async () => {
|
|
174
|
+
const harness = createWorkersHarness({
|
|
175
|
+
presets: [createWorkersPreset()],
|
|
176
|
+
mockHandler: (request) => {
|
|
177
|
+
const callHistory = harness.llmProvider.getCallHistory();
|
|
178
|
+
if (callHistory.length === 0) {
|
|
179
|
+
return {
|
|
180
|
+
content: null,
|
|
181
|
+
toolCalls: [{
|
|
182
|
+
id: ToolCallId('tc1'),
|
|
183
|
+
name: 'worker_immediate_start',
|
|
184
|
+
input: { value: 'test' },
|
|
185
|
+
}],
|
|
186
|
+
finishReason: 'stop',
|
|
187
|
+
metrics: MockLLMProvider.defaultMetrics(),
|
|
188
|
+
};
|
|
189
|
+
}
|
|
190
|
+
return { content: 'Done', toolCalls: [], finishReason: 'stop', metrics: MockLLMProvider.defaultMetrics() };
|
|
191
|
+
},
|
|
192
|
+
});
|
|
193
|
+
// Use a preset with no workers configured to test spawn via direct method
|
|
194
|
+
const harnessNoWorkers = createWorkersHarness({
|
|
195
|
+
presets: [createTestPreset({
|
|
196
|
+
plugins: [workerPlugin.configure({ workers: [] })],
|
|
197
|
+
})],
|
|
198
|
+
llmProvider: MockLLMProvider.withFixedResponse({ content: 'Ok', toolCalls: [] }),
|
|
199
|
+
});
|
|
200
|
+
const session = await harnessNoWorkers.createSession('test');
|
|
201
|
+
await session.sendAndWaitForIdle('Hi');
|
|
202
|
+
const entryAgentId = session.getEntryAgentId();
|
|
203
|
+
const result = await session.callPluginMethod('workers.spawn', {
|
|
204
|
+
sessionId: String(session.sessionId),
|
|
205
|
+
agentId: String(entryAgentId),
|
|
206
|
+
workerType: 'nonexistent',
|
|
207
|
+
config: {},
|
|
208
|
+
});
|
|
209
|
+
expect(result.ok).toBe(false);
|
|
210
|
+
await harnessNoWorkers.shutdown();
|
|
211
|
+
});
|
|
212
|
+
it('spawn with invalid config → validation error', async () => {
|
|
213
|
+
const harness = createWorkersHarness({
|
|
214
|
+
presets: [createWorkersPreset()],
|
|
215
|
+
llmProvider: MockLLMProvider.withFixedResponse({ content: 'Ok', toolCalls: [] }),
|
|
216
|
+
});
|
|
217
|
+
const session = await harness.createSession('test');
|
|
218
|
+
await session.sendAndWaitForIdle('Hi');
|
|
219
|
+
const entryAgentId = session.getEntryAgentId();
|
|
220
|
+
const result = await session.callPluginMethod('workers.spawn', {
|
|
221
|
+
sessionId: String(session.sessionId),
|
|
222
|
+
agentId: String(entryAgentId),
|
|
223
|
+
workerType: 'immediate',
|
|
224
|
+
config: { wrong_field: 123 },
|
|
225
|
+
});
|
|
226
|
+
expect(result.ok).toBe(false);
|
|
227
|
+
await harness.shutdown();
|
|
228
|
+
});
|
|
229
|
+
});
|
|
230
|
+
// =========================================================================
|
|
231
|
+
// Worker completion and failure
|
|
232
|
+
// =========================================================================
|
|
233
|
+
describe('worker completion and failure', () => {
|
|
234
|
+
it('worker returns Ok → worker_completed event → status completed', async () => {
|
|
235
|
+
const harness = createWorkersHarness({
|
|
236
|
+
presets: [createWorkersPreset()],
|
|
237
|
+
llmProvider: MockLLMProvider.withSequence([
|
|
238
|
+
{
|
|
239
|
+
toolCalls: [{
|
|
240
|
+
id: ToolCallId('tc1'),
|
|
241
|
+
name: 'worker_immediate_start',
|
|
242
|
+
input: { value: 'hello' },
|
|
243
|
+
}],
|
|
244
|
+
},
|
|
245
|
+
{ content: 'Done', toolCalls: [] },
|
|
246
|
+
]),
|
|
247
|
+
});
|
|
248
|
+
const session = await harness.createSession('test');
|
|
249
|
+
await session.sendAndWaitForIdle('Start worker');
|
|
250
|
+
// Wait briefly for async worker completion
|
|
251
|
+
await new Promise((r) => setTimeout(r, 100));
|
|
252
|
+
const completedEvents = await session.getEventsByType(workerEvents, 'worker_completed');
|
|
253
|
+
expect(completedEvents).toHaveLength(1);
|
|
254
|
+
expect(completedEvents[0].result.summary).toBe('Processed: hello');
|
|
255
|
+
// Verify state
|
|
256
|
+
const workers = selectPluginState(session.state, 'workers');
|
|
257
|
+
expect(workers.size).toBe(1);
|
|
258
|
+
const worker = Array.from(workers.values())[0];
|
|
259
|
+
expect(worker.status).toBe('completed');
|
|
260
|
+
await harness.shutdown();
|
|
261
|
+
});
|
|
262
|
+
it('worker returns Err → worker_failed event → status failed, resumable flag', async () => {
|
|
263
|
+
const harness = createWorkersHarness({
|
|
264
|
+
presets: [createWorkersPreset()],
|
|
265
|
+
llmProvider: MockLLMProvider.withSequence([
|
|
266
|
+
{
|
|
267
|
+
toolCalls: [{
|
|
268
|
+
id: ToolCallId('tc1'),
|
|
269
|
+
name: 'worker_failing_start',
|
|
270
|
+
input: {},
|
|
271
|
+
}],
|
|
272
|
+
},
|
|
273
|
+
{ content: 'Done', toolCalls: [] },
|
|
274
|
+
]),
|
|
275
|
+
});
|
|
276
|
+
const session = await harness.createSession('test');
|
|
277
|
+
await session.sendAndWaitForIdle('Start worker');
|
|
278
|
+
await new Promise((r) => setTimeout(r, 100));
|
|
279
|
+
const failedEvents = await session.getEventsByType(workerEvents, 'worker_failed');
|
|
280
|
+
expect(failedEvents).toHaveLength(1);
|
|
281
|
+
expect(failedEvents[0].error).toBe('Worker error');
|
|
282
|
+
expect(failedEvents[0].resumable).toBe(true);
|
|
283
|
+
const workers = selectPluginState(session.state, 'workers');
|
|
284
|
+
const worker = Array.from(workers.values())[0];
|
|
285
|
+
expect(worker.status).toBe('failed');
|
|
286
|
+
await harness.shutdown();
|
|
287
|
+
});
|
|
288
|
+
it('worker throws exception → worker_failed event, resumable: false', async () => {
|
|
289
|
+
const harness = createWorkersHarness({
|
|
290
|
+
presets: [createWorkersPreset()],
|
|
291
|
+
llmProvider: MockLLMProvider.withSequence([
|
|
292
|
+
{
|
|
293
|
+
toolCalls: [{
|
|
294
|
+
id: ToolCallId('tc1'),
|
|
295
|
+
name: 'worker_throwing_start',
|
|
296
|
+
input: {},
|
|
297
|
+
}],
|
|
298
|
+
},
|
|
299
|
+
{ content: 'Done', toolCalls: [] },
|
|
300
|
+
]),
|
|
301
|
+
});
|
|
302
|
+
const session = await harness.createSession('test');
|
|
303
|
+
await session.sendAndWaitForIdle('Start worker');
|
|
304
|
+
await new Promise((r) => setTimeout(r, 100));
|
|
305
|
+
const failedEvents = await session.getEventsByType(workerEvents, 'worker_failed');
|
|
306
|
+
expect(failedEvents).toHaveLength(1);
|
|
307
|
+
expect(failedEvents[0].error).toBe('Unexpected crash');
|
|
308
|
+
expect(failedEvents[0].resumable).toBe(false);
|
|
309
|
+
await harness.shutdown();
|
|
310
|
+
});
|
|
311
|
+
});
|
|
312
|
+
// =========================================================================
|
|
313
|
+
// Worker sub-events and state reduction
|
|
314
|
+
// =========================================================================
|
|
315
|
+
describe('worker sub-events and state reduction', () => {
|
|
316
|
+
it('worker emits sub-events → worker_sub_event events → state updated via reducer', async () => {
|
|
317
|
+
const harness = createWorkersHarness({
|
|
318
|
+
presets: [createWorkersPreset()],
|
|
319
|
+
llmProvider: MockLLMProvider.withSequence([
|
|
320
|
+
{
|
|
321
|
+
toolCalls: [{
|
|
322
|
+
id: ToolCallId('tc1'),
|
|
323
|
+
name: 'worker_emitting_start',
|
|
324
|
+
input: {},
|
|
325
|
+
}],
|
|
326
|
+
},
|
|
327
|
+
{ content: 'Done', toolCalls: [] },
|
|
328
|
+
]),
|
|
329
|
+
});
|
|
330
|
+
const session = await harness.createSession('test');
|
|
331
|
+
await session.sendAndWaitForIdle('Start worker');
|
|
332
|
+
await new Promise((r) => setTimeout(r, 100));
|
|
333
|
+
const subEvents = await session.getEventsByType(workerEvents, 'worker_sub_event');
|
|
334
|
+
expect(subEvents).toHaveLength(2);
|
|
335
|
+
expect(subEvents[0].subEvent.type).toBe('item_added');
|
|
336
|
+
expect(subEvents[0].subEvent.item).toBe('alpha');
|
|
337
|
+
expect(subEvents[1].subEvent.item).toBe('beta');
|
|
338
|
+
// Verify worker state was updated by reducer
|
|
339
|
+
const workers = selectPluginState(session.state, 'workers');
|
|
340
|
+
const worker = Array.from(workers.values())[0];
|
|
341
|
+
const state = worker.state;
|
|
342
|
+
expect(state.items).toEqual(['alpha', 'beta']);
|
|
343
|
+
await harness.shutdown();
|
|
344
|
+
});
|
|
345
|
+
});
|
|
346
|
+
// =========================================================================
|
|
347
|
+
// Worker control (pause/resume/cancel)
|
|
348
|
+
// =========================================================================
|
|
349
|
+
describe('worker control', () => {
|
|
350
|
+
it('cancel running worker → status cancelled, shouldContinue returns false', async () => {
|
|
351
|
+
const { worker: deferred, started } = createDeferredWorker();
|
|
352
|
+
const harness = createWorkersHarness({
|
|
353
|
+
presets: [createTestPreset({
|
|
354
|
+
plugins: [workerPlugin.configure({ workers: [deferred] })],
|
|
355
|
+
})],
|
|
356
|
+
llmProvider: MockLLMProvider.withSequence([
|
|
357
|
+
{
|
|
358
|
+
toolCalls: [{
|
|
359
|
+
id: ToolCallId('tc1'),
|
|
360
|
+
name: 'worker_deferred_start',
|
|
361
|
+
input: {},
|
|
362
|
+
}],
|
|
363
|
+
},
|
|
364
|
+
{ content: 'Done', toolCalls: [] },
|
|
365
|
+
]),
|
|
366
|
+
});
|
|
367
|
+
const session = await harness.createSession('test');
|
|
368
|
+
await session.sendAndWaitForIdle('Start worker');
|
|
369
|
+
// Wait for worker to start executing
|
|
370
|
+
await started;
|
|
371
|
+
// Get worker ID from state
|
|
372
|
+
const workers = selectPluginState(session.state, 'workers');
|
|
373
|
+
const workerId = Array.from(workers.keys())[0];
|
|
374
|
+
// Cancel the worker
|
|
375
|
+
const entryAgentId = session.getEntryAgentId();
|
|
376
|
+
const result = await session.callPluginMethod('workers.cancel', {
|
|
377
|
+
sessionId: String(session.sessionId),
|
|
378
|
+
agentId: String(entryAgentId),
|
|
379
|
+
workerId: String(workerId),
|
|
380
|
+
});
|
|
381
|
+
expect(result.ok).toBe(true);
|
|
382
|
+
// Wait for worker to finish
|
|
383
|
+
await new Promise((r) => setTimeout(r, 200));
|
|
384
|
+
const statusEvents = await session.getEventsByType(workerEvents, 'worker_status_changed');
|
|
385
|
+
const cancelEvent = statusEvents.find((e) => e.toStatus === 'cancelled');
|
|
386
|
+
expect(cancelEvent).toBeDefined();
|
|
387
|
+
await harness.shutdown();
|
|
388
|
+
});
|
|
389
|
+
it('pause running worker → status paused, resume → status running', async () => {
|
|
390
|
+
const { worker: deferred, started } = createDeferredWorker();
|
|
391
|
+
const harness = createWorkersHarness({
|
|
392
|
+
presets: [createTestPreset({
|
|
393
|
+
plugins: [workerPlugin.configure({ workers: [deferred] })],
|
|
394
|
+
})],
|
|
395
|
+
llmProvider: MockLLMProvider.withSequence([
|
|
396
|
+
{
|
|
397
|
+
toolCalls: [{
|
|
398
|
+
id: ToolCallId('tc1'),
|
|
399
|
+
name: 'worker_deferred_start',
|
|
400
|
+
input: {},
|
|
401
|
+
}],
|
|
402
|
+
},
|
|
403
|
+
{ content: 'Done', toolCalls: [] },
|
|
404
|
+
]),
|
|
405
|
+
});
|
|
406
|
+
const session = await harness.createSession('test');
|
|
407
|
+
await session.sendAndWaitForIdle('Start worker');
|
|
408
|
+
await started;
|
|
409
|
+
const workers = selectPluginState(session.state, 'workers');
|
|
410
|
+
const workerId = Array.from(workers.keys())[0];
|
|
411
|
+
const entryAgentId = session.getEntryAgentId();
|
|
412
|
+
// Pause
|
|
413
|
+
const pauseResult = await session.callPluginMethod('workers.pause', {
|
|
414
|
+
sessionId: String(session.sessionId),
|
|
415
|
+
agentId: String(entryAgentId),
|
|
416
|
+
workerId: String(workerId),
|
|
417
|
+
});
|
|
418
|
+
expect(pauseResult.ok).toBe(true);
|
|
419
|
+
let statusEvents = await session.getEventsByType(workerEvents, 'worker_status_changed');
|
|
420
|
+
expect(statusEvents.some((e) => e.toStatus === 'paused')).toBe(true);
|
|
421
|
+
// Resume
|
|
422
|
+
const resumeResult = await session.callPluginMethod('workers.resume', {
|
|
423
|
+
sessionId: String(session.sessionId),
|
|
424
|
+
agentId: String(entryAgentId),
|
|
425
|
+
workerId: String(workerId),
|
|
426
|
+
});
|
|
427
|
+
expect(resumeResult.ok).toBe(true);
|
|
428
|
+
statusEvents = await session.getEventsByType(workerEvents, 'worker_status_changed');
|
|
429
|
+
const resumed = statusEvents.find((e) => e.fromStatus === 'paused' && e.toStatus === 'running');
|
|
430
|
+
expect(resumed).toBeDefined();
|
|
431
|
+
await harness.shutdown();
|
|
432
|
+
});
|
|
433
|
+
it('pause non-running worker → error', async () => {
|
|
434
|
+
const harness = createWorkersHarness({
|
|
435
|
+
presets: [createWorkersPreset()],
|
|
436
|
+
llmProvider: MockLLMProvider.withSequence([
|
|
437
|
+
{
|
|
438
|
+
toolCalls: [{
|
|
439
|
+
id: ToolCallId('tc1'),
|
|
440
|
+
name: 'worker_immediate_start',
|
|
441
|
+
input: { value: 'x' },
|
|
442
|
+
}],
|
|
443
|
+
},
|
|
444
|
+
{ content: 'Done', toolCalls: [] },
|
|
445
|
+
]),
|
|
446
|
+
});
|
|
447
|
+
const session = await harness.createSession('test');
|
|
448
|
+
await session.sendAndWaitForIdle('Start worker');
|
|
449
|
+
await new Promise((r) => setTimeout(r, 100));
|
|
450
|
+
// Worker already completed - pause should fail
|
|
451
|
+
const workers = selectPluginState(session.state, 'workers');
|
|
452
|
+
const workerId = Array.from(workers.keys())[0];
|
|
453
|
+
const entryAgentId = session.getEntryAgentId();
|
|
454
|
+
const result = await session.callPluginMethod('workers.pause', {
|
|
455
|
+
sessionId: String(session.sessionId),
|
|
456
|
+
agentId: String(entryAgentId),
|
|
457
|
+
workerId: String(workerId),
|
|
458
|
+
});
|
|
459
|
+
expect(result.ok).toBe(false);
|
|
460
|
+
await harness.shutdown();
|
|
461
|
+
});
|
|
462
|
+
});
|
|
463
|
+
// =========================================================================
|
|
464
|
+
// Worker commands
|
|
465
|
+
// =========================================================================
|
|
466
|
+
describe('worker commands', () => {
|
|
467
|
+
it('worker with commands → generates command tool', async () => {
|
|
468
|
+
const harness = createWorkersHarness({
|
|
469
|
+
presets: [createTestPreset({
|
|
470
|
+
plugins: [workerPlugin.configure({ workers: [commandWorker] })],
|
|
471
|
+
})],
|
|
472
|
+
llmProvider: MockLLMProvider.withFixedResponse({ content: 'Ok', toolCalls: [] }),
|
|
473
|
+
});
|
|
474
|
+
const session = await harness.createSession('test');
|
|
475
|
+
await session.sendAndWaitForIdle('Hi');
|
|
476
|
+
const lastRequest = harness.llmProvider.getLastRequest();
|
|
477
|
+
const toolNames = lastRequest?.tools?.map((t) => t.name) ?? [];
|
|
478
|
+
expect(toolNames).toContain('worker_commandable_start');
|
|
479
|
+
expect(toolNames).toContain('worker_commandable_update_config');
|
|
480
|
+
await harness.shutdown();
|
|
481
|
+
});
|
|
482
|
+
});
|
|
483
|
+
// =========================================================================
|
|
484
|
+
// Concurrent worker limit
|
|
485
|
+
// =========================================================================
|
|
486
|
+
describe('concurrent worker limit', () => {
|
|
487
|
+
it('spawning more than 10 workers → 11th fails with max reached', async () => {
|
|
488
|
+
// Create 11 deferred workers with different types
|
|
489
|
+
const deferredWorkers = Array.from({ length: 11 }, (_, i) => {
|
|
490
|
+
const { worker } = createDeferredWorker();
|
|
491
|
+
return createWorkerDefinition(`deferred_${i}`, `Deferred worker ${i}`, z.object({}), {
|
|
492
|
+
initialState: () => ({}),
|
|
493
|
+
reduce: (state) => state,
|
|
494
|
+
execute: async (_config, ctx) => {
|
|
495
|
+
while (ctx.shouldContinue()) {
|
|
496
|
+
await new Promise((r) => setTimeout(r, 10));
|
|
497
|
+
}
|
|
498
|
+
return Ok({ status: 'done', summary: 'Done' });
|
|
499
|
+
},
|
|
500
|
+
});
|
|
501
|
+
});
|
|
502
|
+
const harness = createWorkersHarness({
|
|
503
|
+
presets: [createTestPreset({
|
|
504
|
+
plugins: [workerPlugin.configure({ workers: deferredWorkers })],
|
|
505
|
+
})],
|
|
506
|
+
llmProvider: MockLLMProvider.withFixedResponse({ content: 'Ok', toolCalls: [] }),
|
|
507
|
+
});
|
|
508
|
+
const session = await harness.createSession('test');
|
|
509
|
+
await session.sendAndWaitForIdle('Hi');
|
|
510
|
+
const entryAgentId = session.getEntryAgentId();
|
|
511
|
+
// Spawn 10 workers
|
|
512
|
+
for (let i = 0; i < 10; i++) {
|
|
513
|
+
const result = await session.callPluginMethod('workers.spawn', {
|
|
514
|
+
sessionId: String(session.sessionId),
|
|
515
|
+
agentId: String(entryAgentId),
|
|
516
|
+
workerType: `deferred_${i}`,
|
|
517
|
+
config: {},
|
|
518
|
+
});
|
|
519
|
+
expect(result.ok).toBe(true);
|
|
520
|
+
}
|
|
521
|
+
// 11th should fail
|
|
522
|
+
const result = await session.callPluginMethod('workers.spawn', {
|
|
523
|
+
sessionId: String(session.sessionId),
|
|
524
|
+
agentId: String(entryAgentId),
|
|
525
|
+
workerType: 'deferred_10',
|
|
526
|
+
config: {},
|
|
527
|
+
});
|
|
528
|
+
expect(result.ok).toBe(false);
|
|
529
|
+
await harness.shutdown();
|
|
530
|
+
});
|
|
531
|
+
});
|
|
532
|
+
// =========================================================================
|
|
533
|
+
// Session close cleanup
|
|
534
|
+
// =========================================================================
|
|
535
|
+
describe('session close cleanup', () => {
|
|
536
|
+
it('closing session cancels running workers', async () => {
|
|
537
|
+
const { worker: deferred, started } = createDeferredWorker();
|
|
538
|
+
const harness = createWorkersHarness({
|
|
539
|
+
presets: [createTestPreset({
|
|
540
|
+
plugins: [workerPlugin.configure({ workers: [deferred] })],
|
|
541
|
+
})],
|
|
542
|
+
llmProvider: MockLLMProvider.withSequence([
|
|
543
|
+
{
|
|
544
|
+
toolCalls: [{
|
|
545
|
+
id: ToolCallId('tc1'),
|
|
546
|
+
name: 'worker_deferred_start',
|
|
547
|
+
input: {},
|
|
548
|
+
}],
|
|
549
|
+
},
|
|
550
|
+
{ content: 'Done', toolCalls: [] },
|
|
551
|
+
]),
|
|
552
|
+
});
|
|
553
|
+
const session = await harness.createSession('test');
|
|
554
|
+
await session.sendAndWaitForIdle('Start worker');
|
|
555
|
+
await started;
|
|
556
|
+
// Verify worker is running
|
|
557
|
+
const workers = selectPluginState(session.state, 'workers');
|
|
558
|
+
expect(workers.size).toBe(1);
|
|
559
|
+
const worker = Array.from(workers.values())[0];
|
|
560
|
+
expect(worker.status).toBe('running');
|
|
561
|
+
// Close session → should cancel workers
|
|
562
|
+
await session.close();
|
|
563
|
+
await new Promise((r) => setTimeout(r, 200));
|
|
564
|
+
await harness.shutdown();
|
|
565
|
+
});
|
|
566
|
+
});
|
|
567
|
+
// =========================================================================
|
|
568
|
+
// Worker artifacts
|
|
569
|
+
// =========================================================================
|
|
570
|
+
describe('worker file writing', () => {
|
|
571
|
+
it('worker writes file via files store → worker completes successfully', async () => {
|
|
572
|
+
const harness = createWorkersHarness({
|
|
573
|
+
presets: [createWorkersPreset()],
|
|
574
|
+
llmProvider: MockLLMProvider.withSequence([
|
|
575
|
+
{
|
|
576
|
+
toolCalls: [{
|
|
577
|
+
id: ToolCallId('tc1'),
|
|
578
|
+
name: 'worker_artifact_start',
|
|
579
|
+
input: {},
|
|
580
|
+
}],
|
|
581
|
+
},
|
|
582
|
+
{ content: 'Done', toolCalls: [] },
|
|
583
|
+
]),
|
|
584
|
+
});
|
|
585
|
+
const session = await harness.createSession('test');
|
|
586
|
+
await session.sendAndWaitForIdle('Start worker');
|
|
587
|
+
await new Promise((r) => setTimeout(r, 200));
|
|
588
|
+
const completedEvents = await session.getEventsByType(workerEvents, 'worker_completed');
|
|
589
|
+
expect(completedEvents).toHaveLength(1);
|
|
590
|
+
expect(completedEvents[0].result.summary).toBe('Wrote file');
|
|
591
|
+
const workers = selectPluginState(session.state, 'workers');
|
|
592
|
+
const worker = Array.from(workers.values())[0];
|
|
593
|
+
expect(worker.status).toBe('completed');
|
|
594
|
+
await harness.shutdown();
|
|
595
|
+
});
|
|
596
|
+
});
|
|
597
|
+
// =========================================================================
|
|
598
|
+
// Worker agent notification
|
|
599
|
+
// =========================================================================
|
|
600
|
+
describe('worker agent notification', () => {
|
|
601
|
+
it('worker calls notifyAgent → mailbox message emitted', async () => {
|
|
602
|
+
const harness = createWorkersHarness({
|
|
603
|
+
presets: [createWorkersPreset()],
|
|
604
|
+
llmProvider: MockLLMProvider.withSequence([
|
|
605
|
+
{
|
|
606
|
+
toolCalls: [{
|
|
607
|
+
id: ToolCallId('tc1'),
|
|
608
|
+
name: 'worker_notifying_start',
|
|
609
|
+
input: {},
|
|
610
|
+
}],
|
|
611
|
+
},
|
|
612
|
+
// Agent may be re-scheduled due to mailbox message
|
|
613
|
+
{ content: 'Got it', toolCalls: [] },
|
|
614
|
+
{ content: 'Done', toolCalls: [] },
|
|
615
|
+
]),
|
|
616
|
+
});
|
|
617
|
+
const session = await harness.createSession('test');
|
|
618
|
+
await session.sendAndWaitForIdle('Start worker', { timeoutMs: 5000 });
|
|
619
|
+
await new Promise((r) => setTimeout(r, 200));
|
|
620
|
+
// Check for mailbox_message event with worker's notification
|
|
621
|
+
const allEvents = await session.getEvents();
|
|
622
|
+
const mailboxMessages = allEvents.filter((e) => e.type === 'mailbox_message');
|
|
623
|
+
const workerMessage = mailboxMessages.find((e) => e.message?.content === 'Progress update: 50%');
|
|
624
|
+
expect(workerMessage).toBeDefined();
|
|
625
|
+
await harness.shutdown();
|
|
626
|
+
});
|
|
627
|
+
});
|
|
628
|
+
});
|
|
629
|
+
//# sourceMappingURL=workers.integration.test.js.map
|