bonecode 1.0.0 → 1.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +64 -50
- package/bone/output/agent/.dockerignore +7 -7
- package/bone/output/agent/.env.example +36 -36
- package/bone/output/agent/.github/workflows/ci.yaml +58 -58
- package/bone/output/agent/AgentDomain.bone.map +349 -349
- package/bone/output/agent/AgentDomain.postman_collection.json +957 -957
- package/bone/output/agent/Dockerfile +22 -22
- package/bone/output/agent/README.md +47 -47
- package/bone/output/agent/admin/index.html +739 -739
- package/bone/output/agent/docker-compose.yaml +22 -22
- package/bone/output/agent/k8s/deployment.yaml +75 -75
- package/bone/output/agent/migrations/agent.sql +36 -36
- package/bone/output/agent/migrations/agent_instance.sql +36 -36
- package/bone/output/agent/migrations/audit_log.sql +18 -18
- package/bone/output/agent/migrations/build_step.sql +34 -34
- package/bone/output/agent/migrations/event_outbox.sql +31 -31
- package/bone/output/agent/migrations/plan.sql +30 -30
- package/bone/output/agent/migrations/task.sql +30 -30
- package/bone/output/agent/migrations/tool_call.sql +33 -33
- package/bone/output/agent/openapi.yaml +1116 -1116
- package/bone/output/agent/package.json +35 -35
- package/bone/output/agent/schema.graphql +233 -233
- package/bone/output/agent/sdk/client.ts +231 -231
- package/bone/output/agent/src/algorithms.ts +2 -2
- package/bone/output/agent/src/audit.ts +44 -44
- package/bone/output/agent/src/auth.ts +57 -57
- package/bone/output/agent/src/cron.ts +12 -12
- package/bone/output/agent/src/db.ts +31 -31
- package/bone/output/agent/src/debug.ts +66 -66
- package/bone/output/agent/src/events.ts +243 -243
- package/bone/output/agent/src/extensions.ts +54 -54
- package/bone/output/agent/src/failure_rules.ts +322 -322
- package/bone/output/agent/src/flows.ts +168 -168
- package/bone/output/agent/src/health.ts +43 -43
- package/bone/output/agent/src/index.ts +99 -99
- package/bone/output/agent/src/logger.ts +69 -66
- package/bone/output/agent/src/metrics.ts +75 -75
- package/bone/output/agent/src/migrate.ts +351 -351
- package/bone/output/agent/src/migration_diff.ts +108 -108
- package/bone/output/agent/src/notify.ts +125 -125
- package/bone/output/agent/src/routes/plan.ts +91 -91
- package/bone/output/agent/src/routes/task.ts +105 -105
- package/bone/output/agent/src/routes/tool_call.ts +166 -166
- package/bone/output/agent/src/schemas.ts +384 -384
- package/bone/output/agent/src/state_machines/agent_instance.ts +24 -24
- package/bone/output/agent/src/state_machines/build_step.ts +22 -22
- package/bone/output/agent/src/state_machines/plan.ts +22 -22
- package/bone/output/agent/src/state_machines/task.ts +22 -22
- package/bone/output/agent/src/state_machines/tool_call.ts +22 -22
- package/bone/output/agent/src/tests.ts +361 -361
- package/bone/output/agent/src/websocket.ts +200 -200
- package/bone/output/agent/tsconfig.json +24 -24
- package/bone/output/rag/.dockerignore +7 -7
- package/bone/output/rag/.env.example +36 -36
- package/bone/output/rag/.github/workflows/ci.yaml +58 -58
- package/bone/output/rag/Dockerfile +22 -22
- package/bone/output/rag/RAGDomain.bone.map +286 -286
- package/bone/output/rag/RAGDomain.postman_collection.json +922 -922
- package/bone/output/rag/README.md +47 -47
- package/bone/output/rag/admin/index.html +817 -817
- package/bone/output/rag/docker-compose.yaml +22 -22
- package/bone/output/rag/k8s/deployment.yaml +75 -75
- package/bone/output/rag/migrations/audit_log.sql +18 -18
- package/bone/output/rag/migrations/code_chunk.sql +34 -34
- package/bone/output/rag/migrations/code_file.sql +33 -33
- package/bone/output/rag/migrations/event_outbox.sql +31 -31
- package/bone/output/rag/migrations/indexing_job.sql +33 -33
- package/bone/output/rag/migrations/knowledge_base.sql +35 -35
- package/bone/output/rag/migrations/memory_entry.sql +34 -34
- package/bone/output/rag/openapi.yaml +1097 -1097
- package/bone/output/rag/package.json +35 -35
- package/bone/output/rag/schema.graphql +245 -245
- package/bone/output/rag/sdk/client.ts +234 -234
- package/bone/output/rag/src/algorithms.ts +2 -2
- package/bone/output/rag/src/audit.ts +37 -37
- package/bone/output/rag/src/auth.ts +57 -57
- package/bone/output/rag/src/cron.ts +12 -12
- package/bone/output/rag/src/db.ts +31 -31
- package/bone/output/rag/src/debug.ts +66 -66
- package/bone/output/rag/src/events.ts +243 -243
- package/bone/output/rag/src/extensions.ts +350 -350
- package/bone/output/rag/src/failure_rules.ts +314 -314
- package/bone/output/rag/src/flows.ts +239 -239
- package/bone/output/rag/src/health.ts +43 -43
- package/bone/output/rag/src/index.ts +94 -94
- package/bone/output/rag/src/logger.ts +69 -66
- package/bone/output/rag/src/metrics.ts +75 -75
- package/bone/output/rag/src/migrate.ts +363 -363
- package/bone/output/rag/src/migration_diff.ts +108 -108
- package/bone/output/rag/src/notify.ts +99 -99
- package/bone/output/rag/src/routes/code_chunk.ts +75 -75
- package/bone/output/rag/src/routes/code_file.ts +101 -101
- package/bone/output/rag/src/routes/indexing_job.ts +87 -87
- package/bone/output/rag/src/routes/knowledge_base.ts +230 -230
- package/bone/output/rag/src/routes/memory_entry.ts +87 -87
- package/bone/output/rag/src/schemas.ts +394 -394
- package/bone/output/rag/src/state_machines/code_file.ts +23 -23
- package/bone/output/rag/src/state_machines/indexing_job.ts +22 -22
- package/bone/output/rag/src/state_machines/knowledge_base.ts +23 -23
- package/bone/output/rag/src/state_machines/memory_entry.ts +20 -20
- package/bone/output/rag/src/tests.ts +339 -339
- package/bone/output/rag/tsconfig.json +24 -24
- package/bone/output/session/.dockerignore +7 -7
- package/bone/output/session/.env.example +36 -36
- package/bone/output/session/.github/workflows/ci.yaml +58 -58
- package/bone/output/session/Dockerfile +22 -22
- package/bone/output/session/README.md +47 -47
- package/bone/output/session/SessionDomain.bone.map +349 -349
- package/bone/output/session/SessionDomain.postman_collection.json +957 -957
- package/bone/output/session/admin/index.html +666 -666
- package/bone/output/session/docker-compose.yaml +22 -22
- package/bone/output/session/k8s/deployment.yaml +75 -75
- package/bone/output/session/migrations/audit_log.sql +18 -18
- package/bone/output/session/migrations/event_outbox.sql +31 -31
- package/bone/output/session/migrations/message.sql +31 -31
- package/bone/output/session/migrations/part.sql +28 -28
- package/bone/output/session/migrations/permission.sql +28 -28
- package/bone/output/session/migrations/project.sql +28 -28
- package/bone/output/session/migrations/session.sql +38 -38
- package/bone/output/session/openapi.yaml +1101 -1101
- package/bone/output/session/package.json +35 -35
- package/bone/output/session/schema.graphql +222 -222
- package/bone/output/session/sdk/client.ts +225 -225
- package/bone/output/session/src/algorithms.ts +2 -2
- package/bone/output/session/src/audit.ts +44 -44
- package/bone/output/session/src/auth.ts +57 -57
- package/bone/output/session/src/cron.ts +12 -12
- package/bone/output/session/src/db.ts +31 -31
- package/bone/output/session/src/debug.ts +66 -66
- package/bone/output/session/src/events.ts +270 -270
- package/bone/output/session/src/extensions.ts +215 -215
- package/bone/output/session/src/failure_rules.ts +283 -283
- package/bone/output/session/src/flows.ts +168 -168
- package/bone/output/session/src/health.ts +43 -43
- package/bone/output/session/src/index.ts +99 -99
- package/bone/output/session/src/logger.ts +67 -66
- package/bone/output/session/src/metrics.ts +75 -75
- package/bone/output/session/src/migrate.ts +331 -331
- package/bone/output/session/src/migration_diff.ts +108 -108
- package/bone/output/session/src/notify.ts +112 -112
- package/bone/output/session/src/routes/message.ts +93 -93
- package/bone/output/session/src/routes/part.ts +79 -79
- package/bone/output/session/src/routes/permission.ts +79 -79
- package/bone/output/session/src/routes/project.ts +79 -79
- package/bone/output/session/src/routes/session.ts +294 -294
- package/bone/output/session/src/schemas.ts +357 -357
- package/bone/output/session/src/state_machines/session.ts +23 -23
- package/bone/output/session/src/tests.ts +325 -325
- package/bone/output/session/src/websocket.ts +223 -200
- package/bone/output/session/tsconfig.json +24 -24
- package/bone/output/workspace/.dockerignore +7 -7
- package/bone/output/workspace/.env.example +36 -36
- package/bone/output/workspace/.github/workflows/ci.yaml +58 -58
- package/bone/output/workspace/Dockerfile +22 -22
- package/bone/output/workspace/README.md +45 -45
- package/bone/output/workspace/WorkspaceDomain.bone.map +188 -188
- package/bone/output/workspace/WorkspaceDomain.postman_collection.json +620 -620
- package/bone/output/workspace/admin/index.html +484 -484
- package/bone/output/workspace/docker-compose.yaml +22 -22
- package/bone/output/workspace/k8s/deployment.yaml +75 -75
- package/bone/output/workspace/migrations/audit_log.sql +18 -18
- package/bone/output/workspace/migrations/codebase.sql +34 -34
- package/bone/output/workspace/migrations/event_outbox.sql +31 -31
- package/bone/output/workspace/migrations/snapshot.sql +32 -32
- package/bone/output/workspace/migrations/workspace.sql +33 -33
- package/bone/output/workspace/openapi.yaml +721 -721
- package/bone/output/workspace/package.json +35 -35
- package/bone/output/workspace/schema.graphql +153 -153
- package/bone/output/workspace/sdk/client.ts +155 -155
- package/bone/output/workspace/src/algorithms.ts +2 -2
- package/bone/output/workspace/src/audit.ts +37 -37
- package/bone/output/workspace/src/auth.ts +57 -57
- package/bone/output/workspace/src/cron.ts +12 -12
- package/bone/output/workspace/src/db.ts +31 -31
- package/bone/output/workspace/src/debug.ts +66 -66
- package/bone/output/workspace/src/events.ts +243 -243
- package/bone/output/workspace/src/extensions.ts +44 -44
- package/bone/output/workspace/src/failure_rules.ts +152 -152
- package/bone/output/workspace/src/health.ts +43 -43
- package/bone/output/workspace/src/index.ts +88 -88
- package/bone/output/workspace/src/logger.ts +69 -66
- package/bone/output/workspace/src/metrics.ts +75 -75
- package/bone/output/workspace/src/migrate.ts +219 -219
- package/bone/output/workspace/src/migration_diff.ts +108 -108
- package/bone/output/workspace/src/notify.ts +73 -73
- package/bone/output/workspace/src/routes/codebase.ts +87 -87
- package/bone/output/workspace/src/routes/snapshot.ts +127 -127
- package/bone/output/workspace/src/routes/workspace.ts +190 -190
- package/bone/output/workspace/src/schemas.ts +231 -231
- package/bone/output/workspace/src/state_machines/codebase.ts +21 -21
- package/bone/output/workspace/src/state_machines/snapshot.ts +20 -20
- package/bone/output/workspace/src/state_machines/workspace.ts +21 -21
- package/bone/output/workspace/src/tests.ts +248 -248
- package/bone/output/workspace/tsconfig.json +24 -24
- package/compat/opencode_adapter.ts +94 -17
- package/package.json +15 -2
- package/src/cli.ts +66 -107
- package/src/db_adapter.ts +354 -0
- package/src/engine/account/account.sql.ts +39 -39
- package/src/engine/account/account.ts +456 -456
- package/src/engine/account/repo.ts +166 -166
- package/src/engine/account/schema.ts +99 -99
- package/src/engine/account/url.ts +8 -8
- package/src/engine/acp/README.md +174 -174
- package/src/engine/acp/agent.ts +1968 -1968
- package/src/engine/acp/runtime.ts +22 -22
- package/src/engine/acp/session.ts +122 -122
- package/src/engine/acp/types.ts +24 -24
- package/src/engine/agent/agent.ts +463 -463
- package/src/engine/agent/generate.txt +75 -75
- package/src/engine/agent/prompt/compaction.txt +9 -9
- package/src/engine/agent/prompt/explore.txt +18 -18
- package/src/engine/agent/prompt/scout.txt +36 -36
- package/src/engine/agent/prompt/summary.txt +11 -11
- package/src/engine/agent/prompt/title.txt +44 -44
- package/src/engine/agent/subagent-permissions.ts +34 -34
- package/src/engine/auth/index.ts +96 -96
- package/src/engine/background/background/job.ts +200 -200
- package/src/engine/background/job.ts +200 -200
- package/src/engine/bus/bus-event.ts +45 -45
- package/src/engine/bus/global.ts +22 -22
- package/src/engine/bus/index.ts +203 -203
- package/src/engine/command/command/index.ts +181 -181
- package/src/engine/command/command/template/initialize.txt +66 -66
- package/src/engine/command/command/template/review.txt +101 -101
- package/src/engine/command/index.ts +181 -181
- package/src/engine/command/template/initialize.txt +66 -66
- package/src/engine/command/template/review.txt +101 -101
- package/src/engine/config/agent.ts +172 -172
- package/src/engine/config/attachment.ts +25 -25
- package/src/engine/config/command.ts +62 -62
- package/src/engine/config/config.ts +833 -833
- package/src/engine/config/console-state.ts +14 -14
- package/src/engine/config/entry-name.ts +16 -16
- package/src/engine/config/error.ts +23 -23
- package/src/engine/config/formatter.ts +13 -13
- package/src/engine/config/layout.ts +6 -6
- package/src/engine/config/lsp.ts +43 -43
- package/src/engine/config/managed.ts +71 -71
- package/src/engine/config/markdown.ts +96 -96
- package/src/engine/config/mcp.ts +56 -56
- package/src/engine/config/model-id.ts +5 -5
- package/src/engine/config/parse.ts +79 -79
- package/src/engine/config/paths.ts +45 -45
- package/src/engine/config/permission.ts +58 -58
- package/src/engine/config/plugin.ts +84 -84
- package/src/engine/config/provider.ts +111 -111
- package/src/engine/config/reference.ts +23 -23
- package/src/engine/config/server.ts +19 -19
- package/src/engine/config/skills.ts +14 -14
- package/src/engine/config/variable.ts +90 -90
- package/src/engine/control-plane/adapters/index.ts +41 -41
- package/src/engine/control-plane/adapters/worktree.ts +96 -96
- package/src/engine/control-plane/dev/README.md +19 -19
- package/src/engine/control-plane/dev/debug-workspace-plugin.ts +73 -73
- package/src/engine/control-plane/schema.ts +14 -14
- package/src/engine/control-plane/types.ts +59 -59
- package/src/engine/control-plane/util.ts +39 -39
- package/src/engine/control-plane/workspace-adapter-runtime.ts +51 -51
- package/src/engine/control-plane/workspace-context.ts +26 -26
- package/src/engine/control-plane/workspace.sql.ts +20 -20
- package/src/engine/control-plane/workspace.ts +1072 -1072
- package/src/engine/data-migration.ts +161 -161
- package/src/engine/effect/app-runtime.ts +143 -143
- package/src/engine/effect/bootstrap-runtime.ts +29 -29
- package/src/engine/effect/bridge.ts +84 -84
- package/src/engine/effect/config-service.ts +67 -67
- package/src/engine/effect/instance-ref.ts +11 -11
- package/src/engine/effect/instance-registry.ts +12 -12
- package/src/engine/effect/instance-state.ts +72 -72
- package/src/engine/effect/promise.ts +17 -17
- package/src/engine/effect/run-service.ts +47 -47
- package/src/engine/effect/runner.ts +217 -217
- package/src/engine/effect/runtime-flags.ts +74 -74
- package/src/engine/effect/service-use.ts +38 -38
- package/src/engine/env/index.ts +37 -37
- package/src/engine/event-v2-bridge.ts +89 -89
- package/src/engine/file/file/ignore.ts +81 -81
- package/src/engine/file/file/index.ts +651 -651
- package/src/engine/file/file/protected.ts +59 -59
- package/src/engine/file/file/ripgrep.ts +481 -481
- package/src/engine/file/file/watcher.ts +167 -167
- package/src/engine/file/ignore.ts +81 -81
- package/src/engine/file/index.ts +651 -651
- package/src/engine/file/protected.ts +59 -59
- package/src/engine/file/ripgrep.ts +481 -481
- package/src/engine/file/watcher.ts +167 -167
- package/src/engine/format/format/formatter.ts +404 -404
- package/src/engine/format/format/index.ts +209 -209
- package/src/engine/format/formatter.ts +404 -404
- package/src/engine/format/index.ts +209 -209
- package/src/engine/git/git/index.ts +347 -347
- package/src/engine/git/index.ts +347 -347
- package/src/engine/id/id.ts +80 -80
- package/src/engine/ide/index.ts +70 -70
- package/src/engine/image/image/image.ts +176 -176
- package/src/engine/image/image.ts +176 -176
- package/src/engine/index.ts +251 -251
- package/src/engine/installation/index.ts +327 -327
- package/src/engine/lsp/client.ts +707 -707
- package/src/engine/lsp/diagnostic.ts +29 -29
- package/src/engine/lsp/language.ts +121 -121
- package/src/engine/lsp/launch.ts +21 -21
- package/src/engine/lsp/lsp/client.ts +707 -707
- package/src/engine/lsp/lsp/diagnostic.ts +29 -29
- package/src/engine/lsp/lsp/language.ts +121 -121
- package/src/engine/lsp/lsp/launch.ts +21 -21
- package/src/engine/lsp/lsp/lsp.ts +507 -507
- package/src/engine/lsp/lsp/server.ts +2064 -2064
- package/src/engine/lsp/lsp.ts +507 -507
- package/src/engine/lsp/server.ts +2064 -2064
- package/src/engine/mcp/auth.ts +146 -146
- package/src/engine/mcp/index.ts +958 -958
- package/src/engine/mcp/mcp/auth.ts +146 -146
- package/src/engine/mcp/mcp/index.ts +958 -958
- package/src/engine/mcp/mcp/oauth-callback.ts +232 -232
- package/src/engine/mcp/mcp/oauth-provider.ts +214 -214
- package/src/engine/mcp/oauth-callback.ts +232 -232
- package/src/engine/mcp/oauth-provider.ts +214 -214
- package/src/engine/node.ts +6 -6
- package/src/engine/patch/index.ts +689 -689
- package/src/engine/patch/patch/index.ts +689 -689
- package/src/engine/permission/arity.ts +163 -163
- package/src/engine/permission/evaluate.ts +15 -15
- package/src/engine/permission/index.ts +306 -306
- package/src/engine/permission/permission/arity.ts +163 -163
- package/src/engine/permission/permission/evaluate.ts +15 -15
- package/src/engine/permission/permission/index.ts +306 -306
- package/src/engine/permission/permission/schema.ts +13 -13
- package/src/engine/permission/schema.ts +13 -13
- package/src/engine/plugin/azure.ts +26 -26
- package/src/engine/plugin/cloudflare.ts +76 -76
- package/src/engine/plugin/codex.ts +622 -622
- package/src/engine/plugin/digitalocean.ts +411 -411
- package/src/engine/plugin/github-copilot/copilot.ts +394 -394
- package/src/engine/plugin/github-copilot/models.ts +196 -196
- package/src/engine/plugin/index.ts +295 -295
- package/src/engine/plugin/install.ts +439 -439
- package/src/engine/plugin/loader.ts +216 -216
- package/src/engine/plugin/meta.ts +188 -188
- package/src/engine/plugin/shared.ts +323 -323
- package/src/engine/project/bootstrap-service.ts +9 -9
- package/src/engine/project/bootstrap.ts +75 -75
- package/src/engine/project/instance-context.ts +24 -24
- package/src/engine/project/instance-layer.ts +11 -11
- package/src/engine/project/instance-runtime.ts +16 -16
- package/src/engine/project/instance-store.ts +193 -193
- package/src/engine/project/project.sql.ts +17 -17
- package/src/engine/project/project.ts +537 -537
- package/src/engine/project/schema.ts +13 -13
- package/src/engine/project/vcs.ts +405 -405
- package/src/engine/provider/auth.ts +225 -225
- package/src/engine/provider/error.ts +204 -204
- package/src/engine/provider/model-status.ts +8 -8
- package/src/engine/provider/provider.ts +1843 -1843
- package/src/engine/provider/schema.ts +30 -30
- package/src/engine/provider/transform.ts +1376 -1376
- package/src/engine/pty/index.ts +365 -365
- package/src/engine/pty/input.ts +24 -24
- package/src/engine/pty/pty/index.ts +365 -365
- package/src/engine/pty/pty/input.ts +24 -24
- package/src/engine/pty/pty/pty.bun.ts +26 -26
- package/src/engine/pty/pty/pty.node.ts +27 -27
- package/src/engine/pty/pty/pty.ts +25 -25
- package/src/engine/pty/pty/schema.ts +14 -14
- package/src/engine/pty/pty/ticket.ts +68 -68
- package/src/engine/pty/pty.bun.ts +26 -26
- package/src/engine/pty/pty.node.ts +27 -27
- package/src/engine/pty/pty.ts +25 -25
- package/src/engine/pty/schema.ts +14 -14
- package/src/engine/pty/ticket.ts +68 -68
- package/src/engine/question/index.ts +213 -213
- package/src/engine/question/question/index.ts +213 -213
- package/src/engine/question/question/schema.ts +10 -10
- package/src/engine/question/schema.ts +10 -10
- package/src/engine/reference/reference/reference.ts +241 -241
- package/src/engine/reference/reference/repository-cache.ts +147 -147
- package/src/engine/reference/reference.ts +241 -241
- package/src/engine/reference/repository-cache.ts +147 -147
- package/src/engine/session/compaction.ts +651 -651
- package/src/engine/session/instruction.ts +238 -238
- package/src/engine/session/llm.ts +459 -459
- package/src/engine/session/message-error.ts +14 -14
- package/src/engine/session/message-v2.ts +1202 -1202
- package/src/engine/session/message.ts +146 -146
- package/src/engine/session/overflow.ts +32 -32
- package/src/engine/session/processor.ts +823 -823
- package/src/engine/session/prompt/anthropic.txt +105 -105
- package/src/engine/session/prompt/beast.txt +147 -147
- package/src/engine/session/prompt/build-switch.txt +5 -5
- package/src/engine/session/prompt/codex.txt +79 -79
- package/src/engine/session/prompt/copilot-gpt-5.txt +143 -143
- package/src/engine/session/prompt/default.txt +105 -105
- package/src/engine/session/prompt/gemini.txt +155 -155
- package/src/engine/session/prompt/gpt.txt +107 -107
- package/src/engine/session/prompt/kimi.txt +95 -95
- package/src/engine/session/prompt/max-steps.txt +15 -15
- package/src/engine/session/prompt/plan-reminder-anthropic.txt +67 -67
- package/src/engine/session/prompt/plan.txt +26 -26
- package/src/engine/session/prompt/trinity.txt +97 -97
- package/src/engine/session/prompt.ts +66 -9
- package/src/engine/session/retry.ts +200 -200
- package/src/engine/session/revert.ts +162 -162
- package/src/engine/session/run-state.ts +153 -153
- package/src/engine/session/schema.ts +26 -26
- package/src/engine/session/session.sql.ts +137 -137
- package/src/engine/session/session.ts +1011 -1011
- package/src/engine/session/status.ts +94 -94
- package/src/engine/session/summary.ts +164 -164
- package/src/engine/session/system.ts +84 -84
- package/src/engine/session/todo.ts +81 -81
- package/src/engine/share/session.ts +61 -61
- package/src/engine/share/share-next.ts +376 -376
- package/src/engine/share/share.sql.ts +13 -13
- package/src/engine/shell/shell/shell.ts +215 -215
- package/src/engine/shell/shell.ts +215 -215
- package/src/engine/skill/discovery.ts +116 -116
- package/src/engine/skill/index.ts +336 -336
- package/src/engine/skill/prompt/customize-opencode.md +377 -377
- package/src/engine/skill/skill/discovery.ts +116 -116
- package/src/engine/skill/skill/index.ts +336 -336
- package/src/engine/skill/skill/prompt/customize-opencode.md +377 -377
- package/src/engine/snapshot/index.ts +762 -762
- package/src/engine/snapshot/snapshot/index.ts +762 -762
- package/src/engine/sync/README.md +179 -179
- package/src/engine/sync/event.sql.ts +17 -17
- package/src/engine/sync/index.ts +410 -410
- package/src/engine/sync/schema.ts +11 -11
- package/src/engine/temporary.ts +33 -33
- package/src/engine/tool/apply_patch.ts +313 -313
- package/src/engine/tool/apply_patch.txt +33 -33
- package/src/engine/tool/edit.ts +711 -711
- package/src/engine/tool/edit.txt +10 -10
- package/src/engine/tool/external-directory.ts +49 -49
- package/src/engine/tool/glob.ts +103 -103
- package/src/engine/tool/glob.txt +6 -6
- package/src/engine/tool/grep.ts +156 -156
- package/src/engine/tool/grep.txt +8 -8
- package/src/engine/tool/invalid.ts +21 -21
- package/src/engine/tool/json-schema.ts +164 -164
- package/src/engine/tool/lsp.ts +113 -113
- package/src/engine/tool/lsp.txt +24 -24
- package/src/engine/tool/mcp-websearch.ts +96 -96
- package/src/engine/tool/plan-enter.txt +14 -14
- package/src/engine/tool/plan-exit.txt +13 -13
- package/src/engine/tool/plan.ts +78 -78
- package/src/engine/tool/question.ts +44 -44
- package/src/engine/tool/question.txt +10 -10
- package/src/engine/tool/read.ts +337 -337
- package/src/engine/tool/read.txt +14 -14
- package/src/engine/tool/registry.ts +472 -472
- package/src/engine/tool/repo_clone.ts +80 -80
- package/src/engine/tool/repo_clone.txt +5 -5
- package/src/engine/tool/repo_overview.ts +279 -279
- package/src/engine/tool/repo_overview.txt +4 -4
- package/src/engine/tool/schema.ts +14 -14
- package/src/engine/tool/shell/id.ts +19 -19
- package/src/engine/tool/shell/prompt.ts +295 -295
- package/src/engine/tool/shell/shell.txt +77 -77
- package/src/engine/tool/shell.ts +647 -647
- package/src/engine/tool/skill.ts +75 -75
- package/src/engine/tool/skill.txt +5 -5
- package/src/engine/tool/task.ts +337 -337
- package/src/engine/tool/task.txt +58 -58
- package/src/engine/tool/task_status.ts +179 -179
- package/src/engine/tool/task_status.txt +13 -13
- package/src/engine/tool/todo.ts +57 -57
- package/src/engine/tool/todowrite.txt +167 -167
- package/src/engine/tool/tool/apply_patch.ts +313 -313
- package/src/engine/tool/tool/apply_patch.txt +33 -33
- package/src/engine/tool/tool/edit.ts +711 -711
- package/src/engine/tool/tool/edit.txt +10 -10
- package/src/engine/tool/tool/external-directory.ts +49 -49
- package/src/engine/tool/tool/glob.ts +103 -103
- package/src/engine/tool/tool/glob.txt +6 -6
- package/src/engine/tool/tool/grep.ts +156 -156
- package/src/engine/tool/tool/grep.txt +8 -8
- package/src/engine/tool/tool/invalid.ts +21 -21
- package/src/engine/tool/tool/json-schema.ts +164 -164
- package/src/engine/tool/tool/lsp.ts +113 -113
- package/src/engine/tool/tool/lsp.txt +24 -24
- package/src/engine/tool/tool/mcp-websearch.ts +96 -96
- package/src/engine/tool/tool/plan-enter.txt +14 -14
- package/src/engine/tool/tool/plan-exit.txt +13 -13
- package/src/engine/tool/tool/plan.ts +78 -78
- package/src/engine/tool/tool/question.ts +44 -44
- package/src/engine/tool/tool/question.txt +10 -10
- package/src/engine/tool/tool/read.ts +337 -337
- package/src/engine/tool/tool/read.txt +14 -14
- package/src/engine/tool/tool/registry.ts +472 -472
- package/src/engine/tool/tool/repo_clone.ts +80 -80
- package/src/engine/tool/tool/repo_clone.txt +5 -5
- package/src/engine/tool/tool/repo_overview.ts +279 -279
- package/src/engine/tool/tool/repo_overview.txt +4 -4
- package/src/engine/tool/tool/schema.ts +14 -14
- package/src/engine/tool/tool/shell/id.ts +19 -19
- package/src/engine/tool/tool/shell/prompt.ts +295 -295
- package/src/engine/tool/tool/shell/shell.txt +77 -77
- package/src/engine/tool/tool/shell.ts +647 -647
- package/src/engine/tool/tool/skill.ts +75 -75
- package/src/engine/tool/tool/skill.txt +5 -5
- package/src/engine/tool/tool/task.ts +337 -337
- package/src/engine/tool/tool/task.txt +58 -58
- package/src/engine/tool/tool/task_status.ts +179 -179
- package/src/engine/tool/tool/task_status.txt +13 -13
- package/src/engine/tool/tool/todo.ts +57 -57
- package/src/engine/tool/tool/todowrite.txt +167 -167
- package/src/engine/tool/tool/tool.ts +164 -164
- package/src/engine/tool/tool/truncate.ts +160 -160
- package/src/engine/tool/tool/truncation-dir.ts +4 -4
- package/src/engine/tool/tool/webfetch.ts +192 -192
- package/src/engine/tool/tool/webfetch.txt +13 -13
- package/src/engine/tool/tool/websearch.ts +143 -143
- package/src/engine/tool/tool/websearch.txt +14 -14
- package/src/engine/tool/tool/write.ts +104 -104
- package/src/engine/tool/tool/write.txt +8 -8
- package/src/engine/tool/tool.ts +164 -164
- package/src/engine/tool/truncate.ts +160 -160
- package/src/engine/tool/truncation-dir.ts +4 -4
- package/src/engine/tool/webfetch.ts +192 -192
- package/src/engine/tool/webfetch.txt +13 -13
- package/src/engine/tool/websearch.ts +143 -143
- package/src/engine/tool/websearch.txt +14 -14
- package/src/engine/tool/write.ts +104 -104
- package/src/engine/tool/write.txt +8 -8
- package/src/engine/util/archive.ts +17 -17
- package/src/engine/util/bom.ts +31 -31
- package/src/engine/util/data-url.ts +9 -9
- package/src/engine/util/defer.ts +10 -10
- package/src/engine/util/effect-http-client.ts +11 -11
- package/src/engine/util/error.ts +88 -88
- package/src/engine/util/filesystem.ts +252 -252
- package/src/engine/util/format.ts +20 -20
- package/src/engine/util/iife.ts +3 -3
- package/src/engine/util/lazy.ts +20 -20
- package/src/engine/util/local-context.ts +25 -25
- package/src/engine/util/locale.ts +86 -86
- package/src/engine/util/media.ts +26 -26
- package/src/engine/util/process.ts +176 -176
- package/src/engine/util/queue.ts +32 -32
- package/src/engine/util/record.ts +3 -3
- package/src/engine/util/repository.ts +158 -158
- package/src/engine/util/rpc.ts +66 -66
- package/src/engine/util/signal.ts +12 -12
- package/src/engine/util/timeout.ts +13 -13
- package/src/engine/util/token.ts +7 -7
- package/src/engine/util/util/archive.ts +17 -17
- package/src/engine/util/util/bom.ts +31 -31
- package/src/engine/util/util/data-url.ts +9 -9
- package/src/engine/util/util/defer.ts +10 -10
- package/src/engine/util/util/effect-http-client.ts +11 -11
- package/src/engine/util/util/error.ts +88 -88
- package/src/engine/util/util/filesystem.ts +252 -252
- package/src/engine/util/util/format.ts +20 -20
- package/src/engine/util/util/iife.ts +3 -3
- package/src/engine/util/util/lazy.ts +20 -20
- package/src/engine/util/util/local-context.ts +25 -25
- package/src/engine/util/util/locale.ts +86 -86
- package/src/engine/util/util/media.ts +26 -26
- package/src/engine/util/util/process.ts +176 -176
- package/src/engine/util/util/queue.ts +32 -32
- package/src/engine/util/util/record.ts +3 -3
- package/src/engine/util/util/repository.ts +158 -158
- package/src/engine/util/util/rpc.ts +66 -66
- package/src/engine/util/util/signal.ts +12 -12
- package/src/engine/util/util/timeout.ts +13 -13
- package/src/engine/util/util/token.ts +7 -7
- package/src/engine/util/util/which.ts +14 -14
- package/src/engine/util/util/wildcard.ts +59 -59
- package/src/engine/util/which.ts +14 -14
- package/src/engine/util/wildcard.ts +59 -59
- package/src/engine/worktree/index.ts +621 -621
- package/src/server.ts +121 -158
- package/src/tui.ts +485 -502
package/src/engine/sync/index.ts
CHANGED
|
@@ -1,410 +1,410 @@
|
|
|
1
|
-
// Legacy sync event system. It should stay unaware of core EventV2 execution;
|
|
2
|
-
// the only temporary V2 coupling here is exposing versioned core event schemas
|
|
3
|
-
// in effectPayloads() so existing HTTP/SDK schema generation remains stable.
|
|
4
|
-
// Remove that registry read when event schemas are generated from core directly.
|
|
5
|
-
import { Database } from "@/storage/db"
|
|
6
|
-
import { eq } from "drizzle-orm"
|
|
7
|
-
import { GlobalBus } from "@/bus/global"
|
|
8
|
-
import { Bus as ProjectBus } from "@/bus"
|
|
9
|
-
import { BusEvent } from "@/bus/bus-event"
|
|
10
|
-
import type { InstanceContext } from "@/project/instance-context"
|
|
11
|
-
import { EventSequenceTable, EventTable } from "./event.sql"
|
|
12
|
-
import type { WorkspaceID } from "@/control-plane/schema"
|
|
13
|
-
import { EventID } from "./schema"
|
|
14
|
-
import { Context, Effect, Layer, Schema as EffectSchema } from "effect"
|
|
15
|
-
import type { DeepMutable } from "@opencode-ai/core/schema"
|
|
16
|
-
import { EventV2 } from "@opencode-ai/core/event"
|
|
17
|
-
import { serviceUse } from "@/effect/service-use"
|
|
18
|
-
import { InstanceState } from "@/effect/instance-state"
|
|
19
|
-
import { RuntimeFlags } from "@/effect/runtime-flags"
|
|
20
|
-
|
|
21
|
-
// Keep `Event["data"]` mutable because projectors mutate the persisted shape
|
|
22
|
-
// when writing to the database. Bus payloads (`Properties`) stay readonly —
|
|
23
|
-
// subscribers only read.
|
|
24
|
-
|
|
25
|
-
export type Definition<
|
|
26
|
-
Type extends string = string,
|
|
27
|
-
Schema extends EffectSchema.Top = EffectSchema.Top,
|
|
28
|
-
BusSchema extends EffectSchema.Top = Schema,
|
|
29
|
-
> = {
|
|
30
|
-
type: Type
|
|
31
|
-
version: number
|
|
32
|
-
aggregate: string
|
|
33
|
-
schema: Schema
|
|
34
|
-
// Bus event payload schema. Defaults to `schema` unless `busSchema` was
|
|
35
|
-
// passed at definition time (see `session.updated`, whose projector
|
|
36
|
-
// expands the persisted data to a `{ sessionID, info }` bus payload).
|
|
37
|
-
properties: BusSchema
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
export type Event<Def extends Definition = Definition> = {
|
|
41
|
-
id: string
|
|
42
|
-
seq: number
|
|
43
|
-
aggregateID: string
|
|
44
|
-
data: DeepMutable<EffectSchema.Schema.Type<Def["schema"]>>
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
export type Properties<Def extends Definition = Definition> = EffectSchema.Schema.Type<Def["properties"]>
|
|
48
|
-
|
|
49
|
-
export type SerializedEvent<Def extends Definition = Definition> = Event<Def> & { type: string }
|
|
50
|
-
|
|
51
|
-
type ProjectorFunc = (db: Database.TxOrDb, data: unknown, event: Event) => void
|
|
52
|
-
type ConvertEvent = (type: string, data: Event["data"]) => unknown | Promise<unknown>
|
|
53
|
-
type PublishContext = {
|
|
54
|
-
instance?: InstanceContext
|
|
55
|
-
workspace?: WorkspaceID
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
export interface Interface {
|
|
59
|
-
readonly run: <Def extends Definition>(
|
|
60
|
-
def: Def,
|
|
61
|
-
data: Event<Def>["data"],
|
|
62
|
-
options?: { publish?: boolean },
|
|
63
|
-
) => Effect.Effect<void>
|
|
64
|
-
readonly replay: (event: SerializedEvent, options?: { publish: boolean; ownerID?: string }) => Effect.Effect<void>
|
|
65
|
-
readonly replayAll: (
|
|
66
|
-
events: SerializedEvent[],
|
|
67
|
-
options?: { publish: boolean; ownerID?: string },
|
|
68
|
-
) => Effect.Effect<string | undefined>
|
|
69
|
-
readonly remove: (aggregateID: string) => Effect.Effect<void>
|
|
70
|
-
readonly claim: (aggregateID: string, ownerID: string) => Effect.Effect<void>
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
export class Service extends Context.Service<Service, Interface>()("@opencode/SyncEvent") {}
|
|
74
|
-
|
|
75
|
-
export const layer = Layer.effect(Service)(
|
|
76
|
-
Effect.gen(function* () {
|
|
77
|
-
const flags = yield* RuntimeFlags.Service
|
|
78
|
-
|
|
79
|
-
const replay: Interface["replay"] = Effect.fn("SyncEvent.replay")(function* (event, options) {
|
|
80
|
-
const def = registry.get(event.type)
|
|
81
|
-
if (!def) {
|
|
82
|
-
throw new Error(`Unknown event type: ${event.type}`)
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
const row = Database.use((db) =>
|
|
86
|
-
db
|
|
87
|
-
.select({ seq: EventSequenceTable.seq, ownerID: EventSequenceTable.owner_id })
|
|
88
|
-
.from(EventSequenceTable)
|
|
89
|
-
.where(eq(EventSequenceTable.aggregate_id, event.aggregateID))
|
|
90
|
-
.get(),
|
|
91
|
-
)
|
|
92
|
-
|
|
93
|
-
const latest = row?.seq ?? -1
|
|
94
|
-
if (event.seq <= latest) return
|
|
95
|
-
|
|
96
|
-
if (row?.ownerID && row.ownerID !== options?.ownerID) {
|
|
97
|
-
return
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
const expected = latest + 1
|
|
101
|
-
if (event.seq !== expected) {
|
|
102
|
-
throw new Error(
|
|
103
|
-
`Sequence mismatch for aggregate "${event.aggregateID}": expected ${expected}, got ${event.seq}`,
|
|
104
|
-
)
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
const publish = !!options?.publish
|
|
108
|
-
const context = publish
|
|
109
|
-
? {
|
|
110
|
-
instance: yield* InstanceState.context,
|
|
111
|
-
workspace: yield* InstanceState.workspaceID,
|
|
112
|
-
}
|
|
113
|
-
: undefined
|
|
114
|
-
process(def, event, {
|
|
115
|
-
publish,
|
|
116
|
-
context,
|
|
117
|
-
ownerID: options?.ownerID,
|
|
118
|
-
experimentalWorkspaces: flags.experimentalWorkspaces,
|
|
119
|
-
})
|
|
120
|
-
})
|
|
121
|
-
|
|
122
|
-
const replayAll: Interface["replayAll"] = Effect.fn("SyncEvent.replayAll")(function* (events, options) {
|
|
123
|
-
const source = events[0]?.aggregateID
|
|
124
|
-
if (!source) return undefined
|
|
125
|
-
if (events.some((item) => item.aggregateID !== source)) {
|
|
126
|
-
throw new Error("Replay events must belong to the same session")
|
|
127
|
-
}
|
|
128
|
-
const start = events[0].seq
|
|
129
|
-
for (const [i, item] of events.entries()) {
|
|
130
|
-
const seq = start + i
|
|
131
|
-
if (item.seq !== seq) {
|
|
132
|
-
throw new Error(`Replay sequence mismatch at index ${i}: expected ${seq}, got ${item.seq}`)
|
|
133
|
-
}
|
|
134
|
-
}
|
|
135
|
-
for (const item of events) {
|
|
136
|
-
yield* replay(item, options)
|
|
137
|
-
}
|
|
138
|
-
return source
|
|
139
|
-
})
|
|
140
|
-
|
|
141
|
-
const run: Interface["run"] = Effect.fn("SyncEvent.run")(function* (def, data, options) {
|
|
142
|
-
const agg = (data as Record<string, string>)[def.aggregate]
|
|
143
|
-
// This should never happen: we've enforced it via typescript in
|
|
144
|
-
// the definition
|
|
145
|
-
if (agg == null) {
|
|
146
|
-
throw new Error(`SyncEvent.run: "${def.aggregate}" required but not found: ${JSON.stringify(data)}`)
|
|
147
|
-
}
|
|
148
|
-
|
|
149
|
-
if (def.version !== versions.get(def.type)) {
|
|
150
|
-
throw new Error(`SyncEvent.run: running old versions of events is not allowed: ${def.type}`)
|
|
151
|
-
}
|
|
152
|
-
|
|
153
|
-
const { publish = true } = options || {}
|
|
154
|
-
const context = publish
|
|
155
|
-
? {
|
|
156
|
-
instance: yield* InstanceState.context,
|
|
157
|
-
workspace: yield* InstanceState.workspaceID,
|
|
158
|
-
}
|
|
159
|
-
: undefined
|
|
160
|
-
|
|
161
|
-
// Note that this is an "immediate" transaction which is critical.
|
|
162
|
-
// We need to make sure we can safely read and write with nothing
|
|
163
|
-
// else changing the data from under us
|
|
164
|
-
Database.transaction(
|
|
165
|
-
(tx) => {
|
|
166
|
-
const id = EventID.ascending()
|
|
167
|
-
const row = tx
|
|
168
|
-
.select({ seq: EventSequenceTable.seq })
|
|
169
|
-
.from(EventSequenceTable)
|
|
170
|
-
.where(eq(EventSequenceTable.aggregate_id, agg))
|
|
171
|
-
.get()
|
|
172
|
-
const seq = row?.seq != null ? row.seq + 1 : 0
|
|
173
|
-
|
|
174
|
-
const event = { id, seq, aggregateID: agg, data }
|
|
175
|
-
process(def, event, { publish, context, experimentalWorkspaces: flags.experimentalWorkspaces })
|
|
176
|
-
},
|
|
177
|
-
{
|
|
178
|
-
behavior: "immediate",
|
|
179
|
-
},
|
|
180
|
-
)
|
|
181
|
-
})
|
|
182
|
-
|
|
183
|
-
const remove: Interface["remove"] = Effect.fn("SyncEvent.remove")(function* (aggregateID) {
|
|
184
|
-
Database.transaction((tx) => {
|
|
185
|
-
tx.delete(EventSequenceTable).where(eq(EventSequenceTable.aggregate_id, aggregateID)).run()
|
|
186
|
-
tx.delete(EventTable).where(eq(EventTable.aggregate_id, aggregateID)).run()
|
|
187
|
-
})
|
|
188
|
-
})
|
|
189
|
-
|
|
190
|
-
const claim: Interface["claim"] = Effect.fn("SyncEvent.claim")((aggregateID, ownerID) =>
|
|
191
|
-
Effect.sync(() =>
|
|
192
|
-
Database.use((db) =>
|
|
193
|
-
db
|
|
194
|
-
.update(EventSequenceTable)
|
|
195
|
-
.set({ owner_id: ownerID })
|
|
196
|
-
.where(eq(EventSequenceTable.aggregate_id, aggregateID))
|
|
197
|
-
.run(),
|
|
198
|
-
),
|
|
199
|
-
),
|
|
200
|
-
)
|
|
201
|
-
|
|
202
|
-
return Service.of({
|
|
203
|
-
run,
|
|
204
|
-
replay,
|
|
205
|
-
replayAll,
|
|
206
|
-
remove,
|
|
207
|
-
claim,
|
|
208
|
-
})
|
|
209
|
-
}),
|
|
210
|
-
)
|
|
211
|
-
|
|
212
|
-
export const defaultLayer = layer.pipe(Layer.provide(RuntimeFlags.defaultLayer))
|
|
213
|
-
|
|
214
|
-
export const use = serviceUse(Service)
|
|
215
|
-
|
|
216
|
-
export const registry = new Map<string, Definition>()
|
|
217
|
-
let projectors: Map<string, ProjectorFunc> | undefined
|
|
218
|
-
const versions = new Map<string, number>()
|
|
219
|
-
let frozen = false
|
|
220
|
-
let convertEvent: ConvertEvent
|
|
221
|
-
|
|
222
|
-
export function reset() {
|
|
223
|
-
frozen = false
|
|
224
|
-
projectors = undefined
|
|
225
|
-
convertEvent = (_, data) => data
|
|
226
|
-
}
|
|
227
|
-
|
|
228
|
-
export function init(input: { projectors: Array<[Definition, ProjectorFunc]>; convertEvent?: ConvertEvent }) {
|
|
229
|
-
projectors = new Map(input.projectors.map(([def, func]) => [versionedType(def.type, def.version), func]))
|
|
230
|
-
for (let entry of EventV2.registry.values()) {
|
|
231
|
-
if (!entry.version || !entry.aggregate) continue
|
|
232
|
-
register({
|
|
233
|
-
type: entry.type,
|
|
234
|
-
version: entry.version,
|
|
235
|
-
aggregate: entry.aggregate,
|
|
236
|
-
properties: entry.data,
|
|
237
|
-
schema: entry.data,
|
|
238
|
-
})
|
|
239
|
-
}
|
|
240
|
-
|
|
241
|
-
// Install all the latest event defs to the bus. We only ever emit
|
|
242
|
-
// latest versions from code, and keep around old versions for
|
|
243
|
-
// replaying. Replaying does not go through the bus, and it
|
|
244
|
-
// simplifies the bus to only use unversioned latest events
|
|
245
|
-
for (let [type, version] of versions.entries()) {
|
|
246
|
-
let def = registry.get(versionedType(type, version))!
|
|
247
|
-
BusEvent.define(def.type, def.properties)
|
|
248
|
-
}
|
|
249
|
-
|
|
250
|
-
// Freeze the system so it clearly errors if events are defined
|
|
251
|
-
// after `init` which would cause bugs
|
|
252
|
-
frozen = true
|
|
253
|
-
convertEvent = input.convertEvent ?? ((_, data) => data)
|
|
254
|
-
}
|
|
255
|
-
|
|
256
|
-
export function versionedType<A extends string>(type: A): A
|
|
257
|
-
export function versionedType<A extends string, B extends number>(type: A, version: B): `${A}/${B}`
|
|
258
|
-
export function versionedType(type: string, version?: number) {
|
|
259
|
-
return version ? `${type}.${version}` : type
|
|
260
|
-
}
|
|
261
|
-
|
|
262
|
-
export function define<
|
|
263
|
-
Type extends string,
|
|
264
|
-
Agg extends string,
|
|
265
|
-
Schema extends EffectSchema.Top,
|
|
266
|
-
BusSchema extends EffectSchema.Top = Schema,
|
|
267
|
-
>(input: {
|
|
268
|
-
type: Type
|
|
269
|
-
version: number
|
|
270
|
-
aggregate: Agg
|
|
271
|
-
schema: Schema
|
|
272
|
-
busSchema?: BusSchema
|
|
273
|
-
}): Definition<Type, Schema, BusSchema> {
|
|
274
|
-
if (frozen) {
|
|
275
|
-
throw new Error("Error defining sync event: sync system has been frozen")
|
|
276
|
-
}
|
|
277
|
-
|
|
278
|
-
const def = {
|
|
279
|
-
type: input.type,
|
|
280
|
-
version: input.version,
|
|
281
|
-
aggregate: input.aggregate,
|
|
282
|
-
schema: input.schema,
|
|
283
|
-
properties: (input.busSchema ?? input.schema) as BusSchema,
|
|
284
|
-
}
|
|
285
|
-
|
|
286
|
-
register(def)
|
|
287
|
-
|
|
288
|
-
return def
|
|
289
|
-
}
|
|
290
|
-
|
|
291
|
-
export function project<Def extends Definition>(
|
|
292
|
-
def: Def,
|
|
293
|
-
func: (db: Database.TxOrDb, data: Event<Def>["data"], event: Event<Def>) => void,
|
|
294
|
-
): [Definition, ProjectorFunc] {
|
|
295
|
-
return [def, func as ProjectorFunc]
|
|
296
|
-
}
|
|
297
|
-
|
|
298
|
-
function register(def: Definition) {
|
|
299
|
-
versions.set(def.type, Math.max(def.version, versions.get(def.type) || 0))
|
|
300
|
-
registry.set(versionedType(def.type, def.version), def)
|
|
301
|
-
}
|
|
302
|
-
|
|
303
|
-
function process<Def extends Definition>(
|
|
304
|
-
def: Def,
|
|
305
|
-
event: Event<Def>,
|
|
306
|
-
options: { publish: boolean; context?: PublishContext; ownerID?: string; experimentalWorkspaces: boolean },
|
|
307
|
-
) {
|
|
308
|
-
if (projectors == null) {
|
|
309
|
-
throw new Error("No projectors available. Call `SyncEvent.init` to install projectors")
|
|
310
|
-
}
|
|
311
|
-
|
|
312
|
-
const projector = projectors.get(versionedType(def.type, def.version))
|
|
313
|
-
if (!projector) {
|
|
314
|
-
if (!def.type.includes("next")) throw new Error(`Projector not found for event: ${def.type}`)
|
|
315
|
-
return
|
|
316
|
-
}
|
|
317
|
-
|
|
318
|
-
Database.transaction((tx) => {
|
|
319
|
-
projector(tx, event.data, event)
|
|
320
|
-
|
|
321
|
-
if (options.experimentalWorkspaces) {
|
|
322
|
-
tx.insert(EventSequenceTable)
|
|
323
|
-
.values({
|
|
324
|
-
aggregate_id: event.aggregateID,
|
|
325
|
-
seq: event.seq,
|
|
326
|
-
owner_id: options?.ownerID,
|
|
327
|
-
})
|
|
328
|
-
.onConflictDoUpdate({
|
|
329
|
-
target: EventSequenceTable.aggregate_id,
|
|
330
|
-
set: { seq: event.seq },
|
|
331
|
-
})
|
|
332
|
-
.run()
|
|
333
|
-
tx.insert(EventTable)
|
|
334
|
-
.values({
|
|
335
|
-
id: event.id,
|
|
336
|
-
seq: event.seq,
|
|
337
|
-
aggregate_id: event.aggregateID,
|
|
338
|
-
type: versionedType(def.type, def.version),
|
|
339
|
-
data: event.data as Record<string, unknown>,
|
|
340
|
-
})
|
|
341
|
-
.run()
|
|
342
|
-
}
|
|
343
|
-
|
|
344
|
-
Database.effect(() => {
|
|
345
|
-
if (options?.publish) {
|
|
346
|
-
if (!options.context?.instance) {
|
|
347
|
-
throw new Error("SyncEvent.process: publish requires instance context")
|
|
348
|
-
}
|
|
349
|
-
|
|
350
|
-
const result = convertEvent(def.type, event.data)
|
|
351
|
-
const publish = (data: unknown) => ProjectBus.publish(def, data as Properties<Def>, { id: event.id })
|
|
352
|
-
if (result instanceof Promise) {
|
|
353
|
-
void result.then(publish)
|
|
354
|
-
} else {
|
|
355
|
-
void publish(result)
|
|
356
|
-
}
|
|
357
|
-
|
|
358
|
-
GlobalBus.emit("event", {
|
|
359
|
-
directory: options.context.instance.directory,
|
|
360
|
-
project: options.context.instance.project.id,
|
|
361
|
-
workspace: options.context.workspace,
|
|
362
|
-
payload: {
|
|
363
|
-
type: "sync",
|
|
364
|
-
syncEvent: {
|
|
365
|
-
type: versionedType(def.type, def.version),
|
|
366
|
-
...event,
|
|
367
|
-
},
|
|
368
|
-
},
|
|
369
|
-
})
|
|
370
|
-
}
|
|
371
|
-
})
|
|
372
|
-
})
|
|
373
|
-
}
|
|
374
|
-
|
|
375
|
-
export function effectPayloads() {
|
|
376
|
-
return [
|
|
377
|
-
...registry
|
|
378
|
-
.entries()
|
|
379
|
-
.map(([type, def]) =>
|
|
380
|
-
EffectSchema.Struct({
|
|
381
|
-
type: EffectSchema.Literal("sync"),
|
|
382
|
-
name: EffectSchema.Literal(type),
|
|
383
|
-
id: EffectSchema.String,
|
|
384
|
-
seq: EffectSchema.Finite,
|
|
385
|
-
aggregateID: EffectSchema.Literal(def.aggregate),
|
|
386
|
-
data: def.schema,
|
|
387
|
-
}).annotate({ identifier: `SyncEvent.${type}` }),
|
|
388
|
-
)
|
|
389
|
-
.toArray(),
|
|
390
|
-
...EventV2.registry
|
|
391
|
-
.values()
|
|
392
|
-
.filter(
|
|
393
|
-
(definition) =>
|
|
394
|
-
definition.version !== undefined && !registry.has(versionedType(definition.type, definition.version)),
|
|
395
|
-
)
|
|
396
|
-
.map((definition) =>
|
|
397
|
-
EffectSchema.Struct({
|
|
398
|
-
type: EffectSchema.Literal("sync"),
|
|
399
|
-
name: EffectSchema.Literal(versionedType(definition.type, definition.version!)),
|
|
400
|
-
id: EffectSchema.String,
|
|
401
|
-
seq: EffectSchema.Finite,
|
|
402
|
-
aggregateID: EffectSchema.Literal(definition.aggregate!),
|
|
403
|
-
data: definition.data,
|
|
404
|
-
}).annotate({ identifier: `SyncEvent.${definition.type}` }),
|
|
405
|
-
)
|
|
406
|
-
.toArray(),
|
|
407
|
-
]
|
|
408
|
-
}
|
|
409
|
-
|
|
410
|
-
export * as SyncEvent from "."
|
|
1
|
+
// Legacy sync event system. It should stay unaware of core EventV2 execution;
|
|
2
|
+
// the only temporary V2 coupling here is exposing versioned core event schemas
|
|
3
|
+
// in effectPayloads() so existing HTTP/SDK schema generation remains stable.
|
|
4
|
+
// Remove that registry read when event schemas are generated from core directly.
|
|
5
|
+
import { Database } from "@/storage/db"
|
|
6
|
+
import { eq } from "drizzle-orm"
|
|
7
|
+
import { GlobalBus } from "@/bus/global"
|
|
8
|
+
import { Bus as ProjectBus } from "@/bus"
|
|
9
|
+
import { BusEvent } from "@/bus/bus-event"
|
|
10
|
+
import type { InstanceContext } from "@/project/instance-context"
|
|
11
|
+
import { EventSequenceTable, EventTable } from "./event.sql"
|
|
12
|
+
import type { WorkspaceID } from "@/control-plane/schema"
|
|
13
|
+
import { EventID } from "./schema"
|
|
14
|
+
import { Context, Effect, Layer, Schema as EffectSchema } from "effect"
|
|
15
|
+
import type { DeepMutable } from "@opencode-ai/core/schema"
|
|
16
|
+
import { EventV2 } from "@opencode-ai/core/event"
|
|
17
|
+
import { serviceUse } from "@/effect/service-use"
|
|
18
|
+
import { InstanceState } from "@/effect/instance-state"
|
|
19
|
+
import { RuntimeFlags } from "@/effect/runtime-flags"
|
|
20
|
+
|
|
21
|
+
// Keep `Event["data"]` mutable because projectors mutate the persisted shape
|
|
22
|
+
// when writing to the database. Bus payloads (`Properties`) stay readonly —
|
|
23
|
+
// subscribers only read.
|
|
24
|
+
|
|
25
|
+
export type Definition<
|
|
26
|
+
Type extends string = string,
|
|
27
|
+
Schema extends EffectSchema.Top = EffectSchema.Top,
|
|
28
|
+
BusSchema extends EffectSchema.Top = Schema,
|
|
29
|
+
> = {
|
|
30
|
+
type: Type
|
|
31
|
+
version: number
|
|
32
|
+
aggregate: string
|
|
33
|
+
schema: Schema
|
|
34
|
+
// Bus event payload schema. Defaults to `schema` unless `busSchema` was
|
|
35
|
+
// passed at definition time (see `session.updated`, whose projector
|
|
36
|
+
// expands the persisted data to a `{ sessionID, info }` bus payload).
|
|
37
|
+
properties: BusSchema
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
export type Event<Def extends Definition = Definition> = {
|
|
41
|
+
id: string
|
|
42
|
+
seq: number
|
|
43
|
+
aggregateID: string
|
|
44
|
+
data: DeepMutable<EffectSchema.Schema.Type<Def["schema"]>>
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
export type Properties<Def extends Definition = Definition> = EffectSchema.Schema.Type<Def["properties"]>
|
|
48
|
+
|
|
49
|
+
export type SerializedEvent<Def extends Definition = Definition> = Event<Def> & { type: string }
|
|
50
|
+
|
|
51
|
+
type ProjectorFunc = (db: Database.TxOrDb, data: unknown, event: Event) => void
|
|
52
|
+
type ConvertEvent = (type: string, data: Event["data"]) => unknown | Promise<unknown>
|
|
53
|
+
type PublishContext = {
|
|
54
|
+
instance?: InstanceContext
|
|
55
|
+
workspace?: WorkspaceID
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
export interface Interface {
|
|
59
|
+
readonly run: <Def extends Definition>(
|
|
60
|
+
def: Def,
|
|
61
|
+
data: Event<Def>["data"],
|
|
62
|
+
options?: { publish?: boolean },
|
|
63
|
+
) => Effect.Effect<void>
|
|
64
|
+
readonly replay: (event: SerializedEvent, options?: { publish: boolean; ownerID?: string }) => Effect.Effect<void>
|
|
65
|
+
readonly replayAll: (
|
|
66
|
+
events: SerializedEvent[],
|
|
67
|
+
options?: { publish: boolean; ownerID?: string },
|
|
68
|
+
) => Effect.Effect<string | undefined>
|
|
69
|
+
readonly remove: (aggregateID: string) => Effect.Effect<void>
|
|
70
|
+
readonly claim: (aggregateID: string, ownerID: string) => Effect.Effect<void>
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
export class Service extends Context.Service<Service, Interface>()("@opencode/SyncEvent") {}
|
|
74
|
+
|
|
75
|
+
export const layer = Layer.effect(Service)(
|
|
76
|
+
Effect.gen(function* () {
|
|
77
|
+
const flags = yield* RuntimeFlags.Service
|
|
78
|
+
|
|
79
|
+
const replay: Interface["replay"] = Effect.fn("SyncEvent.replay")(function* (event, options) {
|
|
80
|
+
const def = registry.get(event.type)
|
|
81
|
+
if (!def) {
|
|
82
|
+
throw new Error(`Unknown event type: ${event.type}`)
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
const row = Database.use((db) =>
|
|
86
|
+
db
|
|
87
|
+
.select({ seq: EventSequenceTable.seq, ownerID: EventSequenceTable.owner_id })
|
|
88
|
+
.from(EventSequenceTable)
|
|
89
|
+
.where(eq(EventSequenceTable.aggregate_id, event.aggregateID))
|
|
90
|
+
.get(),
|
|
91
|
+
)
|
|
92
|
+
|
|
93
|
+
const latest = row?.seq ?? -1
|
|
94
|
+
if (event.seq <= latest) return
|
|
95
|
+
|
|
96
|
+
if (row?.ownerID && row.ownerID !== options?.ownerID) {
|
|
97
|
+
return
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
const expected = latest + 1
|
|
101
|
+
if (event.seq !== expected) {
|
|
102
|
+
throw new Error(
|
|
103
|
+
`Sequence mismatch for aggregate "${event.aggregateID}": expected ${expected}, got ${event.seq}`,
|
|
104
|
+
)
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
const publish = !!options?.publish
|
|
108
|
+
const context = publish
|
|
109
|
+
? {
|
|
110
|
+
instance: yield* InstanceState.context,
|
|
111
|
+
workspace: yield* InstanceState.workspaceID,
|
|
112
|
+
}
|
|
113
|
+
: undefined
|
|
114
|
+
process(def, event, {
|
|
115
|
+
publish,
|
|
116
|
+
context,
|
|
117
|
+
ownerID: options?.ownerID,
|
|
118
|
+
experimentalWorkspaces: flags.experimentalWorkspaces,
|
|
119
|
+
})
|
|
120
|
+
})
|
|
121
|
+
|
|
122
|
+
const replayAll: Interface["replayAll"] = Effect.fn("SyncEvent.replayAll")(function* (events, options) {
|
|
123
|
+
const source = events[0]?.aggregateID
|
|
124
|
+
if (!source) return undefined
|
|
125
|
+
if (events.some((item) => item.aggregateID !== source)) {
|
|
126
|
+
throw new Error("Replay events must belong to the same session")
|
|
127
|
+
}
|
|
128
|
+
const start = events[0].seq
|
|
129
|
+
for (const [i, item] of events.entries()) {
|
|
130
|
+
const seq = start + i
|
|
131
|
+
if (item.seq !== seq) {
|
|
132
|
+
throw new Error(`Replay sequence mismatch at index ${i}: expected ${seq}, got ${item.seq}`)
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
for (const item of events) {
|
|
136
|
+
yield* replay(item, options)
|
|
137
|
+
}
|
|
138
|
+
return source
|
|
139
|
+
})
|
|
140
|
+
|
|
141
|
+
const run: Interface["run"] = Effect.fn("SyncEvent.run")(function* (def, data, options) {
|
|
142
|
+
const agg = (data as Record<string, string>)[def.aggregate]
|
|
143
|
+
// This should never happen: we've enforced it via typescript in
|
|
144
|
+
// the definition
|
|
145
|
+
if (agg == null) {
|
|
146
|
+
throw new Error(`SyncEvent.run: "${def.aggregate}" required but not found: ${JSON.stringify(data)}`)
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
if (def.version !== versions.get(def.type)) {
|
|
150
|
+
throw new Error(`SyncEvent.run: running old versions of events is not allowed: ${def.type}`)
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
const { publish = true } = options || {}
|
|
154
|
+
const context = publish
|
|
155
|
+
? {
|
|
156
|
+
instance: yield* InstanceState.context,
|
|
157
|
+
workspace: yield* InstanceState.workspaceID,
|
|
158
|
+
}
|
|
159
|
+
: undefined
|
|
160
|
+
|
|
161
|
+
// Note that this is an "immediate" transaction which is critical.
|
|
162
|
+
// We need to make sure we can safely read and write with nothing
|
|
163
|
+
// else changing the data from under us
|
|
164
|
+
Database.transaction(
|
|
165
|
+
(tx) => {
|
|
166
|
+
const id = EventID.ascending()
|
|
167
|
+
const row = tx
|
|
168
|
+
.select({ seq: EventSequenceTable.seq })
|
|
169
|
+
.from(EventSequenceTable)
|
|
170
|
+
.where(eq(EventSequenceTable.aggregate_id, agg))
|
|
171
|
+
.get()
|
|
172
|
+
const seq = row?.seq != null ? row.seq + 1 : 0
|
|
173
|
+
|
|
174
|
+
const event = { id, seq, aggregateID: agg, data }
|
|
175
|
+
process(def, event, { publish, context, experimentalWorkspaces: flags.experimentalWorkspaces })
|
|
176
|
+
},
|
|
177
|
+
{
|
|
178
|
+
behavior: "immediate",
|
|
179
|
+
},
|
|
180
|
+
)
|
|
181
|
+
})
|
|
182
|
+
|
|
183
|
+
const remove: Interface["remove"] = Effect.fn("SyncEvent.remove")(function* (aggregateID) {
|
|
184
|
+
Database.transaction((tx) => {
|
|
185
|
+
tx.delete(EventSequenceTable).where(eq(EventSequenceTable.aggregate_id, aggregateID)).run()
|
|
186
|
+
tx.delete(EventTable).where(eq(EventTable.aggregate_id, aggregateID)).run()
|
|
187
|
+
})
|
|
188
|
+
})
|
|
189
|
+
|
|
190
|
+
const claim: Interface["claim"] = Effect.fn("SyncEvent.claim")((aggregateID, ownerID) =>
|
|
191
|
+
Effect.sync(() =>
|
|
192
|
+
Database.use((db) =>
|
|
193
|
+
db
|
|
194
|
+
.update(EventSequenceTable)
|
|
195
|
+
.set({ owner_id: ownerID })
|
|
196
|
+
.where(eq(EventSequenceTable.aggregate_id, aggregateID))
|
|
197
|
+
.run(),
|
|
198
|
+
),
|
|
199
|
+
),
|
|
200
|
+
)
|
|
201
|
+
|
|
202
|
+
return Service.of({
|
|
203
|
+
run,
|
|
204
|
+
replay,
|
|
205
|
+
replayAll,
|
|
206
|
+
remove,
|
|
207
|
+
claim,
|
|
208
|
+
})
|
|
209
|
+
}),
|
|
210
|
+
)
|
|
211
|
+
|
|
212
|
+
export const defaultLayer = layer.pipe(Layer.provide(RuntimeFlags.defaultLayer))
|
|
213
|
+
|
|
214
|
+
export const use = serviceUse(Service)
|
|
215
|
+
|
|
216
|
+
export const registry = new Map<string, Definition>()
|
|
217
|
+
let projectors: Map<string, ProjectorFunc> | undefined
|
|
218
|
+
const versions = new Map<string, number>()
|
|
219
|
+
let frozen = false
|
|
220
|
+
let convertEvent: ConvertEvent
|
|
221
|
+
|
|
222
|
+
export function reset() {
|
|
223
|
+
frozen = false
|
|
224
|
+
projectors = undefined
|
|
225
|
+
convertEvent = (_, data) => data
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
export function init(input: { projectors: Array<[Definition, ProjectorFunc]>; convertEvent?: ConvertEvent }) {
|
|
229
|
+
projectors = new Map(input.projectors.map(([def, func]) => [versionedType(def.type, def.version), func]))
|
|
230
|
+
for (let entry of EventV2.registry.values()) {
|
|
231
|
+
if (!entry.version || !entry.aggregate) continue
|
|
232
|
+
register({
|
|
233
|
+
type: entry.type,
|
|
234
|
+
version: entry.version,
|
|
235
|
+
aggregate: entry.aggregate,
|
|
236
|
+
properties: entry.data,
|
|
237
|
+
schema: entry.data,
|
|
238
|
+
})
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
// Install all the latest event defs to the bus. We only ever emit
|
|
242
|
+
// latest versions from code, and keep around old versions for
|
|
243
|
+
// replaying. Replaying does not go through the bus, and it
|
|
244
|
+
// simplifies the bus to only use unversioned latest events
|
|
245
|
+
for (let [type, version] of versions.entries()) {
|
|
246
|
+
let def = registry.get(versionedType(type, version))!
|
|
247
|
+
BusEvent.define(def.type, def.properties)
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
// Freeze the system so it clearly errors if events are defined
|
|
251
|
+
// after `init` which would cause bugs
|
|
252
|
+
frozen = true
|
|
253
|
+
convertEvent = input.convertEvent ?? ((_, data) => data)
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
export function versionedType<A extends string>(type: A): A
|
|
257
|
+
export function versionedType<A extends string, B extends number>(type: A, version: B): `${A}/${B}`
|
|
258
|
+
export function versionedType(type: string, version?: number) {
|
|
259
|
+
return version ? `${type}.${version}` : type
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
export function define<
|
|
263
|
+
Type extends string,
|
|
264
|
+
Agg extends string,
|
|
265
|
+
Schema extends EffectSchema.Top,
|
|
266
|
+
BusSchema extends EffectSchema.Top = Schema,
|
|
267
|
+
>(input: {
|
|
268
|
+
type: Type
|
|
269
|
+
version: number
|
|
270
|
+
aggregate: Agg
|
|
271
|
+
schema: Schema
|
|
272
|
+
busSchema?: BusSchema
|
|
273
|
+
}): Definition<Type, Schema, BusSchema> {
|
|
274
|
+
if (frozen) {
|
|
275
|
+
throw new Error("Error defining sync event: sync system has been frozen")
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
const def = {
|
|
279
|
+
type: input.type,
|
|
280
|
+
version: input.version,
|
|
281
|
+
aggregate: input.aggregate,
|
|
282
|
+
schema: input.schema,
|
|
283
|
+
properties: (input.busSchema ?? input.schema) as BusSchema,
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
register(def)
|
|
287
|
+
|
|
288
|
+
return def
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
export function project<Def extends Definition>(
|
|
292
|
+
def: Def,
|
|
293
|
+
func: (db: Database.TxOrDb, data: Event<Def>["data"], event: Event<Def>) => void,
|
|
294
|
+
): [Definition, ProjectorFunc] {
|
|
295
|
+
return [def, func as ProjectorFunc]
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
function register(def: Definition) {
|
|
299
|
+
versions.set(def.type, Math.max(def.version, versions.get(def.type) || 0))
|
|
300
|
+
registry.set(versionedType(def.type, def.version), def)
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
function process<Def extends Definition>(
|
|
304
|
+
def: Def,
|
|
305
|
+
event: Event<Def>,
|
|
306
|
+
options: { publish: boolean; context?: PublishContext; ownerID?: string; experimentalWorkspaces: boolean },
|
|
307
|
+
) {
|
|
308
|
+
if (projectors == null) {
|
|
309
|
+
throw new Error("No projectors available. Call `SyncEvent.init` to install projectors")
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
const projector = projectors.get(versionedType(def.type, def.version))
|
|
313
|
+
if (!projector) {
|
|
314
|
+
if (!def.type.includes("next")) throw new Error(`Projector not found for event: ${def.type}`)
|
|
315
|
+
return
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
Database.transaction((tx) => {
|
|
319
|
+
projector(tx, event.data, event)
|
|
320
|
+
|
|
321
|
+
if (options.experimentalWorkspaces) {
|
|
322
|
+
tx.insert(EventSequenceTable)
|
|
323
|
+
.values({
|
|
324
|
+
aggregate_id: event.aggregateID,
|
|
325
|
+
seq: event.seq,
|
|
326
|
+
owner_id: options?.ownerID,
|
|
327
|
+
})
|
|
328
|
+
.onConflictDoUpdate({
|
|
329
|
+
target: EventSequenceTable.aggregate_id,
|
|
330
|
+
set: { seq: event.seq },
|
|
331
|
+
})
|
|
332
|
+
.run()
|
|
333
|
+
tx.insert(EventTable)
|
|
334
|
+
.values({
|
|
335
|
+
id: event.id,
|
|
336
|
+
seq: event.seq,
|
|
337
|
+
aggregate_id: event.aggregateID,
|
|
338
|
+
type: versionedType(def.type, def.version),
|
|
339
|
+
data: event.data as Record<string, unknown>,
|
|
340
|
+
})
|
|
341
|
+
.run()
|
|
342
|
+
}
|
|
343
|
+
|
|
344
|
+
Database.effect(() => {
|
|
345
|
+
if (options?.publish) {
|
|
346
|
+
if (!options.context?.instance) {
|
|
347
|
+
throw new Error("SyncEvent.process: publish requires instance context")
|
|
348
|
+
}
|
|
349
|
+
|
|
350
|
+
const result = convertEvent(def.type, event.data)
|
|
351
|
+
const publish = (data: unknown) => ProjectBus.publish(def, data as Properties<Def>, { id: event.id })
|
|
352
|
+
if (result instanceof Promise) {
|
|
353
|
+
void result.then(publish)
|
|
354
|
+
} else {
|
|
355
|
+
void publish(result)
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
GlobalBus.emit("event", {
|
|
359
|
+
directory: options.context.instance.directory,
|
|
360
|
+
project: options.context.instance.project.id,
|
|
361
|
+
workspace: options.context.workspace,
|
|
362
|
+
payload: {
|
|
363
|
+
type: "sync",
|
|
364
|
+
syncEvent: {
|
|
365
|
+
type: versionedType(def.type, def.version),
|
|
366
|
+
...event,
|
|
367
|
+
},
|
|
368
|
+
},
|
|
369
|
+
})
|
|
370
|
+
}
|
|
371
|
+
})
|
|
372
|
+
})
|
|
373
|
+
}
|
|
374
|
+
|
|
375
|
+
export function effectPayloads() {
|
|
376
|
+
return [
|
|
377
|
+
...registry
|
|
378
|
+
.entries()
|
|
379
|
+
.map(([type, def]) =>
|
|
380
|
+
EffectSchema.Struct({
|
|
381
|
+
type: EffectSchema.Literal("sync"),
|
|
382
|
+
name: EffectSchema.Literal(type),
|
|
383
|
+
id: EffectSchema.String,
|
|
384
|
+
seq: EffectSchema.Finite,
|
|
385
|
+
aggregateID: EffectSchema.Literal(def.aggregate),
|
|
386
|
+
data: def.schema,
|
|
387
|
+
}).annotate({ identifier: `SyncEvent.${type}` }),
|
|
388
|
+
)
|
|
389
|
+
.toArray(),
|
|
390
|
+
...EventV2.registry
|
|
391
|
+
.values()
|
|
392
|
+
.filter(
|
|
393
|
+
(definition) =>
|
|
394
|
+
definition.version !== undefined && !registry.has(versionedType(definition.type, definition.version)),
|
|
395
|
+
)
|
|
396
|
+
.map((definition) =>
|
|
397
|
+
EffectSchema.Struct({
|
|
398
|
+
type: EffectSchema.Literal("sync"),
|
|
399
|
+
name: EffectSchema.Literal(versionedType(definition.type, definition.version!)),
|
|
400
|
+
id: EffectSchema.String,
|
|
401
|
+
seq: EffectSchema.Finite,
|
|
402
|
+
aggregateID: EffectSchema.Literal(definition.aggregate!),
|
|
403
|
+
data: definition.data,
|
|
404
|
+
}).annotate({ identifier: `SyncEvent.${definition.type}` }),
|
|
405
|
+
)
|
|
406
|
+
.toArray(),
|
|
407
|
+
]
|
|
408
|
+
}
|
|
409
|
+
|
|
410
|
+
export * as SyncEvent from "."
|