sensorium-mcp 3.1.2 → 3.1.3-board.10
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/Install-Sensorium.ps1 +257 -43
- package/README.md +2 -0
- package/dist/board/api/api.js +84 -0
- package/dist/board/api/api.test.ts +23 -0
- package/dist/board/api/client.js +113 -0
- package/dist/board/components/BottomNav.js +32 -0
- package/dist/board/components/Card.js +78 -0
- package/dist/board/components/Combobox.js +79 -0
- package/dist/board/components/CommentComposer.js +29 -0
- package/dist/board/components/CommentList.js +42 -0
- package/dist/board/components/DirTreePicker.js +128 -0
- package/dist/board/components/Dropdown.js +67 -0
- package/dist/board/components/Lane.js +47 -0
- package/dist/board/components/PriorityChip.js +20 -0
- package/dist/board/components/ProfileSummary.js +89 -0
- package/dist/board/components/StateBanner.js +24 -0
- package/dist/board/components/StatusChip.js +26 -0
- package/dist/board/components/rateLimit.js +32 -0
- package/dist/board/components/rateLimit.test.ts +16 -0
- package/dist/board/components/time.js +14 -0
- package/dist/board/config.js +56 -0
- package/dist/board/index.html +18 -0
- package/dist/board/main.js +37 -0
- package/dist/board/mock/api.mock.js +491 -0
- package/dist/board/mock/api.mock.test.ts +460 -0
- package/dist/board/mock/fixtures.js +512 -0
- package/dist/board/schema/policy.js +261 -0
- package/dist/board/state/recur.js +24 -0
- package/dist/board/state/recur.test.ts +24 -0
- package/dist/board/state/useBoard.js +161 -0
- package/dist/board/state/useBuilder.js +357 -0
- package/dist/board/state/useBuilder.test.ts +468 -0
- package/dist/board/state/useCard.js +193 -0
- package/dist/board/state/useCard.test.ts +435 -0
- package/dist/board/state/useDirBrowser.js +23 -0
- package/dist/board/styles/board.css +2885 -0
- package/dist/board/styles/tokens.css +72 -0
- package/dist/board/vendor/vue.esm-browser.js +9 -0
- package/dist/board/views/App.js +61 -0
- package/dist/board/views/BoardView.js +153 -0
- package/dist/board/views/BuilderView.js +582 -0
- package/dist/board/views/CardView.js +382 -0
- package/dist/board/views/SettingsView.js +152 -0
- package/dist/config/agent-settings.d.ts +11 -0
- package/dist/config/agent-settings.d.ts.map +1 -1
- package/dist/config/agent-settings.js +79 -0
- package/dist/config/agent-settings.js.map +1 -1
- package/dist/config/detail-grant.d.ts +7 -16
- package/dist/config/detail-grant.d.ts.map +1 -1
- package/dist/config/detail-grant.js +12 -35
- package/dist/config/detail-grant.js.map +1 -1
- package/dist/config/index.d.ts +2 -0
- package/dist/config/index.d.ts.map +1 -1
- package/dist/config/index.js +17 -0
- package/dist/config/index.js.map +1 -1
- package/dist/config/mcp-settings.d.ts +7 -1
- package/dist/config/mcp-settings.d.ts.map +1 -1
- package/dist/config/mcp-settings.js +9 -0
- package/dist/config/mcp-settings.js.map +1 -1
- package/dist/config/misc-settings.d.ts +22 -1
- package/dist/config/misc-settings.d.ts.map +1 -1
- package/dist/config/misc-settings.js +93 -3
- package/dist/config/misc-settings.js.map +1 -1
- package/dist/config/operator-grant.d.ts +9 -0
- package/dist/config/operator-grant.d.ts.map +1 -0
- package/dist/config/operator-grant.js +24 -0
- package/dist/config/operator-grant.js.map +1 -0
- package/dist/config/voice-grant.d.ts +10 -0
- package/dist/config/voice-grant.d.ts.map +1 -0
- package/dist/config/voice-grant.js +18 -0
- package/dist/config/voice-grant.js.map +1 -0
- package/dist/dashboard/board-static.d.ts +22 -0
- package/dist/dashboard/board-static.d.ts.map +1 -0
- package/dist/dashboard/board-static.js +130 -0
- package/dist/dashboard/board-static.js.map +1 -0
- package/dist/dashboard/presets.d.ts +1 -1
- package/dist/dashboard/presets.d.ts.map +1 -1
- package/dist/dashboard/presets.js +1 -1
- package/dist/dashboard/presets.js.map +1 -1
- package/dist/dashboard/routes/agent-templates.d.ts.map +1 -1
- package/dist/dashboard/routes/agent-templates.js +6 -9
- package/dist/dashboard/routes/agent-templates.js.map +1 -1
- package/dist/dashboard/routes/board-body.d.ts +8 -0
- package/dist/dashboard/routes/board-body.d.ts.map +1 -0
- package/dist/dashboard/routes/board-body.js +20 -0
- package/dist/dashboard/routes/board-body.js.map +1 -0
- package/dist/dashboard/routes/board-dir-listing.d.ts +70 -0
- package/dist/dashboard/routes/board-dir-listing.d.ts.map +1 -0
- package/dist/dashboard/routes/board-dir-listing.js +192 -0
- package/dist/dashboard/routes/board-dir-listing.js.map +1 -0
- package/dist/dashboard/routes/board-lane-groups.d.ts +6 -0
- package/dist/dashboard/routes/board-lane-groups.d.ts.map +1 -0
- package/dist/dashboard/routes/board-lane-groups.js +52 -0
- package/dist/dashboard/routes/board-lane-groups.js.map +1 -0
- package/dist/dashboard/routes/board-policy.d.ts +224 -0
- package/dist/dashboard/routes/board-policy.d.ts.map +1 -0
- package/dist/dashboard/routes/board-policy.js +214 -0
- package/dist/dashboard/routes/board-policy.js.map +1 -0
- package/dist/dashboard/routes/board-profile-parse.d.ts +32 -0
- package/dist/dashboard/routes/board-profile-parse.d.ts.map +1 -0
- package/dist/dashboard/routes/board-profile-parse.js +338 -0
- package/dist/dashboard/routes/board-profile-parse.js.map +1 -0
- package/dist/dashboard/routes/board.d.ts +90 -0
- package/dist/dashboard/routes/board.d.ts.map +1 -0
- package/dist/dashboard/routes/board.js +721 -0
- package/dist/dashboard/routes/board.js.map +1 -0
- package/dist/dashboard/routes/codex.d.ts +14 -0
- package/dist/dashboard/routes/codex.d.ts.map +1 -0
- package/dist/dashboard/routes/codex.js +92 -0
- package/dist/dashboard/routes/codex.js.map +1 -0
- package/dist/dashboard/routes/prompts.d.ts +2 -2
- package/dist/dashboard/routes/prompts.d.ts.map +1 -1
- package/dist/dashboard/routes/prompts.js +2 -2
- package/dist/dashboard/routes/prompts.js.map +1 -1
- package/dist/dashboard/routes/settings.d.ts +2 -0
- package/dist/dashboard/routes/settings.d.ts.map +1 -1
- package/dist/dashboard/routes/settings.js +24 -1
- package/dist/dashboard/routes/settings.js.map +1 -1
- package/dist/dashboard/routes/skills.d.ts +7 -1
- package/dist/dashboard/routes/skills.d.ts.map +1 -1
- package/dist/dashboard/routes/skills.js +6 -6
- package/dist/dashboard/routes/skills.js.map +1 -1
- package/dist/dashboard/routes/snapshots.d.ts +2 -1
- package/dist/dashboard/routes/snapshots.d.ts.map +1 -1
- package/dist/dashboard/routes/snapshots.js +24 -18
- package/dist/dashboard/routes/snapshots.js.map +1 -1
- package/dist/dashboard/routes/templates.js +5 -5
- package/dist/dashboard/routes/templates.js.map +1 -1
- package/dist/dashboard/routes/threads-create.d.ts +17 -0
- package/dist/dashboard/routes/threads-create.d.ts.map +1 -1
- package/dist/dashboard/routes/threads-create.js +32 -10
- package/dist/dashboard/routes/threads-create.js.map +1 -1
- package/dist/dashboard/routes/threads-helpers.d.ts +11 -2
- package/dist/dashboard/routes/threads-helpers.d.ts.map +1 -1
- package/dist/dashboard/routes/threads-helpers.js +20 -3
- package/dist/dashboard/routes/threads-helpers.js.map +1 -1
- package/dist/dashboard/routes/threads-read.d.ts +16 -4
- package/dist/dashboard/routes/threads-read.d.ts.map +1 -1
- package/dist/dashboard/routes/threads-read.js +61 -55
- package/dist/dashboard/routes/threads-read.js.map +1 -1
- package/dist/dashboard/routes/threads.d.ts +2 -2
- package/dist/dashboard/routes/threads.d.ts.map +1 -1
- package/dist/dashboard/routes/threads.js +143 -29
- package/dist/dashboard/routes/threads.js.map +1 -1
- package/dist/dashboard/routes/types.d.ts +6 -0
- package/dist/dashboard/routes/types.d.ts.map +1 -1
- package/dist/dashboard/routes/types.js.map +1 -1
- package/dist/dashboard/routes.d.ts +2 -2
- package/dist/dashboard/routes.d.ts.map +1 -1
- package/dist/dashboard/routes.js +85 -7
- package/dist/dashboard/routes.js.map +1 -1
- package/dist/dashboard/spa.html +15 -12
- package/dist/data/board/board-schema.d.ts +29 -0
- package/dist/data/board/board-schema.d.ts.map +1 -0
- package/dist/data/board/board-schema.js +202 -0
- package/dist/data/board/board-schema.js.map +1 -0
- package/dist/data/board/board-types.d.ts +175 -0
- package/dist/data/board/board-types.d.ts.map +1 -0
- package/dist/data/board/board-types.js +9 -0
- package/dist/data/board/board-types.js.map +1 -0
- package/dist/data/board/card.repository.d.ts +137 -0
- package/dist/data/board/card.repository.d.ts.map +1 -0
- package/dist/data/board/card.repository.js +470 -0
- package/dist/data/board/card.repository.js.map +1 -0
- package/dist/data/board/comment.repository.d.ts +14 -0
- package/dist/data/board/comment.repository.d.ts.map +1 -0
- package/dist/data/board/comment.repository.js +42 -0
- package/dist/data/board/comment.repository.js.map +1 -0
- package/dist/data/board/lane-group.repository.d.ts +19 -0
- package/dist/data/board/lane-group.repository.d.ts.map +1 -0
- package/dist/data/board/lane-group.repository.js +66 -0
- package/dist/data/board/lane-group.repository.js.map +1 -0
- package/dist/data/board/profile-defaults.d.ts +17 -0
- package/dist/data/board/profile-defaults.d.ts.map +1 -0
- package/dist/data/board/profile-defaults.js +107 -0
- package/dist/data/board/profile-defaults.js.map +1 -0
- package/dist/data/interfaces.d.ts +1 -0
- package/dist/data/interfaces.d.ts.map +1 -1
- package/dist/data/memory/bootstrap.d.ts +1 -8
- package/dist/data/memory/bootstrap.d.ts.map +1 -1
- package/dist/data/memory/bootstrap.js +27 -37
- package/dist/data/memory/bootstrap.js.map +1 -1
- package/dist/data/memory/consolidation.d.ts +9 -31
- package/dist/data/memory/consolidation.d.ts.map +1 -1
- package/dist/data/memory/consolidation.js +22 -32
- package/dist/data/memory/consolidation.js.map +1 -1
- package/dist/data/memory/db-maintenance.d.ts +54 -0
- package/dist/data/memory/db-maintenance.d.ts.map +1 -0
- package/dist/data/memory/db-maintenance.js +81 -0
- package/dist/data/memory/db-maintenance.js.map +1 -0
- package/dist/data/memory/episodes.d.ts +2 -1
- package/dist/data/memory/episodes.d.ts.map +1 -1
- package/dist/data/memory/episodes.js +5 -1
- package/dist/data/memory/episodes.js.map +1 -1
- package/dist/data/memory/index.d.ts +0 -4
- package/dist/data/memory/index.d.ts.map +1 -1
- package/dist/data/memory/index.js +0 -4
- package/dist/data/memory/index.js.map +1 -1
- package/dist/data/memory/key-knowledge.d.ts +51 -0
- package/dist/data/memory/key-knowledge.d.ts.map +1 -0
- package/dist/data/memory/key-knowledge.js +128 -0
- package/dist/data/memory/key-knowledge.js.map +1 -0
- package/dist/data/memory/migration-runner.d.ts +1 -1
- package/dist/data/memory/migration-runner.d.ts.map +1 -1
- package/dist/data/memory/migration-runner.js +407 -1
- package/dist/data/memory/migration-runner.js.map +1 -1
- package/dist/data/memory/narrative-lint.d.ts +2 -2
- package/dist/data/memory/narrative-lint.d.ts.map +1 -1
- package/dist/data/memory/narrative-lint.js +23 -13
- package/dist/data/memory/narrative-lint.js.map +1 -1
- package/dist/data/memory/narrative-resolutions.d.ts +9 -2
- package/dist/data/memory/narrative-resolutions.d.ts.map +1 -1
- package/dist/data/memory/narrative-resolutions.js +9 -8
- package/dist/data/memory/narrative-resolutions.js.map +1 -1
- package/dist/data/memory/narrative-sources.d.ts +1 -1
- package/dist/data/memory/narrative-sources.d.ts.map +1 -1
- package/dist/data/memory/narrative-sources.js +8 -3
- package/dist/data/memory/narrative-sources.js.map +1 -1
- package/dist/data/memory/narrative-store.d.ts +24 -0
- package/dist/data/memory/narrative-store.d.ts.map +1 -1
- package/dist/data/memory/narrative-store.js +73 -35
- package/dist/data/memory/narrative-store.js.map +1 -1
- package/dist/data/memory/narrative.d.ts.map +1 -1
- package/dist/data/memory/narrative.js +47 -29
- package/dist/data/memory/narrative.js.map +1 -1
- package/dist/data/memory/note-archival.d.ts +1 -1
- package/dist/data/memory/note-archival.d.ts.map +1 -1
- package/dist/data/memory/note-archival.js +7 -3
- package/dist/data/memory/note-archival.js.map +1 -1
- package/dist/data/memory/note-embeddings.d.ts +7 -0
- package/dist/data/memory/note-embeddings.d.ts.map +1 -1
- package/dist/data/memory/note-embeddings.js +6 -2
- package/dist/data/memory/note-embeddings.js.map +1 -1
- package/dist/data/memory/passive-notice.repository.d.ts +70 -0
- package/dist/data/memory/passive-notice.repository.d.ts.map +1 -0
- package/dist/data/memory/passive-notice.repository.js +85 -0
- package/dist/data/memory/passive-notice.repository.js.map +1 -0
- package/dist/data/memory/schema-ddl.d.ts +120 -1
- package/dist/data/memory/schema-ddl.d.ts.map +1 -1
- package/dist/data/memory/schema-ddl.js +171 -4
- package/dist/data/memory/schema-ddl.js.map +1 -1
- package/dist/data/memory/schema-guard.d.ts.map +1 -1
- package/dist/data/memory/schema-guard.js +5 -41
- package/dist/data/memory/schema-guard.js.map +1 -1
- package/dist/data/memory/schema.d.ts.map +1 -1
- package/dist/data/memory/schema.js +10 -34
- package/dist/data/memory/schema.js.map +1 -1
- package/dist/data/memory/semantic-notes.d.ts +13 -8
- package/dist/data/memory/semantic-notes.d.ts.map +1 -1
- package/dist/data/memory/semantic-notes.js +12 -17
- package/dist/data/memory/semantic-notes.js.map +1 -1
- package/dist/data/memory/thread-registry.d.ts +330 -15
- package/dist/data/memory/thread-registry.d.ts.map +1 -1
- package/dist/data/memory/thread-registry.js +523 -67
- package/dist/data/memory/thread-registry.js.map +1 -1
- package/dist/data/memory/utils.d.ts +6 -0
- package/dist/data/memory/utils.d.ts.map +1 -1
- package/dist/data/memory/utils.js +13 -0
- package/dist/data/memory/utils.js.map +1 -1
- package/dist/data/memory/worker-lifecycle.repository.d.ts +308 -0
- package/dist/data/memory/worker-lifecycle.repository.d.ts.map +1 -0
- package/dist/data/memory/worker-lifecycle.repository.js +428 -0
- package/dist/data/memory/worker-lifecycle.repository.js.map +1 -0
- package/dist/data/optional.d.ts +16 -0
- package/dist/data/optional.d.ts.map +1 -0
- package/dist/data/optional.js +47 -0
- package/dist/data/optional.js.map +1 -0
- package/dist/index.js +156 -24
- package/dist/index.js.map +1 -1
- package/dist/integrations/openai/speech.d.ts.map +1 -1
- package/dist/integrations/openai/speech.js +52 -19
- package/dist/integrations/openai/speech.js.map +1 -1
- package/dist/integrations/openai/video.d.ts +1 -1
- package/dist/integrations/openai/video.d.ts.map +1 -1
- package/dist/integrations/openai/video.js +13 -8
- package/dist/integrations/openai/video.js.map +1 -1
- package/dist/integrations/telegram/types.d.ts +11 -0
- package/dist/integrations/telegram/types.d.ts.map +1 -1
- package/dist/lib/http-retry.d.ts +91 -0
- package/dist/lib/http-retry.d.ts.map +1 -0
- package/dist/lib/http-retry.js +177 -0
- package/dist/lib/http-retry.js.map +1 -0
- package/dist/lib/mcp-http-port.d.ts +12 -0
- package/dist/lib/mcp-http-port.d.ts.map +1 -0
- package/dist/lib/mcp-http-port.js +19 -0
- package/dist/lib/mcp-http-port.js.map +1 -0
- package/dist/lib/paths.d.ts +29 -4
- package/dist/lib/paths.d.ts.map +1 -1
- package/dist/lib/paths.js +31 -4
- package/dist/lib/paths.js.map +1 -1
- package/dist/lib/types.d.ts +2 -0
- package/dist/lib/types.d.ts.map +1 -1
- package/dist/lib/usage-metering/pricing.js +1 -1
- package/dist/lib/usage-metering/pricing.js.map +1 -1
- package/dist/lib/usage-metering/sink.d.ts +4 -0
- package/dist/lib/usage-metering/sink.d.ts.map +1 -1
- package/dist/lib/usage-metering/sink.js +6 -4
- package/dist/lib/usage-metering/sink.js.map +1 -1
- package/dist/lib/utils.d.ts +31 -0
- package/dist/lib/utils.d.ts.map +1 -1
- package/dist/lib/utils.js +49 -0
- package/dist/lib/utils.js.map +1 -1
- package/dist/llm/prompts/narrative.d.ts.map +1 -1
- package/dist/llm/prompts/narrative.js +27 -86
- package/dist/llm/prompts/narrative.js.map +1 -1
- package/dist/log-parsing/log-events.d.ts +38 -0
- package/dist/log-parsing/log-events.d.ts.map +1 -0
- package/dist/log-parsing/log-events.js +2 -0
- package/dist/log-parsing/log-events.js.map +1 -0
- package/dist/log-parsing/parser-registry.d.ts +4 -0
- package/dist/log-parsing/parser-registry.d.ts.map +1 -0
- package/dist/log-parsing/parser-registry.js +18 -0
- package/dist/log-parsing/parser-registry.js.map +1 -0
- package/dist/log-parsing/parsers/claude.d.ts +6 -0
- package/dist/log-parsing/parsers/claude.d.ts.map +1 -0
- package/dist/log-parsing/parsers/claude.js +100 -0
- package/dist/log-parsing/parsers/claude.js.map +1 -0
- package/dist/log-parsing/parsers/codex.d.ts +6 -0
- package/dist/log-parsing/parsers/codex.d.ts.map +1 -0
- package/dist/log-parsing/parsers/codex.js +116 -0
- package/dist/log-parsing/parsers/codex.js.map +1 -0
- package/dist/log-parsing/parsers/copilot.d.ts +6 -0
- package/dist/log-parsing/parsers/copilot.d.ts.map +1 -0
- package/dist/log-parsing/parsers/copilot.js +65 -0
- package/dist/log-parsing/parsers/copilot.js.map +1 -0
- package/dist/log-parsing/parsers/json-lines.d.ts +9 -0
- package/dist/log-parsing/parsers/json-lines.d.ts.map +1 -0
- package/dist/log-parsing/parsers/json-lines.js +25 -0
- package/dist/log-parsing/parsers/json-lines.js.map +1 -0
- package/dist/log-parsing/render.d.ts +33 -0
- package/dist/log-parsing/render.d.ts.map +1 -0
- package/dist/log-parsing/render.js +113 -0
- package/dist/log-parsing/render.js.map +1 -0
- package/dist/log-parsing/text.d.ts +8 -0
- package/dist/log-parsing/text.d.ts.map +1 -0
- package/dist/log-parsing/text.js +20 -0
- package/dist/log-parsing/text.js.map +1 -0
- package/dist/server/http-server.d.ts +8 -1
- package/dist/server/http-server.d.ts.map +1 -1
- package/dist/server/http-server.js +41 -19
- package/dist/server/http-server.js.map +1 -1
- package/dist/server/port-holder.d.ts +94 -0
- package/dist/server/port-holder.d.ts.map +1 -0
- package/dist/server/port-holder.js +122 -0
- package/dist/server/port-holder.js.map +1 -0
- package/dist/services/agent-spawn.service.d.ts +50 -5
- package/dist/services/agent-spawn.service.d.ts.map +1 -1
- package/dist/services/agent-spawn.service.js +59 -66
- package/dist/services/agent-spawn.service.js.map +1 -1
- package/dist/services/background-runner.d.ts +0 -1
- package/dist/services/background-runner.d.ts.map +1 -1
- package/dist/services/background-runner.js +0 -58
- package/dist/services/background-runner.js.map +1 -1
- package/dist/services/board/board-signals.d.ts +45 -0
- package/dist/services/board/board-signals.d.ts.map +1 -0
- package/dist/services/board/board-signals.js +170 -0
- package/dist/services/board/board-signals.js.map +1 -0
- package/dist/services/board/card-briefing.d.ts +24 -0
- package/dist/services/board/card-briefing.d.ts.map +1 -0
- package/dist/services/board/card-briefing.js +132 -0
- package/dist/services/board/card-briefing.js.map +1 -0
- package/dist/services/board/card-diagnostics.d.ts +25 -0
- package/dist/services/board/card-diagnostics.d.ts.map +1 -0
- package/dist/services/board/card-diagnostics.js +50 -0
- package/dist/services/board/card-diagnostics.js.map +1 -0
- package/dist/services/board/live-root-thread.d.ts +8 -0
- package/dist/services/board/live-root-thread.d.ts.map +1 -0
- package/dist/services/board/live-root-thread.js +2 -0
- package/dist/services/board/live-root-thread.js.map +1 -0
- package/dist/services/board/orchestrator.service.d.ts +119 -0
- package/dist/services/board/orchestrator.service.d.ts.map +1 -0
- package/dist/services/board/orchestrator.service.js +387 -0
- package/dist/services/board/orchestrator.service.js.map +1 -0
- package/dist/services/board/release-worker.d.ts +43 -0
- package/dist/services/board/release-worker.d.ts.map +1 -0
- package/dist/services/board/release-worker.js +96 -0
- package/dist/services/board/release-worker.js.map +1 -0
- package/dist/services/board/report-capture.d.ts +94 -0
- package/dist/services/board/report-capture.d.ts.map +1 -0
- package/dist/services/board/report-capture.js +398 -0
- package/dist/services/board/report-capture.js.map +1 -0
- package/dist/services/board/worker-spawn.d.ts +89 -0
- package/dist/services/board/worker-spawn.d.ts.map +1 -0
- package/dist/services/board/worker-spawn.js +177 -0
- package/dist/services/board/worker-spawn.js.map +1 -0
- package/dist/services/board/worktree.d.ts +45 -0
- package/dist/services/board/worktree.d.ts.map +1 -0
- package/dist/services/board/worktree.js +183 -0
- package/dist/services/board/worktree.js.map +1 -0
- package/dist/services/broker-client.d.ts +84 -2
- package/dist/services/broker-client.d.ts.map +1 -1
- package/dist/services/broker-client.js +72 -6
- package/dist/services/broker-client.js.map +1 -1
- package/dist/services/claude-spawn.service.d.ts +5 -0
- package/dist/services/claude-spawn.service.d.ts.map +1 -1
- package/dist/services/claude-spawn.service.js +37 -21
- package/dist/services/claude-spawn.service.js.map +1 -1
- package/dist/services/codex-spawn.service.d.ts +8 -3
- package/dist/services/codex-spawn.service.d.ts.map +1 -1
- package/dist/services/codex-spawn.service.js +84 -67
- package/dist/services/codex-spawn.service.js.map +1 -1
- package/dist/services/consolidation.service.d.ts.map +1 -1
- package/dist/services/consolidation.service.js +5 -49
- package/dist/services/consolidation.service.js.map +1 -1
- package/dist/services/copilot-spawn.service.d.ts +1 -1
- package/dist/services/copilot-spawn.service.d.ts.map +1 -1
- package/dist/services/copilot-spawn.service.js +10 -5
- package/dist/services/copilot-spawn.service.js.map +1 -1
- package/dist/services/daily-session.d.ts +24 -11
- package/dist/services/daily-session.d.ts.map +1 -1
- package/dist/services/daily-session.js +113 -33
- package/dist/services/daily-session.js.map +1 -1
- package/dist/services/death-alert.service.d.ts +55 -0
- package/dist/services/death-alert.service.d.ts.map +1 -0
- package/dist/services/death-alert.service.js +64 -0
- package/dist/services/death-alert.service.js.map +1 -0
- package/dist/services/dispatcher/broker.d.ts +66 -0
- package/dist/services/dispatcher/broker.d.ts.map +1 -1
- package/dist/services/dispatcher/broker.js +60 -52
- package/dist/services/dispatcher/broker.js.map +1 -1
- package/dist/services/dispatcher/poller.d.ts.map +1 -1
- package/dist/services/dispatcher/poller.js +31 -24
- package/dist/services/dispatcher/poller.js.map +1 -1
- package/dist/services/http-retry.d.ts +1 -90
- package/dist/services/http-retry.d.ts.map +1 -1
- package/dist/services/http-retry.js +1 -176
- package/dist/services/http-retry.js.map +1 -1
- package/dist/services/intent.d.ts +15 -1
- package/dist/services/intent.d.ts.map +1 -1
- package/dist/services/intent.js +39 -27
- package/dist/services/intent.js.map +1 -1
- package/dist/services/keeper.service.d.ts +76 -3
- package/dist/services/keeper.service.d.ts.map +1 -1
- package/dist/services/keeper.service.js +112 -35
- package/dist/services/keeper.service.js.map +1 -1
- package/dist/services/mcp-config.service.d.ts.map +1 -1
- package/dist/services/mcp-config.service.js +14 -1
- package/dist/services/mcp-config.service.js.map +1 -1
- package/dist/services/memory-briefing.service.d.ts +1 -1
- package/dist/services/memory-briefing.service.d.ts.map +1 -1
- package/dist/services/memory-briefing.service.js +28 -73
- package/dist/services/memory-briefing.service.js.map +1 -1
- package/dist/services/passive-notice.service.d.ts +56 -0
- package/dist/services/passive-notice.service.d.ts.map +1 -0
- package/dist/services/passive-notice.service.js +92 -0
- package/dist/services/passive-notice.service.js.map +1 -0
- package/dist/services/predefined-prompts.d.ts +11 -0
- package/dist/services/predefined-prompts.d.ts.map +1 -0
- package/dist/services/predefined-prompts.js +25 -0
- package/dist/services/predefined-prompts.js.map +1 -0
- package/dist/services/process.service.d.ts +111 -27
- package/dist/services/process.service.d.ts.map +1 -1
- package/dist/services/process.service.js +245 -173
- package/dist/services/process.service.js.map +1 -1
- package/dist/services/spawn-common.d.ts +281 -5
- package/dist/services/spawn-common.d.ts.map +1 -1
- package/dist/services/spawn-common.js +884 -188
- package/dist/services/spawn-common.js.map +1 -1
- package/dist/services/spawn-exit-watcher.d.ts +45 -35
- package/dist/services/spawn-exit-watcher.d.ts.map +1 -1
- package/dist/services/spawn-exit-watcher.js +120 -100
- package/dist/services/spawn-exit-watcher.js.map +1 -1
- package/dist/services/telegram.d.ts +31 -8
- package/dist/services/telegram.d.ts.map +1 -1
- package/dist/services/telegram.js +58 -26
- package/dist/services/telegram.js.map +1 -1
- package/dist/services/thread-health.service.d.ts +8 -0
- package/dist/services/thread-health.service.d.ts.map +1 -1
- package/dist/services/thread-health.service.js +14 -10
- package/dist/services/thread-health.service.js.map +1 -1
- package/dist/services/thread-lifecycle.service.d.ts +17 -1
- package/dist/services/thread-lifecycle.service.d.ts.map +1 -1
- package/dist/services/thread-lifecycle.service.js +47 -6
- package/dist/services/thread-lifecycle.service.js.map +1 -1
- package/dist/services/thread-log-reader.d.ts +81 -0
- package/dist/services/thread-log-reader.d.ts.map +1 -0
- package/dist/services/thread-log-reader.js +141 -0
- package/dist/services/thread-log-reader.js.map +1 -0
- package/dist/services/thread-purge.service.d.ts +200 -0
- package/dist/services/thread-purge.service.d.ts.map +1 -0
- package/dist/services/thread-purge.service.js +644 -0
- package/dist/services/thread-purge.service.js.map +1 -0
- package/dist/services/topic.service.d.ts +44 -2
- package/dist/services/topic.service.d.ts.map +1 -1
- package/dist/services/topic.service.js +74 -13
- package/dist/services/topic.service.js.map +1 -1
- package/dist/services/usage/usage-inbox-notifier.d.ts +50 -0
- package/dist/services/usage/usage-inbox-notifier.d.ts.map +1 -0
- package/dist/services/usage/usage-inbox-notifier.js +118 -0
- package/dist/services/usage/usage-inbox-notifier.js.map +1 -0
- package/dist/services/usage/usage-poller.service.d.ts +41 -0
- package/dist/services/usage/usage-poller.service.d.ts.map +1 -0
- package/dist/services/usage/usage-poller.service.js +67 -0
- package/dist/services/usage/usage-poller.service.js.map +1 -0
- package/dist/services/usage/usage-snapshot-provider.d.ts +40 -0
- package/dist/services/usage/usage-snapshot-provider.d.ts.map +1 -0
- package/dist/services/usage/usage-snapshot-provider.js +89 -0
- package/dist/services/usage/usage-snapshot-provider.js.map +1 -0
- package/dist/services/usage/usage-types.d.ts +28 -0
- package/dist/services/usage/usage-types.d.ts.map +1 -0
- package/dist/services/usage/usage-types.js +14 -0
- package/dist/services/usage/usage-types.js.map +1 -0
- package/dist/services/worker-birth.d.ts +154 -0
- package/dist/services/worker-birth.d.ts.map +1 -0
- package/dist/services/worker-birth.js +274 -0
- package/dist/services/worker-birth.js.map +1 -0
- package/dist/services/worker-cleanup.service.d.ts +242 -19
- package/dist/services/worker-cleanup.service.d.ts.map +1 -1
- package/dist/services/worker-cleanup.service.js +893 -355
- package/dist/services/worker-cleanup.service.js.map +1 -1
- package/dist/services/worker-lifecycle-executor.d.ts +42 -0
- package/dist/services/worker-lifecycle-executor.d.ts.map +1 -0
- package/dist/services/worker-lifecycle-executor.js +63 -0
- package/dist/services/worker-lifecycle-executor.js.map +1 -0
- package/dist/services/worker-single-use.d.ts +92 -0
- package/dist/services/worker-single-use.d.ts.map +1 -0
- package/dist/services/worker-single-use.js +155 -0
- package/dist/services/worker-single-use.js.map +1 -0
- package/dist/sessions/mcp-registry.d.ts +33 -2
- package/dist/sessions/mcp-registry.d.ts.map +1 -1
- package/dist/sessions/mcp-registry.js +153 -30
- package/dist/sessions/mcp-registry.js.map +1 -1
- package/dist/test-bootstrap.d.ts +19 -12
- package/dist/test-bootstrap.d.ts.map +1 -1
- package/dist/test-bootstrap.js +69 -21
- package/dist/test-bootstrap.js.map +1 -1
- package/dist/test-tripwire.test-support.d.ts +75 -0
- package/dist/test-tripwire.test-support.d.ts.map +1 -0
- package/dist/test-tripwire.test-support.js +353 -0
- package/dist/test-tripwire.test-support.js.map +1 -0
- package/dist/tools/defs/memory-defs.d.ts.map +1 -1
- package/dist/tools/defs/memory-defs.js +12 -4
- package/dist/tools/defs/memory-defs.js.map +1 -1
- package/dist/tools/defs/session-defs.d.ts.map +1 -1
- package/dist/tools/defs/session-defs.js +26 -10
- package/dist/tools/defs/session-defs.js.map +1 -1
- package/dist/tools/defs/utility-defs.js +1 -1
- package/dist/tools/defs/utility-defs.js.map +1 -1
- package/dist/tools/delegate-tool.d.ts +81 -1
- package/dist/tools/delegate-tool.d.ts.map +1 -1
- package/dist/tools/delegate-tool.js +840 -219
- package/dist/tools/delegate-tool.js.map +1 -1
- package/dist/tools/memory-tools.d.ts.map +1 -1
- package/dist/tools/memory-tools.js +66 -9
- package/dist/tools/memory-tools.js.map +1 -1
- package/dist/tools/response-builders.d.ts.map +1 -1
- package/dist/tools/response-builders.js +12 -8
- package/dist/tools/response-builders.js.map +1 -1
- package/dist/tools/session-tools.d.ts.map +1 -1
- package/dist/tools/session-tools.js +3 -32
- package/dist/tools/session-tools.js.map +1 -1
- package/dist/tools/skill-tools.js +1 -1
- package/dist/tools/skill-tools.js.map +1 -1
- package/dist/tools/start-session-tool.d.ts.map +1 -1
- package/dist/tools/start-session-tool.js +66 -20
- package/dist/tools/start-session-tool.js.map +1 -1
- package/dist/tools/utility-tools.d.ts.map +1 -1
- package/dist/tools/utility-tools.js +38 -3
- package/dist/tools/utility-tools.js.map +1 -1
- package/dist/tools/wait/auto-forward.d.ts.map +1 -1
- package/dist/tools/wait/auto-forward.js +8 -3
- package/dist/tools/wait/auto-forward.js.map +1 -1
- package/dist/tools/wait/consolidation-strategy.d.ts +42 -0
- package/dist/tools/wait/consolidation-strategy.d.ts.map +1 -0
- package/dist/tools/wait/consolidation-strategy.js +50 -0
- package/dist/tools/wait/consolidation-strategy.js.map +1 -0
- package/dist/tools/wait/drive-handler.d.ts +5 -7
- package/dist/tools/wait/drive-handler.d.ts.map +1 -1
- package/dist/tools/wait/drive-handler.js +45 -59
- package/dist/tools/wait/drive-handler.js.map +1 -1
- package/dist/tools/wait/media-processor.d.ts.map +1 -1
- package/dist/tools/wait/media-processor.js +8 -4
- package/dist/tools/wait/media-processor.js.map +1 -1
- package/dist/tools/wait/message-delivery.d.ts +9 -6
- package/dist/tools/wait/message-delivery.d.ts.map +1 -1
- package/dist/tools/wait/message-delivery.js +77 -58
- package/dist/tools/wait/message-delivery.js.map +1 -1
- package/dist/tools/wait/message-processing.d.ts.map +1 -1
- package/dist/tools/wait/message-processing.js +2 -1
- package/dist/tools/wait/message-processing.js.map +1 -1
- package/dist/tools/wait/poll-loop.d.ts.map +1 -1
- package/dist/tools/wait/poll-loop.js +339 -239
- package/dist/tools/wait/poll-loop.js.map +1 -1
- package/package.json +4 -3
- package/templates/azure-devops-securevault.default.md +20 -6
- package/templates/board-quality-checklist.default.md +121 -0
- package/templates/buildless-vue-preview.default.md +47 -0
- package/templates/expert-code-review.default.md +12 -0
- package/templates/handoff.default.md +41 -18
- package/templates/increment-pr-pipeline.default.md +79 -0
- package/templates/swarm.default.md +1 -0
- package/templates/worker-autonomous.default.md +1 -0
- package/templates/worker-delegate.default.md +1 -0
- package/dist/dashboard/log-parser.d.ts +0 -65
- package/dist/dashboard/log-parser.d.ts.map +0 -1
- package/dist/dashboard/log-parser.js +0 -219
- package/dist/dashboard/log-parser.js.map +0 -1
- package/dist/data/memory/reflection-dedup.d.ts +0 -17
- package/dist/data/memory/reflection-dedup.d.ts.map +0 -1
- package/dist/data/memory/reflection-dedup.js +0 -55
- package/dist/data/memory/reflection-dedup.js.map +0 -1
- package/dist/data/memory/reflection-gates.d.ts +0 -40
- package/dist/data/memory/reflection-gates.d.ts.map +0 -1
- package/dist/data/memory/reflection-gates.js +0 -220
- package/dist/data/memory/reflection-gates.js.map +0 -1
- package/dist/data/memory/reflection-sources.d.ts +0 -13
- package/dist/data/memory/reflection-sources.d.ts.map +0 -1
- package/dist/data/memory/reflection-sources.js +0 -115
- package/dist/data/memory/reflection-sources.js.map +0 -1
- package/dist/data/memory/reflection.d.ts +0 -43
- package/dist/data/memory/reflection.d.ts.map +0 -1
- package/dist/data/memory/reflection.js +0 -329
- package/dist/data/memory/reflection.js.map +0 -1
- package/dist/llm/prompts/reflection.d.ts +0 -6
- package/dist/llm/prompts/reflection.d.ts.map +0 -1
- package/dist/llm/prompts/reflection.js +0 -77
- package/dist/llm/prompts/reflection.js.map +0 -1
- package/dist/services/memory-pruning.service.d.ts +0 -12
- package/dist/services/memory-pruning.service.d.ts.map +0 -1
- package/dist/services/memory-pruning.service.js +0 -179
- package/dist/services/memory-pruning.service.js.map +0 -1
- package/templates/daily-review.default.md +0 -26
- package/templates/fire-and-forget.default.md +0 -76
- package/templates/offload.default.md +0 -33
- package/templates/sensorium-repair.default.md +0 -114
|
@@ -18,14 +18,16 @@ import { readFile, rename, unlink } from "node:fs/promises";
|
|
|
18
18
|
import { join } from "node:path";
|
|
19
19
|
import { checkMaintenanceFlag, writeActivityHeartbeat, writeThreadHeartbeatSync, } from "../../data/file-storage.js";
|
|
20
20
|
import { onMaintenanceSignal, markMaintenanceObserved, clearMaintenanceObserved, } from "../../services/maintenance-signal.js";
|
|
21
|
-
import {
|
|
21
|
+
import { getEffectiveAutonomousMode } from "../../services/thread-config.service.js";
|
|
22
22
|
import { peekThreadMessages } from "../../services/dispatcher/index.js";
|
|
23
23
|
import { log } from "../../lib/logger.js";
|
|
24
24
|
import { getShortReminder, buildMaintenanceResponse } from "../response-builders.js";
|
|
25
25
|
import { ThreadState } from "../../services/thread-lifecycle.service.js";
|
|
26
|
-
import { PENDING_TASKS_DIR
|
|
27
|
-
import {
|
|
28
|
-
import {
|
|
26
|
+
import { PENDING_TASKS_DIR } from "../../services/process.service.js";
|
|
27
|
+
import { Optional } from "../../data/optional.js";
|
|
28
|
+
import { markWorkerTaskConsumed } from "../../data/memory/worker-lifecycle.repository.js";
|
|
29
|
+
import { takeWorkerDeathNotice } from "../../services/passive-notice.service.js";
|
|
30
|
+
import { isSessionSuperseded, markThreadWaiting, reconcileThreadOwnership, unmarkThreadWaiting, } from "../../sessions/mcp-registry.js";
|
|
29
31
|
import { handleReactionOnly } from "./reaction-handler.js";
|
|
30
32
|
import { checkForDueTasks } from "./task-handler.js";
|
|
31
33
|
import { processIncomingMessages, handlePollTimeout } from "./message-processing.js";
|
|
@@ -39,42 +41,105 @@ import { maybeAutoForwardFinalText } from "./auto-forward.js";
|
|
|
39
41
|
// close. The set is shared with self-update (ACK-gated port close) and lives in
|
|
40
42
|
// maintenance-signal.ts; this loop owns clearing it because the poll loop is the
|
|
41
43
|
// only place that reads the flag continuously.
|
|
44
|
+
// unref'd like every other background timer here (index.ts, orchestrator,
|
|
45
|
+
// dispatcher poller, spawn-exit-watcher): clearing a stale flag must never be the
|
|
46
|
+
// handle that keeps a process alive. The server's transport handles own its
|
|
47
|
+
// lifetime; without this, merely IMPORTING this module pins the event loop open.
|
|
42
48
|
setInterval(() => {
|
|
43
49
|
if (checkMaintenanceFlag() === null) {
|
|
44
50
|
clearMaintenanceObserved();
|
|
45
51
|
}
|
|
46
|
-
}, 30_000);
|
|
52
|
+
}, 30_000).unref();
|
|
47
53
|
// ---------------------------------------------------------------------------
|
|
48
54
|
// Pending-task file helper
|
|
49
55
|
// ---------------------------------------------------------------------------
|
|
50
56
|
/**
|
|
51
57
|
* Check for a pending task file written by send_message_to_thread.
|
|
52
|
-
* If one exists, atomically consume it and return
|
|
58
|
+
* If one exists, atomically consume it and return the ToolResult carrying it.
|
|
53
59
|
* The file now contains pre-formatted structured messages (one-shot or
|
|
54
60
|
* manager-worker), so we pass the content through as-is.
|
|
55
|
-
*
|
|
61
|
+
* Empty when no pending task is available.
|
|
62
|
+
*
|
|
63
|
+
* `db` is here for one write: this is the single place a task is consumed, so it is
|
|
64
|
+
* the single place that records the consumption durably. A thread that read its work
|
|
65
|
+
* must still read as having read it in the NEXT server process — see
|
|
66
|
+
* `markWorkerTaskConsumed`.
|
|
67
|
+
*
|
|
68
|
+
* ## Ordering: the claim and the content, never apart
|
|
69
|
+
*
|
|
70
|
+
* The steps are rename → read → RECORD → unlink → deliver, and a failure at the
|
|
71
|
+
* record leaves the `.processing` file for the next poll to ADOPT. That order is
|
|
72
|
+
* forced, in the shape inc E3a settled for the passive-notice store: nothing that
|
|
73
|
+
* makes the briefing unrecoverable may happen before the consumption fact is
|
|
74
|
+
* durable.
|
|
75
|
+
*
|
|
76
|
+
* The order used to be rename → read → UNLINK → record, and the record sits under
|
|
77
|
+
* the catch below. One failing SQLite write therefore returned empty with the
|
|
78
|
+
* mailbox AND the `.processing` file gone and no row written: a transient DB error
|
|
79
|
+
* permanently deleted a worker's briefing — the one thing a card worker cannot work
|
|
80
|
+
* without. The in-memory Set this column replaced had no such path, because it could
|
|
81
|
+
* not fail.
|
|
82
|
+
*
|
|
83
|
+
* Adoption is what makes the rename reversible, and it is required rather than
|
|
84
|
+
* decorative: nothing else in this codebase ever comes back for a `.processing`
|
|
85
|
+
* file. `deletePendingTaskMailbox` is the only other code that knows that name, and
|
|
86
|
+
* it only DELETES, at retirement — so "leave it behind on failure" is a remedy only
|
|
87
|
+
* once some path returns for it, and this is that path.
|
|
88
|
+
*
|
|
89
|
+
* On a failed record the task stays queued and the worker polls again in 2s; it is
|
|
90
|
+
* never "neither the task nor the record". Delivery is NOT conditional on the
|
|
91
|
+
* database being writable in the sense that matters: a blip costs a poll interval,
|
|
92
|
+
* not the briefing.
|
|
93
|
+
*
|
|
94
|
+
* What adoption pays for is duplicate DELIVERY, never loss, and the cost lands on the
|
|
95
|
+
* WORKER rather than on this column: it receives the same briefing twice and may ACT
|
|
96
|
+
* twice. Three states reach that — the unlink failed, the process died between the
|
|
97
|
+
* commit and the unlink, two pollers adopted one stranded file. The column is unmoved
|
|
98
|
+
* in all three, because `markWorkerTaskConsumed` keeps the FIRST timestamp.
|
|
99
|
+
*
|
|
100
|
+
* The number of extra deliveries is not one. A TRANSIENT unlink failure costs exactly
|
|
101
|
+
* one: the next poll adopts the file, delivers it, and unlinks it. An unlink that can
|
|
102
|
+
* NEVER succeed — file held open, permissions revoked — leaves a `.processing` that
|
|
103
|
+
* the fast pre-check counts as pending work on every poll, so the same briefing goes
|
|
104
|
+
* out every 2s for the life of this wait call, where the old order lost it exactly
|
|
105
|
+
* once. What keeps that narrow is the step before it: the write that recorded the
|
|
106
|
+
* consumption already succeeded, so a filesystem that cannot unlink the file it just
|
|
107
|
+
* let us rename and read is already misbehaving.
|
|
56
108
|
*/
|
|
57
|
-
async function consumePendingTask(threadId) {
|
|
109
|
+
async function consumePendingTask(db, threadId) {
|
|
58
110
|
const pendingTaskPath = join(PENDING_TASKS_DIR, `${threadId}.txt`);
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
111
|
+
const claimedPath = pendingTaskPath + ".processing";
|
|
112
|
+
// Fast pre-check to avoid unnecessary rename attempts every 2s. A `.processing`
|
|
113
|
+
// file counts as pending work: it is an unfinished consumption, not litter.
|
|
114
|
+
if (!existsSync(pendingTaskPath) && !existsSync(claimedPath))
|
|
115
|
+
return Optional.empty();
|
|
62
116
|
try {
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
117
|
+
// The rename is the claim, and it is atomic between this loop's two arms and
|
|
118
|
+
// between racing sessions. A `.processing` that is already there is a claim an
|
|
119
|
+
// earlier pass took and did not finish: adopt it rather than renaming onto it.
|
|
120
|
+
if (existsSync(pendingTaskPath))
|
|
121
|
+
await rename(pendingTaskPath, claimedPath);
|
|
122
|
+
const taskContent = (await readFile(claimedPath, "utf-8")).trim();
|
|
123
|
+
// Record the consumption durably, so the worker-exit handler never respawns a
|
|
124
|
+
// worker that already did work — including after a server restart, which the
|
|
125
|
+
// in-memory Set this replaces could not survive, and across which the exit
|
|
126
|
+
// watcher still observes a worker that outlived it. Also guards against the
|
|
127
|
+
// duplicate posts a late mailbox append used to cause by recreating the file.
|
|
128
|
+
//
|
|
129
|
+
// BEFORE the unlink: a throw here returns empty with the content still sitting in
|
|
130
|
+
// `.processing`, which the next poll adopts. After the unlink, the same throw
|
|
131
|
+
// would have deleted the briefing outright.
|
|
132
|
+
markWorkerTaskConsumed(db, threadId, Date.now());
|
|
66
133
|
try {
|
|
67
|
-
await unlink(
|
|
134
|
+
await unlink(claimedPath);
|
|
68
135
|
}
|
|
69
136
|
catch {
|
|
70
|
-
/* ignore cleanup errors
|
|
137
|
+
/* ignore cleanup errors — the fact is already durable, so a surviving
|
|
138
|
+
.processing costs re-delivery and never the task; the ordering note above
|
|
139
|
+
says how much re-delivery */
|
|
71
140
|
}
|
|
72
|
-
// Mark this thread's task as consumed so the worker-exit handler never
|
|
73
|
-
// respawns a worker that already did work (guards against duplicate posts
|
|
74
|
-
// when a late mailbox append recreates the pending-task file).
|
|
75
|
-
markTaskConsumed(threadId);
|
|
76
141
|
log.info(`[wait] Injecting pending task for thread ${threadId} (${taskContent.length} chars)`);
|
|
77
|
-
return {
|
|
142
|
+
return Optional.of({
|
|
78
143
|
content: [
|
|
79
144
|
{
|
|
80
145
|
type: "text",
|
|
@@ -83,14 +148,34 @@ async function consumePendingTask(threadId) {
|
|
|
83
148
|
`<<< END CROSS-THREAD MESSAGE >>>`,
|
|
84
149
|
},
|
|
85
150
|
],
|
|
86
|
-
};
|
|
151
|
+
});
|
|
87
152
|
}
|
|
88
153
|
catch (err) {
|
|
89
154
|
if (err?.code !== "ENOENT")
|
|
90
155
|
log.warn(`[wait] Pending task read failed: ${err}`);
|
|
91
|
-
|
|
156
|
+
// The file is gone, unreadable, or the consumption could not be recorded. In the
|
|
157
|
+
// last case the claimed `.processing` file still holds the task and the next poll
|
|
158
|
+
// adopts it, so returning empty costs a poll interval and not the briefing.
|
|
159
|
+
return Optional.empty();
|
|
92
160
|
}
|
|
93
161
|
}
|
|
162
|
+
/** A worker's death notice, delivered as its own inbox message — the way the
|
|
163
|
+
* worker's reply would have arrived. One per wait call, oldest first. */
|
|
164
|
+
function consumeDeathNotice(db, threadId) {
|
|
165
|
+
return takeWorkerDeathNotice(db, threadId).map((notice) => {
|
|
166
|
+
log.info(`[wait] Delivering a worker death notice to thread ${threadId}`);
|
|
167
|
+
return {
|
|
168
|
+
content: [
|
|
169
|
+
{
|
|
170
|
+
type: "text",
|
|
171
|
+
text: `<<< CROSS-THREAD MESSAGE >>>
|
|
172
|
+
${notice.text}
|
|
173
|
+
<<< END CROSS-THREAD MESSAGE >>>`,
|
|
174
|
+
},
|
|
175
|
+
],
|
|
176
|
+
};
|
|
177
|
+
});
|
|
178
|
+
}
|
|
94
179
|
// ---------------------------------------------------------------------------
|
|
95
180
|
// Handler
|
|
96
181
|
// ---------------------------------------------------------------------------
|
|
@@ -126,13 +211,7 @@ export async function handleWaitForInstructions(args, ctx, extra) {
|
|
|
126
211
|
}
|
|
127
212
|
const callNumber = ++state.waitCallCount;
|
|
128
213
|
const timeoutMs = WAIT_TIMEOUT_MINUTES * 60 * 1000;
|
|
129
|
-
|
|
130
|
-
// SSE keepalive progress notifications. Cap the loop to 90s so we always
|
|
131
|
-
// return a valid response before the Codex client gives up.
|
|
132
|
-
const agentType = getEffectiveAgentType(effectiveThreadId);
|
|
133
|
-
const isShortTimeoutClient = agentType === "codex" || agentType === "openai_codex";
|
|
134
|
-
const effectiveTimeoutMs = isShortTimeoutClient ? 90_000 : timeoutMs;
|
|
135
|
-
const deadline = Date.now() + effectiveTimeoutMs;
|
|
214
|
+
const deadline = Date.now() + timeoutMs;
|
|
136
215
|
// ── Pending task injection (pre-loop check) ────────────────────────────
|
|
137
216
|
// If start_thread or send_message_to_thread wrote a task file for this
|
|
138
217
|
// thread, deliver it immediately — but only if this session is still active.
|
|
@@ -152,9 +231,12 @@ export async function handleWaitForInstructions(args, ctx, extra) {
|
|
|
152
231
|
],
|
|
153
232
|
};
|
|
154
233
|
}
|
|
155
|
-
const preLoopTask = await consumePendingTask(effectiveThreadId);
|
|
156
|
-
if (preLoopTask)
|
|
157
|
-
return preLoopTask;
|
|
234
|
+
const preLoopTask = await consumePendingTask(getMemoryDb(), effectiveThreadId);
|
|
235
|
+
if (preLoopTask.has())
|
|
236
|
+
return preLoopTask.get();
|
|
237
|
+
const preLoopDeath = consumeDeathNotice(getMemoryDb(), effectiveThreadId);
|
|
238
|
+
if (preLoopDeath.has())
|
|
239
|
+
return preLoopDeath.get();
|
|
158
240
|
// Poll the dispatcher's per-thread file instead of calling getUpdates
|
|
159
241
|
// directly. This avoids 409 conflicts between concurrent instances.
|
|
160
242
|
const POLL_INTERVAL_MS = 2000;
|
|
@@ -173,245 +255,263 @@ export async function handleWaitForInstructions(args, ctx, extra) {
|
|
|
173
255
|
// echoing requestId there fails to match, the keepalive never resets its
|
|
174
256
|
// timeout, and the call dies at ~60s. Echo the client's token when present.
|
|
175
257
|
const progressToken = extra._meta?.progressToken ?? extra.requestId;
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
text: "Client disconnected. Call wait_for_instructions again to resume.",
|
|
203
|
-
},
|
|
204
|
-
],
|
|
205
|
-
};
|
|
206
|
-
}
|
|
207
|
-
// Bail out if the thread has been archived — graceful shutdown without kill.
|
|
208
|
-
if (Date.now() - lastArchivedCheck >= ARCHIVED_CHECK_INTERVAL_MS) {
|
|
209
|
-
lastArchivedCheck = Date.now();
|
|
210
|
-
// TTL grace window: the worker crossed its TTL and is winding down, but
|
|
211
|
-
// its MCP socket is deliberately kept open so it can finish THIS turn and
|
|
212
|
-
// deliver its final result before the cleanup service tears it down. This
|
|
213
|
-
// returns to the worker so it can still act (send its result) — a soft
|
|
214
|
-
// "finish then terminate" signal, not a hard stop.
|
|
215
|
-
if (isWorkerInGrace(effectiveThreadId)) {
|
|
216
|
-
log.info(`[wait] Thread ${effectiveThreadId} is in TTL grace — instructing worker to finish and deliver its final result.`);
|
|
258
|
+
// ── Park mark ───────────────────────────────────────────────────────────
|
|
259
|
+
// From here until this call returns, the worker is PARKED: it is not working,
|
|
260
|
+
// it is waiting on us. The TTL sweep reads this to tell a working worker
|
|
261
|
+
// (defer teardown) from a parked one (tear down — parked is not work). Marked
|
|
262
|
+
// AFTER the pre-loop task consumption, which returns without ever waiting.
|
|
263
|
+
//
|
|
264
|
+
// The mark is filed under THIS call's owner identity (the same `preSid` the
|
|
265
|
+
// reconcile above just claimed ownership with), so a superseded session's
|
|
266
|
+
// residual mark can never speak for the replacement that owns the thread now.
|
|
267
|
+
//
|
|
268
|
+
// The returned key is released verbatim below — never recomputed, since a
|
|
269
|
+
// mid-wait token change would resolve to a different key and leak the mark.
|
|
270
|
+
//
|
|
271
|
+
// The unmark MUST be in a `finally`: every exit path — message delivered,
|
|
272
|
+
// superseded, aborted, grace, archived, maintenance, timeout — has to release
|
|
273
|
+
// it, or a worker that resumed working would still read as parked.
|
|
274
|
+
const parkKey = markThreadWaiting(effectiveThreadId, preSid);
|
|
275
|
+
try {
|
|
276
|
+
while (Date.now() < deadline) {
|
|
277
|
+
try {
|
|
278
|
+
// Bail out if this session has been superseded by a newer session for the
|
|
279
|
+
// same thread. Without this, a zombie session races the active one for
|
|
280
|
+
// messages — consuming them but responding with degraded/stale context.
|
|
281
|
+
const currentSid = ctx.getMcpSessionId?.();
|
|
282
|
+
if (isSessionSuperseded(currentSid, effectiveThreadId)) {
|
|
283
|
+
log.warn(`[wait] Session ${currentSid?.slice(0, 8)}… superseded for thread ${effectiveThreadId} — terminating poll loop.`);
|
|
217
284
|
state.lastToolCallAt = Date.now();
|
|
218
285
|
return {
|
|
219
286
|
content: [
|
|
220
287
|
{
|
|
221
288
|
type: "text",
|
|
222
|
-
text: "
|
|
289
|
+
text: "Session terminated — a newer session is now active for this thread. Do not call wait_for_instructions again.",
|
|
223
290
|
},
|
|
224
291
|
],
|
|
225
292
|
};
|
|
226
293
|
}
|
|
227
|
-
|
|
228
|
-
if (
|
|
229
|
-
log.info(`[wait]
|
|
294
|
+
// Bail out if the MCP transport signalled abort (client disconnected).
|
|
295
|
+
if (extra.signal.aborted) {
|
|
296
|
+
log.info(`[wait] Signal aborted for session ${currentSid?.slice(0, 8)}… thread ${effectiveThreadId} — client disconnected.`);
|
|
230
297
|
state.lastToolCallAt = Date.now();
|
|
231
298
|
return {
|
|
232
299
|
content: [
|
|
233
300
|
{
|
|
234
301
|
type: "text",
|
|
235
|
-
text: "
|
|
302
|
+
text: "Client disconnected. Call wait_for_instructions again to resume.",
|
|
236
303
|
},
|
|
237
304
|
],
|
|
238
305
|
};
|
|
239
306
|
}
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
if (markMaintenanceObserved(tgKey)) {
|
|
256
|
-
let version = "unknown";
|
|
257
|
-
try {
|
|
258
|
-
version = JSON.parse(maintenanceInfo).version ?? version;
|
|
307
|
+
// Bail out if the thread has been archived — graceful shutdown without kill.
|
|
308
|
+
if (Date.now() - lastArchivedCheck >= ARCHIVED_CHECK_INTERVAL_MS) {
|
|
309
|
+
lastArchivedCheck = Date.now();
|
|
310
|
+
const threadState = ctx.threadLifecycle.getThreadState(getMemoryDb(), effectiveThreadId);
|
|
311
|
+
if (threadState === ThreadState.Archived || threadState === ThreadState.Expired) {
|
|
312
|
+
log.info(`[wait] Thread ${effectiveThreadId} is ${threadState} — instructing agent to exit.`);
|
|
313
|
+
state.lastToolCallAt = Date.now();
|
|
314
|
+
return {
|
|
315
|
+
content: [
|
|
316
|
+
{
|
|
317
|
+
type: "text",
|
|
318
|
+
text: "Session terminated. Thread has been archived. Do not call wait_for_instructions again — exit immediately.",
|
|
319
|
+
},
|
|
320
|
+
],
|
|
321
|
+
};
|
|
259
322
|
}
|
|
260
|
-
|
|
261
|
-
|
|
323
|
+
}
|
|
324
|
+
// Check for pending update — tell agent to poll the supervisor's /ready
|
|
325
|
+
// endpoint over plain HTTP. CRITICAL: Do NOT tell agents to call any MCP tool
|
|
326
|
+
// on sensorium-mcp here — the server is about to die. buildMaintenanceResponse
|
|
327
|
+
// hands back a PowerShell poll loop against the supervisor (survives the
|
|
328
|
+
// restart), with an external sleep as the last-resort fallback.
|
|
329
|
+
const maintenanceInfo = checkMaintenanceFlag();
|
|
330
|
+
if (maintenanceInfo) {
|
|
331
|
+
log.info(`[wait] Maintenance flag detected: ${maintenanceInfo}`);
|
|
332
|
+
// Record that this thread observed maintenance. This both (a) fires the
|
|
333
|
+
// Telegram notification once per thread across all wait_for_instructions
|
|
334
|
+
// calls, and (b) tells self-update this agent has backed off so the port
|
|
335
|
+
// close can proceed (ACK-gated). markMaintenanceObserved returns true only
|
|
336
|
+
// on the first observation this cycle.
|
|
337
|
+
const tgKey = effectiveThreadId ?? 0;
|
|
338
|
+
if (markMaintenanceObserved(tgKey)) {
|
|
339
|
+
let version = "unknown";
|
|
340
|
+
try {
|
|
341
|
+
version = JSON.parse(maintenanceInfo).version ?? version;
|
|
342
|
+
}
|
|
343
|
+
catch {
|
|
344
|
+
/* not JSON or missing field */
|
|
345
|
+
}
|
|
346
|
+
telegram
|
|
347
|
+
.sendMessage(telegramChatId, `\u26A0\uFE0F Server update: v${version} deploying. Agent sessions will reconnect after update.`, undefined, effectiveThreadId)
|
|
348
|
+
.catch((err) => {
|
|
349
|
+
log.warn(`[poll] Maintenance notification failed for thread ${effectiveThreadId}: ${err instanceof Error ? err.message : err}`);
|
|
350
|
+
});
|
|
262
351
|
}
|
|
263
|
-
|
|
264
|
-
.sendMessage(telegramChatId, `\u26A0\uFE0F Server update: v${version} deploying. Agent sessions will reconnect after update.`, undefined, effectiveThreadId)
|
|
265
|
-
.catch((err) => {
|
|
266
|
-
log.warn(`[poll] Maintenance notification failed for thread ${effectiveThreadId}: ${err instanceof Error ? err.message : err}`);
|
|
267
|
-
});
|
|
352
|
+
return buildMaintenanceResponse(effectiveThreadId, getShortReminder(effectiveThreadId, state.sessionStartedAt));
|
|
268
353
|
}
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
sessionStartedAt: state.sessionStartedAt,
|
|
288
|
-
autonomousMode: getEffectiveAutonomousMode(effectiveThreadId),
|
|
289
|
-
});
|
|
290
|
-
if (reactionResult)
|
|
291
|
-
return reactionResult;
|
|
292
|
-
}
|
|
293
|
-
// ── Pending task injection (in-loop) ─────────────────────────────────────────
|
|
294
|
-
// Check for tasks sent via send_message_to_thread while we're already
|
|
295
|
-
// polling. Without this, messages arrive only on the NEXT
|
|
296
|
-
// wait_for_instructions call, causing a "no instructions" gap.
|
|
297
|
-
if (!extra.signal.aborted &&
|
|
298
|
-
!isSessionSuperseded(ctx.getMcpSessionId?.(), effectiveThreadId)) {
|
|
299
|
-
const inLoopTask = await consumePendingTask(effectiveThreadId);
|
|
300
|
-
if (inLoopTask)
|
|
301
|
-
return inLoopTask;
|
|
302
|
-
}
|
|
303
|
-
// Check scheduled tasks every ~60s during idle polling.
|
|
304
|
-
if (effectiveThreadId !== undefined && Date.now() - lastScheduleCheck >= 60_000) {
|
|
305
|
-
lastScheduleCheck = Date.now();
|
|
306
|
-
const taskResult = checkForDueTasks(ctx, effectiveThreadId);
|
|
307
|
-
if (taskResult)
|
|
308
|
-
return taskResult;
|
|
309
|
-
}
|
|
310
|
-
// ── In-loop drive activation check (every 30 min) ──────────────────
|
|
311
|
-
// Without this, the drive only fires on poll TIMEOUT (every 2h default).
|
|
312
|
-
// Checking inside the loop ensures consistent activation during long polls.
|
|
313
|
-
if (effectiveThreadId !== undefined &&
|
|
314
|
-
getEffectiveAutonomousMode(effectiveThreadId) &&
|
|
315
|
-
Date.now() - lastDriveCheck >= DRIVE_CHECK_INTERVAL_MS) {
|
|
316
|
-
lastDriveCheck = Date.now();
|
|
317
|
-
runAutoConsolidation({
|
|
318
|
-
state,
|
|
319
|
-
effectiveThreadId,
|
|
320
|
-
getMemoryDb,
|
|
321
|
-
apiKey: config.OPENAI_API_KEY || undefined,
|
|
322
|
-
config,
|
|
323
|
-
memoryRefresh: "",
|
|
324
|
-
scheduleHint: "",
|
|
325
|
-
});
|
|
326
|
-
const driveResult = checkDriveActivation({
|
|
327
|
-
state,
|
|
328
|
-
effectiveThreadId,
|
|
329
|
-
getMemoryDb,
|
|
330
|
-
apiKey: config.OPENAI_API_KEY || undefined,
|
|
331
|
-
config,
|
|
332
|
-
memoryRefresh: "",
|
|
333
|
-
scheduleHint: "",
|
|
334
|
-
});
|
|
335
|
-
if (driveResult)
|
|
336
|
-
return driveResult;
|
|
337
|
-
}
|
|
338
|
-
// No messages yet — sleep briefly and check again.
|
|
339
|
-
// Send SSE keepalive to prevent silent connection death during long polls.
|
|
340
|
-
if (Date.now() - lastKeepalive >= SSE_KEEPALIVE_INTERVAL_MS) {
|
|
341
|
-
lastKeepalive = Date.now();
|
|
342
|
-
state.lastToolCallAt = Date.now();
|
|
343
|
-
try {
|
|
344
|
-
await extra.sendNotification({
|
|
345
|
-
method: "notifications/progress",
|
|
346
|
-
params: {
|
|
347
|
-
progressToken,
|
|
348
|
-
progress: 0,
|
|
349
|
-
total: 0,
|
|
350
|
-
},
|
|
354
|
+
// Peek first (non-destructive) to avoid consuming messages when the
|
|
355
|
+
// SSE connection may be dead.
|
|
356
|
+
const peeked = peekThreadMessages(effectiveThreadId);
|
|
357
|
+
if (peeked.length > 0) {
|
|
358
|
+
return processIncomingMessages(effectiveThreadId, peeked.length, ctx, extra);
|
|
359
|
+
}
|
|
360
|
+
// ── Reaction-only wake-up ───────────────────────────────────────
|
|
361
|
+
// Guard: don't consume the reaction file if the SSE connection is
|
|
362
|
+
// already dead — readPendingReaction() is destructive (read + delete).
|
|
363
|
+
// Without this check the reaction is eaten but never delivered.
|
|
364
|
+
if (!extra.signal.aborted &&
|
|
365
|
+
!isSessionSuperseded(ctx.getMcpSessionId?.(), effectiveThreadId)) {
|
|
366
|
+
const reactionResult = await handleReactionOnly({
|
|
367
|
+
telegram,
|
|
368
|
+
getMemoryDb,
|
|
369
|
+
effectiveThreadId,
|
|
370
|
+
sessionStartedAt: state.sessionStartedAt,
|
|
371
|
+
autonomousMode: getEffectiveAutonomousMode(effectiveThreadId),
|
|
351
372
|
});
|
|
373
|
+
if (reactionResult)
|
|
374
|
+
return reactionResult;
|
|
352
375
|
}
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
};
|
|
376
|
+
// ── Pending task injection (in-loop) ─────────────────────────────────────────
|
|
377
|
+
// Check for tasks sent via send_message_to_thread while we're already
|
|
378
|
+
// polling. Without this, messages arrive only on the NEXT
|
|
379
|
+
// wait_for_instructions call, causing a "no instructions" gap.
|
|
380
|
+
if (!extra.signal.aborted &&
|
|
381
|
+
!isSessionSuperseded(ctx.getMcpSessionId?.(), effectiveThreadId)) {
|
|
382
|
+
const inLoopTask = await consumePendingTask(ctx.getMemoryDb(), effectiveThreadId);
|
|
383
|
+
if (inLoopTask.has())
|
|
384
|
+
return inLoopTask.get();
|
|
385
|
+
const inLoopDeath = consumeDeathNotice(ctx.getMemoryDb(), effectiveThreadId);
|
|
386
|
+
if (inLoopDeath.has())
|
|
387
|
+
return inLoopDeath.get();
|
|
366
388
|
}
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
resolved = true;
|
|
374
|
-
clearTimeout(timer);
|
|
375
|
-
unsubMaintenance?.();
|
|
376
|
-
resolve();
|
|
377
|
-
}
|
|
378
|
-
};
|
|
379
|
-
const timer = setTimeout(done, POLL_INTERVAL_MS);
|
|
380
|
-
// Wake up immediately if the maintenance flag is written — don't wait
|
|
381
|
-
// for the next 2s tick, which could be too late if killServer() follows
|
|
382
|
-
// immediately after the flag is written.
|
|
383
|
-
unsubMaintenance = onMaintenanceSignal(done);
|
|
384
|
-
if (!extra.signal.aborted) {
|
|
385
|
-
extra.signal.addEventListener("abort", done, { once: true });
|
|
389
|
+
// Check scheduled tasks every ~60s during idle polling.
|
|
390
|
+
if (effectiveThreadId !== undefined && Date.now() - lastScheduleCheck >= 60_000) {
|
|
391
|
+
lastScheduleCheck = Date.now();
|
|
392
|
+
const taskResult = checkForDueTasks(ctx, effectiveThreadId);
|
|
393
|
+
if (taskResult)
|
|
394
|
+
return taskResult;
|
|
386
395
|
}
|
|
387
|
-
|
|
388
|
-
|
|
396
|
+
// ── In-loop drive activation check (every 30 min) ──────────────────
|
|
397
|
+
// Without this, the drive only fires on poll TIMEOUT (every 2h default).
|
|
398
|
+
// Checking inside the loop ensures consistent activation during long polls.
|
|
399
|
+
if (effectiveThreadId !== undefined &&
|
|
400
|
+
getEffectiveAutonomousMode(effectiveThreadId) &&
|
|
401
|
+
Date.now() - lastDriveCheck >= DRIVE_CHECK_INTERVAL_MS) {
|
|
402
|
+
lastDriveCheck = Date.now();
|
|
403
|
+
runAutoConsolidation({
|
|
404
|
+
state,
|
|
405
|
+
effectiveThreadId,
|
|
406
|
+
getMemoryDb,
|
|
407
|
+
apiKey: config.OPENAI_API_KEY || undefined,
|
|
408
|
+
config,
|
|
409
|
+
memoryRefresh: "",
|
|
410
|
+
scheduleHint: "",
|
|
411
|
+
});
|
|
412
|
+
const driveResult = checkDriveActivation({
|
|
413
|
+
state,
|
|
414
|
+
effectiveThreadId,
|
|
415
|
+
getMemoryDb,
|
|
416
|
+
apiKey: config.OPENAI_API_KEY || undefined,
|
|
417
|
+
config,
|
|
418
|
+
memoryRefresh: "",
|
|
419
|
+
scheduleHint: "",
|
|
420
|
+
});
|
|
421
|
+
if (driveResult)
|
|
422
|
+
return driveResult;
|
|
389
423
|
}
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
// iteration — every 60s is enough for reconnect detection).
|
|
396
|
-
if (Date.now() - lastRegistryUpdate > 60_000) {
|
|
397
|
-
lastRegistryUpdate = Date.now();
|
|
424
|
+
// No messages yet — sleep briefly and check again.
|
|
425
|
+
// Send SSE keepalive to prevent silent connection death during long polls.
|
|
426
|
+
if (Date.now() - lastKeepalive >= SSE_KEEPALIVE_INTERVAL_MS) {
|
|
427
|
+
lastKeepalive = Date.now();
|
|
428
|
+
state.lastToolCallAt = Date.now();
|
|
398
429
|
try {
|
|
399
|
-
|
|
400
|
-
|
|
430
|
+
await extra.sendNotification({
|
|
431
|
+
method: "notifications/progress",
|
|
432
|
+
params: {
|
|
433
|
+
progressToken,
|
|
434
|
+
progress: 0,
|
|
435
|
+
total: 0,
|
|
436
|
+
},
|
|
401
437
|
});
|
|
402
438
|
}
|
|
403
|
-
catch
|
|
404
|
-
|
|
439
|
+
catch {
|
|
440
|
+
// If notification fails, the SSE stream is already dead.
|
|
441
|
+
// Return immediately so the agent can reconnect.
|
|
442
|
+
log.warn(`[wait] SSE keepalive failed — connection dead. Returning early.`);
|
|
443
|
+
state.lastToolCallAt = Date.now();
|
|
444
|
+
return {
|
|
445
|
+
content: [
|
|
446
|
+
{
|
|
447
|
+
type: "text",
|
|
448
|
+
text: "The connection was interrupted. Please call wait_for_instructions again immediately to resume polling.",
|
|
449
|
+
},
|
|
450
|
+
],
|
|
451
|
+
};
|
|
452
|
+
}
|
|
453
|
+
}
|
|
454
|
+
await new Promise((resolve) => {
|
|
455
|
+
let resolved = false;
|
|
456
|
+
// A no-op until onMaintenanceSignal hands back the real unsubscribe below:
|
|
457
|
+
// `done` closes over this before the subscription exists, and a done() that
|
|
458
|
+
// fires first has nothing to unsubscribe.
|
|
459
|
+
let unsubMaintenance = () => { };
|
|
460
|
+
const done = () => {
|
|
461
|
+
if (!resolved) {
|
|
462
|
+
resolved = true;
|
|
463
|
+
clearTimeout(timer);
|
|
464
|
+
unsubMaintenance();
|
|
465
|
+
resolve();
|
|
466
|
+
}
|
|
467
|
+
};
|
|
468
|
+
const timer = setTimeout(done, POLL_INTERVAL_MS);
|
|
469
|
+
// Wake up immediately if the maintenance flag is written — don't wait
|
|
470
|
+
// for the next 2s tick, which could be too late if killServer() follows
|
|
471
|
+
// immediately after the flag is written.
|
|
472
|
+
unsubMaintenance = onMaintenanceSignal(done);
|
|
473
|
+
if (!extra.signal.aborted) {
|
|
474
|
+
extra.signal.addEventListener("abort", done, { once: true });
|
|
475
|
+
}
|
|
476
|
+
else {
|
|
477
|
+
done();
|
|
478
|
+
}
|
|
479
|
+
});
|
|
480
|
+
// A transport can close while the two-second poll sleep is resolving.
|
|
481
|
+
// Do not let that retired session write one final heartbeat: it would
|
|
482
|
+
// mask the dead agent from keeper until the next liveness check.
|
|
483
|
+
if (extra.signal.aborted ||
|
|
484
|
+
isSessionSuperseded(ctx.getMcpSessionId?.(), effectiveThreadId)) {
|
|
485
|
+
continue;
|
|
486
|
+
}
|
|
487
|
+
writeActivityHeartbeat();
|
|
488
|
+
if (effectiveThreadId !== undefined) {
|
|
489
|
+
writeThreadHeartbeatSync(effectiveThreadId);
|
|
490
|
+
// Update thread_registry.lastActiveAt periodically (not on every poll
|
|
491
|
+
// iteration — every 60s is enough for reconnect detection).
|
|
492
|
+
if (Date.now() - lastRegistryUpdate > 60_000) {
|
|
493
|
+
lastRegistryUpdate = Date.now();
|
|
494
|
+
try {
|
|
495
|
+
ctx.threadLifecycle.touchThread(getMemoryDb(), effectiveThreadId, {
|
|
496
|
+
lastActiveAt: new Date().toISOString(),
|
|
497
|
+
});
|
|
498
|
+
}
|
|
499
|
+
catch (err) {
|
|
500
|
+
log.debug(`[poll] Heartbeat update failed for thread ${effectiveThreadId}: ${err instanceof Error ? err.message : err}`);
|
|
501
|
+
}
|
|
405
502
|
}
|
|
406
503
|
}
|
|
407
504
|
}
|
|
505
|
+
catch (loopErr) {
|
|
506
|
+
log.error(`Poll loop error: ${loopErr instanceof Error ? loopErr.message : String(loopErr)}`);
|
|
507
|
+
continue;
|
|
508
|
+
}
|
|
408
509
|
}
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
510
|
+
// Timeout elapsed with no actionable message.
|
|
511
|
+
return handlePollTimeout(effectiveThreadId, callNumber, ctx);
|
|
512
|
+
}
|
|
513
|
+
finally {
|
|
514
|
+
unmarkThreadWaiting(effectiveThreadId, parkKey);
|
|
413
515
|
}
|
|
414
|
-
// Timeout elapsed with no actionable message.
|
|
415
|
-
return handlePollTimeout(effectiveThreadId, callNumber, ctx);
|
|
416
516
|
}
|
|
417
517
|
//# sourceMappingURL=poll-loop.js.map
|