@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,22 @@
|
|
|
1
|
+
export * as ConfigReference from "./reference"
|
|
2
|
+
|
|
3
|
+
import { Schema } from "effect"
|
|
4
|
+
|
|
5
|
+
export class Git extends Schema.Class<Git>("ConfigV2.Reference.Git")({
|
|
6
|
+
repository: Schema.String,
|
|
7
|
+
branch: Schema.String.pipe(Schema.optional),
|
|
8
|
+
description: Schema.String.pipe(Schema.optional),
|
|
9
|
+
hidden: Schema.Boolean.pipe(Schema.optional),
|
|
10
|
+
}) {}
|
|
11
|
+
|
|
12
|
+
export class Local extends Schema.Class<Local>("ConfigV2.Reference.Local")({
|
|
13
|
+
path: Schema.String,
|
|
14
|
+
description: Schema.String.pipe(Schema.optional),
|
|
15
|
+
hidden: Schema.Boolean.pipe(Schema.optional),
|
|
16
|
+
}) {}
|
|
17
|
+
|
|
18
|
+
export const Entry = Schema.Union([Schema.String, Git, Local])
|
|
19
|
+
export type Entry = typeof Entry.Type
|
|
20
|
+
|
|
21
|
+
export const Info = Schema.Record(Schema.String, Entry)
|
|
22
|
+
export type Info = typeof Info.Type
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export * as ConfigToolOutput from "./tool-output"
|
|
2
|
+
|
|
3
|
+
import { Schema } from "effect"
|
|
4
|
+
import { PositiveInt } from "../schema"
|
|
5
|
+
|
|
6
|
+
export class Info extends Schema.Class<Info>("ConfigV2.ToolOutput")({
|
|
7
|
+
max_lines: PositiveInt.pipe(Schema.optional),
|
|
8
|
+
max_bytes: PositiveInt.pipe(Schema.optional),
|
|
9
|
+
}) {}
|
package/src/config.ts
ADDED
|
@@ -0,0 +1,227 @@
|
|
|
1
|
+
export * as Config from "./config"
|
|
2
|
+
|
|
3
|
+
import { makeLocationNode } from "./effect/app-node"
|
|
4
|
+
import path from "path"
|
|
5
|
+
import { type ParseError, parse } from "jsonc-parser"
|
|
6
|
+
import { Context, Effect, Layer, Option, Schema } from "effect"
|
|
7
|
+
import { Permission } from "@neurocode-ai/schema/permission"
|
|
8
|
+
import { FSUtil } from "./fs-util"
|
|
9
|
+
import { Global } from "./global"
|
|
10
|
+
import { Location } from "./location"
|
|
11
|
+
import { Policy } from "./policy"
|
|
12
|
+
import { AbsolutePath } from "./schema"
|
|
13
|
+
import { ConfigAgent } from "./config/agent"
|
|
14
|
+
import { ConfigAttachments } from "./config/attachments"
|
|
15
|
+
import { ConfigCompaction } from "./config/compaction"
|
|
16
|
+
import { ConfigCommand } from "./config/command"
|
|
17
|
+
import { ConfigExperimental } from "./config/experimental"
|
|
18
|
+
import { ConfigFormatter } from "./config/formatter"
|
|
19
|
+
import { ConfigLSP } from "./config/lsp"
|
|
20
|
+
import { ConfigMCP } from "./config/mcp"
|
|
21
|
+
import { ConfigPlugin } from "./config/plugin"
|
|
22
|
+
import { ConfigProvider } from "./config/provider"
|
|
23
|
+
import { ConfigReference } from "./config/reference"
|
|
24
|
+
import { ConfigToolOutput } from "./config/tool-output"
|
|
25
|
+
import { ConfigWatcher } from "./config/watcher"
|
|
26
|
+
import { ConfigV1 } from "./v1/config/config"
|
|
27
|
+
import { ConfigMigrateV1 } from "./v1/config/migrate"
|
|
28
|
+
|
|
29
|
+
export class Info extends Schema.Class<Info>("Config.Info")({
|
|
30
|
+
$schema: Schema.optional(Schema.String).annotate({
|
|
31
|
+
description: "JSON schema reference for configuration validation",
|
|
32
|
+
}),
|
|
33
|
+
shell: Schema.String.pipe(Schema.optional).annotate({
|
|
34
|
+
description: "Default shell to use for terminal and shell tool execution",
|
|
35
|
+
}),
|
|
36
|
+
model: Schema.String.pipe(Schema.optional).annotate({
|
|
37
|
+
description: "Default model to use when no session or agent model is selected",
|
|
38
|
+
}),
|
|
39
|
+
default_agent: Schema.String.pipe(Schema.optional).annotate({
|
|
40
|
+
description: "Default primary agent to use when no session agent is selected",
|
|
41
|
+
}),
|
|
42
|
+
autoupdate: Schema.Union([Schema.Boolean, Schema.Literal("notify")])
|
|
43
|
+
.pipe(Schema.optional)
|
|
44
|
+
.annotate({
|
|
45
|
+
description: "Automatically update or notify when a new version is available",
|
|
46
|
+
}),
|
|
47
|
+
share: Schema.Literals(["manual", "auto", "disabled"]).pipe(Schema.optional).annotate({
|
|
48
|
+
description: "Control whether sessions may be shared manually, automatically, or not at all",
|
|
49
|
+
}),
|
|
50
|
+
enterprise: Schema.Struct({
|
|
51
|
+
url: Schema.String.pipe(Schema.optional),
|
|
52
|
+
})
|
|
53
|
+
.pipe(Schema.optional)
|
|
54
|
+
.annotate({
|
|
55
|
+
description: "Enterprise sharing service configuration",
|
|
56
|
+
}),
|
|
57
|
+
username: Schema.String.pipe(Schema.optional).annotate({
|
|
58
|
+
description: "Username displayed in conversations and used for telemetry identity",
|
|
59
|
+
}),
|
|
60
|
+
permissions: Permission.Ruleset.pipe(Schema.optional).annotate({
|
|
61
|
+
description: "Ordered tool permission rules applied to agent tool use",
|
|
62
|
+
}),
|
|
63
|
+
agents: Schema.Record(Schema.String, ConfigAgent.Info).pipe(Schema.optional).annotate({
|
|
64
|
+
description: "Named built-in agent overrides and custom agent definitions",
|
|
65
|
+
}),
|
|
66
|
+
snapshots: Schema.Boolean.pipe(Schema.optional).annotate({
|
|
67
|
+
description: "Enable snapshots used for undo and revert behavior",
|
|
68
|
+
}),
|
|
69
|
+
watcher: ConfigWatcher.Info.pipe(Schema.optional).annotate({
|
|
70
|
+
description: "Filesystem watcher configuration",
|
|
71
|
+
}),
|
|
72
|
+
formatter: ConfigFormatter.Info.pipe(Schema.optional).annotate({
|
|
73
|
+
description: "Enable built-in formatters or configure formatter overrides",
|
|
74
|
+
}),
|
|
75
|
+
lsp: ConfigLSP.Info.pipe(Schema.optional).annotate({
|
|
76
|
+
description: "Enable built-in language servers or configure server overrides",
|
|
77
|
+
}),
|
|
78
|
+
attachments: ConfigAttachments.Info.pipe(Schema.optional).annotate({
|
|
79
|
+
description: "Attachment processing configuration",
|
|
80
|
+
}),
|
|
81
|
+
tool_output: ConfigToolOutput.Info.pipe(Schema.optional).annotate({
|
|
82
|
+
description: "Tool output truncation thresholds",
|
|
83
|
+
}),
|
|
84
|
+
mcp: ConfigMCP.Info.pipe(Schema.optional).annotate({
|
|
85
|
+
description: "MCP server configuration",
|
|
86
|
+
}),
|
|
87
|
+
compaction: ConfigCompaction.Info.pipe(Schema.optional).annotate({
|
|
88
|
+
description: "Conversation compaction behavior",
|
|
89
|
+
}),
|
|
90
|
+
skills: Schema.String.pipe(Schema.Array, Schema.optional).annotate({
|
|
91
|
+
description: "Additional paths or URLs to discover skills from",
|
|
92
|
+
}),
|
|
93
|
+
commands: Schema.Record(Schema.String, ConfigCommand.Info).pipe(Schema.optional).annotate({
|
|
94
|
+
description: "Named slash command definitions",
|
|
95
|
+
}),
|
|
96
|
+
instructions: Schema.String.pipe(Schema.Array, Schema.optional).annotate({
|
|
97
|
+
description: "Additional paths or URLs supplying ambient instructions",
|
|
98
|
+
}),
|
|
99
|
+
references: ConfigReference.Info.pipe(Schema.optional).annotate({
|
|
100
|
+
description: "Named local directories or Git repositories available as external context",
|
|
101
|
+
}),
|
|
102
|
+
plugins: ConfigPlugin.Plugins.pipe(Schema.optional).annotate({
|
|
103
|
+
description: "Ordered external plugin packages to load",
|
|
104
|
+
}),
|
|
105
|
+
experimental: ConfigExperimental.Experimental.pipe(Schema.optional),
|
|
106
|
+
providers: Schema.Record(Schema.String, ConfigProvider.Info).pipe(Schema.optional),
|
|
107
|
+
}) {}
|
|
108
|
+
|
|
109
|
+
export class Document extends Schema.Class<Document>("Config.Document")({
|
|
110
|
+
type: Schema.Literal("document"),
|
|
111
|
+
path: Schema.String.pipe(Schema.optional),
|
|
112
|
+
info: Info,
|
|
113
|
+
}) {}
|
|
114
|
+
|
|
115
|
+
export class Directory extends Schema.Class<Directory>("Config.Directory")({
|
|
116
|
+
type: Schema.Literal("directory"),
|
|
117
|
+
path: AbsolutePath,
|
|
118
|
+
}) {}
|
|
119
|
+
|
|
120
|
+
export type Entry = Document | Directory
|
|
121
|
+
|
|
122
|
+
export function latest<K extends keyof Info>(entries: readonly Entry[], key: K): Info[K] | undefined {
|
|
123
|
+
return entries
|
|
124
|
+
.filter((entry): entry is Document => entry.type === "document")
|
|
125
|
+
.findLast((entry) => entry.info[key] !== undefined)?.info[key]
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
export interface Interface {
|
|
129
|
+
/** Returns location config documents and supplemental directories from lowest to highest priority. */
|
|
130
|
+
readonly entries: () => Effect.Effect<Entry[]>
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
export class Service extends Context.Service<Service, Interface>()("@neurocode/v2/Config") {}
|
|
134
|
+
|
|
135
|
+
const layer = Layer.effect(
|
|
136
|
+
Service,
|
|
137
|
+
Effect.gen(function* () {
|
|
138
|
+
const fs = yield* FSUtil.Service
|
|
139
|
+
const global = yield* Global.Service
|
|
140
|
+
const location = yield* Location.Service
|
|
141
|
+
const policy = yield* Policy.Service
|
|
142
|
+
const names = ["neurocode.json", "neurocode.jsonc"]
|
|
143
|
+
const decodeOptions = { errors: "all", onExcessProperty: "ignore", propertyOrder: "original" } as const
|
|
144
|
+
const decodeInfo = Schema.decodeUnknownOption(Info, decodeOptions)
|
|
145
|
+
const decodeV1Info = Schema.decodeUnknownOption(ConfigV1.Info, decodeOptions)
|
|
146
|
+
|
|
147
|
+
const loadFile = Effect.fnUntraced(function* (filepath: string) {
|
|
148
|
+
const text = yield* fs.readFileStringSafe(filepath)
|
|
149
|
+
if (!text) return
|
|
150
|
+
|
|
151
|
+
const errors: ParseError[] = []
|
|
152
|
+
const input: unknown = parse(text, errors, { allowTrailingComma: true })
|
|
153
|
+
if (errors.length) return
|
|
154
|
+
|
|
155
|
+
const info = Option.getOrUndefined(
|
|
156
|
+
ConfigMigrateV1.isV1(input)
|
|
157
|
+
? decodeV1Info(input).pipe(Option.map(ConfigMigrateV1.migrate), Option.flatMap(decodeInfo))
|
|
158
|
+
: decodeInfo(input),
|
|
159
|
+
)
|
|
160
|
+
if (!info) return
|
|
161
|
+
return new Document({ type: "document", path: filepath, info })
|
|
162
|
+
})
|
|
163
|
+
|
|
164
|
+
const loadDirectory = Effect.fnUntraced(function* (directory: AbsolutePath) {
|
|
165
|
+
return [
|
|
166
|
+
...(yield* Effect.forEach(names, (file) => loadFile(path.join(directory, file))).pipe(
|
|
167
|
+
Effect.map((configs) => configs.filter((config): config is Document => config !== undefined)),
|
|
168
|
+
)),
|
|
169
|
+
new Directory({ type: "directory", path: directory }),
|
|
170
|
+
]
|
|
171
|
+
})
|
|
172
|
+
|
|
173
|
+
const globalDirectory = AbsolutePath.make(global.config)
|
|
174
|
+
const locationIsGlobal = path.resolve(location.directory) === path.resolve(global.config)
|
|
175
|
+
// Read configuration once when this location opens. Later calls reuse these
|
|
176
|
+
// values until the location is reopened.
|
|
177
|
+
const discovered = locationIsGlobal
|
|
178
|
+
? []
|
|
179
|
+
: yield* fs
|
|
180
|
+
.up({
|
|
181
|
+
targets: [".neurocode", ...names.toReversed()],
|
|
182
|
+
start: location.directory,
|
|
183
|
+
stop: location.project.directory,
|
|
184
|
+
})
|
|
185
|
+
.pipe(Effect.orDie)
|
|
186
|
+
const directories = [
|
|
187
|
+
globalDirectory,
|
|
188
|
+
...discovered
|
|
189
|
+
.filter((item) => path.basename(item) === ".neurocode")
|
|
190
|
+
.toReversed()
|
|
191
|
+
.map((directory) => AbsolutePath.make(directory)),
|
|
192
|
+
]
|
|
193
|
+
// A config closer to the opened directory should win over one higher up.
|
|
194
|
+
// Search starts nearby, so reverse the results before applying them.
|
|
195
|
+
const directPaths = discovered.filter((item) => path.basename(item) !== ".neurocode").toReversed()
|
|
196
|
+
const direct = yield* Effect.forEach(directPaths, loadFile).pipe(
|
|
197
|
+
Effect.orDie,
|
|
198
|
+
Effect.map((configs) => configs.filter((config): config is Document => config !== undefined)),
|
|
199
|
+
)
|
|
200
|
+
const supplementary = yield* Effect.forEach(directories, loadDirectory).pipe(Effect.orDie)
|
|
201
|
+
// Apply general settings first and more specific settings last:
|
|
202
|
+
// global config, project files, then `.neurocode` files.
|
|
203
|
+
const configs = [...(supplementary[0] ?? []), ...direct, ...supplementary.slice(1).flat()]
|
|
204
|
+
// Rules use the opposite order so a user-global rule can override a
|
|
205
|
+
// repository rule. Statement order inside each file stays unchanged.
|
|
206
|
+
yield* policy.load(
|
|
207
|
+
configs
|
|
208
|
+
.filter((config): config is Document => config.type === "document")
|
|
209
|
+
.toReversed()
|
|
210
|
+
.flatMap((config) => config.info.experimental?.policies ?? []),
|
|
211
|
+
)
|
|
212
|
+
|
|
213
|
+
return Service.of({
|
|
214
|
+
entries: Effect.fn("Config.entries")(function* () {
|
|
215
|
+
return configs
|
|
216
|
+
}),
|
|
217
|
+
})
|
|
218
|
+
}),
|
|
219
|
+
)
|
|
220
|
+
|
|
221
|
+
export const locationLayer = layer.pipe(Layer.provideMerge(Policy.locationLayer))
|
|
222
|
+
|
|
223
|
+
export const node = makeLocationNode({
|
|
224
|
+
service: Service,
|
|
225
|
+
layer,
|
|
226
|
+
deps: [FSUtil.node, Global.node, Location.node, Policy.node],
|
|
227
|
+
})
|
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
export * as MoveSession from "./move-session"
|
|
2
|
+
|
|
3
|
+
import { Context, DateTime, Effect, Layer, Schema } from "effect"
|
|
4
|
+
import { makeGlobalNode } from "../effect/app-node"
|
|
5
|
+
import { EventV2 } from "../event"
|
|
6
|
+
import { Git } from "../git"
|
|
7
|
+
import { Location } from "../location"
|
|
8
|
+
import { ProjectV2 } from "../project"
|
|
9
|
+
import { SessionV2 } from "../session"
|
|
10
|
+
import { SessionEvent } from "../session/event"
|
|
11
|
+
import { SessionSchema } from "../session/schema"
|
|
12
|
+
import { SessionStore } from "../session/store"
|
|
13
|
+
import { AbsolutePath, RelativePath } from "../schema"
|
|
14
|
+
import path from "path"
|
|
15
|
+
|
|
16
|
+
export const Destination = Schema.Struct({
|
|
17
|
+
directory: AbsolutePath,
|
|
18
|
+
}).annotate({ identifier: "MoveSession.Destination" })
|
|
19
|
+
export type Destination = typeof Destination.Type
|
|
20
|
+
|
|
21
|
+
export const Input = Schema.Struct({
|
|
22
|
+
sessionID: SessionSchema.ID,
|
|
23
|
+
destination: Destination,
|
|
24
|
+
moveChanges: Schema.optional(Schema.Boolean),
|
|
25
|
+
}).annotate({ identifier: "MoveSession.Input" })
|
|
26
|
+
export type Input = typeof Input.Type
|
|
27
|
+
|
|
28
|
+
export class DestinationProjectMismatchError extends Schema.TaggedErrorClass<DestinationProjectMismatchError>()(
|
|
29
|
+
"MoveSession.DestinationProjectMismatchError",
|
|
30
|
+
{
|
|
31
|
+
expected: ProjectV2.ID,
|
|
32
|
+
actual: ProjectV2.ID,
|
|
33
|
+
},
|
|
34
|
+
) {}
|
|
35
|
+
|
|
36
|
+
export class ApplyChangesError extends Schema.TaggedErrorClass<ApplyChangesError>()("MoveSession.ApplyChangesError", {
|
|
37
|
+
message: Schema.String,
|
|
38
|
+
}) {}
|
|
39
|
+
|
|
40
|
+
export class CaptureChangesError extends Schema.TaggedErrorClass<CaptureChangesError>()(
|
|
41
|
+
"MoveSession.CaptureChangesError",
|
|
42
|
+
{
|
|
43
|
+
message: Schema.String,
|
|
44
|
+
},
|
|
45
|
+
) {}
|
|
46
|
+
|
|
47
|
+
export class ResetSourceChangesError extends Schema.TaggedErrorClass<ResetSourceChangesError>()(
|
|
48
|
+
"MoveSession.ResetSourceChangesError",
|
|
49
|
+
{
|
|
50
|
+
directory: AbsolutePath,
|
|
51
|
+
message: Schema.String,
|
|
52
|
+
cause: Schema.optional(Schema.Defect()),
|
|
53
|
+
},
|
|
54
|
+
) {}
|
|
55
|
+
|
|
56
|
+
export type Error =
|
|
57
|
+
| SessionV2.NotFoundError
|
|
58
|
+
| DestinationProjectMismatchError
|
|
59
|
+
| CaptureChangesError
|
|
60
|
+
| ApplyChangesError
|
|
61
|
+
| ResetSourceChangesError
|
|
62
|
+
|
|
63
|
+
export interface Interface {
|
|
64
|
+
readonly moveSession: (input: Input) => Effect.Effect<void, Error>
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
export class Service extends Context.Service<Service, Interface>()("@neurocode/ControlPlaneMoveSession") {}
|
|
68
|
+
|
|
69
|
+
const layer = Layer.effect(
|
|
70
|
+
Service,
|
|
71
|
+
Effect.gen(function* () {
|
|
72
|
+
const git = yield* Git.Service
|
|
73
|
+
const events = yield* EventV2.Service
|
|
74
|
+
const project = yield* ProjectV2.Service
|
|
75
|
+
const sessions = yield* SessionStore.Service
|
|
76
|
+
|
|
77
|
+
const moveSession = Effect.fn("MoveSession.moveSession")(function* (input: Input) {
|
|
78
|
+
const current = yield* sessions.get(input.sessionID)
|
|
79
|
+
if (!current) return yield* new SessionV2.NotFoundError({ sessionID: input.sessionID })
|
|
80
|
+
const directory = AbsolutePath.make(input.destination.directory)
|
|
81
|
+
if (current.location.directory === directory) return
|
|
82
|
+
|
|
83
|
+
const source = yield* project.resolve(current.location.directory)
|
|
84
|
+
const destination = yield* project.resolve(directory)
|
|
85
|
+
if (current.projectID !== destination.id) {
|
|
86
|
+
return yield* new DestinationProjectMismatchError({ expected: current.projectID, actual: destination.id })
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
const moveChanges = input.moveChanges && source.directory !== destination.directory
|
|
90
|
+
const sourceRepository = moveChanges ? yield* git.repo.discover(current.location.directory) : undefined
|
|
91
|
+
if (moveChanges && !sourceRepository)
|
|
92
|
+
return yield* new CaptureChangesError({ message: "Source is not a Git repository" })
|
|
93
|
+
const patch = sourceRepository
|
|
94
|
+
? yield* git.change
|
|
95
|
+
.capture({ repository: sourceRepository, path: current.location.directory })
|
|
96
|
+
.pipe(Effect.mapError((error) => new CaptureChangesError({ message: error.message })))
|
|
97
|
+
: Git.ChangeSet.make("")
|
|
98
|
+
if (patch) {
|
|
99
|
+
const repository = yield* git.repo.discover(directory)
|
|
100
|
+
if (!repository) return yield* new ApplyChangesError({ message: "Destination is not a Git repository" })
|
|
101
|
+
yield* git.change
|
|
102
|
+
.apply({ repository, path: directory, changes: patch })
|
|
103
|
+
.pipe(Effect.mapError((error) => new ApplyChangesError({ message: error.message })))
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
yield* events.publish(SessionEvent.Moved, {
|
|
107
|
+
sessionID: input.sessionID,
|
|
108
|
+
location: Location.Ref.make({ directory }),
|
|
109
|
+
subdirectory: RelativePath.make(path.relative(destination.directory, directory).replaceAll("\\", "/")),
|
|
110
|
+
timestamp: yield* DateTime.now,
|
|
111
|
+
})
|
|
112
|
+
|
|
113
|
+
if (patch) {
|
|
114
|
+
const repository = yield* git.repo.discover(current.location.directory)
|
|
115
|
+
if (!repository)
|
|
116
|
+
return yield* new ResetSourceChangesError({
|
|
117
|
+
directory: current.location.directory,
|
|
118
|
+
message: "Source is not a Git repository",
|
|
119
|
+
})
|
|
120
|
+
yield* git.change
|
|
121
|
+
.discard({
|
|
122
|
+
repository,
|
|
123
|
+
path: current.location.directory,
|
|
124
|
+
index: "preserve",
|
|
125
|
+
untracked: "remove",
|
|
126
|
+
})
|
|
127
|
+
.pipe(
|
|
128
|
+
Effect.mapError(
|
|
129
|
+
(error) =>
|
|
130
|
+
new ResetSourceChangesError({
|
|
131
|
+
directory: current.location.directory,
|
|
132
|
+
message: error.message,
|
|
133
|
+
cause: error.cause,
|
|
134
|
+
}),
|
|
135
|
+
),
|
|
136
|
+
)
|
|
137
|
+
}
|
|
138
|
+
})
|
|
139
|
+
|
|
140
|
+
return Service.of({ moveSession })
|
|
141
|
+
}),
|
|
142
|
+
)
|
|
143
|
+
|
|
144
|
+
export const node = makeGlobalNode({
|
|
145
|
+
service: Service,
|
|
146
|
+
layer,
|
|
147
|
+
deps: [Git.node, EventV2.node, ProjectV2.node, SessionStore.node],
|
|
148
|
+
})
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { sqliteTable, text, integer } from "drizzle-orm/sqlite-core"
|
|
2
|
+
import { ProjectTable } from "../project/sql"
|
|
3
|
+
import { ProjectV2 } from "../project"
|
|
4
|
+
import { WorkspaceV2 } from "../workspace"
|
|
5
|
+
|
|
6
|
+
export const WorkspaceTable = sqliteTable("workspace", {
|
|
7
|
+
id: text().$type<WorkspaceV2.ID>().primaryKey(),
|
|
8
|
+
type: text().notNull(),
|
|
9
|
+
name: text().notNull().default(""),
|
|
10
|
+
branch: text(),
|
|
11
|
+
directory: text(),
|
|
12
|
+
extra: text({ mode: "json" }),
|
|
13
|
+
project_id: text()
|
|
14
|
+
.$type<ProjectV2.ID>()
|
|
15
|
+
.notNull()
|
|
16
|
+
.references(() => ProjectTable.id, { onDelete: "cascade" }),
|
|
17
|
+
time_used: integer()
|
|
18
|
+
.notNull()
|
|
19
|
+
.$default(() => Date.now()),
|
|
20
|
+
})
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { integer, sqliteTable, text } from "drizzle-orm/sqlite-core"
|
|
2
|
+
import { Timestamps } from "../database/schema.sql"
|
|
3
|
+
import type { Credential } from "../credential"
|
|
4
|
+
|
|
5
|
+
export const CredentialTable = sqliteTable("credential", {
|
|
6
|
+
id: text().$type<Credential.ID>().primaryKey(),
|
|
7
|
+
integration_id: text().$type<Credential.Info["integrationID"]>(),
|
|
8
|
+
label: text().notNull(),
|
|
9
|
+
value: text({ mode: "json" }).$type<Credential.Value>().notNull(),
|
|
10
|
+
connector_id: text(),
|
|
11
|
+
method_id: text(),
|
|
12
|
+
active: integer({ mode: "boolean" }),
|
|
13
|
+
...Timestamps,
|
|
14
|
+
})
|
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
export * as Credential from "./credential"
|
|
2
|
+
|
|
3
|
+
import { asc, eq } from "drizzle-orm"
|
|
4
|
+
import { Context, Effect, Layer, Schema } from "effect"
|
|
5
|
+
import { Credential } from "@neurocode-ai/schema/credential"
|
|
6
|
+
import { Integration } from "@neurocode-ai/schema/integration"
|
|
7
|
+
import { Database } from "./database/database"
|
|
8
|
+
import { makeGlobalNode } from "./effect/app-node"
|
|
9
|
+
import { CredentialTable } from "./credential/sql"
|
|
10
|
+
|
|
11
|
+
export const ID = Credential.ID
|
|
12
|
+
export type ID = Credential.ID
|
|
13
|
+
|
|
14
|
+
export const OAuth = Credential.OAuth
|
|
15
|
+
export type OAuth = Credential.OAuth
|
|
16
|
+
|
|
17
|
+
export const Key = Credential.Key
|
|
18
|
+
export type Key = Credential.Key
|
|
19
|
+
|
|
20
|
+
export const Value = Credential.Value
|
|
21
|
+
export type Value = Credential.Value
|
|
22
|
+
|
|
23
|
+
export class Info extends Schema.Class<Info>("Credential.Info")({
|
|
24
|
+
id: ID,
|
|
25
|
+
integrationID: Integration.ID,
|
|
26
|
+
label: Schema.String,
|
|
27
|
+
value: Value,
|
|
28
|
+
}) {}
|
|
29
|
+
|
|
30
|
+
export interface Interface {
|
|
31
|
+
/** Returns every stored credential. */
|
|
32
|
+
readonly all: () => Effect.Effect<Info[]>
|
|
33
|
+
/** Returns stored credentials belonging to one integration. */
|
|
34
|
+
readonly list: (integrationID: Integration.ID) => Effect.Effect<Info[]>
|
|
35
|
+
/** Returns one stored credential by ID. */
|
|
36
|
+
readonly get: (id: ID) => Effect.Effect<Info | undefined>
|
|
37
|
+
/** Replaces any credential for an integration and returns the new record. */
|
|
38
|
+
readonly create: (input: {
|
|
39
|
+
readonly integrationID: Integration.ID
|
|
40
|
+
readonly value: Value
|
|
41
|
+
readonly label?: string
|
|
42
|
+
}) => Effect.Effect<Info>
|
|
43
|
+
/** Updates the label or secret value of a stored credential. */
|
|
44
|
+
readonly update: (id: ID, updates: Partial<Pick<Info, "label" | "value">>) => Effect.Effect<void>
|
|
45
|
+
/** Removes a stored credential. */
|
|
46
|
+
readonly remove: (id: ID) => Effect.Effect<void>
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
export class Service extends Context.Service<Service, Interface>()("@neurocode/v2/Credential") {}
|
|
50
|
+
|
|
51
|
+
const layer = Layer.effect(
|
|
52
|
+
Service,
|
|
53
|
+
Effect.gen(function* () {
|
|
54
|
+
const { db } = yield* Database.Service
|
|
55
|
+
const decode = Schema.decodeUnknownSync(Value)
|
|
56
|
+
const stored = (row: typeof CredentialTable.$inferSelect) => {
|
|
57
|
+
if (!row.integration_id) return
|
|
58
|
+
return new Info({
|
|
59
|
+
id: row.id,
|
|
60
|
+
integrationID: row.integration_id,
|
|
61
|
+
label: row.label,
|
|
62
|
+
value: decode(row.value),
|
|
63
|
+
})
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
return Service.of({
|
|
67
|
+
all: Effect.fn("Credential.all")(function* () {
|
|
68
|
+
return (yield* db
|
|
69
|
+
.select()
|
|
70
|
+
.from(CredentialTable)
|
|
71
|
+
.orderBy(asc(CredentialTable.time_created))
|
|
72
|
+
.all()
|
|
73
|
+
.pipe(Effect.orDie)).flatMap((row) => {
|
|
74
|
+
const credential = stored(row)
|
|
75
|
+
return credential ? [credential] : []
|
|
76
|
+
})
|
|
77
|
+
}),
|
|
78
|
+
list: Effect.fn("Credential.list")(function* (integrationID) {
|
|
79
|
+
return (yield* db
|
|
80
|
+
.select()
|
|
81
|
+
.from(CredentialTable)
|
|
82
|
+
.where(eq(CredentialTable.integration_id, integrationID))
|
|
83
|
+
.orderBy(asc(CredentialTable.time_created))
|
|
84
|
+
.all()
|
|
85
|
+
.pipe(Effect.orDie)).flatMap((row) => {
|
|
86
|
+
const credential = stored(row)
|
|
87
|
+
return credential ? [credential] : []
|
|
88
|
+
})
|
|
89
|
+
}),
|
|
90
|
+
get: Effect.fn("Credential.get")(function* (id) {
|
|
91
|
+
const row = yield* db.select().from(CredentialTable).where(eq(CredentialTable.id, id)).get().pipe(Effect.orDie)
|
|
92
|
+
return row ? stored(row) : undefined
|
|
93
|
+
}),
|
|
94
|
+
create: Effect.fn("Credential.create")(function* (input) {
|
|
95
|
+
const credential = new Info({
|
|
96
|
+
id: ID.create(),
|
|
97
|
+
integrationID: input.integrationID,
|
|
98
|
+
label: input.label ?? "default",
|
|
99
|
+
value: input.value,
|
|
100
|
+
})
|
|
101
|
+
yield* db
|
|
102
|
+
.transaction((tx) =>
|
|
103
|
+
Effect.gen(function* () {
|
|
104
|
+
yield* tx
|
|
105
|
+
.delete(CredentialTable)
|
|
106
|
+
.where(eq(CredentialTable.integration_id, credential.integrationID))
|
|
107
|
+
.run()
|
|
108
|
+
yield* tx
|
|
109
|
+
.insert(CredentialTable)
|
|
110
|
+
.values({
|
|
111
|
+
id: credential.id,
|
|
112
|
+
integration_id: credential.integrationID,
|
|
113
|
+
label: credential.label,
|
|
114
|
+
value: credential.value,
|
|
115
|
+
})
|
|
116
|
+
.run()
|
|
117
|
+
}),
|
|
118
|
+
)
|
|
119
|
+
.pipe(Effect.orDie)
|
|
120
|
+
return credential
|
|
121
|
+
}),
|
|
122
|
+
update: Effect.fn("Credential.update")(function* (id, updates) {
|
|
123
|
+
if (!updates.label && !updates.value) return
|
|
124
|
+
yield* db
|
|
125
|
+
.update(CredentialTable)
|
|
126
|
+
.set({ label: updates.label, value: updates.value })
|
|
127
|
+
.where(eq(CredentialTable.id, id))
|
|
128
|
+
.run()
|
|
129
|
+
.pipe(Effect.orDie)
|
|
130
|
+
}),
|
|
131
|
+
remove: Effect.fn("Credential.remove")(function* (id) {
|
|
132
|
+
yield* db.delete(CredentialTable).where(eq(CredentialTable.id, id)).run().pipe(Effect.orDie)
|
|
133
|
+
}),
|
|
134
|
+
})
|
|
135
|
+
}),
|
|
136
|
+
)
|
|
137
|
+
|
|
138
|
+
export const node = makeGlobalNode({ service: Service, layer, deps: [Database.node] })
|