@methodts/runtime 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/__fixtures__/executor-fixtures.d.ts +10 -0
- package/dist/__fixtures__/executor-fixtures.d.ts.map +1 -0
- package/dist/__fixtures__/executor-fixtures.js +36 -0
- package/dist/__fixtures__/executor-fixtures.js.map +1 -0
- package/dist/architecture.test.d.ts +2 -0
- package/dist/architecture.test.d.ts.map +1 -0
- package/dist/architecture.test.js +143 -0
- package/dist/architecture.test.js.map +1 -0
- package/dist/config/cost-governor-config.d.ts +40 -0
- package/dist/config/cost-governor-config.d.ts.map +1 -0
- package/dist/config/cost-governor-config.js +48 -0
- package/dist/config/cost-governor-config.js.map +1 -0
- package/dist/config/index.d.ts +7 -0
- package/dist/config/index.d.ts.map +1 -0
- package/dist/config/index.js +6 -0
- package/dist/config/index.js.map +1 -0
- package/dist/config/sessions-config.d.ts +29 -0
- package/dist/config/sessions-config.d.ts.map +1 -0
- package/dist/config/sessions-config.js +37 -0
- package/dist/config/sessions-config.js.map +1 -0
- package/dist/config/strategies-config.d.ts +38 -0
- package/dist/config/strategies-config.d.ts.map +1 -0
- package/dist/config/strategies-config.js +41 -0
- package/dist/config/strategies-config.js.map +1 -0
- package/dist/cost-governor/backpressure-queue.d.ts +20 -0
- package/dist/cost-governor/backpressure-queue.d.ts.map +1 -0
- package/dist/cost-governor/backpressure-queue.js +78 -0
- package/dist/cost-governor/backpressure-queue.js.map +1 -0
- package/dist/cost-governor/backpressure-queue.test.d.ts +2 -0
- package/dist/cost-governor/backpressure-queue.test.d.ts.map +1 -0
- package/dist/cost-governor/backpressure-queue.test.js +48 -0
- package/dist/cost-governor/backpressure-queue.test.js.map +1 -0
- package/dist/cost-governor/cost-events.d.ts +65 -0
- package/dist/cost-governor/cost-events.d.ts.map +1 -0
- package/dist/cost-governor/cost-events.js +48 -0
- package/dist/cost-governor/cost-events.js.map +1 -0
- package/dist/cost-governor/cost-governor-app-id.test.d.ts +19 -0
- package/dist/cost-governor/cost-governor-app-id.test.d.ts.map +1 -0
- package/dist/cost-governor/cost-governor-app-id.test.js +201 -0
- package/dist/cost-governor/cost-governor-app-id.test.js.map +1 -0
- package/dist/cost-governor/cost-oracle-impl.d.ts +19 -0
- package/dist/cost-governor/cost-oracle-impl.d.ts.map +1 -0
- package/dist/cost-governor/cost-oracle-impl.js +52 -0
- package/dist/cost-governor/cost-oracle-impl.js.map +1 -0
- package/dist/cost-governor/estimator.d.ts +22 -0
- package/dist/cost-governor/estimator.d.ts.map +1 -0
- package/dist/cost-governor/estimator.js +119 -0
- package/dist/cost-governor/estimator.js.map +1 -0
- package/dist/cost-governor/estimator.test.d.ts +2 -0
- package/dist/cost-governor/estimator.test.d.ts.map +1 -0
- package/dist/cost-governor/estimator.test.js +141 -0
- package/dist/cost-governor/estimator.test.js.map +1 -0
- package/dist/cost-governor/index.d.ts +75 -0
- package/dist/cost-governor/index.d.ts.map +1 -0
- package/dist/cost-governor/index.js +120 -0
- package/dist/cost-governor/index.js.map +1 -0
- package/dist/cost-governor/observations-store.d.ts +49 -0
- package/dist/cost-governor/observations-store.d.ts.map +1 -0
- package/dist/cost-governor/observations-store.js +179 -0
- package/dist/cost-governor/observations-store.js.map +1 -0
- package/dist/cost-governor/observations-store.test.d.ts +2 -0
- package/dist/cost-governor/observations-store.test.d.ts.map +1 -0
- package/dist/cost-governor/observations-store.test.js +191 -0
- package/dist/cost-governor/observations-store.test.js.map +1 -0
- package/dist/cost-governor/percentile.d.ts +17 -0
- package/dist/cost-governor/percentile.d.ts.map +1 -0
- package/dist/cost-governor/percentile.js +33 -0
- package/dist/cost-governor/percentile.js.map +1 -0
- package/dist/cost-governor/percentile.test.d.ts +2 -0
- package/dist/cost-governor/percentile.test.d.ts.map +1 -0
- package/dist/cost-governor/percentile.test.js +46 -0
- package/dist/cost-governor/percentile.test.js.map +1 -0
- package/dist/cost-governor/rate-governor-impl.d.ts +73 -0
- package/dist/cost-governor/rate-governor-impl.d.ts.map +1 -0
- package/dist/cost-governor/rate-governor-impl.js +148 -0
- package/dist/cost-governor/rate-governor-impl.js.map +1 -0
- package/dist/cost-governor/signature-builder.d.ts +22 -0
- package/dist/cost-governor/signature-builder.d.ts.map +1 -0
- package/dist/cost-governor/signature-builder.js +43 -0
- package/dist/cost-governor/signature-builder.js.map +1 -0
- package/dist/cost-governor/signature-builder.test.d.ts +2 -0
- package/dist/cost-governor/signature-builder.test.d.ts.map +1 -0
- package/dist/cost-governor/signature-builder.test.js +58 -0
- package/dist/cost-governor/signature-builder.test.js.map +1 -0
- package/dist/cost-governor/token-bucket.d.ts +57 -0
- package/dist/cost-governor/token-bucket.d.ts.map +1 -0
- package/dist/cost-governor/token-bucket.js +109 -0
- package/dist/cost-governor/token-bucket.js.map +1 -0
- package/dist/cost-governor/token-bucket.test.d.ts +2 -0
- package/dist/cost-governor/token-bucket.test.d.ts.map +1 -0
- package/dist/cost-governor/token-bucket.test.js +67 -0
- package/dist/cost-governor/token-bucket.test.js.map +1 -0
- package/dist/dlq/cortex-dlq-observer.d.ts +22 -0
- package/dist/dlq/cortex-dlq-observer.d.ts.map +1 -0
- package/dist/dlq/cortex-dlq-observer.js +29 -0
- package/dist/dlq/cortex-dlq-observer.js.map +1 -0
- package/dist/dlq/dlq-observer.test.d.ts +8 -0
- package/dist/dlq/dlq-observer.test.d.ts.map +1 -0
- package/dist/dlq/dlq-observer.test.js +103 -0
- package/dist/dlq/dlq-observer.test.js.map +1 -0
- package/dist/dlq/index.d.ts +6 -0
- package/dist/dlq/index.d.ts.map +1 -0
- package/dist/dlq/index.js +6 -0
- package/dist/dlq/index.js.map +1 -0
- package/dist/event-bus/adapters.d.ts +50 -0
- package/dist/event-bus/adapters.d.ts.map +1 -0
- package/dist/event-bus/adapters.js +51 -0
- package/dist/event-bus/adapters.js.map +1 -0
- package/dist/event-bus/adapters.test.d.ts +5 -0
- package/dist/event-bus/adapters.test.d.ts.map +1 -0
- package/dist/event-bus/adapters.test.js +73 -0
- package/dist/event-bus/adapters.test.js.map +1 -0
- package/dist/event-bus/agent-event-adapter.d.ts +22 -0
- package/dist/event-bus/agent-event-adapter.d.ts.map +1 -0
- package/dist/event-bus/agent-event-adapter.js +49 -0
- package/dist/event-bus/agent-event-adapter.js.map +1 -0
- package/dist/event-bus/agent-event-adapter.test.d.ts +5 -0
- package/dist/event-bus/agent-event-adapter.test.d.ts.map +1 -0
- package/dist/event-bus/agent-event-adapter.test.js +170 -0
- package/dist/event-bus/agent-event-adapter.test.js.map +1 -0
- package/dist/event-bus/channel-sink.d.ts +71 -0
- package/dist/event-bus/channel-sink.d.ts.map +1 -0
- package/dist/event-bus/channel-sink.js +159 -0
- package/dist/event-bus/channel-sink.js.map +1 -0
- package/dist/event-bus/channel-sink.test.d.ts +5 -0
- package/dist/event-bus/channel-sink.test.d.ts.map +1 -0
- package/dist/event-bus/channel-sink.test.js +234 -0
- package/dist/event-bus/channel-sink.test.js.map +1 -0
- package/dist/event-bus/event-types.snapshot.test.d.ts +27 -0
- package/dist/event-bus/event-types.snapshot.test.d.ts.map +1 -0
- package/dist/event-bus/event-types.snapshot.test.js +165 -0
- package/dist/event-bus/event-types.snapshot.test.js.map +1 -0
- package/dist/event-bus/genesis-sink.d.ts +55 -0
- package/dist/event-bus/genesis-sink.d.ts.map +1 -0
- package/dist/event-bus/genesis-sink.js +141 -0
- package/dist/event-bus/genesis-sink.js.map +1 -0
- package/dist/event-bus/genesis-sink.test.d.ts +5 -0
- package/dist/event-bus/genesis-sink.test.d.ts.map +1 -0
- package/dist/event-bus/genesis-sink.test.js +160 -0
- package/dist/event-bus/genesis-sink.test.js.map +1 -0
- package/dist/event-bus/in-memory-event-bus.d.ts +60 -0
- package/dist/event-bus/in-memory-event-bus.d.ts.map +1 -0
- package/dist/event-bus/in-memory-event-bus.js +274 -0
- package/dist/event-bus/in-memory-event-bus.js.map +1 -0
- package/dist/event-bus/in-memory-event-bus.test.d.ts +5 -0
- package/dist/event-bus/in-memory-event-bus.test.d.ts.map +1 -0
- package/dist/event-bus/in-memory-event-bus.test.js +457 -0
- package/dist/event-bus/in-memory-event-bus.test.js.map +1 -0
- package/dist/event-bus/index.d.ts +22 -0
- package/dist/event-bus/index.d.ts.map +1 -0
- package/dist/event-bus/index.js +17 -0
- package/dist/event-bus/index.js.map +1 -0
- package/dist/event-bus/persistence-sink.d.ts +74 -0
- package/dist/event-bus/persistence-sink.d.ts.map +1 -0
- package/dist/event-bus/persistence-sink.js +193 -0
- package/dist/event-bus/persistence-sink.js.map +1 -0
- package/dist/event-bus/persistence-sink.test.d.ts +6 -0
- package/dist/event-bus/persistence-sink.test.d.ts.map +1 -0
- package/dist/event-bus/persistence-sink.test.js +319 -0
- package/dist/event-bus/persistence-sink.test.js.map +1 -0
- package/dist/event-bus/session-checkpoint-sink.d.ts +91 -0
- package/dist/event-bus/session-checkpoint-sink.d.ts.map +1 -0
- package/dist/event-bus/session-checkpoint-sink.js +107 -0
- package/dist/event-bus/session-checkpoint-sink.js.map +1 -0
- package/dist/event-bus/session-checkpoint-sink.test.d.ts +5 -0
- package/dist/event-bus/session-checkpoint-sink.test.d.ts.map +1 -0
- package/dist/event-bus/session-checkpoint-sink.test.js +215 -0
- package/dist/event-bus/session-checkpoint-sink.test.js.map +1 -0
- package/dist/event-bus/webhook-connector.d.ts +59 -0
- package/dist/event-bus/webhook-connector.d.ts.map +1 -0
- package/dist/event-bus/webhook-connector.js +191 -0
- package/dist/event-bus/webhook-connector.js.map +1 -0
- package/dist/event-bus/webhook-connector.test.d.ts +5 -0
- package/dist/event-bus/webhook-connector.test.d.ts.map +1 -0
- package/dist/event-bus/webhook-connector.test.js +214 -0
- package/dist/event-bus/webhook-connector.test.js.map +1 -0
- package/dist/executors/cortex-job-backed-executor.d.ts +137 -0
- package/dist/executors/cortex-job-backed-executor.d.ts.map +1 -0
- package/dist/executors/cortex-job-backed-executor.js +441 -0
- package/dist/executors/cortex-job-backed-executor.js.map +1 -0
- package/dist/executors/cortex-job-backed-executor.test.d.ts +13 -0
- package/dist/executors/cortex-job-backed-executor.test.d.ts.map +1 -0
- package/dist/executors/cortex-job-backed-executor.test.js +303 -0
- package/dist/executors/cortex-job-backed-executor.test.js.map +1 -0
- package/dist/executors/index.d.ts +9 -0
- package/dist/executors/index.d.ts.map +1 -0
- package/dist/executors/index.js +9 -0
- package/dist/executors/index.js.map +1 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +13 -0
- package/dist/index.js.map +1 -0
- package/dist/ports/checkpoint-sink.d.ts +69 -0
- package/dist/ports/checkpoint-sink.d.ts.map +1 -0
- package/dist/ports/checkpoint-sink.js +16 -0
- package/dist/ports/checkpoint-sink.js.map +1 -0
- package/dist/ports/checkpoint.d.ts +68 -0
- package/dist/ports/checkpoint.d.ts.map +1 -0
- package/dist/ports/checkpoint.js +14 -0
- package/dist/ports/checkpoint.js.map +1 -0
- package/dist/ports/continuation-envelope-cross-app.test.d.ts +10 -0
- package/dist/ports/continuation-envelope-cross-app.test.d.ts.map +1 -0
- package/dist/ports/continuation-envelope-cross-app.test.js +95 -0
- package/dist/ports/continuation-envelope-cross-app.test.js.map +1 -0
- package/dist/ports/continuation-envelope.d.ts +199 -0
- package/dist/ports/continuation-envelope.d.ts.map +1 -0
- package/dist/ports/continuation-envelope.js +69 -0
- package/dist/ports/continuation-envelope.js.map +1 -0
- package/dist/ports/conversation.d.ts +64 -0
- package/dist/ports/conversation.d.ts.map +1 -0
- package/dist/ports/conversation.js +19 -0
- package/dist/ports/conversation.js.map +1 -0
- package/dist/ports/cost-oracle.d.ts +26 -0
- package/dist/ports/cost-oracle.d.ts.map +1 -0
- package/dist/ports/cost-oracle.js +9 -0
- package/dist/ports/cost-oracle.js.map +1 -0
- package/dist/ports/cross-app-invoker.d.ts +198 -0
- package/dist/ports/cross-app-invoker.d.ts.map +1 -0
- package/dist/ports/cross-app-invoker.js +157 -0
- package/dist/ports/cross-app-invoker.js.map +1 -0
- package/dist/ports/dlq-observer.d.ts +40 -0
- package/dist/ports/dlq-observer.d.ts.map +1 -0
- package/dist/ports/dlq-observer.js +20 -0
- package/dist/ports/dlq-observer.js.map +1 -0
- package/dist/ports/event-bus.d.ts +169 -0
- package/dist/ports/event-bus.d.ts.map +1 -0
- package/dist/ports/event-bus.js +20 -0
- package/dist/ports/event-bus.js.map +1 -0
- package/dist/ports/event-reader.d.ts +21 -0
- package/dist/ports/event-reader.d.ts.map +1 -0
- package/dist/ports/event-reader.js +12 -0
- package/dist/ports/event-reader.js.map +1 -0
- package/dist/ports/event-rotator.d.ts +39 -0
- package/dist/ports/event-rotator.d.ts.map +1 -0
- package/dist/ports/event-rotator.js +15 -0
- package/dist/ports/event-rotator.js.map +1 -0
- package/dist/ports/file-system.d.ts +48 -0
- package/dist/ports/file-system.d.ts.map +1 -0
- package/dist/ports/file-system.js +10 -0
- package/dist/ports/file-system.js.map +1 -0
- package/dist/ports/historical-observations.d.ts +39 -0
- package/dist/ports/historical-observations.d.ts.map +1 -0
- package/dist/ports/historical-observations.js +12 -0
- package/dist/ports/historical-observations.js.map +1 -0
- package/dist/ports/in-memory-source.d.ts +46 -0
- package/dist/ports/in-memory-source.d.ts.map +1 -0
- package/dist/ports/in-memory-source.js +69 -0
- package/dist/ports/in-memory-source.js.map +1 -0
- package/dist/ports/index.d.ts +32 -0
- package/dist/ports/index.d.ts.map +1 -0
- package/dist/ports/index.js +10 -0
- package/dist/ports/index.js.map +1 -0
- package/dist/ports/job-backed-executor.d.ts +139 -0
- package/dist/ports/job-backed-executor.d.ts.map +1 -0
- package/dist/ports/job-backed-executor.js +56 -0
- package/dist/ports/job-backed-executor.js.map +1 -0
- package/dist/ports/methodology-source.d.ts +95 -0
- package/dist/ports/methodology-source.d.ts.map +1 -0
- package/dist/ports/methodology-source.js +26 -0
- package/dist/ports/methodology-source.js.map +1 -0
- package/dist/ports/native-session-discovery.d.ts +20 -0
- package/dist/ports/native-session-discovery.d.ts.map +1 -0
- package/dist/ports/native-session-discovery.js +13 -0
- package/dist/ports/native-session-discovery.js.map +1 -0
- package/dist/ports/projection-store.d.ts +48 -0
- package/dist/ports/projection-store.d.ts.map +1 -0
- package/dist/ports/projection-store.js +17 -0
- package/dist/ports/projection-store.js.map +1 -0
- package/dist/ports/projection.d.ts +29 -0
- package/dist/ports/projection.d.ts.map +1 -0
- package/dist/ports/projection.js +13 -0
- package/dist/ports/projection.js.map +1 -0
- package/dist/ports/rate-governor.d.ts +17 -0
- package/dist/ports/rate-governor.d.ts.map +1 -0
- package/dist/ports/rate-governor.js +11 -0
- package/dist/ports/rate-governor.js.map +1 -0
- package/dist/ports/schedule-client.d.ts +29 -0
- package/dist/ports/schedule-client.d.ts.map +1 -0
- package/dist/ports/schedule-client.js +2 -0
- package/dist/ports/schedule-client.js.map +1 -0
- package/dist/ports/session-pool.d.ts +162 -0
- package/dist/ports/session-pool.d.ts.map +1 -0
- package/dist/ports/session-pool.js +21 -0
- package/dist/ports/session-pool.js.map +1 -0
- package/dist/ports/session-store-errors.d.ts +22 -0
- package/dist/ports/session-store-errors.d.ts.map +1 -0
- package/dist/ports/session-store-errors.js +29 -0
- package/dist/ports/session-store-errors.js.map +1 -0
- package/dist/ports/session-store-types.d.ts +132 -0
- package/dist/ports/session-store-types.d.ts.map +1 -0
- package/dist/ports/session-store-types.js +14 -0
- package/dist/ports/session-store-types.js.map +1 -0
- package/dist/ports/session-store.d.ts +69 -0
- package/dist/ports/session-store.d.ts.map +1 -0
- package/dist/ports/session-store.js +23 -0
- package/dist/ports/session-store.js.map +1 -0
- package/dist/ports/yaml-loader.d.ts +15 -0
- package/dist/ports/yaml-loader.d.ts.map +1 -0
- package/dist/ports/yaml-loader.js +13 -0
- package/dist/ports/yaml-loader.js.map +1 -0
- package/dist/scheduling/index.d.ts +6 -0
- package/dist/scheduling/index.d.ts.map +1 -0
- package/dist/scheduling/index.js +6 -0
- package/dist/scheduling/index.js.map +1 -0
- package/dist/scheduling/scheduled-pact.d.ts +97 -0
- package/dist/scheduling/scheduled-pact.d.ts.map +1 -0
- package/dist/scheduling/scheduled-pact.js +89 -0
- package/dist/scheduling/scheduled-pact.js.map +1 -0
- package/dist/sessions/__tests__/cognitive-modules.test.d.ts +10 -0
- package/dist/sessions/__tests__/cognitive-modules.test.d.ts.map +1 -0
- package/dist/sessions/__tests__/cognitive-modules.test.js +535 -0
- package/dist/sessions/__tests__/cognitive-modules.test.js.map +1 -0
- package/dist/sessions/__tests__/cognitive-provider.test.d.ts +13 -0
- package/dist/sessions/__tests__/cognitive-provider.test.d.ts.map +1 -0
- package/dist/sessions/__tests__/cognitive-provider.test.js +331 -0
- package/dist/sessions/__tests__/cognitive-provider.test.js.map +1 -0
- package/dist/sessions/__tests__/cognitive-sink.test.d.ts +19 -0
- package/dist/sessions/__tests__/cognitive-sink.test.d.ts.map +1 -0
- package/dist/sessions/__tests__/cognitive-sink.test.js +334 -0
- package/dist/sessions/__tests__/cognitive-sink.test.js.map +1 -0
- package/dist/sessions/__tests__/runtime-tools.test.d.ts +2 -0
- package/dist/sessions/__tests__/runtime-tools.test.d.ts.map +1 -0
- package/dist/sessions/__tests__/runtime-tools.test.js +83 -0
- package/dist/sessions/__tests__/runtime-tools.test.js.map +1 -0
- package/dist/sessions/auto-retro.d.ts +29 -0
- package/dist/sessions/auto-retro.d.ts.map +1 -0
- package/dist/sessions/auto-retro.js +181 -0
- package/dist/sessions/auto-retro.js.map +1 -0
- package/dist/sessions/auto-retro.test.d.ts +2 -0
- package/dist/sessions/auto-retro.test.d.ts.map +1 -0
- package/dist/sessions/auto-retro.test.js +361 -0
- package/dist/sessions/auto-retro.test.js.map +1 -0
- package/dist/sessions/channels.d.ts +55 -0
- package/dist/sessions/channels.d.ts.map +1 -0
- package/dist/sessions/channels.js +118 -0
- package/dist/sessions/channels.js.map +1 -0
- package/dist/sessions/channels.test.d.ts +2 -0
- package/dist/sessions/channels.test.d.ts.map +1 -0
- package/dist/sessions/channels.test.js +285 -0
- package/dist/sessions/channels.test.js.map +1 -0
- package/dist/sessions/cognitive-modules.d.ts +100 -0
- package/dist/sessions/cognitive-modules.d.ts.map +1 -0
- package/dist/sessions/cognitive-modules.js +458 -0
- package/dist/sessions/cognitive-modules.js.map +1 -0
- package/dist/sessions/cognitive-provider.d.ts +42 -0
- package/dist/sessions/cognitive-provider.d.ts.map +1 -0
- package/dist/sessions/cognitive-provider.js +208 -0
- package/dist/sessions/cognitive-provider.js.map +1 -0
- package/dist/sessions/cognitive-sink.d.ts +73 -0
- package/dist/sessions/cognitive-sink.d.ts.map +1 -0
- package/dist/sessions/cognitive-sink.js +154 -0
- package/dist/sessions/cognitive-sink.js.map +1 -0
- package/dist/sessions/diagnostics.d.ts +70 -0
- package/dist/sessions/diagnostics.d.ts.map +1 -0
- package/dist/sessions/diagnostics.js +129 -0
- package/dist/sessions/diagnostics.js.map +1 -0
- package/dist/sessions/diagnostics.test.d.ts +2 -0
- package/dist/sessions/diagnostics.test.d.ts.map +1 -0
- package/dist/sessions/diagnostics.test.js +135 -0
- package/dist/sessions/diagnostics.test.js.map +1 -0
- package/dist/sessions/index.d.ts +32 -0
- package/dist/sessions/index.d.ts.map +1 -0
- package/dist/sessions/index.js +33 -0
- package/dist/sessions/index.js.map +1 -0
- package/dist/sessions/pool.d.ts +218 -0
- package/dist/sessions/pool.d.ts.map +1 -0
- package/dist/sessions/pool.js +991 -0
- package/dist/sessions/pool.js.map +1 -0
- package/dist/sessions/pool.test.d.ts +2 -0
- package/dist/sessions/pool.test.d.ts.map +1 -0
- package/dist/sessions/pool.test.js +633 -0
- package/dist/sessions/pool.test.js.map +1 -0
- package/dist/sessions/print-session.d.ts +142 -0
- package/dist/sessions/print-session.d.ts.map +1 -0
- package/dist/sessions/print-session.js +325 -0
- package/dist/sessions/print-session.js.map +1 -0
- package/dist/sessions/print-session.test.d.ts +2 -0
- package/dist/sessions/print-session.test.d.ts.map +1 -0
- package/dist/sessions/print-session.test.js +418 -0
- package/dist/sessions/print-session.test.js.map +1 -0
- package/dist/sessions/runtime-tools.d.ts +22 -0
- package/dist/sessions/runtime-tools.d.ts.map +1 -0
- package/dist/sessions/runtime-tools.js +162 -0
- package/dist/sessions/runtime-tools.js.map +1 -0
- package/dist/sessions/scope-hook.d.ts +77 -0
- package/dist/sessions/scope-hook.d.ts.map +1 -0
- package/dist/sessions/scope-hook.js +323 -0
- package/dist/sessions/scope-hook.js.map +1 -0
- package/dist/sessions/scope-hook.test.d.ts +2 -0
- package/dist/sessions/scope-hook.test.d.ts.map +1 -0
- package/dist/sessions/scope-hook.test.js +249 -0
- package/dist/sessions/scope-hook.test.js.map +1 -0
- package/dist/sessions/session-store/checkpoint-sink-impl.d.ts +16 -0
- package/dist/sessions/session-store/checkpoint-sink-impl.d.ts.map +1 -0
- package/dist/sessions/session-store/checkpoint-sink-impl.js +191 -0
- package/dist/sessions/session-store/checkpoint-sink-impl.js.map +1 -0
- package/dist/sessions/session-store/checkpoint-sink-impl.test.d.ts +5 -0
- package/dist/sessions/session-store/checkpoint-sink-impl.test.d.ts.map +1 -0
- package/dist/sessions/session-store/checkpoint-sink-impl.test.js +137 -0
- package/dist/sessions/session-store/checkpoint-sink-impl.test.js.map +1 -0
- package/dist/sessions/session-store/conformance.d.ts +59 -0
- package/dist/sessions/session-store/conformance.d.ts.map +1 -0
- package/dist/sessions/session-store/conformance.js +172 -0
- package/dist/sessions/session-store/conformance.js.map +1 -0
- package/dist/sessions/session-store/conformance.test.d.ts +7 -0
- package/dist/sessions/session-store/conformance.test.d.ts.map +1 -0
- package/dist/sessions/session-store/conformance.test.js +22 -0
- package/dist/sessions/session-store/conformance.test.js.map +1 -0
- package/dist/sessions/session-store/in-memory-session-store.d.ts +23 -0
- package/dist/sessions/session-store/in-memory-session-store.d.ts.map +1 -0
- package/dist/sessions/session-store/in-memory-session-store.js +197 -0
- package/dist/sessions/session-store/in-memory-session-store.js.map +1 -0
- package/dist/sessions/session-store/in-memory-session-store.test.d.ts +6 -0
- package/dist/sessions/session-store/in-memory-session-store.test.d.ts.map +1 -0
- package/dist/sessions/session-store/in-memory-session-store.test.js +183 -0
- package/dist/sessions/session-store/in-memory-session-store.test.js.map +1 -0
- package/dist/sessions/session-store/index.d.ts +20 -0
- package/dist/sessions/session-store/index.d.ts.map +1 -0
- package/dist/sessions/session-store/index.js +15 -0
- package/dist/sessions/session-store/index.js.map +1 -0
- package/dist/sessions/session-store/resume.d.ts +88 -0
- package/dist/sessions/session-store/resume.d.ts.map +1 -0
- package/dist/sessions/session-store/resume.js +96 -0
- package/dist/sessions/session-store/resume.js.map +1 -0
- package/dist/sessions/session-store/resume.test.d.ts +5 -0
- package/dist/sessions/session-store/resume.test.d.ts.map +1 -0
- package/dist/sessions/session-store/resume.test.js +119 -0
- package/dist/sessions/session-store/resume.test.js.map +1 -0
- package/dist/sessions/spawn-queue.d.ts +28 -0
- package/dist/sessions/spawn-queue.d.ts.map +1 -0
- package/dist/sessions/spawn-queue.js +63 -0
- package/dist/sessions/spawn-queue.js.map +1 -0
- package/dist/sessions/spawn-queue.test.d.ts +2 -0
- package/dist/sessions/spawn-queue.test.d.ts.map +1 -0
- package/dist/sessions/spawn-queue.test.js +65 -0
- package/dist/sessions/spawn-queue.test.js.map +1 -0
- package/dist/sessions/types.d.ts +16 -0
- package/dist/sessions/types.d.ts.map +1 -0
- package/dist/sessions/types.js +11 -0
- package/dist/sessions/types.js.map +1 -0
- package/dist/sessions/worktree-stale.test.d.ts +2 -0
- package/dist/sessions/worktree-stale.test.d.ts.map +1 -0
- package/dist/sessions/worktree-stale.test.js +468 -0
- package/dist/sessions/worktree-stale.test.js.map +1 -0
- package/dist/strategy/artifact-store.d.ts +12 -0
- package/dist/strategy/artifact-store.d.ts.map +1 -0
- package/dist/strategy/artifact-store.js +12 -0
- package/dist/strategy/artifact-store.js.map +1 -0
- package/dist/strategy/artifact-store.test.d.ts +2 -0
- package/dist/strategy/artifact-store.test.d.ts.map +1 -0
- package/dist/strategy/artifact-store.test.js +170 -0
- package/dist/strategy/artifact-store.test.js.map +1 -0
- package/dist/strategy/context-load-executor.d.ts +23 -0
- package/dist/strategy/context-load-executor.d.ts.map +1 -0
- package/dist/strategy/context-load-executor.js +87 -0
- package/dist/strategy/context-load-executor.js.map +1 -0
- package/dist/strategy/context-load-executor.test.d.ts +16 -0
- package/dist/strategy/context-load-executor.test.d.ts.map +1 -0
- package/dist/strategy/context-load-executor.test.js +158 -0
- package/dist/strategy/context-load-executor.test.js.map +1 -0
- package/dist/strategy/cortex-cross-app-invoker.stub.d.ts +65 -0
- package/dist/strategy/cortex-cross-app-invoker.stub.d.ts.map +1 -0
- package/dist/strategy/cortex-cross-app-invoker.stub.js +68 -0
- package/dist/strategy/cortex-cross-app-invoker.stub.js.map +1 -0
- package/dist/strategy/cross-app-node-executor.d.ts +54 -0
- package/dist/strategy/cross-app-node-executor.d.ts.map +1 -0
- package/dist/strategy/cross-app-node-executor.js +98 -0
- package/dist/strategy/cross-app-node-executor.js.map +1 -0
- package/dist/strategy/cross-app-node-executor.test.d.ts +13 -0
- package/dist/strategy/cross-app-node-executor.test.d.ts.map +1 -0
- package/dist/strategy/cross-app-node-executor.test.js +160 -0
- package/dist/strategy/cross-app-node-executor.test.js.map +1 -0
- package/dist/strategy/gates.d.ts +13 -0
- package/dist/strategy/gates.d.ts.map +1 -0
- package/dist/strategy/gates.js +13 -0
- package/dist/strategy/gates.js.map +1 -0
- package/dist/strategy/gates.test.d.ts +2 -0
- package/dist/strategy/gates.test.d.ts.map +1 -0
- package/dist/strategy/gates.test.js +299 -0
- package/dist/strategy/gates.test.js.map +1 -0
- package/dist/strategy/human-approval-resolver.d.ts +23 -0
- package/dist/strategy/human-approval-resolver.d.ts.map +1 -0
- package/dist/strategy/human-approval-resolver.js +94 -0
- package/dist/strategy/human-approval-resolver.js.map +1 -0
- package/dist/strategy/human-approval-resolver.test.d.ts +16 -0
- package/dist/strategy/human-approval-resolver.test.d.ts.map +1 -0
- package/dist/strategy/human-approval-resolver.test.js +200 -0
- package/dist/strategy/human-approval-resolver.test.js.map +1 -0
- package/dist/strategy/in-process-cross-app-invoker.d.ts +105 -0
- package/dist/strategy/in-process-cross-app-invoker.d.ts.map +1 -0
- package/dist/strategy/in-process-cross-app-invoker.js +206 -0
- package/dist/strategy/in-process-cross-app-invoker.js.map +1 -0
- package/dist/strategy/in-process-cross-app-invoker.test.d.ts +15 -0
- package/dist/strategy/in-process-cross-app-invoker.test.d.ts.map +1 -0
- package/dist/strategy/in-process-cross-app-invoker.test.js +190 -0
- package/dist/strategy/in-process-cross-app-invoker.test.js.map +1 -0
- package/dist/strategy/index.d.ts +29 -0
- package/dist/strategy/index.d.ts.map +1 -0
- package/dist/strategy/index.js +29 -0
- package/dist/strategy/index.js.map +1 -0
- package/dist/strategy/pacta-strategy.d.ts +97 -0
- package/dist/strategy/pacta-strategy.d.ts.map +1 -0
- package/dist/strategy/pacta-strategy.js +117 -0
- package/dist/strategy/pacta-strategy.js.map +1 -0
- package/dist/strategy/pacta-strategy.test.d.ts +2 -0
- package/dist/strategy/pacta-strategy.test.d.ts.map +1 -0
- package/dist/strategy/pacta-strategy.test.js +234 -0
- package/dist/strategy/pacta-strategy.test.js.map +1 -0
- package/dist/strategy/retro-generator.d.ts +18 -0
- package/dist/strategy/retro-generator.d.ts.map +1 -0
- package/dist/strategy/retro-generator.js +22 -0
- package/dist/strategy/retro-generator.js.map +1 -0
- package/dist/strategy/retro-writer.d.ts +25 -0
- package/dist/strategy/retro-writer.d.ts.map +1 -0
- package/dist/strategy/retro-writer.js +65 -0
- package/dist/strategy/retro-writer.js.map +1 -0
- package/dist/strategy/strategy-executor.d.ts +39 -0
- package/dist/strategy/strategy-executor.d.ts.map +1 -0
- package/dist/strategy/strategy-executor.js +253 -0
- package/dist/strategy/strategy-executor.js.map +1 -0
- package/dist/strategy/strategy-executor.test.d.ts +8 -0
- package/dist/strategy/strategy-executor.test.d.ts.map +1 -0
- package/dist/strategy/strategy-executor.test.js +1301 -0
- package/dist/strategy/strategy-executor.test.js.map +1 -0
- package/dist/strategy/strategy-parser.d.ts +30 -0
- package/dist/strategy/strategy-parser.d.ts.map +1 -0
- package/dist/strategy/strategy-parser.js +30 -0
- package/dist/strategy/strategy-parser.js.map +1 -0
- package/dist/strategy/sub-strategy-source.d.ts +27 -0
- package/dist/strategy/sub-strategy-source.d.ts.map +1 -0
- package/dist/strategy/sub-strategy-source.js +77 -0
- package/dist/strategy/sub-strategy-source.js.map +1 -0
- package/dist/strategy/types.d.ts +12 -0
- package/dist/strategy/types.d.ts.map +1 -0
- package/dist/strategy/types.js +9 -0
- package/dist/strategy/types.js.map +1 -0
- package/package.json +87 -0
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
2
|
+
/**
|
|
3
|
+
* SpawnQueue — enforces a minimum gap between PTY session spawns.
|
|
4
|
+
*
|
|
5
|
+
* Problem: concurrent spawns cause API rate-limit contention and resource
|
|
6
|
+
* spikes (PRD 012 observation). The bridge HTTP handler already staggers
|
|
7
|
+
* batch spawns with setTimeout, but individual bridge_spawn calls from
|
|
8
|
+
* different orchestrators can still fire simultaneously.
|
|
9
|
+
*
|
|
10
|
+
* Solution: all spawn requests pass through SpawnQueue.enqueue(), which
|
|
11
|
+
* ensures at least MIN_SPAWN_GAP_MS between actual PTY process launches.
|
|
12
|
+
* The queue is FIFO and serializes execution.
|
|
13
|
+
*/
|
|
14
|
+
const DEFAULT_MIN_SPAWN_GAP_MS = 2000;
|
|
15
|
+
export class SpawnQueue {
|
|
16
|
+
minGapMs;
|
|
17
|
+
lastSpawnAt = 0;
|
|
18
|
+
queue = [];
|
|
19
|
+
processing = false;
|
|
20
|
+
constructor(options) {
|
|
21
|
+
this.minGapMs = options?.minGapMs ?? DEFAULT_MIN_SPAWN_GAP_MS;
|
|
22
|
+
}
|
|
23
|
+
enqueue(execute) {
|
|
24
|
+
return new Promise((resolve, reject) => {
|
|
25
|
+
this.queue.push({
|
|
26
|
+
execute: execute,
|
|
27
|
+
resolve: resolve,
|
|
28
|
+
reject,
|
|
29
|
+
});
|
|
30
|
+
this.drain();
|
|
31
|
+
});
|
|
32
|
+
}
|
|
33
|
+
get pending() {
|
|
34
|
+
return this.queue.length;
|
|
35
|
+
}
|
|
36
|
+
get lastSpawnTime() {
|
|
37
|
+
return this.lastSpawnAt;
|
|
38
|
+
}
|
|
39
|
+
async drain() {
|
|
40
|
+
if (this.processing)
|
|
41
|
+
return;
|
|
42
|
+
this.processing = true;
|
|
43
|
+
while (this.queue.length > 0) {
|
|
44
|
+
const item = this.queue.shift();
|
|
45
|
+
const elapsed = Date.now() - this.lastSpawnAt;
|
|
46
|
+
if (elapsed < this.minGapMs && this.lastSpawnAt > 0) {
|
|
47
|
+
const waitMs = this.minGapMs - elapsed;
|
|
48
|
+
await new Promise(r => setTimeout(r, waitMs));
|
|
49
|
+
}
|
|
50
|
+
try {
|
|
51
|
+
const result = await item.execute();
|
|
52
|
+
this.lastSpawnAt = Date.now();
|
|
53
|
+
item.resolve(result);
|
|
54
|
+
}
|
|
55
|
+
catch (err) {
|
|
56
|
+
this.lastSpawnAt = Date.now();
|
|
57
|
+
item.reject(err);
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
this.processing = false;
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
//# sourceMappingURL=spawn-queue.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"spawn-queue.js","sourceRoot":"","sources":["../../src/sessions/spawn-queue.ts"],"names":[],"mappings":"AAAA,sCAAsC;AACtC;;;;;;;;;;;GAWG;AAOH,MAAM,wBAAwB,GAAG,IAAI,CAAC;AAEtC,MAAM,OAAO,UAAU;IACJ,QAAQ,CAAS;IAC1B,WAAW,GAAG,CAAC,CAAC;IAChB,KAAK,GAIR,EAAE,CAAC;IACA,UAAU,GAAG,KAAK,CAAC;IAE3B,YAAY,OAA2B;QACrC,IAAI,CAAC,QAAQ,GAAG,OAAO,EAAE,QAAQ,IAAI,wBAAwB,CAAC;IAChE,CAAC;IAED,OAAO,CAAI,OAAyB;QAClC,OAAO,IAAI,OAAO,CAAI,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;YACxC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC;gBACd,OAAO,EAAE,OAAiC;gBAC1C,OAAO,EAAE,OAAmC;gBAC5C,MAAM;aACP,CAAC,CAAC;YACH,IAAI,CAAC,KAAK,EAAE,CAAC;QACf,CAAC,CAAC,CAAC;IACL,CAAC;IAED,IAAI,OAAO;QACT,OAAO,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC;IAC3B,CAAC;IAED,IAAI,aAAa;QACf,OAAO,IAAI,CAAC,WAAW,CAAC;IAC1B,CAAC;IAEO,KAAK,CAAC,KAAK;QACjB,IAAI,IAAI,CAAC,UAAU;YAAE,OAAO;QAC5B,IAAI,CAAC,UAAU,GAAG,IAAI,CAAC;QAEvB,OAAO,IAAI,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YAC7B,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,KAAK,EAAG,CAAC;YAEjC,MAAM,OAAO,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC,WAAW,CAAC;YAC9C,IAAI,OAAO,GAAG,IAAI,CAAC,QAAQ,IAAI,IAAI,CAAC,WAAW,GAAG,CAAC,EAAE,CAAC;gBACpD,MAAM,MAAM,GAAG,IAAI,CAAC,QAAQ,GAAG,OAAO,CAAC;gBACvC,MAAM,IAAI,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC,UAAU,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC,CAAC;YAChD,CAAC;YAED,IAAI,CAAC;gBACH,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,OAAO,EAAE,CAAC;gBACpC,IAAI,CAAC,WAAW,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;gBAC9B,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;YACvB,CAAC;YAAC,OAAO,GAAG,EAAE,CAAC;gBACb,IAAI,CAAC,WAAW,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;gBAC9B,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;YACnB,CAAC;QACH,CAAC;QAED,IAAI,CAAC,UAAU,GAAG,KAAK,CAAC;IAC1B,CAAC;CACF"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"spawn-queue.test.d.ts","sourceRoot":"","sources":["../../src/sessions/spawn-queue.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
2
|
+
import { describe, it } from 'node:test';
|
|
3
|
+
import assert from 'node:assert/strict';
|
|
4
|
+
import { SpawnQueue } from './spawn-queue.js';
|
|
5
|
+
describe('SpawnQueue', () => {
|
|
6
|
+
it('executes a single enqueued operation', async () => {
|
|
7
|
+
const queue = new SpawnQueue({ minGapMs: 0 });
|
|
8
|
+
const result = await queue.enqueue(() => Promise.resolve('hello'));
|
|
9
|
+
assert.equal(result, 'hello');
|
|
10
|
+
});
|
|
11
|
+
it('enforces minimum gap between consecutive spawns', async () => {
|
|
12
|
+
const gapMs = 100;
|
|
13
|
+
const queue = new SpawnQueue({ minGapMs: gapMs });
|
|
14
|
+
const timestamps = [];
|
|
15
|
+
await queue.enqueue(async () => { timestamps.push(Date.now()); });
|
|
16
|
+
await queue.enqueue(async () => { timestamps.push(Date.now()); });
|
|
17
|
+
assert.equal(timestamps.length, 2);
|
|
18
|
+
const elapsed = timestamps[1] - timestamps[0];
|
|
19
|
+
assert.ok(elapsed >= gapMs - 20, `Expected >= ${gapMs - 20}ms gap, got ${elapsed}ms`);
|
|
20
|
+
});
|
|
21
|
+
it('does not delay the first spawn', async () => {
|
|
22
|
+
const queue = new SpawnQueue({ minGapMs: 5000 });
|
|
23
|
+
const before = Date.now();
|
|
24
|
+
await queue.enqueue(async () => 'fast');
|
|
25
|
+
const elapsed = Date.now() - before;
|
|
26
|
+
assert.ok(elapsed < 100, `First spawn should be immediate, took ${elapsed}ms`);
|
|
27
|
+
});
|
|
28
|
+
it('serializes concurrent enqueue calls', async () => {
|
|
29
|
+
const gapMs = 50;
|
|
30
|
+
const queue = new SpawnQueue({ minGapMs: gapMs });
|
|
31
|
+
const order = [];
|
|
32
|
+
const p1 = queue.enqueue(async () => { order.push(1); return 1; });
|
|
33
|
+
const p2 = queue.enqueue(async () => { order.push(2); return 2; });
|
|
34
|
+
const p3 = queue.enqueue(async () => { order.push(3); return 3; });
|
|
35
|
+
const results = await Promise.all([p1, p2, p3]);
|
|
36
|
+
assert.deepEqual(order, [1, 2, 3]);
|
|
37
|
+
assert.deepEqual(results, [1, 2, 3]);
|
|
38
|
+
});
|
|
39
|
+
it('propagates errors without blocking the queue', async () => {
|
|
40
|
+
const queue = new SpawnQueue({ minGapMs: 0 });
|
|
41
|
+
await assert.rejects(() => queue.enqueue(async () => { throw new Error('boom'); }), /boom/);
|
|
42
|
+
const result = await queue.enqueue(async () => 'recovered');
|
|
43
|
+
assert.equal(result, 'recovered');
|
|
44
|
+
});
|
|
45
|
+
it('reports pending count', async () => {
|
|
46
|
+
const queue = new SpawnQueue({ minGapMs: 100 });
|
|
47
|
+
assert.equal(queue.pending, 0);
|
|
48
|
+
let pendingDuringSecond = -1;
|
|
49
|
+
const p1 = queue.enqueue(async () => 'a');
|
|
50
|
+
const p2 = queue.enqueue(async () => {
|
|
51
|
+
pendingDuringSecond = queue.pending;
|
|
52
|
+
return 'b';
|
|
53
|
+
});
|
|
54
|
+
const p3 = queue.enqueue(async () => 'c');
|
|
55
|
+
await Promise.all([p1, p2, p3]);
|
|
56
|
+
assert.equal(pendingDuringSecond, 1);
|
|
57
|
+
assert.equal(queue.pending, 0);
|
|
58
|
+
});
|
|
59
|
+
it('uses default minGapMs when no options provided', async () => {
|
|
60
|
+
const queue = new SpawnQueue();
|
|
61
|
+
const result = await queue.enqueue(async () => 42);
|
|
62
|
+
assert.equal(result, 42);
|
|
63
|
+
});
|
|
64
|
+
});
|
|
65
|
+
//# sourceMappingURL=spawn-queue.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"spawn-queue.test.js","sourceRoot":"","sources":["../../src/sessions/spawn-queue.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Sessions domain — collected type re-exports (PRD-057 / S2 §3.3 / C5).
|
|
3
|
+
*
|
|
4
|
+
* Transcript reader, routes, and `SessionsConfig` types live in
|
|
5
|
+
* `@methodts/bridge` — this barrel now re-exports only the types that
|
|
6
|
+
* belong to the runtime subpath. Bridge-internal code that needs the
|
|
7
|
+
* full historical bundle should import the specific modules directly.
|
|
8
|
+
*/
|
|
9
|
+
export type { SessionPool, SessionBudget, SessionChainInfo, SessionMode, IsolationMode, WorktreeAction, WorktreeInfo, StaleConfig, SessionStatusInfo, PoolStats, PoolOptions, StreamEvent, } from './pool.js';
|
|
10
|
+
export type { PtySession, SessionStatus, AdaptiveSettleDelay } from './print-session.js';
|
|
11
|
+
export type { ActivityObservation } from './auto-retro.js';
|
|
12
|
+
export type { ChannelMessage, Channel, SessionChannels } from './channels.js';
|
|
13
|
+
export type { SessionDiagnostics } from './diagnostics.js';
|
|
14
|
+
export type { CognitiveSessionConfig, CognitiveSessionOptions, } from './cognitive-provider.js';
|
|
15
|
+
export type { CognitiveEventContext } from './cognitive-sink.js';
|
|
16
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/sessions/types.ts"],"names":[],"mappings":"AACA;;;;;;;GAOG;AAGH,YAAY,EACV,WAAW,EACX,aAAa,EACb,gBAAgB,EAChB,WAAW,EACX,aAAa,EACb,cAAc,EACd,YAAY,EACZ,WAAW,EACX,iBAAiB,EACjB,SAAS,EACT,WAAW,EACX,WAAW,GACZ,MAAM,WAAW,CAAC;AAGnB,YAAY,EAAE,UAAU,EAAE,aAAa,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAC;AAGzF,YAAY,EAAE,mBAAmB,EAAE,MAAM,iBAAiB,CAAC;AAG3D,YAAY,EAAE,cAAc,EAAE,OAAO,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAG9E,YAAY,EAAE,kBAAkB,EAAE,MAAM,kBAAkB,CAAC;AAG3D,YAAY,EACV,sBAAsB,EACtB,uBAAuB,GACxB,MAAM,yBAAyB,CAAC;AACjC,YAAY,EAAE,qBAAqB,EAAE,MAAM,qBAAqB,CAAC"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
2
|
+
/**
|
|
3
|
+
* Sessions domain — collected type re-exports (PRD-057 / S2 §3.3 / C5).
|
|
4
|
+
*
|
|
5
|
+
* Transcript reader, routes, and `SessionsConfig` types live in
|
|
6
|
+
* `@methodts/bridge` — this barrel now re-exports only the types that
|
|
7
|
+
* belong to the runtime subpath. Bridge-internal code that needs the
|
|
8
|
+
* full historical bundle should import the specific modules directly.
|
|
9
|
+
*/
|
|
10
|
+
export {};
|
|
11
|
+
//# sourceMappingURL=types.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/sessions/types.ts"],"names":[],"mappings":"AAAA,sCAAsC;AACtC;;;;;;;GAOG"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"worktree-stale.test.d.ts","sourceRoot":"","sources":["../../src/sessions/worktree-stale.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,468 @@
|
|
|
1
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
2
|
+
import { describe, it } from 'node:test';
|
|
3
|
+
import assert from 'node:assert/strict';
|
|
4
|
+
import { createSessionChannels, appendMessage, readMessages, } from './channels.js';
|
|
5
|
+
/**
|
|
6
|
+
* Create a fake PtySession for testing without spawning a real PTY process.
|
|
7
|
+
* Supports controllable lastActivityAt for stale detection tests.
|
|
8
|
+
*/
|
|
9
|
+
function fakePtySession(id, initialStatus = 'ready') {
|
|
10
|
+
let status = initialStatus;
|
|
11
|
+
let promptCount = 0;
|
|
12
|
+
let lastActivityAt = new Date();
|
|
13
|
+
return {
|
|
14
|
+
id,
|
|
15
|
+
get status() { return status; },
|
|
16
|
+
set status(s) { status = s; },
|
|
17
|
+
queueDepth: 0,
|
|
18
|
+
get promptCount() { return promptCount; },
|
|
19
|
+
set promptCount(n) { promptCount = n; },
|
|
20
|
+
get lastActivityAt() { return lastActivityAt; },
|
|
21
|
+
set lastActivityAt(d) { lastActivityAt = d; },
|
|
22
|
+
get transcript() { return ''; },
|
|
23
|
+
onOutput(_cb) { return () => { }; },
|
|
24
|
+
onExit(_cb) { },
|
|
25
|
+
async sendPrompt(_prompt, _timeoutMs, _settleDelayMs) {
|
|
26
|
+
promptCount++;
|
|
27
|
+
lastActivityAt = new Date();
|
|
28
|
+
return { output: 'mock response', timedOut: false };
|
|
29
|
+
},
|
|
30
|
+
resize() { },
|
|
31
|
+
kill() {
|
|
32
|
+
status = 'dead';
|
|
33
|
+
},
|
|
34
|
+
interrupt() { return false; },
|
|
35
|
+
adaptiveSettle: null,
|
|
36
|
+
pid: null,
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
const DEFAULT_CHAIN = {
|
|
40
|
+
parent_session_id: null,
|
|
41
|
+
depth: 0,
|
|
42
|
+
children: [],
|
|
43
|
+
budget: { max_depth: 3, max_agents: 10, agents_spawned: 0 },
|
|
44
|
+
};
|
|
45
|
+
const DEFAULT_WORKTREE = {
|
|
46
|
+
isolation: 'shared',
|
|
47
|
+
worktree_path: null,
|
|
48
|
+
worktree_branch: null,
|
|
49
|
+
metals_available: true,
|
|
50
|
+
};
|
|
51
|
+
/**
|
|
52
|
+
* Test pool with stale detection support.
|
|
53
|
+
* Sessions can have their lastActivityAt manipulated for stale tests.
|
|
54
|
+
*/
|
|
55
|
+
function createStaleTestPool(maxSessions = 5) {
|
|
56
|
+
const sessions = new Map();
|
|
57
|
+
const sessionMetadata = new Map();
|
|
58
|
+
const sessionWorkdirs = new Map();
|
|
59
|
+
const sessionChains = new Map();
|
|
60
|
+
const sessionChannelsMap = new Map();
|
|
61
|
+
const sessionStaleConfigs = new Map();
|
|
62
|
+
const sessionStaleFlags = new Map();
|
|
63
|
+
let totalSpawned = 0;
|
|
64
|
+
const startedAt = new Date();
|
|
65
|
+
let nextId = 0;
|
|
66
|
+
// Expose internals for test manipulation
|
|
67
|
+
const _internals = { sessions, sessionStaleConfigs, sessionStaleFlags, sessionChannelsMap };
|
|
68
|
+
const pool = {
|
|
69
|
+
_internals,
|
|
70
|
+
async create({ workdir, initialPrompt: _initialPrompt, spawnArgs: _spawnArgs, metadata, parentSessionId, depth, budget, isolation: _isolation, timeout_ms }) {
|
|
71
|
+
const activeSessions = [...sessions.values()].filter((s) => s.status !== 'dead').length;
|
|
72
|
+
if (activeSessions >= maxSessions) {
|
|
73
|
+
throw new Error(`Session pool full — maximum ${maxSessions} active sessions`);
|
|
74
|
+
}
|
|
75
|
+
const effectiveDepth = depth ?? 0;
|
|
76
|
+
const effectiveBudget = {
|
|
77
|
+
max_depth: budget?.max_depth ?? 3,
|
|
78
|
+
max_agents: budget?.max_agents ?? 10,
|
|
79
|
+
agents_spawned: budget?.agents_spawned ?? 0,
|
|
80
|
+
};
|
|
81
|
+
if (parentSessionId) {
|
|
82
|
+
const parentChain = sessionChains.get(parentSessionId);
|
|
83
|
+
if (parentChain) {
|
|
84
|
+
if (effectiveDepth >= parentChain.budget.max_depth) {
|
|
85
|
+
throw new Error(JSON.stringify({ error: 'DEPTH_EXCEEDED' }));
|
|
86
|
+
}
|
|
87
|
+
if (parentChain.budget.agents_spawned >= parentChain.budget.max_agents) {
|
|
88
|
+
throw new Error(JSON.stringify({ error: 'BUDGET_EXHAUSTED' }));
|
|
89
|
+
}
|
|
90
|
+
parentChain.budget.agents_spawned++;
|
|
91
|
+
effectiveBudget.max_depth = parentChain.budget.max_depth;
|
|
92
|
+
effectiveBudget.max_agents = parentChain.budget.max_agents;
|
|
93
|
+
effectiveBudget.agents_spawned = parentChain.budget.agents_spawned;
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
const sessionId = `test-session-${nextId++}`;
|
|
97
|
+
const session = fakePtySession(sessionId);
|
|
98
|
+
sessions.set(sessionId, session);
|
|
99
|
+
sessionWorkdirs.set(sessionId, workdir);
|
|
100
|
+
if (metadata)
|
|
101
|
+
sessionMetadata.set(sessionId, metadata);
|
|
102
|
+
const chainInfo = {
|
|
103
|
+
parent_session_id: parentSessionId ?? null,
|
|
104
|
+
depth: effectiveDepth,
|
|
105
|
+
children: [],
|
|
106
|
+
budget: effectiveBudget,
|
|
107
|
+
};
|
|
108
|
+
sessionChains.set(sessionId, chainInfo);
|
|
109
|
+
const channels = createSessionChannels();
|
|
110
|
+
sessionChannelsMap.set(sessionId, channels);
|
|
111
|
+
appendMessage(channels.events, 'bridge', 'started', { session_id: sessionId });
|
|
112
|
+
// Stale config
|
|
113
|
+
const staleConfig = {
|
|
114
|
+
stale_timeout_ms: timeout_ms ?? 30 * 60 * 1000,
|
|
115
|
+
kill_timeout_ms: timeout_ms ? timeout_ms * 2 : 60 * 60 * 1000,
|
|
116
|
+
};
|
|
117
|
+
sessionStaleConfigs.set(sessionId, staleConfig);
|
|
118
|
+
sessionStaleFlags.set(sessionId, false);
|
|
119
|
+
if (parentSessionId) {
|
|
120
|
+
const parentChain = sessionChains.get(parentSessionId);
|
|
121
|
+
if (parentChain)
|
|
122
|
+
parentChain.children.push(sessionId);
|
|
123
|
+
}
|
|
124
|
+
totalSpawned++;
|
|
125
|
+
return { sessionId, nickname: `test-${nextId - 1}`, status: session.status, chain: chainInfo, worktree: DEFAULT_WORKTREE, mode: 'print' };
|
|
126
|
+
},
|
|
127
|
+
async prompt(sessionId, prompt, timeoutMs, settleDelayMs) {
|
|
128
|
+
const session = sessions.get(sessionId);
|
|
129
|
+
if (!session)
|
|
130
|
+
throw new Error(`Session not found: ${sessionId}`);
|
|
131
|
+
if (session.status === 'dead')
|
|
132
|
+
throw new Error(`Session ${sessionId} is dead`);
|
|
133
|
+
// Reset stale flag on activity
|
|
134
|
+
sessionStaleFlags.set(sessionId, false);
|
|
135
|
+
const result = await session.sendPrompt(prompt, timeoutMs, settleDelayMs);
|
|
136
|
+
return { output: result.output, timedOut: result.timedOut, metadata: null };
|
|
137
|
+
},
|
|
138
|
+
async promptStream(sessionId, prompt, onEvent, timeoutMs) {
|
|
139
|
+
const result = await pool.prompt(sessionId, prompt, timeoutMs);
|
|
140
|
+
onEvent({ type: 'done', output: result.output, metadata: null, timed_out: result.timedOut });
|
|
141
|
+
},
|
|
142
|
+
status(sessionId) {
|
|
143
|
+
const session = sessions.get(sessionId);
|
|
144
|
+
if (!session)
|
|
145
|
+
throw new Error(`Session not found: ${sessionId}`);
|
|
146
|
+
return {
|
|
147
|
+
sessionId: session.id,
|
|
148
|
+
nickname: session.id,
|
|
149
|
+
purpose: null,
|
|
150
|
+
status: session.status,
|
|
151
|
+
queueDepth: session.queueDepth,
|
|
152
|
+
metadata: sessionMetadata.get(sessionId),
|
|
153
|
+
promptCount: session.promptCount,
|
|
154
|
+
lastActivityAt: session.lastActivityAt,
|
|
155
|
+
workdir: sessionWorkdirs.get(sessionId) ?? '',
|
|
156
|
+
chain: sessionChains.get(sessionId) ?? DEFAULT_CHAIN,
|
|
157
|
+
worktree: DEFAULT_WORKTREE,
|
|
158
|
+
stale: sessionStaleFlags.get(sessionId) ?? false,
|
|
159
|
+
waiting_for: null,
|
|
160
|
+
mode: 'print',
|
|
161
|
+
diagnostics: null,
|
|
162
|
+
};
|
|
163
|
+
},
|
|
164
|
+
kill(sessionId, _worktreeAction) {
|
|
165
|
+
const session = sessions.get(sessionId);
|
|
166
|
+
if (!session)
|
|
167
|
+
throw new Error(`Session not found: ${sessionId}`);
|
|
168
|
+
session.kill();
|
|
169
|
+
const channels = sessionChannelsMap.get(sessionId);
|
|
170
|
+
if (channels) {
|
|
171
|
+
appendMessage(channels.events, 'bridge', 'killed', { session_id: sessionId });
|
|
172
|
+
}
|
|
173
|
+
return { sessionId: session.id, killed: true, worktree_cleaned: false };
|
|
174
|
+
},
|
|
175
|
+
list() {
|
|
176
|
+
return [...sessions.entries()].map(([sessionId, session]) => ({
|
|
177
|
+
sessionId: session.id,
|
|
178
|
+
nickname: session.id,
|
|
179
|
+
purpose: null,
|
|
180
|
+
status: session.status,
|
|
181
|
+
queueDepth: session.queueDepth,
|
|
182
|
+
metadata: sessionMetadata.get(sessionId),
|
|
183
|
+
promptCount: session.promptCount,
|
|
184
|
+
lastActivityAt: session.lastActivityAt,
|
|
185
|
+
workdir: sessionWorkdirs.get(sessionId) ?? '',
|
|
186
|
+
chain: sessionChains.get(sessionId) ?? DEFAULT_CHAIN,
|
|
187
|
+
worktree: DEFAULT_WORKTREE,
|
|
188
|
+
stale: sessionStaleFlags.get(sessionId) ?? false,
|
|
189
|
+
waiting_for: null,
|
|
190
|
+
mode: 'print',
|
|
191
|
+
diagnostics: null,
|
|
192
|
+
}));
|
|
193
|
+
},
|
|
194
|
+
getChannels(sessionId) {
|
|
195
|
+
const channels = sessionChannelsMap.get(sessionId);
|
|
196
|
+
if (!channels)
|
|
197
|
+
throw new Error(`Session not found: ${sessionId}`);
|
|
198
|
+
return channels;
|
|
199
|
+
},
|
|
200
|
+
getSession(sessionId) {
|
|
201
|
+
const session = sessions.get(sessionId);
|
|
202
|
+
if (!session)
|
|
203
|
+
throw new Error(`Session not found: ${sessionId}`);
|
|
204
|
+
return session;
|
|
205
|
+
},
|
|
206
|
+
poolStats() {
|
|
207
|
+
const allSessions = [...sessions.values()];
|
|
208
|
+
const active = allSessions.filter((s) => s.status !== 'dead').length;
|
|
209
|
+
const dead = allSessions.filter((s) => s.status === 'dead').length;
|
|
210
|
+
return { totalSpawned, startedAt, maxSessions, activeSessions: active, deadSessions: dead };
|
|
211
|
+
},
|
|
212
|
+
removeDead(ttlMs) {
|
|
213
|
+
let removed = 0;
|
|
214
|
+
for (const [sessionId, session] of sessions.entries()) {
|
|
215
|
+
if (session.status === 'dead' && Date.now() - session.lastActivityAt.getTime() > ttlMs) {
|
|
216
|
+
sessions.delete(sessionId);
|
|
217
|
+
sessionMetadata.delete(sessionId);
|
|
218
|
+
sessionWorkdirs.delete(sessionId);
|
|
219
|
+
sessionChains.delete(sessionId);
|
|
220
|
+
sessionChannelsMap.delete(sessionId);
|
|
221
|
+
sessionStaleConfigs.delete(sessionId);
|
|
222
|
+
sessionStaleFlags.delete(sessionId);
|
|
223
|
+
removed++;
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
return removed;
|
|
227
|
+
},
|
|
228
|
+
/**
|
|
229
|
+
* Stale detection — mirrors pool.ts checkStale() logic.
|
|
230
|
+
*/
|
|
231
|
+
checkStale() {
|
|
232
|
+
const now = Date.now();
|
|
233
|
+
const staleIds = [];
|
|
234
|
+
const killedIds = [];
|
|
235
|
+
for (const [sessionId, session] of sessions.entries()) {
|
|
236
|
+
if (session.status === 'dead')
|
|
237
|
+
continue;
|
|
238
|
+
const config = sessionStaleConfigs.get(sessionId);
|
|
239
|
+
if (!config)
|
|
240
|
+
continue;
|
|
241
|
+
const inactiveMs = now - session.lastActivityAt.getTime();
|
|
242
|
+
const isStale = sessionStaleFlags.get(sessionId) ?? false;
|
|
243
|
+
if (inactiveMs >= config.kill_timeout_ms) {
|
|
244
|
+
session.kill();
|
|
245
|
+
const channels = sessionChannelsMap.get(sessionId);
|
|
246
|
+
if (channels) {
|
|
247
|
+
appendMessage(channels.events, 'bridge', 'stale', {
|
|
248
|
+
session_id: sessionId,
|
|
249
|
+
inactive_ms: inactiveMs,
|
|
250
|
+
action: 'auto_killed',
|
|
251
|
+
});
|
|
252
|
+
}
|
|
253
|
+
killedIds.push(sessionId);
|
|
254
|
+
sessionStaleFlags.set(sessionId, true);
|
|
255
|
+
continue;
|
|
256
|
+
}
|
|
257
|
+
if (inactiveMs >= config.stale_timeout_ms && !isStale) {
|
|
258
|
+
sessionStaleFlags.set(sessionId, true);
|
|
259
|
+
const channels = sessionChannelsMap.get(sessionId);
|
|
260
|
+
if (channels) {
|
|
261
|
+
appendMessage(channels.events, 'bridge', 'stale', {
|
|
262
|
+
session_id: sessionId,
|
|
263
|
+
inactive_ms: inactiveMs,
|
|
264
|
+
action: 'marked_stale',
|
|
265
|
+
});
|
|
266
|
+
}
|
|
267
|
+
staleIds.push(sessionId);
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
return { stale: staleIds, killed: killedIds };
|
|
271
|
+
},
|
|
272
|
+
childPids() {
|
|
273
|
+
return [];
|
|
274
|
+
},
|
|
275
|
+
setObservationHook() {
|
|
276
|
+
// no-op in test pool
|
|
277
|
+
},
|
|
278
|
+
restoreSession() {
|
|
279
|
+
// no-op in test pool
|
|
280
|
+
},
|
|
281
|
+
cleanupStaleCognitiveSessions() {
|
|
282
|
+
return { killed: [] };
|
|
283
|
+
},
|
|
284
|
+
};
|
|
285
|
+
return pool;
|
|
286
|
+
}
|
|
287
|
+
// ── Worktree Isolation Tests (PRD 006 Component 2) ───────────
|
|
288
|
+
describe('Worktree Isolation (PRD 006 Component 2)', () => {
|
|
289
|
+
describe('WorktreeInfo defaults', () => {
|
|
290
|
+
it('shared session has metals_available: true and no worktree path', async () => {
|
|
291
|
+
const pool = createStaleTestPool();
|
|
292
|
+
const result = await pool.create({ workdir: '/tmp/test' });
|
|
293
|
+
assert.equal(result.worktree.isolation, 'shared');
|
|
294
|
+
assert.equal(result.worktree.worktree_path, null);
|
|
295
|
+
assert.equal(result.worktree.worktree_branch, null);
|
|
296
|
+
assert.equal(result.worktree.metals_available, true);
|
|
297
|
+
});
|
|
298
|
+
it('status includes worktree info', async () => {
|
|
299
|
+
const pool = createStaleTestPool();
|
|
300
|
+
const result = await pool.create({ workdir: '/tmp/test' });
|
|
301
|
+
const status = pool.status(result.sessionId);
|
|
302
|
+
assert.equal(status.worktree.isolation, 'shared');
|
|
303
|
+
assert.equal(status.worktree.metals_available, true);
|
|
304
|
+
});
|
|
305
|
+
it('list includes worktree info for all sessions', async () => {
|
|
306
|
+
const pool = createStaleTestPool();
|
|
307
|
+
await pool.create({ workdir: '/tmp/a' });
|
|
308
|
+
await pool.create({ workdir: '/tmp/b' });
|
|
309
|
+
const sessions = pool.list();
|
|
310
|
+
assert.equal(sessions.length, 2);
|
|
311
|
+
for (const s of sessions) {
|
|
312
|
+
assert.equal(s.worktree.isolation, 'shared');
|
|
313
|
+
assert.equal(s.worktree.metals_available, true);
|
|
314
|
+
}
|
|
315
|
+
});
|
|
316
|
+
});
|
|
317
|
+
describe('kill with worktree_action', () => {
|
|
318
|
+
it('kill returns worktree_cleaned: false for shared sessions', async () => {
|
|
319
|
+
const pool = createStaleTestPool();
|
|
320
|
+
const result = await pool.create({ workdir: '/tmp/test' });
|
|
321
|
+
const killResult = pool.kill(result.sessionId, 'discard');
|
|
322
|
+
assert.equal(killResult.killed, true);
|
|
323
|
+
assert.equal(killResult.worktree_cleaned, false);
|
|
324
|
+
});
|
|
325
|
+
it('kill without worktree_action defaults to keep', async () => {
|
|
326
|
+
const pool = createStaleTestPool();
|
|
327
|
+
const result = await pool.create({ workdir: '/tmp/test' });
|
|
328
|
+
const killResult = pool.kill(result.sessionId);
|
|
329
|
+
assert.equal(killResult.killed, true);
|
|
330
|
+
assert.equal(killResult.worktree_cleaned, false);
|
|
331
|
+
});
|
|
332
|
+
});
|
|
333
|
+
});
|
|
334
|
+
// ── Stale Detection Tests (PRD 006 Component 4) ─────────────
|
|
335
|
+
describe('Stale Detection (PRD 006 Component 4)', () => {
|
|
336
|
+
describe('stale flag defaults', () => {
|
|
337
|
+
it('new session is not stale', async () => {
|
|
338
|
+
const pool = createStaleTestPool();
|
|
339
|
+
const result = await pool.create({ workdir: '/tmp/test' });
|
|
340
|
+
const status = pool.status(result.sessionId);
|
|
341
|
+
assert.equal(status.stale, false);
|
|
342
|
+
});
|
|
343
|
+
it('list includes stale flag', async () => {
|
|
344
|
+
const pool = createStaleTestPool();
|
|
345
|
+
await pool.create({ workdir: '/tmp/a' });
|
|
346
|
+
const sessions = pool.list();
|
|
347
|
+
assert.equal(sessions[0].stale, false);
|
|
348
|
+
});
|
|
349
|
+
});
|
|
350
|
+
describe('checkStale()', () => {
|
|
351
|
+
it('returns empty arrays when no sessions are stale', async () => {
|
|
352
|
+
const pool = createStaleTestPool();
|
|
353
|
+
await pool.create({ workdir: '/tmp/test' });
|
|
354
|
+
const result = pool.checkStale();
|
|
355
|
+
assert.deepEqual(result.stale, []);
|
|
356
|
+
assert.deepEqual(result.killed, []);
|
|
357
|
+
});
|
|
358
|
+
it('marks session stale after stale_timeout_ms', async () => {
|
|
359
|
+
const pool = createStaleTestPool();
|
|
360
|
+
// Create with very short timeout for testing
|
|
361
|
+
const created = await pool.create({ workdir: '/tmp/test', timeout_ms: 50 });
|
|
362
|
+
// Simulate inactivity by backdating lastActivityAt well beyond the threshold
|
|
363
|
+
const session = pool._internals.sessions.get(created.sessionId);
|
|
364
|
+
session.lastActivityAt = new Date(Date.now() - 5000); // 5s ago, well past 50ms stale but under 100ms kill
|
|
365
|
+
// Override stale config to ensure kill timeout is far away
|
|
366
|
+
pool._internals.sessionStaleConfigs.set(created.sessionId, {
|
|
367
|
+
stale_timeout_ms: 50,
|
|
368
|
+
kill_timeout_ms: 999_999,
|
|
369
|
+
});
|
|
370
|
+
const result = pool.checkStale();
|
|
371
|
+
assert.deepEqual(result.stale, [created.sessionId]);
|
|
372
|
+
assert.deepEqual(result.killed, []);
|
|
373
|
+
// Status should now show stale
|
|
374
|
+
const status = pool.status(created.sessionId);
|
|
375
|
+
assert.equal(status.stale, true);
|
|
376
|
+
});
|
|
377
|
+
it('does not mark dead sessions as stale', async () => {
|
|
378
|
+
const pool = createStaleTestPool();
|
|
379
|
+
const created = await pool.create({ workdir: '/tmp/test', timeout_ms: 50 });
|
|
380
|
+
// Kill it first
|
|
381
|
+
pool.kill(created.sessionId);
|
|
382
|
+
// Backdate
|
|
383
|
+
const session = pool._internals.sessions.get(created.sessionId);
|
|
384
|
+
session.lastActivityAt = new Date(Date.now() - 100);
|
|
385
|
+
const result = pool.checkStale();
|
|
386
|
+
assert.deepEqual(result.stale, []);
|
|
387
|
+
assert.deepEqual(result.killed, []);
|
|
388
|
+
});
|
|
389
|
+
it('auto-kills session after kill_timeout_ms', async () => {
|
|
390
|
+
const pool = createStaleTestPool();
|
|
391
|
+
const created = await pool.create({ workdir: '/tmp/test', timeout_ms: 50 });
|
|
392
|
+
// kill_timeout_ms = 50 * 2 = 100
|
|
393
|
+
// Backdate beyond kill timeout
|
|
394
|
+
const session = pool._internals.sessions.get(created.sessionId);
|
|
395
|
+
session.lastActivityAt = new Date(Date.now() - 150); // 150ms ago, > 100ms kill timeout
|
|
396
|
+
const result = pool.checkStale();
|
|
397
|
+
assert.deepEqual(result.stale, []);
|
|
398
|
+
assert.deepEqual(result.killed, [created.sessionId]);
|
|
399
|
+
// Session should now be dead
|
|
400
|
+
assert.equal(session.status, 'dead');
|
|
401
|
+
});
|
|
402
|
+
it('emits stale event to channels when marking stale', async () => {
|
|
403
|
+
const pool = createStaleTestPool();
|
|
404
|
+
const created = await pool.create({ workdir: '/tmp/test', timeout_ms: 50 });
|
|
405
|
+
// Backdate
|
|
406
|
+
const session = pool._internals.sessions.get(created.sessionId);
|
|
407
|
+
session.lastActivityAt = new Date(Date.now() - 75); // Past stale, not past kill
|
|
408
|
+
pool.checkStale();
|
|
409
|
+
// Read events channel — should have 'started' + 'stale'
|
|
410
|
+
const channels = pool.getChannels(created.sessionId);
|
|
411
|
+
const events = readMessages(channels.events, 0);
|
|
412
|
+
assert.equal(events.messages.length, 2); // started + stale
|
|
413
|
+
assert.equal(events.messages[1].type, 'stale');
|
|
414
|
+
assert.equal(events.messages[1].content.action, 'marked_stale');
|
|
415
|
+
});
|
|
416
|
+
it('emits stale event with auto_killed action when killing', async () => {
|
|
417
|
+
const pool = createStaleTestPool();
|
|
418
|
+
const created = await pool.create({ workdir: '/tmp/test', timeout_ms: 50 });
|
|
419
|
+
const session = pool._internals.sessions.get(created.sessionId);
|
|
420
|
+
session.lastActivityAt = new Date(Date.now() - 150); // Past kill timeout
|
|
421
|
+
pool.checkStale();
|
|
422
|
+
const channels = pool.getChannels(created.sessionId);
|
|
423
|
+
const events = readMessages(channels.events, 0);
|
|
424
|
+
const staleEvent = events.messages.find(m => m.type === 'stale');
|
|
425
|
+
assert.ok(staleEvent);
|
|
426
|
+
assert.equal(staleEvent.content.action, 'auto_killed');
|
|
427
|
+
});
|
|
428
|
+
it('does not double-mark already stale sessions', async () => {
|
|
429
|
+
const pool = createStaleTestPool();
|
|
430
|
+
const created = await pool.create({ workdir: '/tmp/test', timeout_ms: 50 });
|
|
431
|
+
const session = pool._internals.sessions.get(created.sessionId);
|
|
432
|
+
session.lastActivityAt = new Date(Date.now() - 75); // Past stale, not kill
|
|
433
|
+
// First check — marks stale
|
|
434
|
+
const result1 = pool.checkStale();
|
|
435
|
+
assert.deepEqual(result1.stale, [created.sessionId]);
|
|
436
|
+
// Second check — already stale, should not re-mark
|
|
437
|
+
const result2 = pool.checkStale();
|
|
438
|
+
assert.deepEqual(result2.stale, []);
|
|
439
|
+
});
|
|
440
|
+
it('uses custom timeout_ms when provided', async () => {
|
|
441
|
+
const pool = createStaleTestPool();
|
|
442
|
+
// 10ms stale timeout, 20ms kill timeout
|
|
443
|
+
const created = await pool.create({ workdir: '/tmp/test', timeout_ms: 10 });
|
|
444
|
+
const session = pool._internals.sessions.get(created.sessionId);
|
|
445
|
+
session.lastActivityAt = new Date(Date.now() - 15); // Past 10ms stale, not 20ms kill
|
|
446
|
+
const result = pool.checkStale();
|
|
447
|
+
assert.deepEqual(result.stale, [created.sessionId]);
|
|
448
|
+
assert.deepEqual(result.killed, []);
|
|
449
|
+
});
|
|
450
|
+
it('multiple sessions can be stale independently', async () => {
|
|
451
|
+
const pool = createStaleTestPool();
|
|
452
|
+
const s1 = await pool.create({ workdir: '/tmp/a', timeout_ms: 50 });
|
|
453
|
+
const s2 = await pool.create({ workdir: '/tmp/b', timeout_ms: 50 });
|
|
454
|
+
const s3 = await pool.create({ workdir: '/tmp/c', timeout_ms: 50 });
|
|
455
|
+
// Make s1 and s3 stale, leave s2 active
|
|
456
|
+
pool._internals.sessions.get(s1.sessionId).lastActivityAt = new Date(Date.now() - 75);
|
|
457
|
+
pool._internals.sessions.get(s3.sessionId).lastActivityAt = new Date(Date.now() - 75);
|
|
458
|
+
const result = pool.checkStale();
|
|
459
|
+
assert.equal(result.stale.length, 2);
|
|
460
|
+
assert.ok(result.stale.includes(s1.sessionId));
|
|
461
|
+
assert.ok(result.stale.includes(s3.sessionId));
|
|
462
|
+
assert.deepEqual(result.killed, []);
|
|
463
|
+
// s2 should not be stale
|
|
464
|
+
assert.equal(pool.status(s2.sessionId).stale, false);
|
|
465
|
+
});
|
|
466
|
+
});
|
|
467
|
+
});
|
|
468
|
+
//# sourceMappingURL=worktree-stale.test.js.map
|