@askdkc/kiokuko 0.1.17 → 0.1.19
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/README.ja.md +91 -112
- package/README.ko.md +90 -102
- package/README.md +103 -262
- package/README.zh-CN.md +88 -102
- package/dist/agent-file/atomic-write.d.ts +90 -3
- package/dist/agent-file/atomic-write.d.ts.map +1 -1
- package/dist/agent-file/atomic-write.js +990 -14
- package/dist/agent-file/atomic-write.js.map +1 -1
- package/dist/agent-file/managed-block.d.ts +12 -1
- package/dist/agent-file/managed-block.d.ts.map +1 -1
- package/dist/agent-file/managed-block.js +49 -4
- package/dist/agent-file/managed-block.js.map +1 -1
- package/dist/agent-file/render.d.ts +1 -1
- package/dist/agent-file/render.d.ts.map +1 -1
- package/dist/agent-file/render.js +10 -7
- package/dist/agent-file/render.js.map +1 -1
- package/dist/akinator/agent-task.d.ts +11 -22
- package/dist/akinator/agent-task.d.ts.map +1 -1
- package/dist/akinator/agent-task.js +454 -99
- package/dist/akinator/agent-task.js.map +1 -1
- package/dist/akinator/capabilities.d.ts +18 -6
- package/dist/akinator/capabilities.d.ts.map +1 -1
- package/dist/akinator/capabilities.js +72 -35
- package/dist/akinator/capabilities.js.map +1 -1
- package/dist/akinator/capability-binding.d.ts +11 -0
- package/dist/akinator/capability-binding.d.ts.map +1 -0
- package/dist/akinator/capability-binding.js +56 -0
- package/dist/akinator/capability-binding.js.map +1 -0
- package/dist/akinator/domain.js +2 -2
- package/dist/akinator/domain.js.map +1 -1
- package/dist/akinator/knowledge-path.d.ts.map +1 -1
- package/dist/akinator/knowledge-path.js +409 -39
- package/dist/akinator/knowledge-path.js.map +1 -1
- package/dist/akinator/orchestrator.d.ts +3 -4
- package/dist/akinator/orchestrator.d.ts.map +1 -1
- package/dist/akinator/orchestrator.js +1 -4
- package/dist/akinator/orchestrator.js.map +1 -1
- package/dist/akinator/service.d.ts +0 -4
- package/dist/akinator/service.d.ts.map +1 -1
- package/dist/akinator/service.js +19 -35
- package/dist/akinator/service.js.map +1 -1
- package/dist/akinator/skill-discovery-attempt.d.ts +20 -0
- package/dist/akinator/skill-discovery-attempt.d.ts.map +1 -0
- package/dist/akinator/skill-discovery-attempt.js +390 -0
- package/dist/akinator/skill-discovery-attempt.js.map +1 -0
- package/dist/akinator/store.d.ts.map +1 -1
- package/dist/akinator/store.js +107 -52
- package/dist/akinator/store.js.map +1 -1
- package/dist/akinator/types.d.ts +0 -12
- package/dist/akinator/types.d.ts.map +1 -1
- package/dist/bin/kiokuko.js +0 -0
- package/dist/cli.d.ts +2 -0
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +534 -148
- package/dist/cli.js.map +1 -1
- package/dist/client/server-client.d.ts +5 -3
- package/dist/client/server-client.d.ts.map +1 -1
- package/dist/client/server-client.js +486 -181
- package/dist/client/server-client.js.map +1 -1
- package/dist/commands/agent.d.ts +2 -0
- package/dist/commands/agent.d.ts.map +1 -1
- package/dist/commands/agent.js +861 -86
- package/dist/commands/agent.js.map +1 -1
- package/dist/commands/backup.d.ts +2 -1
- package/dist/commands/backup.d.ts.map +1 -1
- package/dist/commands/backup.js +64 -8
- package/dist/commands/backup.js.map +1 -1
- package/dist/commands/doctor.d.ts +5 -1
- package/dist/commands/doctor.d.ts.map +1 -1
- package/dist/commands/doctor.js +70 -26
- package/dist/commands/doctor.js.map +1 -1
- package/dist/commands/export.d.ts +0 -4
- package/dist/commands/export.d.ts.map +1 -1
- package/dist/commands/export.js +191 -32
- package/dist/commands/export.js.map +1 -1
- package/dist/commands/import.d.ts +10 -1
- package/dist/commands/import.d.ts.map +1 -1
- package/dist/commands/import.js +592 -113
- package/dist/commands/import.js.map +1 -1
- package/dist/commands/init.d.ts +19 -1
- package/dist/commands/init.d.ts.map +1 -1
- package/dist/commands/init.js +569 -22
- package/dist/commands/init.js.map +1 -1
- package/dist/commands/purge.d.ts.map +1 -1
- package/dist/commands/purge.js +3 -0
- package/dist/commands/purge.js.map +1 -1
- package/dist/commands/setup.d.ts +34 -8
- package/dist/commands/setup.d.ts.map +1 -1
- package/dist/commands/setup.js +418 -86
- package/dist/commands/setup.js.map +1 -1
- package/dist/commands/skills.d.ts +9 -0
- package/dist/commands/skills.d.ts.map +1 -0
- package/dist/commands/skills.js +317 -0
- package/dist/commands/skills.js.map +1 -0
- package/dist/commands/use.d.ts +10 -2
- package/dist/commands/use.d.ts.map +1 -1
- package/dist/commands/use.js +851 -73
- package/dist/commands/use.js.map +1 -1
- package/dist/config/paths.d.ts +11 -1
- package/dist/config/paths.d.ts.map +1 -1
- package/dist/config/paths.js +64 -29
- package/dist/config/paths.js.map +1 -1
- package/dist/config/project-config.d.ts +1 -0
- package/dist/config/project-config.d.ts.map +1 -1
- package/dist/config/project-config.js +70 -32
- package/dist/config/project-config.js.map +1 -1
- package/dist/context/broker.d.ts +28 -14
- package/dist/context/broker.d.ts.map +1 -1
- package/dist/context/broker.js +604 -145
- package/dist/context/broker.js.map +1 -1
- package/dist/context/delivery.d.ts +6 -21
- package/dist/context/delivery.d.ts.map +1 -1
- package/dist/context/delivery.js +196 -147
- package/dist/context/delivery.js.map +1 -1
- package/dist/context/feedback.d.ts +11 -12
- package/dist/context/feedback.d.ts.map +1 -1
- package/dist/context/feedback.js +229 -261
- package/dist/context/feedback.js.map +1 -1
- package/dist/context/ranking.d.ts +1 -12
- package/dist/context/ranking.d.ts.map +1 -1
- package/dist/context/ranking.js +13 -4
- package/dist/context/ranking.js.map +1 -1
- package/dist/context/recommendations.d.ts +0 -5
- package/dist/context/recommendations.d.ts.map +1 -1
- package/dist/context/recommendations.js +0 -1
- package/dist/context/recommendations.js.map +1 -1
- package/dist/context/run-state.d.ts +26 -0
- package/dist/context/run-state.d.ts.map +1 -0
- package/dist/context/run-state.js +399 -0
- package/dist/context/run-state.js.map +1 -0
- package/dist/context/scoped-broker.d.ts +17 -5
- package/dist/context/scoped-broker.d.ts.map +1 -1
- package/dist/context/scoped-broker.js +512 -106
- package/dist/context/scoped-broker.js.map +1 -1
- package/dist/context/selection-state.d.ts +19 -0
- package/dist/context/selection-state.d.ts.map +1 -0
- package/dist/context/selection-state.js +250 -0
- package/dist/context/selection-state.js.map +1 -0
- package/dist/db/adapter.d.ts +5 -3
- package/dist/db/adapter.d.ts.map +1 -1
- package/dist/db/adapter.js +6 -3
- package/dist/db/adapter.js.map +1 -1
- package/dist/db/capabilities.d.ts.map +1 -1
- package/dist/db/capabilities.js +34 -16
- package/dist/db/capabilities.js.map +1 -1
- package/dist/db/connection.d.ts +8 -0
- package/dist/db/connection.d.ts.map +1 -1
- package/dist/db/connection.js +55 -26
- package/dist/db/connection.js.map +1 -1
- package/dist/db/migrate.d.ts +28 -7
- package/dist/db/migrate.d.ts.map +1 -1
- package/dist/db/migrate.js +106 -78
- package/dist/db/migrate.js.map +1 -1
- package/dist/db/sqlite-retry.d.ts +11 -0
- package/dist/db/sqlite-retry.d.ts.map +1 -0
- package/dist/db/sqlite-retry.js +66 -0
- package/dist/db/sqlite-retry.js.map +1 -0
- package/dist/db/transaction.d.ts +13 -0
- package/dist/db/transaction.d.ts.map +1 -1
- package/dist/db/transaction.js +53 -24
- package/dist/db/transaction.js.map +1 -1
- package/dist/db/upgrade-backup.d.ts +58 -2
- package/dist/db/upgrade-backup.d.ts.map +1 -1
- package/dist/db/upgrade-backup.js +757 -28
- package/dist/db/upgrade-backup.js.map +1 -1
- package/dist/errors.js +1 -1
- package/dist/errors.js.map +1 -1
- package/dist/gateway/agent-service.d.ts +4 -1
- package/dist/gateway/agent-service.d.ts.map +1 -1
- package/dist/gateway/agent-service.js +71 -58
- package/dist/gateway/agent-service.js.map +1 -1
- package/dist/gateway/checkpoint-service.d.ts +1 -0
- package/dist/gateway/checkpoint-service.d.ts.map +1 -1
- package/dist/gateway/checkpoint-service.js +47 -24
- package/dist/gateway/checkpoint-service.js.map +1 -1
- package/dist/ledger/archive.d.ts +1 -4
- package/dist/ledger/archive.d.ts.map +1 -1
- package/dist/ledger/archive.js +77 -39
- package/dist/ledger/archive.js.map +1 -1
- package/dist/ledger/maintenance.d.ts +0 -11
- package/dist/ledger/maintenance.d.ts.map +1 -1
- package/dist/ledger/maintenance.js +24 -40
- package/dist/ledger/maintenance.js.map +1 -1
- package/dist/ledger/projection.d.ts +0 -1
- package/dist/ledger/projection.d.ts.map +1 -1
- package/dist/ledger/projection.js.map +1 -1
- package/dist/ledger/promotion.d.ts +0 -9
- package/dist/ledger/promotion.d.ts.map +1 -1
- package/dist/ledger/promotion.js.map +1 -1
- package/dist/ledger/query.d.ts +1 -15
- package/dist/ledger/query.d.ts.map +1 -1
- package/dist/ledger/query.js.map +1 -1
- package/dist/ledger/store.d.ts +0 -1
- package/dist/ledger/store.d.ts.map +1 -1
- package/dist/ledger/store.js +11 -8
- package/dist/ledger/store.js.map +1 -1
- package/dist/ledger/types.d.ts +0 -4
- package/dist/ledger/types.d.ts.map +1 -1
- package/dist/ledger/types.js.map +1 -1
- package/dist/ledger/validate.d.ts.map +1 -1
- package/dist/ledger/validate.js +0 -5
- package/dist/ledger/validate.js.map +1 -1
- package/dist/mcp/server.d.ts +4 -0
- package/dist/mcp/server.d.ts.map +1 -1
- package/dist/mcp/server.js +105 -54
- package/dist/mcp/server.js.map +1 -1
- package/dist/memory/audit.d.ts +0 -1
- package/dist/memory/audit.d.ts.map +1 -1
- package/dist/memory/audit.js +0 -1
- package/dist/memory/audit.js.map +1 -1
- package/dist/memory/curator.d.ts.map +1 -1
- package/dist/memory/curator.js +172 -96
- package/dist/memory/curator.js.map +1 -1
- package/dist/memory/entries.d.ts +12 -2
- package/dist/memory/entries.d.ts.map +1 -1
- package/dist/memory/entries.js +198 -114
- package/dist/memory/entries.js.map +1 -1
- package/dist/memory/federated-retrieval.d.ts +12 -1
- package/dist/memory/federated-retrieval.d.ts.map +1 -1
- package/dist/memory/federated-retrieval.js +183 -70
- package/dist/memory/federated-retrieval.js.map +1 -1
- package/dist/memory/hybrid-retrieval.d.ts +5 -11
- package/dist/memory/hybrid-retrieval.d.ts.map +1 -1
- package/dist/memory/hybrid-retrieval.js +78 -58
- package/dist/memory/hybrid-retrieval.js.map +1 -1
- package/dist/memory/lifecycle.d.ts.map +1 -1
- package/dist/memory/lifecycle.js +17 -13
- package/dist/memory/lifecycle.js.map +1 -1
- package/dist/memory/rebuild-search.d.ts +5 -0
- package/dist/memory/rebuild-search.d.ts.map +1 -1
- package/dist/memory/rebuild-search.js +101 -76
- package/dist/memory/rebuild-search.js.map +1 -1
- package/dist/memory/retrieval-query.d.ts +0 -5
- package/dist/memory/retrieval-query.d.ts.map +1 -1
- package/dist/memory/retrieval-query.js +0 -5
- package/dist/memory/retrieval-query.js.map +1 -1
- package/dist/memory/retrieval.d.ts.map +1 -1
- package/dist/memory/retrieval.js +25 -131
- package/dist/memory/retrieval.js.map +1 -1
- package/dist/memory/revisions.d.ts +76 -1
- package/dist/memory/revisions.d.ts.map +1 -1
- package/dist/memory/revisions.js +539 -35
- package/dist/memory/revisions.js.map +1 -1
- package/dist/memory/scoped-memory.d.ts +16 -1
- package/dist/memory/scoped-memory.d.ts.map +1 -1
- package/dist/memory/scoped-memory.js +240 -107
- package/dist/memory/scoped-memory.js.map +1 -1
- package/dist/memory/secrets.d.ts +2 -0
- package/dist/memory/secrets.d.ts.map +1 -1
- package/dist/memory/secrets.js +36 -0
- package/dist/memory/secrets.js.map +1 -1
- package/dist/memory/structured-memory.d.ts +3 -2
- package/dist/memory/structured-memory.d.ts.map +1 -1
- package/dist/memory/structured-memory.js +54 -22
- package/dist/memory/structured-memory.js.map +1 -1
- package/dist/memory/workspaces.d.ts +9 -0
- package/dist/memory/workspaces.d.ts.map +1 -1
- package/dist/memory/workspaces.js +67 -0
- package/dist/memory/workspaces.js.map +1 -1
- package/dist/package-version.d.ts +2 -0
- package/dist/package-version.d.ts.map +1 -0
- package/dist/package-version.js +7 -0
- package/dist/package-version.js.map +1 -0
- package/dist/repository/binding.d.ts +5 -0
- package/dist/repository/binding.d.ts.map +1 -1
- package/dist/repository/binding.js +117 -17
- package/dist/repository/binding.js.map +1 -1
- package/dist/repository/framework-version.d.ts +8 -0
- package/dist/repository/framework-version.d.ts.map +1 -0
- package/dist/repository/framework-version.js +29 -0
- package/dist/repository/framework-version.js.map +1 -0
- package/dist/repository/identity-value.d.ts +4 -0
- package/dist/repository/identity-value.d.ts.map +1 -0
- package/dist/repository/identity-value.js +24 -0
- package/dist/repository/identity-value.js.map +1 -0
- package/dist/repository/identity.d.ts.map +1 -1
- package/dist/repository/identity.js +2 -0
- package/dist/repository/identity.js.map +1 -1
- package/dist/repository/project-fingerprint.d.ts +14 -2
- package/dist/repository/project-fingerprint.d.ts.map +1 -1
- package/dist/repository/project-fingerprint.js +312 -33
- package/dist/repository/project-fingerprint.js.map +1 -1
- package/dist/repository/remote-url.d.ts +0 -1
- package/dist/repository/remote-url.d.ts.map +1 -1
- package/dist/repository/remote-url.js +0 -1
- package/dist/repository/remote-url.js.map +1 -1
- package/dist/runtime-version.d.ts +2 -1
- package/dist/runtime-version.d.ts.map +1 -1
- package/dist/runtime-version.js +21 -4
- package/dist/runtime-version.js.map +1 -1
- package/dist/serialization/boundary-json.d.ts +20 -0
- package/dist/serialization/boundary-json.d.ts.map +1 -0
- package/dist/serialization/boundary-json.js +129 -0
- package/dist/serialization/boundary-json.js.map +1 -0
- package/dist/serialization/envelope.js +1 -1
- package/dist/serialization/envelope.js.map +1 -1
- package/dist/serialization/validate.d.ts +7 -0
- package/dist/serialization/validate.d.ts.map +1 -1
- package/dist/serialization/validate.js +53 -13
- package/dist/serialization/validate.js.map +1 -1
- package/dist/server/app.js +1 -1
- package/dist/server/app.js.map +1 -1
- package/dist/server/http.d.ts +4 -3
- package/dist/server/http.d.ts.map +1 -1
- package/dist/server/http.js +90 -50
- package/dist/server/http.js.map +1 -1
- package/dist/server/idempotency.d.ts +0 -6
- package/dist/server/idempotency.d.ts.map +1 -1
- package/dist/server/idempotency.js.map +1 -1
- package/dist/server/router.d.ts.map +1 -1
- package/dist/server/router.js +21 -4
- package/dist/server/router.js.map +1 -1
- package/dist/server/routes/agent-capability-gate.d.ts +40 -0
- package/dist/server/routes/agent-capability-gate.d.ts.map +1 -0
- package/dist/server/routes/agent-capability-gate.js +182 -0
- package/dist/server/routes/agent-capability-gate.js.map +1 -0
- package/dist/server/routes/agent-events.d.ts.map +1 -1
- package/dist/server/routes/agent-events.js +8 -1
- package/dist/server/routes/agent-events.js.map +1 -1
- package/dist/server/routes/agent-intake.d.ts.map +1 -1
- package/dist/server/routes/agent-intake.js +10 -2
- package/dist/server/routes/agent-intake.js.map +1 -1
- package/dist/server/routes/agent-promotions.d.ts.map +1 -1
- package/dist/server/routes/agent-promotions.js +5 -2
- package/dist/server/routes/agent-promotions.js.map +1 -1
- package/dist/server/routes/agent-runs.d.ts.map +1 -1
- package/dist/server/routes/agent-runs.js +18 -4
- package/dist/server/routes/agent-runs.js.map +1 -1
- package/dist/server/routes/request-binding.d.ts +5 -0
- package/dist/server/routes/request-binding.d.ts.map +1 -0
- package/dist/server/routes/request-binding.js +49 -0
- package/dist/server/routes/request-binding.js.map +1 -0
- package/dist/server/routes/task5-support.d.ts +1 -8
- package/dist/server/routes/task5-support.d.ts.map +1 -1
- package/dist/server/routes/task5-support.js +1 -17
- package/dist/server/routes/task5-support.js.map +1 -1
- package/dist/server/routes/task5.d.ts.map +1 -1
- package/dist/server/routes/task5.js +106 -36
- package/dist/server/routes/task5.js.map +1 -1
- package/dist/server/write-queue.js +2 -2
- package/dist/server/write-queue.js.map +1 -1
- package/dist/setup/claude-config.d.ts +2 -1
- package/dist/setup/claude-config.d.ts.map +1 -1
- package/dist/setup/claude-config.js +54 -4
- package/dist/setup/claude-config.js.map +1 -1
- package/dist/setup/client-detection.d.ts +7 -2
- package/dist/setup/client-detection.d.ts.map +1 -1
- package/dist/setup/client-detection.js +27 -9
- package/dist/setup/client-detection.js.map +1 -1
- package/dist/setup/hermes-config.d.ts +2 -1
- package/dist/setup/hermes-config.d.ts.map +1 -1
- package/dist/setup/hermes-config.js +53 -12
- package/dist/setup/hermes-config.js.map +1 -1
- package/dist/setup/legacy-client-cleanup.d.ts +6 -0
- package/dist/setup/legacy-client-cleanup.d.ts.map +1 -0
- package/dist/setup/legacy-client-cleanup.js +152 -0
- package/dist/setup/legacy-client-cleanup.js.map +1 -0
- package/dist/setup/managed-text.d.ts.map +1 -1
- package/dist/setup/managed-text.js +11 -1
- package/dist/setup/managed-text.js.map +1 -1
- package/dist/setup/opencode-config.d.ts +2 -1
- package/dist/setup/opencode-config.d.ts.map +1 -1
- package/dist/setup/opencode-config.js +57 -5
- package/dist/setup/opencode-config.js.map +1 -1
- package/dist/setup/render.d.ts +2 -1
- package/dist/setup/render.d.ts.map +1 -1
- package/dist/setup/render.js +91 -17
- package/dist/setup/render.js.map +1 -1
- package/dist/setup/standard-skills.d.ts +16 -2
- package/dist/setup/standard-skills.d.ts.map +1 -1
- package/dist/setup/standard-skills.js +37 -13
- package/dist/setup/standard-skills.js.map +1 -1
- package/dist/setup/strict-json.d.ts +7 -0
- package/dist/setup/strict-json.d.ts.map +1 -0
- package/dist/setup/strict-json.js +98 -0
- package/dist/setup/strict-json.js.map +1 -0
- package/dist/setup/strict-toml.d.ts +7 -0
- package/dist/setup/strict-toml.d.ts.map +1 -0
- package/dist/setup/strict-toml.js +470 -0
- package/dist/setup/strict-toml.js.map +1 -0
- package/dist/skills/cache.d.ts +15 -0
- package/dist/skills/cache.d.ts.map +1 -0
- package/dist/skills/cache.js +19 -0
- package/dist/skills/cache.js.map +1 -0
- package/dist/skills/candidate-ranking.d.ts +15 -0
- package/dist/skills/candidate-ranking.d.ts.map +1 -0
- package/dist/skills/candidate-ranking.js +52 -0
- package/dist/skills/candidate-ranking.js.map +1 -0
- package/dist/skills/chunking.d.ts +11 -0
- package/dist/skills/chunking.d.ts.map +1 -0
- package/dist/skills/chunking.js +291 -0
- package/dist/skills/chunking.js.map +1 -0
- package/dist/skills/config.d.ts +19 -0
- package/dist/skills/config.d.ts.map +1 -0
- package/dist/skills/config.js +103 -0
- package/dist/skills/config.js.map +1 -0
- package/dist/skills/discovery-service.d.ts +26 -0
- package/dist/skills/discovery-service.d.ts.map +1 -0
- package/dist/skills/discovery-service.js +921 -0
- package/dist/skills/discovery-service.js.map +1 -0
- package/dist/skills/external-transport.d.ts +2 -0
- package/dist/skills/external-transport.d.ts.map +1 -0
- package/dist/skills/external-transport.js +30 -0
- package/dist/skills/external-transport.js.map +1 -0
- package/dist/skills/find.d.ts +16 -0
- package/dist/skills/find.d.ts.map +1 -0
- package/dist/skills/find.js +58 -0
- package/dist/skills/find.js.map +1 -0
- package/dist/skills/gap-detection.d.ts +23 -0
- package/dist/skills/gap-detection.d.ts.map +1 -0
- package/dist/skills/gap-detection.js +62 -0
- package/dist/skills/gap-detection.js.map +1 -0
- package/dist/skills/import-preparation.d.ts +4 -0
- package/dist/skills/import-preparation.d.ts.map +1 -0
- package/dist/skills/import-preparation.js +20 -0
- package/dist/skills/import-preparation.js.map +1 -0
- package/dist/skills/materialization-authority.d.ts +11 -0
- package/dist/skills/materialization-authority.d.ts.map +1 -0
- package/dist/skills/materialization-authority.js +92 -0
- package/dist/skills/materialization-authority.js.map +1 -0
- package/dist/skills/materialization-service.d.ts +22 -0
- package/dist/skills/materialization-service.d.ts.map +1 -0
- package/dist/skills/materialization-service.js +101 -0
- package/dist/skills/materialization-service.js.map +1 -0
- package/dist/skills/official-catalog.d.ts +31 -0
- package/dist/skills/official-catalog.d.ts.map +1 -0
- package/dist/skills/official-catalog.js +110 -0
- package/dist/skills/official-catalog.js.map +1 -0
- package/dist/skills/providers/schema.d.ts +30 -0
- package/dist/skills/providers/schema.d.ts.map +1 -0
- package/dist/skills/providers/schema.js +354 -0
- package/dist/skills/providers/schema.js.map +1 -0
- package/dist/skills/providers/skills-sh-compat.d.ts +17 -0
- package/dist/skills/providers/skills-sh-compat.d.ts.map +1 -0
- package/dist/skills/providers/skills-sh-compat.js +71 -0
- package/dist/skills/providers/skills-sh-compat.js.map +1 -0
- package/dist/skills/providers/skills-sh-v1.d.ts +23 -0
- package/dist/skills/providers/skills-sh-v1.d.ts.map +1 -0
- package/dist/skills/providers/skills-sh-v1.js +134 -0
- package/dist/skills/providers/skills-sh-v1.js.map +1 -0
- package/dist/skills/query-builder.d.ts +18 -0
- package/dist/skills/query-builder.d.ts.map +1 -0
- package/dist/skills/query-builder.js +93 -0
- package/dist/skills/query-builder.js.map +1 -0
- package/dist/skills/source/errors.d.ts +9 -0
- package/dist/skills/source/errors.d.ts.map +1 -0
- package/dist/skills/source/errors.js +15 -0
- package/dist/skills/source/errors.js.map +1 -0
- package/dist/skills/source/frontmatter.d.ts +9 -0
- package/dist/skills/source/frontmatter.d.ts.map +1 -0
- package/dist/skills/source/frontmatter.js +77 -0
- package/dist/skills/source/frontmatter.js.map +1 -0
- package/dist/skills/source/github-fetcher.d.ts +20 -0
- package/dist/skills/source/github-fetcher.d.ts.map +1 -0
- package/dist/skills/source/github-fetcher.js +292 -0
- package/dist/skills/source/github-fetcher.js.map +1 -0
- package/dist/skills/source/snapshot-validator.d.ts +28 -0
- package/dist/skills/source/snapshot-validator.d.ts.map +1 -0
- package/dist/skills/source/snapshot-validator.js +186 -0
- package/dist/skills/source/snapshot-validator.js.map +1 -0
- package/dist/skills/store.d.ts +181 -0
- package/dist/skills/store.d.ts.map +1 -0
- package/dist/skills/store.js +1710 -0
- package/dist/skills/store.js.map +1 -0
- package/dist/skills/types.d.ts +169 -0
- package/dist/skills/types.d.ts.map +1 -0
- package/dist/skills/types.js +2 -0
- package/dist/skills/types.js.map +1 -0
- package/dist/web/i18n.d.ts +32 -0
- package/dist/web/i18n.d.ts.map +1 -1
- package/dist/web/i18n.js +128 -0
- package/dist/web/i18n.js.map +1 -1
- package/dist/web/server.d.ts.map +1 -1
- package/dist/web/server.js +386 -38
- package/dist/web/server.js.map +1 -1
- package/dist/web/ui.d.ts +4 -0
- package/dist/web/ui.d.ts.map +1 -1
- package/dist/web/ui.js +382 -6
- package/dist/web/ui.js.map +1 -1
- package/migrations/009_external_skill_discovery.sql +126 -0
- package/package.json +4 -3
- package/skills/kiokuko-single-purpose-functions/SKILL.md +288 -0
- package/skills/kiokuko-single-purpose-functions/references/kiokuko-patterns.md +344 -0
- package/skills/kiokuko-single-purpose-functions/references/review-checklist.md +97 -0
- package/skills/kiokuko-ui-design-soul/SKILL.md +1186 -28
- package/templates/AGENTS.md +8 -7
- package/dist/client/runtime-discovery.d.ts +0 -15
- package/dist/client/runtime-discovery.d.ts.map +0 -1
- package/dist/client/runtime-discovery.js +0 -45
- package/dist/client/runtime-discovery.js.map +0 -1
- package/dist/commands/call.d.ts +0 -7
- package/dist/commands/call.d.ts.map +0 -1
- package/dist/commands/call.js +0 -10
- package/dist/commands/call.js.map +0 -1
- package/dist/commands/link.d.ts +0 -6
- package/dist/commands/link.d.ts.map +0 -1
- package/dist/commands/link.js +0 -6
- package/dist/commands/link.js.map +0 -1
- package/dist/commands/promote.d.ts +0 -6
- package/dist/commands/promote.d.ts.map +0 -1
- package/dist/commands/promote.js +0 -6
- package/dist/commands/promote.js.map +0 -1
- package/dist/commands/read.d.ts +0 -6
- package/dist/commands/read.d.ts.map +0 -1
- package/dist/commands/read.js +0 -4
- package/dist/commands/read.js.map +0 -1
- package/dist/commands/recall.d.ts +0 -6
- package/dist/commands/recall.d.ts.map +0 -1
- package/dist/commands/recall.js +0 -4
- package/dist/commands/recall.js.map +0 -1
- package/dist/commands/record.d.ts +0 -6
- package/dist/commands/record.d.ts.map +0 -1
- package/dist/commands/record.js +0 -4
- package/dist/commands/record.js.map +0 -1
- package/dist/commands/search.d.ts +0 -6
- package/dist/commands/search.d.ts.map +0 -1
- package/dist/commands/search.js +0 -4
- package/dist/commands/search.js.map +0 -1
- package/dist/commands/supersede.d.ts +0 -6
- package/dist/commands/supersede.d.ts.map +0 -1
- package/dist/commands/supersede.js +0 -6
- package/dist/commands/supersede.js.map +0 -1
- package/dist/knowledge/sources.d.ts +0 -72
- package/dist/knowledge/sources.d.ts.map +0 -1
- package/dist/knowledge/sources.js +0 -388
- package/dist/knowledge/sources.js.map +0 -1
- package/dist/setup/opencode-evidence.d.ts +0 -37
- package/dist/setup/opencode-evidence.d.ts.map +0 -1
- package/dist/setup/opencode-evidence.js +0 -58
- package/dist/setup/opencode-evidence.js.map +0 -1
- package/dist/setup/opencode-loop-guard.d.ts +0 -9
- package/dist/setup/opencode-loop-guard.d.ts.map +0 -1
- package/dist/setup/opencode-loop-guard.js +0 -248
- package/dist/setup/opencode-loop-guard.js.map +0 -1
package/dist/context/broker.js
CHANGED
|
@@ -1,21 +1,103 @@
|
|
|
1
|
-
import { createHash, randomUUID } from 'node:crypto';
|
|
2
1
|
import { KiokukoError } from '../errors.js';
|
|
3
|
-
import {
|
|
4
|
-
import { listContextDeliveries, readContextDelivery,
|
|
5
|
-
import {
|
|
2
|
+
import { withImmediateTransaction } from '../db/transaction.js';
|
|
3
|
+
import { listContextDeliveries, readContextDelivery, recordContextDeliveryInTransaction, } from './delivery.js';
|
|
4
|
+
import { contextFeedbackSignals } from './feedback.js';
|
|
6
5
|
import { buildRecommendations, RECOMMENDATION_POLICY_VERSION } from './recommendations.js';
|
|
7
|
-
import { CONTEXT_RANKING_VERSION, rankContextCandidates } from './ranking.js';
|
|
8
|
-
import {
|
|
6
|
+
import { CONTEXT_RANKING_VERSION, CONTEXT_SELECTION_REASON_ORDER, rankContextCandidates } from './ranking.js';
|
|
7
|
+
import { rankedEntryHits } from '../memory/retrieval.js';
|
|
8
|
+
import { readEntry } from '../memory/entries.js';
|
|
9
|
+
import { decodeStoredStructuredScope, readEntryRevision } from '../memory/revisions.js';
|
|
9
10
|
import { federatedEntries } from '../memory/federated-retrieval.js';
|
|
10
|
-
import {
|
|
11
|
-
import {
|
|
12
|
-
import {
|
|
13
|
-
import { canonicalContentHash } from '../serialization/validate.js';
|
|
11
|
+
import { isRetrievableEntry } from '../memory/hybrid-retrieval.js';
|
|
12
|
+
import { GLOBAL_WORKSPACE } from '../memory/workspaces.js';
|
|
13
|
+
import { effectiveRetrievalScope, hasExplicitApplicability } from '../memory/structured-memory.js';
|
|
14
|
+
import { canonicalContentHash, compareCanonicalStrings } from '../serialization/validate.js';
|
|
15
|
+
import { entryOriginMatchesWorkspace } from './origin.js';
|
|
16
|
+
import { isExternalSkillReference } from '../skills/store.js';
|
|
17
|
+
import { contextRetrievalStateHash } from './selection-state.js';
|
|
18
|
+
import { readContextRunRetrievalState } from './run-state.js';
|
|
19
|
+
import { captureProjectManifestSnapshot, resolveProjectFingerprint, } from '../repository/project-fingerprint.js';
|
|
14
20
|
export const CONTEXT_BROKER_POLICY_VERSION = `${CONTEXT_RANKING_VERSION}+${RECOMMENDATION_POLICY_VERSION}`;
|
|
15
21
|
export const CONTEXT_BROKER_DEFAULT_LIMIT = 20;
|
|
16
22
|
export const CONTEXT_BROKER_MAX_LIMIT = 100;
|
|
17
23
|
export const CONTEXT_BROKER_DEFAULT_CHARACTER_BUDGET = 8_000;
|
|
18
24
|
export const CONTEXT_BROKER_MAX_CHARACTER_BUDGET = 100_000;
|
|
25
|
+
function normalizedGateDecision(value) {
|
|
26
|
+
if (typeof value !== 'object' || value === null || Array.isArray(value)) {
|
|
27
|
+
throw new TypeError('Context broker gate returned an invalid decision');
|
|
28
|
+
}
|
|
29
|
+
const prototype = Object.getPrototypeOf(value);
|
|
30
|
+
const keys = Reflect.ownKeys(value);
|
|
31
|
+
if ((prototype !== Object.prototype && prototype !== null)
|
|
32
|
+
|| keys.some((key) => typeof key !== 'string'
|
|
33
|
+
|| key !== 'persist' && key !== 'value' && key !== 'assertBeforePersist')
|
|
34
|
+
|| !keys.includes('persist')
|
|
35
|
+
|| !keys.includes('value')) {
|
|
36
|
+
throw new TypeError('Context broker gate returned an invalid decision');
|
|
37
|
+
}
|
|
38
|
+
const persistDescriptor = Object.getOwnPropertyDescriptor(value, 'persist');
|
|
39
|
+
const resultDescriptor = Object.getOwnPropertyDescriptor(value, 'value');
|
|
40
|
+
const assertionDescriptor = Object.getOwnPropertyDescriptor(value, 'assertBeforePersist');
|
|
41
|
+
if (persistDescriptor === undefined
|
|
42
|
+
|| !Object.hasOwn(persistDescriptor, 'value')
|
|
43
|
+
|| typeof persistDescriptor.value !== 'boolean'
|
|
44
|
+
|| resultDescriptor === undefined
|
|
45
|
+
|| !Object.hasOwn(resultDescriptor, 'value')
|
|
46
|
+
|| assertionDescriptor !== undefined
|
|
47
|
+
&& (!Object.hasOwn(assertionDescriptor, 'value') || typeof assertionDescriptor.value !== 'function')) {
|
|
48
|
+
throw new TypeError('Context broker gate returned an invalid decision');
|
|
49
|
+
}
|
|
50
|
+
return {
|
|
51
|
+
persist: persistDescriptor.value,
|
|
52
|
+
value: resultDescriptor.value,
|
|
53
|
+
...(assertionDescriptor === undefined
|
|
54
|
+
? {}
|
|
55
|
+
: { assertBeforePersist: assertionDescriptor.value }),
|
|
56
|
+
};
|
|
57
|
+
}
|
|
58
|
+
function contextDeliverySnapshotHash(delivery) {
|
|
59
|
+
return canonicalContentHash({
|
|
60
|
+
workspace: delivery.workspace,
|
|
61
|
+
deliveryId: delivery.deliveryId,
|
|
62
|
+
runId: delivery.runId,
|
|
63
|
+
throughSequence: delivery.throughSequence,
|
|
64
|
+
intakeSessionId: delivery.intakeSessionId,
|
|
65
|
+
taskProfileHash: delivery.taskProfileHash,
|
|
66
|
+
queryHash: delivery.queryHash,
|
|
67
|
+
policyVersion: delivery.policyVersion,
|
|
68
|
+
charBudget: delivery.charBudget,
|
|
69
|
+
charCount: delivery.charCount,
|
|
70
|
+
truncated: delivery.truncated,
|
|
71
|
+
createdAt: delivery.createdAt,
|
|
72
|
+
scoreSchemaVersion: delivery.scoreSchemaVersion ?? 1,
|
|
73
|
+
items: delivery.items.map((item) => ({
|
|
74
|
+
entryId: item.entryId,
|
|
75
|
+
entryRevision: item.entryRevision,
|
|
76
|
+
rank: item.rank,
|
|
77
|
+
scoreComponents: item.scoreComponents,
|
|
78
|
+
selectionReasons: item.selectionReasons,
|
|
79
|
+
...(item.origin === undefined ? {} : { origin: item.origin }),
|
|
80
|
+
})),
|
|
81
|
+
});
|
|
82
|
+
}
|
|
83
|
+
function assertReplayDeliveryUnchanged(database, expected) {
|
|
84
|
+
let current;
|
|
85
|
+
try {
|
|
86
|
+
current = readContextDelivery(database, {
|
|
87
|
+
workspace: expected.workspace,
|
|
88
|
+
deliveryId: expected.deliveryId,
|
|
89
|
+
});
|
|
90
|
+
}
|
|
91
|
+
catch (error) {
|
|
92
|
+
if (error instanceof KiokukoError && error.code === 'NOT_FOUND') {
|
|
93
|
+
throw new KiokukoError('INTEGRITY_ERROR', 'Stored context delivery disappeared during replay');
|
|
94
|
+
}
|
|
95
|
+
throw error;
|
|
96
|
+
}
|
|
97
|
+
if (contextDeliverySnapshotHash(current) !== contextDeliverySnapshotHash(expected)) {
|
|
98
|
+
throw new KiokukoError('INTEGRITY_ERROR', 'Stored context delivery changed during replay');
|
|
99
|
+
}
|
|
100
|
+
}
|
|
19
101
|
function invalid() {
|
|
20
102
|
throw new KiokukoError('VALIDATION_ERROR', 'Context query input is invalid');
|
|
21
103
|
}
|
|
@@ -73,58 +155,50 @@ function normalizeInput(input) {
|
|
|
73
155
|
...(value.characterBudget === undefined ? {} : { characterBudget: value.characterBudget }),
|
|
74
156
|
};
|
|
75
157
|
}
|
|
76
|
-
function
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
158
|
+
function normalizePersistence(value) {
|
|
159
|
+
if (typeof value !== 'object' || value === null || Array.isArray(value)) {
|
|
160
|
+
throw new TypeError('Context broker persistence adapter is invalid');
|
|
161
|
+
}
|
|
162
|
+
const object = value;
|
|
163
|
+
const prototype = Object.getPrototypeOf(object);
|
|
164
|
+
const keys = Reflect.ownKeys(object);
|
|
165
|
+
const descriptor = Object.getOwnPropertyDescriptor(object, 'enqueueWrite');
|
|
166
|
+
if ((prototype !== Object.prototype && prototype !== null)
|
|
167
|
+
|| keys.some((key) => key !== 'enqueueWrite')
|
|
168
|
+
|| descriptor !== undefined && !Object.hasOwn(descriptor, 'value')) {
|
|
169
|
+
throw new TypeError('Context broker persistence adapter is invalid');
|
|
170
|
+
}
|
|
171
|
+
const enqueueWrite = descriptor?.value;
|
|
172
|
+
if (enqueueWrite !== undefined && typeof enqueueWrite !== 'function') {
|
|
173
|
+
throw new TypeError('Context broker persistence adapter is invalid');
|
|
174
|
+
}
|
|
175
|
+
return enqueueWrite === undefined
|
|
176
|
+
? {}
|
|
177
|
+
: { enqueueWrite: enqueueWrite };
|
|
94
178
|
}
|
|
95
179
|
function currentRunContext(database, runId) {
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
notFound();
|
|
99
|
-
const link = readRunIntakeLink(database, { workspace: run.workspace, runId });
|
|
100
|
-
const session = readAkinatorSession(database, { workspace: run.workspace, sessionId: link.sessionId });
|
|
101
|
-
const status = session.status;
|
|
102
|
-
if (status === 'active') {
|
|
103
|
-
return {
|
|
104
|
-
run,
|
|
105
|
-
profile: session.profile,
|
|
106
|
-
profileHash: link.initialProfileHash ?? canonicalContentHash(session.profile),
|
|
107
|
-
recommendedTags: [...link.recommendedTags],
|
|
108
|
-
intakeSessionId: link.sessionId,
|
|
109
|
-
intakeStatus: status,
|
|
110
|
-
projection: null,
|
|
111
|
-
};
|
|
180
|
+
try {
|
|
181
|
+
return readContextRunRetrievalState(database, runId);
|
|
112
182
|
}
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
183
|
+
catch (error) {
|
|
184
|
+
if (error instanceof KiokukoError
|
|
185
|
+
&& error.code === 'NOT_FOUND'
|
|
186
|
+
&& error.message === 'Context run was not found') {
|
|
187
|
+
notFound();
|
|
188
|
+
}
|
|
189
|
+
throw error;
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
/** Read the same authoritative run/intake/profile snapshot used to rank broker context. */
|
|
193
|
+
export function readContextBrokerRunState(database, runId) {
|
|
194
|
+
const current = currentRunContext(database, runId);
|
|
120
195
|
return {
|
|
121
|
-
run,
|
|
122
|
-
|
|
123
|
-
profileHash:
|
|
124
|
-
recommendedTags: [...
|
|
125
|
-
intakeSessionId:
|
|
126
|
-
intakeStatus:
|
|
127
|
-
projection,
|
|
196
|
+
run: current.run,
|
|
197
|
+
taskProfile: { ...current.profile },
|
|
198
|
+
profileHash: current.profileHash,
|
|
199
|
+
recommendedTags: [...current.recommendedTags],
|
|
200
|
+
intakeSessionId: current.intakeSessionId,
|
|
201
|
+
status: current.intakeStatus === 'active' ? 'needs_answer' : current.intakeStatus,
|
|
128
202
|
};
|
|
129
203
|
}
|
|
130
204
|
function preparedQuery(database, input) {
|
|
@@ -137,6 +211,21 @@ function preparedQuery(database, input) {
|
|
|
137
211
|
const throughSequence = runContext?.run.lastSequence ?? 0;
|
|
138
212
|
const taskProfileHash = runContext?.profileHash ?? canonicalContentHash(profile);
|
|
139
213
|
const recommendedTags = runContext?.recommendedTags ?? input.recommendedTags ?? [];
|
|
214
|
+
const workspace = runContext?.run.workspace ?? requestedWorkspace;
|
|
215
|
+
const project = projectForWorkspace(database, workspace);
|
|
216
|
+
const projectState = project === undefined
|
|
217
|
+
? null
|
|
218
|
+
: {
|
|
219
|
+
project,
|
|
220
|
+
fingerprint: resolveProjectFingerprint(database, project, captureProjectManifestSnapshot(project)),
|
|
221
|
+
};
|
|
222
|
+
const includeEcosystem = projectState !== null;
|
|
223
|
+
const selectionWorkspaces = !includeEcosystem
|
|
224
|
+
? [workspace]
|
|
225
|
+
: [workspace, GLOBAL_WORKSPACE];
|
|
226
|
+
const retrievalStateHash = runContext === null || runContext.intakeStatus !== 'active'
|
|
227
|
+
? contextRetrievalStateHash(database, selectionWorkspaces, { includeEcosystem })
|
|
228
|
+
: null;
|
|
140
229
|
const queryShape = {
|
|
141
230
|
runId: input.runId ?? null,
|
|
142
231
|
workspace: input.runId === undefined ? requestedWorkspace : null,
|
|
@@ -148,10 +237,15 @@ function preparedQuery(database, input) {
|
|
|
148
237
|
throughSequence,
|
|
149
238
|
characterBudget: input.characterBudget ?? CONTEXT_BROKER_DEFAULT_CHARACTER_BUDGET,
|
|
150
239
|
limit: input.limit ?? CONTEXT_BROKER_DEFAULT_LIMIT,
|
|
240
|
+
projectState,
|
|
241
|
+
retrievalStateHash,
|
|
242
|
+
runStateHash: runContext?.stateHash ?? null,
|
|
151
243
|
};
|
|
152
244
|
const queryHash = canonicalContentHash(queryShape);
|
|
153
245
|
return {
|
|
154
|
-
workspace
|
|
246
|
+
workspace,
|
|
247
|
+
selectionWorkspaces,
|
|
248
|
+
includeEcosystem,
|
|
155
249
|
run: runContext?.run ?? null,
|
|
156
250
|
taskProfile: profile,
|
|
157
251
|
profileHash: taskProfileHash,
|
|
@@ -165,11 +259,16 @@ function preparedQuery(database, input) {
|
|
|
165
259
|
intakeSessionId: runContext?.intakeSessionId ?? null,
|
|
166
260
|
projection: runContext?.projection ?? null,
|
|
167
261
|
runStatus: runContext === null ? 'unbound' : runContext.intakeStatus === 'active' ? 'needs_answer' : runContext.intakeStatus,
|
|
262
|
+
projectState,
|
|
263
|
+
retrievalStateHash,
|
|
264
|
+
runStateHash: runContext?.stateHash ?? null,
|
|
265
|
+
deliveryHistoryStateHash: null,
|
|
266
|
+
deliveryHistoryExcludeQueryHash: null,
|
|
168
267
|
queryHash,
|
|
169
|
-
deliveryId:
|
|
268
|
+
deliveryId: null,
|
|
170
269
|
};
|
|
171
270
|
}
|
|
172
|
-
function entrySnapshot(entry, origin) {
|
|
271
|
+
function entrySnapshot(entry, origin, selectionReasons = []) {
|
|
173
272
|
return {
|
|
174
273
|
id: entry.id,
|
|
175
274
|
revision: entry.revision,
|
|
@@ -183,6 +282,7 @@ function entrySnapshot(entry, origin) {
|
|
|
183
282
|
tags: [...entry.tags],
|
|
184
283
|
scope: entry.scope,
|
|
185
284
|
updatedAt: entry.updatedAt,
|
|
285
|
+
selectionReasons: [...selectionReasons],
|
|
186
286
|
...(origin === undefined ? {} : { origin }),
|
|
187
287
|
};
|
|
188
288
|
}
|
|
@@ -190,13 +290,48 @@ function retrievalQuery(query) {
|
|
|
190
290
|
const values = [query.task, query.taskProfile.target, query.taskProfile.expected, ...query.recommendedTags].filter((value) => value !== null && value.length > 0);
|
|
191
291
|
return values.join(' ').slice(0, 16_384) || 'kiokuko';
|
|
192
292
|
}
|
|
293
|
+
const APPLICABILITY_DETAIL_REASONS = new Set([
|
|
294
|
+
'language_match',
|
|
295
|
+
'database_match',
|
|
296
|
+
'runtime_match',
|
|
297
|
+
'tool_match',
|
|
298
|
+
'platform_match',
|
|
299
|
+
'framework_exact_match',
|
|
300
|
+
'framework_match',
|
|
301
|
+
]);
|
|
302
|
+
function canonicalRetrievedReasons(reasons) {
|
|
303
|
+
const normalized = reasons.map((reason) => {
|
|
304
|
+
if (APPLICABILITY_DETAIL_REASONS.has(reason))
|
|
305
|
+
return 'applicability_match';
|
|
306
|
+
if (CONTEXT_SELECTION_REASON_ORDER.includes(reason))
|
|
307
|
+
return reason;
|
|
308
|
+
throw new KiokukoError('INTEGRITY_ERROR', 'Retrieval returned an unknown selection reason');
|
|
309
|
+
});
|
|
310
|
+
const rank = (reason) => CONTEXT_SELECTION_REASON_ORDER.indexOf(reason);
|
|
311
|
+
return [...new Set(normalized)].sort((left, right) => rank(left) - rank(right) || compareCanonicalStrings(left, right));
|
|
312
|
+
}
|
|
313
|
+
function addRetrievedEntry(entries, value) {
|
|
314
|
+
const existing = entries.get(value.entry.id);
|
|
315
|
+
entries.set(value.entry.id, {
|
|
316
|
+
...value,
|
|
317
|
+
selectionReasons: canonicalRetrievedReasons([...(existing?.selectionReasons ?? []), ...value.selectionReasons]),
|
|
318
|
+
});
|
|
319
|
+
}
|
|
193
320
|
function projectForWorkspace(database, workspace) {
|
|
194
321
|
const row = database.prepare(`
|
|
195
322
|
SELECT r.repository_id AS repositoryId, r.workspace, l.canonical_root AS repositoryRoot
|
|
196
323
|
FROM repositories AS r JOIN repository_locations AS l ON l.repository_id = r.repository_id
|
|
197
|
-
WHERE r.workspace = ? ORDER BY l.last_seen_at DESC LIMIT 1
|
|
324
|
+
WHERE r.workspace = ? ORDER BY l.last_seen_at DESC, l.canonical_root ASC LIMIT 1
|
|
198
325
|
`).get(workspace);
|
|
199
|
-
|
|
326
|
+
if (row === undefined)
|
|
327
|
+
return undefined;
|
|
328
|
+
const { repositoryId, repositoryRoot, workspace: storedWorkspace } = row;
|
|
329
|
+
if (typeof repositoryId !== 'string' || repositoryId.length === 0
|
|
330
|
+
|| typeof storedWorkspace !== 'string' || storedWorkspace !== workspace
|
|
331
|
+
|| typeof repositoryRoot !== 'string' || repositoryRoot.length === 0) {
|
|
332
|
+
throw new KiokukoError('INTEGRITY_ERROR', 'Stored context project binding is invalid');
|
|
333
|
+
}
|
|
334
|
+
return { repositoryRoot, repositoryId, workspace: storedWorkspace, source: 'location' };
|
|
200
335
|
}
|
|
201
336
|
async function retrieveEntries(database, query) {
|
|
202
337
|
const terms = [query.task, query.taskProfile.target, query.taskProfile.expected, ...query.recommendedTags]
|
|
@@ -204,62 +339,154 @@ async function retrieveEntries(database, query) {
|
|
|
204
339
|
.map((value) => value.slice(0, 2_000));
|
|
205
340
|
const queries = [retrievalQuery(query), ...terms];
|
|
206
341
|
const entries = new Map();
|
|
207
|
-
const project = projectForWorkspace(database, query.workspace);
|
|
208
342
|
for (const value of queries) {
|
|
209
|
-
if (
|
|
210
|
-
for (const hit of await federatedEntries(database, {
|
|
211
|
-
|
|
343
|
+
if (query.projectState !== null) {
|
|
344
|
+
for (const hit of await federatedEntries(database, {
|
|
345
|
+
project: query.projectState.project,
|
|
346
|
+
fingerprint: query.projectState.fingerprint,
|
|
347
|
+
query: value,
|
|
348
|
+
limit: 500,
|
|
349
|
+
})) {
|
|
350
|
+
addRetrievedEntry(entries, { entry: hit.entry, origin: hit.origin, selectionReasons: hit.selectionReasons });
|
|
351
|
+
}
|
|
212
352
|
}
|
|
213
353
|
else {
|
|
214
|
-
for (const
|
|
215
|
-
entries
|
|
354
|
+
for (const hit of rankedEntryHits(database, { workspace: query.workspace, query: value, limit: 500, includeSuperseded: false }).hits) {
|
|
355
|
+
addRetrievedEntry(entries, {
|
|
356
|
+
entry: readEntry(database, { workspace: query.workspace, entryId: hit.entryId }),
|
|
357
|
+
origin: 'project',
|
|
358
|
+
selectionReasons: ['project_origin', ...hit.reasons],
|
|
359
|
+
});
|
|
360
|
+
}
|
|
216
361
|
}
|
|
217
362
|
}
|
|
218
363
|
return [...entries.values()];
|
|
219
364
|
}
|
|
365
|
+
function assertPreparedProjectState(database, query) {
|
|
366
|
+
const currentProject = projectForWorkspace(database, query.workspace);
|
|
367
|
+
if (query.projectState === null) {
|
|
368
|
+
if (currentProject !== undefined) {
|
|
369
|
+
throw new KiokukoError('CONFLICT', 'Context project state changed after ranking');
|
|
370
|
+
}
|
|
371
|
+
return;
|
|
372
|
+
}
|
|
373
|
+
if (currentProject === undefined
|
|
374
|
+
|| canonicalContentHash(currentProject) !== canonicalContentHash(query.projectState.project)) {
|
|
375
|
+
throw new KiokukoError('CONFLICT', 'Context project state changed after ranking');
|
|
376
|
+
}
|
|
377
|
+
const manifestSnapshot = captureProjectManifestSnapshot(currentProject);
|
|
378
|
+
if (manifestSnapshot.manifestDigest !== query.projectState.fingerprint.manifestDigest) {
|
|
379
|
+
throw new KiokukoError('CONFLICT', 'Context project state changed after ranking');
|
|
380
|
+
}
|
|
381
|
+
const currentFingerprint = resolveProjectFingerprint(database, currentProject, manifestSnapshot, { readOnly: true });
|
|
382
|
+
if (canonicalContentHash(currentFingerprint) !== canonicalContentHash(query.projectState.fingerprint)) {
|
|
383
|
+
throw new KiokukoError('CONFLICT', 'Context project state changed after ranking');
|
|
384
|
+
}
|
|
385
|
+
}
|
|
220
386
|
async function rank(database, query, prior) {
|
|
221
387
|
const entries = await retrieveEntries(database, query);
|
|
388
|
+
const feedback = entries.flatMap(({ entry }) => contextFeedbackSignals(database, entry.id).flatMap((signal) => Array.from({ length: signal.boundedInfluence }, () => ({ entryId: entry.id, verdict: signal.verdict }))));
|
|
222
389
|
return rankContextCandidates({
|
|
223
390
|
taskProfile: query.taskProfile,
|
|
224
391
|
recommendedTags: query.recommendedTags,
|
|
225
392
|
changedPaths: query.changedPaths,
|
|
226
393
|
errorSignatures: query.errorSignatures,
|
|
227
394
|
priorDelivered: prior.delivered,
|
|
228
|
-
feedback
|
|
229
|
-
candidates: entries.map(({ entry, origin }) => entrySnapshot(entry, origin)),
|
|
395
|
+
feedback,
|
|
396
|
+
candidates: entries.map(({ entry, origin, selectionReasons }) => entrySnapshot(entry, origin, selectionReasons)),
|
|
230
397
|
limit: query.limit,
|
|
231
398
|
characterBudget: query.characterBudget,
|
|
232
399
|
});
|
|
233
400
|
}
|
|
234
|
-
function priorData(database, query) {
|
|
401
|
+
function priorData(database, query, options = {}) {
|
|
235
402
|
if (query.run === null)
|
|
236
|
-
return { delivered: [],
|
|
403
|
+
return { delivered: [], stale: [], stateHash: null };
|
|
237
404
|
const deliveries = [];
|
|
238
405
|
let cursor;
|
|
406
|
+
let complete = false;
|
|
239
407
|
for (let page = 0; page < 10; page += 1) {
|
|
240
408
|
const result = listContextDeliveries(database, { workspace: query.workspace, runId: query.run.runId, limit: 100, ...(cursor === undefined ? {} : { cursor }) });
|
|
241
409
|
deliveries.push(...result.items);
|
|
242
|
-
if (result.nextCursor === null)
|
|
410
|
+
if (result.nextCursor === null) {
|
|
411
|
+
complete = true;
|
|
243
412
|
break;
|
|
413
|
+
}
|
|
244
414
|
cursor = result.nextCursor;
|
|
245
415
|
}
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
const
|
|
416
|
+
if (!complete) {
|
|
417
|
+
throw new KiokukoError('INTEGRITY_ERROR', 'Context delivery history exceeds the broker policy bound');
|
|
418
|
+
}
|
|
419
|
+
for (const delivery of deliveries) {
|
|
420
|
+
for (const item of delivery.items) {
|
|
421
|
+
currentRetrievableDeliveryEntry(database, query.workspace, item);
|
|
422
|
+
}
|
|
423
|
+
}
|
|
424
|
+
const stateDeliveries = deliveries.filter((delivery) => delivery.deliveryId !== options.excludeDeliveryId);
|
|
425
|
+
const delivered = stateDeliveries
|
|
426
|
+
.filter((delivery) => delivery.queryHash !== options.excludeDeliveredQueryHash)
|
|
427
|
+
.flatMap((delivery) => delivery.items.flatMap((item) => contextFeedbackSignals(database, item.entryId)
|
|
428
|
+
.some((signal) => signal.verdict === 'helpful')
|
|
429
|
+
? []
|
|
430
|
+
: [{ entryId: item.entryId, revision: item.entryRevision }]));
|
|
431
|
+
const stale = stateDeliveries.flatMap((delivery) => delivery.items.flatMap((item) => {
|
|
250
432
|
const current = database.prepare('SELECT current_revision FROM entries WHERE id = ?').get(item.entryId);
|
|
251
433
|
return current && Number(current.current_revision) > item.entryRevision ? [{ entryId: item.entryId, deliveredRevision: item.entryRevision, currentRevision: Number(current.current_revision), stale: true }] : [];
|
|
252
434
|
}));
|
|
253
|
-
return {
|
|
435
|
+
return {
|
|
436
|
+
delivered,
|
|
437
|
+
stale,
|
|
438
|
+
stateHash: canonicalContentHash({
|
|
439
|
+
runId: query.run.runId,
|
|
440
|
+
excludeDeliveredQueryHash: options.excludeDeliveredQueryHash ?? null,
|
|
441
|
+
deliveries: stateDeliveries.map(contextDeliverySnapshotHash),
|
|
442
|
+
delivered,
|
|
443
|
+
stale,
|
|
444
|
+
}),
|
|
445
|
+
};
|
|
446
|
+
}
|
|
447
|
+
function historyAttestedDeliveryId(query, historyStateHash, excludeDeliveredQueryHash) {
|
|
448
|
+
return `context-${canonicalContentHash({
|
|
449
|
+
kind: 'context-delivery-history-attestation-v1',
|
|
450
|
+
queryHash: query.queryHash,
|
|
451
|
+
historyStateHash,
|
|
452
|
+
excludeDeliveredQueryHash,
|
|
453
|
+
})}`;
|
|
454
|
+
}
|
|
455
|
+
function deliveryHistoryExclusionForReplay(database, query, deliveryId) {
|
|
456
|
+
if (query.run === null)
|
|
457
|
+
return null;
|
|
458
|
+
const priorSameQuery = database.prepare(`
|
|
459
|
+
SELECT 1 AS present
|
|
460
|
+
FROM context_deliveries
|
|
461
|
+
WHERE run_id = ? AND query_hash = ? AND delivery_id <> ?
|
|
462
|
+
LIMIT 1
|
|
463
|
+
`).get(query.run.runId, query.queryHash, deliveryId);
|
|
464
|
+
if (priorSameQuery === undefined)
|
|
465
|
+
return null;
|
|
466
|
+
if (priorSameQuery.present !== 1) {
|
|
467
|
+
throw new KiokukoError('INTEGRITY_ERROR', 'Stored context delivery history is invalid');
|
|
468
|
+
}
|
|
469
|
+
return query.queryHash;
|
|
470
|
+
}
|
|
471
|
+
function deliveryHistoryIsAttested(database, query, delivery) {
|
|
472
|
+
const excludeDeliveredQueryHash = deliveryHistoryExclusionForReplay(database, query, delivery.deliveryId);
|
|
473
|
+
const history = priorData(database, query, {
|
|
474
|
+
...(excludeDeliveredQueryHash === null ? {} : { excludeDeliveredQueryHash }),
|
|
475
|
+
excludeDeliveryId: delivery.deliveryId,
|
|
476
|
+
});
|
|
477
|
+
if (history.stateHash === null) {
|
|
478
|
+
throw new KiokukoError('INTEGRITY_ERROR', 'Stored context delivery history is invalid');
|
|
479
|
+
}
|
|
480
|
+
return delivery.deliveryId === historyAttestedDeliveryId(query, history.stateHash, excludeDeliveredQueryHash);
|
|
254
481
|
}
|
|
255
482
|
function outputContext(query, items, delivery) {
|
|
256
483
|
const sourceItems = items.map((item, index) => ({
|
|
257
484
|
entryId: item.entryId,
|
|
258
485
|
entryRevision: item.revision,
|
|
259
486
|
rank: index + 1,
|
|
260
|
-
scoreComponents: item.scoreComponents,
|
|
487
|
+
scoreComponents: { ...item.scoreComponents },
|
|
261
488
|
selectionReasons: [...item.selectionReasons],
|
|
262
|
-
content: item.content,
|
|
489
|
+
content: { ...item.content },
|
|
263
490
|
untrusted: true,
|
|
264
491
|
...(item.origin === undefined ? {} : { origin: item.origin }),
|
|
265
492
|
}));
|
|
@@ -274,12 +501,12 @@ function outputContext(query, items, delivery) {
|
|
|
274
501
|
untrusted: true,
|
|
275
502
|
};
|
|
276
503
|
}
|
|
277
|
-
function deliveryInput(query, ranked
|
|
504
|
+
function deliveryInput(query, ranked) {
|
|
278
505
|
const items = ranked.map((item, index) => ({
|
|
279
506
|
entryId: item.entryId,
|
|
280
507
|
entryRevision: item.revision,
|
|
281
508
|
rank: index + 1,
|
|
282
|
-
scoreComponents: item.scoreComponents,
|
|
509
|
+
scoreComponents: { ...item.scoreComponents },
|
|
283
510
|
selectionReasons: [...item.selectionReasons],
|
|
284
511
|
...(item.origin === undefined ? {} : { origin: item.origin }),
|
|
285
512
|
}));
|
|
@@ -294,7 +521,6 @@ function deliveryInput(query, ranked, summary) {
|
|
|
294
521
|
taskProfileHash: query.profileHash,
|
|
295
522
|
queryHash: query.queryHash,
|
|
296
523
|
policyVersion: CONTEXT_BROKER_POLICY_VERSION,
|
|
297
|
-
externalSyncSummary: summary,
|
|
298
524
|
charBudget: query.characterBudget,
|
|
299
525
|
charCount,
|
|
300
526
|
truncated,
|
|
@@ -302,19 +528,74 @@ function deliveryInput(query, ranked, summary) {
|
|
|
302
528
|
items,
|
|
303
529
|
};
|
|
304
530
|
}
|
|
305
|
-
function
|
|
306
|
-
|
|
531
|
+
function currentRetrievableDeliveryEntry(database, runWorkspace, item) {
|
|
532
|
+
const candidate = database.prepare('SELECT workspace FROM entries WHERE id = ?')
|
|
533
|
+
.get(item.entryId);
|
|
534
|
+
if (candidate === undefined) {
|
|
535
|
+
throw new KiokukoError('INTEGRITY_ERROR', 'Stored context entry is missing');
|
|
536
|
+
}
|
|
537
|
+
if (typeof candidate.workspace !== 'string' || candidate.workspace.length === 0) {
|
|
538
|
+
throw new KiokukoError('INTEGRITY_ERROR', 'Stored context entry is invalid');
|
|
539
|
+
}
|
|
540
|
+
const origin = item.origin ?? 'project';
|
|
541
|
+
let deliveredRevision;
|
|
542
|
+
try {
|
|
543
|
+
deliveredRevision = readEntryRevision(database, {
|
|
544
|
+
workspace: candidate.workspace,
|
|
545
|
+
entryId: item.entryId,
|
|
546
|
+
revision: item.entryRevision,
|
|
547
|
+
});
|
|
548
|
+
}
|
|
549
|
+
catch (error) {
|
|
550
|
+
if (error instanceof KiokukoError && error.code === 'NOT_FOUND') {
|
|
551
|
+
throw new KiokukoError('INTEGRITY_ERROR', 'Stored context entry revision is missing');
|
|
552
|
+
}
|
|
553
|
+
throw error;
|
|
554
|
+
}
|
|
555
|
+
const deliveredScope = decodeStoredStructuredScope(deliveredRevision.scope, origin !== 'project').canonicalScope;
|
|
556
|
+
if (!entryOriginMatchesWorkspace({ origin, runWorkspace, entryWorkspace: deliveredRevision.workspace })) {
|
|
557
|
+
throw new KiokukoError('INTEGRITY_ERROR', 'Stored context entry origin is invalid');
|
|
558
|
+
}
|
|
559
|
+
if (origin === 'global'
|
|
560
|
+
&& (deliveredScope.visibility !== 'global' || effectiveRetrievalScope(deliveredScope) !== 'global')) {
|
|
561
|
+
throw new KiokukoError('INTEGRITY_ERROR', 'Stored context entry scope is invalid');
|
|
562
|
+
}
|
|
563
|
+
if (origin === 'ecosystem'
|
|
564
|
+
&& (!Object.hasOwn(deliveredScope, 'retrievalScope')
|
|
565
|
+
|| effectiveRetrievalScope(deliveredScope) !== 'ecosystem'
|
|
566
|
+
|| !hasExplicitApplicability(deliveredScope))) {
|
|
567
|
+
throw new KiokukoError('INTEGRITY_ERROR', 'Stored context entry scope is invalid');
|
|
568
|
+
}
|
|
569
|
+
if (isExternalSkillReference(deliveredRevision)) {
|
|
570
|
+
const mappings = database.prepare('SELECT COUNT(*) AS count FROM external_skill_entries WHERE entry_id = ?')
|
|
571
|
+
.get(item.entryId)?.count;
|
|
572
|
+
if (typeof mappings !== 'number' || !Number.isSafeInteger(mappings) || mappings < 1) {
|
|
573
|
+
throw new KiokukoError('INTEGRITY_ERROR', 'Stored context external entry mapping is missing');
|
|
574
|
+
}
|
|
575
|
+
}
|
|
576
|
+
const entry = readEntry(database, { workspace: candidate.workspace, entryId: item.entryId }, { requireStructuredScope: origin !== 'project' });
|
|
577
|
+
const retrievable = isRetrievableEntry(database, entry);
|
|
578
|
+
if (entry.revision !== item.entryRevision)
|
|
579
|
+
return null;
|
|
580
|
+
if (!retrievable)
|
|
581
|
+
return null;
|
|
582
|
+
if (entry.status === 'superseded')
|
|
583
|
+
return null;
|
|
584
|
+
return entry;
|
|
307
585
|
}
|
|
308
586
|
function storedContext(database, query, delivery) {
|
|
309
587
|
let remaining = query.characterBudget;
|
|
588
|
+
let totalCharacterCount = 0;
|
|
589
|
+
let anyTruncated = false;
|
|
310
590
|
const items = delivery.items.map((item) => {
|
|
311
|
-
const
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
591
|
+
const current = currentRetrievableDeliveryEntry(database, query.workspace, item);
|
|
592
|
+
if (current === null)
|
|
593
|
+
throw new KiokukoError('INTEGRITY_ERROR', 'Stored context entry is no longer retrievable');
|
|
594
|
+
const entry = readEntryRevision(database, {
|
|
595
|
+
entryId: item.entryId,
|
|
596
|
+
workspace: current.workspace,
|
|
597
|
+
revision: item.entryRevision,
|
|
598
|
+
});
|
|
318
599
|
const take = (value, budget) => Array.from(value).slice(0, Math.max(0, budget)).join('');
|
|
319
600
|
const count = (value) => Array.from(value).length;
|
|
320
601
|
const title = take(entry.title, remaining);
|
|
@@ -323,6 +604,12 @@ function storedContext(database, query, delivery) {
|
|
|
323
604
|
remaining -= count(summary ?? '');
|
|
324
605
|
const bodyPreview = take(entry.body, remaining);
|
|
325
606
|
remaining -= count(bodyPreview);
|
|
607
|
+
const characterCount = count(title) + count(summary ?? '') + count(bodyPreview);
|
|
608
|
+
const truncated = count(title) < count(entry.title)
|
|
609
|
+
|| (entry.summary !== null && count(summary ?? '') < count(entry.summary))
|
|
610
|
+
|| count(bodyPreview) < count(entry.body);
|
|
611
|
+
totalCharacterCount += characterCount;
|
|
612
|
+
anyTruncated ||= truncated;
|
|
326
613
|
return {
|
|
327
614
|
entryId: item.entryId,
|
|
328
615
|
entryRevision: item.entryRevision,
|
|
@@ -333,13 +620,16 @@ function storedContext(database, query, delivery) {
|
|
|
333
620
|
title,
|
|
334
621
|
summary,
|
|
335
622
|
bodyPreview,
|
|
336
|
-
characterCount
|
|
337
|
-
truncated
|
|
623
|
+
characterCount,
|
|
624
|
+
truncated,
|
|
338
625
|
},
|
|
339
626
|
untrusted: true,
|
|
340
627
|
...(item.origin === undefined ? {} : { origin: item.origin }),
|
|
341
628
|
};
|
|
342
629
|
});
|
|
630
|
+
if (totalCharacterCount !== delivery.charCount || anyTruncated !== delivery.truncated) {
|
|
631
|
+
throw new KiokukoError('INTEGRITY_ERROR', 'Stored context character accounting is invalid');
|
|
632
|
+
}
|
|
343
633
|
return {
|
|
344
634
|
deliveryId: delivery.deliveryId,
|
|
345
635
|
runId: delivery.runId,
|
|
@@ -351,13 +641,87 @@ function storedContext(database, query, delivery) {
|
|
|
351
641
|
untrusted: true,
|
|
352
642
|
};
|
|
353
643
|
}
|
|
644
|
+
function storedDeliveryIsRetrievable(database, query, delivery) {
|
|
645
|
+
if (delivery.throughSequence !== query.throughSequence) {
|
|
646
|
+
throw new KiokukoError('INTEGRITY_ERROR', 'Stored context delivery sequence is invalid');
|
|
647
|
+
}
|
|
648
|
+
if (!delivery.items.every((item) => currentRetrievableDeliveryEntry(database, query.workspace, item) !== null))
|
|
649
|
+
return false;
|
|
650
|
+
return !(delivery.taskProfileHash !== query.profileHash
|
|
651
|
+
|| delivery.queryHash !== query.queryHash
|
|
652
|
+
|| delivery.policyVersion !== CONTEXT_BROKER_POLICY_VERSION
|
|
653
|
+
|| (delivery.scoreSchemaVersion ?? 1) !== 1
|
|
654
|
+
|| delivery.charBudget !== query.characterBudget
|
|
655
|
+
|| delivery.items.length > query.limit);
|
|
656
|
+
}
|
|
657
|
+
function assertPreparedSelectedEntries(database, query, result) {
|
|
658
|
+
if (result.context !== null
|
|
659
|
+
&& result.context.items.some((item) => currentRetrievableDeliveryEntry(database, query.workspace, item) === null)) {
|
|
660
|
+
throw new KiokukoError('CONFLICT', 'Context delivery selection changed before return');
|
|
661
|
+
}
|
|
662
|
+
}
|
|
663
|
+
function assertPreparedBrokerState(database, query, result, expectedHistoryStateHash = query.deliveryHistoryStateHash) {
|
|
664
|
+
assertPreparedProjectState(database, query);
|
|
665
|
+
if (query.run === null) {
|
|
666
|
+
if (query.retrievalStateHash !== null
|
|
667
|
+
&& contextRetrievalStateHash(database, query.selectionWorkspaces, { includeEcosystem: query.includeEcosystem }) !== query.retrievalStateHash) {
|
|
668
|
+
throw new KiokukoError('CONFLICT', 'Context selection state changed after ranking');
|
|
669
|
+
}
|
|
670
|
+
return;
|
|
671
|
+
}
|
|
672
|
+
const current = currentRunContext(database, query.run.runId);
|
|
673
|
+
const currentStatus = current.intakeStatus === 'active' ? 'needs_answer' : current.intakeStatus;
|
|
674
|
+
if (query.runStateHash === null
|
|
675
|
+
|| current.stateHash !== query.runStateHash
|
|
676
|
+
|| current.run.workspace !== query.workspace
|
|
677
|
+
|| current.run.status !== query.run.status
|
|
678
|
+
|| current.run.lastSequence !== query.throughSequence
|
|
679
|
+
|| current.intakeSessionId !== query.intakeSessionId
|
|
680
|
+
|| currentStatus !== query.runStatus
|
|
681
|
+
|| current.profileHash !== query.profileHash
|
|
682
|
+
|| canonicalContentHash([...current.recommendedTags].sort()) !== canonicalContentHash([...query.recommendedTags].sort())) {
|
|
683
|
+
throw new KiokukoError('CONFLICT', 'Context delivery conflicts with current run state');
|
|
684
|
+
}
|
|
685
|
+
if (result.context !== null && query.run.status !== 'active') {
|
|
686
|
+
throw new KiokukoError('CONFLICT', 'Context delivery conflicts with current run state');
|
|
687
|
+
}
|
|
688
|
+
assertPreparedSelectedEntries(database, query, result);
|
|
689
|
+
if (query.retrievalStateHash !== null
|
|
690
|
+
&& contextRetrievalStateHash(database, query.selectionWorkspaces, { includeEcosystem: query.includeEcosystem }) !== query.retrievalStateHash) {
|
|
691
|
+
throw new KiokukoError('CONFLICT', 'Context selection state changed after ranking');
|
|
692
|
+
}
|
|
693
|
+
if (expectedHistoryStateHash !== null) {
|
|
694
|
+
const currentHistory = priorData(database, query, query.deliveryHistoryExcludeQueryHash === null
|
|
695
|
+
? {}
|
|
696
|
+
: { excludeDeliveredQueryHash: query.deliveryHistoryExcludeQueryHash });
|
|
697
|
+
if (currentHistory.stateHash !== expectedHistoryStateHash) {
|
|
698
|
+
throw new KiokukoError('CONFLICT', 'Context delivery history changed after ranking');
|
|
699
|
+
}
|
|
700
|
+
}
|
|
701
|
+
}
|
|
702
|
+
function replayableDelivery(database, query) {
|
|
703
|
+
if (query.run === null)
|
|
704
|
+
return { delivery: null, found: false };
|
|
705
|
+
const rows = database.prepare(`
|
|
706
|
+
SELECT delivery_id AS deliveryId
|
|
707
|
+
FROM context_deliveries
|
|
708
|
+
WHERE run_id = ? AND query_hash = ?
|
|
709
|
+
ORDER BY delivery_id ASC
|
|
710
|
+
`).all(query.run.runId, query.queryHash);
|
|
711
|
+
for (const row of rows) {
|
|
712
|
+
const delivery = readContextDelivery(database, { workspace: query.workspace, deliveryId: row.deliveryId });
|
|
713
|
+
if (storedDeliveryIsRetrievable(database, query, delivery)
|
|
714
|
+
&& deliveryHistoryIsAttested(database, query, delivery)) {
|
|
715
|
+
return { delivery, found: true };
|
|
716
|
+
}
|
|
717
|
+
}
|
|
718
|
+
return { delivery: null, found: rows.length > 0 };
|
|
719
|
+
}
|
|
354
720
|
export class ContextBroker {
|
|
355
721
|
database;
|
|
356
|
-
options;
|
|
357
722
|
inFlight = new Map();
|
|
358
|
-
constructor(database
|
|
723
|
+
constructor(database) {
|
|
359
724
|
this.database = database;
|
|
360
|
-
this.options = options;
|
|
361
725
|
}
|
|
362
726
|
listDeliveries(input) {
|
|
363
727
|
const context = currentRunContext(this.database, input.runId);
|
|
@@ -372,6 +736,20 @@ export class ContextBroker {
|
|
|
372
736
|
};
|
|
373
737
|
}
|
|
374
738
|
async query(rawInput, persistence = {}) {
|
|
739
|
+
return this.execute(rawInput, normalizePersistence(persistence));
|
|
740
|
+
}
|
|
741
|
+
async queryGated(rawInput, decide, persistence = {}) {
|
|
742
|
+
const normalizedPersistence = normalizePersistence(persistence);
|
|
743
|
+
const input = normalizeInput(rawInput);
|
|
744
|
+
const query = preparedQuery(this.database, input);
|
|
745
|
+
const prepared = await this.prepareResult(query);
|
|
746
|
+
const decision = normalizedGateDecision(decide(prepared.result));
|
|
747
|
+
const broker = decision.persist
|
|
748
|
+
? await this.persistPrepared(prepared, normalizedPersistence, query, decision.assertBeforePersist)
|
|
749
|
+
: this.validatePrepared(prepared, query, decision.assertBeforePersist);
|
|
750
|
+
return { broker, value: decision.value };
|
|
751
|
+
}
|
|
752
|
+
async execute(rawInput, persistence) {
|
|
375
753
|
const input = normalizeInput(rawInput);
|
|
376
754
|
const query = preparedQuery(this.database, input);
|
|
377
755
|
const previous = this.inFlight.get(query.queryHash);
|
|
@@ -388,6 +766,10 @@ export class ContextBroker {
|
|
|
388
766
|
}
|
|
389
767
|
}
|
|
390
768
|
async queryPrepared(query, persistence) {
|
|
769
|
+
const prepared = await this.prepareResult(query);
|
|
770
|
+
return this.persistPrepared(prepared, persistence, query);
|
|
771
|
+
}
|
|
772
|
+
async prepareResult(query) {
|
|
391
773
|
const base = {
|
|
392
774
|
status: query.runStatus,
|
|
393
775
|
taskProfile: { ...query.taskProfile },
|
|
@@ -398,63 +780,140 @@ export class ContextBroker {
|
|
|
398
780
|
projection: query.projection,
|
|
399
781
|
context: null,
|
|
400
782
|
recommendations: query.projection === null ? [] : buildRecommendations({ projection: query.projection, broker: {} }),
|
|
401
|
-
externalSyncSummary: emptyExternalSummary(),
|
|
402
783
|
};
|
|
403
784
|
if (query.runStatus === 'needs_answer')
|
|
404
|
-
return base;
|
|
405
|
-
const
|
|
406
|
-
const
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
}
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
throw error;
|
|
414
|
-
}
|
|
415
|
-
})();
|
|
416
|
-
if (existing) {
|
|
785
|
+
return { result: base, replayDelivery: null, pendingDelivery: null };
|
|
786
|
+
const replay = replayableDelivery(this.database, query);
|
|
787
|
+
const excludeDeliveredQueryHash = replay.delivery === null && replay.found ? query.queryHash : undefined;
|
|
788
|
+
const prior = priorData(this.database, query, excludeDeliveredQueryHash === undefined
|
|
789
|
+
? {}
|
|
790
|
+
: { excludeDeliveredQueryHash });
|
|
791
|
+
query.deliveryHistoryStateHash = prior.stateHash;
|
|
792
|
+
query.deliveryHistoryExcludeQueryHash = excludeDeliveredQueryHash ?? null;
|
|
793
|
+
if (replay.delivery !== null) {
|
|
417
794
|
return {
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
795
|
+
result: {
|
|
796
|
+
...base,
|
|
797
|
+
context: storedContext(this.database, query, replay.delivery),
|
|
798
|
+
recommendations: query.projection === null ? [] : buildRecommendations({ projection: query.projection, broker: { staleDeliveredEntries: prior.stale } }),
|
|
799
|
+
},
|
|
800
|
+
replayDelivery: replay.delivery,
|
|
801
|
+
pendingDelivery: null,
|
|
422
802
|
};
|
|
423
803
|
}
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
const prepared = await prepareOfficialSourceSync({
|
|
428
|
-
workspace: query.workspace,
|
|
429
|
-
task: query.task,
|
|
430
|
-
profile: query.taskProfile,
|
|
431
|
-
recommendedTags: query.recommendedTags,
|
|
432
|
-
...(this.options.fetchImpl === undefined ? {} : { fetchImpl: this.options.fetchImpl }),
|
|
433
|
-
});
|
|
434
|
-
const result = persistence.persistSources === undefined
|
|
435
|
-
? persistOfficialSourceSync(this.database, { workspace: query.workspace, prepared })
|
|
436
|
-
: await persistence.persistSources(query.workspace, prepared);
|
|
437
|
-
externalSyncSummary = { attempted: result.attempted, imported: result.imported, sources: result.sources };
|
|
438
|
-
ranked = await rank(this.database, query, priorData(this.database, query));
|
|
804
|
+
const ranked = await rank(this.database, query, prior);
|
|
805
|
+
if (query.run !== null && prior.stateHash === null) {
|
|
806
|
+
throw new KiokukoError('INTEGRITY_ERROR', 'Stored context delivery history is invalid');
|
|
439
807
|
}
|
|
808
|
+
const deliveryQuery = query.run === null
|
|
809
|
+
? query
|
|
810
|
+
: {
|
|
811
|
+
...query,
|
|
812
|
+
deliveryId: historyAttestedDeliveryId(query, prior.stateHash, query.deliveryHistoryExcludeQueryHash),
|
|
813
|
+
};
|
|
440
814
|
const recommendations = query.projection === null
|
|
441
815
|
? []
|
|
442
816
|
: buildRecommendations({ projection: query.projection, broker: { staleDeliveredEntries: prior.stale } });
|
|
443
|
-
const context = outputContext(
|
|
444
|
-
if (
|
|
445
|
-
return { ...base, context, recommendations,
|
|
817
|
+
const context = outputContext(deliveryQuery, ranked, null);
|
|
818
|
+
if (deliveryQuery.deliveryId === null || deliveryQuery.run === null) {
|
|
819
|
+
return { result: { ...base, context, recommendations }, replayDelivery: null, pendingDelivery: null };
|
|
446
820
|
}
|
|
447
|
-
const deliveryRequest = deliveryInput(
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
:
|
|
451
|
-
|
|
821
|
+
const deliveryRequest = deliveryInput(deliveryQuery, ranked);
|
|
822
|
+
return {
|
|
823
|
+
result: { ...base, context, recommendations },
|
|
824
|
+
replayDelivery: null,
|
|
825
|
+
pendingDelivery: { query: deliveryQuery, ranked, input: deliveryRequest },
|
|
826
|
+
};
|
|
827
|
+
}
|
|
828
|
+
async persistPrepared(prepared, persistence, query, assertBeforePersist) {
|
|
829
|
+
if (prepared.pendingDelivery === null) {
|
|
830
|
+
return withImmediateTransaction(this.database, () => {
|
|
831
|
+
if (prepared.replayDelivery !== null) {
|
|
832
|
+
assertPreparedSelectedEntries(this.database, query, prepared.result);
|
|
833
|
+
assertReplayDeliveryUnchanged(this.database, prepared.replayDelivery);
|
|
834
|
+
}
|
|
835
|
+
assertPreparedBrokerState(this.database, query, prepared.result);
|
|
836
|
+
if (assertBeforePersist !== undefined) {
|
|
837
|
+
assertBeforePersist();
|
|
838
|
+
if (prepared.replayDelivery !== null) {
|
|
839
|
+
assertPreparedSelectedEntries(this.database, query, prepared.result);
|
|
840
|
+
assertReplayDeliveryUnchanged(this.database, prepared.replayDelivery);
|
|
841
|
+
}
|
|
842
|
+
assertPreparedBrokerState(this.database, query, prepared.result);
|
|
843
|
+
}
|
|
844
|
+
return prepared.result;
|
|
845
|
+
});
|
|
846
|
+
}
|
|
847
|
+
const pendingDelivery = prepared.pendingDelivery;
|
|
848
|
+
let committedDelivery = null;
|
|
849
|
+
let committedHistoryStateHash = null;
|
|
850
|
+
let invocationCount = 0;
|
|
851
|
+
let acceptingInvocation = true;
|
|
852
|
+
const persist = () => {
|
|
853
|
+
if (!acceptingInvocation) {
|
|
854
|
+
throw new KiokukoError('INTEGRITY_ERROR', 'Context broker write adapter invoked persistence outside its queue operation');
|
|
855
|
+
}
|
|
856
|
+
invocationCount += 1;
|
|
857
|
+
if (invocationCount !== 1) {
|
|
858
|
+
throw new KiokukoError('INTEGRITY_ERROR', 'Context broker write adapter invoked persistence more than once');
|
|
859
|
+
}
|
|
860
|
+
committedDelivery = withImmediateTransaction(this.database, () => {
|
|
861
|
+
assertPreparedBrokerState(this.database, query, prepared.result);
|
|
862
|
+
if (assertBeforePersist !== undefined) {
|
|
863
|
+
assertBeforePersist();
|
|
864
|
+
assertPreparedBrokerState(this.database, query, prepared.result);
|
|
865
|
+
}
|
|
866
|
+
const delivery = recordContextDeliveryInTransaction(this.database, pendingDelivery.input);
|
|
867
|
+
committedHistoryStateHash = priorData(this.database, query, query.deliveryHistoryExcludeQueryHash === null
|
|
868
|
+
? {}
|
|
869
|
+
: { excludeDeliveredQueryHash: query.deliveryHistoryExcludeQueryHash }).stateHash;
|
|
870
|
+
return delivery;
|
|
871
|
+
});
|
|
872
|
+
return committedDelivery;
|
|
873
|
+
};
|
|
874
|
+
let returned;
|
|
875
|
+
try {
|
|
876
|
+
returned = persistence.enqueueWrite === undefined
|
|
877
|
+
? persist()
|
|
878
|
+
: await persistence.enqueueWrite(persist);
|
|
879
|
+
}
|
|
880
|
+
finally {
|
|
881
|
+
acceptingInvocation = false;
|
|
882
|
+
}
|
|
883
|
+
const committed = committedDelivery;
|
|
884
|
+
const committedHistory = committedHistoryStateHash;
|
|
885
|
+
if (invocationCount !== 1 || committed === null || committedHistory === null || returned !== committed) {
|
|
886
|
+
throw new KiokukoError('INTEGRITY_ERROR', 'Context broker write adapter returned an invalid result');
|
|
887
|
+
}
|
|
888
|
+
withImmediateTransaction(this.database, () => {
|
|
889
|
+
assertReplayDeliveryUnchanged(this.database, committed);
|
|
890
|
+
if (!deliveryHistoryIsAttested(this.database, query, committed)) {
|
|
891
|
+
throw new KiokukoError('CONFLICT', 'Context delivery history changed after ranking');
|
|
892
|
+
}
|
|
893
|
+
assertPreparedBrokerState(this.database, query, prepared.result, committedHistory);
|
|
894
|
+
});
|
|
895
|
+
return {
|
|
896
|
+
...prepared.result,
|
|
897
|
+
context: outputContext(pendingDelivery.query, pendingDelivery.ranked, committed),
|
|
898
|
+
};
|
|
899
|
+
}
|
|
900
|
+
validatePrepared(prepared, query, assertBeforeReturn) {
|
|
901
|
+
return withImmediateTransaction(this.database, () => {
|
|
902
|
+
if (prepared.replayDelivery !== null) {
|
|
903
|
+
assertPreparedSelectedEntries(this.database, query, prepared.result);
|
|
904
|
+
assertReplayDeliveryUnchanged(this.database, prepared.replayDelivery);
|
|
905
|
+
}
|
|
906
|
+
assertPreparedBrokerState(this.database, query, prepared.result);
|
|
907
|
+
if (assertBeforeReturn !== undefined) {
|
|
908
|
+
assertBeforeReturn();
|
|
909
|
+
if (prepared.replayDelivery !== null) {
|
|
910
|
+
assertPreparedSelectedEntries(this.database, query, prepared.result);
|
|
911
|
+
assertReplayDeliveryUnchanged(this.database, prepared.replayDelivery);
|
|
912
|
+
}
|
|
913
|
+
assertPreparedBrokerState(this.database, query, prepared.result);
|
|
914
|
+
}
|
|
915
|
+
return prepared.result;
|
|
916
|
+
});
|
|
452
917
|
}
|
|
453
|
-
}
|
|
454
|
-
export function contextBrokerQueryHash(input) {
|
|
455
|
-
return createHash('sha256').update(JSON.stringify(input), 'utf8').digest('hex');
|
|
456
|
-
}
|
|
457
|
-
export function newContextDeliveryId() {
|
|
458
|
-
return `context-${randomUUID()}`;
|
|
459
918
|
}
|
|
460
919
|
//# sourceMappingURL=broker.js.map
|