@askdkc/kiokuko 0.1.17 → 0.1.20
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/cli.d.ts +2 -0
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +560 -150
- 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 +71 -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 +37 -8
- package/dist/commands/setup.d.ts.map +1 -1
- package/dist/commands/setup.js +448 -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 +7 -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 +758 -28
- package/dist/db/upgrade-backup.js.map +1 -1
- package/dist/errors.d.ts +4 -0
- package/dist/errors.d.ts.map +1 -1
- package/dist/errors.js +29 -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 +199 -115
- 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 +540 -36
- 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 +4 -1
- package/dist/setup/claude-config.d.ts.map +1 -1
- package/dist/setup/claude-config.js +62 -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 +4 -1
- package/dist/setup/hermes-config.d.ts.map +1 -1
- package/dist/setup/hermes-config.js +71 -17
- 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/mcp-conflict.d.ts +4 -0
- package/dist/setup/mcp-conflict.d.ts.map +1 -0
- package/dist/setup/mcp-conflict.js +15 -0
- package/dist/setup/mcp-conflict.js.map +1 -0
- package/dist/setup/opencode-config.d.ts +4 -1
- package/dist/setup/opencode-config.d.ts.map +1 -1
- package/dist/setup/opencode-config.js +65 -5
- package/dist/setup/opencode-config.js.map +1 -1
- package/dist/setup/render.d.ts +4 -1
- package/dist/setup/render.d.ts.map +1 -1
- package/dist/setup/render.js +168 -18
- 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 +18 -0
- package/dist/setup/strict-toml.d.ts.map +1 -0
- package/dist/setup/strict-toml.js +491 -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 +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/setup.js
CHANGED
|
@@ -1,21 +1,26 @@
|
|
|
1
|
-
import { access, unlink } from 'node:fs/promises';
|
|
2
1
|
import path from 'node:path';
|
|
2
|
+
import { mkdir, rmdir } from 'node:fs/promises';
|
|
3
3
|
import { createInterface } from 'node:readline/promises';
|
|
4
4
|
import { stdin, stdout } from 'node:process';
|
|
5
|
-
import {
|
|
6
|
-
import { getClaudeInstructionsPath, getClaudeMcpConfigPath, getClaudeSkillsDirectory, getCodexConfigPath, getCodexInstructionsPath, getCodexSkillsDirectory, getGlobalDatabasePath,
|
|
5
|
+
import { atomicWriteTextIfUnchanged, assertAtomicCleanupComplete, AtomicCommittedMutationError, AtomicCommittedUnlinkError, assertFileExpectation, readDirectoryIdentity, readRegularFile, unlinkRegularFileIfUnchanged, } from '../agent-file/atomic-write.js';
|
|
6
|
+
import { getClaudeInstructionsPath, getClaudeMcpConfigPath, getClaudeSkillsDirectory, getCodexConfigPath, getCodexInstructionsPath, getCodexSkillsDirectory, getGlobalDatabasePath, getLegacyClaudePromptHookSettingsPath, getLegacyOpenCodeLoopGuardPath, getOpenCodeConfigDirectory, getOpenCodeInstructionsPath, getOpenCodeSkillsDirectory, resolveHermesProfilePaths, } from '../config/paths.js';
|
|
7
7
|
import { initializeDatabase } from './init.js';
|
|
8
8
|
import { openConnection } from '../db/connection.js';
|
|
9
9
|
import { ensureGlobalWorkspace } from '../memory/workspaces.js';
|
|
10
10
|
import { KiokukoError } from '../errors.js';
|
|
11
|
+
import { isSkillDiscoveryMode, normalizeSkillDiscoveryMode, SKILL_DISCOVERY_ENV } from '../skills/config.js';
|
|
11
12
|
import { renderOpenCodeConfig } from '../setup/opencode-config.js';
|
|
12
|
-
import { renderOpenCodeLoopGuard } from '../setup/opencode-loop-guard.js';
|
|
13
13
|
import { renderCodexMcpConfig, renderGlobalInstructions } from '../setup/render.js';
|
|
14
14
|
import { renderClaudeConfig } from '../setup/claude-config.js';
|
|
15
15
|
import { renderHermesConfig } from '../setup/hermes-config.js';
|
|
16
16
|
import { detectInstalledClients } from '../setup/client-detection.js';
|
|
17
|
-
import {
|
|
17
|
+
import { assertExactLegacyOpenCodeLoopGuard, cleanupLegacyClaudePromptHook, } from '../setup/legacy-client-cleanup.js';
|
|
18
|
+
import { loadBundledStandardSkillFiles, renderStandardSkillFile, } from '../setup/standard-skills.js';
|
|
18
19
|
export const SETUP_CLIENTS = ['codex', 'opencode', 'claude', 'hermes'];
|
|
20
|
+
function setupPathJoin(options, ...segments) {
|
|
21
|
+
const platform = options.platform ?? process.platform;
|
|
22
|
+
return platform === 'win32' ? path.win32.join(...segments) : path.posix.join(...segments);
|
|
23
|
+
}
|
|
19
24
|
export function parseSetupClients(value) {
|
|
20
25
|
const clients = [...new Set(value.split(',').map((client) => client.trim()).filter(Boolean))];
|
|
21
26
|
if (clients.length === 0 || clients.some((client) => !SETUP_CLIENTS.includes(client))) {
|
|
@@ -23,6 +28,12 @@ export function parseSetupClients(value) {
|
|
|
23
28
|
}
|
|
24
29
|
return clients;
|
|
25
30
|
}
|
|
31
|
+
export function parseSetupSkillDiscoveryMode(value) {
|
|
32
|
+
if (!isSkillDiscoveryMode(value)) {
|
|
33
|
+
throw new KiokukoError('VALIDATION_ERROR', 'skill discovery must be off, official, or community');
|
|
34
|
+
}
|
|
35
|
+
return value;
|
|
36
|
+
}
|
|
26
37
|
function setupClientLabel(client) {
|
|
27
38
|
if (client === 'codex')
|
|
28
39
|
return 'Codex';
|
|
@@ -32,92 +43,316 @@ function setupClientLabel(client) {
|
|
|
32
43
|
return 'Claude Code';
|
|
33
44
|
return 'Hermes Agent';
|
|
34
45
|
}
|
|
46
|
+
async function askSetupClients(prompt, output, detected) {
|
|
47
|
+
const defaultSelection = detected.length === 0 ? 'none' : detected.join(',');
|
|
48
|
+
output.write('Select clients to configure (detected clients are preselected):\n');
|
|
49
|
+
for (const [index, client] of SETUP_CLIENTS.entries()) {
|
|
50
|
+
const checked = detected.includes(client) ? 'x' : ' ';
|
|
51
|
+
const status = detected.includes(client) ? 'detected' : 'not detected';
|
|
52
|
+
output.write(` ${index + 1}. [${checked}] ${setupClientLabel(client)} (${status})\n`);
|
|
53
|
+
}
|
|
54
|
+
output.write('Enter client names or numbers separated by commas. Press Enter to accept the checked clients; type none to skip all.\n');
|
|
55
|
+
while (true) {
|
|
56
|
+
const answer = (await prompt.question(`Clients [${defaultSelection}]: `)).trim();
|
|
57
|
+
if (answer.length === 0)
|
|
58
|
+
return detected;
|
|
59
|
+
if (/^(?:none|なし)$/iu.test(answer))
|
|
60
|
+
return [];
|
|
61
|
+
const selected = [];
|
|
62
|
+
let invalid = false;
|
|
63
|
+
for (const token of answer.split(',').map((value) => value.trim()).filter(Boolean)) {
|
|
64
|
+
const index = Number(token);
|
|
65
|
+
const indexedClient = Number.isInteger(index) && index >= 1 && index <= SETUP_CLIENTS.length
|
|
66
|
+
? SETUP_CLIENTS[index - 1]
|
|
67
|
+
: undefined;
|
|
68
|
+
const client = indexedClient ?? token.toLowerCase();
|
|
69
|
+
if (!SETUP_CLIENTS.includes(client)) {
|
|
70
|
+
invalid = true;
|
|
71
|
+
break;
|
|
72
|
+
}
|
|
73
|
+
selected.push(client);
|
|
74
|
+
}
|
|
75
|
+
if (!invalid)
|
|
76
|
+
return [...new Set(selected)];
|
|
77
|
+
output.write(`Invalid selection. Choose names or numbers for: ${SETUP_CLIENTS.join(', ')}.\n`);
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
async function askCommunitySkillDiscovery(prompt, output) {
|
|
81
|
+
output.write('Official external Skill discovery is enabled by default and uses validated content only as untrusted references. It never installs or executes Skills.\n');
|
|
82
|
+
output.write('Community discovery can also use audited community Skills as untrusted references when relevant.\n');
|
|
83
|
+
const answer = (await prompt.question('Enable community Skill discovery? [y/N] ')).trim();
|
|
84
|
+
return /^(?:y|yes|はい)$/iu.test(answer) ? 'community' : 'official';
|
|
85
|
+
}
|
|
86
|
+
async function askReplaceConflictingMcp(prompt, output, client) {
|
|
87
|
+
const label = setupClientLabel(client);
|
|
88
|
+
output.write(`${label} already has a non-canonical or unmanaged Kiokuko MCP identity.\n`);
|
|
89
|
+
output.write('Kiokuko can remove that identity, install the managed configuration, and continue setup.\n');
|
|
90
|
+
const answer = (await prompt.question(`Replace the existing ${label} Kiokuko MCP identity and continue? [y/N] `)).trim();
|
|
91
|
+
return /^(?:y|yes|はい)$/iu.test(answer);
|
|
92
|
+
}
|
|
35
93
|
/** Ask which supported clients should receive configuration in an interactive terminal. */
|
|
36
94
|
export async function promptSetupClients(detected, options = {}) {
|
|
37
95
|
const input = options.input ?? stdin;
|
|
38
96
|
const output = options.output ?? stdout;
|
|
39
97
|
const prompt = createInterface({ input, output });
|
|
40
|
-
const defaultSelection = detected.length === 0 ? 'none' : detected.join(',');
|
|
41
98
|
try {
|
|
42
|
-
|
|
43
|
-
for (const [index, client] of SETUP_CLIENTS.entries()) {
|
|
44
|
-
const checked = detected.includes(client) ? 'x' : ' ';
|
|
45
|
-
const status = detected.includes(client) ? 'detected' : 'not detected';
|
|
46
|
-
output.write(` ${index + 1}. [${checked}] ${setupClientLabel(client)} (${status})\n`);
|
|
47
|
-
}
|
|
48
|
-
output.write('Enter client names or numbers separated by commas. Press Enter to accept the checked clients; type none to skip all.\n');
|
|
49
|
-
while (true) {
|
|
50
|
-
const answer = (await prompt.question(`Clients [${defaultSelection}]: `)).trim();
|
|
51
|
-
if (answer.length === 0)
|
|
52
|
-
return detected;
|
|
53
|
-
if (/^(?:none|なし)$/iu.test(answer))
|
|
54
|
-
return [];
|
|
55
|
-
const selected = [];
|
|
56
|
-
let invalid = false;
|
|
57
|
-
for (const token of answer.split(',').map((value) => value.trim()).filter(Boolean)) {
|
|
58
|
-
const index = Number(token);
|
|
59
|
-
const indexedClient = Number.isInteger(index) && index >= 1 && index <= SETUP_CLIENTS.length
|
|
60
|
-
? SETUP_CLIENTS[index - 1]
|
|
61
|
-
: undefined;
|
|
62
|
-
const client = indexedClient ?? token.toLowerCase();
|
|
63
|
-
if (!SETUP_CLIENTS.includes(client)) {
|
|
64
|
-
invalid = true;
|
|
65
|
-
break;
|
|
66
|
-
}
|
|
67
|
-
selected.push(client);
|
|
68
|
-
}
|
|
69
|
-
if (!invalid)
|
|
70
|
-
return [...new Set(selected)];
|
|
71
|
-
output.write(`Invalid selection. Choose names or numbers for: ${SETUP_CLIENTS.join(', ')}.\n`);
|
|
72
|
-
}
|
|
99
|
+
return await askSetupClients(prompt, output, detected);
|
|
73
100
|
}
|
|
74
101
|
finally {
|
|
75
102
|
prompt.close();
|
|
76
103
|
}
|
|
77
104
|
}
|
|
78
|
-
|
|
105
|
+
/** Ask whether audited community Skill discovery should be enabled. */
|
|
106
|
+
export async function promptCommunitySkillDiscovery(options = {}) {
|
|
107
|
+
const input = options.input ?? stdin;
|
|
108
|
+
const output = options.output ?? stdout;
|
|
109
|
+
const prompt = createInterface({ input, output });
|
|
79
110
|
try {
|
|
80
|
-
await
|
|
81
|
-
return true;
|
|
111
|
+
return await askCommunitySkillDiscovery(prompt, output);
|
|
82
112
|
}
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
113
|
+
finally {
|
|
114
|
+
prompt.close();
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
/** Ask before replacing a client Kiokuko MCP identity that setup does not own. */
|
|
118
|
+
export async function promptReplaceConflictingMcp(client, options = {}) {
|
|
119
|
+
const input = options.input ?? stdin;
|
|
120
|
+
const output = options.output ?? stdout;
|
|
121
|
+
const prompt = createInterface({ input, output });
|
|
122
|
+
try {
|
|
123
|
+
return await askReplaceConflictingMcp(prompt, output, client);
|
|
124
|
+
}
|
|
125
|
+
finally {
|
|
126
|
+
prompt.close();
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
function replacementClientSet(value) {
|
|
130
|
+
if (value === undefined)
|
|
131
|
+
return new Set();
|
|
132
|
+
if (!Array.isArray(value)
|
|
133
|
+
|| value.some((client) => !SETUP_CLIENTS.includes(client))
|
|
134
|
+
|| new Set(value).size !== value.length) {
|
|
135
|
+
throw new KiokukoError('VALIDATION_ERROR', `replaceConflictingMcpServers must be a unique subset of: ${SETUP_CLIENTS.join(', ')}`);
|
|
136
|
+
}
|
|
137
|
+
return new Set(value);
|
|
138
|
+
}
|
|
139
|
+
/** Ask both setup questions through one readline session so buffered input remains intact. */
|
|
140
|
+
export async function promptSetupConfiguration(detected, options = {}) {
|
|
141
|
+
const input = options.input ?? stdin;
|
|
142
|
+
const output = options.output ?? stdout;
|
|
143
|
+
const prompt = createInterface({ input, output });
|
|
144
|
+
try {
|
|
145
|
+
const clients = await askSetupClients(prompt, output, detected);
|
|
146
|
+
const skillDiscoveryMode = clients.length === 0
|
|
147
|
+
? 'official'
|
|
148
|
+
: await askCommunitySkillDiscovery(prompt, output);
|
|
149
|
+
return { clients, skillDiscoveryMode };
|
|
150
|
+
}
|
|
151
|
+
finally {
|
|
152
|
+
prompt.close();
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
function sameFileIdentity(left, right) {
|
|
156
|
+
return left.device === right.device && left.inode === right.inode;
|
|
157
|
+
}
|
|
158
|
+
function setupDirectoryChanged(directoryPath) {
|
|
159
|
+
return new KiokukoError('CONFLICT', 'Setup directory changed after planning', { target: directoryPath });
|
|
160
|
+
}
|
|
161
|
+
function plannedDirectoryIdentity(directory) {
|
|
162
|
+
return directory.original ?? directory.created;
|
|
163
|
+
}
|
|
164
|
+
function directoryLineage(directory) {
|
|
165
|
+
const lineage = [];
|
|
166
|
+
let current = directory;
|
|
167
|
+
while (current !== undefined) {
|
|
168
|
+
lineage.push(current);
|
|
169
|
+
current = current.parent;
|
|
170
|
+
}
|
|
171
|
+
return lineage.reverse();
|
|
172
|
+
}
|
|
173
|
+
async function assertPlannedDirectory(directory) {
|
|
174
|
+
for (const planned of directoryLineage(directory)) {
|
|
175
|
+
const current = await readDirectoryIdentity(planned.path);
|
|
176
|
+
const expected = plannedDirectoryIdentity(planned);
|
|
177
|
+
if ((current === undefined) !== (expected === undefined)
|
|
178
|
+
|| (current !== undefined && expected !== undefined && !sameFileIdentity(current, expected))) {
|
|
179
|
+
throw setupDirectoryChanged(planned.path);
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
async function planDirectory(planning, directoryPath) {
|
|
184
|
+
const resolved = path.resolve(directoryPath);
|
|
185
|
+
const existing = planning.directories.get(resolved);
|
|
186
|
+
if (existing !== undefined)
|
|
187
|
+
return existing;
|
|
188
|
+
const original = await readDirectoryIdentity(resolved);
|
|
189
|
+
const parentPath = path.dirname(resolved);
|
|
190
|
+
const parent = original !== undefined || parentPath === resolved
|
|
191
|
+
? undefined
|
|
192
|
+
: await planDirectory(planning, parentPath);
|
|
193
|
+
const planned = {
|
|
194
|
+
path: resolved,
|
|
195
|
+
parent,
|
|
196
|
+
original,
|
|
197
|
+
created: undefined,
|
|
198
|
+
};
|
|
199
|
+
planning.directories.set(resolved, planned);
|
|
200
|
+
return planned;
|
|
201
|
+
}
|
|
202
|
+
async function readPlannedRegularFile(planning, filePath) {
|
|
203
|
+
const parentDirectory = await planDirectory(planning, path.dirname(filePath));
|
|
204
|
+
await assertPlannedDirectory(parentDirectory);
|
|
205
|
+
const snapshot = await readRegularFile(filePath);
|
|
206
|
+
await assertPlannedDirectory(parentDirectory);
|
|
207
|
+
return { parentDirectory, snapshot };
|
|
208
|
+
}
|
|
209
|
+
function errno(error) {
|
|
210
|
+
return error instanceof Error && 'code' in error
|
|
211
|
+
? String(error.code)
|
|
212
|
+
: undefined;
|
|
213
|
+
}
|
|
214
|
+
async function preparePlannedDirectories(files, createdDirectories) {
|
|
215
|
+
const required = new Set();
|
|
216
|
+
for (const file of files) {
|
|
217
|
+
if (file.action === 'unchanged')
|
|
218
|
+
continue;
|
|
219
|
+
for (const directory of directoryLineage(file.parentDirectory))
|
|
220
|
+
required.add(directory);
|
|
221
|
+
}
|
|
222
|
+
const ordered = [...required].sort((left, right) => directoryLineage(left).length - directoryLineage(right).length);
|
|
223
|
+
for (const directory of ordered) {
|
|
224
|
+
const expected = plannedDirectoryIdentity(directory);
|
|
225
|
+
if (expected !== undefined) {
|
|
226
|
+
await assertPlannedDirectory(directory);
|
|
227
|
+
continue;
|
|
228
|
+
}
|
|
229
|
+
if (directory.parent === undefined) {
|
|
230
|
+
throw new KiokukoError('INTEGRITY_ERROR', 'Setup cannot create a missing filesystem root');
|
|
231
|
+
}
|
|
232
|
+
await assertPlannedDirectory(directory.parent);
|
|
233
|
+
if (await readDirectoryIdentity(directory.path) !== undefined) {
|
|
234
|
+
throw setupDirectoryChanged(directory.path);
|
|
235
|
+
}
|
|
236
|
+
try {
|
|
237
|
+
await mkdir(directory.path, { mode: 0o700 });
|
|
238
|
+
}
|
|
239
|
+
catch (error) {
|
|
240
|
+
if (errno(error) === 'EEXIST')
|
|
241
|
+
throw setupDirectoryChanged(directory.path);
|
|
242
|
+
throw error;
|
|
243
|
+
}
|
|
244
|
+
const created = await readDirectoryIdentity(directory.path);
|
|
245
|
+
if (created === undefined) {
|
|
246
|
+
throw new KiokukoError('INTEGRITY_ERROR', 'Setup directory disappeared immediately after creation', {
|
|
247
|
+
target: directory.path,
|
|
248
|
+
});
|
|
249
|
+
}
|
|
250
|
+
directory.created = created;
|
|
251
|
+
createdDirectories.push(directory);
|
|
252
|
+
await assertPlannedDirectory(directory);
|
|
87
253
|
}
|
|
88
254
|
}
|
|
89
|
-
async function
|
|
90
|
-
const
|
|
255
|
+
async function removeCreatedDirectories(createdDirectories) {
|
|
256
|
+
const failures = [];
|
|
257
|
+
for (const directory of [...createdDirectories].reverse()) {
|
|
258
|
+
try {
|
|
259
|
+
await assertPlannedDirectory(directory);
|
|
260
|
+
await rmdir(directory.path);
|
|
261
|
+
if (await readDirectoryIdentity(directory.path) !== undefined) {
|
|
262
|
+
throw setupDirectoryChanged(directory.path);
|
|
263
|
+
}
|
|
264
|
+
directory.created = undefined;
|
|
265
|
+
if (directory.parent !== undefined)
|
|
266
|
+
await assertPlannedDirectory(directory.parent);
|
|
267
|
+
}
|
|
268
|
+
catch (error) {
|
|
269
|
+
failures.push(error);
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
return failures;
|
|
273
|
+
}
|
|
274
|
+
async function planFile(planning, filePath, client, purpose, render, mustRemainAbsent = []) {
|
|
275
|
+
const { parentDirectory, snapshot: original } = await readPlannedRegularFile(planning, filePath);
|
|
91
276
|
const rendered = render(original?.content);
|
|
92
277
|
const action = original === undefined
|
|
93
278
|
? 'created'
|
|
94
279
|
: rendered.content === original.content ? 'unchanged' : 'updated';
|
|
95
280
|
return {
|
|
96
281
|
path: filePath,
|
|
282
|
+
parentDirectory,
|
|
97
283
|
content: rendered.content,
|
|
98
284
|
mode: original?.mode ?? 0o600,
|
|
99
|
-
original
|
|
285
|
+
original,
|
|
286
|
+
...(mustRemainAbsent.length === 0 ? {} : { mustRemainAbsent }),
|
|
100
287
|
action,
|
|
101
288
|
purpose,
|
|
102
289
|
client,
|
|
290
|
+
report: true,
|
|
103
291
|
};
|
|
104
292
|
}
|
|
105
|
-
async function
|
|
293
|
+
async function planLegacyClaudeHookCleanup(planning, options) {
|
|
294
|
+
const filePath = getLegacyClaudePromptHookSettingsPath(options);
|
|
295
|
+
const { parentDirectory, snapshot: original } = await readPlannedRegularFile(planning, filePath);
|
|
296
|
+
const content = original === undefined ? undefined : cleanupLegacyClaudePromptHook(original.content);
|
|
297
|
+
const changed = original !== undefined && content !== original.content;
|
|
298
|
+
return {
|
|
299
|
+
path: filePath,
|
|
300
|
+
parentDirectory,
|
|
301
|
+
content,
|
|
302
|
+
mode: original?.mode ?? 0o600,
|
|
303
|
+
original,
|
|
304
|
+
action: changed ? 'updated' : 'unchanged',
|
|
305
|
+
purpose: 'legacy-cleanup',
|
|
306
|
+
client: 'claude',
|
|
307
|
+
report: changed,
|
|
308
|
+
};
|
|
309
|
+
}
|
|
310
|
+
async function planLegacyOpenCodeGuardCleanup(planning, options) {
|
|
311
|
+
const filePath = getLegacyOpenCodeLoopGuardPath(options);
|
|
312
|
+
const { parentDirectory, snapshot: original } = await readPlannedRegularFile(planning, filePath);
|
|
313
|
+
if (original !== undefined)
|
|
314
|
+
assertExactLegacyOpenCodeLoopGuard(original.content);
|
|
315
|
+
return {
|
|
316
|
+
path: filePath,
|
|
317
|
+
parentDirectory,
|
|
318
|
+
content: undefined,
|
|
319
|
+
mode: original?.mode ?? 0o600,
|
|
320
|
+
original,
|
|
321
|
+
action: original === undefined ? 'unchanged' : 'deleted',
|
|
322
|
+
purpose: 'legacy-cleanup',
|
|
323
|
+
client: 'opencode',
|
|
324
|
+
report: original !== undefined,
|
|
325
|
+
};
|
|
326
|
+
}
|
|
327
|
+
async function openCodeConfigPath(planning, options) {
|
|
106
328
|
const directory = getOpenCodeConfigDirectory(options);
|
|
107
|
-
const jsonc =
|
|
108
|
-
if (await
|
|
109
|
-
return jsonc;
|
|
110
|
-
|
|
329
|
+
const jsonc = setupPathJoin(options, directory, 'opencode.jsonc');
|
|
330
|
+
if ((await readPlannedRegularFile(planning, jsonc)).snapshot !== undefined) {
|
|
331
|
+
return { path: jsonc, mustRemainAbsent: [] };
|
|
332
|
+
}
|
|
333
|
+
return { path: setupPathJoin(options, directory, 'opencode.json'), mustRemainAbsent: [jsonc] };
|
|
111
334
|
}
|
|
112
|
-
async function restoreFiles(
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
335
|
+
async function restoreFiles(mutations, dependencies) {
|
|
336
|
+
const failures = [];
|
|
337
|
+
for (const mutation of [...mutations].reverse()) {
|
|
338
|
+
const { file, installed } = mutation;
|
|
339
|
+
try {
|
|
340
|
+
if (file.original === undefined) {
|
|
341
|
+
if (installed === undefined)
|
|
342
|
+
throw new KiokukoError('INTEGRITY_ERROR', 'Setup rollback record is invalid');
|
|
343
|
+
const outcome = await dependencies.unlinkRegularFileIfUnchanged(file.path, fileExpectation(file, installed, false));
|
|
344
|
+
assertAtomicCleanupComplete(outcome);
|
|
345
|
+
}
|
|
346
|
+
else {
|
|
347
|
+
const outcome = await dependencies.atomicWriteTextIfUnchanged(file.path, file.original.content, fileExpectation(file, installed, false), file.original.mode);
|
|
348
|
+
assertAtomicCleanupComplete(outcome);
|
|
349
|
+
}
|
|
350
|
+
}
|
|
351
|
+
catch (error) {
|
|
352
|
+
failures.push(error);
|
|
353
|
+
}
|
|
120
354
|
}
|
|
355
|
+
return failures;
|
|
121
356
|
}
|
|
122
357
|
function setupNextStep(clients, standardSkills) {
|
|
123
358
|
return clients.map((client) => {
|
|
@@ -130,55 +365,119 @@ function setupNextStep(clients, standardSkills) {
|
|
|
130
365
|
return `Restart ${label} so it reloads global MCP and instruction configuration${standardSkills ? ' and standard skills' : ''}.`;
|
|
131
366
|
}).join(' ');
|
|
132
367
|
}
|
|
133
|
-
async function standardSkillDirectory(client, options) {
|
|
368
|
+
async function standardSkillDirectory(client, options, hermesProfile) {
|
|
134
369
|
if (client === 'codex')
|
|
135
370
|
return getCodexSkillsDirectory(options);
|
|
136
371
|
if (client === 'opencode')
|
|
137
372
|
return getOpenCodeSkillsDirectory(options);
|
|
138
373
|
if (client === 'claude')
|
|
139
374
|
return getClaudeSkillsDirectory(options);
|
|
140
|
-
|
|
375
|
+
if (hermesProfile === undefined)
|
|
376
|
+
throw new KiokukoError('INTEGRITY_ERROR', 'Hermes profile was not bound during setup planning');
|
|
377
|
+
return hermesProfile.skillsDirectory;
|
|
378
|
+
}
|
|
379
|
+
function fileExpectation(file, expected, includeAlternatePaths = true) {
|
|
380
|
+
const expectedParentDirectory = plannedDirectoryIdentity(file.parentDirectory);
|
|
381
|
+
if (expectedParentDirectory === undefined) {
|
|
382
|
+
throw new KiokukoError('INTEGRITY_ERROR', 'Setup file parent was not created or bound before mutation', {
|
|
383
|
+
target: file.parentDirectory.path,
|
|
384
|
+
});
|
|
385
|
+
}
|
|
386
|
+
return {
|
|
387
|
+
expected,
|
|
388
|
+
expectedParentDirectory,
|
|
389
|
+
...(includeAlternatePaths && file.mustRemainAbsent !== undefined
|
|
390
|
+
? { mustRemainAbsent: file.mustRemainAbsent }
|
|
391
|
+
: {}),
|
|
392
|
+
};
|
|
141
393
|
}
|
|
142
|
-
|
|
394
|
+
async function assertPlannedFile(file, expected) {
|
|
395
|
+
await assertPlannedDirectory(file.parentDirectory);
|
|
396
|
+
if (plannedDirectoryIdentity(file.parentDirectory) === undefined) {
|
|
397
|
+
if (expected !== undefined || await readRegularFile(file.path) !== undefined) {
|
|
398
|
+
throw setupDirectoryChanged(file.parentDirectory.path);
|
|
399
|
+
}
|
|
400
|
+
for (const absentPath of file.mustRemainAbsent ?? []) {
|
|
401
|
+
if (await readRegularFile(absentPath) !== undefined) {
|
|
402
|
+
throw new KiokukoError('CONFLICT', 'Setup target changed after planning', { target: absentPath });
|
|
403
|
+
}
|
|
404
|
+
}
|
|
405
|
+
}
|
|
406
|
+
else {
|
|
407
|
+
await assertFileExpectation(file.path, fileExpectation(file, expected));
|
|
408
|
+
}
|
|
409
|
+
await assertPlannedDirectory(file.parentDirectory);
|
|
410
|
+
}
|
|
411
|
+
async function assertPlannedFiles(files, applied = []) {
|
|
412
|
+
const installedByPath = new Map(applied.map((mutation) => [mutation.file.path, mutation.installed]));
|
|
413
|
+
for (const file of files) {
|
|
414
|
+
const expected = installedByPath.has(file.path) ? installedByPath.get(file.path) : file.original;
|
|
415
|
+
await assertPlannedFile(file, expected);
|
|
416
|
+
}
|
|
417
|
+
}
|
|
418
|
+
export async function setupGlobalClients(options = {}, dependencyOverrides = {}) {
|
|
419
|
+
const dependencies = {
|
|
420
|
+
atomicWriteTextIfUnchanged: dependencyOverrides.atomicWriteTextIfUnchanged ?? atomicWriteTextIfUnchanged,
|
|
421
|
+
unlinkRegularFileIfUnchanged: dependencyOverrides.unlinkRegularFileIfUnchanged ?? unlinkRegularFileIfUnchanged,
|
|
422
|
+
beforeCommit: dependencyOverrides.beforeCommit ?? (() => undefined),
|
|
423
|
+
openConnection: dependencyOverrides.openConnection ?? openConnection,
|
|
424
|
+
ensureGlobalWorkspace: dependencyOverrides.ensureGlobalWorkspace ?? ensureGlobalWorkspace,
|
|
425
|
+
};
|
|
143
426
|
const pathEnvironment = {
|
|
144
427
|
...(options.platform === undefined ? {} : { platform: options.platform }),
|
|
145
428
|
...(options.env === undefined ? {} : { env: options.env }),
|
|
146
429
|
};
|
|
430
|
+
if (options.skillDiscoveryMode !== undefined && !isSkillDiscoveryMode(options.skillDiscoveryMode)) {
|
|
431
|
+
throw new KiokukoError('VALIDATION_ERROR', 'skill discovery must be off, official, or community');
|
|
432
|
+
}
|
|
433
|
+
const replaceConflictingMcpServers = replacementClientSet(options.replaceConflictingMcpServers);
|
|
147
434
|
const clients = options.clients ?? await detectInstalledClients(pathEnvironment);
|
|
148
|
-
if (clients.some((client) => !SETUP_CLIENTS.includes(client))) {
|
|
435
|
+
if (!Array.isArray(clients) || clients.some((client) => !SETUP_CLIENTS.includes(client))) {
|
|
149
436
|
throw new KiokukoError('VALIDATION_ERROR', `clients must be a subset of: ${SETUP_CLIENTS.join(', ')}`);
|
|
150
437
|
}
|
|
151
438
|
const command = options.command ?? 'kiokuko';
|
|
152
|
-
if (command.trim().length === 0 || command.includes('\0'))
|
|
439
|
+
if (typeof command !== 'string' || command.trim().length === 0 || command.includes('\0')) {
|
|
153
440
|
throw new KiokukoError('VALIDATION_ERROR', 'command must be a non-empty executable path or name');
|
|
441
|
+
}
|
|
154
442
|
const databasePath = options.databasePath ?? getGlobalDatabasePath(pathEnvironment);
|
|
155
443
|
const standardSkills = options.standardSkills ?? true;
|
|
444
|
+
const environment = options.env ?? process.env;
|
|
445
|
+
const environmentSkillDiscoveryMode = options.skillDiscoveryMode === undefined
|
|
446
|
+
&& Object.prototype.hasOwnProperty.call(environment, SKILL_DISCOVERY_ENV)
|
|
447
|
+
? normalizeSkillDiscoveryMode(environment[SKILL_DISCOVERY_ENV])
|
|
448
|
+
: undefined;
|
|
449
|
+
const skillDiscoveryMode = options.skillDiscoveryMode ?? environmentSkillDiscoveryMode;
|
|
156
450
|
const files = [];
|
|
451
|
+
const planning = { directories: new Map() };
|
|
452
|
+
const hermesProfile = clients.includes('hermes')
|
|
453
|
+
? await resolveHermesProfilePaths(pathEnvironment)
|
|
454
|
+
: undefined;
|
|
157
455
|
if (clients.includes('codex')) {
|
|
158
|
-
files.push(await planFile(getCodexConfigPath(pathEnvironment), 'codex', 'mcp-config', (existing) => renderCodexMcpConfig(existing ?? '', command)));
|
|
159
|
-
files.push(await planFile(getCodexInstructionsPath(pathEnvironment), 'codex', 'instructions', (existing) => renderGlobalInstructions(existing ?? '')));
|
|
456
|
+
files.push(await planFile(planning, getCodexConfigPath(pathEnvironment), 'codex', 'mcp-config', (existing) => renderCodexMcpConfig(existing ?? '', command, skillDiscoveryMode, { replaceConflictingIdentity: replaceConflictingMcpServers.has('codex') })));
|
|
457
|
+
files.push(await planFile(planning, getCodexInstructionsPath(pathEnvironment), 'codex', 'instructions', (existing) => renderGlobalInstructions(existing ?? '')));
|
|
160
458
|
}
|
|
161
459
|
if (clients.includes('opencode')) {
|
|
162
|
-
|
|
163
|
-
files.push(await planFile(
|
|
164
|
-
files.push(await planFile(
|
|
165
|
-
|
|
166
|
-
...(options.opencodeMode === undefined ? {} : { mode: options.opencodeMode }),
|
|
167
|
-
})));
|
|
460
|
+
const selectedConfig = await openCodeConfigPath(planning, pathEnvironment);
|
|
461
|
+
files.push(await planFile(planning, selectedConfig.path, 'opencode', 'mcp-config', (existing) => renderOpenCodeConfig(existing, command, skillDiscoveryMode, { replaceConflictingIdentity: replaceConflictingMcpServers.has('opencode') }), selectedConfig.mustRemainAbsent));
|
|
462
|
+
files.push(await planFile(planning, getOpenCodeInstructionsPath(pathEnvironment), 'opencode', 'instructions', (existing) => renderGlobalInstructions(existing ?? '')));
|
|
463
|
+
files.push(await planLegacyOpenCodeGuardCleanup(planning, pathEnvironment));
|
|
168
464
|
}
|
|
169
465
|
if (clients.includes('claude')) {
|
|
170
|
-
files.push(await planFile(getClaudeMcpConfigPath(pathEnvironment), 'claude', 'mcp-config', (existing) => renderClaudeConfig(existing, command)));
|
|
171
|
-
files.push(await planFile(getClaudeInstructionsPath(pathEnvironment), 'claude', 'instructions', (existing) => renderGlobalInstructions(existing ?? '')));
|
|
466
|
+
files.push(await planFile(planning, getClaudeMcpConfigPath(pathEnvironment), 'claude', 'mcp-config', (existing) => renderClaudeConfig(existing, command, skillDiscoveryMode, { replaceConflictingIdentity: replaceConflictingMcpServers.has('claude') })));
|
|
467
|
+
files.push(await planFile(planning, getClaudeInstructionsPath(pathEnvironment), 'claude', 'instructions', (existing) => renderGlobalInstructions(existing ?? '')));
|
|
468
|
+
files.push(await planLegacyClaudeHookCleanup(planning, pathEnvironment));
|
|
172
469
|
}
|
|
173
470
|
if (clients.includes('hermes')) {
|
|
174
|
-
|
|
471
|
+
if (hermesProfile === undefined)
|
|
472
|
+
throw new KiokukoError('INTEGRITY_ERROR', 'Hermes profile was not bound during setup planning');
|
|
473
|
+
files.push(await planFile(planning, hermesProfile.configPath, 'hermes', 'mcp-config', (existing) => renderHermesConfig(existing, command, skillDiscoveryMode, { replaceConflictingIdentity: replaceConflictingMcpServers.has('hermes') })));
|
|
175
474
|
}
|
|
176
475
|
if (standardSkills) {
|
|
177
476
|
const bundledFiles = await loadBundledStandardSkillFiles();
|
|
178
477
|
for (const client of clients) {
|
|
179
|
-
const
|
|
478
|
+
const skillsDirectory = await standardSkillDirectory(client, pathEnvironment, hermesProfile);
|
|
180
479
|
for (const bundled of bundledFiles) {
|
|
181
|
-
files.push(await planFile(
|
|
480
|
+
files.push(await planFile(planning, setupPathJoin(pathEnvironment, skillsDirectory, bundled.skillName, bundled.relativePath), client, 'standard-skill', (existing) => renderStandardSkillFile(existing, bundled)));
|
|
182
481
|
}
|
|
183
482
|
}
|
|
184
483
|
}
|
|
@@ -188,7 +487,9 @@ export async function setupGlobalClients(options = {}) {
|
|
|
188
487
|
databaseAction: options.dryRun ? 'planned' : 'initialized',
|
|
189
488
|
databaseBackupPath: null,
|
|
190
489
|
appliedMigrations: [],
|
|
191
|
-
files: files
|
|
490
|
+
files: files
|
|
491
|
+
.filter((file) => file.report)
|
|
492
|
+
.map(({ path: filePath, action, purpose, client }) => ({ path: filePath, action, purpose, client })),
|
|
192
493
|
standardSkills,
|
|
193
494
|
dryRun: options.dryRun ?? false,
|
|
194
495
|
nextStep: setupNextStep(clients, standardSkills),
|
|
@@ -201,24 +502,85 @@ export async function setupGlobalClients(options = {}) {
|
|
|
201
502
|
});
|
|
202
503
|
result.databaseBackupPath = initialized.backupPath;
|
|
203
504
|
result.appliedMigrations = initialized.applied;
|
|
204
|
-
const database = openConnection(databasePath);
|
|
505
|
+
const database = dependencies.openConnection(databasePath);
|
|
506
|
+
let workspaceInitializationFailed = false;
|
|
507
|
+
let workspaceInitializationError;
|
|
205
508
|
try {
|
|
206
|
-
ensureGlobalWorkspace(database);
|
|
509
|
+
dependencies.ensureGlobalWorkspace(database);
|
|
207
510
|
}
|
|
208
|
-
|
|
511
|
+
catch (error) {
|
|
512
|
+
workspaceInitializationFailed = true;
|
|
513
|
+
workspaceInitializationError = error;
|
|
514
|
+
}
|
|
515
|
+
try {
|
|
209
516
|
database.close();
|
|
210
517
|
}
|
|
211
|
-
|
|
518
|
+
catch (closeError) {
|
|
519
|
+
if (workspaceInitializationFailed) {
|
|
520
|
+
throw new AggregateError([workspaceInitializationError, closeError], 'Global workspace initialization failed and closing the database connection also failed');
|
|
521
|
+
}
|
|
522
|
+
throw closeError;
|
|
523
|
+
}
|
|
524
|
+
if (workspaceInitializationFailed)
|
|
525
|
+
throw workspaceInitializationError;
|
|
526
|
+
const applied = [];
|
|
527
|
+
const createdDirectories = [];
|
|
212
528
|
try {
|
|
529
|
+
await dependencies.beforeCommit();
|
|
530
|
+
await preparePlannedDirectories(files, createdDirectories);
|
|
531
|
+
await assertPlannedFiles(files);
|
|
213
532
|
for (const file of files) {
|
|
214
533
|
if (file.action === 'unchanged')
|
|
215
534
|
continue;
|
|
216
|
-
|
|
217
|
-
|
|
535
|
+
// Record a committed mutation before inspecting its cleanup outcome so
|
|
536
|
+
// rollback never loses ownership of a target that already changed.
|
|
537
|
+
let installed;
|
|
538
|
+
if (file.action === 'deleted') {
|
|
539
|
+
if (file.original === undefined)
|
|
540
|
+
throw new KiokukoError('INTEGRITY_ERROR', 'Setup deletion plan is missing original content');
|
|
541
|
+
let outcome;
|
|
542
|
+
try {
|
|
543
|
+
outcome = await dependencies.unlinkRegularFileIfUnchanged(file.path, fileExpectation(file, file.original));
|
|
544
|
+
}
|
|
545
|
+
catch (error) {
|
|
546
|
+
if (error instanceof AtomicCommittedUnlinkError) {
|
|
547
|
+
applied.push({ file, installed: undefined });
|
|
548
|
+
}
|
|
549
|
+
throw error;
|
|
550
|
+
}
|
|
551
|
+
applied.push({ file, installed: undefined });
|
|
552
|
+
assertAtomicCleanupComplete(outcome);
|
|
553
|
+
}
|
|
554
|
+
else {
|
|
555
|
+
if (file.content === undefined)
|
|
556
|
+
throw new KiokukoError('INTEGRITY_ERROR', 'Setup file plan is missing rendered content');
|
|
557
|
+
let outcome;
|
|
558
|
+
try {
|
|
559
|
+
outcome = await dependencies.atomicWriteTextIfUnchanged(file.path, file.content, fileExpectation(file, file.original), file.mode);
|
|
560
|
+
}
|
|
561
|
+
catch (error) {
|
|
562
|
+
if (error instanceof AtomicCommittedMutationError) {
|
|
563
|
+
applied.push({ file, installed: error.outcome.installed });
|
|
564
|
+
}
|
|
565
|
+
else if (error instanceof AtomicCommittedUnlinkError) {
|
|
566
|
+
applied.push({ file, installed: undefined });
|
|
567
|
+
}
|
|
568
|
+
throw error;
|
|
569
|
+
}
|
|
570
|
+
installed = outcome.installed;
|
|
571
|
+
applied.push({ file, installed });
|
|
572
|
+
assertAtomicCleanupComplete(outcome);
|
|
573
|
+
}
|
|
218
574
|
}
|
|
575
|
+
await assertPlannedFiles(files, applied);
|
|
219
576
|
}
|
|
220
577
|
catch (error) {
|
|
221
|
-
await restoreFiles(
|
|
578
|
+
const restorationFailures = await restoreFiles(applied, dependencies);
|
|
579
|
+
const directoryRestorationFailures = await removeCreatedDirectories(createdDirectories);
|
|
580
|
+
const failures = [...restorationFailures, ...directoryRestorationFailures];
|
|
581
|
+
if (failures.length > 0) {
|
|
582
|
+
throw new AggregateError([error, ...failures], 'Setup failed and filesystem restoration also failed');
|
|
583
|
+
}
|
|
222
584
|
throw error;
|
|
223
585
|
}
|
|
224
586
|
return result;
|