@roj-ai/sdk 0.1.35 → 0.2.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/dist/bootstrap.d.ts +420 -26
- package/dist/bootstrap.d.ts.map +1 -1
- package/dist/bootstrap.js +55 -24
- package/dist/bootstrap.js.map +1 -1
- package/dist/bun-platform/fs.d.ts.map +1 -1
- package/dist/bun-platform/fs.js +1 -0
- package/dist/bun-platform/fs.js.map +1 -1
- package/dist/bun-platform/index.d.ts +4 -1
- package/dist/bun-platform/index.d.ts.map +1 -1
- package/dist/bun-platform/index.js +7 -1
- package/dist/bun-platform/index.js.map +1 -1
- package/dist/bun-platform/server-lifecycle.d.ts +30 -0
- package/dist/bun-platform/server-lifecycle.d.ts.map +1 -0
- package/dist/bun-platform/server-lifecycle.js +182 -0
- package/dist/bun-platform/server-lifecycle.js.map +1 -0
- package/dist/bun-platform/shell.d.ts +33 -0
- package/dist/bun-platform/shell.d.ts.map +1 -0
- package/dist/bun-platform/shell.js +322 -0
- package/dist/bun-platform/shell.js.map +1 -0
- package/dist/config.d.ts +34 -0
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +97 -0
- package/dist/config.js.map +1 -1
- package/dist/core/agents/agent.d.ts +42 -7
- package/dist/core/agents/agent.d.ts.map +1 -1
- package/dist/core/agents/agent.js +209 -90
- package/dist/core/agents/agent.js.map +1 -1
- package/dist/core/agents/config.d.ts +8 -1
- package/dist/core/agents/config.d.ts.map +1 -1
- package/dist/core/agents/config.js +5 -1
- package/dist/core/agents/config.js.map +1 -1
- package/dist/core/agents/retry.d.ts +1 -1
- package/dist/core/agents/retry.d.ts.map +1 -1
- package/dist/core/agents/retry.js +14 -16
- package/dist/core/agents/retry.js.map +1 -1
- package/dist/core/agents/state.d.ts +27 -1
- package/dist/core/agents/state.d.ts.map +1 -1
- package/dist/core/agents/state.js +1 -1
- package/dist/core/agents/state.js.map +1 -1
- package/dist/core/context/state.d.ts +3 -3
- package/dist/core/context/state.d.ts.map +1 -1
- package/dist/core/context/state.js +6 -2
- package/dist/core/context/state.js.map +1 -1
- package/dist/core/events/base-event-store.d.ts.map +1 -1
- package/dist/core/events/base-event-store.js +22 -14
- package/dist/core/events/base-event-store.js.map +1 -1
- package/dist/core/events/file.d.ts +39 -1
- package/dist/core/events/file.d.ts.map +1 -1
- package/dist/core/events/file.js +159 -20
- package/dist/core/events/file.js.map +1 -1
- package/dist/core/events/types.d.ts +1 -1
- package/dist/core/file-store/containment.d.ts +19 -0
- package/dist/core/file-store/containment.d.ts.map +1 -0
- package/dist/core/file-store/containment.js +62 -0
- package/dist/core/file-store/containment.js.map +1 -0
- package/dist/core/file-store/file-store.d.ts +22 -2
- package/dist/core/file-store/file-store.d.ts.map +1 -1
- package/dist/core/file-store/file-store.js +88 -20
- package/dist/core/file-store/file-store.js.map +1 -1
- package/dist/core/file-store/types.d.ts +13 -1
- package/dist/core/file-store/types.d.ts.map +1 -1
- package/dist/core/image/image-processor.d.ts.map +1 -1
- package/dist/core/image/image-processor.js +3 -1
- package/dist/core/image/image-processor.js.map +1 -1
- package/dist/core/image/types.d.ts +2 -0
- package/dist/core/image/types.d.ts.map +1 -1
- package/dist/core/image/vips-resizer.d.ts.map +1 -1
- package/dist/core/image/vips-resizer.js +81 -33
- package/dist/core/image/vips-resizer.js.map +1 -1
- package/dist/core/llm/anthropic.d.ts +0 -1
- package/dist/core/llm/anthropic.d.ts.map +1 -1
- package/dist/core/llm/anthropic.js +101 -74
- package/dist/core/llm/anthropic.js.map +1 -1
- package/dist/core/llm/logger.d.ts +14 -2
- package/dist/core/llm/logger.d.ts.map +1 -1
- package/dist/core/llm/logger.js +161 -36
- package/dist/core/llm/logger.js.map +1 -1
- package/dist/core/llm/openrouter.d.ts +0 -1
- package/dist/core/llm/openrouter.d.ts.map +1 -1
- package/dist/core/llm/openrouter.js +70 -74
- package/dist/core/llm/openrouter.js.map +1 -1
- package/dist/core/llm/provider-request.d.ts +10 -0
- package/dist/core/llm/provider-request.d.ts.map +1 -0
- package/dist/core/llm/provider-request.js +41 -0
- package/dist/core/llm/provider-request.js.map +1 -0
- package/dist/core/llm/provider.d.ts +45 -3
- package/dist/core/llm/provider.d.ts.map +1 -1
- package/dist/core/llm/provider.js +26 -0
- package/dist/core/llm/provider.js.map +1 -1
- package/dist/core/llm/state.d.ts +4 -2
- package/dist/core/llm/state.d.ts.map +1 -1
- package/dist/core/llm/state.js +15 -4
- package/dist/core/llm/state.js.map +1 -1
- package/dist/core/plugins/plugin-builder.d.ts +57 -3
- package/dist/core/plugins/plugin-builder.d.ts.map +1 -1
- package/dist/core/plugins/plugin-builder.js +68 -14
- package/dist/core/plugins/plugin-builder.js.map +1 -1
- package/dist/core/preset/preset-builder.d.ts +3 -2
- package/dist/core/preset/preset-builder.d.ts.map +1 -1
- package/dist/core/preset/preset-builder.js +7 -16
- package/dist/core/preset/preset-builder.js.map +1 -1
- package/dist/core/sessions/context.d.ts +23 -5
- package/dist/core/sessions/context.d.ts.map +1 -1
- package/dist/core/sessions/runtime-activity.d.ts +33 -0
- package/dist/core/sessions/runtime-activity.d.ts.map +1 -0
- package/dist/core/sessions/runtime-activity.js +55 -0
- package/dist/core/sessions/runtime-activity.js.map +1 -0
- package/dist/core/sessions/schema.d.ts +23 -2
- package/dist/core/sessions/schema.d.ts.map +1 -1
- package/dist/core/sessions/schema.js +24 -3
- package/dist/core/sessions/schema.js.map +1 -1
- package/dist/core/sessions/session-manager.d.ts +83 -6
- package/dist/core/sessions/session-manager.d.ts.map +1 -1
- package/dist/core/sessions/session-manager.js +517 -118
- package/dist/core/sessions/session-manager.js.map +1 -1
- package/dist/core/sessions/session-store.d.ts +18 -0
- package/dist/core/sessions/session-store.d.ts.map +1 -1
- package/dist/core/sessions/session-store.js +33 -0
- package/dist/core/sessions/session-store.js.map +1 -1
- package/dist/core/sessions/session.d.ts +42 -6
- package/dist/core/sessions/session.d.ts.map +1 -1
- package/dist/core/sessions/session.js +176 -44
- package/dist/core/sessions/session.js.map +1 -1
- package/dist/core/sessions/state.d.ts +10 -1
- package/dist/core/sessions/state.d.ts.map +1 -1
- package/dist/core/sessions/state.js +16 -1
- package/dist/core/sessions/state.js.map +1 -1
- package/dist/core/system.d.ts +9 -0
- package/dist/core/system.d.ts.map +1 -1
- package/dist/core/system.js +4 -1
- package/dist/core/system.js.map +1 -1
- package/dist/core/tools/executor.d.ts +1 -1
- package/dist/core/wake-key.d.ts +34 -0
- package/dist/core/wake-key.d.ts.map +1 -0
- package/dist/core/wake-key.js +51 -0
- package/dist/core/wake-key.js.map +1 -0
- package/dist/index.d.ts +24 -13
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +22 -8
- package/dist/index.js.map +1 -1
- package/dist/lib/archive/archive-inspection.d.ts +48 -0
- package/dist/lib/archive/archive-inspection.d.ts.map +1 -0
- package/dist/lib/archive/archive-inspection.fixtures.d.ts +7 -0
- package/dist/lib/archive/archive-inspection.fixtures.d.ts.map +1 -0
- package/dist/lib/archive/archive-inspection.fixtures.js +134 -0
- package/dist/lib/archive/archive-inspection.fixtures.js.map +1 -0
- package/dist/lib/archive/archive-inspection.js +253 -0
- package/dist/lib/archive/archive-inspection.js.map +1 -0
- package/dist/lib/archive/index.d.ts +3 -0
- package/dist/lib/archive/index.d.ts.map +1 -0
- package/dist/lib/archive/index.js +2 -0
- package/dist/lib/archive/index.js.map +1 -0
- package/dist/lib/logger/console.d.ts +5 -12
- package/dist/lib/logger/console.d.ts.map +1 -1
- package/dist/lib/logger/console.js +5 -47
- package/dist/lib/logger/console.js.map +1 -1
- package/dist/lib/logger/file.d.ts +8 -11
- package/dist/lib/logger/file.d.ts.map +1 -1
- package/dist/lib/logger/file.js +26 -37
- package/dist/lib/logger/file.js.map +1 -1
- package/dist/lib/logger/index.d.ts +3 -1
- package/dist/lib/logger/index.d.ts.map +1 -1
- package/dist/lib/logger/index.js +3 -1
- package/dist/lib/logger/index.js.map +1 -1
- package/dist/lib/logger/jsonl.d.ts +21 -0
- package/dist/lib/logger/jsonl.d.ts.map +1 -0
- package/dist/lib/logger/jsonl.js +29 -0
- package/dist/lib/logger/jsonl.js.map +1 -0
- package/dist/lib/logger/logger.d.ts +22 -0
- package/dist/lib/logger/logger.d.ts.map +1 -1
- package/dist/lib/logger/logger.js +37 -0
- package/dist/lib/logger/logger.js.map +1 -1
- package/dist/lib/logger/session-log.d.ts +21 -0
- package/dist/lib/logger/session-log.d.ts.map +1 -0
- package/dist/lib/logger/session-log.js +37 -0
- package/dist/lib/logger/session-log.js.map +1 -0
- package/dist/lib/utils/concurrency.d.ts +1 -1
- package/dist/lib/utils/concurrency.d.ts.map +1 -1
- package/dist/lib/utils/concurrency.js +30 -7
- package/dist/lib/utils/concurrency.js.map +1 -1
- package/dist/lib/utils/fs-batch.d.ts +17 -0
- package/dist/lib/utils/fs-batch.d.ts.map +1 -0
- package/dist/lib/utils/fs-batch.js +38 -0
- package/dist/lib/utils/fs-batch.js.map +1 -0
- package/dist/lib/utils/result.d.ts +7 -22
- package/dist/lib/utils/result.d.ts.map +1 -1
- package/dist/lib/utils/result.js +6 -17
- package/dist/lib/utils/result.js.map +1 -1
- package/dist/lib/utils/sleep.d.ts +10 -0
- package/dist/lib/utils/sleep.d.ts.map +1 -0
- package/dist/lib/utils/sleep.js +26 -0
- package/dist/lib/utils/sleep.js.map +1 -0
- package/dist/platform/fs-revision.d.ts +21 -0
- package/dist/platform/fs-revision.d.ts.map +1 -0
- package/dist/platform/fs-revision.js +9 -0
- package/dist/platform/fs-revision.js.map +1 -0
- package/dist/platform/fs.d.ts +104 -1
- package/dist/platform/fs.d.ts.map +1 -1
- package/dist/platform/git.d.ts +59 -0
- package/dist/platform/git.d.ts.map +1 -0
- package/dist/platform/git.js +8 -0
- package/dist/platform/git.js.map +1 -0
- package/dist/platform/index.d.ts +40 -1
- package/dist/platform/index.d.ts.map +1 -1
- package/dist/platform/index.js +1 -1
- package/dist/platform/index.js.map +1 -1
- package/dist/platform/llm-call-log.d.ts +80 -0
- package/dist/platform/llm-call-log.d.ts.map +1 -0
- package/dist/platform/llm-call-log.js +12 -0
- package/dist/platform/llm-call-log.js.map +1 -0
- package/dist/platform/scheduler.d.ts +32 -0
- package/dist/platform/scheduler.d.ts.map +1 -0
- package/dist/platform/scheduler.js +46 -0
- package/dist/platform/scheduler.js.map +1 -0
- package/dist/platform/session-log.d.ts +36 -0
- package/dist/platform/session-log.d.ts.map +1 -0
- package/dist/platform/session-log.js +12 -0
- package/dist/platform/session-log.js.map +1 -0
- package/dist/platform/shell.d.ts +83 -0
- package/dist/platform/shell.d.ts.map +1 -0
- package/dist/platform/shell.js +13 -0
- package/dist/platform/shell.js.map +1 -0
- package/dist/plugins/agent-status/plugin.d.ts.map +1 -1
- package/dist/plugins/agent-status/plugin.js +1 -0
- package/dist/plugins/agent-status/plugin.js.map +1 -1
- package/dist/plugins/agents/plugin.d.ts.map +1 -1
- package/dist/plugins/agents/plugin.js +129 -62
- package/dist/plugins/agents/plugin.js.map +1 -1
- package/dist/plugins/filesystem/listing.d.ts +3 -0
- package/dist/plugins/filesystem/listing.d.ts.map +1 -1
- package/dist/plugins/filesystem/listing.js +66 -10
- package/dist/plugins/filesystem/listing.js.map +1 -1
- package/dist/plugins/filesystem/plugin.d.ts.map +1 -1
- package/dist/plugins/filesystem/plugin.js +8 -6
- package/dist/plugins/filesystem/plugin.js.map +1 -1
- package/dist/plugins/git-status/plugin.d.ts +34 -7
- package/dist/plugins/git-status/plugin.d.ts.map +1 -1
- package/dist/plugins/git-status/plugin.js +168 -64
- package/dist/plugins/git-status/plugin.js.map +1 -1
- package/dist/plugins/llm-debug/plugin.d.ts.map +1 -1
- package/dist/plugins/llm-debug/plugin.js +1 -0
- package/dist/plugins/llm-debug/plugin.js.map +1 -1
- package/dist/plugins/logs/plugin.d.ts +1 -4
- package/dist/plugins/logs/plugin.d.ts.map +1 -1
- package/dist/plugins/logs/plugin.js +7 -0
- package/dist/plugins/logs/plugin.js.map +1 -1
- package/dist/plugins/mailbox/helpers.d.ts +2 -2
- package/dist/plugins/mailbox/helpers.js +1 -1
- package/dist/plugins/mailbox/plugin.d.ts.map +1 -1
- package/dist/plugins/mailbox/plugin.js +38 -43
- package/dist/plugins/mailbox/plugin.js.map +1 -1
- package/dist/plugins/mailbox/query.d.ts +7 -2
- package/dist/plugins/mailbox/query.d.ts.map +1 -1
- package/dist/plugins/mailbox/query.js +14 -7
- package/dist/plugins/mailbox/query.js.map +1 -1
- package/dist/plugins/mailbox/state.d.ts +5 -4
- package/dist/plugins/mailbox/state.d.ts.map +1 -1
- package/dist/plugins/mailbox/state.js +6 -5
- package/dist/plugins/mailbox/state.js.map +1 -1
- package/dist/plugins/resources/filename.d.ts +4 -0
- package/dist/plugins/resources/filename.d.ts.map +1 -0
- package/dist/plugins/resources/filename.js +18 -0
- package/dist/plugins/resources/filename.js.map +1 -0
- package/dist/plugins/resources/plugin.d.ts +3 -0
- package/dist/plugins/resources/plugin.d.ts.map +1 -1
- package/dist/plugins/resources/plugin.js +97 -60
- package/dist/plugins/resources/plugin.js.map +1 -1
- package/dist/plugins/resources/state.d.ts +1 -1
- package/dist/plugins/resources/state.js +1 -1
- package/dist/plugins/result-eviction/plugin.d.ts.map +1 -1
- package/dist/plugins/result-eviction/plugin.js +6 -1
- package/dist/plugins/result-eviction/plugin.js.map +1 -1
- package/dist/plugins/services/plugin.d.ts +4 -1
- package/dist/plugins/services/plugin.d.ts.map +1 -1
- package/dist/plugins/services/plugin.js +251 -100
- package/dist/plugins/services/plugin.js.map +1 -1
- package/dist/plugins/services/prompt.d.ts.map +1 -1
- package/dist/plugins/services/prompt.js +1 -4
- package/dist/plugins/services/prompt.js.map +1 -1
- package/dist/plugins/services/schema.d.ts +15 -5
- package/dist/plugins/services/schema.d.ts.map +1 -1
- package/dist/plugins/services/service.d.ts +100 -18
- package/dist/plugins/services/service.d.ts.map +1 -1
- package/dist/plugins/services/service.js +680 -230
- package/dist/plugins/services/service.js.map +1 -1
- package/dist/plugins/session-lifecycle/plugin.d.ts +21 -1
- package/dist/plugins/session-lifecycle/plugin.d.ts.map +1 -1
- package/dist/plugins/session-lifecycle/plugin.js +53 -40
- package/dist/plugins/session-lifecycle/plugin.js.map +1 -1
- package/dist/plugins/session-state/plugin.d.ts +21 -13
- package/dist/plugins/session-state/plugin.d.ts.map +1 -1
- package/dist/plugins/session-state/plugin.js +214 -79
- package/dist/plugins/session-state/plugin.js.map +1 -1
- package/dist/plugins/session-stats/plugin.d.ts.map +1 -1
- package/dist/plugins/session-stats/plugin.js +1 -0
- package/dist/plugins/session-stats/plugin.js.map +1 -1
- package/dist/plugins/shell/executor.d.ts +17 -15
- package/dist/plugins/shell/executor.d.ts.map +1 -1
- package/dist/plugins/shell/executor.js +130 -195
- package/dist/plugins/shell/executor.js.map +1 -1
- package/dist/plugins/shell/index.d.ts +2 -2
- package/dist/plugins/shell/index.d.ts.map +1 -1
- package/dist/plugins/shell/index.js +2 -2
- package/dist/plugins/shell/index.js.map +1 -1
- package/dist/plugins/shell/plugin.d.ts +5 -4
- package/dist/plugins/shell/plugin.d.ts.map +1 -1
- package/dist/plugins/shell/plugin.js +4 -8
- package/dist/plugins/shell/plugin.js.map +1 -1
- package/dist/plugins/skills/discovery.d.ts.map +1 -1
- package/dist/plugins/skills/discovery.js +10 -8
- package/dist/plugins/skills/discovery.js.map +1 -1
- package/dist/plugins/skills/index.d.ts +1 -1
- package/dist/plugins/skills/index.d.ts.map +1 -1
- package/dist/plugins/skills/plugin.d.ts +1 -1
- package/dist/plugins/skills/plugin.d.ts.map +1 -1
- package/dist/plugins/skills/plugin.js +23 -30
- package/dist/plugins/skills/plugin.js.map +1 -1
- package/dist/plugins/skills/prompts.d.ts +3 -3
- package/dist/plugins/skills/prompts.d.ts.map +1 -1
- package/dist/plugins/skills/prompts.js.map +1 -1
- package/dist/plugins/skills/schema.d.ts +4 -2
- package/dist/plugins/skills/schema.d.ts.map +1 -1
- package/dist/plugins/todo/schema.d.ts +1 -1
- package/dist/plugins/uploads/plugin.d.ts +11 -4
- package/dist/plugins/uploads/plugin.d.ts.map +1 -1
- package/dist/plugins/uploads/plugin.js +891 -225
- package/dist/plugins/uploads/plugin.js.map +1 -1
- package/dist/plugins/uploads/preprocessor.d.ts +14 -0
- package/dist/plugins/uploads/preprocessor.d.ts.map +1 -1
- package/dist/plugins/uploads/preprocessor.js +11 -0
- package/dist/plugins/uploads/preprocessor.js.map +1 -1
- package/dist/plugins/uploads/preprocessors/image-classifier.d.ts +1 -1
- package/dist/plugins/uploads/preprocessors/image-classifier.d.ts.map +1 -1
- package/dist/plugins/uploads/preprocessors/image-classifier.js +51 -26
- package/dist/plugins/uploads/preprocessors/image-classifier.js.map +1 -1
- package/dist/plugins/uploads/preprocessors/markitdown-preprocessor.d.ts +2 -2
- package/dist/plugins/uploads/preprocessors/markitdown-preprocessor.d.ts.map +1 -1
- package/dist/plugins/uploads/preprocessors/markitdown-preprocessor.js +41 -16
- package/dist/plugins/uploads/preprocessors/markitdown-preprocessor.js.map +1 -1
- package/dist/plugins/uploads/preprocessors/pdf-preprocessor.d.ts +1 -1
- package/dist/plugins/uploads/preprocessors/pdf-preprocessor.d.ts.map +1 -1
- package/dist/plugins/uploads/preprocessors/pdf-preprocessor.js +29 -14
- package/dist/plugins/uploads/preprocessors/pdf-preprocessor.js.map +1 -1
- package/dist/plugins/uploads/preprocessors/zip-preprocessor.d.ts +1 -1
- package/dist/plugins/uploads/preprocessors/zip-preprocessor.d.ts.map +1 -1
- package/dist/plugins/uploads/preprocessors/zip-preprocessor.js +62 -34
- package/dist/plugins/uploads/preprocessors/zip-preprocessor.js.map +1 -1
- package/dist/plugins/uploads/schema.d.ts +25 -2
- package/dist/plugins/uploads/schema.d.ts.map +1 -1
- package/dist/plugins/uploads/schema.js +24 -3
- package/dist/plugins/uploads/schema.js.map +1 -1
- package/dist/plugins/uploads/state.d.ts +13 -1
- package/dist/plugins/uploads/state.d.ts.map +1 -1
- package/dist/plugins/uploads/state.js +4 -1
- package/dist/plugins/uploads/state.js.map +1 -1
- package/dist/plugins/user-chat/plugin.d.ts +12 -5
- package/dist/plugins/user-chat/plugin.d.ts.map +1 -1
- package/dist/plugins/user-chat/plugin.js +141 -32
- package/dist/plugins/user-chat/plugin.js.map +1 -1
- package/dist/plugins/workers/context.d.ts +35 -13
- package/dist/plugins/workers/context.d.ts.map +1 -1
- package/dist/plugins/workers/context.js +82 -32
- package/dist/plugins/workers/context.js.map +1 -1
- package/dist/plugins/workers/definition.d.ts +7 -0
- package/dist/plugins/workers/definition.d.ts.map +1 -1
- package/dist/plugins/workers/definition.js.map +1 -1
- package/dist/plugins/workers/index.d.ts +4 -4
- package/dist/plugins/workers/index.d.ts.map +1 -1
- package/dist/plugins/workers/index.js +2 -2
- package/dist/plugins/workers/index.js.map +1 -1
- package/dist/plugins/workers/plugin.d.ts +10 -57
- package/dist/plugins/workers/plugin.d.ts.map +1 -1
- package/dist/plugins/workers/plugin.js +385 -123
- package/dist/plugins/workers/plugin.js.map +1 -1
- package/dist/plugins/workers/state.d.ts +69 -0
- package/dist/plugins/workers/state.d.ts.map +1 -0
- package/dist/plugins/workers/state.js +52 -0
- package/dist/plugins/workers/state.js.map +1 -0
- package/dist/plugins/workers/worker.d.ts +15 -4
- package/dist/plugins/workers/worker.d.ts.map +1 -1
- package/dist/testing/conformance.d.ts +106 -0
- package/dist/testing/conformance.d.ts.map +1 -0
- package/dist/testing/conformance.js +1463 -0
- package/dist/testing/conformance.js.map +1 -0
- package/dist/testing/node-platform.d.ts.map +1 -1
- package/dist/testing/node-platform.js +5 -0
- package/dist/testing/node-platform.js.map +1 -1
- package/dist/testing/test-harness.d.ts +11 -1
- package/dist/testing/test-harness.d.ts.map +1 -1
- package/dist/testing/test-harness.js +17 -37
- package/dist/testing/test-harness.js.map +1 -1
- package/dist/testing/wait-helpers.d.ts.map +1 -1
- package/dist/testing/wait-helpers.js +1 -3
- package/dist/testing/wait-helpers.js.map +1 -1
- package/dist/transport/adapter/client-adapter.d.ts +6 -0
- package/dist/transport/adapter/client-adapter.d.ts.map +1 -1
- package/dist/transport/adapter/client-adapter.js +50 -3
- package/dist/transport/adapter/client-adapter.js.map +1 -1
- package/dist/transport/adapter/heartbeat.d.ts +16 -0
- package/dist/transport/adapter/heartbeat.d.ts.map +1 -0
- package/dist/transport/adapter/heartbeat.js +41 -0
- package/dist/transport/adapter/heartbeat.js.map +1 -0
- package/dist/transport/adapter/server-adapter.d.ts.map +1 -1
- package/dist/transport/adapter/server-adapter.js +6 -0
- package/dist/transport/adapter/server-adapter.js.map +1 -1
- package/dist/transport/http/app.d.ts +3 -30
- package/dist/transport/http/app.d.ts.map +1 -1
- package/dist/transport/http/app.js +3 -7
- package/dist/transport/http/app.js.map +1 -1
- package/dist/transport/http/context.d.ts +40 -0
- package/dist/transport/http/context.d.ts.map +1 -0
- package/dist/transport/http/context.js +17 -0
- package/dist/transport/http/context.js.map +1 -0
- package/dist/transport/http/fetch-guard.d.ts +49 -0
- package/dist/transport/http/fetch-guard.d.ts.map +1 -0
- package/dist/transport/http/fetch-guard.js +312 -0
- package/dist/transport/http/fetch-guard.js.map +1 -0
- package/dist/transport/http/index.d.ts +1 -1
- package/dist/transport/http/index.d.ts.map +1 -1
- package/dist/transport/http/middleware/bearer-auth.d.ts +1 -1
- package/dist/transport/http/middleware/bearer-auth.d.ts.map +1 -1
- package/dist/transport/http/middleware/error-handler.d.ts +2 -2
- package/dist/transport/http/middleware/error-handler.d.ts.map +1 -1
- package/dist/transport/http/path-containment.d.ts +20 -0
- package/dist/transport/http/path-containment.d.ts.map +1 -0
- package/dist/transport/http/path-containment.js +31 -0
- package/dist/transport/http/path-containment.js.map +1 -0
- package/dist/transport/http/responses.d.ts +30 -0
- package/dist/transport/http/responses.d.ts.map +1 -0
- package/dist/transport/http/responses.js +5 -0
- package/dist/transport/http/responses.js.map +1 -0
- package/dist/transport/http/routes/files.d.ts +1 -1
- package/dist/transport/http/routes/files.d.ts.map +1 -1
- package/dist/transport/http/routes/files.js +54 -155
- package/dist/transport/http/routes/files.js.map +1 -1
- package/dist/transport/http/routes/resources.d.ts +1 -1
- package/dist/transport/http/routes/resources.d.ts.map +1 -1
- package/dist/transport/http/routes/resources.js +92 -57
- package/dist/transport/http/routes/resources.js.map +1 -1
- package/dist/transport/http/routes/rpc.d.ts +6 -1
- package/dist/transport/http/routes/rpc.d.ts.map +1 -1
- package/dist/transport/http/routes/rpc.js +51 -21
- package/dist/transport/http/routes/rpc.js.map +1 -1
- package/dist/transport/http/routes/upload.d.ts +1 -1
- package/dist/transport/http/routes/upload.d.ts.map +1 -1
- package/dist/transport/http/routes/upload.js +256 -169
- package/dist/transport/http/routes/upload.js.map +1 -1
- package/dist/user-config.d.ts +34 -7
- package/dist/user-config.d.ts.map +1 -1
- package/dist/user-config.js +71 -0
- package/dist/user-config.js.map +1 -1
- package/package.json +18 -8
- package/src/bootstrap.ts +119 -35
- package/src/bun-platform/fs.ts +1 -0
- package/src/bun-platform/index.ts +18 -1
- package/src/bun-platform/server-lifecycle.ts +218 -0
- package/src/bun-platform/shell.ts +362 -0
- package/src/config.ts +130 -0
- package/src/core/agents/agent.ts +219 -95
- package/src/core/agents/config.ts +8 -0
- package/src/core/agents/retry.ts +16 -17
- package/src/core/agents/state.ts +28 -0
- package/src/core/context/state.ts +4 -0
- package/src/core/events/base-event-store.ts +24 -16
- package/src/core/events/file.ts +198 -22
- package/src/core/file-store/containment.ts +75 -0
- package/src/core/file-store/file-store.ts +106 -25
- package/src/core/file-store/types.ts +14 -1
- package/src/core/image/image-processor.ts +3 -1
- package/src/core/image/types.ts +2 -0
- package/src/core/image/vips-resizer.ts +102 -37
- package/src/core/llm/anthropic.ts +127 -82
- package/src/core/llm/logger.ts +175 -37
- package/src/core/llm/openrouter.ts +82 -81
- package/src/core/llm/provider-request.ts +40 -0
- package/src/core/llm/provider.ts +72 -3
- package/src/core/llm/state.ts +12 -0
- package/src/core/plugins/plugin-builder.ts +106 -14
- package/src/core/preset/preset-builder.ts +12 -22
- package/src/core/sessions/context.ts +18 -0
- package/src/core/sessions/runtime-activity.ts +78 -0
- package/src/core/sessions/schema.ts +29 -3
- package/src/core/sessions/session-manager.ts +560 -140
- package/src/core/sessions/session-store.ts +38 -0
- package/src/core/sessions/session.ts +187 -47
- package/src/core/sessions/state.ts +16 -0
- package/src/core/system.ts +15 -0
- package/src/core/wake-key.ts +65 -0
- package/src/index.ts +31 -12
- package/src/lib/archive/archive-inspection.fixtures.ts +138 -0
- package/src/lib/archive/archive-inspection.ts +359 -0
- package/src/lib/archive/index.ts +17 -0
- package/src/lib/logger/console.ts +7 -57
- package/src/lib/logger/file.ts +28 -50
- package/src/lib/logger/index.ts +3 -1
- package/src/lib/logger/jsonl.ts +36 -0
- package/src/lib/logger/logger.ts +48 -0
- package/src/lib/logger/session-log.ts +42 -0
- package/src/lib/utils/concurrency.ts +37 -8
- package/src/lib/utils/fs-batch.ts +49 -0
- package/src/lib/utils/result.ts +7 -31
- package/src/lib/utils/sleep.ts +23 -0
- package/src/platform/fs-revision.ts +21 -0
- package/src/platform/fs.ts +109 -1
- package/src/platform/git.ts +67 -0
- package/src/platform/index.ts +51 -1
- package/src/platform/llm-call-log.ts +86 -0
- package/src/platform/scheduler.ts +71 -0
- package/src/platform/session-log.ts +39 -0
- package/src/platform/shell.ts +89 -0
- package/src/plugins/agent-status/plugin.ts +1 -0
- package/src/plugins/agents/plugin.ts +134 -81
- package/src/plugins/filesystem/listing.ts +70 -12
- package/src/plugins/filesystem/plugin.ts +8 -6
- package/src/plugins/git-status/plugin.ts +204 -77
- package/src/plugins/llm-debug/plugin.ts +1 -0
- package/src/plugins/logs/plugin.ts +9 -0
- package/src/plugins/mailbox/plugin.ts +46 -64
- package/src/plugins/mailbox/query.ts +15 -7
- package/src/plugins/mailbox/state.ts +1 -0
- package/src/plugins/resources/filename.ts +19 -0
- package/src/plugins/resources/plugin.ts +111 -59
- package/src/plugins/result-eviction/plugin.ts +6 -1
- package/src/plugins/services/plugin.ts +254 -98
- package/src/plugins/services/prompt.ts +1 -6
- package/src/plugins/services/schema.ts +17 -3
- package/src/plugins/services/service.ts +702 -252
- package/src/plugins/session-lifecycle/plugin.ts +56 -41
- package/src/plugins/session-state/plugin.ts +242 -88
- package/src/plugins/session-stats/plugin.ts +1 -0
- package/src/plugins/shell/executor.ts +144 -226
- package/src/plugins/shell/index.ts +1 -4
- package/src/plugins/shell/plugin.ts +7 -9
- package/src/plugins/skills/discovery.ts +10 -8
- package/src/plugins/skills/index.ts +1 -1
- package/src/plugins/skills/plugin.ts +19 -27
- package/src/plugins/skills/prompts.ts +3 -3
- package/src/plugins/skills/schema.ts +5 -2
- package/src/plugins/uploads/plugin.ts +991 -273
- package/src/plugins/uploads/preprocessor.ts +25 -0
- package/src/plugins/uploads/preprocessors/image-classifier.ts +56 -25
- package/src/plugins/uploads/preprocessors/markitdown-preprocessor.ts +41 -15
- package/src/plugins/uploads/preprocessors/pdf-preprocessor.ts +32 -16
- package/src/plugins/uploads/preprocessors/zip-preprocessor.ts +67 -38
- package/src/plugins/uploads/schema.ts +30 -3
- package/src/plugins/uploads/state.ts +12 -0
- package/src/plugins/user-chat/plugin.ts +196 -40
- package/src/plugins/workers/context.ts +102 -39
- package/src/plugins/workers/definition.ts +7 -0
- package/src/plugins/workers/index.ts +4 -4
- package/src/plugins/workers/plugin.ts +461 -151
- package/src/plugins/workers/state.ts +64 -0
- package/src/plugins/workers/worker.ts +15 -4
- package/src/testing/conformance.ts +1751 -0
- package/src/testing/node-platform.ts +5 -0
- package/src/testing/test-harness.ts +21 -38
- package/src/testing/wait-helpers.ts +1 -4
- package/src/transport/adapter/client-adapter.ts +60 -3
- package/src/transport/adapter/heartbeat.ts +50 -0
- package/src/transport/adapter/server-adapter.ts +6 -0
- package/src/transport/http/app.ts +7 -35
- package/src/transport/http/context.ts +46 -0
- package/src/transport/http/fetch-guard.ts +318 -0
- package/src/transport/http/index.ts +1 -1
- package/src/transport/http/middleware/bearer-auth.ts +1 -1
- package/src/transport/http/middleware/error-handler.ts +1 -1
- package/src/transport/http/path-containment.ts +44 -0
- package/src/transport/http/responses.ts +20 -0
- package/src/transport/http/routes/files.ts +69 -159
- package/src/transport/http/routes/resources.ts +124 -93
- package/src/transport/http/routes/rpc.ts +63 -26
- package/src/transport/http/routes/upload.ts +327 -258
- package/src/user-config.ts +93 -7
- package/dist/config.test.d.ts +0 -2
- package/dist/config.test.d.ts.map +0 -1
- package/dist/config.test.js +0 -155
- package/dist/config.test.js.map +0 -1
- package/dist/core/agent-loop.integration.test.d.ts +0 -2
- package/dist/core/agent-loop.integration.test.d.ts.map +0 -1
- package/dist/core/agent-loop.integration.test.js +0 -414
- package/dist/core/agent-loop.integration.test.js.map +0 -1
- package/dist/core/agents/agent-config.test.d.ts +0 -2
- package/dist/core/agents/agent-config.test.d.ts.map +0 -1
- package/dist/core/agents/agent-config.test.js +0 -194
- package/dist/core/agents/agent-config.test.js.map +0 -1
- package/dist/core/agents/agent-shutdown.test.d.ts +0 -6
- package/dist/core/agents/agent-shutdown.test.d.ts.map +0 -1
- package/dist/core/agents/agent-shutdown.test.js +0 -180
- package/dist/core/agents/agent-shutdown.test.js.map +0 -1
- package/dist/core/agents/agent.test.d.ts +0 -2
- package/dist/core/agents/agent.test.d.ts.map +0 -1
- package/dist/core/agents/agent.test.js +0 -313
- package/dist/core/agents/agent.test.js.map +0 -1
- package/dist/core/agents/communicator.d.ts +0 -3
- package/dist/core/agents/communicator.d.ts.map +0 -1
- package/dist/core/agents/communicator.js +0 -13
- package/dist/core/agents/communicator.js.map +0 -1
- package/dist/core/agents/handler-events.test.d.ts +0 -5
- package/dist/core/agents/handler-events.test.d.ts.map +0 -1
- package/dist/core/agents/handler-events.test.js +0 -115
- package/dist/core/agents/handler-events.test.js.map +0 -1
- package/dist/core/agents/response-sanitizer.test.d.ts +0 -2
- package/dist/core/agents/response-sanitizer.test.d.ts.map +0 -1
- package/dist/core/agents/response-sanitizer.test.js +0 -101
- package/dist/core/agents/response-sanitizer.test.js.map +0 -1
- package/dist/core/error-recovery.integration.test.d.ts +0 -2
- package/dist/core/error-recovery.integration.test.d.ts.map +0 -1
- package/dist/core/error-recovery.integration.test.js +0 -288
- package/dist/core/error-recovery.integration.test.js.map +0 -1
- package/dist/core/event-sourcing.integration.test.d.ts +0 -2
- package/dist/core/event-sourcing.integration.test.d.ts.map +0 -1
- package/dist/core/event-sourcing.integration.test.js +0 -154
- package/dist/core/event-sourcing.integration.test.js.map +0 -1
- package/dist/core/events/file.test.d.ts +0 -2
- package/dist/core/events/file.test.d.ts.map +0 -1
- package/dist/core/events/file.test.js +0 -284
- package/dist/core/events/file.test.js.map +0 -1
- package/dist/core/events/memory.test.d.ts +0 -2
- package/dist/core/events/memory.test.d.ts.map +0 -1
- package/dist/core/events/memory.test.js +0 -502
- package/dist/core/events/memory.test.js.map +0 -1
- package/dist/core/image/image-processor.test.d.ts +0 -2
- package/dist/core/image/image-processor.test.d.ts.map +0 -1
- package/dist/core/image/image-processor.test.js +0 -171
- package/dist/core/image/image-processor.test.js.map +0 -1
- package/dist/core/image/vips-resizer.test.d.ts +0 -2
- package/dist/core/image/vips-resizer.test.d.ts.map +0 -1
- package/dist/core/image/vips-resizer.test.js +0 -336
- package/dist/core/image/vips-resizer.test.js.map +0 -1
- package/dist/core/llm/anthropic.test.d.ts +0 -2
- package/dist/core/llm/anthropic.test.d.ts.map +0 -1
- package/dist/core/llm/anthropic.test.js +0 -464
- package/dist/core/llm/anthropic.test.js.map +0 -1
- package/dist/core/llm/cache-breakpoints.test.d.ts +0 -2
- package/dist/core/llm/cache-breakpoints.test.d.ts.map +0 -1
- package/dist/core/llm/cache-breakpoints.test.js +0 -69
- package/dist/core/llm/cache-breakpoints.test.js.map +0 -1
- package/dist/core/llm/cache-live.test.d.ts +0 -16
- package/dist/core/llm/cache-live.test.d.ts.map +0 -1
- package/dist/core/llm/cache-live.test.js +0 -137
- package/dist/core/llm/cache-live.test.js.map +0 -1
- package/dist/core/llm/logger.test.d.ts +0 -7
- package/dist/core/llm/logger.test.d.ts.map +0 -1
- package/dist/core/llm/logger.test.js +0 -228
- package/dist/core/llm/logger.test.js.map +0 -1
- package/dist/core/llm/message-sanitization.test.d.ts +0 -2
- package/dist/core/llm/message-sanitization.test.d.ts.map +0 -1
- package/dist/core/llm/message-sanitization.test.js +0 -181
- package/dist/core/llm/message-sanitization.test.js.map +0 -1
- package/dist/core/llm/mock.test.d.ts +0 -2
- package/dist/core/llm/mock.test.d.ts.map +0 -1
- package/dist/core/llm/mock.test.js +0 -318
- package/dist/core/llm/mock.test.js.map +0 -1
- package/dist/core/llm/openrouter-mapping.test.d.ts +0 -2
- package/dist/core/llm/openrouter-mapping.test.d.ts.map +0 -1
- package/dist/core/llm/openrouter-mapping.test.js +0 -172
- package/dist/core/llm/openrouter-mapping.test.js.map +0 -1
- package/dist/core/llm/openrouter.test.d.ts +0 -2
- package/dist/core/llm/openrouter.test.d.ts.map +0 -1
- package/dist/core/llm/openrouter.test.js +0 -377
- package/dist/core/llm/openrouter.test.js.map +0 -1
- package/dist/core/llm/provider-integration.test.d.ts +0 -12
- package/dist/core/llm/provider-integration.test.d.ts.map +0 -1
- package/dist/core/llm/provider-integration.test.js +0 -350
- package/dist/core/llm/provider-integration.test.js.map +0 -1
- package/dist/core/llm/routing-provider.test.d.ts +0 -2
- package/dist/core/llm/routing-provider.test.d.ts.map +0 -1
- package/dist/core/llm/routing-provider.test.js +0 -94
- package/dist/core/llm/routing-provider.test.js.map +0 -1
- package/dist/core/llm/snapshot-middleware.test.d.ts +0 -2
- package/dist/core/llm/snapshot-middleware.test.d.ts.map +0 -1
- package/dist/core/llm/snapshot-middleware.test.js +0 -144
- package/dist/core/llm/snapshot-middleware.test.js.map +0 -1
- package/dist/core/multi-agent.integration.test.d.ts +0 -2
- package/dist/core/multi-agent.integration.test.d.ts.map +0 -1
- package/dist/core/multi-agent.integration.test.js +0 -298
- package/dist/core/multi-agent.integration.test.js.map +0 -1
- package/dist/core/plugin-hooks.integration.test.d.ts +0 -2
- package/dist/core/plugin-hooks.integration.test.d.ts.map +0 -1
- package/dist/core/plugin-hooks.integration.test.js +0 -458
- package/dist/core/plugin-hooks.integration.test.js.map +0 -1
- package/dist/core/session-lifecycle.integration.test.d.ts +0 -2
- package/dist/core/session-lifecycle.integration.test.d.ts.map +0 -1
- package/dist/core/session-lifecycle.integration.test.js +0 -159
- package/dist/core/session-lifecycle.integration.test.js.map +0 -1
- package/dist/core/sessions/fork-utils.test.d.ts +0 -2
- package/dist/core/sessions/fork-utils.test.d.ts.map +0 -1
- package/dist/core/sessions/fork-utils.test.js +0 -129
- package/dist/core/sessions/fork-utils.test.js.map +0 -1
- package/dist/core/sessions/session-overrides.integration.test.d.ts +0 -2
- package/dist/core/sessions/session-overrides.integration.test.d.ts.map +0 -1
- package/dist/core/sessions/session-overrides.integration.test.js +0 -154
- package/dist/core/sessions/session-overrides.integration.test.js.map +0 -1
- package/dist/core/sessions/session.test.d.ts +0 -2
- package/dist/core/sessions/session.test.d.ts.map +0 -1
- package/dist/core/sessions/session.test.js +0 -1100
- package/dist/core/sessions/session.test.js.map +0 -1
- package/dist/core/tools/executor.test.d.ts +0 -2
- package/dist/core/tools/executor.test.d.ts.map +0 -1
- package/dist/core/tools/executor.test.js +0 -144
- package/dist/core/tools/executor.test.js.map +0 -1
- package/dist/lib/logger/console.test.d.ts +0 -2
- package/dist/lib/logger/console.test.d.ts.map +0 -1
- package/dist/lib/logger/console.test.js +0 -258
- package/dist/lib/logger/console.test.js.map +0 -1
- package/dist/lib/never.d.ts +0 -2
- package/dist/lib/never.d.ts.map +0 -1
- package/dist/lib/never.js +0 -4
- package/dist/lib/never.js.map +0 -1
- package/dist/lib/utils/concurrency.test.d.ts +0 -2
- package/dist/lib/utils/concurrency.test.d.ts.map +0 -1
- package/dist/lib/utils/concurrency.test.js +0 -135
- package/dist/lib/utils/concurrency.test.js.map +0 -1
- package/dist/plugins/agent-status/agent-status.test.d.ts +0 -2
- package/dist/plugins/agent-status/agent-status.test.d.ts.map +0 -1
- package/dist/plugins/agent-status/agent-status.test.js +0 -136
- package/dist/plugins/agent-status/agent-status.test.js.map +0 -1
- package/dist/plugins/agents/agents.integration.test.d.ts +0 -2
- package/dist/plugins/agents/agents.integration.test.d.ts.map +0 -1
- package/dist/plugins/agents/agents.integration.test.js +0 -830
- package/dist/plugins/agents/agents.integration.test.js.map +0 -1
- package/dist/plugins/agents/supervision.integration.test.d.ts +0 -2
- package/dist/plugins/agents/supervision.integration.test.d.ts.map +0 -1
- package/dist/plugins/agents/supervision.integration.test.js +0 -215
- package/dist/plugins/agents/supervision.integration.test.js.map +0 -1
- package/dist/plugins/context-compact/compaction-live.test.d.ts +0 -17
- package/dist/plugins/context-compact/compaction-live.test.d.ts.map +0 -1
- package/dist/plugins/context-compact/compaction-live.test.js +0 -177
- package/dist/plugins/context-compact/compaction-live.test.js.map +0 -1
- package/dist/plugins/context-compact/context-compact.integration.test.d.ts +0 -2
- package/dist/plugins/context-compact/context-compact.integration.test.d.ts.map +0 -1
- package/dist/plugins/context-compact/context-compact.integration.test.js +0 -364
- package/dist/plugins/context-compact/context-compact.integration.test.js.map +0 -1
- package/dist/plugins/context-compact/context-compactor.test.d.ts +0 -2
- package/dist/plugins/context-compact/context-compactor.test.d.ts.map +0 -1
- package/dist/plugins/context-compact/context-compactor.test.js +0 -858
- package/dist/plugins/context-compact/context-compactor.test.js.map +0 -1
- package/dist/plugins/context-compact/history-offloader.test.d.ts +0 -2
- package/dist/plugins/context-compact/history-offloader.test.d.ts.map +0 -1
- package/dist/plugins/context-compact/history-offloader.test.js +0 -77
- package/dist/plugins/context-compact/history-offloader.test.js.map +0 -1
- package/dist/plugins/filesystem/filesystem.integration.test.d.ts +0 -2
- package/dist/plugins/filesystem/filesystem.integration.test.d.ts.map +0 -1
- package/dist/plugins/filesystem/filesystem.integration.test.js +0 -447
- package/dist/plugins/filesystem/filesystem.integration.test.js.map +0 -1
- package/dist/plugins/filesystem/schema.d.ts +0 -7
- package/dist/plugins/filesystem/schema.d.ts.map +0 -1
- package/dist/plugins/filesystem/schema.js +0 -2
- package/dist/plugins/filesystem/schema.js.map +0 -1
- package/dist/plugins/limits-guard/limit-guard.test.d.ts +0 -2
- package/dist/plugins/limits-guard/limit-guard.test.d.ts.map +0 -1
- package/dist/plugins/limits-guard/limit-guard.test.js +0 -194
- package/dist/plugins/limits-guard/limit-guard.test.js.map +0 -1
- package/dist/plugins/limits-guard/limits-guard.integration.test.d.ts +0 -2
- package/dist/plugins/limits-guard/limits-guard.integration.test.d.ts.map +0 -1
- package/dist/plugins/limits-guard/limits-guard.integration.test.js +0 -887
- package/dist/plugins/limits-guard/limits-guard.integration.test.js.map +0 -1
- package/dist/plugins/llm-debug/llm-debug.integration.test.d.ts +0 -2
- package/dist/plugins/llm-debug/llm-debug.integration.test.d.ts.map +0 -1
- package/dist/plugins/llm-debug/llm-debug.integration.test.js +0 -157
- package/dist/plugins/llm-debug/llm-debug.integration.test.js.map +0 -1
- package/dist/plugins/mailbox/mailbox.integration.test.d.ts +0 -2
- package/dist/plugins/mailbox/mailbox.integration.test.d.ts.map +0 -1
- package/dist/plugins/mailbox/mailbox.integration.test.js +0 -678
- package/dist/plugins/mailbox/mailbox.integration.test.js.map +0 -1
- package/dist/plugins/resources/resources.integration.test.d.ts +0 -2
- package/dist/plugins/resources/resources.integration.test.d.ts.map +0 -1
- package/dist/plugins/resources/resources.integration.test.js +0 -62
- package/dist/plugins/resources/resources.integration.test.js.map +0 -1
- package/dist/plugins/result-eviction/result-eviction.integration.test.d.ts +0 -2
- package/dist/plugins/result-eviction/result-eviction.integration.test.d.ts.map +0 -1
- package/dist/plugins/result-eviction/result-eviction.integration.test.js +0 -294
- package/dist/plugins/result-eviction/result-eviction.integration.test.js.map +0 -1
- package/dist/plugins/services/pid-registry.test.d.ts +0 -2
- package/dist/plugins/services/pid-registry.test.d.ts.map +0 -1
- package/dist/plugins/services/pid-registry.test.js +0 -161
- package/dist/plugins/services/pid-registry.test.js.map +0 -1
- package/dist/plugins/services/services.integration.test.d.ts +0 -2
- package/dist/plugins/services/services.integration.test.d.ts.map +0 -1
- package/dist/plugins/services/services.integration.test.js +0 -1057
- package/dist/plugins/services/services.integration.test.js.map +0 -1
- package/dist/plugins/session-lifecycle/session-lifecycle.integration.test.d.ts +0 -2
- package/dist/plugins/session-lifecycle/session-lifecycle.integration.test.d.ts.map +0 -1
- package/dist/plugins/session-lifecycle/session-lifecycle.integration.test.js +0 -498
- package/dist/plugins/session-lifecycle/session-lifecycle.integration.test.js.map +0 -1
- package/dist/plugins/session-stats/plugin.test.d.ts +0 -2
- package/dist/plugins/session-stats/plugin.test.d.ts.map +0 -1
- package/dist/plugins/session-stats/plugin.test.js +0 -145
- package/dist/plugins/session-stats/plugin.test.js.map +0 -1
- package/dist/plugins/shell/shell.integration.test.d.ts +0 -2
- package/dist/plugins/shell/shell.integration.test.d.ts.map +0 -1
- package/dist/plugins/shell/shell.integration.test.js +0 -234
- package/dist/plugins/shell/shell.integration.test.js.map +0 -1
- package/dist/plugins/shell/shell.test.d.ts +0 -2
- package/dist/plugins/shell/shell.test.d.ts.map +0 -1
- package/dist/plugins/shell/shell.test.js +0 -236
- package/dist/plugins/shell/shell.test.js.map +0 -1
- package/dist/plugins/skills/discovery.test.d.ts +0 -2
- package/dist/plugins/skills/discovery.test.d.ts.map +0 -1
- package/dist/plugins/skills/discovery.test.js +0 -312
- package/dist/plugins/skills/discovery.test.js.map +0 -1
- package/dist/plugins/skills/skills.integration.test.d.ts +0 -2
- package/dist/plugins/skills/skills.integration.test.d.ts.map +0 -1
- package/dist/plugins/skills/skills.integration.test.js +0 -475
- package/dist/plugins/skills/skills.integration.test.js.map +0 -1
- package/dist/plugins/todo/todo.integration.test.d.ts +0 -2
- package/dist/plugins/todo/todo.integration.test.d.ts.map +0 -1
- package/dist/plugins/todo/todo.integration.test.js +0 -605
- package/dist/plugins/todo/todo.integration.test.js.map +0 -1
- package/dist/plugins/uploads/preprocessors/image-classifier.test.d.ts +0 -2
- package/dist/plugins/uploads/preprocessors/image-classifier.test.d.ts.map +0 -1
- package/dist/plugins/uploads/preprocessors/image-classifier.test.js +0 -113
- package/dist/plugins/uploads/preprocessors/image-classifier.test.js.map +0 -1
- package/dist/plugins/uploads/uploads.integration.test.d.ts +0 -2
- package/dist/plugins/uploads/uploads.integration.test.d.ts.map +0 -1
- package/dist/plugins/uploads/uploads.integration.test.js +0 -639
- package/dist/plugins/uploads/uploads.integration.test.js.map +0 -1
- package/dist/plugins/user-chat/user-chat.integration.test.d.ts +0 -2
- package/dist/plugins/user-chat/user-chat.integration.test.d.ts.map +0 -1
- package/dist/plugins/user-chat/user-chat.integration.test.js +0 -754
- package/dist/plugins/user-chat/user-chat.integration.test.js.map +0 -1
- package/dist/plugins/workers/workers.integration.test.d.ts +0 -2
- package/dist/plugins/workers/workers.integration.test.d.ts.map +0 -1
- package/dist/plugins/workers/workers.integration.test.js +0 -629
- package/dist/plugins/workers/workers.integration.test.js.map +0 -1
- package/dist/prompts/macros.test.d.ts +0 -2
- package/dist/prompts/macros.test.d.ts.map +0 -1
- package/dist/prompts/macros.test.js +0 -80
- package/dist/prompts/macros.test.js.map +0 -1
- package/dist/testing/test-harness.test.d.ts +0 -2
- package/dist/testing/test-harness.test.d.ts.map +0 -1
- package/dist/testing/test-harness.test.js +0 -92
- package/dist/testing/test-harness.test.js.map +0 -1
- package/dist/transport/http/routes/rpc.integration.test.d.ts +0 -2
- package/dist/transport/http/routes/rpc.integration.test.d.ts.map +0 -1
- package/dist/transport/http/routes/rpc.integration.test.js +0 -189
- package/dist/transport/http/routes/rpc.integration.test.js.map +0 -1
- package/dist/transport/http/routes/rpc.test.d.ts +0 -2
- package/dist/transport/http/routes/rpc.test.d.ts.map +0 -1
- package/dist/transport/http/routes/rpc.test.js +0 -316
- package/dist/transport/http/routes/rpc.test.js.map +0 -1
- package/src/config.test.ts +0 -174
- package/src/core/agent-loop.integration.test.ts +0 -503
- package/src/core/agents/agent-config.test.ts +0 -240
- package/src/core/agents/agent-shutdown.test.ts +0 -236
- package/src/core/agents/agent.test.ts +0 -387
- package/src/core/agents/communicator.ts +0 -16
- package/src/core/agents/handler-events.test.ts +0 -167
- package/src/core/agents/response-sanitizer.test.ts +0 -137
- package/src/core/error-recovery.integration.test.ts +0 -343
- package/src/core/event-sourcing.integration.test.ts +0 -191
- package/src/core/events/file.test.ts +0 -436
- package/src/core/events/memory.test.ts +0 -741
- package/src/core/image/image-processor.test.ts +0 -218
- package/src/core/image/vips-resizer.test.ts +0 -388
- package/src/core/llm/anthropic.test.ts +0 -546
- package/src/core/llm/cache-breakpoints.test.ts +0 -85
- package/src/core/llm/cache-live.test.ts +0 -155
- package/src/core/llm/logger.test.ts +0 -270
- package/src/core/llm/message-sanitization.test.ts +0 -217
- package/src/core/llm/mock.test.ts +0 -402
- package/src/core/llm/openrouter-mapping.test.ts +0 -210
- package/src/core/llm/openrouter.test.ts +0 -499
- package/src/core/llm/provider-integration.test.ts +0 -408
- package/src/core/llm/routing-provider.test.ts +0 -113
- package/src/core/llm/snapshot-middleware.test.ts +0 -168
- package/src/core/multi-agent.integration.test.ts +0 -340
- package/src/core/plugin-hooks.integration.test.ts +0 -568
- package/src/core/session-lifecycle.integration.test.ts +0 -202
- package/src/core/sessions/fork-utils.test.ts +0 -158
- package/src/core/sessions/session-overrides.integration.test.ts +0 -210
- package/src/core/sessions/session.test.ts +0 -1736
- package/src/core/tools/executor.test.ts +0 -161
- package/src/lib/logger/console.test.ts +0 -348
- package/src/lib/never.ts +0 -3
- package/src/lib/utils/concurrency.test.ts +0 -169
- package/src/plugins/agent-status/agent-status.test.ts +0 -164
- package/src/plugins/agents/agents.integration.test.ts +0 -976
- package/src/plugins/agents/supervision.integration.test.ts +0 -249
- package/src/plugins/context-compact/compaction-live.test.ts +0 -221
- package/src/plugins/context-compact/context-compact.integration.test.ts +0 -418
- package/src/plugins/context-compact/context-compactor.test.ts +0 -1036
- package/src/plugins/context-compact/history-offloader.test.ts +0 -100
- package/src/plugins/filesystem/filesystem.integration.test.ts +0 -529
- package/src/plugins/filesystem/schema.ts +0 -6
- package/src/plugins/limits-guard/limit-guard.test.ts +0 -253
- package/src/plugins/limits-guard/limits-guard.integration.test.ts +0 -1012
- package/src/plugins/llm-debug/llm-debug.integration.test.ts +0 -192
- package/src/plugins/mailbox/mailbox.integration.test.ts +0 -794
- package/src/plugins/resources/resources.integration.test.ts +0 -68
- package/src/plugins/result-eviction/result-eviction.integration.test.ts +0 -332
- package/src/plugins/services/pid-registry.test.ts +0 -180
- package/src/plugins/services/services.integration.test.ts +0 -1223
- package/src/plugins/session-lifecycle/session-lifecycle.integration.test.ts +0 -639
- package/src/plugins/session-stats/plugin.test.ts +0 -160
- package/src/plugins/shell/shell.integration.test.ts +0 -273
- package/src/plugins/shell/shell.test.ts +0 -314
- package/src/plugins/skills/discovery.test.ts +0 -395
- package/src/plugins/skills/skills.integration.test.ts +0 -580
- package/src/plugins/todo/todo.integration.test.ts +0 -687
- package/src/plugins/uploads/preprocessors/image-classifier.test.ts +0 -142
- package/src/plugins/uploads/uploads.integration.test.ts +0 -831
- package/src/plugins/user-chat/user-chat.integration.test.ts +0 -893
- package/src/plugins/workers/workers.integration.test.ts +0 -778
- package/src/prompts/macros.test.ts +0 -107
- package/src/testing/test-harness.test.ts +0 -114
- package/src/transport/http/routes/rpc.integration.test.ts +0 -243
- package/src/transport/http/routes/rpc.test.ts +0 -372
|
@@ -10,8 +10,8 @@
|
|
|
10
10
|
import { join } from 'node:path'
|
|
11
11
|
import z4 from 'zod/v4'
|
|
12
12
|
import { COMMUNICATOR_ROLE, ORCHESTRATOR_ROLE } from '~/core/agents/agent-roles.js'
|
|
13
|
-
import
|
|
14
|
-
import { generateAgentId } from '~/core/agents/schema.js'
|
|
13
|
+
import { parseAgentWakeKey, parsePluginWakeKey } from '~/core/wake-key.js'
|
|
14
|
+
import { AgentId, generateAgentId } from '~/core/agents/schema.js'
|
|
15
15
|
import { agentEvents } from '~/core/agents/state.js'
|
|
16
16
|
import { type DomainError, PresetErrors, SessionErrors, ValidationErrors } from '~/core/errors.js'
|
|
17
17
|
import { withSessionId } from '~/core/events/test-helpers.js'
|
|
@@ -19,18 +19,22 @@ import type { DomainEvent } from '~/core/events/types.js'
|
|
|
19
19
|
import type { FileStore } from '~/core/file-store/types.js'
|
|
20
20
|
import type { LLMLogger } from '~/core/llm/logger.js'
|
|
21
21
|
import type { LLMProvider } from '~/core/llm/provider.js'
|
|
22
|
-
import
|
|
22
|
+
import { DEFAULT_PLUGIN_ORDER } from '~/core/plugins/plugin-builder.js'
|
|
23
|
+
import type { CallerContext, ConfiguredPlugin, ManagerMethodContext, PluginDefinition, SessionCloseReason } from '~/core/plugins/plugin-builder.js'
|
|
24
|
+
import { AGENT_CALLER } from '~/core/plugins/plugin-builder.js'
|
|
23
25
|
import type { Preset } from '~/core/preset/index.js'
|
|
24
26
|
import { knownDefinitionNames, unknownOverrideTargets } from '~/core/preset/overrides.js'
|
|
25
|
-
import type {
|
|
26
|
-
import { generateSessionId } from '~/core/sessions/schema.js'
|
|
27
|
+
import type { SessionMetadata } from '~/core/sessions/schema.js'
|
|
28
|
+
import { generateSessionId, isValidSessionId, SessionId } from '~/core/sessions/schema.js'
|
|
27
29
|
import type { SessionCreatedEvent, SessionOverridesPatch } from '~/core/sessions/state.js'
|
|
28
30
|
import { checkRecoveryNeeded, isSessionCreatedEvent, reconstructSessionState, sessionEvents } from '~/core/sessions/state.js'
|
|
29
31
|
import type { ToolExecutor } from '~/core/tools'
|
|
30
|
-
import {
|
|
32
|
+
import type { ArchiveLimitOverrides } from '~/lib/archive/index.js'
|
|
31
33
|
import type { Logger } from '~/lib/logger/logger.js'
|
|
34
|
+
import { createSessionLogger } from '~/lib/logger/session-log.js'
|
|
32
35
|
import { TeeLogger } from '~/lib/logger/tee.js'
|
|
33
36
|
import type { Platform } from '~/platform/index.js'
|
|
37
|
+
import { isLiveScheduler } from '~/platform/index.js'
|
|
34
38
|
import type { Result } from '~/lib/utils/result.js'
|
|
35
39
|
import { Err, Ok } from '~/lib/utils/result.js'
|
|
36
40
|
import type { SpawnableAgentInfo } from '~/plugins/agents/index.js'
|
|
@@ -44,7 +48,8 @@ import { EventStore } from '../events/event-store.js'
|
|
|
44
48
|
import { createApplyEvent } from './apply-event.js'
|
|
45
49
|
import { rewriteEventsForFork } from './fork-utils.js'
|
|
46
50
|
import { SessionStore } from './session-store.js'
|
|
47
|
-
import { Session, type UserOutputCallback } from './session.js'
|
|
51
|
+
import { Session, type SessionReopenRegistration, type UserOutputCallback } from './session.js'
|
|
52
|
+
import { SessionRuntimeActivityController } from './runtime-activity.js'
|
|
48
53
|
|
|
49
54
|
// ============================================================================
|
|
50
55
|
// Errors
|
|
@@ -77,21 +82,48 @@ export interface SessionManagerOptions {
|
|
|
77
82
|
dataFileStore: FileStore
|
|
78
83
|
onUserOutput?: UserOutputCallback
|
|
79
84
|
preprocessorRegistry?: PreprocessorRegistry
|
|
85
|
+
uploadArchiveLimits?: ArchiveLimitOverrides
|
|
86
|
+
resourceArchiveLimits?: ArchiveLimitOverrides
|
|
80
87
|
llmLogger?: LLMLogger
|
|
81
88
|
portPool?: PortPool
|
|
82
89
|
pidRegistry?: ServicePidRegistry
|
|
83
90
|
/** Host-environment adapters (filesystem, process). */
|
|
84
91
|
platform: Platform
|
|
85
92
|
systemPlugins?: readonly PluginDefinition<string, any, any, any, any>[]
|
|
93
|
+
/** Evict resident runtimes after this idle period. Absent or zero disables eviction. */
|
|
94
|
+
sessionIdleTimeoutMs?: number
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
interface SessionCacheEntry {
|
|
98
|
+
state: 'loading' | 'ready' | 'evicting'
|
|
99
|
+
promise: Promise<Session>
|
|
100
|
+
activity: SessionRuntimeActivityController
|
|
101
|
+
lastAccessAt: number
|
|
102
|
+
unloadPromise?: Promise<void>
|
|
103
|
+
listenerCleanup?: () => void
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
/** Why the manager is dropping a resident runtime — finer-grained than what plugins see. */
|
|
107
|
+
type RuntimeDisposalCause = 'idle' | 'closed' | 'disposed' | 'shutdown'
|
|
108
|
+
|
|
109
|
+
// Both parking causes map to `evicted`: the session survives and the next access rebuilds its runtime.
|
|
110
|
+
const RUNTIME_DISPOSAL_CLOSE_REASON: Record<RuntimeDisposalCause, SessionCloseReason> = {
|
|
111
|
+
idle: 'evicted',
|
|
112
|
+
disposed: 'evicted',
|
|
113
|
+
closed: 'closed',
|
|
114
|
+
shutdown: 'shutdown',
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
export interface AcquiredSessionLease {
|
|
118
|
+
session: Session
|
|
119
|
+
release: () => void
|
|
86
120
|
}
|
|
87
121
|
|
|
88
122
|
/**
|
|
89
123
|
* SessionManager manages session lifecycle and caching.
|
|
90
124
|
*/
|
|
91
125
|
export class SessionManager {
|
|
92
|
-
private readonly sessions = new Map<SessionId,
|
|
93
|
-
/** Unsubscribe functions for session event listeners, keyed by sessionId */
|
|
94
|
-
private readonly sessionListenerCleanup = new Map<SessionId, () => void>()
|
|
126
|
+
private readonly sessions = new Map<SessionId, SessionCacheEntry>()
|
|
95
127
|
/** Manager-level methods collected from plugin definitions across all presets */
|
|
96
128
|
private readonly managerMethods: Map<string, {
|
|
97
129
|
input: z4.ZodType
|
|
@@ -109,13 +141,25 @@ export class SessionManager {
|
|
|
109
141
|
private readonly dataFileStore: FileStore
|
|
110
142
|
private readonly onUserOutput?: UserOutputCallback
|
|
111
143
|
private readonly preprocessorRegistry?: PreprocessorRegistry
|
|
144
|
+
private readonly uploadArchiveLimits?: ArchiveLimitOverrides
|
|
145
|
+
private readonly resourceArchiveLimits?: ArchiveLimitOverrides
|
|
112
146
|
private readonly llmLogger?: LLMLogger
|
|
113
147
|
private readonly portPool?: PortPool
|
|
114
148
|
private readonly pidRegistry?: ServicePidRegistry
|
|
115
149
|
private readonly platform: Platform
|
|
116
150
|
private readonly systemPlugins: readonly PluginDefinition<string, any, any, any, any>[]
|
|
151
|
+
private readonly sessionIdleTimeoutMs: number
|
|
152
|
+
private readonly evictionSweepTimer?: ReturnType<typeof setInterval>
|
|
153
|
+
private cacheHits = 0
|
|
154
|
+
private cacheMisses = 0
|
|
155
|
+
private cacheEvictions = 0
|
|
156
|
+
/** Set by shutdown(). Also fences wakes: one armed before it must not reload a session after it. */
|
|
157
|
+
private shuttingDown = false
|
|
117
158
|
|
|
118
159
|
constructor(options: SessionManagerOptions) {
|
|
160
|
+
if (options.sessionIdleTimeoutMs !== undefined && (!Number.isSafeInteger(options.sessionIdleTimeoutMs) || options.sessionIdleTimeoutMs < 0)) {
|
|
161
|
+
throw new Error(`Invalid sessionIdleTimeoutMs: ${options.sessionIdleTimeoutMs}`)
|
|
162
|
+
}
|
|
119
163
|
this.eventStore = options.eventStore
|
|
120
164
|
this.llmProvider = options.llmProvider
|
|
121
165
|
this.llmProviders = options.llmProviders ?? new Map()
|
|
@@ -126,12 +170,35 @@ export class SessionManager {
|
|
|
126
170
|
this.dataFileStore = options.dataFileStore
|
|
127
171
|
this.onUserOutput = options.onUserOutput
|
|
128
172
|
this.preprocessorRegistry = options.preprocessorRegistry
|
|
173
|
+
this.uploadArchiveLimits = options.uploadArchiveLimits
|
|
174
|
+
this.resourceArchiveLimits = options.resourceArchiveLimits
|
|
129
175
|
this.llmLogger = options.llmLogger
|
|
130
176
|
this.portPool = options.portPool
|
|
131
177
|
this.pidRegistry = options.pidRegistry
|
|
132
178
|
this.platform = options.platform
|
|
133
179
|
this.systemPlugins = options.systemPlugins ?? []
|
|
180
|
+
this.sessionIdleTimeoutMs = options.sessionIdleTimeoutMs ?? 0
|
|
134
181
|
this.managerMethods = this.collectManagerMethods()
|
|
182
|
+
if (this.sessionIdleTimeoutMs > 0) {
|
|
183
|
+
const sweepIntervalMs = Math.min(this.sessionIdleTimeoutMs, 60_000)
|
|
184
|
+
this.evictionSweepTimer = setInterval(() => {
|
|
185
|
+
void this.evictIdleSessions()
|
|
186
|
+
}, sweepIntervalMs)
|
|
187
|
+
this.evictionSweepTimer.unref()
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
// A live scheduler has nowhere else to deliver. Hosts that wake out-of-band
|
|
191
|
+
// (a Durable Object alarm) call dispatchWake() from their own handler.
|
|
192
|
+
const scheduler = this.platform.scheduler
|
|
193
|
+
if (isLiveScheduler(scheduler)) {
|
|
194
|
+
scheduler.onWake(async (key) => {
|
|
195
|
+
try {
|
|
196
|
+
await this.dispatchWake(key)
|
|
197
|
+
} catch (error) {
|
|
198
|
+
this.logger.error('Scheduler wake dispatch failed', error instanceof Error ? error : new Error(String(error)), { key })
|
|
199
|
+
}
|
|
200
|
+
})
|
|
201
|
+
}
|
|
135
202
|
}
|
|
136
203
|
|
|
137
204
|
/** Expose platform adapters (used by Session for building contexts). */
|
|
@@ -139,6 +206,76 @@ export class SessionManager {
|
|
|
139
206
|
return this.platform
|
|
140
207
|
}
|
|
141
208
|
|
|
209
|
+
/**
|
|
210
|
+
* Deliver a scheduler wake that has come due.
|
|
211
|
+
*
|
|
212
|
+
* The host's entry point back into the SDK — on Cloudflare, called from
|
|
213
|
+
* `alarm()` in an isolate that never armed the wake. SessionManager owns it
|
|
214
|
+
* because it is the only thing that can turn a session id back into a live
|
|
215
|
+
* session, so the key alone is enough input.
|
|
216
|
+
*
|
|
217
|
+
* Two vocabularies route here: `agent:` wakes re-enter the agent loop,
|
|
218
|
+
* `plugin:` wakes call a plugin method. Anything else is a quiet no-op, and so
|
|
219
|
+
* is a key naming a session, agent or plugin that is gone — wakes outlive what
|
|
220
|
+
* they point at. Only genuinely unexpected failures (event store IO) throw, so
|
|
221
|
+
* a host that retries alarms retries those and only those.
|
|
222
|
+
*/
|
|
223
|
+
async dispatchWake(key: string): Promise<void> {
|
|
224
|
+
const agentWake = parseAgentWakeKey(key)
|
|
225
|
+
if (agentWake) {
|
|
226
|
+
await this.withWakeTarget(key, agentWake.sessionId, async (session) => {
|
|
227
|
+
await session.getAgent(agentWake.agentId)?.deliverWake(agentWake.kind)
|
|
228
|
+
})
|
|
229
|
+
return
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
const pluginWake = parsePluginWakeKey(key)
|
|
233
|
+
if (pluginWake) {
|
|
234
|
+
await this.withWakeTarget(key, pluginWake.sessionId, async (session) => {
|
|
235
|
+
const result = await session.callPluginMethod(
|
|
236
|
+
`${pluginWake.pluginName}.${pluginWake.method}`,
|
|
237
|
+
pluginWake.agentId === undefined ? {} : { agentId: pluginWake.agentId },
|
|
238
|
+
pluginWake.agentId,
|
|
239
|
+
AGENT_CALLER,
|
|
240
|
+
)
|
|
241
|
+
// A preset that no longer registers the plugin lands here, same as a
|
|
242
|
+
// missing agent does: the wake points at something that is gone.
|
|
243
|
+
if (!result.ok) this.logger.debug('Scheduler wake method rejected', { key, error: result.error.type })
|
|
244
|
+
})
|
|
245
|
+
return
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
this.logger.debug('Ignoring unrecognized scheduler wake key', { key })
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
/** Run `deliver` against the session a due wake names, under a runtime lease. */
|
|
252
|
+
private async withWakeTarget(key: string, sessionId: SessionId, deliver: (session: Session) => Promise<void>): Promise<void> {
|
|
253
|
+
// Nothing armed before shutdown may load a session back in afterwards.
|
|
254
|
+
if (this.shuttingDown) return
|
|
255
|
+
// Nor may a wake that lands mid-teardown rebuild what is being torn down —
|
|
256
|
+
// getSession() would wait out the unload and reload. onSessionReady re-arms.
|
|
257
|
+
const resident = this.sessions.get(sessionId)
|
|
258
|
+
if (resident && (resident.state === 'evicting' || resident.activity.getSnapshot().state !== 'ready')) return
|
|
259
|
+
|
|
260
|
+
const sessionResult = await this.getSession(sessionId)
|
|
261
|
+
if (!sessionResult.ok) {
|
|
262
|
+
this.logger.debug('Scheduler wake for a session that no longer loads', { key, error: sessionResult.error.type })
|
|
263
|
+
return
|
|
264
|
+
}
|
|
265
|
+
const session = sessionResult.value
|
|
266
|
+
// A closed session's log is sealed; re-entering it would only fail to write.
|
|
267
|
+
if (session.state.status === 'closed') return
|
|
268
|
+
|
|
269
|
+
// Lease the delivery, not the delay before it — an idle session stays evictable while it waits.
|
|
270
|
+
const release = session.tryAcquireRuntimeLease(`wake:${key}`)
|
|
271
|
+
if (!release) return
|
|
272
|
+
try {
|
|
273
|
+
await deliver(session)
|
|
274
|
+
} finally {
|
|
275
|
+
release()
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
|
|
142
279
|
/**
|
|
143
280
|
* Create a new session with the given preset.
|
|
144
281
|
*/
|
|
@@ -146,6 +283,7 @@ export class SessionManager {
|
|
|
146
283
|
presetId: string,
|
|
147
284
|
options?: { workspaceDir?: string; sessionId?: string; overrides?: SessionOverridesPatch },
|
|
148
285
|
): Promise<Result<Session, DomainError>> {
|
|
286
|
+
if (this.shuttingDown) return Err(ValidationErrors.invalid('Session manager is shutting down'))
|
|
149
287
|
const preset = this.presets.get(presetId)
|
|
150
288
|
if (!preset) {
|
|
151
289
|
return Err(PresetErrors.notFound(presetId))
|
|
@@ -160,7 +298,12 @@ export class SessionManager {
|
|
|
160
298
|
}
|
|
161
299
|
}
|
|
162
300
|
|
|
163
|
-
|
|
301
|
+
// Validate before anything derives a path from it — the id reaches join() for the
|
|
302
|
+
// session dir, the event log and the file logger, and path.join collapses `..`.
|
|
303
|
+
if (options?.sessionId !== undefined && !isValidSessionId(options.sessionId)) {
|
|
304
|
+
return Err(ValidationErrors.invalid(`Invalid session id: ${JSON.stringify(options.sessionId)}`))
|
|
305
|
+
}
|
|
306
|
+
const sessionId = options?.sessionId ? SessionId(options.sessionId) : generateSessionId()
|
|
164
307
|
// First orchestrator gets seq 1
|
|
165
308
|
const orchestratorId = generateAgentId(ORCHESTRATOR_ROLE, 1)
|
|
166
309
|
|
|
@@ -229,25 +372,40 @@ export class SessionManager {
|
|
|
229
372
|
))
|
|
230
373
|
}
|
|
231
374
|
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
375
|
+
if (this.sessions.has(sessionId)) return Err(SessionErrors.alreadyExists(String(sessionId)))
|
|
376
|
+
const activity = new SessionRuntimeActivityController()
|
|
377
|
+
let entry: SessionCacheEntry
|
|
378
|
+
const creationPromise = Promise.resolve().then(async () => {
|
|
379
|
+
if (await this.eventStore.exists(sessionId)) throw new SessionLoadError(SessionErrors.alreadyExists(String(sessionId)))
|
|
380
|
+
await this.eventStore.appendBatch(sessionId, events)
|
|
381
|
+
const plugins = this.buildPlugins(preset)
|
|
382
|
+
const composedReducer = createApplyEvent(plugins)
|
|
383
|
+
const state = reconstructSessionState(events, composedReducer)
|
|
384
|
+
if (!state) throw new SessionLoadError(ValidationErrors.invalid('Failed to reconstruct session'))
|
|
385
|
+
const store = new SessionStore(sessionId, this.eventStore, state, composedReducer)
|
|
386
|
+
return this.createSessionInstance(store, preset, plugins, entry)
|
|
387
|
+
})
|
|
388
|
+
entry = {
|
|
389
|
+
state: 'loading',
|
|
390
|
+
promise: creationPromise,
|
|
391
|
+
activity,
|
|
392
|
+
lastAccessAt: performance.now(),
|
|
243
393
|
}
|
|
394
|
+
this.sessions.set(sessionId, entry)
|
|
244
395
|
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
396
|
+
let session: Session
|
|
397
|
+
try {
|
|
398
|
+
session = await creationPromise
|
|
399
|
+
if (this.sessions.get(sessionId) === entry && entry.state === 'loading') {
|
|
400
|
+
entry.state = 'ready'
|
|
401
|
+
entry.lastAccessAt = performance.now()
|
|
402
|
+
}
|
|
403
|
+
} catch (error) {
|
|
404
|
+
if (this.sessions.get(sessionId) === entry) this.sessions.delete(sessionId)
|
|
405
|
+
entry.listenerCleanup?.()
|
|
406
|
+
if (error instanceof SessionLoadError) return Err(error.domainError)
|
|
407
|
+
throw error
|
|
408
|
+
}
|
|
251
409
|
|
|
252
410
|
this.logger.info('Session created', {
|
|
253
411
|
sessionId,
|
|
@@ -266,8 +424,10 @@ export class SessionManager {
|
|
|
266
424
|
sourceSessionId: SessionId,
|
|
267
425
|
eventIndex: number,
|
|
268
426
|
): Promise<Result<Session, DomainError>> {
|
|
427
|
+
if (this.shuttingDown) return Err(ValidationErrors.invalid('Session manager is shutting down'))
|
|
269
428
|
// Load source events
|
|
270
429
|
const sourceEvents = await this.eventStore.load(sourceSessionId)
|
|
430
|
+
if (this.shuttingDown) return Err(ValidationErrors.invalid('Session manager is shutting down'))
|
|
271
431
|
if (sourceEvents.length === 0) {
|
|
272
432
|
return Err(SessionErrors.notFound(String(sourceSessionId)))
|
|
273
433
|
}
|
|
@@ -317,43 +477,49 @@ export class SessionManager {
|
|
|
317
477
|
})
|
|
318
478
|
}
|
|
319
479
|
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
480
|
+
const activity = new SessionRuntimeActivityController()
|
|
481
|
+
let entry: SessionCacheEntry
|
|
482
|
+
const forkPromise = Promise.resolve().then(async () => {
|
|
483
|
+
await this.eventStore.appendBatch(newSessionId, forkedEvents)
|
|
484
|
+
const plugins = this.buildPlugins(preset)
|
|
485
|
+
const composedReducer = createApplyEvent(plugins)
|
|
486
|
+
const state = reconstructSessionState(forkedEvents, composedReducer)
|
|
487
|
+
if (!state) throw new SessionLoadError(ValidationErrors.invalid('Failed to reconstruct forked session'))
|
|
488
|
+
const store = new SessionStore(newSessionId, this.eventStore, state, composedReducer)
|
|
489
|
+
const recoveryData = checkRecoveryNeeded(state)
|
|
490
|
+
if (recoveryData) {
|
|
491
|
+
await store.emit(withSessionId(
|
|
492
|
+
newSessionId,
|
|
493
|
+
sessionEvents.create('session_restarted', {
|
|
494
|
+
resetAgentIds: recoveryData.resetAgentIds,
|
|
495
|
+
clearedToolAgentIds: recoveryData.clearedToolAgentIds,
|
|
496
|
+
}),
|
|
497
|
+
))
|
|
498
|
+
}
|
|
499
|
+
return this.createSessionInstance(store, preset, plugins, entry)
|
|
500
|
+
})
|
|
501
|
+
entry = {
|
|
502
|
+
state: 'loading',
|
|
503
|
+
promise: forkPromise,
|
|
504
|
+
activity,
|
|
505
|
+
lastAccessAt: performance.now(),
|
|
331
506
|
}
|
|
507
|
+
this.sessions.set(newSessionId, entry)
|
|
332
508
|
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
resetAgentIds: recoveryData.resetAgentIds,
|
|
343
|
-
clearedToolAgentIds: recoveryData.clearedToolAgentIds,
|
|
344
|
-
}),
|
|
345
|
-
))
|
|
509
|
+
let session: Session
|
|
510
|
+
try {
|
|
511
|
+
session = await forkPromise
|
|
512
|
+
if (this.sessions.get(newSessionId) === entry && entry.state === 'loading') entry.state = 'ready'
|
|
513
|
+
} catch (error) {
|
|
514
|
+
if (this.sessions.get(newSessionId) === entry) this.sessions.delete(newSessionId)
|
|
515
|
+
entry.listenerCleanup?.()
|
|
516
|
+
if (error instanceof SessionLoadError) return Err(error.domainError)
|
|
517
|
+
throw error
|
|
346
518
|
}
|
|
347
519
|
|
|
348
|
-
// Create session instance (auto-start services run via onSessionReady)
|
|
349
|
-
const session = await this.createSessionInstance(store, preset, plugins)
|
|
350
|
-
|
|
351
520
|
// Check for pending agents
|
|
352
521
|
session.checkPendingAgents()
|
|
353
522
|
|
|
354
|
-
// Cache session
|
|
355
|
-
this.sessions.set(newSessionId, Promise.resolve(session))
|
|
356
|
-
|
|
357
523
|
this.logger.info('Session forked', {
|
|
358
524
|
sourceSessionId,
|
|
359
525
|
newSessionId,
|
|
@@ -369,40 +535,59 @@ export class SessionManager {
|
|
|
369
535
|
async getSession(
|
|
370
536
|
sessionId: SessionId,
|
|
371
537
|
): Promise<Result<Session, DomainError>> {
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
throw error
|
|
538
|
+
while (true) {
|
|
539
|
+
if (this.shuttingDown) return Err(ValidationErrors.invalid('Session manager is shutting down'))
|
|
540
|
+
let entry = this.sessions.get(sessionId)
|
|
541
|
+
if (entry?.state === 'evicting') {
|
|
542
|
+
await entry.unloadPromise
|
|
543
|
+
continue
|
|
544
|
+
}
|
|
545
|
+
if (entry?.state === 'ready' && entry.activity.getSnapshot().state !== 'ready') {
|
|
546
|
+
const session = await entry.promise
|
|
547
|
+
await this.beginCacheEntryDisposal(sessionId, entry, session, 'disposed')
|
|
548
|
+
continue
|
|
384
549
|
}
|
|
385
|
-
}
|
|
386
550
|
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
551
|
+
if (entry) {
|
|
552
|
+
this.cacheHits++
|
|
553
|
+
entry.lastAccessAt = performance.now()
|
|
554
|
+
} else {
|
|
555
|
+
this.cacheMisses++
|
|
556
|
+
const activity = new SessionRuntimeActivityController()
|
|
557
|
+
let loadingEntry: SessionCacheEntry
|
|
558
|
+
const promise = Promise.resolve().then(() => this.loadSession(sessionId, loadingEntry))
|
|
559
|
+
loadingEntry = {
|
|
560
|
+
state: 'loading',
|
|
561
|
+
activity,
|
|
562
|
+
lastAccessAt: performance.now(),
|
|
563
|
+
promise,
|
|
564
|
+
}
|
|
565
|
+
entry = loadingEntry
|
|
566
|
+
this.sessions.set(sessionId, entry)
|
|
567
|
+
}
|
|
390
568
|
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
569
|
+
try {
|
|
570
|
+
const session = await entry.promise
|
|
571
|
+
if (this.sessions.get(sessionId) === entry && entry.state === 'loading') {
|
|
572
|
+
if (session.state.status === 'closed') this.sessions.delete(sessionId)
|
|
573
|
+
else {
|
|
574
|
+
entry.state = 'ready'
|
|
575
|
+
entry.lastAccessAt = performance.now()
|
|
576
|
+
}
|
|
577
|
+
}
|
|
578
|
+
return Ok(session)
|
|
579
|
+
} catch (error) {
|
|
580
|
+
if (this.sessions.get(sessionId) === entry) this.sessions.delete(sessionId)
|
|
581
|
+
if (error instanceof SessionLoadError) return Err(error.domainError)
|
|
582
|
+
throw error
|
|
397
583
|
}
|
|
398
|
-
throw error
|
|
399
584
|
}
|
|
400
585
|
}
|
|
401
586
|
|
|
402
587
|
/**
|
|
403
588
|
* Internal session loading - throws SessionLoadError on domain errors.
|
|
404
589
|
*/
|
|
405
|
-
private async loadSession(sessionId: SessionId): Promise<Session> {
|
|
590
|
+
private async loadSession(sessionId: SessionId, entry: SessionCacheEntry): Promise<Session> {
|
|
406
591
|
// We need to peek at events first to determine the preset, so we can build plugins
|
|
407
592
|
// and compose the reducer before loading the store
|
|
408
593
|
const events = await this.eventStore.load(sessionId)
|
|
@@ -425,7 +610,7 @@ export class SessionManager {
|
|
|
425
610
|
const composedReducer = createApplyEvent(plugins)
|
|
426
611
|
|
|
427
612
|
// Load store with composed reducer
|
|
428
|
-
const store = await SessionStore.
|
|
613
|
+
const store = await SessionStore.fromEvents(sessionId, this.eventStore, events, composedReducer)
|
|
429
614
|
if (!store) {
|
|
430
615
|
throw new SessionLoadError(SessionErrors.notFound(String(sessionId)))
|
|
431
616
|
}
|
|
@@ -434,11 +619,9 @@ export class SessionManager {
|
|
|
434
619
|
|
|
435
620
|
// Don't cache closed sessions
|
|
436
621
|
if (state.status === 'closed') {
|
|
437
|
-
// Remove from cache since we don't cache closed sessions
|
|
438
|
-
this.sessions.delete(sessionId)
|
|
439
622
|
// Skip onSessionReady hooks — closed sessions are immutable, firing hooks
|
|
440
623
|
// would emit events to a sealed event log on every read / restart.
|
|
441
|
-
return await this.createSessionInstance(store, preset, plugins, { skipReadyHooks: true })
|
|
624
|
+
return await this.createSessionInstance(store, preset, plugins, entry, { skipReadyHooks: true })
|
|
442
625
|
}
|
|
443
626
|
|
|
444
627
|
// Check if recovery is needed after restart
|
|
@@ -460,7 +643,7 @@ export class SessionManager {
|
|
|
460
643
|
}
|
|
461
644
|
|
|
462
645
|
// Create session (auto-start services run via onSessionReady)
|
|
463
|
-
const session = await this.createSessionInstance(store, preset, plugins)
|
|
646
|
+
const session = await this.createSessionInstance(store, preset, plugins, entry)
|
|
464
647
|
|
|
465
648
|
// Check for pending agents
|
|
466
649
|
session.checkPendingAgents()
|
|
@@ -482,10 +665,55 @@ export class SessionManager {
|
|
|
482
665
|
agentId?: AgentId,
|
|
483
666
|
caller?: CallerContext,
|
|
484
667
|
): Promise<Result<unknown, DomainError>> {
|
|
485
|
-
|
|
486
|
-
|
|
668
|
+
return this.withSessionLease(sessionId, `request:${method}`, (session) => (
|
|
669
|
+
session.callPluginMethod(method, input, agentId, caller)
|
|
670
|
+
))
|
|
671
|
+
}
|
|
487
672
|
|
|
488
|
-
|
|
673
|
+
/** Run an operation while atomically keeping the selected runtime resident. */
|
|
674
|
+
async withSessionLease<T>(
|
|
675
|
+
sessionId: SessionId,
|
|
676
|
+
reason: string,
|
|
677
|
+
operation: (session: Session) => Promise<Result<T, DomainError>>,
|
|
678
|
+
): Promise<Result<T, DomainError>> {
|
|
679
|
+
const acquired = await this.acquireSessionLease(sessionId, reason)
|
|
680
|
+
if (!acquired.ok) return acquired
|
|
681
|
+
try {
|
|
682
|
+
return await operation(acquired.value.session)
|
|
683
|
+
} finally {
|
|
684
|
+
acquired.value.release()
|
|
685
|
+
}
|
|
686
|
+
}
|
|
687
|
+
|
|
688
|
+
/** Atomically look up a runtime and acquire a caller-managed lease on it. */
|
|
689
|
+
async acquireSessionLease(
|
|
690
|
+
sessionId: SessionId,
|
|
691
|
+
reason: string,
|
|
692
|
+
): Promise<Result<AcquiredSessionLease, DomainError>> {
|
|
693
|
+
while (true) {
|
|
694
|
+
const sessionResult = await this.getSession(sessionId)
|
|
695
|
+
if (!sessionResult.ok) return sessionResult
|
|
696
|
+
|
|
697
|
+
const entry = this.sessions.get(sessionId)
|
|
698
|
+
if (!entry) return Ok({ session: sessionResult.value, release: () => {} })
|
|
699
|
+
const release = entry.activity.tryAcquire(reason)
|
|
700
|
+
if (!release) {
|
|
701
|
+
if (entry.unloadPromise) await entry.unloadPromise
|
|
702
|
+
continue
|
|
703
|
+
}
|
|
704
|
+
|
|
705
|
+
entry.lastAccessAt = performance.now()
|
|
706
|
+
let released = false
|
|
707
|
+
return Ok({
|
|
708
|
+
session: sessionResult.value,
|
|
709
|
+
release: () => {
|
|
710
|
+
if (released) return
|
|
711
|
+
released = true
|
|
712
|
+
entry.lastAccessAt = performance.now()
|
|
713
|
+
release()
|
|
714
|
+
},
|
|
715
|
+
})
|
|
716
|
+
}
|
|
489
717
|
}
|
|
490
718
|
|
|
491
719
|
/**
|
|
@@ -572,6 +800,7 @@ export class SessionManager {
|
|
|
572
800
|
*/
|
|
573
801
|
async getStats(): Promise<{
|
|
574
802
|
sessionCount: number
|
|
803
|
+
loadedSessionCount: number
|
|
575
804
|
pendingAgents: number
|
|
576
805
|
processingAgents: number
|
|
577
806
|
lastActivityAt: number | null
|
|
@@ -586,9 +815,14 @@ export class SessionManager {
|
|
|
586
815
|
let processingAgents = 0
|
|
587
816
|
let lastActivityAt: number | null = null
|
|
588
817
|
|
|
589
|
-
|
|
818
|
+
const metadataResult = await this.eventStore.listSessionsWithMetadata()
|
|
819
|
+
const openMetadata = metadataResult.sessions.filter((metadata) => metadata.status !== 'closed')
|
|
820
|
+
|
|
821
|
+
// Wait for resident sessions, ignoring failed and evicting loads.
|
|
590
822
|
const sessions = await Promise.all(
|
|
591
|
-
Array.from(this.sessions.values())
|
|
823
|
+
Array.from(this.sessions.values())
|
|
824
|
+
.filter((entry) => entry.state !== 'evicting')
|
|
825
|
+
.map((entry) => entry.promise.catch(() => null)),
|
|
592
826
|
)
|
|
593
827
|
|
|
594
828
|
// Filter out closed sessions — they do not contribute to activity
|
|
@@ -596,13 +830,8 @@ export class SessionManager {
|
|
|
596
830
|
(s): s is Session => s !== null && s.state.status !== 'closed',
|
|
597
831
|
)
|
|
598
832
|
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
openSessions.map((s) => this.eventStore.getMetadata(s.state.id).catch(() => null)),
|
|
602
|
-
)
|
|
603
|
-
|
|
604
|
-
for (const metadata of metadataResults) {
|
|
605
|
-
if (metadata?.lastActivityAt) {
|
|
833
|
+
for (const metadata of openMetadata) {
|
|
834
|
+
if (metadata.lastActivityAt) {
|
|
606
835
|
if (
|
|
607
836
|
lastActivityAt === null
|
|
608
837
|
|| metadata.lastActivityAt > lastActivityAt
|
|
@@ -619,6 +848,7 @@ export class SessionManager {
|
|
|
619
848
|
metrics: SessionStatsState
|
|
620
849
|
}> = []
|
|
621
850
|
|
|
851
|
+
const loadedById = new Map(openSessions.map((session) => [session.id, session]))
|
|
622
852
|
for (const session of openSessions) {
|
|
623
853
|
for (const [agentId, agentState] of session.state.agents) {
|
|
624
854
|
if (agentState.status === 'pending') {
|
|
@@ -635,16 +865,21 @@ export class SessionManager {
|
|
|
635
865
|
}
|
|
636
866
|
}
|
|
637
867
|
|
|
868
|
+
}
|
|
869
|
+
|
|
870
|
+
for (const metadata of openMetadata) {
|
|
871
|
+
const loaded = loadedById.get(metadata.sessionId)
|
|
638
872
|
sessionStats.push({
|
|
639
|
-
id:
|
|
640
|
-
presetId:
|
|
641
|
-
status:
|
|
642
|
-
metrics: selectSessionStats(
|
|
873
|
+
id: metadata.sessionId,
|
|
874
|
+
presetId: metadata.presetId,
|
|
875
|
+
status: loaded?.state.status ?? metadata.status,
|
|
876
|
+
metrics: loaded ? selectSessionStats(loaded.state) : statsFromMetadata(metadata),
|
|
643
877
|
})
|
|
644
878
|
}
|
|
645
879
|
|
|
646
880
|
return {
|
|
647
|
-
sessionCount:
|
|
881
|
+
sessionCount: openMetadata.length,
|
|
882
|
+
loadedSessionCount: openSessions.length,
|
|
648
883
|
pendingAgents,
|
|
649
884
|
processingAgents,
|
|
650
885
|
lastActivityAt,
|
|
@@ -656,36 +891,92 @@ export class SessionManager {
|
|
|
656
891
|
* Shutdown - clean up all sessions.
|
|
657
892
|
*/
|
|
658
893
|
async shutdown(): Promise<void> {
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
894
|
+
this.shuttingDown = true
|
|
895
|
+
if (this.evictionSweepTimer) clearInterval(this.evictionSweepTimer)
|
|
896
|
+
await Promise.all([...this.sessions].map(async ([sessionId, entry]) => {
|
|
897
|
+
try {
|
|
898
|
+
const session = await entry.promise
|
|
899
|
+
await this.beginCacheEntryDisposal(sessionId, entry, session, 'shutdown')
|
|
900
|
+
} catch (error) {
|
|
901
|
+
entry.listenerCleanup?.()
|
|
902
|
+
entry.listenerCleanup = undefined
|
|
903
|
+
this.logger.error(
|
|
904
|
+
'Failed to dispose session during shutdown',
|
|
905
|
+
error instanceof Error ? error : new Error(String(error)),
|
|
906
|
+
{ sessionId },
|
|
907
|
+
)
|
|
667
908
|
}
|
|
668
|
-
}
|
|
909
|
+
}))
|
|
669
910
|
this.sessions.clear()
|
|
670
|
-
for (const cleanup of this.sessionListenerCleanup.values()) {
|
|
671
|
-
cleanup()
|
|
672
|
-
}
|
|
673
|
-
this.sessionListenerCleanup.clear()
|
|
674
911
|
this.logger.info('SessionManager shutdown complete')
|
|
675
912
|
}
|
|
676
913
|
|
|
914
|
+
/** Narrow runtime-cache diagnostics for lifecycle tests and operational logs. */
|
|
915
|
+
getRuntimeCacheStats(): {
|
|
916
|
+
hits: number
|
|
917
|
+
misses: number
|
|
918
|
+
evictions: number
|
|
919
|
+
loadedSessionCount: number
|
|
920
|
+
sessions: Array<{
|
|
921
|
+
id: SessionId
|
|
922
|
+
state: SessionCacheEntry['state']
|
|
923
|
+
lastAccessAt: number
|
|
924
|
+
activeLeaseCount: number
|
|
925
|
+
leaseReasons: Readonly<Record<string, number>>
|
|
926
|
+
}>
|
|
927
|
+
} {
|
|
928
|
+
return {
|
|
929
|
+
hits: this.cacheHits,
|
|
930
|
+
misses: this.cacheMisses,
|
|
931
|
+
evictions: this.cacheEvictions,
|
|
932
|
+
loadedSessionCount: this.sessions.size,
|
|
933
|
+
sessions: [...this.sessions].map(([id, entry]) => {
|
|
934
|
+
const activity = entry.activity.getSnapshot()
|
|
935
|
+
return {
|
|
936
|
+
id,
|
|
937
|
+
state: entry.state,
|
|
938
|
+
lastAccessAt: Math.max(entry.lastAccessAt, activity.lastActivityAt),
|
|
939
|
+
activeLeaseCount: activity.activeCount,
|
|
940
|
+
leaseReasons: activity.reasons,
|
|
941
|
+
}
|
|
942
|
+
}),
|
|
943
|
+
}
|
|
944
|
+
}
|
|
945
|
+
|
|
946
|
+
/**
|
|
947
|
+
* Sessions whose runtime is already resident and ready.
|
|
948
|
+
*
|
|
949
|
+
* Deliberately does not load, and does not refresh `lastAccessAt` — a passive
|
|
950
|
+
* reader must not keep a runtime alive or resurrect an evicted one. Use this
|
|
951
|
+
* over `getSession()` for read-only sweeps across sessions.
|
|
952
|
+
*/
|
|
953
|
+
async listResidentSessions(): Promise<Session[]> {
|
|
954
|
+
const entries = [...this.sessions].filter(([, entry]) => entry.state === 'ready')
|
|
955
|
+
const sessions = await Promise.all(entries.map(async ([sessionId, entry]) => {
|
|
956
|
+
const session = await entry.promise.catch(() => null)
|
|
957
|
+
// Re-check: the entry can start evicting while we await the resolved promise.
|
|
958
|
+
if (!session || this.sessions.get(sessionId) !== entry || entry.state !== 'ready') return null
|
|
959
|
+
return session
|
|
960
|
+
}))
|
|
961
|
+
return sessions.filter((session): session is Session => session !== null)
|
|
962
|
+
}
|
|
963
|
+
|
|
677
964
|
// ============================================================================
|
|
678
965
|
// Private methods
|
|
679
966
|
// ============================================================================
|
|
680
967
|
|
|
681
968
|
/**
|
|
682
|
-
* Build ConfiguredPlugin[] for a session.
|
|
969
|
+
* Build ConfiguredPlugin[] for a session, in hook order.
|
|
683
970
|
*
|
|
684
971
|
* Iterates all system-registered plugins. For each:
|
|
685
972
|
* 1. Check if preset has explicit SessionPluginConfig → use that config
|
|
686
973
|
* 2. If not, try auto-deriving infrastructure config (agents, uploads, services)
|
|
687
974
|
* 3. If no config at all → call .create() with no args (void config)
|
|
688
975
|
* 4. Check isSessionEnabled — skip plugin if not enabled
|
|
976
|
+
*
|
|
977
|
+
* The result is sorted by each plugin's declared `.order()` — the precedence
|
|
978
|
+
* between plugins that both want the same hook, since most agent hooks stop
|
|
979
|
+
* at the first non-null result.
|
|
689
980
|
*/
|
|
690
981
|
private buildPlugins(preset: Preset): ConfiguredPlugin[] {
|
|
691
982
|
// Build a lookup from preset Sessionplugins
|
|
@@ -759,7 +1050,8 @@ export class SessionManager {
|
|
|
759
1050
|
}
|
|
760
1051
|
}
|
|
761
1052
|
|
|
762
|
-
|
|
1053
|
+
// Stable, so plugins that declare no order keep their registration order.
|
|
1054
|
+
return plugins.sort((a, b) => (a.order ?? DEFAULT_PLUGIN_ORDER) - (b.order ?? DEFAULT_PLUGIN_ORDER))
|
|
763
1055
|
}
|
|
764
1056
|
|
|
765
1057
|
/**
|
|
@@ -786,8 +1078,13 @@ export class SessionManager {
|
|
|
786
1078
|
configs.set('uploads', {
|
|
787
1079
|
dataFileStore: this.dataFileStore,
|
|
788
1080
|
preprocessorRegistry: this.preprocessorRegistry,
|
|
1081
|
+
archiveLimits: this.uploadArchiveLimits,
|
|
789
1082
|
})
|
|
790
1083
|
|
|
1084
|
+
if (this.resourceArchiveLimits) {
|
|
1085
|
+
configs.set('resources', { archiveLimits: this.resourceArchiveLimits })
|
|
1086
|
+
}
|
|
1087
|
+
|
|
791
1088
|
// services plugin — collect services from all agent definitions
|
|
792
1089
|
const allAgentConfigs = [preset.orchestrator, ...(preset.communicator ? [preset.communicator] : []), ...preset.agents]
|
|
793
1090
|
const servicesByType = new Map<string, ServiceConfig>()
|
|
@@ -816,17 +1113,13 @@ export class SessionManager {
|
|
|
816
1113
|
store: SessionStore,
|
|
817
1114
|
preset: Preset,
|
|
818
1115
|
plugins: ConfiguredPlugin[],
|
|
1116
|
+
entry: SessionCacheEntry,
|
|
819
1117
|
opts: { skipReadyHooks?: boolean } = {},
|
|
820
1118
|
): Promise<Session> {
|
|
821
|
-
// Only register cache eviction listener for active sessions (not closed)
|
|
822
|
-
if (store.getState().status !== 'closed') {
|
|
823
|
-
this.registerSessionEventListener(store.sessionId, store)
|
|
824
|
-
}
|
|
825
|
-
|
|
826
1119
|
const sessionDir = this.getSessionDir(store.sessionId)
|
|
827
1120
|
const sessionLogger = new TeeLogger([
|
|
828
1121
|
this.logger.child({ sessionId: store.sessionId }),
|
|
829
|
-
|
|
1122
|
+
createSessionLogger(this.platform, String(store.sessionId), join(sessionDir, 'session.log')),
|
|
830
1123
|
])
|
|
831
1124
|
|
|
832
1125
|
// Create session
|
|
@@ -843,8 +1136,15 @@ export class SessionManager {
|
|
|
843
1136
|
eventStore: this.eventStore,
|
|
844
1137
|
llmLogger: this.llmLogger,
|
|
845
1138
|
platform: this.platform,
|
|
1139
|
+
runtimeActivity: entry.activity,
|
|
1140
|
+
registerReopenedSession: (reopenedSession) => this.registerReopenedSession(reopenedSession, entry.activity),
|
|
846
1141
|
})
|
|
847
1142
|
|
|
1143
|
+
// Only register cache eviction listener for active sessions (not closed)
|
|
1144
|
+
if (store.getState().status !== 'closed') {
|
|
1145
|
+
this.registerSessionEventListener(store.sessionId, store, session, entry)
|
|
1146
|
+
}
|
|
1147
|
+
|
|
848
1148
|
// Ensure session and workspace directories exist before plugins run
|
|
849
1149
|
await this.platform.fs.mkdir(sessionDir, { recursive: true })
|
|
850
1150
|
const workspaceDir = store.getState().workspaceDir
|
|
@@ -852,14 +1152,17 @@ export class SessionManager {
|
|
|
852
1152
|
await this.platform.fs.mkdir(workspaceDir, { recursive: true })
|
|
853
1153
|
}
|
|
854
1154
|
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
1155
|
+
try {
|
|
1156
|
+
// Safe for closed sessions — createContext is pure local setup, no event emit.
|
|
1157
|
+
await session.initPluginContexts()
|
|
858
1158
|
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
await session.
|
|
1159
|
+
// Skipped for closed sessions to preserve event log immutability.
|
|
1160
|
+
if (!opts.skipReadyHooks) await session.callSessionReadyHooks()
|
|
1161
|
+
} catch (error) {
|
|
1162
|
+
await session.dispose('evicted')
|
|
1163
|
+
entry.listenerCleanup?.()
|
|
1164
|
+
entry.listenerCleanup = undefined
|
|
1165
|
+
throw error
|
|
863
1166
|
}
|
|
864
1167
|
|
|
865
1168
|
return session
|
|
@@ -896,20 +1199,137 @@ export class SessionManager {
|
|
|
896
1199
|
* Cleans up any previous listener for this sessionId (from a prior load)
|
|
897
1200
|
* to prevent duplicate listeners firing on old stores.
|
|
898
1201
|
*/
|
|
899
|
-
private registerSessionEventListener(sessionId: SessionId, store: SessionStore): void {
|
|
900
|
-
|
|
901
|
-
if (prevCleanup) prevCleanup()
|
|
902
|
-
|
|
1202
|
+
private registerSessionEventListener(sessionId: SessionId, store: SessionStore, session: Session, entry: SessionCacheEntry): void {
|
|
1203
|
+
entry.listenerCleanup?.()
|
|
903
1204
|
const unsubscribe = store.onEvent((event) => {
|
|
904
|
-
if (event.type === 'session_closed'
|
|
905
|
-
this.sessions.
|
|
906
|
-
|
|
1205
|
+
if (event.type === 'session_closed') {
|
|
1206
|
+
if (this.sessions.get(sessionId) === entry) this.beginCacheEntryDisposal(sessionId, entry, session, 'closed')
|
|
1207
|
+
else void session.dispose('closed')
|
|
1208
|
+
} else if (event.type === 'session_reopened') {
|
|
1209
|
+
if (this.sessions.get(sessionId) === entry) this.sessions.delete(sessionId)
|
|
1210
|
+
unsubscribe()
|
|
1211
|
+
entry.listenerCleanup = undefined
|
|
907
1212
|
}
|
|
908
1213
|
})
|
|
909
|
-
|
|
1214
|
+
entry.listenerCleanup = unsubscribe
|
|
1215
|
+
}
|
|
1216
|
+
|
|
1217
|
+
private registerReopenedSession(
|
|
1218
|
+
session: Session,
|
|
1219
|
+
activity: SessionRuntimeActivityController,
|
|
1220
|
+
): Result<SessionReopenRegistration | undefined, DomainError> {
|
|
1221
|
+
if (this.shuttingDown) return Err(ValidationErrors.invalid('Session manager is shutting down'))
|
|
1222
|
+
if (activity.getSnapshot().state !== 'ready') return Ok(undefined)
|
|
1223
|
+
if (this.sessions.has(session.id)) return Err(SessionErrors.alreadyExists(String(session.id)))
|
|
1224
|
+
|
|
1225
|
+
const deferred = Promise.withResolvers<Session>()
|
|
1226
|
+
void deferred.promise.catch(() => {})
|
|
1227
|
+
const entry: SessionCacheEntry = {
|
|
1228
|
+
state: 'loading',
|
|
1229
|
+
promise: deferred.promise,
|
|
1230
|
+
activity,
|
|
1231
|
+
lastAccessAt: performance.now(),
|
|
1232
|
+
}
|
|
1233
|
+
this.sessions.set(session.id, entry)
|
|
1234
|
+
|
|
1235
|
+
return Ok({
|
|
1236
|
+
complete: async () => {
|
|
1237
|
+
if (this.sessions.get(session.id) !== entry) {
|
|
1238
|
+
throw new Error(`Reopened session lost cache ownership: ${session.id}`)
|
|
1239
|
+
}
|
|
1240
|
+
this.registerSessionEventListener(session.id, session.store, session, entry)
|
|
1241
|
+
try {
|
|
1242
|
+
await session.callSessionReadyHooks()
|
|
1243
|
+
session.checkPendingAgents()
|
|
1244
|
+
if (this.sessions.get(session.id) !== entry || entry.state !== 'loading' || activity.getSnapshot().state !== 'ready') {
|
|
1245
|
+
throw new Error(`Reopened session became unavailable during ready hooks: ${session.id}`)
|
|
1246
|
+
}
|
|
1247
|
+
entry.state = 'ready'
|
|
1248
|
+
entry.lastAccessAt = performance.now()
|
|
1249
|
+
deferred.resolve(session)
|
|
1250
|
+
} catch (error) {
|
|
1251
|
+
if (this.sessions.get(session.id) === entry) this.sessions.delete(session.id)
|
|
1252
|
+
entry.listenerCleanup?.()
|
|
1253
|
+
entry.listenerCleanup = undefined
|
|
1254
|
+
deferred.reject(error)
|
|
1255
|
+
await session.dispose('evicted')
|
|
1256
|
+
throw error
|
|
1257
|
+
}
|
|
1258
|
+
},
|
|
1259
|
+
abort: (error) => {
|
|
1260
|
+
if (this.sessions.get(session.id) === entry) this.sessions.delete(session.id)
|
|
1261
|
+
entry.listenerCleanup?.()
|
|
1262
|
+
entry.listenerCleanup = undefined
|
|
1263
|
+
deferred.reject(error)
|
|
1264
|
+
},
|
|
1265
|
+
})
|
|
1266
|
+
}
|
|
1267
|
+
|
|
1268
|
+
private async evictIdleSessions(): Promise<void> {
|
|
1269
|
+
if (this.sessionIdleTimeoutMs === 0) return
|
|
1270
|
+
const now = performance.now()
|
|
1271
|
+
const disposals: Promise<void>[] = []
|
|
1272
|
+
for (const [sessionId, entry] of this.sessions) {
|
|
1273
|
+
if (entry.state !== 'ready') continue
|
|
1274
|
+
const activity = entry.activity.getSnapshot()
|
|
1275
|
+
if (now - Math.max(entry.lastAccessAt, activity.lastActivityAt) < this.sessionIdleTimeoutMs) continue
|
|
1276
|
+
if (!entry.activity.tryBeginUnload()) continue
|
|
1277
|
+
const session = await entry.promise
|
|
1278
|
+
disposals.push(this.beginCacheEntryDisposal(sessionId, entry, session, 'idle'))
|
|
1279
|
+
}
|
|
1280
|
+
await Promise.all(disposals)
|
|
1281
|
+
}
|
|
1282
|
+
|
|
1283
|
+
private beginCacheEntryDisposal(
|
|
1284
|
+
sessionId: SessionId,
|
|
1285
|
+
entry: SessionCacheEntry,
|
|
1286
|
+
session: Session,
|
|
1287
|
+
reason: RuntimeDisposalCause,
|
|
1288
|
+
): Promise<void> {
|
|
1289
|
+
if (entry.unloadPromise) return entry.unloadPromise
|
|
1290
|
+
entry.state = 'evicting'
|
|
1291
|
+
entry.activity.beginForcedUnload()
|
|
1292
|
+
entry.unloadPromise = session.dispose(RUNTIME_DISPOSAL_CLOSE_REASON[reason])
|
|
1293
|
+
.catch((error) => {
|
|
1294
|
+
this.logger.error(
|
|
1295
|
+
'Failed to dispose session runtime',
|
|
1296
|
+
error instanceof Error ? error : new Error(String(error)),
|
|
1297
|
+
{ sessionId, reason },
|
|
1298
|
+
)
|
|
1299
|
+
})
|
|
1300
|
+
.finally(() => {
|
|
1301
|
+
if (this.sessions.get(sessionId) === entry) this.sessions.delete(sessionId)
|
|
1302
|
+
entry.listenerCleanup?.()
|
|
1303
|
+
entry.listenerCleanup = undefined
|
|
1304
|
+
if (reason === 'idle') this.cacheEvictions++
|
|
1305
|
+
this.logger.debug('Session runtime evicted', { sessionId, reason })
|
|
1306
|
+
})
|
|
1307
|
+
return entry.unloadPromise
|
|
910
1308
|
}
|
|
911
1309
|
|
|
912
1310
|
private getSessionDir(sessionId: SessionId): string {
|
|
913
1311
|
return join(this.basePath, 'sessions', String(sessionId))
|
|
914
1312
|
}
|
|
915
1313
|
}
|
|
1314
|
+
|
|
1315
|
+
function statsFromMetadata(metadata: SessionMetadata): SessionStatsState {
|
|
1316
|
+
return {
|
|
1317
|
+
totalTokens: metadata.metrics?.totalTokens ?? 0,
|
|
1318
|
+
promptTokens: metadata.metrics?.inputTokens ?? 0,
|
|
1319
|
+
completionTokens: metadata.metrics?.outputTokens ?? 0,
|
|
1320
|
+
cacheReadTokens: 0,
|
|
1321
|
+
cacheWriteTokens: 0,
|
|
1322
|
+
totalCost: metadata.metrics?.totalCost ?? 0,
|
|
1323
|
+
llmCalls: metadata.metrics?.totalLLMCalls ?? 0,
|
|
1324
|
+
llmErrors: 0,
|
|
1325
|
+
toolCalls: metadata.metrics?.totalToolCalls ?? 0,
|
|
1326
|
+
toolErrors: 0,
|
|
1327
|
+
userMessages: metadata.metrics?.totalMessages ?? 0,
|
|
1328
|
+
compactions: 0,
|
|
1329
|
+
agentCount: metadata.metrics?.totalAgents ?? 0,
|
|
1330
|
+
firstEventAt: metadata.createdAt,
|
|
1331
|
+
lastEventAt: metadata.lastActivityAt,
|
|
1332
|
+
byProvider: {},
|
|
1333
|
+
byAgent: {},
|
|
1334
|
+
}
|
|
1335
|
+
}
|