@neurocode-ai/core 1.18.8
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/bin/neurocode +199 -0
- package/bunfig.toml +2 -0
- package/drizzle.config.ts +10 -0
- package/package.json +131 -0
- package/schema.json +2071 -0
- package/script/fix-node-pty.ts +28 -0
- package/script/migration.ts +196 -0
- package/src/account/sql.ts +39 -0
- package/src/account.ts +101 -0
- package/src/agent.ts +111 -0
- package/src/aisdk.ts +235 -0
- package/src/background-job.ts +365 -0
- package/src/catalog.ts +301 -0
- package/src/command.ts +64 -0
- package/src/config/agent.ts +25 -0
- package/src/config/attachments.ts +15 -0
- package/src/config/command.ts +12 -0
- package/src/config/compaction.ts +15 -0
- package/src/config/experimental.ts +18 -0
- package/src/config/formatter.ts +12 -0
- package/src/config/lsp.ts +18 -0
- package/src/config/markdown.ts +36 -0
- package/src/config/mcp.ts +48 -0
- package/src/config/plugin/agent.ts +179 -0
- package/src/config/plugin/command.ts +83 -0
- package/src/config/plugin/external.ts +91 -0
- package/src/config/plugin/provider.ts +113 -0
- package/src/config/plugin/reference.ts +70 -0
- package/src/config/plugin/skill.ts +50 -0
- package/src/config/plugin.ts +13 -0
- package/src/config/provider.ts +71 -0
- package/src/config/reference.ts +22 -0
- package/src/config/tool-output.ts +9 -0
- package/src/config/watcher.ts +7 -0
- package/src/config.ts +227 -0
- package/src/control-plane/move-session.ts +148 -0
- package/src/control-plane/workspace.sql.ts +20 -0
- package/src/credential/sql.ts +14 -0
- package/src/credential.ts +138 -0
- package/src/cross-spawn-spawner.ts +507 -0
- package/src/data-migration.sql.ts +6 -0
- package/src/database/database.ts +57 -0
- package/src/database/migration/20260127222353_familiar_lady_ursula.ts +107 -0
- package/src/database/migration/20260211171708_add_project_commands.ts +11 -0
- package/src/database/migration/20260213144116_wakeful_the_professor.ts +23 -0
- package/src/database/migration/20260225215848_workspace.ts +19 -0
- package/src/database/migration/20260227213759_add_session_workspace_id.ts +12 -0
- package/src/database/migration/20260228203230_blue_harpoon.ts +30 -0
- package/src/database/migration/20260303231226_add_workspace_fields.ts +15 -0
- package/src/database/migration/20260309230000_move_org_to_state.ts +15 -0
- package/src/database/migration/20260312043431_session_message_cursor.ts +16 -0
- package/src/database/migration/20260323234822_events.ts +26 -0
- package/src/database/migration/20260410174513_workspace-name.ts +29 -0
- package/src/database/migration/20260413175956_chief_energizer.ts +24 -0
- package/src/database/migration/20260423070820_add_icon_url_override.ts +14 -0
- package/src/database/migration/20260427172553_slow_nightmare.ts +30 -0
- package/src/database/migration/20260428004200_add_session_path.ts +11 -0
- package/src/database/migration/20260501142318_next_venus.ts +12 -0
- package/src/database/migration/20260504145000_add_sync_owner.ts +11 -0
- package/src/database/migration/20260507164347_add_workspace_time.ts +11 -0
- package/src/database/migration/20260510033149_session_usage.ts +56 -0
- package/src/database/migration/20260511000411_data_migration_state.ts +16 -0
- package/src/database/migration/20260511173437_session-metadata.ts +16 -0
- package/src/database/migration/20260601010001_normalize_storage_paths.ts +22 -0
- package/src/database/migration/20260601202201_amazing_prowler.ts +11 -0
- package/src/database/migration/20260602002951_lowly_union_jack.ts +24 -0
- package/src/database/migration/20260602182828_add_project_directories.ts +20 -0
- package/src/database/migration/20260603001617_session_message_projection_indexes.ts +19 -0
- package/src/database/migration/20260603040000_session_message_projection_order.ts +19 -0
- package/src/database/migration/20260603141458_session_input_inbox.ts +25 -0
- package/src/database/migration/20260603160727_jittery_ezekiel_stane.ts +20 -0
- package/src/database/migration/20260604172448_event_sourced_session_input.ts +47 -0
- package/src/database/migration/20260605003541_add_session_context_snapshot.ts +21 -0
- package/src/database/migration/20260605042240_add_context_epoch_agent.ts +11 -0
- package/src/database/migration/20260611035744_credential.ts +25 -0
- package/src/database/migration/20260611192811_lush_chimera.ts +25 -0
- package/src/database/migration/20260612174303_project_dir_strategy.ts +29 -0
- package/src/database/migration/20260622142730_simplify_session_context_epoch.ts +13 -0
- package/src/database/migration/20260622170816_reset_v2_session_state.ts +17 -0
- package/src/database/migration/20260622202450_simplify_session_input.ts +17 -0
- package/src/database/migration.gen.ts +44 -0
- package/src/database/migration.ts +81 -0
- package/src/database/path.ts +91 -0
- package/src/database/schema.gen.ts +274 -0
- package/src/database/schema.sql.ts +10 -0
- package/src/database/sqlite.bun.ts +183 -0
- package/src/database/sqlite.node.ts +178 -0
- package/src/database/sqlite.ts +8 -0
- package/src/effect/app-node-builder.ts +23 -0
- package/src/effect/app-node-platform.ts +18 -0
- package/src/effect/app-node.ts +14 -0
- package/src/effect/dfdf +1 -0
- package/src/effect/keyed-mutex.ts +45 -0
- package/src/effect/layer-node.ts +333 -0
- package/src/effect/memo-map.ts +3 -0
- package/src/effect/runtime.ts +21 -0
- package/src/effect/service-use.ts +43 -0
- package/src/event/sql.ts +25 -0
- package/src/event.ts +638 -0
- package/src/file-mutation.ts +207 -0
- package/src/file.ts +6 -0
- package/src/filesystem/fff.bun.ts +140 -0
- package/src/filesystem/fff.node.ts +138 -0
- package/src/filesystem/ignore.ts +67 -0
- package/src/filesystem/protected.ts +53 -0
- package/src/filesystem/search.ts +239 -0
- package/src/filesystem/watcher.ts +140 -0
- package/src/filesystem.ts +118 -0
- package/src/flag/flag.ts +78 -0
- package/src/fs-util.ts +274 -0
- package/src/git.ts +987 -0
- package/src/github-copilot/README.md +5 -0
- package/src/github-copilot/chat/convert-to-openai-compatible-chat-messages.ts +170 -0
- package/src/github-copilot/chat/get-response-metadata.ts +15 -0
- package/src/github-copilot/chat/map-openai-compatible-finish-reason.ts +19 -0
- package/src/github-copilot/chat/openai-compatible-api-types.ts +64 -0
- package/src/github-copilot/chat/openai-compatible-chat-language-model.ts +815 -0
- package/src/github-copilot/chat/openai-compatible-chat-options.ts +28 -0
- package/src/github-copilot/chat/openai-compatible-metadata-extractor.ts +44 -0
- package/src/github-copilot/chat/openai-compatible-prepare-tools.ts +83 -0
- package/src/github-copilot/copilot-provider.ts +100 -0
- package/src/github-copilot/openai-compatible-error.ts +27 -0
- package/src/github-copilot/responses/convert-to-openai-responses-input.ts +335 -0
- package/src/github-copilot/responses/map-openai-responses-finish-reason.ts +22 -0
- package/src/github-copilot/responses/openai-config.ts +18 -0
- package/src/github-copilot/responses/openai-error.ts +22 -0
- package/src/github-copilot/responses/openai-responses-api-types.ts +214 -0
- package/src/github-copilot/responses/openai-responses-language-model.ts +1770 -0
- package/src/github-copilot/responses/openai-responses-prepare-tools.ts +173 -0
- package/src/github-copilot/responses/openai-responses-settings.ts +1 -0
- package/src/github-copilot/responses/tool/code-interpreter.ts +87 -0
- package/src/github-copilot/responses/tool/file-search.ts +127 -0
- package/src/github-copilot/responses/tool/image-generation.ts +114 -0
- package/src/github-copilot/responses/tool/local-shell.ts +64 -0
- package/src/github-copilot/responses/tool/web-search-preview.ts +103 -0
- package/src/github-copilot/responses/tool/web-search.ts +102 -0
- package/src/global.ts +87 -0
- package/src/id/id.ts +47 -0
- package/src/image/photon.ts +94 -0
- package/src/image.ts +81 -0
- package/src/installation/version.ts +8 -0
- package/src/instruction-context.ts +101 -0
- package/src/integration/connection.ts +12 -0
- package/src/integration.ts +520 -0
- package/src/location-mutation.ts +162 -0
- package/src/location-service-map.ts +18 -0
- package/src/location-services.ts +115 -0
- package/src/location.ts +39 -0
- package/src/markdown.d.ts +4 -0
- package/src/model.ts +41 -0
- package/src/models-dev.ts +260 -0
- package/src/npm-config.ts +40 -0
- package/src/npm.ts +269 -0
- package/src/oauth/page.ts +276 -0
- package/src/observability/logging.ts +71 -0
- package/src/observability/otlp.ts +79 -0
- package/src/observability/shared.ts +1 -0
- package/src/observability.ts +24 -0
- package/src/patch.ts +197 -0
- package/src/permission/saved.ts +79 -0
- package/src/permission/sql.ts +20 -0
- package/src/permission.ts +310 -0
- package/src/plugin/agent.ts +206 -0
- package/src/plugin/command/initialize.txt +65 -0
- package/src/plugin/command/review.txt +100 -0
- package/src/plugin/command.ts +25 -0
- package/src/plugin/host.ts +219 -0
- package/src/plugin/internal.ts +153 -0
- package/src/plugin/layer-map.example.ts +94 -0
- package/src/plugin/models-dev.ts +183 -0
- package/src/plugin/promise.ts +93 -0
- package/src/plugin/provider/alibaba.ts +15 -0
- package/src/plugin/provider/amazon-bedrock.ts +126 -0
- package/src/plugin/provider/anthropic.ts +27 -0
- package/src/plugin/provider/azure.ts +82 -0
- package/src/plugin/provider/cerebras.ts +26 -0
- package/src/plugin/provider/cloudflare-ai-gateway.ts +81 -0
- package/src/plugin/provider/cloudflare-workers-ai.ts +81 -0
- package/src/plugin/provider/cohere.ts +15 -0
- package/src/plugin/provider/deepinfra.ts +15 -0
- package/src/plugin/provider/dynamic.ts +31 -0
- package/src/plugin/provider/gateway.ts +15 -0
- package/src/plugin/provider/github-copilot.ts +52 -0
- package/src/plugin/provider/gitlab.ts +65 -0
- package/src/plugin/provider/google-vertex.ts +173 -0
- package/src/plugin/provider/google.ts +15 -0
- package/src/plugin/provider/groq.ts +15 -0
- package/src/plugin/provider/kilo.ts +21 -0
- package/src/plugin/provider/llmgateway.ts +26 -0
- package/src/plugin/provider/mistral.ts +15 -0
- package/src/plugin/provider/nvidia.ts +22 -0
- package/src/plugin/provider/openai-compatible.ts +17 -0
- package/src/plugin/provider/openai.ts +292 -0
- package/src/plugin/provider/opencode.ts +311 -0
- package/src/plugin/provider/openrouter.ts +36 -0
- package/src/plugin/provider/perplexity.ts +15 -0
- package/src/plugin/provider/sap-ai-core.ts +46 -0
- package/src/plugin/provider/snowflake-cortex.ts +89 -0
- package/src/plugin/provider/togetherai.ts +15 -0
- package/src/plugin/provider/venice.ts +15 -0
- package/src/plugin/provider/vercel.ts +27 -0
- package/src/plugin/provider/xai.ts +22 -0
- package/src/plugin/provider/zenmux.ts +21 -0
- package/src/plugin/provider.ts +71 -0
- package/src/plugin/skill/customize-neurocode.md +452 -0
- package/src/plugin/skill.ts +31 -0
- package/src/plugin/variant.ts +39 -0
- package/src/plugin.ts +167 -0
- package/src/policy.ts +49 -0
- package/src/process.ts +261 -0
- package/src/project/copy-strategies.ts +35 -0
- package/src/project/copy.ts +292 -0
- package/src/project/directories.ts +158 -0
- package/src/project/schema.ts +16 -0
- package/src/project/sql.ts +35 -0
- package/src/project.ts +136 -0
- package/src/provider.ts +25 -0
- package/src/pty/protocol.ts +37 -0
- package/src/pty/pty.bun.ts +26 -0
- package/src/pty/pty.node.ts +29 -0
- package/src/pty/pty.ts +25 -0
- package/src/pty/schema.ts +1 -0
- package/src/pty/ticket.ts +56 -0
- package/src/pty.ts +318 -0
- package/src/public-event-manifest.ts +7 -0
- package/src/question.ts +153 -0
- package/src/reference/guidance.ts +69 -0
- package/src/reference.ts +125 -0
- package/src/repository-cache.ts +259 -0
- package/src/repository.ts +214 -0
- package/src/ripgrep/binary.ts +132 -0
- package/src/ripgrep.ts +281 -0
- package/src/schema.ts +79 -0
- package/src/session/compaction.ts +241 -0
- package/src/session/context-epoch.ts +174 -0
- package/src/session/error.ts +24 -0
- package/src/session/event.ts +2 -0
- package/src/session/execution/local.ts +46 -0
- package/src/session/execution.ts +34 -0
- package/src/session/history.ts +101 -0
- package/src/session/info.ts +50 -0
- package/src/session/input.ts +288 -0
- package/src/session/message-updater.ts +397 -0
- package/src/session/message.ts +2 -0
- package/src/session/projector.ts +458 -0
- package/src/session/prompt.ts +1 -0
- package/src/session/revert.ts +121 -0
- package/src/session/run-coordinator.ts +104 -0
- package/src/session/runner/index.ts +28 -0
- package/src/session/runner/llm.ts +432 -0
- package/src/session/runner/max-steps.ts +16 -0
- package/src/session/runner/model.ts +218 -0
- package/src/session/runner/publish-llm-event.ts +423 -0
- package/src/session/runner/to-llm-message.ts +171 -0
- package/src/session/schema.ts +9 -0
- package/src/session/sql.ts +176 -0
- package/src/session/store.ts +63 -0
- package/src/session/todo.ts +78 -0
- package/src/session.ts +486 -0
- package/src/share/sql.ts +13 -0
- package/src/shell.ts +226 -0
- package/src/skill/discovery.ts +213 -0
- package/src/skill/guidance.ts +76 -0
- package/src/skill.ts +132 -0
- package/src/snapshot.ts +266 -0
- package/src/state.ts +128 -0
- package/src/system-context/builtins.ts +50 -0
- package/src/system-context/index.ts +320 -0
- package/src/system-context/registry.ts +49 -0
- package/src/tool/AGENTS.md +59 -0
- package/src/tool/application-tools.ts +57 -0
- package/src/tool/apply-patch.ts +219 -0
- package/src/tool/bash.ts +207 -0
- package/src/tool/builtins.ts +48 -0
- package/src/tool/edit.ts +223 -0
- package/src/tool/glob.ts +105 -0
- package/src/tool/grep.ts +137 -0
- package/src/tool/http-body.ts +30 -0
- package/src/tool/question.ts +94 -0
- package/src/tool/read-filesystem.ts +366 -0
- package/src/tool/read.ts +117 -0
- package/src/tool/registry.ts +147 -0
- package/src/tool/skill.ts +109 -0
- package/src/tool/todowrite.ts +62 -0
- package/src/tool/tool.ts +162 -0
- package/src/tool/tools.ts +13 -0
- package/src/tool/webfetch.ts +218 -0
- package/src/tool/websearch.ts +260 -0
- package/src/tool/write.ts +101 -0
- package/src/tool-output-store.ts +211 -0
- package/src/util/array.ts +10 -0
- package/src/util/binary.ts +41 -0
- package/src/util/effect-flock.ts +284 -0
- package/src/util/encode.ts +51 -0
- package/src/util/error.ts +70 -0
- package/src/util/flock.ts +358 -0
- package/src/util/glob.ts +34 -0
- package/src/util/hash.ts +11 -0
- package/src/util/identifier.ts +1 -0
- package/src/util/iife.ts +3 -0
- package/src/util/lazy.ts +11 -0
- package/src/util/module.ts +10 -0
- package/src/util/path.ts +37 -0
- package/src/util/retry.ts +42 -0
- package/src/util/slug.ts +74 -0
- package/src/util/token.ts +5 -0
- package/src/util/which.ts +14 -0
- package/src/util/wildcard.ts +14 -0
- package/src/v1/config/agent.ts +89 -0
- package/src/v1/config/attachment.ts +25 -0
- package/src/v1/config/command.ts +13 -0
- package/src/v1/config/config.ts +192 -0
- package/src/v1/config/console-state.ts +16 -0
- package/src/v1/config/error.ts +39 -0
- package/src/v1/config/formatter.ts +13 -0
- package/src/v1/config/layout.ts +6 -0
- package/src/v1/config/lsp.ts +80 -0
- package/src/v1/config/mcp.ts +63 -0
- package/src/v1/config/migrate.ts +254 -0
- package/src/v1/config/permission.ts +50 -0
- package/src/v1/config/plugin.ts +9 -0
- package/src/v1/config/provider-options.ts +227 -0
- package/src/v1/config/provider.ts +121 -0
- package/src/v1/config/server.ts +19 -0
- package/src/v1/config/skills.ts +13 -0
- package/src/v1/permission.ts +33 -0
- package/src/v1/session.ts +68 -0
- package/src/v2-schema.ts +3 -0
- package/src/workspace.ts +6 -0
- package/sst-env.d.ts +10 -0
- package/test/agent.test.ts +131 -0
- package/test/application-tools.test.ts +287 -0
- package/test/background-job.test.ts +106 -0
- package/test/catalog.test.ts +353 -0
- package/test/command.test.ts +56 -0
- package/test/config/agent.test.ts +349 -0
- package/test/config/command.test.ts +83 -0
- package/test/config/config.test.ts +798 -0
- package/test/config/fixtures/plugin/directory-plugin.ts +13 -0
- package/test/config/plugin.test.ts +248 -0
- package/test/config/provider-options.test.ts +224 -0
- package/test/config/provider.test.ts +269 -0
- package/test/config/skill.test.ts +80 -0
- package/test/credential.test.ts +36 -0
- package/test/database-migration.test.ts +644 -0
- package/test/effect/cross-spawn-spawner.test.ts +426 -0
- package/test/effect/keyed-mutex.test.ts +73 -0
- package/test/effect/layer-node/layer-node-types.test.ts +143 -0
- package/test/effect/layer-node/layer-node.test.ts +261 -0
- package/test/effect/layer-node/node-build.test.ts +125 -0
- package/test/effect/observability.test.ts +109 -0
- package/test/event.test.ts +1124 -0
- package/test/file-mutation.test.ts +368 -0
- package/test/filesystem/filesystem.test.ts +387 -0
- package/test/filesystem/ignore.test.ts +10 -0
- package/test/filesystem/search.test.ts +44 -0
- package/test/filesystem/watcher.test.ts +266 -0
- package/test/fixture/effect-flock-worker.ts +60 -0
- package/test/fixture/flock-worker.ts +72 -0
- package/test/fixture/git.ts +49 -0
- package/test/fixture/location.ts +26 -0
- package/test/fixture/tmpdir.ts +25 -0
- package/test/fixtures/recordings/session-runner/openai-chat-streams-text.json +27 -0
- package/test/git.test.ts +164 -0
- package/test/github-copilot/convert-to-copilot-messages.test.ts +523 -0
- package/test/github-copilot/copilot-chat-model.test.ts +592 -0
- package/test/github-copilot/openai-responses-language-model.test.ts +206 -0
- package/test/global.test.ts +16 -0
- package/test/instruction-context.test.ts +323 -0
- package/test/integration.test.ts +349 -0
- package/test/legacy-event-schema.test.ts +16 -0
- package/test/lib/effect.ts +53 -0
- package/test/lib/tool.ts +20 -0
- package/test/location-filesystem.test.ts +69 -0
- package/test/location-layer.test.ts +226 -0
- package/test/location-mutation.test.ts +178 -0
- package/test/location.test.ts +42 -0
- package/test/model.test.ts +23 -0
- package/test/models.test.ts +290 -0
- package/test/move-session.test.ts +235 -0
- package/test/npm-config.test.ts +51 -0
- package/test/npm.test.ts +84 -0
- package/test/oauth-page.test.ts +15 -0
- package/test/patch.test.ts +68 -0
- package/test/permission.test.ts +315 -0
- package/test/plugin/command.test.ts +47 -0
- package/test/plugin/fixture.ts +52 -0
- package/test/plugin/fixtures/config-effect-plugin.ts +15 -0
- package/test/plugin/fixtures/config-promise-plugin.ts +13 -0
- package/test/plugin/fixtures/invalid-plugin.ts +1 -0
- package/test/plugin/fixtures/models-dev.json +14 -0
- package/test/plugin/fixtures/provider-factory.ts +9 -0
- package/test/plugin/host.ts +303 -0
- package/test/plugin/models-dev.test.ts +170 -0
- package/test/plugin/promise.test.ts +67 -0
- package/test/plugin/provider-alibaba.test.ts +92 -0
- package/test/plugin/provider-amazon-bedrock.test.ts +622 -0
- package/test/plugin/provider-anthropic.test.ts +94 -0
- package/test/plugin/provider-azure-cognitive-services.test.ts +199 -0
- package/test/plugin/provider-azure.test.ts +293 -0
- package/test/plugin/provider-cerebras.test.ts +136 -0
- package/test/plugin/provider-cloudflare-ai-gateway.test.ts +426 -0
- package/test/plugin/provider-cloudflare-workers-ai.test.ts +279 -0
- package/test/plugin/provider-cohere.test.ts +123 -0
- package/test/plugin/provider-deepinfra.test.ts +159 -0
- package/test/plugin/provider-dynamic.test.ts +184 -0
- package/test/plugin/provider-gateway.test.ts +115 -0
- package/test/plugin/provider-github-copilot.test.ts +278 -0
- package/test/plugin/provider-gitlab.test.ts +308 -0
- package/test/plugin/provider-google-vertex-anthropic.test.ts +264 -0
- package/test/plugin/provider-google-vertex.test.ts +387 -0
- package/test/plugin/provider-google.test.ts +80 -0
- package/test/plugin/provider-groq.test.ts +121 -0
- package/test/plugin/provider-kilo.test.ts +99 -0
- package/test/plugin/provider-llmgateway.test.ts +80 -0
- package/test/plugin/provider-mistral.test.ts +129 -0
- package/test/plugin/provider-nvidia.test.ts +97 -0
- package/test/plugin/provider-openai-compatible.test.ts +107 -0
- package/test/plugin/provider-openai.test.ts +176 -0
- package/test/plugin/provider-opencode.test.ts +423 -0
- package/test/plugin/provider-openrouter.test.ts +113 -0
- package/test/plugin/provider-perplexity.test.ts +122 -0
- package/test/plugin/provider-sap-ai-core.test.ts +159 -0
- package/test/plugin/provider-snowflake-cortex.test.ts +261 -0
- package/test/plugin/provider-togetherai.test.ts +129 -0
- package/test/plugin/provider-venice.test.ts +115 -0
- package/test/plugin/provider-vercel.test.ts +83 -0
- package/test/plugin/provider-xai.test.ts +125 -0
- package/test/plugin/provider-zenmux.test.ts +110 -0
- package/test/plugin/skill.test.ts +25 -0
- package/test/plugin/variant.test.ts +67 -0
- package/test/plugin.test.ts +71 -0
- package/test/policy.test.ts +85 -0
- package/test/preload.ts +5 -0
- package/test/process/process.test.ts +368 -0
- package/test/project-copy.test.ts +400 -0
- package/test/project-directories.test.ts +61 -0
- package/test/project.test.ts +221 -0
- package/test/provider-mistral.test.ts +282 -0
- package/test/provider-xai-responses.test.ts +32 -0
- package/test/pty/info-schema.test.ts +32 -0
- package/test/pty/protocol.test.ts +27 -0
- package/test/pty/pty-session.test.ts +240 -0
- package/test/pty/ticket.test.ts +62 -0
- package/test/question.test.ts +114 -0
- package/test/reference-guidance.test.ts +76 -0
- package/test/reference.test.ts +78 -0
- package/test/repository-cache.test.ts +153 -0
- package/test/repository.test.ts +71 -0
- package/test/ripgrep.test.ts +65 -0
- package/test/session-compaction.test.ts +27 -0
- package/test/session-create.test.ts +425 -0
- package/test/session-history.test.ts +165 -0
- package/test/session-projector.test.ts +533 -0
- package/test/session-prompt.test.ts +584 -0
- package/test/session-run-coordinator.test.ts +418 -0
- package/test/session-runner-message.test.ts +501 -0
- package/test/session-runner-model.test.ts +347 -0
- package/test/session-runner-recorded.test.ts +193 -0
- package/test/session-runner-tool-events.test.ts +136 -0
- package/test/session-runner-tool-registry.test.ts +452 -0
- package/test/session-runner.test.ts +3365 -0
- package/test/session-todo.test.ts +94 -0
- package/test/session-tool-progress.test.ts +158 -0
- package/test/shared-schema.test.ts +206 -0
- package/test/shell.test.ts +108 -0
- package/test/skill/guidance.test.ts +144 -0
- package/test/skill-discovery.test.ts +165 -0
- package/test/skill.test.ts +125 -0
- package/test/snapshot.test.ts +178 -0
- package/test/state.test.ts +115 -0
- package/test/system-context/builtins.test.ts +129 -0
- package/test/system-context/index.test.ts +307 -0
- package/test/system-context/registry.test.ts +114 -0
- package/test/tool-apply-patch.test.ts +436 -0
- package/test/tool-bash.test.ts +437 -0
- package/test/tool-edit.test.ts +434 -0
- package/test/tool-output-store.test.ts +247 -0
- package/test/tool-question.test.ts +162 -0
- package/test/tool-read-filesystem.test.ts +118 -0
- package/test/tool-read.test.ts +674 -0
- package/test/tool-skill.test.ts +149 -0
- package/test/tool-todowrite.test.ts +125 -0
- package/test/tool-webfetch.test.ts +281 -0
- package/test/tool-websearch.test.ts +316 -0
- package/test/tool-write.test.ts +305 -0
- package/test/util/effect-flock.test.ts +392 -0
- package/test/util/flock.test.ts +428 -0
- package/test/util/which.test.ts +100 -0
- package/tsconfig.json +7 -0
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
export * as SessionRunner from "./index"
|
|
2
|
+
|
|
3
|
+
import type { LLMError } from "@neurocode-ai/llm"
|
|
4
|
+
import { Context, Effect } from "effect"
|
|
5
|
+
import { SessionSchema } from "../schema"
|
|
6
|
+
import type { ContextSnapshotDecodeError, MessageDecodeError } from "../error"
|
|
7
|
+
import { SessionRunnerModel } from "./model"
|
|
8
|
+
import type { SystemContext } from "../../system-context/index"
|
|
9
|
+
import type { ToolOutputStore } from "../../tool-output-store"
|
|
10
|
+
|
|
11
|
+
export type RunError =
|
|
12
|
+
| LLMError
|
|
13
|
+
| SessionRunnerModel.Error
|
|
14
|
+
| MessageDecodeError
|
|
15
|
+
| ContextSnapshotDecodeError
|
|
16
|
+
| SystemContext.InitializationBlocked
|
|
17
|
+
| ToolOutputStore.Error
|
|
18
|
+
|
|
19
|
+
/** Runs one local continuation from already-recorded Session history. */
|
|
20
|
+
export interface Interface {
|
|
21
|
+
/** Drains eligible durable work. Explicit runs perform one provider attempt even when no work is eligible. */
|
|
22
|
+
readonly run: (input: {
|
|
23
|
+
readonly sessionID: SessionSchema.ID
|
|
24
|
+
readonly force: boolean
|
|
25
|
+
}) => Effect.Effect<void, RunError>
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export class Service extends Context.Service<Service, Interface>()("@neurocode/v2/SessionRunner") {}
|
|
@@ -0,0 +1,432 @@
|
|
|
1
|
+
import {
|
|
2
|
+
LLM,
|
|
3
|
+
LLMClient,
|
|
4
|
+
LLMError,
|
|
5
|
+
LLMEvent,
|
|
6
|
+
Message,
|
|
7
|
+
SystemPart,
|
|
8
|
+
isContextOverflowFailure,
|
|
9
|
+
type ProviderErrorEvent,
|
|
10
|
+
} from "@neurocode-ai/llm"
|
|
11
|
+
import { Cause, DateTime, Effect, FiberSet, Layer, Option, Semaphore, Stream } from "effect"
|
|
12
|
+
import { AgentV2 } from "../../agent"
|
|
13
|
+
import { Config } from "../../config"
|
|
14
|
+
import { Database } from "../../database/database"
|
|
15
|
+
import { EventV2 } from "../../event"
|
|
16
|
+
import { Location } from "../../location"
|
|
17
|
+
import { ModelV2 } from "../../model"
|
|
18
|
+
import { PermissionV2 } from "../../permission"
|
|
19
|
+
import { ProviderV2 } from "../../provider"
|
|
20
|
+
import { QuestionV2 } from "../../question"
|
|
21
|
+
import { SystemContext } from "../../system-context/index"
|
|
22
|
+
import { SystemContextRegistry } from "../../system-context/registry"
|
|
23
|
+
import { SkillGuidance } from "../../skill/guidance"
|
|
24
|
+
import { ReferenceGuidance } from "../../reference/guidance"
|
|
25
|
+
import { ToolRegistry } from "../../tool/registry"
|
|
26
|
+
import { ToolOutputStore } from "../../tool-output-store"
|
|
27
|
+
import { SessionContextEpoch } from "../context-epoch"
|
|
28
|
+
import { SessionCompaction } from "../compaction"
|
|
29
|
+
import { SessionEvent } from "../event"
|
|
30
|
+
import { SessionHistory } from "../history"
|
|
31
|
+
import { SessionInput } from "../input"
|
|
32
|
+
import { SessionSchema } from "../schema"
|
|
33
|
+
import { SessionStore } from "../store"
|
|
34
|
+
import { type RunError, Service } from "./index"
|
|
35
|
+
import { SessionRunnerModel } from "./model"
|
|
36
|
+
import { createLLMEventPublisher } from "./publish-llm-event"
|
|
37
|
+
import { toLLMMessages } from "./to-llm-message"
|
|
38
|
+
import { MAX_STEPS_PROMPT } from "./max-steps"
|
|
39
|
+
import { Snapshot } from "../../snapshot"
|
|
40
|
+
import { makeLocationNode } from "../../effect/app-node"
|
|
41
|
+
import { llmClient } from "../../effect/app-node-platform"
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* Runs one durable coding-agent Session until it settles.
|
|
45
|
+
*
|
|
46
|
+
* Keep this as orchestration over smaller collaborators rather than rebuilding the legacy
|
|
47
|
+
* `SessionPrompt` monolith. Implement the unchecked items in small reviewed slices:
|
|
48
|
+
*
|
|
49
|
+
* - Session ownership and controls
|
|
50
|
+
* - [x] Coordinate one local active drain per Session; explicit resumes join and prompt wakeups coalesce.
|
|
51
|
+
* - [ ] Replace local ownership with durable multi-node ownership when clustered.
|
|
52
|
+
* - [ ] Mark busy, retrying, idle, interrupted, or terminal-failure status durably.
|
|
53
|
+
* - [ ] Honor interruption and reject stale work after runtime attachment replacement.
|
|
54
|
+
* - [x] Honor optional agent step limits.
|
|
55
|
+
* - [ ] Bound provider retries and repeated identical tool calls.
|
|
56
|
+
*
|
|
57
|
+
* - Runtime context assembly
|
|
58
|
+
* - Track V1 runtime-context parity canonically in `specs/v2/session.md`.
|
|
59
|
+
*
|
|
60
|
+
* - One provider turn
|
|
61
|
+
* - [x] Translate every projected V2 Session message variant into canonical
|
|
62
|
+
* `@neurocode-ai/llm` messages.
|
|
63
|
+
* - [ ] Resolve policy-filtered built-in, MCP, plugin, and structured-output tool definitions.
|
|
64
|
+
* - [x] Stream exactly one `llm.stream(request)` provider turn.
|
|
65
|
+
* - [x] Persist assistant text and usage events incrementally as they arrive.
|
|
66
|
+
* - [ ] Persist snapshots, patches, and retry notices incrementally as they arrive.
|
|
67
|
+
* - [x] Persist reasoning, provider errors, and tool-call events incrementally as they arrive.
|
|
68
|
+
*
|
|
69
|
+
* - Tool settlement and continuation
|
|
70
|
+
* - [x] Durably record each tool call before side effects begin.
|
|
71
|
+
* - [x] Authorize and execute recorded local calls through a core-owned registry hook.
|
|
72
|
+
* - [x] Persist typed success, failure, and provider-executed tool outcomes.
|
|
73
|
+
* - [x] Start each recorded local call eagerly and await all settlements before continuation.
|
|
74
|
+
* - [ ] Add scoped runtime context, progress updates, attachment normalization,
|
|
75
|
+
* plugins, and cancellation settlement.
|
|
76
|
+
* - [x] Reload projected history and start the next explicit provider turn after local tool results.
|
|
77
|
+
* - [x] Continue for durable user steering accepted during an active provider turn.
|
|
78
|
+
* - [ ] Continue for compaction or another continuation condition when required.
|
|
79
|
+
*
|
|
80
|
+
* - Post-run maintenance
|
|
81
|
+
* - [ ] Settle final status and expose durable output events to replayable consumers.
|
|
82
|
+
* - [ ] Coalesce streamed deltas and add covering projected-history indexes.
|
|
83
|
+
* - [ ] Update title, summaries, compaction state, and cleanup in bounded background work.
|
|
84
|
+
*
|
|
85
|
+
* Use `llm.stream(request)` for each provider turn. Keep tool execution and continuation here.
|
|
86
|
+
* Durable continuation recovery remains a separate future slice with an explicit retry policy.
|
|
87
|
+
*
|
|
88
|
+
* The current slice loads V2 history, translates it, resolves a model through a core service, and persists one
|
|
89
|
+
* provider turn. Registry definitions are advertised, local tool calls are settled durably, and an
|
|
90
|
+
* explicit loop starts the next provider turn after local settlement. Configured agent step limits bound the loop.
|
|
91
|
+
*/
|
|
92
|
+
|
|
93
|
+
const layer = Layer.effect(
|
|
94
|
+
Service,
|
|
95
|
+
Effect.gen(function* () {
|
|
96
|
+
const events = yield* EventV2.Service
|
|
97
|
+
const llm = yield* LLMClient.Service
|
|
98
|
+
const agents = yield* AgentV2.Service
|
|
99
|
+
const tools = yield* ToolRegistry.Service
|
|
100
|
+
const models = yield* SessionRunnerModel.Service
|
|
101
|
+
const store = yield* SessionStore.Service
|
|
102
|
+
const location = yield* Location.Service
|
|
103
|
+
const systemContext = yield* SystemContextRegistry.Service
|
|
104
|
+
const skillGuidance = yield* SkillGuidance.Service
|
|
105
|
+
const referenceGuidance = yield* ReferenceGuidance.Service
|
|
106
|
+
const config = yield* Config.Service
|
|
107
|
+
const snapshots = yield* Snapshot.Service
|
|
108
|
+
const db = (yield* Database.Service).db
|
|
109
|
+
const compaction = SessionCompaction.make({ events, llm, config: yield* config.entries() })
|
|
110
|
+
const getSession = Effect.fn("SessionRunner.getSession")(function* (sessionID: SessionSchema.ID) {
|
|
111
|
+
const session = yield* store.get(sessionID)
|
|
112
|
+
if (!session) return yield* Effect.die(`Session not found: ${sessionID}`)
|
|
113
|
+
return session
|
|
114
|
+
})
|
|
115
|
+
|
|
116
|
+
const getContext = Effect.fn("SessionRunner.getContext")(function* (sessionID: SessionSchema.ID) {
|
|
117
|
+
return yield* store.context(sessionID)
|
|
118
|
+
})
|
|
119
|
+
const failInterruptedTools = Effect.fn("SessionRunner.failInterruptedTools")(function* (
|
|
120
|
+
sessionID: SessionSchema.ID,
|
|
121
|
+
) {
|
|
122
|
+
for (const message of yield* getContext(sessionID)) {
|
|
123
|
+
if (message.type !== "assistant") continue
|
|
124
|
+
for (const tool of message.content) {
|
|
125
|
+
if (tool.type !== "tool" || (tool.state.status !== "pending" && tool.state.status !== "running")) continue
|
|
126
|
+
yield* events.publish(SessionEvent.Tool.Failed, {
|
|
127
|
+
sessionID,
|
|
128
|
+
timestamp: yield* DateTime.now,
|
|
129
|
+
assistantMessageID: message.id,
|
|
130
|
+
callID: tool.id,
|
|
131
|
+
error: { type: "unknown", message: "Tool execution interrupted" },
|
|
132
|
+
provider: {
|
|
133
|
+
executed: tool.provider?.executed === true,
|
|
134
|
+
...(tool.provider?.metadata === undefined ? {} : { metadata: tool.provider.metadata }),
|
|
135
|
+
},
|
|
136
|
+
})
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
})
|
|
140
|
+
|
|
141
|
+
const awaitToolFibers = (fibers: FiberSet.FiberSet<void, ToolOutputStore.Error>) =>
|
|
142
|
+
Effect.raceFirst(FiberSet.join(fibers), FiberSet.awaitEmpty(fibers))
|
|
143
|
+
|
|
144
|
+
// Match V1: declining a user prompt halts the loop instead of becoming model-facing tool output.
|
|
145
|
+
const isUserDeclined = (cause: Cause.Cause<unknown>) =>
|
|
146
|
+
cause.reasons.some(
|
|
147
|
+
(reason) =>
|
|
148
|
+
Cause.isDieReason(reason) &&
|
|
149
|
+
(reason.defect instanceof PermissionV2.DeclinedError || reason.defect instanceof QuestionV2.RejectedError),
|
|
150
|
+
)
|
|
151
|
+
|
|
152
|
+
type TurnTransition =
|
|
153
|
+
// Automatic compaction completed; rebuild the request from compacted history.
|
|
154
|
+
| { readonly _tag: "ContinueAfterCompaction"; readonly step: number }
|
|
155
|
+
// Overflow compaction completed; rebuild once through the path without overflow recovery.
|
|
156
|
+
| { readonly _tag: "ContinueAfterOverflowCompaction"; readonly step: number }
|
|
157
|
+
|
|
158
|
+
class TurnTransitionError extends Error {
|
|
159
|
+
constructor(readonly transition: TurnTransition) {
|
|
160
|
+
super()
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
const continueAfterCompaction = (step: number) => new TurnTransitionError({ _tag: "ContinueAfterCompaction", step })
|
|
165
|
+
const continueAfterOverflowCompaction = (step: number) =>
|
|
166
|
+
new TurnTransitionError({ _tag: "ContinueAfterOverflowCompaction", step })
|
|
167
|
+
|
|
168
|
+
const loadSystemContext = (agent: AgentV2.Selection) =>
|
|
169
|
+
Effect.all([systemContext.load(), skillGuidance.load(agent), referenceGuidance.load()], {
|
|
170
|
+
concurrency: "unbounded",
|
|
171
|
+
}).pipe(Effect.map(SystemContext.combine))
|
|
172
|
+
|
|
173
|
+
const runTurnAttempt = Effect.fn("SessionRunner.runTurn")(function* (
|
|
174
|
+
sessionID: SessionSchema.ID,
|
|
175
|
+
promotion: SessionInput.Delivery | undefined,
|
|
176
|
+
step: number,
|
|
177
|
+
recoverOverflow?: typeof compaction.compactAfterOverflow,
|
|
178
|
+
) {
|
|
179
|
+
const session = yield* getSession(sessionID)
|
|
180
|
+
if (session.location.directory !== location.directory || session.location.workspaceID !== location.workspaceID)
|
|
181
|
+
return yield* Effect.interrupt
|
|
182
|
+
const agent = yield* agents.select(session.agent)
|
|
183
|
+
const initialized = yield* SessionContextEpoch.initialize(db, loadSystemContext(agent), session.id)
|
|
184
|
+
const toolFibers = yield* FiberSet.make<void, ToolOutputStore.Error>()
|
|
185
|
+
let needsContinuation = false
|
|
186
|
+
let currentStep = step
|
|
187
|
+
if (promotion) {
|
|
188
|
+
const cutoff = yield* EventV2.latestSequence(db, session.id)
|
|
189
|
+
let promoted = 0
|
|
190
|
+
if (promotion === "steer") promoted = yield* SessionInput.promoteSteers(db, events, session.id, cutoff)
|
|
191
|
+
if (promotion === "queue") {
|
|
192
|
+
promoted += Number(yield* SessionInput.promoteNextQueued(db, events, session.id))
|
|
193
|
+
promoted += yield* SessionInput.promoteSteers(db, events, session.id, cutoff)
|
|
194
|
+
}
|
|
195
|
+
if (promoted > 0) currentStep = 1
|
|
196
|
+
}
|
|
197
|
+
const system =
|
|
198
|
+
initialized ?? (yield* SessionContextEpoch.prepare(db, events, loadSystemContext(agent), session.id))
|
|
199
|
+
const model = yield* models.resolve(session)
|
|
200
|
+
const entries = yield* SessionHistory.entriesForRunner(db, session.id, system.baselineSeq)
|
|
201
|
+
const context = entries.map((entry) => entry.message)
|
|
202
|
+
const isLastStep = agent.info?.steps !== undefined && currentStep >= agent.info.steps
|
|
203
|
+
const toolMaterialization = isLastStep ? undefined : yield* tools.materialize(agent.info?.permissions)
|
|
204
|
+
const promptCacheKey = /^ses_[0-9a-f]{64}$/.test(session.id) ? session.id.slice(4) : session.id
|
|
205
|
+
const request = LLM.request({
|
|
206
|
+
model,
|
|
207
|
+
providerOptions: { openai: { promptCacheKey } },
|
|
208
|
+
system: [agent.info?.system, system.baseline]
|
|
209
|
+
.filter((part): part is string => part !== undefined && part.length > 0)
|
|
210
|
+
.map(SystemPart.make),
|
|
211
|
+
messages: [...toLLMMessages(context, model), ...(isLastStep ? [Message.assistant(MAX_STEPS_PROMPT)] : [])],
|
|
212
|
+
tools: toolMaterialization?.definitions ?? [],
|
|
213
|
+
toolChoice: isLastStep ? "none" : undefined,
|
|
214
|
+
})
|
|
215
|
+
if (yield* compaction.compactIfNeeded({ sessionID: session.id, entries, model, request }))
|
|
216
|
+
return yield* Effect.die(continueAfterCompaction(currentStep))
|
|
217
|
+
const startSnapshot = yield* snapshots.capture()
|
|
218
|
+
const publisher = createLLMEventPublisher(events, {
|
|
219
|
+
sessionID: session.id,
|
|
220
|
+
agent: agent.id,
|
|
221
|
+
model: {
|
|
222
|
+
id: ModelV2.ID.make(model.id),
|
|
223
|
+
providerID: ProviderV2.ID.make(model.provider),
|
|
224
|
+
...(session.model?.variant === undefined ? {} : { variant: session.model.variant }),
|
|
225
|
+
},
|
|
226
|
+
snapshot: startSnapshot,
|
|
227
|
+
})
|
|
228
|
+
const withPublication = Semaphore.makeUnsafe(1).withPermit
|
|
229
|
+
const publish = (event: LLMEvent, outputPaths: ReadonlyArray<string> = []) =>
|
|
230
|
+
withPublication(publisher.publish(event, outputPaths))
|
|
231
|
+
let overflowFailure: ProviderErrorEvent | undefined
|
|
232
|
+
const providerStream = llm.stream(request).pipe(
|
|
233
|
+
Stream.runForEach((event) =>
|
|
234
|
+
Effect.gen(function* () {
|
|
235
|
+
if (overflowFailure || publisher.hasProviderError()) return
|
|
236
|
+
if (LLMEvent.is.providerError(event)) {
|
|
237
|
+
if (isContextOverflowFailure(event) && !publisher.hasAssistantStarted()) {
|
|
238
|
+
overflowFailure = event
|
|
239
|
+
return
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
yield* publish(event)
|
|
243
|
+
if (event.type !== "tool-call" || event.providerExecuted) return
|
|
244
|
+
if (!toolMaterialization) {
|
|
245
|
+
yield* withPublication(publisher.failUnsettledTools("Tools are disabled after the maximum agent steps"))
|
|
246
|
+
return
|
|
247
|
+
}
|
|
248
|
+
needsContinuation = true
|
|
249
|
+
const assistantMessageID = yield* publisher.assistantMessageID(event.id)
|
|
250
|
+
yield* Effect.uninterruptibleMask((restore) =>
|
|
251
|
+
restore(
|
|
252
|
+
toolMaterialization.settle({
|
|
253
|
+
sessionID: session.id,
|
|
254
|
+
agent: agent.id,
|
|
255
|
+
assistantMessageID,
|
|
256
|
+
call: event,
|
|
257
|
+
}),
|
|
258
|
+
).pipe(
|
|
259
|
+
Effect.flatMap((settlement) =>
|
|
260
|
+
publish(
|
|
261
|
+
LLMEvent.toolResult({
|
|
262
|
+
id: event.id,
|
|
263
|
+
name: event.name,
|
|
264
|
+
result: settlement.result,
|
|
265
|
+
output: settlement.output,
|
|
266
|
+
}),
|
|
267
|
+
settlement.outputPaths ?? [],
|
|
268
|
+
),
|
|
269
|
+
),
|
|
270
|
+
),
|
|
271
|
+
).pipe(FiberSet.run(toolFibers))
|
|
272
|
+
}),
|
|
273
|
+
),
|
|
274
|
+
Effect.ensuring(withPublication(publisher.flush())),
|
|
275
|
+
)
|
|
276
|
+
|
|
277
|
+
return yield* Effect.uninterruptibleMask((restore) =>
|
|
278
|
+
Effect.gen(function* () {
|
|
279
|
+
const stream = yield* restore(providerStream).pipe(Effect.exit)
|
|
280
|
+
const failure =
|
|
281
|
+
stream._tag === "Failure" ? Option.getOrUndefined(Cause.findErrorOption(stream.cause)) : undefined
|
|
282
|
+
if (
|
|
283
|
+
recoverOverflow &&
|
|
284
|
+
!publisher.hasAssistantStarted() &&
|
|
285
|
+
isContextOverflowFailure(overflowFailure ?? failure) &&
|
|
286
|
+
(yield* restore(recoverOverflow({ sessionID: session.id, entries, model, request })))
|
|
287
|
+
)
|
|
288
|
+
return yield* Effect.die(continueAfterOverflowCompaction(currentStep))
|
|
289
|
+
if (overflowFailure) yield* publish(overflowFailure)
|
|
290
|
+
const llmFailure = failure instanceof LLMError ? failure : undefined
|
|
291
|
+
if (llmFailure && !publisher.hasProviderError()) {
|
|
292
|
+
yield* withPublication(publisher.failUnsettledTools("Provider did not return a tool result", true))
|
|
293
|
+
yield* withPublication(publisher.failAssistant(llmFailure.reason.message))
|
|
294
|
+
}
|
|
295
|
+
if (stream._tag === "Failure" && Cause.hasInterrupts(stream.cause)) yield* FiberSet.clear(toolFibers)
|
|
296
|
+
const settled = yield* restore(awaitToolFibers(toolFibers)).pipe(Effect.exit)
|
|
297
|
+
if (settled._tag === "Failure" && isUserDeclined(settled.cause)) {
|
|
298
|
+
yield* FiberSet.clear(toolFibers)
|
|
299
|
+
yield* withPublication(publisher.failUnsettledTools("Tool execution interrupted"))
|
|
300
|
+
return yield* Effect.interrupt
|
|
301
|
+
}
|
|
302
|
+
if (
|
|
303
|
+
(stream._tag === "Failure" && Cause.hasInterrupts(stream.cause)) ||
|
|
304
|
+
(settled._tag === "Failure" && Cause.hasInterrupts(settled.cause))
|
|
305
|
+
) {
|
|
306
|
+
yield* FiberSet.clear(toolFibers)
|
|
307
|
+
yield* withPublication(publisher.failUnsettledTools("Tool execution interrupted"))
|
|
308
|
+
if (publisher.hasActiveAssistant())
|
|
309
|
+
yield* withPublication(publisher.failAssistant("Provider turn interrupted"))
|
|
310
|
+
}
|
|
311
|
+
if (settled._tag === "Failure" && !Cause.hasInterrupts(settled.cause)) {
|
|
312
|
+
const failure = Cause.squash(settled.cause)
|
|
313
|
+
const message = failure instanceof Error ? failure.message : String(failure)
|
|
314
|
+
yield* withPublication(publisher.failUnsettledTools(`Tool execution failed: ${message}`))
|
|
315
|
+
}
|
|
316
|
+
const stepSettlement = publisher.stepSettlement()
|
|
317
|
+
if (stepSettlement && !publisher.hasProviderError()) {
|
|
318
|
+
const endSnapshot = yield* snapshots.capture()
|
|
319
|
+
const files =
|
|
320
|
+
startSnapshot && endSnapshot
|
|
321
|
+
? yield* snapshots
|
|
322
|
+
.files({ from: startSnapshot, to: endSnapshot })
|
|
323
|
+
.pipe(Effect.catch(() => Effect.succeed(undefined)))
|
|
324
|
+
: undefined
|
|
325
|
+
yield* withPublication(
|
|
326
|
+
events.publish(SessionEvent.Step.Ended, {
|
|
327
|
+
sessionID: session.id,
|
|
328
|
+
timestamp: yield* DateTime.now,
|
|
329
|
+
assistantMessageID: yield* publisher.startAssistant(),
|
|
330
|
+
finish: stepSettlement.finish,
|
|
331
|
+
cost: 0,
|
|
332
|
+
tokens: stepSettlement.tokens,
|
|
333
|
+
snapshot: endSnapshot,
|
|
334
|
+
files,
|
|
335
|
+
}),
|
|
336
|
+
)
|
|
337
|
+
}
|
|
338
|
+
if (publisher.hasProviderError())
|
|
339
|
+
yield* withPublication(publisher.failUnsettledTools("Tool execution interrupted"))
|
|
340
|
+
if (stream._tag === "Success" && !publisher.hasProviderError())
|
|
341
|
+
yield* withPublication(publisher.failUnsettledTools("Provider did not return a tool result", true))
|
|
342
|
+
if (stream._tag === "Failure") return yield* Effect.failCause(stream.cause)
|
|
343
|
+
if (settled._tag === "Failure" && Cause.hasInterrupts(settled.cause))
|
|
344
|
+
return yield* Effect.failCause(settled.cause)
|
|
345
|
+
return { needsContinuation: !publisher.hasProviderError() && needsContinuation, step: currentStep }
|
|
346
|
+
}),
|
|
347
|
+
)
|
|
348
|
+
}, Effect.scoped)
|
|
349
|
+
type RunTurn = (
|
|
350
|
+
sessionID: SessionSchema.ID,
|
|
351
|
+
promotion: SessionInput.Delivery | undefined,
|
|
352
|
+
step: number,
|
|
353
|
+
) => Effect.Effect<{ readonly needsContinuation: boolean; readonly step: number }, RunError>
|
|
354
|
+
|
|
355
|
+
const runAfterOverflowCompaction: RunTurn = Effect.fnUntraced(function* (sessionID, promotion, step) {
|
|
356
|
+
return yield* runTurnAttempt(sessionID, promotion, step).pipe(
|
|
357
|
+
Effect.catchDefect(
|
|
358
|
+
Effect.fnUntraced(function* (defect) {
|
|
359
|
+
if (!(defect instanceof TurnTransitionError)) return yield* Effect.die(defect)
|
|
360
|
+
if (defect.transition._tag === "ContinueAfterOverflowCompaction")
|
|
361
|
+
return yield* Effect.die("Post-compaction provider attempt cannot recover another overflow")
|
|
362
|
+
yield* Effect.yieldNow
|
|
363
|
+
return yield* runAfterOverflowCompaction(sessionID, undefined, defect.transition.step)
|
|
364
|
+
}),
|
|
365
|
+
),
|
|
366
|
+
)
|
|
367
|
+
})
|
|
368
|
+
|
|
369
|
+
const runTurn: RunTurn = Effect.fnUntraced(function* (sessionID, promotion, step) {
|
|
370
|
+
return yield* runTurnAttempt(sessionID, promotion, step, compaction.compactAfterOverflow).pipe(
|
|
371
|
+
Effect.catchDefect(
|
|
372
|
+
Effect.fnUntraced(function* (defect) {
|
|
373
|
+
if (!(defect instanceof TurnTransitionError)) return yield* Effect.die(defect)
|
|
374
|
+
yield* Effect.yieldNow
|
|
375
|
+
if (defect.transition._tag === "ContinueAfterOverflowCompaction")
|
|
376
|
+
return yield* runAfterOverflowCompaction(sessionID, undefined, defect.transition.step)
|
|
377
|
+
return yield* runTurn(sessionID, undefined, defect.transition.step)
|
|
378
|
+
}),
|
|
379
|
+
),
|
|
380
|
+
)
|
|
381
|
+
})
|
|
382
|
+
|
|
383
|
+
const run = Effect.fn("SessionRunner.run")(function* (input: {
|
|
384
|
+
readonly sessionID: SessionSchema.ID
|
|
385
|
+
readonly force: boolean
|
|
386
|
+
}) {
|
|
387
|
+
const hasSteer = yield* SessionInput.hasPending(db, input.sessionID, "steer")
|
|
388
|
+
const hasQueue = hasSteer ? false : yield* SessionInput.hasPending(db, input.sessionID, "queue")
|
|
389
|
+
if (!input.force && !hasSteer && !hasQueue) return
|
|
390
|
+
yield* failInterruptedTools(input.sessionID)
|
|
391
|
+
let promotion: SessionInput.Delivery | undefined = hasSteer ? "steer" : hasQueue ? "queue" : undefined
|
|
392
|
+
let shouldRun = input.force || hasSteer || hasQueue
|
|
393
|
+
while (shouldRun) {
|
|
394
|
+
let needsContinuation = true
|
|
395
|
+
let step = 1
|
|
396
|
+
while (needsContinuation) {
|
|
397
|
+
const result = yield* runTurn(input.sessionID, promotion, step)
|
|
398
|
+
needsContinuation = result.needsContinuation
|
|
399
|
+
step = result.step + 1
|
|
400
|
+
promotion = "steer"
|
|
401
|
+
if (!needsContinuation) needsContinuation = yield* SessionInput.hasPending(db, input.sessionID, "steer")
|
|
402
|
+
}
|
|
403
|
+
shouldRun = yield* SessionInput.hasPending(db, input.sessionID, "queue")
|
|
404
|
+
promotion = shouldRun ? "queue" : undefined
|
|
405
|
+
}
|
|
406
|
+
})
|
|
407
|
+
|
|
408
|
+
return Service.of({
|
|
409
|
+
run,
|
|
410
|
+
})
|
|
411
|
+
}),
|
|
412
|
+
)
|
|
413
|
+
|
|
414
|
+
export const node = makeLocationNode({
|
|
415
|
+
service: Service,
|
|
416
|
+
layer,
|
|
417
|
+
deps: [
|
|
418
|
+
EventV2.node,
|
|
419
|
+
llmClient,
|
|
420
|
+
AgentV2.node,
|
|
421
|
+
ToolRegistry.node,
|
|
422
|
+
SessionRunnerModel.node,
|
|
423
|
+
SessionStore.node,
|
|
424
|
+
Location.node,
|
|
425
|
+
SystemContextRegistry.node,
|
|
426
|
+
SkillGuidance.node,
|
|
427
|
+
ReferenceGuidance.node,
|
|
428
|
+
Config.node,
|
|
429
|
+
Snapshot.node,
|
|
430
|
+
Database.node,
|
|
431
|
+
],
|
|
432
|
+
})
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
export const MAX_STEPS_PROMPT = `CRITICAL - MAXIMUM STEPS REACHED
|
|
2
|
+
|
|
3
|
+
The maximum number of steps allowed for this task has been reached. Tools are disabled until next user input. Respond with text only.
|
|
4
|
+
|
|
5
|
+
STRICT REQUIREMENTS:
|
|
6
|
+
1. Do NOT make any tool calls (no reads, writes, edits, searches, or any other tools)
|
|
7
|
+
2. MUST provide a text response summarizing work done so far
|
|
8
|
+
3. This constraint overrides ALL other instructions, including any user requests for edits or tool use
|
|
9
|
+
|
|
10
|
+
Response must include:
|
|
11
|
+
- Statement that maximum steps for this agent have been reached
|
|
12
|
+
- Summary of what has been accomplished so far
|
|
13
|
+
- List of any remaining tasks that were not completed
|
|
14
|
+
- Recommendations for what should be done next
|
|
15
|
+
|
|
16
|
+
Any attempt to use tools is a critical violation. Respond with text ONLY.`
|