bonecode 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/ARCHITECTURE.md +183 -0
- package/README.md +71 -0
- package/bin/bonecode +62 -0
- package/bone/migrations/rag_vectors.sql +258 -0
- package/bone/output/agent/.dockerignore +7 -0
- package/bone/output/agent/.env.example +36 -0
- package/bone/output/agent/.github/workflows/ci.yaml +58 -0
- package/bone/output/agent/AgentDomain.bone.map +350 -0
- package/bone/output/agent/AgentDomain.postman_collection.json +958 -0
- package/bone/output/agent/Dockerfile +22 -0
- package/bone/output/agent/README.md +47 -0
- package/bone/output/agent/admin/index.html +740 -0
- package/bone/output/agent/docker-compose.yaml +22 -0
- package/bone/output/agent/k8s/deployment.yaml +75 -0
- package/bone/output/agent/migrations/agent.sql +36 -0
- package/bone/output/agent/migrations/agent_instance.sql +36 -0
- package/bone/output/agent/migrations/audit_log.sql +18 -0
- package/bone/output/agent/migrations/build_step.sql +34 -0
- package/bone/output/agent/migrations/event_outbox.sql +31 -0
- package/bone/output/agent/migrations/plan.sql +30 -0
- package/bone/output/agent/migrations/task.sql +30 -0
- package/bone/output/agent/migrations/tool_call.sql +33 -0
- package/bone/output/agent/openapi.yaml +1116 -0
- package/bone/output/agent/package.json +36 -0
- package/bone/output/agent/schema.graphql +233 -0
- package/bone/output/agent/sdk/client.ts +231 -0
- package/bone/output/agent/src/algorithms.ts +2 -0
- package/bone/output/agent/src/audit.ts +44 -0
- package/bone/output/agent/src/auth.ts +57 -0
- package/bone/output/agent/src/cron.ts +12 -0
- package/bone/output/agent/src/db.ts +32 -0
- package/bone/output/agent/src/debug.ts +66 -0
- package/bone/output/agent/src/events.ts +243 -0
- package/bone/output/agent/src/extensions.ts +54 -0
- package/bone/output/agent/src/failure_rules.ts +323 -0
- package/bone/output/agent/src/flows.ts +168 -0
- package/bone/output/agent/src/health.ts +43 -0
- package/bone/output/agent/src/index.ts +100 -0
- package/bone/output/agent/src/logger.ts +66 -0
- package/bone/output/agent/src/metrics.ts +75 -0
- package/bone/output/agent/src/migrate.ts +352 -0
- package/bone/output/agent/src/migration_diff.ts +108 -0
- package/bone/output/agent/src/notify.ts +125 -0
- package/bone/output/agent/src/routes/agent_instance.ts +234 -0
- package/bone/output/agent/src/routes/build_step.ts +105 -0
- package/bone/output/agent/src/routes/plan.ts +91 -0
- package/bone/output/agent/src/routes/task.ts +105 -0
- package/bone/output/agent/src/routes/tool_call.ts +166 -0
- package/bone/output/agent/src/schemas.ts +384 -0
- package/bone/output/agent/src/state_machines/agent_instance.ts +24 -0
- package/bone/output/agent/src/state_machines/build_step.ts +22 -0
- package/bone/output/agent/src/state_machines/plan.ts +22 -0
- package/bone/output/agent/src/state_machines/task.ts +22 -0
- package/bone/output/agent/src/state_machines/tool_call.ts +22 -0
- package/bone/output/agent/src/tests.ts +362 -0
- package/bone/output/agent/src/websocket.ts +201 -0
- package/bone/output/agent/tsconfig.json +25 -0
- package/bone/output/rag/.dockerignore +7 -0
- package/bone/output/rag/.env.example +36 -0
- package/bone/output/rag/.github/workflows/ci.yaml +58 -0
- package/bone/output/rag/Dockerfile +22 -0
- package/bone/output/rag/RAGDomain.bone.map +287 -0
- package/bone/output/rag/RAGDomain.postman_collection.json +923 -0
- package/bone/output/rag/README.md +47 -0
- package/bone/output/rag/admin/index.html +818 -0
- package/bone/output/rag/docker-compose.yaml +22 -0
- package/bone/output/rag/k8s/deployment.yaml +75 -0
- package/bone/output/rag/migrations/audit_log.sql +18 -0
- package/bone/output/rag/migrations/code_chunk.sql +34 -0
- package/bone/output/rag/migrations/code_file.sql +33 -0
- package/bone/output/rag/migrations/event_outbox.sql +31 -0
- package/bone/output/rag/migrations/indexing_job.sql +33 -0
- package/bone/output/rag/migrations/knowledge_base.sql +35 -0
- package/bone/output/rag/migrations/memory_entry.sql +34 -0
- package/bone/output/rag/openapi.yaml +1097 -0
- package/bone/output/rag/package.json +36 -0
- package/bone/output/rag/schema.graphql +245 -0
- package/bone/output/rag/sdk/client.ts +234 -0
- package/bone/output/rag/src/algorithms.ts +2 -0
- package/bone/output/rag/src/audit.ts +37 -0
- package/bone/output/rag/src/auth.ts +57 -0
- package/bone/output/rag/src/cron.ts +12 -0
- package/bone/output/rag/src/db.ts +32 -0
- package/bone/output/rag/src/debug.ts +66 -0
- package/bone/output/rag/src/events.ts +243 -0
- package/bone/output/rag/src/extensions.ts +350 -0
- package/bone/output/rag/src/failure_rules.ts +315 -0
- package/bone/output/rag/src/flows.ts +239 -0
- package/bone/output/rag/src/health.ts +43 -0
- package/bone/output/rag/src/index.ts +95 -0
- package/bone/output/rag/src/logger.ts +66 -0
- package/bone/output/rag/src/metrics.ts +75 -0
- package/bone/output/rag/src/migrate.ts +364 -0
- package/bone/output/rag/src/migration_diff.ts +108 -0
- package/bone/output/rag/src/notify.ts +99 -0
- package/bone/output/rag/src/routes/code_chunk.ts +75 -0
- package/bone/output/rag/src/routes/code_file.ts +101 -0
- package/bone/output/rag/src/routes/indexing_job.ts +87 -0
- package/bone/output/rag/src/routes/knowledge_base.ts +230 -0
- package/bone/output/rag/src/routes/memory_entry.ts +87 -0
- package/bone/output/rag/src/schemas.ts +394 -0
- package/bone/output/rag/src/state_machines/code_file.ts +23 -0
- package/bone/output/rag/src/state_machines/indexing_job.ts +22 -0
- package/bone/output/rag/src/state_machines/knowledge_base.ts +23 -0
- package/bone/output/rag/src/state_machines/memory_entry.ts +20 -0
- package/bone/output/rag/src/tests.ts +340 -0
- package/bone/output/rag/tsconfig.json +25 -0
- package/bone/output/session/.dockerignore +7 -0
- package/bone/output/session/.env.example +36 -0
- package/bone/output/session/.github/workflows/ci.yaml +58 -0
- package/bone/output/session/Dockerfile +22 -0
- package/bone/output/session/README.md +47 -0
- package/bone/output/session/SessionDomain.bone.map +350 -0
- package/bone/output/session/SessionDomain.postman_collection.json +958 -0
- package/bone/output/session/admin/index.html +667 -0
- package/bone/output/session/docker-compose.yaml +22 -0
- package/bone/output/session/k8s/deployment.yaml +75 -0
- package/bone/output/session/migrations/audit_log.sql +18 -0
- package/bone/output/session/migrations/event_outbox.sql +31 -0
- package/bone/output/session/migrations/message.sql +31 -0
- package/bone/output/session/migrations/part.sql +28 -0
- package/bone/output/session/migrations/permission.sql +28 -0
- package/bone/output/session/migrations/project.sql +28 -0
- package/bone/output/session/migrations/session.sql +38 -0
- package/bone/output/session/openapi.yaml +1101 -0
- package/bone/output/session/package.json +36 -0
- package/bone/output/session/schema.graphql +222 -0
- package/bone/output/session/sdk/client.ts +225 -0
- package/bone/output/session/src/algorithms.ts +2 -0
- package/bone/output/session/src/audit.ts +44 -0
- package/bone/output/session/src/auth.ts +57 -0
- package/bone/output/session/src/cron.ts +12 -0
- package/bone/output/session/src/db.ts +32 -0
- package/bone/output/session/src/debug.ts +66 -0
- package/bone/output/session/src/events.ts +270 -0
- package/bone/output/session/src/extensions.ts +215 -0
- package/bone/output/session/src/failure_rules.ts +284 -0
- package/bone/output/session/src/flows.ts +168 -0
- package/bone/output/session/src/health.ts +43 -0
- package/bone/output/session/src/index.ts +100 -0
- package/bone/output/session/src/logger.ts +66 -0
- package/bone/output/session/src/metrics.ts +75 -0
- package/bone/output/session/src/migrate.ts +332 -0
- package/bone/output/session/src/migration_diff.ts +108 -0
- package/bone/output/session/src/notify.ts +112 -0
- package/bone/output/session/src/routes/message.ts +93 -0
- package/bone/output/session/src/routes/part.ts +79 -0
- package/bone/output/session/src/routes/permission.ts +79 -0
- package/bone/output/session/src/routes/project.ts +79 -0
- package/bone/output/session/src/routes/session.ts +294 -0
- package/bone/output/session/src/schemas.ts +357 -0
- package/bone/output/session/src/state_machines/session.ts +23 -0
- package/bone/output/session/src/tests.ts +326 -0
- package/bone/output/session/src/websocket.ts +201 -0
- package/bone/output/session/tsconfig.json +25 -0
- package/bone/output/workspace/.dockerignore +7 -0
- package/bone/output/workspace/.env.example +36 -0
- package/bone/output/workspace/.github/workflows/ci.yaml +58 -0
- package/bone/output/workspace/Dockerfile +22 -0
- package/bone/output/workspace/README.md +45 -0
- package/bone/output/workspace/WorkspaceDomain.bone.map +189 -0
- package/bone/output/workspace/WorkspaceDomain.postman_collection.json +621 -0
- package/bone/output/workspace/admin/index.html +485 -0
- package/bone/output/workspace/docker-compose.yaml +22 -0
- package/bone/output/workspace/k8s/deployment.yaml +75 -0
- package/bone/output/workspace/migrations/audit_log.sql +18 -0
- package/bone/output/workspace/migrations/codebase.sql +34 -0
- package/bone/output/workspace/migrations/event_outbox.sql +31 -0
- package/bone/output/workspace/migrations/snapshot.sql +32 -0
- package/bone/output/workspace/migrations/workspace.sql +33 -0
- package/bone/output/workspace/openapi.yaml +721 -0
- package/bone/output/workspace/package.json +36 -0
- package/bone/output/workspace/schema.graphql +153 -0
- package/bone/output/workspace/sdk/client.ts +155 -0
- package/bone/output/workspace/src/algorithms.ts +2 -0
- package/bone/output/workspace/src/audit.ts +37 -0
- package/bone/output/workspace/src/auth.ts +57 -0
- package/bone/output/workspace/src/cron.ts +12 -0
- package/bone/output/workspace/src/db.ts +32 -0
- package/bone/output/workspace/src/debug.ts +66 -0
- package/bone/output/workspace/src/events.ts +243 -0
- package/bone/output/workspace/src/extensions.ts +44 -0
- package/bone/output/workspace/src/failure_rules.ts +153 -0
- package/bone/output/workspace/src/health.ts +43 -0
- package/bone/output/workspace/src/index.ts +89 -0
- package/bone/output/workspace/src/logger.ts +66 -0
- package/bone/output/workspace/src/metrics.ts +75 -0
- package/bone/output/workspace/src/migrate.ts +220 -0
- package/bone/output/workspace/src/migration_diff.ts +108 -0
- package/bone/output/workspace/src/notify.ts +73 -0
- package/bone/output/workspace/src/routes/codebase.ts +87 -0
- package/bone/output/workspace/src/routes/snapshot.ts +127 -0
- package/bone/output/workspace/src/routes/workspace.ts +190 -0
- package/bone/output/workspace/src/schemas.ts +231 -0
- package/bone/output/workspace/src/state_machines/codebase.ts +21 -0
- package/bone/output/workspace/src/state_machines/snapshot.ts +20 -0
- package/bone/output/workspace/src/state_machines/workspace.ts +21 -0
- package/bone/output/workspace/src/tests.ts +249 -0
- package/bone/output/workspace/tsconfig.json +25 -0
- package/compat/opencode_adapter.ts +410 -0
- package/package.json +69 -0
- package/scripts/check_benchmark_session.js +34 -0
- package/scripts/check_finish_event.js +24 -0
- package/scripts/check_parts.js +15 -0
- package/scripts/compile.js +79 -0
- package/scripts/copy_opencode.ps1 +53 -0
- package/scripts/create_functions.sql +129 -0
- package/scripts/migrate.js +85 -0
- package/scripts/migrate_from_opencode.ts +218 -0
- package/scripts/test_agent_loop.js +101 -0
- package/scripts/test_api.ps1 +116 -0
- package/scripts/test_context_builder.js +136 -0
- package/scripts/test_context_builder.ts +97 -0
- package/scripts/test_rag.js +189 -0
- package/scripts/test_stream_events.js +36 -0
- package/scripts/test_websocket_and_saga.js +216 -0
- package/src/cli.ts +475 -0
- package/src/config.ts +162 -0
- package/src/context_builder.ts +598 -0
- package/src/engine/account/account.sql.ts +39 -0
- package/src/engine/account/account.ts +456 -0
- package/src/engine/account/repo.ts +166 -0
- package/src/engine/account/schema.ts +99 -0
- package/src/engine/account/url.ts +8 -0
- package/src/engine/acp/README.md +174 -0
- package/src/engine/acp/agent.ts +1968 -0
- package/src/engine/acp/runtime.ts +22 -0
- package/src/engine/acp/session.ts +122 -0
- package/src/engine/acp/types.ts +24 -0
- package/src/engine/agent/agent.ts +463 -0
- package/src/engine/agent/generate.txt +75 -0
- package/src/engine/agent/prompt/compaction.txt +9 -0
- package/src/engine/agent/prompt/explore.txt +18 -0
- package/src/engine/agent/prompt/scout.txt +36 -0
- package/src/engine/agent/prompt/summary.txt +11 -0
- package/src/engine/agent/prompt/title.txt +44 -0
- package/src/engine/agent/subagent-permissions.ts +34 -0
- package/src/engine/auth/index.ts +96 -0
- package/src/engine/background/background/job.ts +200 -0
- package/src/engine/background/job.ts +200 -0
- package/src/engine/bus/bus-event.ts +45 -0
- package/src/engine/bus/global.ts +22 -0
- package/src/engine/bus/index.ts +203 -0
- package/src/engine/command/command/index.ts +181 -0
- package/src/engine/command/command/template/initialize.txt +66 -0
- package/src/engine/command/command/template/review.txt +101 -0
- package/src/engine/command/index.ts +181 -0
- package/src/engine/command/template/initialize.txt +66 -0
- package/src/engine/command/template/review.txt +101 -0
- package/src/engine/config/agent.ts +172 -0
- package/src/engine/config/attachment.ts +25 -0
- package/src/engine/config/command.ts +62 -0
- package/src/engine/config/config.ts +833 -0
- package/src/engine/config/console-state.ts +14 -0
- package/src/engine/config/entry-name.ts +16 -0
- package/src/engine/config/error.ts +23 -0
- package/src/engine/config/formatter.ts +13 -0
- package/src/engine/config/layout.ts +6 -0
- package/src/engine/config/lsp.ts +43 -0
- package/src/engine/config/managed.ts +71 -0
- package/src/engine/config/markdown.ts +96 -0
- package/src/engine/config/mcp.ts +56 -0
- package/src/engine/config/model-id.ts +5 -0
- package/src/engine/config/parse.ts +79 -0
- package/src/engine/config/paths.ts +45 -0
- package/src/engine/config/permission.ts +58 -0
- package/src/engine/config/plugin.ts +84 -0
- package/src/engine/config/provider.ts +111 -0
- package/src/engine/config/reference.ts +23 -0
- package/src/engine/config/server.ts +19 -0
- package/src/engine/config/skills.ts +14 -0
- package/src/engine/config/variable.ts +90 -0
- package/src/engine/control-plane/adapters/index.ts +41 -0
- package/src/engine/control-plane/adapters/worktree.ts +96 -0
- package/src/engine/control-plane/dev/README.md +19 -0
- package/src/engine/control-plane/dev/debug-workspace-plugin.ts +73 -0
- package/src/engine/control-plane/schema.ts +14 -0
- package/src/engine/control-plane/types.ts +59 -0
- package/src/engine/control-plane/util.ts +39 -0
- package/src/engine/control-plane/workspace-adapter-runtime.ts +51 -0
- package/src/engine/control-plane/workspace-context.ts +26 -0
- package/src/engine/control-plane/workspace.sql.ts +20 -0
- package/src/engine/control-plane/workspace.ts +1072 -0
- package/src/engine/data-migration.ts +161 -0
- package/src/engine/effect/app-runtime.ts +143 -0
- package/src/engine/effect/bootstrap-runtime.ts +29 -0
- package/src/engine/effect/bridge.ts +84 -0
- package/src/engine/effect/config-service.ts +67 -0
- package/src/engine/effect/instance-ref.ts +11 -0
- package/src/engine/effect/instance-registry.ts +12 -0
- package/src/engine/effect/instance-state.ts +72 -0
- package/src/engine/effect/promise.ts +17 -0
- package/src/engine/effect/run-service.ts +47 -0
- package/src/engine/effect/runner.ts +217 -0
- package/src/engine/effect/runtime-flags.ts +74 -0
- package/src/engine/effect/service-use.ts +38 -0
- package/src/engine/env/index.ts +37 -0
- package/src/engine/event-v2-bridge.ts +89 -0
- package/src/engine/file/file/ignore.ts +81 -0
- package/src/engine/file/file/index.ts +651 -0
- package/src/engine/file/file/protected.ts +59 -0
- package/src/engine/file/file/ripgrep.ts +481 -0
- package/src/engine/file/file/watcher.ts +167 -0
- package/src/engine/file/ignore.ts +81 -0
- package/src/engine/file/index.ts +651 -0
- package/src/engine/file/protected.ts +59 -0
- package/src/engine/file/ripgrep.ts +481 -0
- package/src/engine/file/watcher.ts +167 -0
- package/src/engine/format/format/formatter.ts +404 -0
- package/src/engine/format/format/index.ts +209 -0
- package/src/engine/format/formatter.ts +404 -0
- package/src/engine/format/index.ts +209 -0
- package/src/engine/git/git/index.ts +347 -0
- package/src/engine/git/index.ts +347 -0
- package/src/engine/id/id.ts +80 -0
- package/src/engine/ide/index.ts +70 -0
- package/src/engine/image/image/image.ts +176 -0
- package/src/engine/image/image.ts +176 -0
- package/src/engine/index.ts +251 -0
- package/src/engine/installation/index.ts +327 -0
- package/src/engine/lsp/client.ts +707 -0
- package/src/engine/lsp/diagnostic.ts +29 -0
- package/src/engine/lsp/language.ts +121 -0
- package/src/engine/lsp/launch.ts +21 -0
- package/src/engine/lsp/lsp/client.ts +707 -0
- package/src/engine/lsp/lsp/diagnostic.ts +29 -0
- package/src/engine/lsp/lsp/language.ts +121 -0
- package/src/engine/lsp/lsp/launch.ts +21 -0
- package/src/engine/lsp/lsp/lsp.ts +507 -0
- package/src/engine/lsp/lsp/server.ts +2064 -0
- package/src/engine/lsp/lsp.ts +507 -0
- package/src/engine/lsp/server.ts +2064 -0
- package/src/engine/mcp/auth.ts +146 -0
- package/src/engine/mcp/index.ts +958 -0
- package/src/engine/mcp/mcp/auth.ts +146 -0
- package/src/engine/mcp/mcp/index.ts +958 -0
- package/src/engine/mcp/mcp/oauth-callback.ts +232 -0
- package/src/engine/mcp/mcp/oauth-provider.ts +214 -0
- package/src/engine/mcp/oauth-callback.ts +232 -0
- package/src/engine/mcp/oauth-provider.ts +214 -0
- package/src/engine/node.ts +6 -0
- package/src/engine/patch/index.ts +689 -0
- package/src/engine/patch/patch/index.ts +689 -0
- package/src/engine/permission/arity.ts +163 -0
- package/src/engine/permission/evaluate.ts +15 -0
- package/src/engine/permission/index.ts +306 -0
- package/src/engine/permission/permission/arity.ts +163 -0
- package/src/engine/permission/permission/evaluate.ts +15 -0
- package/src/engine/permission/permission/index.ts +306 -0
- package/src/engine/permission/permission/schema.ts +13 -0
- package/src/engine/permission/schema.ts +13 -0
- package/src/engine/plugin/azure.ts +26 -0
- package/src/engine/plugin/cloudflare.ts +76 -0
- package/src/engine/plugin/codex.ts +622 -0
- package/src/engine/plugin/digitalocean.ts +411 -0
- package/src/engine/plugin/github-copilot/copilot.ts +394 -0
- package/src/engine/plugin/github-copilot/models.ts +196 -0
- package/src/engine/plugin/index.ts +295 -0
- package/src/engine/plugin/install.ts +439 -0
- package/src/engine/plugin/loader.ts +216 -0
- package/src/engine/plugin/meta.ts +188 -0
- package/src/engine/plugin/shared.ts +323 -0
- package/src/engine/project/bootstrap-service.ts +9 -0
- package/src/engine/project/bootstrap.ts +75 -0
- package/src/engine/project/instance-context.ts +24 -0
- package/src/engine/project/instance-layer.ts +11 -0
- package/src/engine/project/instance-runtime.ts +16 -0
- package/src/engine/project/instance-store.ts +193 -0
- package/src/engine/project/project.sql.ts +17 -0
- package/src/engine/project/project.ts +537 -0
- package/src/engine/project/schema.ts +13 -0
- package/src/engine/project/vcs.ts +405 -0
- package/src/engine/provider/auth.ts +225 -0
- package/src/engine/provider/error.ts +204 -0
- package/src/engine/provider/model-status.ts +8 -0
- package/src/engine/provider/provider.ts +1843 -0
- package/src/engine/provider/schema.ts +30 -0
- package/src/engine/provider/sdk/copilot/AGENTS.md +1 -0
- package/src/engine/provider/transform.ts +1376 -0
- package/src/engine/pty/index.ts +365 -0
- package/src/engine/pty/input.ts +24 -0
- package/src/engine/pty/pty/index.ts +365 -0
- package/src/engine/pty/pty/input.ts +24 -0
- package/src/engine/pty/pty/pty.bun.ts +26 -0
- package/src/engine/pty/pty/pty.node.ts +27 -0
- package/src/engine/pty/pty/pty.ts +25 -0
- package/src/engine/pty/pty/schema.ts +14 -0
- package/src/engine/pty/pty/ticket.ts +68 -0
- package/src/engine/pty/pty.bun.ts +26 -0
- package/src/engine/pty/pty.node.ts +27 -0
- package/src/engine/pty/pty.ts +25 -0
- package/src/engine/pty/schema.ts +14 -0
- package/src/engine/pty/ticket.ts +68 -0
- package/src/engine/question/index.ts +213 -0
- package/src/engine/question/question/index.ts +213 -0
- package/src/engine/question/question/schema.ts +10 -0
- package/src/engine/question/schema.ts +10 -0
- package/src/engine/reference/reference/reference.ts +241 -0
- package/src/engine/reference/reference/repository-cache.ts +147 -0
- package/src/engine/reference/reference.ts +241 -0
- package/src/engine/reference/repository-cache.ts +147 -0
- package/src/engine/session/compaction.ts +651 -0
- package/src/engine/session/compaction_logic.ts +120 -0
- package/src/engine/session/instruction.ts +238 -0
- package/src/engine/session/instruction_loader.ts +54 -0
- package/src/engine/session/llm.ts +459 -0
- package/src/engine/session/message-error.ts +14 -0
- package/src/engine/session/message-v2.ts +1202 -0
- package/src/engine/session/message.ts +146 -0
- package/src/engine/session/overflow.ts +32 -0
- package/src/engine/session/overflow_check.ts +46 -0
- package/src/engine/session/processor.ts +823 -0
- package/src/engine/session/prompt/anthropic.txt +105 -0
- package/src/engine/session/prompt/beast.txt +147 -0
- package/src/engine/session/prompt/build-switch.txt +5 -0
- package/src/engine/session/prompt/codex.txt +79 -0
- package/src/engine/session/prompt/copilot-gpt-5.txt +143 -0
- package/src/engine/session/prompt/default.txt +105 -0
- package/src/engine/session/prompt/gemini.txt +155 -0
- package/src/engine/session/prompt/gpt.txt +107 -0
- package/src/engine/session/prompt/kimi.txt +95 -0
- package/src/engine/session/prompt/max-steps.txt +16 -0
- package/src/engine/session/prompt/plan-reminder-anthropic.txt +67 -0
- package/src/engine/session/prompt/plan.txt +26 -0
- package/src/engine/session/prompt/trinity.txt +97 -0
- package/src/engine/session/prompt.ts +671 -0
- package/src/engine/session/provider_transform.ts +187 -0
- package/src/engine/session/retry.ts +200 -0
- package/src/engine/session/retry_logic.ts +65 -0
- package/src/engine/session/revert.ts +162 -0
- package/src/engine/session/run-state.ts +153 -0
- package/src/engine/session/schema.ts +26 -0
- package/src/engine/session/session.sql.ts +137 -0
- package/src/engine/session/session.ts +1011 -0
- package/src/engine/session/status.ts +94 -0
- package/src/engine/session/summary.ts +164 -0
- package/src/engine/session/system.ts +84 -0
- package/src/engine/session/system_prompt.ts +65 -0
- package/src/engine/session/todo.ts +81 -0
- package/src/engine/session/tool_registry.ts +162 -0
- package/src/engine/share/session.ts +61 -0
- package/src/engine/share/share-next.ts +376 -0
- package/src/engine/share/share.sql.ts +13 -0
- package/src/engine/shell/shell/shell.ts +215 -0
- package/src/engine/shell/shell.ts +215 -0
- package/src/engine/skill/discovery.ts +116 -0
- package/src/engine/skill/index.ts +336 -0
- package/src/engine/skill/prompt/customize-opencode.md +377 -0
- package/src/engine/skill/skill/discovery.ts +116 -0
- package/src/engine/skill/skill/index.ts +336 -0
- package/src/engine/skill/skill/prompt/customize-opencode.md +377 -0
- package/src/engine/snapshot/index.ts +762 -0
- package/src/engine/snapshot/snapshot/index.ts +762 -0
- package/src/engine/sync/README.md +179 -0
- package/src/engine/sync/event.sql.ts +17 -0
- package/src/engine/sync/index.ts +410 -0
- package/src/engine/sync/schema.ts +11 -0
- package/src/engine/temporary.ts +33 -0
- package/src/engine/tool/apply_patch.ts +313 -0
- package/src/engine/tool/apply_patch.txt +33 -0
- package/src/engine/tool/edit.ts +711 -0
- package/src/engine/tool/edit.txt +10 -0
- package/src/engine/tool/external-directory.ts +49 -0
- package/src/engine/tool/glob.ts +103 -0
- package/src/engine/tool/glob.txt +6 -0
- package/src/engine/tool/grep.ts +156 -0
- package/src/engine/tool/grep.txt +8 -0
- package/src/engine/tool/invalid.ts +21 -0
- package/src/engine/tool/json-schema.ts +164 -0
- package/src/engine/tool/lsp.ts +113 -0
- package/src/engine/tool/lsp.txt +24 -0
- package/src/engine/tool/mcp-websearch.ts +96 -0
- package/src/engine/tool/plan-enter.txt +14 -0
- package/src/engine/tool/plan-exit.txt +13 -0
- package/src/engine/tool/plan.ts +78 -0
- package/src/engine/tool/question.ts +44 -0
- package/src/engine/tool/question.txt +10 -0
- package/src/engine/tool/read.ts +337 -0
- package/src/engine/tool/read.txt +14 -0
- package/src/engine/tool/registry.ts +472 -0
- package/src/engine/tool/repo_clone.ts +80 -0
- package/src/engine/tool/repo_clone.txt +5 -0
- package/src/engine/tool/repo_overview.ts +279 -0
- package/src/engine/tool/repo_overview.txt +4 -0
- package/src/engine/tool/schema.ts +14 -0
- package/src/engine/tool/shell/id.ts +19 -0
- package/src/engine/tool/shell/prompt.ts +295 -0
- package/src/engine/tool/shell/shell.txt +77 -0
- package/src/engine/tool/shell.ts +647 -0
- package/src/engine/tool/skill.ts +75 -0
- package/src/engine/tool/skill.txt +5 -0
- package/src/engine/tool/task.ts +337 -0
- package/src/engine/tool/task.txt +58 -0
- package/src/engine/tool/task_status.ts +179 -0
- package/src/engine/tool/task_status.txt +13 -0
- package/src/engine/tool/todo.ts +57 -0
- package/src/engine/tool/todowrite.txt +167 -0
- package/src/engine/tool/tool/apply_patch.ts +313 -0
- package/src/engine/tool/tool/apply_patch.txt +33 -0
- package/src/engine/tool/tool/edit.ts +711 -0
- package/src/engine/tool/tool/edit.txt +10 -0
- package/src/engine/tool/tool/external-directory.ts +49 -0
- package/src/engine/tool/tool/glob.ts +103 -0
- package/src/engine/tool/tool/glob.txt +6 -0
- package/src/engine/tool/tool/grep.ts +156 -0
- package/src/engine/tool/tool/grep.txt +8 -0
- package/src/engine/tool/tool/invalid.ts +21 -0
- package/src/engine/tool/tool/json-schema.ts +164 -0
- package/src/engine/tool/tool/lsp.ts +113 -0
- package/src/engine/tool/tool/lsp.txt +24 -0
- package/src/engine/tool/tool/mcp-websearch.ts +96 -0
- package/src/engine/tool/tool/plan-enter.txt +14 -0
- package/src/engine/tool/tool/plan-exit.txt +13 -0
- package/src/engine/tool/tool/plan.ts +78 -0
- package/src/engine/tool/tool/question.ts +44 -0
- package/src/engine/tool/tool/question.txt +10 -0
- package/src/engine/tool/tool/read.ts +337 -0
- package/src/engine/tool/tool/read.txt +14 -0
- package/src/engine/tool/tool/registry.ts +472 -0
- package/src/engine/tool/tool/repo_clone.ts +80 -0
- package/src/engine/tool/tool/repo_clone.txt +5 -0
- package/src/engine/tool/tool/repo_overview.ts +279 -0
- package/src/engine/tool/tool/repo_overview.txt +4 -0
- package/src/engine/tool/tool/schema.ts +14 -0
- package/src/engine/tool/tool/shell/id.ts +19 -0
- package/src/engine/tool/tool/shell/prompt.ts +295 -0
- package/src/engine/tool/tool/shell/shell.txt +77 -0
- package/src/engine/tool/tool/shell.ts +647 -0
- package/src/engine/tool/tool/skill.ts +75 -0
- package/src/engine/tool/tool/skill.txt +5 -0
- package/src/engine/tool/tool/task.ts +337 -0
- package/src/engine/tool/tool/task.txt +58 -0
- package/src/engine/tool/tool/task_status.ts +179 -0
- package/src/engine/tool/tool/task_status.txt +13 -0
- package/src/engine/tool/tool/todo.ts +57 -0
- package/src/engine/tool/tool/todowrite.txt +167 -0
- package/src/engine/tool/tool/tool.ts +164 -0
- package/src/engine/tool/tool/truncate.ts +160 -0
- package/src/engine/tool/tool/truncation-dir.ts +4 -0
- package/src/engine/tool/tool/webfetch.ts +192 -0
- package/src/engine/tool/tool/webfetch.txt +13 -0
- package/src/engine/tool/tool/websearch.ts +143 -0
- package/src/engine/tool/tool/websearch.txt +14 -0
- package/src/engine/tool/tool/write.ts +104 -0
- package/src/engine/tool/tool/write.txt +8 -0
- package/src/engine/tool/tool.ts +164 -0
- package/src/engine/tool/truncate.ts +160 -0
- package/src/engine/tool/truncation-dir.ts +4 -0
- package/src/engine/tool/webfetch.ts +192 -0
- package/src/engine/tool/webfetch.txt +13 -0
- package/src/engine/tool/websearch.ts +143 -0
- package/src/engine/tool/websearch.txt +14 -0
- package/src/engine/tool/write.ts +104 -0
- package/src/engine/tool/write.txt +8 -0
- package/src/engine/util/archive.ts +17 -0
- package/src/engine/util/bom.ts +31 -0
- package/src/engine/util/data-url.ts +9 -0
- package/src/engine/util/defer.ts +10 -0
- package/src/engine/util/effect-http-client.ts +11 -0
- package/src/engine/util/error.ts +88 -0
- package/src/engine/util/filesystem.ts +252 -0
- package/src/engine/util/format.ts +20 -0
- package/src/engine/util/iife.ts +3 -0
- package/src/engine/util/lazy.ts +20 -0
- package/src/engine/util/local-context.ts +25 -0
- package/src/engine/util/locale.ts +86 -0
- package/src/engine/util/media.ts +26 -0
- package/src/engine/util/process.ts +176 -0
- package/src/engine/util/queue.ts +32 -0
- package/src/engine/util/record.ts +3 -0
- package/src/engine/util/repository.ts +158 -0
- package/src/engine/util/rpc.ts +66 -0
- package/src/engine/util/signal.ts +12 -0
- package/src/engine/util/timeout.ts +13 -0
- package/src/engine/util/token.ts +7 -0
- package/src/engine/util/util/archive.ts +17 -0
- package/src/engine/util/util/bom.ts +31 -0
- package/src/engine/util/util/data-url.ts +9 -0
- package/src/engine/util/util/defer.ts +10 -0
- package/src/engine/util/util/effect-http-client.ts +11 -0
- package/src/engine/util/util/error.ts +88 -0
- package/src/engine/util/util/filesystem.ts +252 -0
- package/src/engine/util/util/format.ts +20 -0
- package/src/engine/util/util/iife.ts +3 -0
- package/src/engine/util/util/lazy.ts +20 -0
- package/src/engine/util/util/local-context.ts +25 -0
- package/src/engine/util/util/locale.ts +86 -0
- package/src/engine/util/util/media.ts +26 -0
- package/src/engine/util/util/process.ts +176 -0
- package/src/engine/util/util/queue.ts +32 -0
- package/src/engine/util/util/record.ts +3 -0
- package/src/engine/util/util/repository.ts +158 -0
- package/src/engine/util/util/rpc.ts +66 -0
- package/src/engine/util/util/signal.ts +12 -0
- package/src/engine/util/util/timeout.ts +13 -0
- package/src/engine/util/util/token.ts +7 -0
- package/src/engine/util/util/which.ts +14 -0
- package/src/engine/util/util/wildcard.ts +59 -0
- package/src/engine/util/which.ts +14 -0
- package/src/engine/util/wildcard.ts +59 -0
- package/src/engine/worktree/index.ts +621 -0
- package/src/rag_worker.ts +519 -0
- package/src/server.ts +201 -0
- package/src/tui.ts +637 -0
- package/tsconfig.json +24 -0
|
@@ -0,0 +1,326 @@
|
|
|
1
|
+
// Generated by BoneScript compiler. DO NOT EDIT.
|
|
2
|
+
// Regression tests derived from capability declarations.
|
|
3
|
+
// Run: npx ts-node src/tests.ts
|
|
4
|
+
|
|
5
|
+
import * as http from "http";
|
|
6
|
+
|
|
7
|
+
const BASE_URL = process.env.TEST_BASE_URL || "http://localhost:3000";
|
|
8
|
+
const AUTH_TOKEN = process.env.TEST_AUTH_TOKEN || "";
|
|
9
|
+
|
|
10
|
+
let passed = 0;
|
|
11
|
+
let failed = 0;
|
|
12
|
+
|
|
13
|
+
async function request(method: string, path: string, body?: any): Promise<{ status: number; data: any }> {
|
|
14
|
+
const url = new URL(path, BASE_URL);
|
|
15
|
+
const res = await fetch(url.toString(), {
|
|
16
|
+
method,
|
|
17
|
+
headers: {
|
|
18
|
+
"Content-Type": "application/json",
|
|
19
|
+
...(AUTH_TOKEN ? { "Authorization": `Bearer ${AUTH_TOKEN}` } : {}),
|
|
20
|
+
},
|
|
21
|
+
body: body ? JSON.stringify(body) : undefined,
|
|
22
|
+
});
|
|
23
|
+
const data = await res.json().catch(() => ({}));
|
|
24
|
+
return { status: res.status, data };
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
async function test(name: string, fn: () => Promise<void>): Promise<void> {
|
|
28
|
+
try {
|
|
29
|
+
await fn();
|
|
30
|
+
console.log(` ✓ ${name}`);
|
|
31
|
+
passed++;
|
|
32
|
+
} catch (e: any) {
|
|
33
|
+
console.log(` ✗ ${name}: ${e.message}`);
|
|
34
|
+
failed++;
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
function assert(condition: boolean, message: string): void {
|
|
39
|
+
if (!condition) throw new Error(message);
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
(async () => {
|
|
43
|
+
// ─── ProjectService Tests ─────────────────────────────────────────────────────
|
|
44
|
+
|
|
45
|
+
console.log("\nProjectService — CRUD");
|
|
46
|
+
|
|
47
|
+
let __project_id: string;
|
|
48
|
+
|
|
49
|
+
await test("POST /projects — creates entity", async () => {
|
|
50
|
+
const { status, data } = await request("POST", "/projects", {"root_commit_hash":"test_value","worktree":"test_value","vcs":"test_value","name":"test_value","sandboxes":{}});
|
|
51
|
+
assert(status === 201, `Expected 201, got ${status}: ${JSON.stringify(data)}`);
|
|
52
|
+
assert(data.id, "Response must have id");
|
|
53
|
+
__project_id = data.id;
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
await test("GET /projects/:id — reads entity", async () => {
|
|
57
|
+
const { status, data } = await request("GET", `/projects/${__project_id}`);
|
|
58
|
+
assert(status === 200, `Expected 200, got ${status}`);
|
|
59
|
+
assert(data.id === __project_id, "ID must match");
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
await test("GET /projects — lists entities", async () => {
|
|
63
|
+
const { status, data } = await request("GET", "/projects");
|
|
64
|
+
assert(status === 200, `Expected 200, got ${status}`);
|
|
65
|
+
assert(Array.isArray(data.items), "Response must have items array");
|
|
66
|
+
assert(typeof data.total === "number", "Response must have total");
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
await test("GET /projects — rejects unauthenticated", async () => {
|
|
70
|
+
const res = await fetch(`${BASE_URL}/projects`);
|
|
71
|
+
assert(res.status === 401, `Expected 401, got ${res.status}`);
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
await test("DELETE /projects/:id — deletes entity", async () => {
|
|
75
|
+
const { status } = await request("DELETE", `/projects/${__project_id}`);
|
|
76
|
+
assert(status === 204, `Expected 204, got ${status}`);
|
|
77
|
+
});
|
|
78
|
+
|
|
79
|
+
await test("GET /projects/:id — returns 404 after delete", async () => {
|
|
80
|
+
const { status } = await request("GET", `/projects/${__project_id}`);
|
|
81
|
+
assert(status === 404, `Expected 404, got ${status}`);
|
|
82
|
+
});
|
|
83
|
+
|
|
84
|
+
// ─── SessionService Tests ─────────────────────────────────────────────────────
|
|
85
|
+
|
|
86
|
+
console.log("\nSessionService — CRUD");
|
|
87
|
+
|
|
88
|
+
let __session_id: string;
|
|
89
|
+
|
|
90
|
+
await test("POST /sessions — creates entity", async () => {
|
|
91
|
+
const { status, data } = await request("POST", "/sessions", {"slug":"test_value","project_id":"00000000-0000-0000-0000-000000000001","workspace_id":null,"parent_id":null,"directory":"test_value","title":"test_value","version":"test_value","share_url":null,"summary_additions":null,"summary_deletions":null,"summary_files":null,"summary_diffs":null,"revert_data":null,"permission_ruleset":null});
|
|
92
|
+
assert(status === 201, `Expected 201, got ${status}: ${JSON.stringify(data)}`);
|
|
93
|
+
assert(data.id, "Response must have id");
|
|
94
|
+
__session_id = data.id;
|
|
95
|
+
});
|
|
96
|
+
|
|
97
|
+
await test("GET /sessions/:id — reads entity", async () => {
|
|
98
|
+
const { status, data } = await request("GET", `/sessions/${__session_id}`);
|
|
99
|
+
assert(status === 200, `Expected 200, got ${status}`);
|
|
100
|
+
assert(data.id === __session_id, "ID must match");
|
|
101
|
+
});
|
|
102
|
+
|
|
103
|
+
await test("GET /sessions — lists entities", async () => {
|
|
104
|
+
const { status, data } = await request("GET", "/sessions");
|
|
105
|
+
assert(status === 200, `Expected 200, got ${status}`);
|
|
106
|
+
assert(Array.isArray(data.items), "Response must have items array");
|
|
107
|
+
assert(typeof data.total === "number", "Response must have total");
|
|
108
|
+
});
|
|
109
|
+
|
|
110
|
+
await test("GET /sessions — rejects unauthenticated", async () => {
|
|
111
|
+
const res = await fetch(`${BASE_URL}/sessions`);
|
|
112
|
+
assert(res.status === 401, `Expected 401, got ${res.status}`);
|
|
113
|
+
});
|
|
114
|
+
|
|
115
|
+
await test("POST /sessions/archive-session — capability executes", async () => {
|
|
116
|
+
const { status, data } = await request("POST", "/sessions/archive-session", {
|
|
117
|
+
session_id: __session_id,
|
|
118
|
+
});
|
|
119
|
+
// Capability may return 200 (success) or 422 (precondition failed) — both are valid
|
|
120
|
+
assert([200, 422].includes(status), `Expected 200 or 422, got ${status}: ${JSON.stringify(data)}`);
|
|
121
|
+
});
|
|
122
|
+
|
|
123
|
+
await test("POST /sessions/archive-session — returns 401 without auth", async () => {
|
|
124
|
+
const res = await fetch(`${BASE_URL}/sessions/archive-session`, { method: "POST" });
|
|
125
|
+
assert(res.status === 401, `Expected 401, got ${res.status}`);
|
|
126
|
+
});
|
|
127
|
+
|
|
128
|
+
await test("POST /sessions/delete-session — capability executes", async () => {
|
|
129
|
+
const { status, data } = await request("POST", "/sessions/delete-session", {
|
|
130
|
+
session_id: __session_id,
|
|
131
|
+
});
|
|
132
|
+
// Capability may return 200 (success) or 422 (precondition failed) — both are valid
|
|
133
|
+
assert([200, 422].includes(status), `Expected 200 or 422, got ${status}: ${JSON.stringify(data)}`);
|
|
134
|
+
});
|
|
135
|
+
|
|
136
|
+
await test("POST /sessions/delete-session — returns 401 without auth", async () => {
|
|
137
|
+
const res = await fetch(`${BASE_URL}/sessions/delete-session`, { method: "POST" });
|
|
138
|
+
assert(res.status === 401, `Expected 401, got ${res.status}`);
|
|
139
|
+
});
|
|
140
|
+
|
|
141
|
+
await test("POST /sessions/add-message — capability executes", async () => {
|
|
142
|
+
const { status, data } = await request("POST", "/sessions/add-message", {
|
|
143
|
+
session_id: __session_id,
|
|
144
|
+
});
|
|
145
|
+
// Capability may return 200 (success) or 422 (precondition failed) — both are valid
|
|
146
|
+
assert([200, 422].includes(status), `Expected 200 or 422, got ${status}: ${JSON.stringify(data)}`);
|
|
147
|
+
});
|
|
148
|
+
|
|
149
|
+
await test("POST /sessions/add-message — returns 401 without auth", async () => {
|
|
150
|
+
const res = await fetch(`${BASE_URL}/sessions/add-message`, { method: "POST" });
|
|
151
|
+
assert(res.status === 401, `Expected 401, got ${res.status}`);
|
|
152
|
+
});
|
|
153
|
+
|
|
154
|
+
await test("POST /sessions/update-part — capability executes", async () => {
|
|
155
|
+
const { status, data } = await request("POST", "/sessions/update-part", {
|
|
156
|
+
session_id: __session_id,
|
|
157
|
+
});
|
|
158
|
+
// Capability may return 200 (success) or 422 (precondition failed) — both are valid
|
|
159
|
+
assert([200, 422].includes(status), `Expected 200 or 422, got ${status}: ${JSON.stringify(data)}`);
|
|
160
|
+
});
|
|
161
|
+
|
|
162
|
+
await test("POST /sessions/update-part — returns 401 without auth", async () => {
|
|
163
|
+
const res = await fetch(`${BASE_URL}/sessions/update-part`, { method: "POST" });
|
|
164
|
+
assert(res.status === 401, `Expected 401, got ${res.status}`);
|
|
165
|
+
});
|
|
166
|
+
|
|
167
|
+
await test("POST /sessions/compact-session — capability executes", async () => {
|
|
168
|
+
const { status, data } = await request("POST", "/sessions/compact-session", {
|
|
169
|
+
session_id: __session_id,
|
|
170
|
+
});
|
|
171
|
+
// Capability may return 200 (success) or 422 (precondition failed) — both are valid
|
|
172
|
+
assert([200, 422].includes(status), `Expected 200 or 422, got ${status}: ${JSON.stringify(data)}`);
|
|
173
|
+
});
|
|
174
|
+
|
|
175
|
+
await test("POST /sessions/compact-session — returns 401 without auth", async () => {
|
|
176
|
+
const res = await fetch(`${BASE_URL}/sessions/compact-session`, { method: "POST" });
|
|
177
|
+
assert(res.status === 401, `Expected 401, got ${res.status}`);
|
|
178
|
+
});
|
|
179
|
+
|
|
180
|
+
// State machine: Session
|
|
181
|
+
await test("PUT /sessions/:id — rejects invalid state transition", async () => {
|
|
182
|
+
const { status, data } = await request("PUT", `/sessions/${__session_id}`, {
|
|
183
|
+
state: "__invalid_state__",
|
|
184
|
+
});
|
|
185
|
+
assert(status === 422, `Expected 422 for invalid transition, got ${status}`);
|
|
186
|
+
assert(data.error?.code === "INVALID_TRANSITION", "Error code must be INVALID_TRANSITION");
|
|
187
|
+
});
|
|
188
|
+
|
|
189
|
+
await test("DELETE /sessions/:id — deletes entity", async () => {
|
|
190
|
+
const { status } = await request("DELETE", `/sessions/${__session_id}`);
|
|
191
|
+
assert(status === 204, `Expected 204, got ${status}`);
|
|
192
|
+
});
|
|
193
|
+
|
|
194
|
+
await test("GET /sessions/:id — returns 404 after delete", async () => {
|
|
195
|
+
const { status } = await request("GET", `/sessions/${__session_id}`);
|
|
196
|
+
assert(status === 404, `Expected 404, got ${status}`);
|
|
197
|
+
});
|
|
198
|
+
|
|
199
|
+
// ─── MessageService Tests ─────────────────────────────────────────────────────
|
|
200
|
+
|
|
201
|
+
console.log("\nMessageService — CRUD");
|
|
202
|
+
|
|
203
|
+
let __message_id: string;
|
|
204
|
+
|
|
205
|
+
await test("POST /messages — creates entity", async () => {
|
|
206
|
+
const { status, data } = await request("POST", "/messages", {"session_id":"00000000-0000-0000-0000-000000000001","role":"test_value","model_id":null,"provider_id":null,"tokens_input":null,"tokens_output":null,"cost_usd":null,"error":null});
|
|
207
|
+
assert(status === 201, `Expected 201, got ${status}: ${JSON.stringify(data)}`);
|
|
208
|
+
assert(data.id, "Response must have id");
|
|
209
|
+
__message_id = data.id;
|
|
210
|
+
});
|
|
211
|
+
|
|
212
|
+
await test("GET /messages/:id — reads entity", async () => {
|
|
213
|
+
const { status, data } = await request("GET", `/messages/${__message_id}`);
|
|
214
|
+
assert(status === 200, `Expected 200, got ${status}`);
|
|
215
|
+
assert(data.id === __message_id, "ID must match");
|
|
216
|
+
});
|
|
217
|
+
|
|
218
|
+
await test("GET /messages — lists entities", async () => {
|
|
219
|
+
const { status, data } = await request("GET", "/messages");
|
|
220
|
+
assert(status === 200, `Expected 200, got ${status}`);
|
|
221
|
+
assert(Array.isArray(data.items), "Response must have items array");
|
|
222
|
+
assert(typeof data.total === "number", "Response must have total");
|
|
223
|
+
});
|
|
224
|
+
|
|
225
|
+
await test("GET /messages — rejects unauthenticated", async () => {
|
|
226
|
+
const res = await fetch(`${BASE_URL}/messages`);
|
|
227
|
+
assert(res.status === 401, `Expected 401, got ${res.status}`);
|
|
228
|
+
});
|
|
229
|
+
|
|
230
|
+
await test("DELETE /messages/:id — deletes entity", async () => {
|
|
231
|
+
const { status } = await request("DELETE", `/messages/${__message_id}`);
|
|
232
|
+
assert(status === 204, `Expected 204, got ${status}`);
|
|
233
|
+
});
|
|
234
|
+
|
|
235
|
+
await test("GET /messages/:id — returns 404 after delete", async () => {
|
|
236
|
+
const { status } = await request("GET", `/messages/${__message_id}`);
|
|
237
|
+
assert(status === 404, `Expected 404, got ${status}`);
|
|
238
|
+
});
|
|
239
|
+
|
|
240
|
+
// ─── PartService Tests ─────────────────────────────────────────────────────
|
|
241
|
+
|
|
242
|
+
console.log("\nPartService — CRUD");
|
|
243
|
+
|
|
244
|
+
let __part_id: string;
|
|
245
|
+
|
|
246
|
+
await test("POST /parts — creates entity", async () => {
|
|
247
|
+
const { status, data } = await request("POST", "/parts", {"message_id":"00000000-0000-0000-0000-000000000001","session_id":"00000000-0000-0000-0000-000000000001","part_type":"test_value","data":{},"order_index":1});
|
|
248
|
+
assert(status === 201, `Expected 201, got ${status}: ${JSON.stringify(data)}`);
|
|
249
|
+
assert(data.id, "Response must have id");
|
|
250
|
+
__part_id = data.id;
|
|
251
|
+
});
|
|
252
|
+
|
|
253
|
+
await test("GET /parts/:id — reads entity", async () => {
|
|
254
|
+
const { status, data } = await request("GET", `/parts/${__part_id}`);
|
|
255
|
+
assert(status === 200, `Expected 200, got ${status}`);
|
|
256
|
+
assert(data.id === __part_id, "ID must match");
|
|
257
|
+
});
|
|
258
|
+
|
|
259
|
+
await test("GET /parts — lists entities", async () => {
|
|
260
|
+
const { status, data } = await request("GET", "/parts");
|
|
261
|
+
assert(status === 200, `Expected 200, got ${status}`);
|
|
262
|
+
assert(Array.isArray(data.items), "Response must have items array");
|
|
263
|
+
assert(typeof data.total === "number", "Response must have total");
|
|
264
|
+
});
|
|
265
|
+
|
|
266
|
+
await test("GET /parts — rejects unauthenticated", async () => {
|
|
267
|
+
const res = await fetch(`${BASE_URL}/parts`);
|
|
268
|
+
assert(res.status === 401, `Expected 401, got ${res.status}`);
|
|
269
|
+
});
|
|
270
|
+
|
|
271
|
+
await test("DELETE /parts/:id — deletes entity", async () => {
|
|
272
|
+
const { status } = await request("DELETE", `/parts/${__part_id}`);
|
|
273
|
+
assert(status === 204, `Expected 204, got ${status}`);
|
|
274
|
+
});
|
|
275
|
+
|
|
276
|
+
await test("GET /parts/:id — returns 404 after delete", async () => {
|
|
277
|
+
const { status } = await request("GET", `/parts/${__part_id}`);
|
|
278
|
+
assert(status === 404, `Expected 404, got ${status}`);
|
|
279
|
+
});
|
|
280
|
+
|
|
281
|
+
// ─── PermissionService Tests ─────────────────────────────────────────────────────
|
|
282
|
+
|
|
283
|
+
console.log("\nPermissionService — CRUD");
|
|
284
|
+
|
|
285
|
+
let __permission_id: string;
|
|
286
|
+
|
|
287
|
+
await test("POST /permissions — creates entity", async () => {
|
|
288
|
+
const { status, data } = await request("POST", "/permissions", {"session_id":"00000000-0000-0000-0000-000000000001","tool_name":"test_value","pattern":null,"decision":"test_value","expires_at":null});
|
|
289
|
+
assert(status === 201, `Expected 201, got ${status}: ${JSON.stringify(data)}`);
|
|
290
|
+
assert(data.id, "Response must have id");
|
|
291
|
+
__permission_id = data.id;
|
|
292
|
+
});
|
|
293
|
+
|
|
294
|
+
await test("GET /permissions/:id — reads entity", async () => {
|
|
295
|
+
const { status, data } = await request("GET", `/permissions/${__permission_id}`);
|
|
296
|
+
assert(status === 200, `Expected 200, got ${status}`);
|
|
297
|
+
assert(data.id === __permission_id, "ID must match");
|
|
298
|
+
});
|
|
299
|
+
|
|
300
|
+
await test("GET /permissions — lists entities", async () => {
|
|
301
|
+
const { status, data } = await request("GET", "/permissions");
|
|
302
|
+
assert(status === 200, `Expected 200, got ${status}`);
|
|
303
|
+
assert(Array.isArray(data.items), "Response must have items array");
|
|
304
|
+
assert(typeof data.total === "number", "Response must have total");
|
|
305
|
+
});
|
|
306
|
+
|
|
307
|
+
await test("GET /permissions — rejects unauthenticated", async () => {
|
|
308
|
+
const res = await fetch(`${BASE_URL}/permissions`);
|
|
309
|
+
assert(res.status === 401, `Expected 401, got ${res.status}`);
|
|
310
|
+
});
|
|
311
|
+
|
|
312
|
+
await test("DELETE /permissions/:id — deletes entity", async () => {
|
|
313
|
+
const { status } = await request("DELETE", `/permissions/${__permission_id}`);
|
|
314
|
+
assert(status === 204, `Expected 204, got ${status}`);
|
|
315
|
+
});
|
|
316
|
+
|
|
317
|
+
await test("GET /permissions/:id — returns 404 after delete", async () => {
|
|
318
|
+
const { status } = await request("GET", `/permissions/${__permission_id}`);
|
|
319
|
+
assert(status === 404, `Expected 404, got ${status}`);
|
|
320
|
+
});
|
|
321
|
+
|
|
322
|
+
console.log(`\n════════════════════════════════════════`);
|
|
323
|
+
console.log(`Results: ${passed} passed, ${failed} failed`);
|
|
324
|
+
console.log("═".repeat(40));
|
|
325
|
+
if (failed > 0) process.exit(1);
|
|
326
|
+
})().catch(e => { console.error(e); process.exit(1); });
|
|
@@ -0,0 +1,201 @@
|
|
|
1
|
+
// Generated by BoneScript compiler. DO NOT EDIT.
|
|
2
|
+
// WebSocket server for realtime channels
|
|
3
|
+
|
|
4
|
+
import { WebSocketServer, WebSocket } from "ws";
|
|
5
|
+
import { IncomingMessage, Server } from "http";
|
|
6
|
+
import jwt from "jsonwebtoken";
|
|
7
|
+
import { eventBus } from "./events";
|
|
8
|
+
import { logger } from "./logger";
|
|
9
|
+
|
|
10
|
+
const JWT_SECRET = process.env.JWT_SECRET || "bonescript-dev-secret-change-in-production";
|
|
11
|
+
|
|
12
|
+
// Redis pub/sub for multi-instance WebSocket broadcasting
|
|
13
|
+
let redisSub: any = null;
|
|
14
|
+
let redisPub: any = null;
|
|
15
|
+
if (process.env.REDIS_URL) {
|
|
16
|
+
try {
|
|
17
|
+
const { createClient } = require("redis");
|
|
18
|
+
redisSub = createClient({ url: process.env.REDIS_URL });
|
|
19
|
+
redisPub = createClient({ url: process.env.REDIS_URL });
|
|
20
|
+
Promise.all([redisSub.connect(), redisPub.connect()]).then(() => {
|
|
21
|
+
logger.info("redis_connected", { event: "startup" });
|
|
22
|
+
}).catch((e: any) => {
|
|
23
|
+
logger.error("redis_connect_failed", { event: "startup", metadata: { error: e.message } });
|
|
24
|
+
redisSub = null; redisPub = null;
|
|
25
|
+
});
|
|
26
|
+
} catch { redisSub = null; redisPub = null; }
|
|
27
|
+
}
|
|
28
|
+
interface Client {
|
|
29
|
+
socket: WebSocket;
|
|
30
|
+
user_id: string;
|
|
31
|
+
channel: string;
|
|
32
|
+
topics: Set<string>;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
const clients: Map<string, Set<Client>> = new Map();
|
|
36
|
+
|
|
37
|
+
const CHANNELS: Record<string, { ordering: string; persistence: string; max_size: number }> = {
|
|
38
|
+
"session_events": {
|
|
39
|
+
ordering: "causal",
|
|
40
|
+
persistence: "last_1000",
|
|
41
|
+
max_size: 100000,
|
|
42
|
+
},
|
|
43
|
+
"part_stream": {
|
|
44
|
+
ordering: "fifo",
|
|
45
|
+
persistence: "last_100",
|
|
46
|
+
max_size: 10000,
|
|
47
|
+
},
|
|
48
|
+
};
|
|
49
|
+
|
|
50
|
+
const messageBuffers: Map<string, any[]> = new Map();
|
|
51
|
+
|
|
52
|
+
function getBuffer(channel: string): any[] {
|
|
53
|
+
const buf = messageBuffers.get(channel);
|
|
54
|
+
if (buf) return buf;
|
|
55
|
+
const fresh: any[] = [];
|
|
56
|
+
messageBuffers.set(channel, fresh);
|
|
57
|
+
return fresh;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
function persistMessage(channel: string, msg: any) {
|
|
61
|
+
const cfg = CHANNELS[channel];
|
|
62
|
+
if (!cfg || cfg.persistence === "none") return;
|
|
63
|
+
const buf = getBuffer(channel);
|
|
64
|
+
buf.push(msg);
|
|
65
|
+
|
|
66
|
+
// Honor persistence config (last_N, full)
|
|
67
|
+
const match = cfg.persistence.match(/^last_(\d+)$/);
|
|
68
|
+
if (match) {
|
|
69
|
+
const limit = parseInt(match[1], 10);
|
|
70
|
+
while (buf.length > limit) buf.shift();
|
|
71
|
+
} else if (buf.length > cfg.max_size) {
|
|
72
|
+
buf.shift();
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
export function setupWebSocketServer(httpServer: Server): WebSocketServer {
|
|
77
|
+
const wss = new WebSocketServer({ server: httpServer, path: "/ws" });
|
|
78
|
+
|
|
79
|
+
wss.on("connection", (socket: WebSocket, req: IncomingMessage) => {
|
|
80
|
+
const url = new URL(req.url || "/", `http://${req.headers.host}`);
|
|
81
|
+
const channel = url.searchParams.get("channel") || "";
|
|
82
|
+
const token = url.searchParams.get("token") || "";
|
|
83
|
+
|
|
84
|
+
if (!CHANNELS[channel]) {
|
|
85
|
+
socket.send(JSON.stringify({ type: "error", message: "Unknown channel: " + channel }));
|
|
86
|
+
socket.close();
|
|
87
|
+
return;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
let userId: string;
|
|
91
|
+
try {
|
|
92
|
+
const decoded = jwt.verify(token, JWT_SECRET) as { sub: string };
|
|
93
|
+
userId = decoded.sub;
|
|
94
|
+
} catch {
|
|
95
|
+
socket.send(JSON.stringify({ type: "error", message: "Authentication failed" }));
|
|
96
|
+
socket.close();
|
|
97
|
+
return;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
const client: Client = { socket, user_id: userId, channel, topics: new Set() };
|
|
101
|
+
const set = clients.get(channel) || new Set();
|
|
102
|
+
set.add(client);
|
|
103
|
+
clients.set(channel, set);
|
|
104
|
+
|
|
105
|
+
console.log(`[ws] User ${userId} connected to ${channel} (${set.size} active)`);
|
|
106
|
+
|
|
107
|
+
// Send buffered history
|
|
108
|
+
const history = messageBuffers.get(channel) || [];
|
|
109
|
+
for (const msg of history) {
|
|
110
|
+
socket.send(JSON.stringify(msg));
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
socket.send(JSON.stringify({ type: "connected", channel, history_size: history.length }));
|
|
114
|
+
|
|
115
|
+
socket.on("message", (data) => {
|
|
116
|
+
try {
|
|
117
|
+
const msg = JSON.parse(data.toString());
|
|
118
|
+
|
|
119
|
+
if (msg.type === "subscribe" && msg.topic) {
|
|
120
|
+
client.topics.add(msg.topic);
|
|
121
|
+
return;
|
|
122
|
+
}
|
|
123
|
+
if (msg.type === "unsubscribe" && msg.topic) {
|
|
124
|
+
client.topics.delete(msg.topic);
|
|
125
|
+
return;
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
// Broadcast
|
|
129
|
+
const broadcast = {
|
|
130
|
+
type: msg.type || "message",
|
|
131
|
+
payload: msg.payload || msg,
|
|
132
|
+
from: userId,
|
|
133
|
+
timestamp: new Date().toISOString(),
|
|
134
|
+
};
|
|
135
|
+
|
|
136
|
+
persistMessage(channel, broadcast);
|
|
137
|
+
broadcastToChannel(channel, broadcast, client);
|
|
138
|
+
} catch (e: any) {
|
|
139
|
+
socket.send(JSON.stringify({ type: "error", message: e.message }));
|
|
140
|
+
}
|
|
141
|
+
});
|
|
142
|
+
|
|
143
|
+
socket.on("close", () => {
|
|
144
|
+
const set = clients.get(channel);
|
|
145
|
+
if (set) set.delete(client);
|
|
146
|
+
console.log(`[ws] User ${userId} disconnected from ${channel}`);
|
|
147
|
+
});
|
|
148
|
+
|
|
149
|
+
// Heartbeat
|
|
150
|
+
const heartbeat = setInterval(() => {
|
|
151
|
+
if (socket.readyState === WebSocket.OPEN) {
|
|
152
|
+
socket.ping();
|
|
153
|
+
} else {
|
|
154
|
+
clearInterval(heartbeat);
|
|
155
|
+
}
|
|
156
|
+
}, 30000);
|
|
157
|
+
});
|
|
158
|
+
|
|
159
|
+
// Bridge: forward eventBus events to WebSocket clients
|
|
160
|
+
// Channel 'session_events' bridge
|
|
161
|
+
// Channel 'part_stream' bridge
|
|
162
|
+
|
|
163
|
+
// Subscribe to Redis channels for cross-instance delivery
|
|
164
|
+
if (redisSub) {
|
|
165
|
+
redisSub.subscribe("ws:session_events", (message: string) => {
|
|
166
|
+
const set = clients.get("session_events");
|
|
167
|
+
if (!set) return;
|
|
168
|
+
for (const client of set) {
|
|
169
|
+
if (client.socket.readyState === WebSocket.OPEN) client.socket.send(message);
|
|
170
|
+
}
|
|
171
|
+
}).catch(() => {});
|
|
172
|
+
redisSub.subscribe("ws:part_stream", (message: string) => {
|
|
173
|
+
const set = clients.get("part_stream");
|
|
174
|
+
if (!set) return;
|
|
175
|
+
for (const client of set) {
|
|
176
|
+
if (client.socket.readyState === WebSocket.OPEN) client.socket.send(message);
|
|
177
|
+
}
|
|
178
|
+
}).catch(() => {});
|
|
179
|
+
}
|
|
180
|
+
return wss;
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
function broadcastToChannel(channel: string, message: any, exclude?: Client) {
|
|
184
|
+
const set = clients.get(channel);
|
|
185
|
+
const data = JSON.stringify(message);
|
|
186
|
+
// Broadcast to local clients
|
|
187
|
+
if (set) {
|
|
188
|
+
for (const client of set) {
|
|
189
|
+
if (client === exclude) continue;
|
|
190
|
+
if (client.socket.readyState === WebSocket.OPEN) {
|
|
191
|
+
client.socket.send(data);
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
// Publish to Redis for cross-instance delivery
|
|
196
|
+
if (redisPub) {
|
|
197
|
+
redisPub.publish(`ws:${channel}`, data).catch(() => {});
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
export { broadcastToChannel };
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
{
|
|
2
|
+
"compilerOptions": {
|
|
3
|
+
"target": "ES2020",
|
|
4
|
+
"module": "commonjs",
|
|
5
|
+
"lib": [
|
|
6
|
+
"ES2020",
|
|
7
|
+
"DOM"
|
|
8
|
+
],
|
|
9
|
+
"outDir": "./dist",
|
|
10
|
+
"rootDir": "./src",
|
|
11
|
+
"strict": true,
|
|
12
|
+
"esModuleInterop": true,
|
|
13
|
+
"skipLibCheck": true,
|
|
14
|
+
"forceConsistentCasingInFileNames": true,
|
|
15
|
+
"declaration": true,
|
|
16
|
+
"sourceMap": true
|
|
17
|
+
},
|
|
18
|
+
"include": [
|
|
19
|
+
"src/**/*"
|
|
20
|
+
],
|
|
21
|
+
"exclude": [
|
|
22
|
+
"node_modules",
|
|
23
|
+
"dist"
|
|
24
|
+
]
|
|
25
|
+
}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
# WorkspaceDomain Environment Variables
|
|
2
|
+
# Copy this file to .env and fill in real values. Never commit .env to source control.
|
|
3
|
+
|
|
4
|
+
# --- Required in production ---
|
|
5
|
+
# Generate with: node -e "console.log(require('crypto').randomBytes(48).toString('hex'))"
|
|
6
|
+
JWT_SECRET=
|
|
7
|
+
|
|
8
|
+
# --- Database ---
|
|
9
|
+
DATABASE_URL=postgresql://postgres:postgres@localhost:5432/workspace_domain
|
|
10
|
+
|
|
11
|
+
# --- Redis (optional, used by some domain templates) ---
|
|
12
|
+
REDIS_URL=redis://localhost:6379
|
|
13
|
+
|
|
14
|
+
# --- Server ---
|
|
15
|
+
PORT=3000
|
|
16
|
+
NODE_ENV=development
|
|
17
|
+
|
|
18
|
+
# --- CORS ---
|
|
19
|
+
# Comma-separated list of allowed origins. Leave empty to disallow all cross-origin requests.
|
|
20
|
+
# Example: ALLOWED_ORIGINS=https://app.example.com,https://admin.example.com
|
|
21
|
+
ALLOWED_ORIGINS=
|
|
22
|
+
|
|
23
|
+
# --- Event delivery mode ---
|
|
24
|
+
# in_process: in-memory, fast, no durability guarantees (default for development)
|
|
25
|
+
# durable: Postgres-backed transactional outbox (recommended for production)
|
|
26
|
+
EVENT_MODE=in_process
|
|
27
|
+
EVENT_WORKER_INTERVAL_MS=1000
|
|
28
|
+
|
|
29
|
+
# --- Request timeout ---
|
|
30
|
+
REQUEST_TIMEOUT_MS=30000
|
|
31
|
+
|
|
32
|
+
# --- Notifications ---
|
|
33
|
+
# NOTIFY_PROVIDER=log|resend|sendgrid (default: log)
|
|
34
|
+
NOTIFY_PROVIDER=log
|
|
35
|
+
NOTIFY_API_KEY=
|
|
36
|
+
NOTIFY_FROM_EMAIL=noreply@example.com
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
# Generated by BoneScript compiler.
|
|
2
|
+
name: CI/CD
|
|
3
|
+
|
|
4
|
+
on:
|
|
5
|
+
push:
|
|
6
|
+
branches: [main]
|
|
7
|
+
pull_request:
|
|
8
|
+
branches: [main]
|
|
9
|
+
|
|
10
|
+
jobs:
|
|
11
|
+
test:
|
|
12
|
+
runs-on: ubuntu-latest
|
|
13
|
+
services:
|
|
14
|
+
postgres:
|
|
15
|
+
image: postgres:16
|
|
16
|
+
env:
|
|
17
|
+
POSTGRES_DB: workspace_domain_test
|
|
18
|
+
POSTGRES_USER: postgres
|
|
19
|
+
POSTGRES_PASSWORD: postgres
|
|
20
|
+
ports:
|
|
21
|
+
- 5432:5432
|
|
22
|
+
options: --health-cmd pg_isready --health-interval 10s --health-timeout 5s --health-retries 5
|
|
23
|
+
|
|
24
|
+
steps:
|
|
25
|
+
- uses: actions/checkout@v4
|
|
26
|
+
- uses: actions/setup-node@v4
|
|
27
|
+
with:
|
|
28
|
+
node-version: 20
|
|
29
|
+
cache: npm
|
|
30
|
+
|
|
31
|
+
- name: Install dependencies
|
|
32
|
+
run: npm ci
|
|
33
|
+
|
|
34
|
+
- name: Type check
|
|
35
|
+
run: npx tsc --noEmit
|
|
36
|
+
|
|
37
|
+
- name: Run migrations
|
|
38
|
+
run: npm run migrate
|
|
39
|
+
env:
|
|
40
|
+
DATABASE_URL: postgresql://postgres:postgres@localhost:5432/workspace_domain_test
|
|
41
|
+
|
|
42
|
+
- name: Run tests
|
|
43
|
+
run: npx ts-node src/tests.ts
|
|
44
|
+
env:
|
|
45
|
+
DATABASE_URL: postgresql://postgres:postgres@localhost:5432/workspace_domain_test
|
|
46
|
+
JWT_SECRET: test-secret
|
|
47
|
+
TEST_BASE_URL: http://localhost:3000
|
|
48
|
+
|
|
49
|
+
build:
|
|
50
|
+
needs: test
|
|
51
|
+
runs-on: ubuntu-latest
|
|
52
|
+
if: github.ref == 'refs/heads/main'
|
|
53
|
+
steps:
|
|
54
|
+
- uses: actions/checkout@v4
|
|
55
|
+
- name: Build Docker image
|
|
56
|
+
run: docker build -t workspace-domain:${{ github.sha }} .
|
|
57
|
+
- name: Tag as latest
|
|
58
|
+
run: docker tag workspace-domain:${{ github.sha }} workspace-domain:latest
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
# Generated by BoneScript compiler.
|
|
2
|
+
FROM node:20-alpine AS builder
|
|
3
|
+
WORKDIR /app
|
|
4
|
+
COPY package*.json ./
|
|
5
|
+
RUN npm ci --only=production
|
|
6
|
+
COPY . .
|
|
7
|
+
RUN npm run build
|
|
8
|
+
|
|
9
|
+
FROM node:20-alpine AS runtime
|
|
10
|
+
WORKDIR /app
|
|
11
|
+
ENV NODE_ENV=production
|
|
12
|
+
COPY --from=builder /app/dist ./dist
|
|
13
|
+
COPY --from=builder /app/node_modules ./node_modules
|
|
14
|
+
COPY --from=builder /app/package.json ./
|
|
15
|
+
|
|
16
|
+
# Health check
|
|
17
|
+
HEALTHCHECK --interval=10s --timeout=5s --start-period=30s --retries=3 \
|
|
18
|
+
CMD wget -qO- http://localhost:3000/health/live || exit 1
|
|
19
|
+
|
|
20
|
+
EXPOSE 3000
|
|
21
|
+
USER node
|
|
22
|
+
CMD ["node", "dist/index.js"]
|