@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/agent.js
CHANGED
|
@@ -1,14 +1,26 @@
|
|
|
1
|
-
import { randomUUID } from 'node:crypto';
|
|
2
|
-
import {
|
|
1
|
+
import { createHash, randomUUID } from 'node:crypto';
|
|
2
|
+
import { constants as fsConstants } from 'node:fs';
|
|
3
|
+
import { open } from 'node:fs/promises';
|
|
3
4
|
import { TextDecoder } from 'node:util';
|
|
5
|
+
import { isProxy } from 'node:util/types';
|
|
4
6
|
import { KiokukoError } from '../errors.js';
|
|
7
|
+
import { CAPABILITY_KINDS, MAX_CAPABILITY_NAME_CHARS, MEMORY_REASONING_SKILL_NAME, } from '../akinator/capabilities.js';
|
|
8
|
+
import { TASK_TYPES } from '../akinator/types.js';
|
|
9
|
+
import { CONTEXT_RANKING_COMPONENTS, CONTEXT_SELECTION_REASON_ORDER, } from '../context/ranking.js';
|
|
10
|
+
import { RECOMMENDATION_CODES } from '../context/recommendations.js';
|
|
11
|
+
import { findSecret } from '../memory/secrets.js';
|
|
5
12
|
import { successEnvelope } from '../serialization/envelope.js';
|
|
13
|
+
import { cloneBoundaryJson as cloneStrictBoundaryJson, stringifyBoundaryJson, } from '../serialization/boundary-json.js';
|
|
14
|
+
import { AGENT_MUTATION_OPERATIONS, agentRequestBindingHash, } from '../server/routes/request-binding.js';
|
|
15
|
+
import { MAX_STRICT_JSON_DEPTH, parseStrictJson } from '../setup/strict-json.js';
|
|
6
16
|
import { createServerClient, } from '../client/server-client.js';
|
|
7
17
|
const MAX_INPUT_BYTES = 2 * 1024 * 1024;
|
|
8
18
|
const MAX_ID_BYTES = 256;
|
|
9
19
|
const MAX_TEXT_BYTES = 16 * 1024;
|
|
10
20
|
const MAX_INPUT_PATH_BYTES = 4 * 1024;
|
|
21
|
+
const MAX_JSON_NODES = 262_144;
|
|
11
22
|
const CONTROL_CHARACTERS = /\p{Cc}/u;
|
|
23
|
+
const UNSAFE_CAPABILITY_LABEL_CHARACTERS = /[\p{Cc}\p{Cf}]/u;
|
|
12
24
|
const CAPTURE_PROFILES = new Set(['minimal', 'standard', 'full']);
|
|
13
25
|
function validationError() {
|
|
14
26
|
return new KiokukoError('VALIDATION_ERROR', 'Agent input is invalid');
|
|
@@ -23,13 +35,28 @@ function boundedString(value, maximumBytes) {
|
|
|
23
35
|
function boundedId(value) {
|
|
24
36
|
return boundedString(value, MAX_ID_BYTES);
|
|
25
37
|
}
|
|
26
|
-
function
|
|
27
|
-
|
|
38
|
+
function boundedIdempotencyKey(value) {
|
|
39
|
+
const key = boundedString(value, MAX_ID_BYTES);
|
|
40
|
+
if (key.trim() !== key)
|
|
28
41
|
throw validationError();
|
|
29
|
-
|
|
30
|
-
|
|
42
|
+
return key;
|
|
43
|
+
}
|
|
44
|
+
function cloneBoundaryJson(value, failure) {
|
|
45
|
+
return cloneStrictBoundaryJson(value, {
|
|
46
|
+
failure,
|
|
47
|
+
maximumDepth: MAX_STRICT_JSON_DEPTH,
|
|
48
|
+
maximumNodes: MAX_JSON_NODES,
|
|
49
|
+
maximumStringBytes: MAX_INPUT_BYTES,
|
|
50
|
+
});
|
|
51
|
+
}
|
|
52
|
+
function inputJson(value) {
|
|
53
|
+
return cloneBoundaryJson(value, validationError);
|
|
54
|
+
}
|
|
55
|
+
function inputObject(value) {
|
|
56
|
+
const cloned = inputJson(value);
|
|
57
|
+
if (typeof cloned !== 'object' || cloned === null || Array.isArray(cloned))
|
|
31
58
|
throw validationError();
|
|
32
|
-
return
|
|
59
|
+
return cloned;
|
|
33
60
|
}
|
|
34
61
|
function validateInputPath(value) {
|
|
35
62
|
if (value === '-')
|
|
@@ -39,47 +66,110 @@ function validateInputPath(value) {
|
|
|
39
66
|
async function readStdinBytes() {
|
|
40
67
|
const chunks = [];
|
|
41
68
|
let size = 0;
|
|
69
|
+
for await (const chunk of process.stdin) {
|
|
70
|
+
const bytes = Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk, 'utf8');
|
|
71
|
+
size += bytes.byteLength;
|
|
72
|
+
if (size > MAX_INPUT_BYTES)
|
|
73
|
+
throw validationError();
|
|
74
|
+
chunks.push(bytes);
|
|
75
|
+
}
|
|
76
|
+
return Buffer.concat(chunks);
|
|
77
|
+
}
|
|
78
|
+
const INPUT_FILESYSTEM_ERROR_CODES = new Set([
|
|
79
|
+
'EACCES', 'EIO', 'EISDIR', 'EMFILE', 'ENFILE', 'ENOENT', 'ENOTDIR', 'EPERM',
|
|
80
|
+
]);
|
|
81
|
+
function isInputFilesystemError(error) {
|
|
82
|
+
if ((typeof error !== 'object' && typeof error !== 'function') || error === null || isProxy(error))
|
|
83
|
+
return false;
|
|
84
|
+
const descriptor = Object.getOwnPropertyDescriptor(error, 'code');
|
|
85
|
+
return descriptor !== undefined && 'value' in descriptor
|
|
86
|
+
&& typeof descriptor.value === 'string'
|
|
87
|
+
&& INPUT_FILESYSTEM_ERROR_CODES.has(descriptor.value);
|
|
88
|
+
}
|
|
89
|
+
function isExactAgentKiokukoError(error) {
|
|
90
|
+
return typeof error === 'object' && error !== null && !isProxy(error)
|
|
91
|
+
&& Object.getPrototypeOf(error) === KiokukoError.prototype;
|
|
92
|
+
}
|
|
93
|
+
async function readBoundedRegularFile(filePath, closeHandle) {
|
|
94
|
+
let handle;
|
|
42
95
|
try {
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
96
|
+
handle = await open(filePath, fsConstants.O_RDONLY | fsConstants.O_NONBLOCK);
|
|
97
|
+
}
|
|
98
|
+
catch (error) {
|
|
99
|
+
if (isInputFilesystemError(error))
|
|
100
|
+
throw validationError();
|
|
101
|
+
throw error;
|
|
102
|
+
}
|
|
103
|
+
let operationResult;
|
|
104
|
+
let operationFailed = false;
|
|
105
|
+
let operationError;
|
|
106
|
+
try {
|
|
107
|
+
const metadata = await handle.stat();
|
|
108
|
+
if (!metadata.isFile() || !Number.isSafeInteger(metadata.size) || metadata.size < 0
|
|
109
|
+
|| metadata.size > MAX_INPUT_BYTES)
|
|
110
|
+
throw validationError();
|
|
111
|
+
const bytes = Buffer.allocUnsafe(MAX_INPUT_BYTES + 1);
|
|
112
|
+
let offset = 0;
|
|
113
|
+
while (offset <= MAX_INPUT_BYTES) {
|
|
114
|
+
const result = await handle.read(bytes, offset, bytes.byteLength - offset, null);
|
|
115
|
+
if (result.bytesRead === 0) {
|
|
116
|
+
operationResult = bytes.subarray(0, offset);
|
|
117
|
+
break;
|
|
118
|
+
}
|
|
119
|
+
offset += result.bytesRead;
|
|
120
|
+
if (offset > MAX_INPUT_BYTES)
|
|
47
121
|
throw validationError();
|
|
48
|
-
chunks.push(bytes);
|
|
49
122
|
}
|
|
50
123
|
}
|
|
51
124
|
catch (error) {
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
125
|
+
operationFailed = true;
|
|
126
|
+
operationError = isExactAgentKiokukoError(error) && error.code === 'VALIDATION_ERROR'
|
|
127
|
+
? error
|
|
128
|
+
: isInputFilesystemError(error)
|
|
129
|
+
? validationError()
|
|
130
|
+
: error;
|
|
55
131
|
}
|
|
56
|
-
|
|
132
|
+
try {
|
|
133
|
+
await closeHandle(handle);
|
|
134
|
+
}
|
|
135
|
+
catch (closeError) {
|
|
136
|
+
if (operationFailed) {
|
|
137
|
+
throw new AggregateError([operationError, closeError], 'Agent input read failed and its file descriptor could not be closed');
|
|
138
|
+
}
|
|
139
|
+
throw closeError;
|
|
140
|
+
}
|
|
141
|
+
if (operationFailed)
|
|
142
|
+
throw operationError;
|
|
143
|
+
if (operationResult === undefined) {
|
|
144
|
+
throw new KiokukoError('INTEGRITY_ERROR', 'Agent input read produced no result');
|
|
145
|
+
}
|
|
146
|
+
return operationResult;
|
|
57
147
|
}
|
|
58
|
-
async function readStrictJsonInput(filePath) {
|
|
148
|
+
async function readStrictJsonInput(filePath, closeHandle) {
|
|
59
149
|
const safePath = validateInputPath(filePath);
|
|
60
150
|
let bytes;
|
|
61
|
-
|
|
62
|
-
bytes =
|
|
151
|
+
if (safePath === '-') {
|
|
152
|
+
bytes = await readStdinBytes();
|
|
63
153
|
}
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
throw error;
|
|
67
|
-
throw validationError();
|
|
154
|
+
else {
|
|
155
|
+
bytes = await readBoundedRegularFile(safePath, closeHandle);
|
|
68
156
|
}
|
|
69
157
|
if (bytes.byteLength > MAX_INPUT_BYTES)
|
|
70
158
|
throw validationError();
|
|
71
159
|
let text;
|
|
72
160
|
try {
|
|
73
|
-
text = new TextDecoder('utf-8', { fatal: true }).decode(bytes);
|
|
161
|
+
text = new TextDecoder('utf-8', { fatal: true, ignoreBOM: true }).decode(bytes);
|
|
74
162
|
}
|
|
75
163
|
catch {
|
|
76
164
|
throw validationError();
|
|
77
165
|
}
|
|
78
166
|
try {
|
|
79
|
-
return
|
|
167
|
+
return parseStrictJson(text, { allowTrailingComma: false, disallowComments: true, allowEmptyContent: false }, 'Agent input is not valid JSON with unique keys');
|
|
80
168
|
}
|
|
81
|
-
catch {
|
|
82
|
-
|
|
169
|
+
catch (error) {
|
|
170
|
+
if (isExactAgentKiokukoError(error) && error.code === 'VALIDATION_ERROR')
|
|
171
|
+
throw validationError();
|
|
172
|
+
throw error;
|
|
83
173
|
}
|
|
84
174
|
}
|
|
85
175
|
function captureProfile(value) {
|
|
@@ -102,88 +192,748 @@ function runPath(runId, suffix) {
|
|
|
102
192
|
}
|
|
103
193
|
function keyFromFactory(dependencies) {
|
|
104
194
|
const factory = dependencies.idempotencyKeyFactory ?? randomUUID;
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
if (error instanceof KiokukoError)
|
|
110
|
-
throw error;
|
|
111
|
-
throw validationError();
|
|
112
|
-
}
|
|
195
|
+
return boundedIdempotencyKey(factory());
|
|
196
|
+
}
|
|
197
|
+
function requestIdempotencyKey(value, dependencies) {
|
|
198
|
+
return value === undefined ? keyFromFactory(dependencies) : boundedIdempotencyKey(value);
|
|
113
199
|
}
|
|
114
200
|
function bodyAndKey(value, dependencies) {
|
|
115
201
|
if (Object.prototype.hasOwnProperty.call(value, 'idempotencyKey')) {
|
|
116
|
-
const idempotencyKey =
|
|
202
|
+
const idempotencyKey = boundedIdempotencyKey(value.idempotencyKey);
|
|
117
203
|
const { idempotencyKey: _removed, ...body } = value;
|
|
118
204
|
return { body, idempotencyKey };
|
|
119
205
|
}
|
|
120
206
|
return { body: value, idempotencyKey: keyFromFactory(dependencies) };
|
|
121
207
|
}
|
|
122
208
|
async function readInput(dependencies, filePath) {
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
return
|
|
209
|
+
return inputObject(await readUnknownInput(dependencies, filePath));
|
|
210
|
+
}
|
|
211
|
+
async function readUnknownInput(dependencies, filePath) {
|
|
212
|
+
return dependencies.readJsonInput === undefined
|
|
213
|
+
? readStrictJsonInput(filePath, dependencies.closeInputFile ?? ((handle) => handle.close()))
|
|
214
|
+
: dependencies.readJsonInput(validateInputPath(filePath));
|
|
215
|
+
}
|
|
216
|
+
async function readCapabilityCatalog(dependencies, filePath) {
|
|
217
|
+
const value = inputJson(await readUnknownInput(dependencies, filePath));
|
|
218
|
+
if (!Array.isArray(value))
|
|
219
|
+
throw validationError();
|
|
220
|
+
return value;
|
|
127
221
|
}
|
|
128
222
|
async function getClient(dependencies) {
|
|
129
223
|
const factory = dependencies.createClient ?? createServerClient;
|
|
130
224
|
const options = dependencies.fetchImplementation === undefined
|
|
131
225
|
? {}
|
|
132
226
|
: { fetchImplementation: dependencies.fetchImplementation };
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
227
|
+
return factory(options);
|
|
228
|
+
}
|
|
229
|
+
function runIdFromRequestPath(path) {
|
|
230
|
+
const match = /^\/api\/v1\/agent\/runs\/([^/]+)\/(?:intake\/answers|events|checkpoints|close|feedback)$/u.exec(path);
|
|
231
|
+
if (match?.[1] === undefined)
|
|
232
|
+
return undefined;
|
|
233
|
+
return decodeURIComponent(match[1]);
|
|
234
|
+
}
|
|
235
|
+
function responseBindingForRequest(request) {
|
|
236
|
+
if (!AGENT_MUTATION_OPERATIONS.includes(request.operation)) {
|
|
237
|
+
throw new TypeError('Agent request operation is invalid');
|
|
140
238
|
}
|
|
239
|
+
const requestBody = inputObject(request.body);
|
|
240
|
+
return {
|
|
241
|
+
operation: request.operation,
|
|
242
|
+
expectedRunId: runIdFromRequestPath(request.path),
|
|
243
|
+
requestBody,
|
|
244
|
+
idempotencyKey: boundedIdempotencyKey(request.idempotencyKey),
|
|
245
|
+
};
|
|
141
246
|
}
|
|
142
247
|
async function sendRequest(dependencies, request) {
|
|
143
|
-
|
|
144
|
-
|
|
248
|
+
const binding = responseBindingForRequest(request);
|
|
249
|
+
if (request.operation !== 'agent.open' && binding.expectedRunId === undefined) {
|
|
250
|
+
throw new TypeError('Agent request path is not bound to a run');
|
|
145
251
|
}
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
252
|
+
const response = await (await getClient(dependencies)).request(request);
|
|
253
|
+
return validateAgentResponse(binding.operation, response, binding);
|
|
254
|
+
}
|
|
255
|
+
function responseIntegrityError() {
|
|
256
|
+
return new KiokukoError('INTEGRITY_ERROR', 'Agent server response is invalid');
|
|
257
|
+
}
|
|
258
|
+
function responseObject(value, required, optional = []) {
|
|
259
|
+
if (typeof value !== 'object' || value === null || Array.isArray(value))
|
|
260
|
+
throw responseIntegrityError();
|
|
261
|
+
const object = value;
|
|
262
|
+
const keys = Object.keys(object);
|
|
263
|
+
const allowed = new Set([...required, ...optional]);
|
|
264
|
+
if (keys.some((key) => !allowed.has(key)) || required.some((key) => !Object.hasOwn(object, key))) {
|
|
265
|
+
throw responseIntegrityError();
|
|
150
266
|
}
|
|
267
|
+
return object;
|
|
268
|
+
}
|
|
269
|
+
function responseArray(value, maximum) {
|
|
270
|
+
if (!Array.isArray(value) || value.length > maximum)
|
|
271
|
+
throw responseIntegrityError();
|
|
272
|
+
return value;
|
|
273
|
+
}
|
|
274
|
+
function responseString(value, maximumBytes = MAX_INPUT_BYTES, allowEmpty = false) {
|
|
275
|
+
if (typeof value !== 'string' || (!allowEmpty && value.length === 0)
|
|
276
|
+
|| Buffer.byteLength(value, 'utf8') > maximumBytes)
|
|
277
|
+
throw responseIntegrityError();
|
|
278
|
+
return value;
|
|
279
|
+
}
|
|
280
|
+
function responseIdentifier(value) {
|
|
281
|
+
const result = responseString(value, MAX_INPUT_BYTES);
|
|
282
|
+
if (result.length > MAX_ID_BYTES || CONTROL_CHARACTERS.test(result))
|
|
283
|
+
throw responseIntegrityError();
|
|
284
|
+
return result;
|
|
285
|
+
}
|
|
286
|
+
function responseEventId(value) {
|
|
287
|
+
if (typeof value !== 'string' || value.trim().length === 0
|
|
288
|
+
|| value.length > MAX_ID_BYTES || value.includes('\u0000'))
|
|
289
|
+
throw responseIntegrityError();
|
|
290
|
+
return value;
|
|
291
|
+
}
|
|
292
|
+
function responseEnum(value, allowed) {
|
|
293
|
+
if (typeof value !== 'string' || !allowed.includes(value))
|
|
294
|
+
throw responseIntegrityError();
|
|
295
|
+
return value;
|
|
296
|
+
}
|
|
297
|
+
function responseInteger(value, minimum = 0, maximum = Number.MAX_SAFE_INTEGER) {
|
|
298
|
+
if (typeof value !== 'number' || !Number.isSafeInteger(value) || value < minimum || value > maximum) {
|
|
299
|
+
throw responseIntegrityError();
|
|
300
|
+
}
|
|
301
|
+
return value;
|
|
302
|
+
}
|
|
303
|
+
function responseHash(value) {
|
|
304
|
+
if (typeof value !== 'string' || !/^[0-9a-f]{64}$/u.test(value))
|
|
305
|
+
throw responseIntegrityError();
|
|
306
|
+
return value;
|
|
307
|
+
}
|
|
308
|
+
function validateRequestBindingHash(object, binding) {
|
|
309
|
+
const actual = responseHash(object.requestBindingHash);
|
|
310
|
+
const expected = agentRequestBindingHash({
|
|
311
|
+
operation: binding.operation,
|
|
312
|
+
pathRunId: binding.expectedRunId ?? null,
|
|
313
|
+
idempotencyKey: binding.idempotencyKey,
|
|
314
|
+
requestBody: binding.requestBody,
|
|
315
|
+
});
|
|
316
|
+
if (actual !== expected)
|
|
317
|
+
throw responseIntegrityError();
|
|
318
|
+
}
|
|
319
|
+
function responseTimestamp(value) {
|
|
320
|
+
if (typeof value !== 'string' || !/^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}\.\d{3}Z$/u.test(value)) {
|
|
321
|
+
throw responseIntegrityError();
|
|
322
|
+
}
|
|
323
|
+
const timestamp = Date.parse(value);
|
|
324
|
+
if (!Number.isFinite(timestamp) || new Date(timestamp).toISOString() !== value)
|
|
325
|
+
throw responseIntegrityError();
|
|
326
|
+
return value;
|
|
327
|
+
}
|
|
328
|
+
function responseStringArray(value, maximum, allowed) {
|
|
329
|
+
const items = responseArray(value, maximum).map((item) => responseString(item, MAX_TEXT_BYTES));
|
|
330
|
+
if (new Set(items).size !== items.length || (allowed !== undefined && items.some((item) => !allowed.includes(item)))) {
|
|
331
|
+
throw responseIntegrityError();
|
|
332
|
+
}
|
|
333
|
+
return items;
|
|
334
|
+
}
|
|
335
|
+
function sameResponseValue(left, right) {
|
|
336
|
+
return stringifyBoundaryJson(cloneBoundaryJson(left, responseIntegrityError))
|
|
337
|
+
=== stringifyBoundaryJson(cloneBoundaryJson(right, responseIntegrityError));
|
|
151
338
|
}
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
339
|
+
const PROFILE_FIELDS = ['taskType', 'target', 'expected', 'constraints'];
|
|
340
|
+
const INTAKE_STATUSES = ['needs_answer', 'ready', 'exhausted'];
|
|
341
|
+
const ACTIVE_RUN_STATUSES = ['intake', 'active'];
|
|
342
|
+
const TERMINAL_RUN_STATUSES = ['completed', 'failed', 'cancelled', 'interrupted'];
|
|
343
|
+
const CAPABILITY_AVAILABILITIES = ['known-empty', 'known-nonempty', 'unknown'];
|
|
344
|
+
const CAPABILITY_RECOMMENDATION_AVAILABILITIES = ['available', 'missing', 'unknown'];
|
|
345
|
+
const COVERAGE_FIELDS = ['run', 'tool', 'command', 'file', 'approval'];
|
|
346
|
+
const COVERAGE_LEVELS = ['complete', 'best_effort', 'declared', 'unavailable'];
|
|
347
|
+
const CAPABILITY_WARNING_CODES = [
|
|
348
|
+
'CAPABILITY_CATALOG_COMPACTED',
|
|
349
|
+
'CAPABILITY_CATALOG_ITEMS_DROPPED',
|
|
350
|
+
'CAPABILITY_CATALOG_BUDGET_EXCEEDED',
|
|
351
|
+
'CAPABILITY_CATALOG_UNAVAILABLE',
|
|
352
|
+
];
|
|
353
|
+
function validateTaskProfileSchema(value, withSource = false) {
|
|
354
|
+
const object = responseObject(value, withSource ? [...PROFILE_FIELDS, 'source'] : PROFILE_FIELDS);
|
|
355
|
+
if (object.taskType !== null)
|
|
356
|
+
responseEnum(object.taskType, TASK_TYPES);
|
|
357
|
+
for (const field of ['target', 'expected', 'constraints']) {
|
|
358
|
+
if (object[field] !== null)
|
|
359
|
+
responseString(object[field], MAX_INPUT_BYTES, true);
|
|
159
360
|
}
|
|
160
|
-
|
|
361
|
+
if (withSource && object.source !== 'akinator+ledger-revisions')
|
|
362
|
+
throw responseIntegrityError();
|
|
363
|
+
return object;
|
|
161
364
|
}
|
|
162
|
-
function
|
|
163
|
-
if (
|
|
365
|
+
function validateQuestion(value) {
|
|
366
|
+
if (value === null)
|
|
367
|
+
return null;
|
|
368
|
+
const object = responseObject(value, ['id', 'prompt', 'options', 'required']);
|
|
369
|
+
responseEnum(object.id, PROFILE_FIELDS);
|
|
370
|
+
responseString(object.prompt, MAX_TEXT_BYTES);
|
|
371
|
+
if (object.options !== null)
|
|
372
|
+
responseStringArray(object.options, 100);
|
|
373
|
+
if (typeof object.required !== 'boolean')
|
|
374
|
+
throw responseIntegrityError();
|
|
375
|
+
return object;
|
|
376
|
+
}
|
|
377
|
+
function validateCapabilityWarnings(value) {
|
|
378
|
+
const warnings = responseArray(value, CAPABILITY_WARNING_CODES.length);
|
|
379
|
+
const seen = new Set();
|
|
380
|
+
for (const warning of warnings) {
|
|
381
|
+
const object = responseObject(warning, ['code', 'message']);
|
|
382
|
+
const code = responseEnum(object.code, CAPABILITY_WARNING_CODES);
|
|
383
|
+
responseString(object.message, MAX_TEXT_BYTES);
|
|
384
|
+
if (seen.has(code))
|
|
385
|
+
throw responseIntegrityError();
|
|
386
|
+
seen.add(code);
|
|
387
|
+
}
|
|
388
|
+
return warnings;
|
|
389
|
+
}
|
|
390
|
+
function validateCapabilityRecommendations(value) {
|
|
391
|
+
const recommendations = responseArray(value, 205);
|
|
392
|
+
for (const recommendation of recommendations) {
|
|
393
|
+
const object = responseObject(recommendation, ['kind', 'name', 'availability', 'reason', 'source'], ['required']);
|
|
394
|
+
responseEnum(object.kind, CAPABILITY_KINDS);
|
|
395
|
+
const name = responseString(object.name, MAX_INPUT_BYTES);
|
|
396
|
+
if (Array.from(name).length > MAX_CAPABILITY_NAME_CHARS
|
|
397
|
+
|| name.trim() !== name || UNSAFE_CAPABILITY_LABEL_CHARACTERS.test(name))
|
|
398
|
+
throw responseIntegrityError();
|
|
399
|
+
responseEnum(object.availability, CAPABILITY_RECOMMENDATION_AVAILABILITIES);
|
|
400
|
+
responseString(object.reason, MAX_TEXT_BYTES);
|
|
401
|
+
responseEnum(object.source, ['akinator_policy', 'catalog_similarity']);
|
|
402
|
+
if (Object.hasOwn(object, 'required') && typeof object.required !== 'boolean')
|
|
403
|
+
throw responseIntegrityError();
|
|
404
|
+
}
|
|
405
|
+
return recommendations;
|
|
406
|
+
}
|
|
407
|
+
function validateCapabilities(value) {
|
|
408
|
+
const object = responseObject(value, [
|
|
409
|
+
'availability', 'catalogProvided', 'availableSkillCount', 'diagnostics', 'warnings', 'recommendations',
|
|
410
|
+
]);
|
|
411
|
+
const availability = responseEnum(object.availability, CAPABILITY_AVAILABILITIES);
|
|
412
|
+
if (typeof object.catalogProvided !== 'boolean' || object.catalogProvided !== (availability !== 'unknown')) {
|
|
413
|
+
throw responseIntegrityError();
|
|
414
|
+
}
|
|
415
|
+
if (availability === 'unknown') {
|
|
416
|
+
if (object.availableSkillCount !== null)
|
|
417
|
+
throw responseIntegrityError();
|
|
418
|
+
}
|
|
419
|
+
else {
|
|
420
|
+
responseInteger(object.availableSkillCount);
|
|
421
|
+
}
|
|
422
|
+
const diagnostics = responseObject(object.diagnostics, ['received', 'accepted', 'truncated', 'dropped']);
|
|
423
|
+
for (const field of ['received', 'accepted', 'truncated', 'dropped'])
|
|
424
|
+
responseInteger(diagnostics[field]);
|
|
425
|
+
if (diagnostics.accepted > diagnostics.received
|
|
426
|
+
|| diagnostics.truncated > diagnostics.accepted)
|
|
427
|
+
throw responseIntegrityError();
|
|
428
|
+
validateCapabilityWarnings(object.warnings);
|
|
429
|
+
validateCapabilityRecommendations(object.recommendations);
|
|
430
|
+
return object;
|
|
431
|
+
}
|
|
432
|
+
function validateContextRecommendation(value) {
|
|
433
|
+
const object = responseObject(value, [
|
|
434
|
+
'code', 'message', 'evidenceEventIds', 'priority', 'untrusted', 'actionable', 'metadata',
|
|
435
|
+
]);
|
|
436
|
+
responseEnum(object.code, RECOMMENDATION_CODES);
|
|
437
|
+
responseString(object.message, MAX_TEXT_BYTES);
|
|
438
|
+
responseInteger(object.priority, 1, RECOMMENDATION_CODES.length);
|
|
439
|
+
if (object.untrusted !== true
|
|
440
|
+
|| object.actionable !== false)
|
|
441
|
+
throw responseIntegrityError();
|
|
442
|
+
responseStringArray(object.evidenceEventIds, 16);
|
|
443
|
+
const metadata = responseObject(object.metadata, ['truncated', 'referenceIds'], ['incompleteCoverageCategories']);
|
|
444
|
+
if (typeof metadata.truncated !== 'boolean')
|
|
445
|
+
throw responseIntegrityError();
|
|
446
|
+
responseStringArray(metadata.referenceIds, 16);
|
|
447
|
+
if (Object.hasOwn(metadata, 'incompleteCoverageCategories')) {
|
|
448
|
+
responseStringArray(metadata.incompleteCoverageCategories, COVERAGE_FIELDS.length, COVERAGE_FIELDS);
|
|
449
|
+
}
|
|
450
|
+
return object;
|
|
451
|
+
}
|
|
452
|
+
function validateContextRecommendations(value) {
|
|
453
|
+
const recommendations = responseArray(value, RECOMMENDATION_CODES.length);
|
|
454
|
+
const codes = new Set();
|
|
455
|
+
for (const recommendation of recommendations) {
|
|
456
|
+
const object = validateContextRecommendation(recommendation);
|
|
457
|
+
const code = object.code;
|
|
458
|
+
if (codes.has(code))
|
|
459
|
+
throw responseIntegrityError();
|
|
460
|
+
codes.add(code);
|
|
461
|
+
}
|
|
462
|
+
return recommendations;
|
|
463
|
+
}
|
|
464
|
+
function validateScoreComponentsSchema(value) {
|
|
465
|
+
const score = responseObject(value, CONTEXT_RANKING_COMPONENTS);
|
|
466
|
+
for (const field of CONTEXT_RANKING_COMPONENTS) {
|
|
467
|
+
if (typeof score[field] !== 'number' || !Number.isSafeInteger(score[field])
|
|
468
|
+
|| score[field] < -1_000_000 || score[field] > 1_000_000) {
|
|
469
|
+
throw responseIntegrityError();
|
|
470
|
+
}
|
|
471
|
+
}
|
|
472
|
+
}
|
|
473
|
+
function validateContextSchema(value) {
|
|
474
|
+
if (value === null)
|
|
475
|
+
return null;
|
|
476
|
+
const object = responseObject(value, [
|
|
477
|
+
'deliveryId', 'runId', 'throughSequence', 'taskProfileHash', 'queryHash', 'policyVersion', 'items', 'untrusted',
|
|
478
|
+
]);
|
|
479
|
+
if (object.deliveryId !== null)
|
|
480
|
+
responseIdentifier(object.deliveryId);
|
|
481
|
+
responseIdentifier(object.runId);
|
|
482
|
+
responseInteger(object.throughSequence);
|
|
483
|
+
responseHash(object.taskProfileHash);
|
|
484
|
+
responseHash(object.queryHash);
|
|
485
|
+
if (object.policyVersion !== 'context-ranking-v1+recommendations.v1' || object.untrusted !== true) {
|
|
486
|
+
throw responseIntegrityError();
|
|
487
|
+
}
|
|
488
|
+
const items = responseArray(object.items, 100);
|
|
489
|
+
const entryIds = new Set();
|
|
490
|
+
for (const value of items) {
|
|
491
|
+
const item = responseObject(value, [
|
|
492
|
+
'entryId', 'entryRevision', 'rank', 'scoreComponents', 'selectionReasons', 'content', 'untrusted',
|
|
493
|
+
], ['origin']);
|
|
494
|
+
const entryId = responseIdentifier(item.entryId);
|
|
495
|
+
if (entryIds.has(entryId))
|
|
496
|
+
throw responseIntegrityError();
|
|
497
|
+
entryIds.add(entryId);
|
|
498
|
+
responseInteger(item.entryRevision, 1);
|
|
499
|
+
responseInteger(item.rank, 1);
|
|
500
|
+
if (item.untrusted !== true)
|
|
501
|
+
throw responseIntegrityError();
|
|
502
|
+
validateScoreComponentsSchema(item.scoreComponents);
|
|
503
|
+
const selectionReasons = responseStringArray(item.selectionReasons, CONTEXT_SELECTION_REASON_ORDER.length, CONTEXT_SELECTION_REASON_ORDER);
|
|
504
|
+
if (selectionReasons.length === 0)
|
|
505
|
+
throw responseIntegrityError();
|
|
506
|
+
const content = responseObject(item.content, ['title', 'summary', 'bodyPreview', 'characterCount', 'truncated']);
|
|
507
|
+
responseString(content.title, MAX_INPUT_BYTES, true);
|
|
508
|
+
if (content.summary !== null)
|
|
509
|
+
responseString(content.summary, MAX_INPUT_BYTES, true);
|
|
510
|
+
responseString(content.bodyPreview, MAX_INPUT_BYTES, true);
|
|
511
|
+
responseInteger(content.characterCount);
|
|
512
|
+
if (typeof content.truncated !== 'boolean')
|
|
513
|
+
throw responseIntegrityError();
|
|
514
|
+
if (Object.hasOwn(item, 'origin'))
|
|
515
|
+
responseEnum(item.origin, ['project', 'ecosystem', 'global']);
|
|
516
|
+
}
|
|
517
|
+
return object;
|
|
518
|
+
}
|
|
519
|
+
function preservedEventId(value) {
|
|
520
|
+
if (typeof value !== 'string')
|
|
164
521
|
return undefined;
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
522
|
+
responseIdentifier(value);
|
|
523
|
+
return /^[A-Za-z0-9._:-]+$/u.test(value) && findSecret(value) === undefined ? value : undefined;
|
|
524
|
+
}
|
|
525
|
+
function validateAckFields(object) {
|
|
526
|
+
responseIdentifier(object.runId);
|
|
527
|
+
const acceptedThrough = responseInteger(object.acceptedThrough, 1);
|
|
528
|
+
const localSequences = responseArray(object.localSequences, 200).map((value) => responseInteger(value, 1));
|
|
529
|
+
const sourceSequences = responseArray(object.sourceSequences, 200).map((value) => value === null ? null : responseInteger(value));
|
|
530
|
+
const eventIds = responseArray(object.eventIds, 200).map(responseEventId);
|
|
531
|
+
if (new Set(eventIds).size !== eventIds.length)
|
|
532
|
+
throw responseIntegrityError();
|
|
533
|
+
if (localSequences.length === 0 || localSequences.length !== sourceSequences.length || localSequences.length !== eventIds.length
|
|
534
|
+
|| new Set(localSequences).size !== localSequences.length
|
|
535
|
+
|| localSequences.some((sequence, index) => index > 0 && sequence <= localSequences[index - 1])
|
|
536
|
+
|| localSequences.at(-1) !== acceptedThrough)
|
|
537
|
+
throw responseIntegrityError();
|
|
538
|
+
return { acceptedThrough, localSequences, sourceSequences, eventIds };
|
|
539
|
+
}
|
|
540
|
+
function expectedEventAck(value) {
|
|
541
|
+
const events = responseArray(value, 200);
|
|
542
|
+
if (events.length === 0)
|
|
543
|
+
throw responseIntegrityError();
|
|
544
|
+
const sourceSequences = [];
|
|
545
|
+
const eventIds = [];
|
|
546
|
+
for (const event of events) {
|
|
547
|
+
const object = responseObject(event, ['eventType', 'actor', 'payload'], [
|
|
548
|
+
'eventId', 'sourceEventId', 'sourceSequence', 'sourceType', 'outcome', 'occurredAt',
|
|
549
|
+
]);
|
|
550
|
+
// The gateway sanitizes event identifiers before persistence, and the CLI
|
|
551
|
+
// does not know the run workspace required to reproduce that transform.
|
|
552
|
+
// Bind the count/order/source sequence here; the response schema still
|
|
553
|
+
// requires unique, bounded event IDs.
|
|
554
|
+
eventIds.push(preservedEventId(object.eventId));
|
|
555
|
+
sourceSequences.push(Object.hasOwn(object, 'sourceSequence')
|
|
556
|
+
? responseInteger(object.sourceSequence)
|
|
557
|
+
: null);
|
|
558
|
+
}
|
|
559
|
+
return { sourceSequences, eventIds };
|
|
560
|
+
}
|
|
561
|
+
function validateExpectedAck(ack, expected, exactCardinality = true) {
|
|
562
|
+
const orderedSources = (values) => [...values]
|
|
563
|
+
.sort((left, right) => left === null ? (right === null ? 0 : -1) : right === null ? 1 : left - right);
|
|
564
|
+
const explicitIds = expected.eventIds.filter((value) => value !== undefined);
|
|
565
|
+
if (new Set(explicitIds).size !== explicitIds.length
|
|
566
|
+
|| (exactCardinality && ack.sourceSequences.length !== expected.sourceSequences.length)
|
|
567
|
+
|| (!exactCardinality && ack.sourceSequences.length < expected.sourceSequences.length)) {
|
|
568
|
+
throw responseIntegrityError();
|
|
569
|
+
}
|
|
570
|
+
if (exactCardinality
|
|
571
|
+
&& !sameResponseValue(orderedSources(ack.sourceSequences), orderedSources(expected.sourceSequences))) {
|
|
572
|
+
throw responseIntegrityError();
|
|
573
|
+
}
|
|
574
|
+
if (!exactCardinality) {
|
|
575
|
+
const remaining = [...ack.sourceSequences];
|
|
576
|
+
for (const source of expected.sourceSequences) {
|
|
577
|
+
const index = remaining.indexOf(source);
|
|
578
|
+
if (index < 0)
|
|
579
|
+
throw responseIntegrityError();
|
|
580
|
+
remaining.splice(index, 1);
|
|
581
|
+
}
|
|
582
|
+
}
|
|
583
|
+
for (let expectedIndex = 0; expectedIndex < expected.eventIds.length; expectedIndex += 1) {
|
|
584
|
+
const expectedId = expected.eventIds[expectedIndex];
|
|
585
|
+
if (expectedId === undefined)
|
|
586
|
+
continue;
|
|
587
|
+
let actualIndex = -1;
|
|
588
|
+
for (let index = 0; index < ack.eventIds.length; index += 1) {
|
|
589
|
+
if (ack.eventIds[index] === expectedId) {
|
|
590
|
+
actualIndex = index;
|
|
591
|
+
break;
|
|
592
|
+
}
|
|
593
|
+
}
|
|
594
|
+
if (actualIndex < 0 || ack.sourceSequences[actualIndex] !== expected.sourceSequences[expectedIndex]) {
|
|
595
|
+
throw responseIntegrityError();
|
|
596
|
+
}
|
|
597
|
+
}
|
|
598
|
+
}
|
|
599
|
+
function validateAppendResponse(value, binding) {
|
|
600
|
+
const object = responseObject(value, [
|
|
601
|
+
'runId', 'acceptedThrough', 'localSequences', 'sourceSequences', 'eventIds', 'runStatus', 'untrusted',
|
|
602
|
+
'requestBindingHash',
|
|
603
|
+
]);
|
|
604
|
+
validateRequestBindingHash(object, binding);
|
|
605
|
+
const ack = validateAckFields(object);
|
|
606
|
+
if (object.runId !== binding.expectedRunId)
|
|
607
|
+
throw responseIntegrityError();
|
|
608
|
+
const request = responseObject(binding.requestBody, ['apiVersion', 'events']);
|
|
609
|
+
if (request.apiVersion !== '1')
|
|
610
|
+
throw responseIntegrityError();
|
|
611
|
+
responseEnum(object.runStatus, ACTIVE_RUN_STATUSES);
|
|
612
|
+
const expected = expectedEventAck(request.events);
|
|
613
|
+
validateExpectedAck(ack, expected);
|
|
614
|
+
if (object.untrusted !== true)
|
|
615
|
+
throw responseIntegrityError();
|
|
616
|
+
return object;
|
|
617
|
+
}
|
|
618
|
+
function validateCloseResponse(value, binding) {
|
|
619
|
+
const object = responseObject(value, [
|
|
620
|
+
'runId', 'acceptedThrough', 'localSequences', 'sourceSequences', 'eventIds',
|
|
621
|
+
'status', 'runStatus', 'untrusted', 'requestBindingHash',
|
|
622
|
+
]);
|
|
623
|
+
validateRequestBindingHash(object, binding);
|
|
624
|
+
const ack = validateAckFields(object);
|
|
625
|
+
if (object.runId !== binding.expectedRunId)
|
|
626
|
+
throw responseIntegrityError();
|
|
627
|
+
const request = responseObject(binding.requestBody, ['apiVersion', 'status'], ['events']);
|
|
628
|
+
if (request.apiVersion !== '1')
|
|
629
|
+
throw responseIntegrityError();
|
|
630
|
+
if (Object.hasOwn(request, 'events')) {
|
|
631
|
+
const expected = expectedEventAck(request.events);
|
|
632
|
+
if (ack.eventIds.length !== expected.eventIds.length + 1)
|
|
633
|
+
throw responseIntegrityError();
|
|
634
|
+
validateExpectedAck(ack, expected, false);
|
|
635
|
+
}
|
|
636
|
+
else if (ack.eventIds.length !== 1) {
|
|
637
|
+
throw responseIntegrityError();
|
|
638
|
+
}
|
|
639
|
+
const status = responseEnum(object.status, TERMINAL_RUN_STATUSES);
|
|
640
|
+
if (status !== request.status || object.runStatus !== status || object.untrusted !== true)
|
|
641
|
+
throw responseIntegrityError();
|
|
642
|
+
return object;
|
|
643
|
+
}
|
|
644
|
+
function validateCoverage(value) {
|
|
645
|
+
const object = responseObject(value, COVERAGE_FIELDS);
|
|
646
|
+
for (const field of COVERAGE_FIELDS)
|
|
647
|
+
responseEnum(object[field], COVERAGE_LEVELS);
|
|
648
|
+
return object;
|
|
649
|
+
}
|
|
650
|
+
function validateProjectionSchema(value) {
|
|
651
|
+
const object = responseObject(value, [
|
|
652
|
+
'throughSequence', 'taskProfile', 'profileHash', 'evidenceState', 'unresolvedFailureEventIds',
|
|
653
|
+
'unknownOutcomeEventIds', 'latestMutationSequence', 'latestPassingVerificationSequence', 'coverage',
|
|
654
|
+
'declaredCoverage', 'intakeIncomplete', 'missingProfileFields',
|
|
655
|
+
]);
|
|
656
|
+
responseInteger(object.throughSequence);
|
|
657
|
+
validateTaskProfileSchema(object.taskProfile);
|
|
658
|
+
responseHash(object.profileHash);
|
|
659
|
+
responseEnum(object.evidenceState, ['none', 'failed', 'fresh', 'stale']);
|
|
660
|
+
responseArray(object.unresolvedFailureEventIds, 4096).forEach(responseEventId);
|
|
661
|
+
responseArray(object.unknownOutcomeEventIds, 4096).forEach(responseEventId);
|
|
662
|
+
for (const field of ['latestMutationSequence', 'latestPassingVerificationSequence']) {
|
|
663
|
+
if (object[field] !== null)
|
|
664
|
+
responseInteger(object[field], 1);
|
|
665
|
+
}
|
|
666
|
+
responseEnum(object.coverage, ['complete', 'partial']);
|
|
667
|
+
validateCoverage(object.declaredCoverage);
|
|
668
|
+
if (typeof object.intakeIncomplete !== 'boolean')
|
|
669
|
+
throw responseIntegrityError();
|
|
670
|
+
const projectionMissingFields = ['taskType', 'target', 'expected'];
|
|
671
|
+
responseStringArray(object.missingProfileFields, projectionMissingFields.length, projectionMissingFields);
|
|
672
|
+
return object;
|
|
673
|
+
}
|
|
674
|
+
function validateCapabilityGate(object, intakeNeedsAnswer, requiresMemoryReasoning) {
|
|
675
|
+
const capabilities = validateCapabilities(object.capabilities);
|
|
676
|
+
const warnings = validateCapabilityWarnings(object.warnings);
|
|
677
|
+
if (!sameResponseValue(warnings, capabilities.warnings))
|
|
678
|
+
throw responseIntegrityError();
|
|
679
|
+
validateContextRecommendations(object.recommendations);
|
|
680
|
+
const nextAction = responseEnum(object.nextAction, [
|
|
681
|
+
'proceed', 'answer_from_evidence_or_ask_user', 'required_capability_unavailable',
|
|
682
|
+
]);
|
|
683
|
+
const capabilityRecommendations = capabilities.recommendations;
|
|
684
|
+
const required = capabilityRecommendations.filter((recommendation) => (recommendation.required === true));
|
|
685
|
+
const memoryRecommendations = capabilityRecommendations.filter((recommendation) => (recommendation.name === MEMORY_REASONING_SKILL_NAME));
|
|
686
|
+
let memoryAvailability;
|
|
687
|
+
if (requiresMemoryReasoning) {
|
|
688
|
+
if (required.length !== 1 || memoryRecommendations.length !== 1)
|
|
689
|
+
throw responseIntegrityError();
|
|
690
|
+
const memory = memoryRecommendations[0];
|
|
691
|
+
if (memory.kind !== 'skill' || memory.name !== MEMORY_REASONING_SKILL_NAME
|
|
692
|
+
|| memory.source !== 'akinator_policy' || memory.required !== true)
|
|
693
|
+
throw responseIntegrityError();
|
|
694
|
+
memoryAvailability = memory.availability;
|
|
695
|
+
}
|
|
696
|
+
else if (required.length !== 0 || memoryRecommendations.length !== 0) {
|
|
697
|
+
throw responseIntegrityError();
|
|
698
|
+
}
|
|
699
|
+
const expectedAction = intakeNeedsAnswer
|
|
700
|
+
? 'answer_from_evidence_or_ask_user'
|
|
701
|
+
: requiresMemoryReasoning && memoryAvailability !== 'available'
|
|
702
|
+
? 'required_capability_unavailable'
|
|
703
|
+
: 'proceed';
|
|
704
|
+
if (nextAction !== expectedAction)
|
|
705
|
+
throw responseIntegrityError();
|
|
706
|
+
if (nextAction === 'required_capability_unavailable'
|
|
707
|
+
&& (object.context !== null || object.recommendations.length !== 0))
|
|
708
|
+
throw responseIntegrityError();
|
|
709
|
+
return nextAction;
|
|
710
|
+
}
|
|
711
|
+
function validateMemoryPolicy(value) {
|
|
712
|
+
const policy = responseObject(value, ['memoryReasoningRequired']);
|
|
713
|
+
if (typeof policy.memoryReasoningRequired !== 'boolean')
|
|
714
|
+
throw responseIntegrityError();
|
|
715
|
+
return policy.memoryReasoningRequired;
|
|
716
|
+
}
|
|
717
|
+
function validateIntakeResponse(value, binding) {
|
|
718
|
+
const object = responseObject(value, [
|
|
719
|
+
'runId', 'runStatus', 'intakeSessionId', 'intakeStatus', 'intake', 'question', 'currentQuestion',
|
|
720
|
+
'missingFields', 'recommendedTags', 'taskProfile', 'profileHash', 'context', 'untrusted',
|
|
721
|
+
'recommendations', 'capabilities', 'memoryPolicy', 'warnings', 'nextAction', 'requestBindingHash',
|
|
722
|
+
]);
|
|
723
|
+
validateRequestBindingHash(object, binding);
|
|
724
|
+
const runId = responseIdentifier(object.runId);
|
|
725
|
+
if (binding.expectedRunId !== undefined && runId !== binding.expectedRunId)
|
|
726
|
+
throw responseIntegrityError();
|
|
727
|
+
const runStatus = responseEnum(object.runStatus, ACTIVE_RUN_STATUSES);
|
|
728
|
+
const intakeSessionId = responseIdentifier(object.intakeSessionId);
|
|
729
|
+
const intakeStatus = responseEnum(object.intakeStatus, INTAKE_STATUSES);
|
|
730
|
+
const intake = responseObject(object.intake, ['status', 'sessionId', 'question']);
|
|
731
|
+
const question = validateQuestion(object.question);
|
|
732
|
+
const currentQuestion = validateQuestion(object.currentQuestion);
|
|
733
|
+
if (intake.status !== intakeStatus || intake.sessionId !== intakeSessionId
|
|
734
|
+
|| !sameResponseValue(intake.question, question) || !sameResponseValue(currentQuestion, question)) {
|
|
735
|
+
throw responseIntegrityError();
|
|
736
|
+
}
|
|
737
|
+
validateTaskProfileSchema(object.taskProfile);
|
|
738
|
+
const requiredProfileFields = ['taskType', 'target', 'expected'];
|
|
739
|
+
responseStringArray(object.missingFields, requiredProfileFields.length, requiredProfileFields);
|
|
740
|
+
responseStringArray(object.recommendedTags, 10);
|
|
741
|
+
const needsAnswer = intakeStatus === 'needs_answer';
|
|
742
|
+
if (needsAnswer) {
|
|
743
|
+
if (runStatus !== 'intake' || question === null || object.profileHash !== null || object.context !== null) {
|
|
744
|
+
throw responseIntegrityError();
|
|
745
|
+
}
|
|
746
|
+
if (object.recommendations.length !== 0)
|
|
747
|
+
throw responseIntegrityError();
|
|
748
|
+
}
|
|
749
|
+
else {
|
|
750
|
+
if (runStatus !== 'active' || question !== null)
|
|
751
|
+
throw responseIntegrityError();
|
|
752
|
+
responseHash(object.profileHash);
|
|
753
|
+
}
|
|
754
|
+
if (object.untrusted !== true)
|
|
755
|
+
throw responseIntegrityError();
|
|
756
|
+
const context = needsAnswer ? null : validateContextSchema(object.context);
|
|
757
|
+
if (context !== null && (context.runId !== runId || context.taskProfileHash !== object.profileHash)) {
|
|
758
|
+
throw responseIntegrityError();
|
|
759
|
+
}
|
|
760
|
+
const requiresMemoryReasoning = validateMemoryPolicy(object.memoryPolicy);
|
|
761
|
+
const nextAction = validateCapabilityGate(object, needsAnswer, requiresMemoryReasoning);
|
|
762
|
+
if (!needsAnswer) {
|
|
763
|
+
if (nextAction === 'proceed' && context === null)
|
|
764
|
+
throw responseIntegrityError();
|
|
765
|
+
}
|
|
766
|
+
return object;
|
|
767
|
+
}
|
|
768
|
+
function checkpointExpectedAck(body) {
|
|
769
|
+
return Object.hasOwn(body, 'events') ? expectedEventAck(body.events) : undefined;
|
|
770
|
+
}
|
|
771
|
+
function validateCheckpointResponse(value, binding) {
|
|
772
|
+
const object = responseObject(value, [
|
|
773
|
+
'runId', 'acceptedThrough', 'localSequences', 'sourceSequences', 'eventIds', 'runStatus', 'intakeStatus',
|
|
774
|
+
'taskProfile', 'profileHash', 'projection', 'recommendations', 'characterBudget', 'context', 'untrusted',
|
|
775
|
+
'capabilities', 'memoryPolicy', 'warnings', 'nextAction', 'requestBindingHash',
|
|
776
|
+
]);
|
|
777
|
+
validateRequestBindingHash(object, binding);
|
|
778
|
+
const ack = validateAckFields(object);
|
|
779
|
+
const expectedAck = checkpointExpectedAck(binding.requestBody);
|
|
780
|
+
const runId = responseIdentifier(object.runId);
|
|
781
|
+
if (runId !== binding.expectedRunId)
|
|
782
|
+
throw responseIntegrityError();
|
|
783
|
+
if (expectedAck !== undefined)
|
|
784
|
+
validateExpectedAck(ack, expectedAck, false);
|
|
785
|
+
if (object.runStatus !== 'active')
|
|
786
|
+
throw responseIntegrityError();
|
|
787
|
+
responseEnum(object.intakeStatus, ['ready', 'exhausted']);
|
|
788
|
+
validateTaskProfileSchema(object.taskProfile, true);
|
|
789
|
+
responseHash(object.profileHash);
|
|
790
|
+
validateProjectionSchema(object.projection);
|
|
791
|
+
responseInteger(object.characterBudget, 1, 100_000);
|
|
792
|
+
if (object.untrusted !== true)
|
|
793
|
+
throw responseIntegrityError();
|
|
794
|
+
const context = validateContextSchema(object.context);
|
|
795
|
+
if (context !== null && (context.runId !== runId || context.taskProfileHash !== object.profileHash)) {
|
|
796
|
+
throw responseIntegrityError();
|
|
797
|
+
}
|
|
798
|
+
const requiresMemoryReasoning = validateMemoryPolicy(object.memoryPolicy);
|
|
799
|
+
const nextAction = validateCapabilityGate(object, false, requiresMemoryReasoning);
|
|
800
|
+
if (nextAction === 'proceed') {
|
|
801
|
+
if (context === null)
|
|
802
|
+
throw responseIntegrityError();
|
|
803
|
+
}
|
|
804
|
+
return object;
|
|
805
|
+
}
|
|
806
|
+
function validateFeedbackRecord(category, value) {
|
|
807
|
+
const common = ['feedbackId', 'workspace', 'runId', 'actor', 'idempotencyKeyHash', 'createdAt'];
|
|
808
|
+
const nullableText = (candidate, maximumBytes = 4 * 1024) => {
|
|
809
|
+
if (candidate !== null)
|
|
810
|
+
responseString(candidate, maximumBytes);
|
|
811
|
+
};
|
|
812
|
+
if (category === 'context') {
|
|
813
|
+
const object = responseObject(value, [...common, 'deliveryId', 'entryId', 'verdict', 'comment']);
|
|
814
|
+
for (const field of ['feedbackId', 'workspace', 'runId', 'actor', 'deliveryId', 'entryId'])
|
|
815
|
+
responseIdentifier(object[field]);
|
|
816
|
+
responseEnum(object.verdict, ['helpful', 'irrelevant', 'stale', 'conflicting']);
|
|
817
|
+
nullableText(object.comment);
|
|
818
|
+
responseHash(object.idempotencyKeyHash);
|
|
819
|
+
responseTimestamp(object.createdAt);
|
|
820
|
+
return object;
|
|
821
|
+
}
|
|
822
|
+
if (category === 'intake') {
|
|
823
|
+
const object = responseObject(value, [...common, 'sessionId', 'questionId', 'profileField', 'verdict', 'comment']);
|
|
824
|
+
for (const field of ['feedbackId', 'workspace', 'runId', 'actor', 'sessionId'])
|
|
825
|
+
responseIdentifier(object[field]);
|
|
826
|
+
for (const field of ['questionId', 'profileField']) {
|
|
827
|
+
if (object[field] !== null)
|
|
828
|
+
responseEnum(object[field], PROFILE_FIELDS);
|
|
829
|
+
}
|
|
830
|
+
if ((object.questionId === null) === (object.profileField === null))
|
|
831
|
+
throw responseIntegrityError();
|
|
832
|
+
responseEnum(object.verdict, ['helpful', 'unnecessary', 'corrected']);
|
|
833
|
+
nullableText(object.comment);
|
|
834
|
+
responseHash(object.idempotencyKeyHash);
|
|
835
|
+
responseTimestamp(object.createdAt);
|
|
836
|
+
return object;
|
|
837
|
+
}
|
|
838
|
+
const object = responseObject(value, [
|
|
839
|
+
...common, 'outcome', 'recommendationCode', 'recommendationVerdict', 'rating', 'comment',
|
|
840
|
+
]);
|
|
841
|
+
for (const field of ['feedbackId', 'workspace', 'runId', 'actor'])
|
|
842
|
+
responseIdentifier(object[field]);
|
|
843
|
+
nullableText(object.outcome);
|
|
844
|
+
if (object.recommendationCode !== null) {
|
|
845
|
+
const recommendationCode = responseString(object.recommendationCode, MAX_INPUT_BYTES);
|
|
846
|
+
if (recommendationCode.length > MAX_ID_BYTES)
|
|
847
|
+
throw responseIntegrityError();
|
|
848
|
+
}
|
|
849
|
+
nullableText(object.comment);
|
|
850
|
+
if (object.recommendationVerdict !== null)
|
|
851
|
+
responseEnum(object.recommendationVerdict, ['accepted', 'dismissed', 'resolved']);
|
|
852
|
+
if ((object.recommendationCode === null) !== (object.recommendationVerdict === null))
|
|
853
|
+
throw responseIntegrityError();
|
|
854
|
+
if (object.rating !== null)
|
|
855
|
+
responseInteger(object.rating, 1, 5);
|
|
856
|
+
if (object.outcome === null && object.recommendationCode === null && object.rating === null)
|
|
857
|
+
throw responseIntegrityError();
|
|
858
|
+
responseHash(object.idempotencyKeyHash);
|
|
859
|
+
responseTimestamp(object.createdAt);
|
|
860
|
+
return object;
|
|
861
|
+
}
|
|
862
|
+
function validateFeedbackBinding(category, record, binding) {
|
|
863
|
+
if (binding.requestBody.category !== category
|
|
864
|
+
|| binding.requestBody.feedbackId !== record.feedbackId
|
|
865
|
+
|| record.runId !== binding.expectedRunId
|
|
866
|
+
|| record.idempotencyKeyHash !== createHash('sha256').update(binding.idempotencyKey, 'utf8').digest('hex')) {
|
|
867
|
+
throw responseIntegrityError();
|
|
868
|
+
}
|
|
869
|
+
}
|
|
870
|
+
function validateFeedbackResponse(value, binding) {
|
|
871
|
+
const object = responseObject(value, ['category', 'record', 'untrusted', 'requestBindingHash']);
|
|
872
|
+
validateRequestBindingHash(object, binding);
|
|
873
|
+
const category = responseEnum(object.category, ['context', 'recommendation', 'intake', 'run']);
|
|
874
|
+
const record = validateFeedbackRecord(category, object.record);
|
|
875
|
+
validateFeedbackBinding(category, record, binding);
|
|
876
|
+
if (object.untrusted !== true)
|
|
877
|
+
throw responseIntegrityError();
|
|
878
|
+
return object;
|
|
879
|
+
}
|
|
880
|
+
function validateAgentResponse(operation, value, binding) {
|
|
881
|
+
const cloned = cloneBoundaryJson(value, responseIntegrityError);
|
|
882
|
+
if (Buffer.byteLength(stringifyBoundaryJson(cloned), 'utf8') > MAX_INPUT_BYTES)
|
|
883
|
+
throw responseIntegrityError();
|
|
884
|
+
switch (operation) {
|
|
885
|
+
case 'agent.open': return validateIntakeResponse(cloned, binding);
|
|
886
|
+
case 'agent.answer': return validateIntakeResponse(cloned, binding);
|
|
887
|
+
case 'agent.events': return validateAppendResponse(cloned, binding);
|
|
888
|
+
case 'agent.checkpoint': return validateCheckpointResponse(cloned, binding);
|
|
889
|
+
case 'agent.close': return validateCloseResponse(cloned, binding);
|
|
890
|
+
case 'agent.feedback': return validateFeedbackResponse(cloned, binding);
|
|
891
|
+
default: throw responseIntegrityError();
|
|
892
|
+
}
|
|
893
|
+
}
|
|
894
|
+
function responseStatus(operation, data) {
|
|
895
|
+
if (data.nextAction === 'required_capability_unavailable')
|
|
896
|
+
return data.nextAction;
|
|
897
|
+
switch (operation) {
|
|
898
|
+
case 'agent.open':
|
|
899
|
+
case 'agent.answer':
|
|
900
|
+
case 'agent.checkpoint': return data.intakeStatus;
|
|
901
|
+
case 'agent.events': return data.runStatus;
|
|
902
|
+
case 'agent.close': return data.status;
|
|
903
|
+
case 'agent.feedback': return 'recorded';
|
|
904
|
+
default: throw responseIntegrityError();
|
|
905
|
+
}
|
|
906
|
+
}
|
|
907
|
+
function responseQuestion(operation, data) {
|
|
908
|
+
if (operation !== 'agent.open' && operation !== 'agent.answer')
|
|
168
909
|
return undefined;
|
|
169
|
-
const
|
|
170
|
-
return
|
|
910
|
+
const question = data.currentQuestion;
|
|
911
|
+
return question === null ? undefined : question.id;
|
|
912
|
+
}
|
|
913
|
+
function requiredCapabilitySummary(data) {
|
|
914
|
+
const capabilities = data.capabilities;
|
|
915
|
+
const recommendations = capabilities.recommendations;
|
|
916
|
+
const labels = recommendations
|
|
917
|
+
.filter((recommendation) => recommendation.required === true && recommendation.availability !== 'available')
|
|
918
|
+
.map((recommendation) => `${recommendation.name} (${recommendation.availability})`);
|
|
919
|
+
if (labels.length === 0)
|
|
920
|
+
throw responseIntegrityError();
|
|
921
|
+
return `; required capabilities unavailable: ${labels.join(', ')}`;
|
|
171
922
|
}
|
|
172
923
|
function humanSummary(operation, data) {
|
|
173
|
-
const question = responseQuestion(data);
|
|
174
|
-
const status = responseStatus(data);
|
|
175
|
-
const context =
|
|
176
|
-
|
|
177
|
-
&& data.context !== undefined
|
|
178
|
-
? '; initial context available'
|
|
179
|
-
: '';
|
|
924
|
+
const question = responseQuestion(operation, data);
|
|
925
|
+
const status = responseStatus(operation, data);
|
|
926
|
+
const context = data.context !== null && data.context !== undefined ? '; initial context available' : '';
|
|
927
|
+
const required = status === 'required_capability_unavailable' ? requiredCapabilitySummary(data) : '';
|
|
180
928
|
return question === undefined
|
|
181
|
-
? `Kiokuko ${operation}: ${status}${context}`
|
|
182
|
-
: `Kiokuko ${operation}: ${status} (current question ${question})${context}`;
|
|
929
|
+
? `Kiokuko ${operation}: ${status}${required}${context}`
|
|
930
|
+
: `Kiokuko ${operation}: ${status} (current question ${question})${required}${context}`;
|
|
183
931
|
}
|
|
184
932
|
function emitResult(json, operation, data) {
|
|
185
|
-
if (json)
|
|
186
|
-
|
|
933
|
+
if (json) {
|
|
934
|
+
const envelope = cloneBoundaryJson(successEnvelope(operation, data), responseIntegrityError);
|
|
935
|
+
process.stdout.write(`${stringifyBoundaryJson(envelope)}\n`);
|
|
936
|
+
}
|
|
187
937
|
else
|
|
188
938
|
process.stdout.write(`${humanSummary(operation, data)}\n`);
|
|
189
939
|
}
|
|
@@ -197,12 +947,17 @@ export function registerAgentCommand(cli, dependencies = {}) {
|
|
|
197
947
|
.option('--client-version <version>')
|
|
198
948
|
.option('--session-id <id>')
|
|
199
949
|
.option('--capture-profile <profile>', 'Capture profile: minimal, standard, or full', 'standard')
|
|
950
|
+
.option('--capabilities-json <file|->', 'Complete local capability catalog as a JSON array')
|
|
951
|
+
.option('--idempotency-key <key>', 'Reuse the same key only to retry this exact request')
|
|
200
952
|
.option('--json')
|
|
201
953
|
.action(async (options) => {
|
|
202
954
|
const workspace = boundedString(options.workspace, MAX_TEXT_BYTES);
|
|
203
955
|
const clientKind = boundedId(options.client);
|
|
204
956
|
const task = boundedString(options.task, MAX_TEXT_BYTES);
|
|
205
957
|
const profile = captureProfile(options.captureProfile);
|
|
958
|
+
const capabilities = options.capabilitiesJson === undefined
|
|
959
|
+
? undefined
|
|
960
|
+
: await readCapabilityCatalog(dependencies, options.capabilitiesJson);
|
|
206
961
|
const client = {
|
|
207
962
|
kind: clientKind,
|
|
208
963
|
...(options.clientVersion === undefined ? {} : { version: boundedId(options.clientVersion) }),
|
|
@@ -226,13 +981,14 @@ export function registerAgentCommand(cli, dependencies = {}) {
|
|
|
226
981
|
approval: 'unavailable',
|
|
227
982
|
},
|
|
228
983
|
metadata: {},
|
|
984
|
+
...(capabilities === undefined ? {} : { capabilities }),
|
|
229
985
|
};
|
|
230
986
|
const data = await sendRequest(dependencies, {
|
|
231
987
|
method: 'POST',
|
|
232
988
|
path: '/api/v1/agent/runs',
|
|
233
989
|
operation: 'agent.open',
|
|
234
990
|
body,
|
|
235
|
-
idempotencyKey:
|
|
991
|
+
idempotencyKey: requestIdempotencyKey(options.idempotencyKey, dependencies),
|
|
236
992
|
});
|
|
237
993
|
emitResult(options.json, 'agent.open', data);
|
|
238
994
|
});
|
|
@@ -241,16 +997,26 @@ export function registerAgentCommand(cli, dependencies = {}) {
|
|
|
241
997
|
.argument('<run-id>')
|
|
242
998
|
.requiredOption('--question-id <id>')
|
|
243
999
|
.requiredOption('--value <answer>')
|
|
1000
|
+
.option('--capabilities-json <file|->', 'Same complete local capability catalog supplied to agent open')
|
|
1001
|
+
.option('--idempotency-key <key>', 'Reuse the same key only to retry this exact request')
|
|
244
1002
|
.option('--json')
|
|
245
1003
|
.action(async (runId, options) => {
|
|
246
1004
|
const questionId = boundedId(options.questionId);
|
|
247
1005
|
const value = boundedString(options.value, MAX_TEXT_BYTES);
|
|
1006
|
+
const capabilities = options.capabilitiesJson === undefined
|
|
1007
|
+
? undefined
|
|
1008
|
+
: await readCapabilityCatalog(dependencies, options.capabilitiesJson);
|
|
248
1009
|
const data = await sendRequest(dependencies, {
|
|
249
1010
|
method: 'POST',
|
|
250
1011
|
path: runPath(runId, 'intake/answers'),
|
|
251
1012
|
operation: 'agent.answer',
|
|
252
|
-
body: {
|
|
253
|
-
|
|
1013
|
+
body: {
|
|
1014
|
+
apiVersion: '1',
|
|
1015
|
+
questionId,
|
|
1016
|
+
value,
|
|
1017
|
+
...(capabilities === undefined ? {} : { capabilities }),
|
|
1018
|
+
},
|
|
1019
|
+
idempotencyKey: requestIdempotencyKey(options.idempotencyKey, dependencies),
|
|
254
1020
|
});
|
|
255
1021
|
emitResult(options.json, 'agent.answer', data);
|
|
256
1022
|
});
|
|
@@ -260,19 +1026,28 @@ export function registerAgentCommand(cli, dependencies = {}) {
|
|
|
260
1026
|
['close', 'agent.close', 'close'],
|
|
261
1027
|
['feedback', 'agent.feedback', 'feedback'],
|
|
262
1028
|
]) {
|
|
263
|
-
agent.command(name)
|
|
1029
|
+
const command = agent.command(name)
|
|
264
1030
|
.description(`Send an ${name} request for an agent run`)
|
|
265
1031
|
.argument('<run-id>')
|
|
266
1032
|
.requiredOption('--input-json <file|->')
|
|
267
|
-
.option('--json')
|
|
268
|
-
|
|
1033
|
+
.option('--json');
|
|
1034
|
+
if (name === 'checkpoint') {
|
|
1035
|
+
command.option('--capabilities-json <file|->', 'Same complete local capability catalog supplied to agent open');
|
|
1036
|
+
}
|
|
1037
|
+
command.action(async (runId, options) => {
|
|
269
1038
|
const input = await readInput(dependencies, options.inputJson);
|
|
270
1039
|
const request = bodyAndKey(input, dependencies);
|
|
1040
|
+
const capabilities = name === 'checkpoint' && options.capabilitiesJson !== undefined
|
|
1041
|
+
? await readCapabilityCatalog(dependencies, options.capabilitiesJson)
|
|
1042
|
+
: undefined;
|
|
1043
|
+
if (capabilities !== undefined && Object.prototype.hasOwnProperty.call(request.body, 'capabilities')) {
|
|
1044
|
+
throw validationError();
|
|
1045
|
+
}
|
|
271
1046
|
const data = await sendRequest(dependencies, {
|
|
272
1047
|
method: 'POST',
|
|
273
1048
|
path: runPath(runId, suffix),
|
|
274
1049
|
operation,
|
|
275
|
-
body: request.body,
|
|
1050
|
+
body: capabilities === undefined ? request.body : { ...request.body, capabilities },
|
|
276
1051
|
idempotencyKey: request.idempotencyKey,
|
|
277
1052
|
});
|
|
278
1053
|
emitResult(options.json, operation, data);
|