@askdkc/kiokuko 0.1.16 → 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 -260
- 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 +14 -24
- package/dist/akinator/agent-task.d.ts.map +1 -1
- package/dist/akinator/agent-task.js +460 -103
- package/dist/akinator/agent-task.js.map +1 -1
- package/dist/akinator/capabilities.d.ts +52 -7
- package/dist/akinator/capabilities.d.ts.map +1 -1
- package/dist/akinator/capabilities.js +226 -28
- 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 +561 -144
- 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 +30 -14
- package/dist/context/broker.d.ts.map +1 -1
- package/dist/context/broker.js +628 -150
- package/dist/context/broker.js.map +1 -1
- package/dist/context/delivery.d.ts +8 -22
- package/dist/context/delivery.d.ts.map +1 -1
- package/dist/context/delivery.js +204 -152
- 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 +250 -268
- package/dist/context/feedback.js.map +1 -1
- package/dist/context/origin.d.ts +9 -0
- package/dist/context/origin.d.ts.map +1 -0
- package/dist/context/origin.js +15 -0
- package/dist/context/origin.js.map +1 -0
- package/dist/context/ranking.d.ts +4 -13
- package/dist/context/ranking.d.ts.map +1 -1
- package/dist/context/ranking.js +21 -5
- 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 +19 -6
- package/dist/context/scoped-broker.d.ts.map +1 -1
- package/dist/context/scoped-broker.js +530 -131
- 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 +134 -54
- 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 +41 -44
- 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/bounded-stdio-transport.d.ts +23 -0
- package/dist/mcp/bounded-stdio-transport.d.ts.map +1 -0
- package/dist/mcp/bounded-stdio-transport.js +109 -0
- package/dist/mcp/bounded-stdio-transport.js.map +1 -0
- package/dist/mcp/server.d.ts +4 -0
- package/dist/mcp/server.d.ts.map +1 -1
- package/dist/mcp/server.js +111 -75
- 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 +45 -1
- package/dist/memory/curator.d.ts.map +1 -1
- package/dist/memory/curator.js +290 -68
- 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 +78 -0
- package/dist/memory/federated-retrieval.d.ts.map +1 -0
- package/dist/memory/federated-retrieval.js +441 -0
- package/dist/memory/federated-retrieval.js.map +1 -0
- 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/portability.d.ts +10 -0
- package/dist/memory/portability.d.ts.map +1 -0
- package/dist/memory/portability.js +44 -0
- package/dist/memory/portability.js.map +1 -0
- 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 +11 -0
- package/dist/memory/retrieval.d.ts.map +1 -1
- package/dist/memory/retrieval.js +34 -120
- 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 +22 -13
- package/dist/memory/scoped-memory.d.ts.map +1 -1
- package/dist/memory/scoped-memory.js +248 -139
- 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 +8 -1
- package/dist/memory/structured-memory.d.ts.map +1 -1
- package/dist/memory/structured-memory.js +74 -20
- 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 +33 -0
- package/dist/repository/project-fingerprint.d.ts.map +1 -0
- package/dist/repository/project-fingerprint.js +429 -0
- package/dist/repository/project-fingerprint.js.map +1 -0
- 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 +56 -8
- package/dist/web/i18n.d.ts.map +1 -1
- package/dist/web/i18n.js +224 -32
- package/dist/web/i18n.js.map +1 -1
- package/dist/web/server.d.ts.map +1 -1
- package/dist/web/server.js +458 -42
- 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 +697 -61
- package/dist/web/ui.js.map +1 -1
- package/migrations/008_federated_memory.sql +46 -0
- package/migrations/009_external_skill_discovery.sql +126 -0
- package/package.json +6 -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/commands/use.js
CHANGED
|
@@ -1,11 +1,15 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { randomUUID } from 'node:crypto';
|
|
2
|
+
import { lstat } from 'node:fs/promises';
|
|
2
3
|
import path from 'node:path';
|
|
3
|
-
import {
|
|
4
|
+
import { setTimeout as delay } from 'node:timers/promises';
|
|
5
|
+
import { assertFileExpectation, assertAtomicCleanupComplete, AtomicCommittedMutationError, AtomicCommittedUnlinkError, atomicWriteTextIfUnchanged, readPendingAtomicMutation, readRegularFile, unlinkRegularFileIfUnchanged, } from '../agent-file/atomic-write.js';
|
|
6
|
+
import { readManagedBlockTemplateVersion, removeManagedBlock, } from '../agent-file/managed-block.js';
|
|
4
7
|
import { AGENT_TEMPLATE_VERSION, renderAgentFile } from '../agent-file/render.js';
|
|
5
8
|
import { getGlobalDatabasePath } from '../config/paths.js';
|
|
6
|
-
import {
|
|
9
|
+
import { parseProjectConfig, parseProjectConfigText, } from '../config/project-config.js';
|
|
7
10
|
import { initializeDatabase } from './init.js';
|
|
8
11
|
import { openConnection } from '../db/connection.js';
|
|
12
|
+
import { TransactionCommitUncertainError } from '../db/transaction.js';
|
|
9
13
|
import { registerRepositoryAndLocation } from '../repository/binding.js';
|
|
10
14
|
import { detectRepositoryRoot } from '../repository/detect-root.js';
|
|
11
15
|
import { createRepositoryIdentity } from '../repository/identity.js';
|
|
@@ -14,20 +18,15 @@ import { readGitOrigin } from '../repository/git-origin.js';
|
|
|
14
18
|
function ensureChildPath(root, filePath) {
|
|
15
19
|
const resolvedRoot = path.resolve(root);
|
|
16
20
|
const resolvedPath = path.resolve(root, filePath);
|
|
17
|
-
if (resolvedPath
|
|
21
|
+
if (resolvedPath === resolvedRoot || !resolvedPath.startsWith(`${resolvedRoot}${path.sep}`)) {
|
|
18
22
|
throw new KiokukoError('VALIDATION_ERROR', 'agentFile must remain inside the repository root');
|
|
19
23
|
}
|
|
20
24
|
return resolvedPath;
|
|
21
25
|
}
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
return
|
|
25
|
-
|
|
26
|
-
catch (error) {
|
|
27
|
-
if (error instanceof Error && 'code' in error && error.code === 'ENOENT')
|
|
28
|
-
return undefined;
|
|
29
|
-
throw error;
|
|
30
|
-
}
|
|
26
|
+
function parseBindingSnapshot(snapshot) {
|
|
27
|
+
if (snapshot === undefined)
|
|
28
|
+
return undefined;
|
|
29
|
+
return parseProjectConfigText(snapshot.content);
|
|
31
30
|
}
|
|
32
31
|
function bindingText(value) {
|
|
33
32
|
return `${JSON.stringify(value, null, 2)}\n`;
|
|
@@ -42,7 +41,497 @@ function preferredCliCommand() {
|
|
|
42
41
|
? 'npm exec -- kiokuko'
|
|
43
42
|
: 'kiokuko';
|
|
44
43
|
}
|
|
45
|
-
|
|
44
|
+
class ConcurrentUseBinding extends Error {
|
|
45
|
+
binding;
|
|
46
|
+
constructor(binding) {
|
|
47
|
+
super('A concurrent use operation created the repository binding');
|
|
48
|
+
this.binding = binding;
|
|
49
|
+
this.name = 'ConcurrentUseBinding';
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
const CONCURRENT_IDENTICAL_OBSERVATION_ATTEMPTS = 50;
|
|
53
|
+
const CONCURRENT_IDENTICAL_OBSERVATION_DELAY_MS = 10;
|
|
54
|
+
class CommittedRegistrationCloseError extends AggregateError {
|
|
55
|
+
constructor(closeError) {
|
|
56
|
+
super([closeError], 'Repository registration committed, but closing the database connection failed');
|
|
57
|
+
this.name = 'CommittedRegistrationCloseError';
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
class UncertainRegistrationCloseError extends AggregateError {
|
|
61
|
+
registrationError;
|
|
62
|
+
closeError;
|
|
63
|
+
constructor(registrationError, closeError) {
|
|
64
|
+
super([registrationError, closeError], 'Repository registration may have committed, and closing the database connection also failed');
|
|
65
|
+
this.name = 'UncertainRegistrationCloseError';
|
|
66
|
+
this.registrationError = registrationError;
|
|
67
|
+
this.closeError = closeError;
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
function expectation(expected, containmentRoot, parentIdentity) {
|
|
71
|
+
return {
|
|
72
|
+
expected,
|
|
73
|
+
containmentRoot,
|
|
74
|
+
...(parentIdentity === undefined ? {} : { expectedParentDirectory: parentIdentity }),
|
|
75
|
+
};
|
|
76
|
+
}
|
|
77
|
+
async function existingParentIdentity(filePath) {
|
|
78
|
+
let info;
|
|
79
|
+
try {
|
|
80
|
+
info = await lstat(path.dirname(filePath), { bigint: true });
|
|
81
|
+
}
|
|
82
|
+
catch (error) {
|
|
83
|
+
if (error instanceof Error && 'code' in error && error.code === 'ENOENT') {
|
|
84
|
+
throw new KiokukoError('VALIDATION_ERROR', 'Managed file parent directory must already exist');
|
|
85
|
+
}
|
|
86
|
+
throw error;
|
|
87
|
+
}
|
|
88
|
+
if (info.isSymbolicLink()) {
|
|
89
|
+
throw new KiokukoError('SECURITY_REJECTION', 'Refusing to traverse a symbolic link');
|
|
90
|
+
}
|
|
91
|
+
if (!info.isDirectory()) {
|
|
92
|
+
throw new KiokukoError('VALIDATION_ERROR', 'Managed file parent must be a directory');
|
|
93
|
+
}
|
|
94
|
+
const identity = { device: BigInt(info.dev), inode: BigInt(info.ino) };
|
|
95
|
+
if (identity.inode === 0n) {
|
|
96
|
+
throw new KiokukoError('SECURITY_REJECTION', 'The filesystem does not expose a stable parent-directory identity required for safe mutation');
|
|
97
|
+
}
|
|
98
|
+
return identity;
|
|
99
|
+
}
|
|
100
|
+
async function restoreInstalledWrites(files, dependencies) {
|
|
101
|
+
const failures = [];
|
|
102
|
+
for (const file of [...files].reverse()) {
|
|
103
|
+
try {
|
|
104
|
+
if (file.original === undefined) {
|
|
105
|
+
if (file.installed === undefined) {
|
|
106
|
+
throw new KiokukoError('INTEGRITY_ERROR', 'Invalid file-restoration state');
|
|
107
|
+
}
|
|
108
|
+
const outcome = await dependencies.unlinkRegularFileIfUnchanged(file.path, expectation(file.installed, file.containmentRoot, file.parentIdentity));
|
|
109
|
+
assertAtomicCleanupComplete(outcome);
|
|
110
|
+
}
|
|
111
|
+
else {
|
|
112
|
+
const outcome = await dependencies.atomicWriteTextIfUnchanged(file.path, file.original.content, expectation(file.installed, file.containmentRoot, file.parentIdentity), file.original.mode);
|
|
113
|
+
assertAtomicCleanupComplete(outcome);
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
catch (error) {
|
|
117
|
+
failures.push(error);
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
return failures;
|
|
121
|
+
}
|
|
122
|
+
function isConflict(error) {
|
|
123
|
+
return error instanceof KiokukoError && error.code === 'CONFLICT';
|
|
124
|
+
}
|
|
125
|
+
function isTargetConflict(error, filePath) {
|
|
126
|
+
return isConflict(error) && error.details.target === filePath;
|
|
127
|
+
}
|
|
128
|
+
function sameFileIdentity(left, right) {
|
|
129
|
+
return left.device === right.device && left.inode === right.inode;
|
|
130
|
+
}
|
|
131
|
+
function assertSupportedManagedTemplate(snapshot, label) {
|
|
132
|
+
if (snapshot === undefined)
|
|
133
|
+
return;
|
|
134
|
+
const version = readManagedBlockTemplateVersion(snapshot.content);
|
|
135
|
+
if (version !== undefined && version > AGENT_TEMPLATE_VERSION) {
|
|
136
|
+
throw new KiokukoError('VALIDATION_ERROR', `${label} uses managed template version ${version}, newer than supported version ${AGENT_TEMPLATE_VERSION}`);
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
function sameRegularFileSnapshot(left, right) {
|
|
140
|
+
return left.content === right.content
|
|
141
|
+
&& left.mode === right.mode
|
|
142
|
+
&& sameFileIdentity(left.identity, right.identity);
|
|
143
|
+
}
|
|
144
|
+
async function readObservedTarget(filePath, containmentRoot, parentIdentity) {
|
|
145
|
+
const current = await readRegularFile(filePath, { containmentRoot });
|
|
146
|
+
await assertFileExpectation(filePath, expectation(current, containmentRoot, parentIdentity));
|
|
147
|
+
if (current === undefined)
|
|
148
|
+
return undefined;
|
|
149
|
+
let info;
|
|
150
|
+
try {
|
|
151
|
+
info = await lstat(filePath, { bigint: true });
|
|
152
|
+
}
|
|
153
|
+
catch (error) {
|
|
154
|
+
if (error instanceof Error && 'code' in error && error.code === 'ENOENT') {
|
|
155
|
+
throw new KiokukoError('CONFLICT', 'Concurrent target changed during convergence', {
|
|
156
|
+
target: filePath,
|
|
157
|
+
});
|
|
158
|
+
}
|
|
159
|
+
throw error;
|
|
160
|
+
}
|
|
161
|
+
if (!info.isFile()
|
|
162
|
+
|| info.dev !== current.identity.device
|
|
163
|
+
|| info.ino !== current.identity.inode
|
|
164
|
+
|| Number(info.mode & 511n) !== current.mode) {
|
|
165
|
+
throw new KiokukoError('CONFLICT', 'Concurrent target changed during convergence', {
|
|
166
|
+
target: filePath,
|
|
167
|
+
});
|
|
168
|
+
}
|
|
169
|
+
await assertFileExpectation(filePath, expectation(current, containmentRoot, parentIdentity));
|
|
170
|
+
return { snapshot: current, linkCount: info.nlink };
|
|
171
|
+
}
|
|
172
|
+
async function readStrictSettledTarget(filePath, containmentRoot, parentIdentity, label) {
|
|
173
|
+
const first = await readObservedTarget(filePath, containmentRoot, parentIdentity);
|
|
174
|
+
const firstPending = await readPendingAtomicMutation(filePath, parentIdentity, containmentRoot);
|
|
175
|
+
if (firstPending !== undefined) {
|
|
176
|
+
throw new KiokukoError('CONFLICT', `${label} has a concurrent atomic mutation`, {
|
|
177
|
+
target: filePath,
|
|
178
|
+
});
|
|
179
|
+
}
|
|
180
|
+
const second = await readObservedTarget(filePath, containmentRoot, parentIdentity);
|
|
181
|
+
const secondPending = await readPendingAtomicMutation(filePath, parentIdentity, containmentRoot);
|
|
182
|
+
if (secondPending !== undefined
|
|
183
|
+
|| (first === undefined) !== (second === undefined)
|
|
184
|
+
|| (first !== undefined
|
|
185
|
+
&& second !== undefined
|
|
186
|
+
&& !sameRegularFileSnapshot(first.snapshot, second.snapshot))) {
|
|
187
|
+
throw new KiokukoError('CONFLICT', `${label} changed while settling`, {
|
|
188
|
+
target: filePath,
|
|
189
|
+
});
|
|
190
|
+
}
|
|
191
|
+
const linked = first?.linkCount !== undefined && first.linkCount !== 1n
|
|
192
|
+
? first
|
|
193
|
+
: second?.linkCount !== undefined && second.linkCount !== 1n
|
|
194
|
+
? second
|
|
195
|
+
: undefined;
|
|
196
|
+
if (linked !== undefined) {
|
|
197
|
+
throw new KiokukoError('SECURITY_REJECTION', `${label} must have exactly one link`, {
|
|
198
|
+
target: filePath,
|
|
199
|
+
});
|
|
200
|
+
}
|
|
201
|
+
return second?.snapshot;
|
|
202
|
+
}
|
|
203
|
+
async function observeConcurrentTarget(filePath, content, mode, containmentRoot, parentIdentity) {
|
|
204
|
+
const observed = await readObservedTarget(filePath, containmentRoot, parentIdentity);
|
|
205
|
+
if (observed === undefined)
|
|
206
|
+
return { kind: 'absent' };
|
|
207
|
+
if (observed.snapshot.content !== content || observed.snapshot.mode !== mode) {
|
|
208
|
+
return { kind: 'different' };
|
|
209
|
+
}
|
|
210
|
+
if (observed.linkCount !== 1n)
|
|
211
|
+
return { kind: 'linked', snapshot: observed.snapshot };
|
|
212
|
+
return { kind: 'identical', snapshot: observed.snapshot };
|
|
213
|
+
}
|
|
214
|
+
async function readIdenticalTargetAfterConflict(filePath, content, mode, containmentRoot, parentIdentity, planned) {
|
|
215
|
+
let settlingCandidate;
|
|
216
|
+
let lastObservation;
|
|
217
|
+
let lastHadPendingArtifact = false;
|
|
218
|
+
for (let attempt = 0; attempt < CONCURRENT_IDENTICAL_OBSERVATION_ATTEMPTS; attempt += 1) {
|
|
219
|
+
const observation = await observeConcurrentTarget(filePath, content, mode, containmentRoot, parentIdentity);
|
|
220
|
+
if (settlingCandidate !== undefined) {
|
|
221
|
+
if (observation.kind === 'absent')
|
|
222
|
+
return undefined;
|
|
223
|
+
if (observation.kind === 'different'
|
|
224
|
+
|| !sameRegularFileSnapshot(settlingCandidate, observation.snapshot)) {
|
|
225
|
+
throw new KiokukoError('CONFLICT', 'Concurrent target changed while settling', {
|
|
226
|
+
target: filePath,
|
|
227
|
+
});
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
lastObservation = observation;
|
|
231
|
+
if (observation.kind === 'different')
|
|
232
|
+
return undefined;
|
|
233
|
+
if (observation.kind === 'absent') {
|
|
234
|
+
if (planned === undefined)
|
|
235
|
+
return undefined;
|
|
236
|
+
const pending = await readPendingAtomicMutation(filePath, parentIdentity, containmentRoot);
|
|
237
|
+
if (pending === undefined
|
|
238
|
+
|| pending.kind !== 'previous'
|
|
239
|
+
|| !sameRegularFileSnapshot(pending.snapshot, planned)) {
|
|
240
|
+
return undefined;
|
|
241
|
+
}
|
|
242
|
+
lastHadPendingArtifact = true;
|
|
243
|
+
}
|
|
244
|
+
else if (observation.kind === 'linked') {
|
|
245
|
+
settlingCandidate = observation.snapshot;
|
|
246
|
+
lastHadPendingArtifact = false;
|
|
247
|
+
}
|
|
248
|
+
else {
|
|
249
|
+
if (planned !== undefined
|
|
250
|
+
&& sameFileIdentity(observation.snapshot.identity, planned.identity)) {
|
|
251
|
+
throw new KiokukoError('CONFLICT', 'Concurrent target was modified in place instead of atomically replaced', { target: filePath });
|
|
252
|
+
}
|
|
253
|
+
const pending = await readPendingAtomicMutation(filePath, parentIdentity, containmentRoot);
|
|
254
|
+
if (pending === undefined)
|
|
255
|
+
return observation.snapshot;
|
|
256
|
+
if (planned === undefined
|
|
257
|
+
|| pending.kind !== 'previous'
|
|
258
|
+
|| !sameRegularFileSnapshot(pending.snapshot, planned)) {
|
|
259
|
+
throw new KiokukoError('CONFLICT', 'Concurrent target retained an incompatible atomic artifact', { target: filePath });
|
|
260
|
+
}
|
|
261
|
+
settlingCandidate = observation.snapshot;
|
|
262
|
+
lastHadPendingArtifact = true;
|
|
263
|
+
}
|
|
264
|
+
if (attempt + 1 < CONCURRENT_IDENTICAL_OBSERVATION_ATTEMPTS) {
|
|
265
|
+
await delay(CONCURRENT_IDENTICAL_OBSERVATION_DELAY_MS);
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
if (lastObservation?.kind === 'linked') {
|
|
269
|
+
throw new KiokukoError('SECURITY_REJECTION', 'Refusing to adopt a hard-linked concurrent target', { target: filePath });
|
|
270
|
+
}
|
|
271
|
+
if (lastHadPendingArtifact) {
|
|
272
|
+
throw new KiokukoError('CONFLICT', 'Concurrent target mutation did not settle', {
|
|
273
|
+
target: filePath,
|
|
274
|
+
});
|
|
275
|
+
}
|
|
276
|
+
return undefined;
|
|
277
|
+
}
|
|
278
|
+
async function writeOrConvergeIdentical(dependencies, filePath, content, planned, mode, containmentRoot, parentIdentity) {
|
|
279
|
+
try {
|
|
280
|
+
const outcome = await dependencies.atomicWriteTextIfUnchanged(filePath, content, expectation(planned, containmentRoot, parentIdentity), mode);
|
|
281
|
+
return {
|
|
282
|
+
snapshot: outcome.installed,
|
|
283
|
+
owned: true,
|
|
284
|
+
cleanupFailures: outcome.cleanupFailures,
|
|
285
|
+
};
|
|
286
|
+
}
|
|
287
|
+
catch (error) {
|
|
288
|
+
if (!isTargetConflict(error, filePath))
|
|
289
|
+
throw error;
|
|
290
|
+
const current = await readIdenticalTargetAfterConflict(filePath, content, mode, containmentRoot, parentIdentity, planned);
|
|
291
|
+
if (current === undefined)
|
|
292
|
+
throw error;
|
|
293
|
+
return { snapshot: current, owned: false, cleanupFailures: [] };
|
|
294
|
+
}
|
|
295
|
+
}
|
|
296
|
+
async function writeStrict(dependencies, filePath, content, planned, mode, containmentRoot, parentIdentity) {
|
|
297
|
+
const outcome = await dependencies.atomicWriteTextIfUnchanged(filePath, content, expectation(planned, containmentRoot, parentIdentity), mode);
|
|
298
|
+
return {
|
|
299
|
+
snapshot: outcome.installed,
|
|
300
|
+
owned: true,
|
|
301
|
+
cleanupFailures: outcome.cleanupFailures,
|
|
302
|
+
};
|
|
303
|
+
}
|
|
304
|
+
async function readSettledBindingSnapshot(bindingFile, repositoryRoot, bindingParentIdentity) {
|
|
305
|
+
let candidate;
|
|
306
|
+
let pendingOriginal;
|
|
307
|
+
let sawPending = false;
|
|
308
|
+
let lastState;
|
|
309
|
+
for (let attempt = 0; attempt < CONCURRENT_IDENTICAL_OBSERVATION_ATTEMPTS; attempt += 1) {
|
|
310
|
+
let observed = await readObservedTarget(bindingFile, repositoryRoot, bindingParentIdentity);
|
|
311
|
+
let pending = await readPendingAtomicMutation(bindingFile, bindingParentIdentity, repositoryRoot);
|
|
312
|
+
if (observed === undefined && candidate !== undefined) {
|
|
313
|
+
throw new KiokukoError('CONFLICT', 'Repository binding disappeared while settling', {
|
|
314
|
+
target: bindingFile,
|
|
315
|
+
});
|
|
316
|
+
}
|
|
317
|
+
if (observed === undefined && pending === undefined) {
|
|
318
|
+
observed = await readObservedTarget(bindingFile, repositoryRoot, bindingParentIdentity);
|
|
319
|
+
if (observed === undefined) {
|
|
320
|
+
pending = await readPendingAtomicMutation(bindingFile, bindingParentIdentity, repositoryRoot);
|
|
321
|
+
if (pending === undefined) {
|
|
322
|
+
if (sawPending) {
|
|
323
|
+
throw new KiokukoError('CONFLICT', 'Concurrent repository binding mutation ended without a target', { target: bindingFile });
|
|
324
|
+
}
|
|
325
|
+
return undefined;
|
|
326
|
+
}
|
|
327
|
+
}
|
|
328
|
+
}
|
|
329
|
+
if (pending !== undefined) {
|
|
330
|
+
sawPending = true;
|
|
331
|
+
if (pending.kind !== 'previous'
|
|
332
|
+
|| (pendingOriginal !== undefined
|
|
333
|
+
&& !sameRegularFileSnapshot(pendingOriginal, pending.snapshot))) {
|
|
334
|
+
throw new KiokukoError('CONFLICT', 'Repository binding has an incompatible atomic artifact', { target: bindingFile });
|
|
335
|
+
}
|
|
336
|
+
pendingOriginal = pending.snapshot;
|
|
337
|
+
}
|
|
338
|
+
if (observed !== undefined) {
|
|
339
|
+
if (candidate !== undefined && !sameRegularFileSnapshot(candidate, observed.snapshot)) {
|
|
340
|
+
throw new KiokukoError('CONFLICT', 'Repository binding changed while settling', {
|
|
341
|
+
target: bindingFile,
|
|
342
|
+
});
|
|
343
|
+
}
|
|
344
|
+
candidate = observed.snapshot;
|
|
345
|
+
if (pending === undefined && observed.linkCount === 1n)
|
|
346
|
+
return observed.snapshot;
|
|
347
|
+
lastState = pending === undefined ? 'linked' : 'pending';
|
|
348
|
+
}
|
|
349
|
+
else {
|
|
350
|
+
lastState = 'pending';
|
|
351
|
+
}
|
|
352
|
+
if (attempt + 1 < CONCURRENT_IDENTICAL_OBSERVATION_ATTEMPTS) {
|
|
353
|
+
await delay(CONCURRENT_IDENTICAL_OBSERVATION_DELAY_MS);
|
|
354
|
+
}
|
|
355
|
+
}
|
|
356
|
+
if (lastState === 'linked') {
|
|
357
|
+
throw new KiokukoError('SECURITY_REJECTION', 'Refusing to plan from a hard-linked repository binding file', { target: bindingFile });
|
|
358
|
+
}
|
|
359
|
+
throw new KiokukoError('CONFLICT', 'Concurrent repository binding mutation did not settle', {
|
|
360
|
+
target: bindingFile,
|
|
361
|
+
});
|
|
362
|
+
}
|
|
363
|
+
async function readConcurrentBinding(bindingFile, repositoryRoot, requestedAgentFile, bindingParentIdentity) {
|
|
364
|
+
const snapshot = await readSettledBindingSnapshot(bindingFile, repositoryRoot, bindingParentIdentity);
|
|
365
|
+
const binding = parseBindingSnapshot(snapshot);
|
|
366
|
+
if (snapshot === undefined || binding === undefined) {
|
|
367
|
+
throw new KiokukoError('CONFLICT', 'Concurrent repository binding disappeared during convergence', { target: bindingFile });
|
|
368
|
+
}
|
|
369
|
+
if (snapshot.content !== bindingText(binding)
|
|
370
|
+
|| (process.platform !== 'win32' && snapshot.mode !== 0o644)
|
|
371
|
+
|| binding.agentFile !== requestedAgentFile
|
|
372
|
+
|| binding.templateVersion !== AGENT_TEMPLATE_VERSION) {
|
|
373
|
+
throw new KiokukoError('CONFLICT', 'Concurrent use operation created an incompatible repository binding', { target: bindingFile });
|
|
374
|
+
}
|
|
375
|
+
return binding;
|
|
376
|
+
}
|
|
377
|
+
async function readSettledAgentPlan(filePath, containmentRoot, parentIdentity, forbiddenBindingIdentity, intendedFromOriginal) {
|
|
378
|
+
const continuePendingMutation = async (pending, observedFinalCandidate) => {
|
|
379
|
+
const intended = pending.kind === 'previous'
|
|
380
|
+
? intendedFromOriginal?.(pending.snapshot)
|
|
381
|
+
: undefined;
|
|
382
|
+
if (intended === undefined) {
|
|
383
|
+
throw new KiokukoError('CONFLICT', 'Agent target is absent during an incompatible atomic mutation', { target: filePath });
|
|
384
|
+
}
|
|
385
|
+
if (observedFinalCandidate !== undefined
|
|
386
|
+
&& (observedFinalCandidate.content !== intended.content
|
|
387
|
+
|| observedFinalCandidate.mode !== intended.mode
|
|
388
|
+
|| sameFileIdentity(observedFinalCandidate.identity, pending.snapshot.identity))) {
|
|
389
|
+
throw new KiokukoError('CONFLICT', 'Observed agent target is not the intended atomic result', { target: filePath });
|
|
390
|
+
}
|
|
391
|
+
const settled = await readRetriedAgentPlan(filePath, pending.snapshot, intended.content, intended.mode, containmentRoot, parentIdentity, forbiddenBindingIdentity, observedFinalCandidate);
|
|
392
|
+
if (settled === undefined) {
|
|
393
|
+
throw new KiokukoError('CONFLICT', 'Concurrent agent mutation did not settle', {
|
|
394
|
+
target: filePath,
|
|
395
|
+
});
|
|
396
|
+
}
|
|
397
|
+
return settled;
|
|
398
|
+
};
|
|
399
|
+
let linkedCandidate;
|
|
400
|
+
for (let attempt = 0; attempt < CONCURRENT_IDENTICAL_OBSERVATION_ATTEMPTS; attempt += 1) {
|
|
401
|
+
let observed = await readObservedTarget(filePath, containmentRoot, parentIdentity);
|
|
402
|
+
if (observed === undefined && linkedCandidate !== undefined) {
|
|
403
|
+
throw new KiokukoError('CONFLICT', 'Agent target disappeared while settling', {
|
|
404
|
+
target: filePath,
|
|
405
|
+
});
|
|
406
|
+
}
|
|
407
|
+
if (observed === undefined) {
|
|
408
|
+
let pending = await readPendingAtomicMutation(filePath, parentIdentity, containmentRoot);
|
|
409
|
+
if (pending === undefined) {
|
|
410
|
+
observed = await readObservedTarget(filePath, containmentRoot, parentIdentity);
|
|
411
|
+
if (observed === undefined) {
|
|
412
|
+
pending = await readPendingAtomicMutation(filePath, parentIdentity, containmentRoot);
|
|
413
|
+
if (pending === undefined)
|
|
414
|
+
return undefined;
|
|
415
|
+
}
|
|
416
|
+
}
|
|
417
|
+
if (observed === undefined) {
|
|
418
|
+
if (pending === undefined) {
|
|
419
|
+
throw new KiokukoError('INTEGRITY_ERROR', 'Atomic quarantine observation was lost');
|
|
420
|
+
}
|
|
421
|
+
return continuePendingMutation(pending);
|
|
422
|
+
}
|
|
423
|
+
}
|
|
424
|
+
if (forbiddenBindingIdentity !== undefined
|
|
425
|
+
&& sameFileIdentity(observed.snapshot.identity, forbiddenBindingIdentity)) {
|
|
426
|
+
throw new KiokukoError('CONFLICT', 'agentFile resolves to the repository binding file');
|
|
427
|
+
}
|
|
428
|
+
if (linkedCandidate !== undefined
|
|
429
|
+
&& !sameRegularFileSnapshot(linkedCandidate, observed.snapshot)) {
|
|
430
|
+
throw new KiokukoError('CONFLICT', 'Agent target changed while settling', {
|
|
431
|
+
target: filePath,
|
|
432
|
+
});
|
|
433
|
+
}
|
|
434
|
+
linkedCandidate = observed.snapshot;
|
|
435
|
+
if (observed.linkCount === 1n) {
|
|
436
|
+
const pending = await readPendingAtomicMutation(filePath, parentIdentity, containmentRoot);
|
|
437
|
+
if (pending === undefined)
|
|
438
|
+
return observed.snapshot;
|
|
439
|
+
return continuePendingMutation(pending, observed.snapshot);
|
|
440
|
+
}
|
|
441
|
+
if (attempt + 1 < CONCURRENT_IDENTICAL_OBSERVATION_ATTEMPTS) {
|
|
442
|
+
await delay(CONCURRENT_IDENTICAL_OBSERVATION_DELAY_MS);
|
|
443
|
+
}
|
|
444
|
+
}
|
|
445
|
+
throw new KiokukoError('SECURITY_REJECTION', 'Refusing to plan from a hard-linked agent target', { target: filePath });
|
|
446
|
+
}
|
|
447
|
+
async function readRetriedAgentPlan(filePath, initial, intendedContent, intendedMode, containmentRoot, parentIdentity, forbiddenBindingIdentity, initialFinalCandidate) {
|
|
448
|
+
let finalCandidate = initialFinalCandidate;
|
|
449
|
+
let linkedCandidate;
|
|
450
|
+
let lastWasLinked = false;
|
|
451
|
+
for (let attempt = 0; attempt < CONCURRENT_IDENTICAL_OBSERVATION_ATTEMPTS; attempt += 1) {
|
|
452
|
+
const observed = await readObservedTarget(filePath, containmentRoot, parentIdentity);
|
|
453
|
+
if (observed === undefined) {
|
|
454
|
+
lastWasLinked = false;
|
|
455
|
+
if (linkedCandidate !== undefined || finalCandidate !== undefined) {
|
|
456
|
+
throw new KiokukoError('CONFLICT', 'Concurrent agent target disappeared while settling', {
|
|
457
|
+
target: filePath,
|
|
458
|
+
});
|
|
459
|
+
}
|
|
460
|
+
const pending = await readPendingAtomicMutation(filePath, parentIdentity, containmentRoot);
|
|
461
|
+
if (initial === undefined) {
|
|
462
|
+
if (pending !== undefined) {
|
|
463
|
+
throw new KiokukoError('CONFLICT', 'An unexpected atomic quarantine appeared for an initially absent agent target', { target: filePath });
|
|
464
|
+
}
|
|
465
|
+
return undefined;
|
|
466
|
+
}
|
|
467
|
+
if (pending === undefined
|
|
468
|
+
|| pending.kind !== 'previous'
|
|
469
|
+
|| !sameRegularFileSnapshot(pending.snapshot, initial)) {
|
|
470
|
+
throw new KiokukoError('CONFLICT', 'Agent target disappeared outside its exact atomic quarantine', { target: filePath });
|
|
471
|
+
}
|
|
472
|
+
}
|
|
473
|
+
else {
|
|
474
|
+
if (forbiddenBindingIdentity !== undefined
|
|
475
|
+
&& sameFileIdentity(observed.snapshot.identity, forbiddenBindingIdentity)) {
|
|
476
|
+
throw new KiokukoError('CONFLICT', 'agentFile resolves to the repository binding file');
|
|
477
|
+
}
|
|
478
|
+
if (linkedCandidate !== undefined
|
|
479
|
+
&& !sameRegularFileSnapshot(linkedCandidate, observed.snapshot)) {
|
|
480
|
+
throw new KiokukoError('CONFLICT', 'Concurrent agent target changed while settling', {
|
|
481
|
+
target: filePath,
|
|
482
|
+
});
|
|
483
|
+
}
|
|
484
|
+
const isInitial = initial !== undefined
|
|
485
|
+
&& sameRegularFileSnapshot(observed.snapshot, initial);
|
|
486
|
+
const isIntendedFinal = intendedContent !== undefined
|
|
487
|
+
&& observed.snapshot.content === intendedContent
|
|
488
|
+
&& observed.snapshot.mode === intendedMode
|
|
489
|
+
&& (initial === undefined
|
|
490
|
+
|| !sameFileIdentity(observed.snapshot.identity, initial.identity));
|
|
491
|
+
if (finalCandidate !== undefined
|
|
492
|
+
&& !sameRegularFileSnapshot(finalCandidate, observed.snapshot)) {
|
|
493
|
+
throw new KiokukoError('CONFLICT', 'Concurrent agent result changed while settling', {
|
|
494
|
+
target: filePath,
|
|
495
|
+
});
|
|
496
|
+
}
|
|
497
|
+
if (!isInitial && !isIntendedFinal) {
|
|
498
|
+
throw new KiokukoError('CONFLICT', 'Concurrent agent target is neither the planned original nor the intended final state', { target: filePath });
|
|
499
|
+
}
|
|
500
|
+
if (isIntendedFinal)
|
|
501
|
+
finalCandidate = observed.snapshot;
|
|
502
|
+
lastWasLinked = observed.linkCount !== 1n;
|
|
503
|
+
if (lastWasLinked) {
|
|
504
|
+
linkedCandidate = observed.snapshot;
|
|
505
|
+
}
|
|
506
|
+
else {
|
|
507
|
+
const pending = await readPendingAtomicMutation(filePath, parentIdentity, containmentRoot);
|
|
508
|
+
if (pending === undefined)
|
|
509
|
+
return observed.snapshot;
|
|
510
|
+
if (initial === undefined
|
|
511
|
+
|| pending.kind !== 'previous'
|
|
512
|
+
|| !sameRegularFileSnapshot(pending.snapshot, initial)) {
|
|
513
|
+
throw new KiokukoError('CONFLICT', 'Concurrent agent target retained an incompatible atomic artifact', { target: filePath });
|
|
514
|
+
}
|
|
515
|
+
}
|
|
516
|
+
}
|
|
517
|
+
if (attempt + 1 < CONCURRENT_IDENTICAL_OBSERVATION_ATTEMPTS) {
|
|
518
|
+
await delay(CONCURRENT_IDENTICAL_OBSERVATION_DELAY_MS);
|
|
519
|
+
}
|
|
520
|
+
}
|
|
521
|
+
if (lastWasLinked) {
|
|
522
|
+
throw new KiokukoError('SECURITY_REJECTION', 'Refusing to plan from a hard-linked concurrent agent target', { target: filePath });
|
|
523
|
+
}
|
|
524
|
+
throw new KiokukoError('CONFLICT', 'Concurrent agent mutation did not settle', {
|
|
525
|
+
target: filePath,
|
|
526
|
+
});
|
|
527
|
+
}
|
|
528
|
+
async function useRepositoryAttempt(options = {}, dependencyOverrides = {}, allowConcurrentConvergence, allowConcurrentAgentConvergence, retryParents) {
|
|
529
|
+
const dependencies = {
|
|
530
|
+
atomicWriteTextIfUnchanged: dependencyOverrides.atomicWriteTextIfUnchanged ?? atomicWriteTextIfUnchanged,
|
|
531
|
+
unlinkRegularFileIfUnchanged: dependencyOverrides.unlinkRegularFileIfUnchanged ?? unlinkRegularFileIfUnchanged,
|
|
532
|
+
registerRepositoryAndLocation: dependencyOverrides.registerRepositoryAndLocation ?? registerRepositoryAndLocation,
|
|
533
|
+
openConnection: dependencyOverrides.openConnection ?? openConnection,
|
|
534
|
+
};
|
|
46
535
|
const rootOptions = {};
|
|
47
536
|
if (options.cwd !== undefined)
|
|
48
537
|
rootOptions.cwd = options.cwd;
|
|
@@ -52,49 +541,139 @@ export async function useRepository(options = {}) {
|
|
|
52
541
|
rootOptions.allowDirectory = options.allowDirectory;
|
|
53
542
|
const detected = detectRepositoryRoot(rootOptions);
|
|
54
543
|
const repositoryRoot = detected.root;
|
|
544
|
+
if (retryParents !== undefined && repositoryRoot !== retryParents.repositoryRoot) {
|
|
545
|
+
throw new KiokukoError('CONFLICT', 'Repository root changed during concurrent binding convergence');
|
|
546
|
+
}
|
|
55
547
|
const bindingFile = path.join(repositoryRoot, '.kiokuko.json');
|
|
56
|
-
const
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
throw new KiokukoError('CONFLICT', '
|
|
548
|
+
const bindingParentIdentity = await existingParentIdentity(bindingFile);
|
|
549
|
+
if (retryParents !== undefined
|
|
550
|
+
&& !sameFileIdentity(bindingParentIdentity, retryParents.bindingParentIdentity)) {
|
|
551
|
+
throw new KiokukoError('CONFLICT', 'Repository root changed during concurrent binding convergence');
|
|
552
|
+
}
|
|
553
|
+
const bindingSnapshot = await readSettledBindingSnapshot(bindingFile, repositoryRoot, bindingParentIdentity);
|
|
554
|
+
const existingBinding = parseBindingSnapshot(bindingSnapshot);
|
|
555
|
+
if (existingBinding !== undefined && existingBinding.templateVersion > AGENT_TEMPLATE_VERSION) {
|
|
556
|
+
throw new KiokukoError('VALIDATION_ERROR', `Project binding templateVersion ${existingBinding.templateVersion} is newer than supported version ${AGENT_TEMPLATE_VERSION}`);
|
|
557
|
+
}
|
|
558
|
+
if (options.forceRebind && existingBinding === undefined) {
|
|
559
|
+
throw new KiokukoError('CONFLICT', 'Cannot rebind a repository without an existing project binding');
|
|
560
|
+
}
|
|
561
|
+
if (existingBinding && !options.forceRebind) {
|
|
562
|
+
if (options.repositoryId !== undefined && existingBinding.repositoryId !== options.repositoryId) {
|
|
563
|
+
throw new KiokukoError('CONFLICT', 'Existing binding uses another repository ID; pass --force-rebind to change it');
|
|
564
|
+
}
|
|
565
|
+
if (options.workspace !== undefined && existingBinding.workspace !== options.workspace) {
|
|
566
|
+
throw new KiokukoError('CONFLICT', 'Existing binding uses another workspace; pass --force-rebind to change it');
|
|
567
|
+
}
|
|
60
568
|
}
|
|
61
569
|
const requestedAgentFile = options.agentFile ?? existingBinding?.agentFile ?? 'AGENTS.md';
|
|
62
|
-
const agentFile = ensureChildPath(repositoryRoot, requestedAgentFile);
|
|
63
|
-
const existingAgent = options.noAgentFile ? undefined : await readRegularFile(agentFile);
|
|
64
570
|
const identityOptions = { repositoryRoot };
|
|
65
571
|
const remote = readGitOrigin(repositoryRoot);
|
|
66
572
|
if (remote !== undefined)
|
|
67
573
|
identityOptions.remoteUrl = remote;
|
|
68
|
-
if (options.
|
|
69
|
-
|
|
70
|
-
|
|
574
|
+
if (existingBinding && options.forceRebind) {
|
|
575
|
+
if (options.repositoryId === undefined && options.workspace === undefined) {
|
|
576
|
+
throw new KiokukoError('CONFLICT', 'Forced rebind requires a different target identity');
|
|
577
|
+
}
|
|
578
|
+
identityOptions.repositoryId = options.repositoryId ?? `repo_${randomUUID()}`;
|
|
579
|
+
if (options.workspace !== undefined)
|
|
580
|
+
identityOptions.workspace = options.workspace;
|
|
581
|
+
}
|
|
582
|
+
else if (existingBinding) {
|
|
71
583
|
identityOptions.existingBinding = {
|
|
72
584
|
repositoryId: existingBinding.repositoryId,
|
|
73
585
|
workspace: existingBinding.workspace,
|
|
74
586
|
};
|
|
75
587
|
}
|
|
76
|
-
|
|
77
|
-
|
|
588
|
+
else {
|
|
589
|
+
if (options.repositoryId !== undefined)
|
|
590
|
+
identityOptions.repositoryId = options.repositoryId;
|
|
591
|
+
if (options.workspace !== undefined)
|
|
592
|
+
identityOptions.workspace = options.workspace;
|
|
593
|
+
}
|
|
78
594
|
const identity = createRepositoryIdentity(identityOptions);
|
|
79
|
-
if (existingBinding && options.
|
|
80
|
-
|
|
595
|
+
if (existingBinding && options.forceRebind
|
|
596
|
+
&& (identity.repositoryId === existingBinding.repositoryId
|
|
597
|
+
|| identity.workspace === existingBinding.workspace)) {
|
|
598
|
+
throw new KiokukoError('CONFLICT', 'Forced rebind requires both a different repository ID and a different workspace');
|
|
81
599
|
}
|
|
82
|
-
|
|
600
|
+
// Validate the exact serialized binding before resolving, reading, initializing,
|
|
601
|
+
// or writing anything. Absolute and non-canonical lexical paths cannot persist.
|
|
602
|
+
const nextBinding = parseProjectConfig({
|
|
83
603
|
schemaVersion: 1,
|
|
84
604
|
repositoryId: identity.repositoryId,
|
|
85
605
|
workspace: identity.workspace,
|
|
86
606
|
agentFile: requestedAgentFile,
|
|
87
607
|
templateVersion: AGENT_TEMPLATE_VERSION,
|
|
608
|
+
});
|
|
609
|
+
const agentFile = ensureChildPath(repositoryRoot, nextBinding.agentFile);
|
|
610
|
+
const agentParentIdentity = await existingParentIdentity(agentFile);
|
|
611
|
+
if (retryParents !== undefined
|
|
612
|
+
&& !sameFileIdentity(agentParentIdentity, retryParents.agentParentIdentity)) {
|
|
613
|
+
throw new KiokukoError('CONFLICT', 'agentFile parent changed during concurrent binding convergence');
|
|
614
|
+
}
|
|
615
|
+
const agentTemplateValues = {
|
|
616
|
+
repositoryId: identity.repositoryId,
|
|
617
|
+
workspace: identity.workspace,
|
|
618
|
+
cliCommand: preferredCliCommand(),
|
|
619
|
+
templateVersion: AGENT_TEMPLATE_VERSION,
|
|
88
620
|
};
|
|
621
|
+
const retryRendered = retryParents === undefined || options.noAgentFile
|
|
622
|
+
? undefined
|
|
623
|
+
: renderAgentFile(retryParents.agentSnapshot?.content, agentTemplateValues);
|
|
624
|
+
const plannedAgent = retryParents === undefined
|
|
625
|
+
? await readSettledAgentPlan(agentFile, repositoryRoot, agentParentIdentity, bindingSnapshot?.identity, options.noAgentFile
|
|
626
|
+
? undefined
|
|
627
|
+
: (original) => ({
|
|
628
|
+
content: renderAgentFile(original.content, agentTemplateValues).content,
|
|
629
|
+
mode: original.mode,
|
|
630
|
+
}))
|
|
631
|
+
: await readRetriedAgentPlan(agentFile, retryParents.agentSnapshot, retryRendered?.action === 'unchanged' ? undefined : retryRendered?.content, retryParents.agentSnapshot?.mode ?? 0o644, repositoryRoot, agentParentIdentity, bindingSnapshot?.identity);
|
|
632
|
+
assertSupportedManagedTemplate(plannedAgent, 'Prospective agentFile');
|
|
633
|
+
const existingAgent = options.noAgentFile ? undefined : plannedAgent;
|
|
634
|
+
if (options.noAgentFile && plannedAgent !== undefined) {
|
|
635
|
+
const plannedManagedBlock = removeManagedBlock(plannedAgent.content);
|
|
636
|
+
if (plannedManagedBlock.action !== 'absent'
|
|
637
|
+
&& renderAgentFile(plannedAgent.content, agentTemplateValues).action !== 'unchanged') {
|
|
638
|
+
throw new KiokukoError('CONFLICT', 'Cannot use --no-agent-file while the prospective agentFile contains a stale managed block');
|
|
639
|
+
}
|
|
640
|
+
}
|
|
641
|
+
if (bindingSnapshot !== undefined
|
|
642
|
+
&& plannedAgent !== undefined
|
|
643
|
+
&& bindingSnapshot.identity.device === plannedAgent.identity.device
|
|
644
|
+
&& bindingSnapshot.identity.inode === plannedAgent.identity.inode) {
|
|
645
|
+
throw new KiokukoError('CONFLICT', 'agentFile resolves to the repository binding file');
|
|
646
|
+
}
|
|
647
|
+
const previousAgentFile = existingBinding !== undefined
|
|
648
|
+
&& existingBinding.agentFile !== nextBinding.agentFile
|
|
649
|
+
? ensureChildPath(repositoryRoot, existingBinding.agentFile)
|
|
650
|
+
: undefined;
|
|
651
|
+
const previousAgentParentIdentity = previousAgentFile === undefined
|
|
652
|
+
? bindingParentIdentity
|
|
653
|
+
: await existingParentIdentity(previousAgentFile);
|
|
654
|
+
const previousAgent = previousAgentFile === undefined
|
|
655
|
+
? undefined
|
|
656
|
+
: await readStrictSettledTarget(previousAgentFile, repositoryRoot, previousAgentParentIdentity, 'Previous agentFile');
|
|
657
|
+
assertSupportedManagedTemplate(previousAgent, 'Previous agentFile');
|
|
658
|
+
if (bindingSnapshot !== undefined
|
|
659
|
+
&& previousAgent !== undefined
|
|
660
|
+
&& bindingSnapshot.identity.device === previousAgent.identity.device
|
|
661
|
+
&& bindingSnapshot.identity.inode === previousAgent.identity.inode) {
|
|
662
|
+
throw new KiokukoError('CONFLICT', 'Previous agentFile resolves to the repository binding file');
|
|
663
|
+
}
|
|
664
|
+
if (previousAgent !== undefined
|
|
665
|
+
&& plannedAgent !== undefined
|
|
666
|
+
&& previousAgent.identity.device === plannedAgent.identity.device
|
|
667
|
+
&& previousAgent.identity.inode === plannedAgent.identity.inode) {
|
|
668
|
+
throw new KiokukoError('CONFLICT', 'Old and new agentFile paths resolve to the same regular file');
|
|
669
|
+
}
|
|
670
|
+
const previousAgentRemoval = previousAgent === undefined
|
|
671
|
+
? undefined
|
|
672
|
+
: removeManagedBlock(previousAgent.content);
|
|
89
673
|
const nextBindingText = bindingText(nextBinding);
|
|
90
674
|
const rendered = options.noAgentFile
|
|
91
675
|
? undefined
|
|
92
|
-
: renderAgentFile(existingAgent?.content,
|
|
93
|
-
repositoryId: identity.repositoryId,
|
|
94
|
-
workspace: identity.workspace,
|
|
95
|
-
cliCommand: preferredCliCommand(),
|
|
96
|
-
templateVersion: AGENT_TEMPLATE_VERSION,
|
|
97
|
-
});
|
|
676
|
+
: renderAgentFile(existingAgent?.content, agentTemplateValues);
|
|
98
677
|
const databasePath = options.databasePath ?? getGlobalDatabasePath();
|
|
99
678
|
const result = {
|
|
100
679
|
repositoryRoot,
|
|
@@ -104,7 +683,7 @@ export async function useRepository(options = {}) {
|
|
|
104
683
|
bindingFile,
|
|
105
684
|
agentFile: options.noAgentFile ? null : agentFile,
|
|
106
685
|
agentFileAction: options.noAgentFile ? 'skipped' : rendered?.action ?? 'unchanged',
|
|
107
|
-
bindingAction: options.dryRun ? 'planned' : bindingAction(
|
|
686
|
+
bindingAction: options.dryRun ? 'planned' : bindingAction(bindingSnapshot?.content, nextBindingText),
|
|
108
687
|
dryRun: options.dryRun ?? false,
|
|
109
688
|
templateVersion: AGENT_TEMPLATE_VERSION,
|
|
110
689
|
};
|
|
@@ -114,11 +693,199 @@ export async function useRepository(options = {}) {
|
|
|
114
693
|
if (options.migrationsDirectory !== undefined)
|
|
115
694
|
initOptions.migrationsDirectory = options.migrationsDirectory;
|
|
116
695
|
await initializeDatabase(initOptions);
|
|
117
|
-
const
|
|
118
|
-
let retryBinding;
|
|
696
|
+
const installed = [];
|
|
119
697
|
try {
|
|
698
|
+
let resolvedBinding = bindingSnapshot;
|
|
699
|
+
if (result.bindingAction !== 'unchanged') {
|
|
700
|
+
try {
|
|
701
|
+
const resolution = bindingSnapshot === undefined
|
|
702
|
+
? await writeOrConvergeIdentical(dependencies, bindingFile, nextBindingText, bindingSnapshot, 0o644, repositoryRoot, bindingParentIdentity)
|
|
703
|
+
: await writeStrict(dependencies, bindingFile, nextBindingText, bindingSnapshot, bindingSnapshot.mode, repositoryRoot, bindingParentIdentity);
|
|
704
|
+
resolvedBinding = resolution.snapshot;
|
|
705
|
+
if (resolution.owned) {
|
|
706
|
+
installed.push({
|
|
707
|
+
path: bindingFile,
|
|
708
|
+
original: bindingSnapshot,
|
|
709
|
+
installed: resolution.snapshot,
|
|
710
|
+
containmentRoot: repositoryRoot,
|
|
711
|
+
parentIdentity: bindingParentIdentity,
|
|
712
|
+
});
|
|
713
|
+
}
|
|
714
|
+
assertAtomicCleanupComplete(resolution);
|
|
715
|
+
}
|
|
716
|
+
catch (error) {
|
|
717
|
+
if (error instanceof AtomicCommittedMutationError) {
|
|
718
|
+
installed.push({
|
|
719
|
+
path: bindingFile,
|
|
720
|
+
original: bindingSnapshot,
|
|
721
|
+
installed: error.outcome.installed,
|
|
722
|
+
containmentRoot: repositoryRoot,
|
|
723
|
+
parentIdentity: bindingParentIdentity,
|
|
724
|
+
});
|
|
725
|
+
}
|
|
726
|
+
else if (error instanceof AtomicCommittedUnlinkError && bindingSnapshot !== undefined) {
|
|
727
|
+
installed.push({
|
|
728
|
+
path: bindingFile,
|
|
729
|
+
original: bindingSnapshot,
|
|
730
|
+
installed: undefined,
|
|
731
|
+
containmentRoot: repositoryRoot,
|
|
732
|
+
parentIdentity: bindingParentIdentity,
|
|
733
|
+
});
|
|
734
|
+
}
|
|
735
|
+
if (allowConcurrentConvergence
|
|
736
|
+
&& isTargetConflict(error, bindingFile)
|
|
737
|
+
&& bindingSnapshot === undefined
|
|
738
|
+
&& existingBinding === undefined
|
|
739
|
+
&& options.repositoryId === undefined
|
|
740
|
+
&& options.workspace === undefined) {
|
|
741
|
+
throw new ConcurrentUseBinding(await readConcurrentBinding(bindingFile, repositoryRoot, requestedAgentFile, bindingParentIdentity));
|
|
742
|
+
}
|
|
743
|
+
throw error;
|
|
744
|
+
}
|
|
745
|
+
}
|
|
746
|
+
else if (bindingSnapshot !== undefined) {
|
|
747
|
+
await assertFileExpectation(bindingFile, expectation(bindingSnapshot, repositoryRoot, bindingParentIdentity));
|
|
748
|
+
resolvedBinding = bindingSnapshot;
|
|
749
|
+
}
|
|
750
|
+
let resolvedAgent = existingAgent;
|
|
751
|
+
if (rendered && rendered.action !== 'unchanged') {
|
|
752
|
+
try {
|
|
753
|
+
const resolution = existingBinding === undefined || allowConcurrentAgentConvergence
|
|
754
|
+
? await writeOrConvergeIdentical(dependencies, agentFile, rendered.content, existingAgent, existingAgent?.mode ?? 0o644, repositoryRoot, agentParentIdentity)
|
|
755
|
+
: await writeStrict(dependencies, agentFile, rendered.content, existingAgent, existingAgent?.mode ?? 0o644, repositoryRoot, agentParentIdentity);
|
|
756
|
+
resolvedAgent = resolution.snapshot;
|
|
757
|
+
if (resolution.owned) {
|
|
758
|
+
installed.push({
|
|
759
|
+
path: agentFile,
|
|
760
|
+
original: existingAgent,
|
|
761
|
+
installed: resolution.snapshot,
|
|
762
|
+
containmentRoot: repositoryRoot,
|
|
763
|
+
parentIdentity: agentParentIdentity,
|
|
764
|
+
});
|
|
765
|
+
}
|
|
766
|
+
assertAtomicCleanupComplete(resolution);
|
|
767
|
+
}
|
|
768
|
+
catch (error) {
|
|
769
|
+
if (error instanceof AtomicCommittedMutationError) {
|
|
770
|
+
installed.push({
|
|
771
|
+
path: agentFile,
|
|
772
|
+
original: existingAgent,
|
|
773
|
+
installed: error.outcome.installed,
|
|
774
|
+
containmentRoot: repositoryRoot,
|
|
775
|
+
parentIdentity: agentParentIdentity,
|
|
776
|
+
});
|
|
777
|
+
}
|
|
778
|
+
else if (error instanceof AtomicCommittedUnlinkError && existingAgent !== undefined) {
|
|
779
|
+
installed.push({
|
|
780
|
+
path: agentFile,
|
|
781
|
+
original: existingAgent,
|
|
782
|
+
installed: undefined,
|
|
783
|
+
containmentRoot: repositoryRoot,
|
|
784
|
+
parentIdentity: agentParentIdentity,
|
|
785
|
+
});
|
|
786
|
+
}
|
|
787
|
+
throw error;
|
|
788
|
+
}
|
|
789
|
+
}
|
|
790
|
+
else if (rendered && existingAgent !== undefined) {
|
|
791
|
+
await assertFileExpectation(agentFile, expectation(existingAgent, repositoryRoot, agentParentIdentity));
|
|
792
|
+
resolvedAgent = existingAgent;
|
|
793
|
+
}
|
|
794
|
+
let resolvedPreviousAgent = previousAgent;
|
|
795
|
+
if (previousAgentFile !== undefined
|
|
796
|
+
&& previousAgent !== undefined
|
|
797
|
+
&& previousAgentRemoval?.action === 'updated'
|
|
798
|
+
&& previousAgentRemoval.content !== undefined) {
|
|
799
|
+
try {
|
|
800
|
+
const outcome = await dependencies.atomicWriteTextIfUnchanged(previousAgentFile, previousAgentRemoval.content, expectation(previousAgent, repositoryRoot, previousAgentParentIdentity), previousAgent.mode);
|
|
801
|
+
resolvedPreviousAgent = outcome.installed;
|
|
802
|
+
installed.push({
|
|
803
|
+
path: previousAgentFile,
|
|
804
|
+
original: previousAgent,
|
|
805
|
+
installed: outcome.installed,
|
|
806
|
+
containmentRoot: repositoryRoot,
|
|
807
|
+
parentIdentity: previousAgentParentIdentity,
|
|
808
|
+
});
|
|
809
|
+
assertAtomicCleanupComplete(outcome);
|
|
810
|
+
}
|
|
811
|
+
catch (error) {
|
|
812
|
+
if (error instanceof AtomicCommittedMutationError) {
|
|
813
|
+
installed.push({
|
|
814
|
+
path: previousAgentFile,
|
|
815
|
+
original: previousAgent,
|
|
816
|
+
installed: error.outcome.installed,
|
|
817
|
+
containmentRoot: repositoryRoot,
|
|
818
|
+
parentIdentity: previousAgentParentIdentity,
|
|
819
|
+
});
|
|
820
|
+
}
|
|
821
|
+
else if (error instanceof AtomicCommittedUnlinkError) {
|
|
822
|
+
installed.push({
|
|
823
|
+
path: previousAgentFile,
|
|
824
|
+
original: previousAgent,
|
|
825
|
+
installed: undefined,
|
|
826
|
+
containmentRoot: repositoryRoot,
|
|
827
|
+
parentIdentity: previousAgentParentIdentity,
|
|
828
|
+
});
|
|
829
|
+
}
|
|
830
|
+
throw error;
|
|
831
|
+
}
|
|
832
|
+
}
|
|
833
|
+
else if (previousAgentFile !== undefined
|
|
834
|
+
&& previousAgent !== undefined
|
|
835
|
+
&& previousAgentRemoval?.action === 'deleted') {
|
|
836
|
+
try {
|
|
837
|
+
const outcome = await dependencies.unlinkRegularFileIfUnchanged(previousAgentFile, expectation(previousAgent, repositoryRoot, previousAgentParentIdentity));
|
|
838
|
+
resolvedPreviousAgent = undefined;
|
|
839
|
+
installed.push({
|
|
840
|
+
path: previousAgentFile,
|
|
841
|
+
original: previousAgent,
|
|
842
|
+
installed: undefined,
|
|
843
|
+
containmentRoot: repositoryRoot,
|
|
844
|
+
parentIdentity: previousAgentParentIdentity,
|
|
845
|
+
});
|
|
846
|
+
assertAtomicCleanupComplete(outcome);
|
|
847
|
+
}
|
|
848
|
+
catch (error) {
|
|
849
|
+
if (error instanceof AtomicCommittedUnlinkError) {
|
|
850
|
+
installed.push({
|
|
851
|
+
path: previousAgentFile,
|
|
852
|
+
original: previousAgent,
|
|
853
|
+
installed: undefined,
|
|
854
|
+
containmentRoot: repositoryRoot,
|
|
855
|
+
parentIdentity: previousAgentParentIdentity,
|
|
856
|
+
});
|
|
857
|
+
}
|
|
858
|
+
throw error;
|
|
859
|
+
}
|
|
860
|
+
}
|
|
861
|
+
const finalBinding = await readSettledBindingSnapshot(bindingFile, repositoryRoot, bindingParentIdentity);
|
|
862
|
+
if (resolvedBinding === undefined
|
|
863
|
+
|| finalBinding === undefined
|
|
864
|
+
|| !sameRegularFileSnapshot(finalBinding, resolvedBinding)) {
|
|
865
|
+
throw new KiokukoError('CONFLICT', 'Repository binding changed before registration', {
|
|
866
|
+
target: bindingFile,
|
|
867
|
+
});
|
|
868
|
+
}
|
|
869
|
+
if (!options.noAgentFile) {
|
|
870
|
+
await assertFileExpectation(agentFile, expectation(resolvedAgent, repositoryRoot, agentParentIdentity));
|
|
871
|
+
}
|
|
872
|
+
else {
|
|
873
|
+
await assertFileExpectation(agentFile, expectation(plannedAgent, repositoryRoot, agentParentIdentity));
|
|
874
|
+
}
|
|
875
|
+
if (previousAgentFile !== undefined) {
|
|
876
|
+
const finalPreviousAgent = await readStrictSettledTarget(previousAgentFile, repositoryRoot, previousAgentParentIdentity, 'Previous agentFile');
|
|
877
|
+
if ((resolvedPreviousAgent === undefined) !== (finalPreviousAgent === undefined)
|
|
878
|
+
|| (resolvedPreviousAgent !== undefined
|
|
879
|
+
&& finalPreviousAgent !== undefined
|
|
880
|
+
&& !sameRegularFileSnapshot(resolvedPreviousAgent, finalPreviousAgent))) {
|
|
881
|
+
throw new KiokukoError('CONFLICT', 'Previous agentFile changed before registration', {
|
|
882
|
+
target: previousAgentFile,
|
|
883
|
+
});
|
|
884
|
+
}
|
|
885
|
+
}
|
|
886
|
+
const database = dependencies.openConnection(databasePath);
|
|
120
887
|
try {
|
|
121
|
-
registerRepositoryAndLocation(database, {
|
|
888
|
+
dependencies.registerRepositoryAndLocation(database, {
|
|
122
889
|
repositoryId: identity.repositoryId,
|
|
123
890
|
workspace: identity.workspace,
|
|
124
891
|
displayName: identity.displayName,
|
|
@@ -126,51 +893,62 @@ export async function useRepository(options = {}) {
|
|
|
126
893
|
remoteFingerprint: identity.remoteFingerprint,
|
|
127
894
|
bindingSchemaVersion: 1,
|
|
128
895
|
agentTemplateVersion: AGENT_TEMPLATE_VERSION,
|
|
896
|
+
...(options.forceRebind && existingBinding !== undefined
|
|
897
|
+
? {
|
|
898
|
+
rebindFrom: {
|
|
899
|
+
repositoryId: existingBinding.repositoryId,
|
|
900
|
+
workspace: existingBinding.workspace,
|
|
901
|
+
},
|
|
902
|
+
}
|
|
903
|
+
: {}),
|
|
129
904
|
});
|
|
130
905
|
}
|
|
131
|
-
catch (
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
906
|
+
catch (registrationError) {
|
|
907
|
+
try {
|
|
908
|
+
database.close();
|
|
909
|
+
}
|
|
910
|
+
catch (closeError) {
|
|
911
|
+
if (registrationError instanceof TransactionCommitUncertainError) {
|
|
912
|
+
throw new UncertainRegistrationCloseError(registrationError, closeError);
|
|
913
|
+
}
|
|
914
|
+
throw new AggregateError([registrationError, closeError], 'Repository registration failed and closing the database connection also failed');
|
|
915
|
+
}
|
|
916
|
+
throw registrationError;
|
|
917
|
+
}
|
|
918
|
+
try {
|
|
919
|
+
database.close();
|
|
920
|
+
}
|
|
921
|
+
catch (closeError) {
|
|
922
|
+
throw new CommittedRegistrationCloseError(closeError);
|
|
141
923
|
}
|
|
142
|
-
}
|
|
143
|
-
finally {
|
|
144
|
-
database.close();
|
|
145
|
-
}
|
|
146
|
-
if (retryBinding) {
|
|
147
|
-
return useRepository({ ...options, repositoryId: retryBinding.repositoryId, workspace: retryBinding.workspace });
|
|
148
|
-
}
|
|
149
|
-
const originalBinding = existingBindingText;
|
|
150
|
-
const originalAgent = existingAgent?.content;
|
|
151
|
-
try {
|
|
152
|
-
if (result.bindingAction !== 'unchanged')
|
|
153
|
-
await atomicWriteText(bindingFile, nextBindingText, 0o644);
|
|
154
|
-
if (rendered && rendered.action !== 'unchanged')
|
|
155
|
-
await atomicWriteText(agentFile, rendered.content, existingAgent?.mode ?? 0o644);
|
|
156
924
|
}
|
|
157
925
|
catch (error) {
|
|
158
|
-
if (
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
if (options.noAgentFile) {
|
|
163
|
-
// No agent file was requested, so there is nothing to restore.
|
|
926
|
+
if (error instanceof CommittedRegistrationCloseError
|
|
927
|
+
|| error instanceof TransactionCommitUncertainError
|
|
928
|
+
|| error instanceof UncertainRegistrationCloseError) {
|
|
929
|
+
throw error;
|
|
164
930
|
}
|
|
165
|
-
|
|
166
|
-
|
|
931
|
+
const restorationFailures = await restoreInstalledWrites(installed, dependencies);
|
|
932
|
+
if (restorationFailures.length > 0) {
|
|
933
|
+
throw new AggregateError([error, ...restorationFailures], 'Repository setup failed and file restoration also failed');
|
|
167
934
|
}
|
|
168
|
-
|
|
169
|
-
|
|
935
|
+
if (error instanceof ConcurrentUseBinding) {
|
|
936
|
+
return useRepositoryAttempt({
|
|
937
|
+
...options,
|
|
938
|
+
repositoryId: error.binding.repositoryId,
|
|
939
|
+
workspace: error.binding.workspace,
|
|
940
|
+
}, dependencyOverrides, false, true, {
|
|
941
|
+
repositoryRoot,
|
|
942
|
+
bindingParentIdentity,
|
|
943
|
+
agentParentIdentity,
|
|
944
|
+
agentSnapshot: plannedAgent,
|
|
945
|
+
});
|
|
170
946
|
}
|
|
171
947
|
throw error;
|
|
172
948
|
}
|
|
173
949
|
return result;
|
|
174
950
|
}
|
|
175
|
-
export
|
|
951
|
+
export async function useRepository(options = {}, dependencyOverrides = {}) {
|
|
952
|
+
return useRepositoryAttempt(options, dependencyOverrides, true, false);
|
|
953
|
+
}
|
|
176
954
|
//# sourceMappingURL=use.js.map
|