@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/web/server.js
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import { randomBytes } from 'node:crypto';
|
|
2
2
|
import { KiokukoError } from '../errors.js';
|
|
3
|
+
import { rollbackFailedTransaction } from '../db/transaction.js';
|
|
3
4
|
import { readEntry, updateCandidateEntry } from '../memory/entries.js';
|
|
4
5
|
import { searchEntries } from '../memory/retrieval.js';
|
|
5
|
-
import { ENTRY_KINDS, ENTRY_STATUSES, requireWorkspace } from '../serialization/validate.js';
|
|
6
|
+
import { compareCanonicalStrings, ENTRY_KINDS, ENTRY_STATUSES, requireWorkspace } from '../serialization/validate.js';
|
|
6
7
|
import { AgentGatewayService } from '../gateway/agent-service.js';
|
|
7
8
|
import { ContextBroker } from '../context/broker.js';
|
|
8
9
|
import { listContextFeedback, listIntakeFeedback, listRunFeedback } from '../context/feedback.js';
|
|
@@ -11,11 +12,28 @@ import { readAkinatorSession, readRunIntakeLink } from '../akinator/store.js';
|
|
|
11
12
|
import { startHttpServer } from '../server/http.js';
|
|
12
13
|
import { createAgentV1Handler } from '../server/agent-application.js';
|
|
13
14
|
import { WEB_HTML } from './ui.js';
|
|
14
|
-
import { curateMemoryCandidates, globalizeCuratorCandidate } from '../memory/curator.js';
|
|
15
|
+
import { curateMemoryCandidates, curatorFacets, globalizeCuratorCandidate } from '../memory/curator.js';
|
|
16
|
+
import { MEMORY_CLASSES } from '../memory/structured-memory.js';
|
|
17
|
+
import { GLOBAL_WORKSPACE } from '../memory/workspaces.js';
|
|
18
|
+
import { recallScopedMemory } from '../memory/scoped-memory.js';
|
|
19
|
+
import { documentsFromSkillSnapshot } from '../skills/import-preparation.js';
|
|
20
|
+
import { readSkillDiscoveryConfig } from '../skills/config.js';
|
|
21
|
+
import { GitHubSkillSourceFetcher } from '../skills/source/github-fetcher.js';
|
|
22
|
+
import { SkillSourceError } from '../skills/source/errors.js';
|
|
23
|
+
import { externalSkillRequirement, externalSkillSourceFetchRequest, listExternalSkills, listExternalSkillsPage, markExternalSkillRefreshFailure, readExternalSkill, refreshExternalSkillSnapshot, setExternalSkillState } from '../skills/store.js';
|
|
24
|
+
import { createSkillRegistryProvider } from '../skills/find.js';
|
|
25
|
+
import { parseStrictJson } from '../setup/strict-json.js';
|
|
26
|
+
import { fetchMaterializableSkillSnapshot } from '../skills/materialization-service.js';
|
|
15
27
|
const DEFAULT_HOST = '127.0.0.1';
|
|
16
28
|
const DEFAULT_PORT = 4173;
|
|
17
29
|
const MAX_BODY_BYTES = 2 * 1024 * 1024;
|
|
18
30
|
const MAX_WEB_ENTRIES = 200;
|
|
31
|
+
function hasUtf8Bom(bytes) {
|
|
32
|
+
return bytes.byteLength >= 3 && bytes[0] === 0xef && bytes[1] === 0xbb && bytes[2] === 0xbf;
|
|
33
|
+
}
|
|
34
|
+
function isInvalidUtf8EncodingError(error) {
|
|
35
|
+
return error instanceof TypeError && 'code' in error && error.code === 'ERR_ENCODING_INVALID_ENCODED_DATA';
|
|
36
|
+
}
|
|
19
37
|
function jsonResponse(response, status, value) {
|
|
20
38
|
const body = JSON.stringify(value);
|
|
21
39
|
response.writeHead(status, {
|
|
@@ -48,20 +66,22 @@ function cookieValue(request, name) {
|
|
|
48
66
|
}
|
|
49
67
|
return undefined;
|
|
50
68
|
}
|
|
51
|
-
function
|
|
52
|
-
if (
|
|
53
|
-
throw new KiokukoError('AUTHENTICATION_ERROR', '
|
|
69
|
+
function requireTrustedWebOrigin(request, trustedOrigin) {
|
|
70
|
+
if (trustedOrigin === undefined) {
|
|
71
|
+
throw new KiokukoError('AUTHENTICATION_ERROR', 'Origin is invalid');
|
|
72
|
+
}
|
|
73
|
+
const expectedHost = new URL(trustedOrigin).host;
|
|
74
|
+
if (request.headers.host !== expectedHost) {
|
|
75
|
+
throw new KiokukoError('AUTHENTICATION_ERROR', 'Origin is invalid');
|
|
54
76
|
}
|
|
55
77
|
const origin = request.headers.origin;
|
|
56
|
-
|
|
57
|
-
const expectedOrigin = host === undefined ? undefined : `http://${host}`;
|
|
58
|
-
if (origin !== undefined && (expectedOrigin === undefined || origin !== expectedOrigin)) {
|
|
78
|
+
if (origin !== undefined && origin !== trustedOrigin) {
|
|
59
79
|
throw new KiokukoError('AUTHENTICATION_ERROR', 'Origin is invalid');
|
|
60
80
|
}
|
|
61
81
|
const referer = request.headers.referer;
|
|
62
82
|
if (referer !== undefined) {
|
|
63
83
|
try {
|
|
64
|
-
if (
|
|
84
|
+
if (new URL(referer).origin !== trustedOrigin)
|
|
65
85
|
throw new Error('origin');
|
|
66
86
|
}
|
|
67
87
|
catch {
|
|
@@ -69,6 +89,11 @@ function requireUiSession(request, sessionToken) {
|
|
|
69
89
|
}
|
|
70
90
|
}
|
|
71
91
|
}
|
|
92
|
+
function requireUiSession(request, sessionToken) {
|
|
93
|
+
if (cookieValue(request, UI_SESSION_COOKIE) !== sessionToken) {
|
|
94
|
+
throw new KiokukoError('AUTHENTICATION_ERROR', 'Authorization is invalid');
|
|
95
|
+
}
|
|
96
|
+
}
|
|
72
97
|
function errorStatus(error) {
|
|
73
98
|
if (!(error instanceof KiokukoError))
|
|
74
99
|
return 500;
|
|
@@ -80,17 +105,48 @@ function errorStatus(error) {
|
|
|
80
105
|
return 404;
|
|
81
106
|
if (error.code === 'CONFLICT')
|
|
82
107
|
return 409;
|
|
108
|
+
if (error.code === 'BACKPRESSURE')
|
|
109
|
+
return 429;
|
|
83
110
|
if (error.code === 'SECURITY_REJECTION')
|
|
84
111
|
return 422;
|
|
112
|
+
if (error.code === 'SERVICE_UNAVAILABLE' || error.code === 'DATABASE_ERROR')
|
|
113
|
+
return 503;
|
|
114
|
+
if (error.code === 'NOT_IMPLEMENTED')
|
|
115
|
+
return 501;
|
|
85
116
|
return 500;
|
|
86
117
|
}
|
|
118
|
+
function boundedRetryAfterSeconds(value) {
|
|
119
|
+
if (typeof value !== 'number' || !Number.isFinite(value))
|
|
120
|
+
return 1;
|
|
121
|
+
return Math.min(60, Math.max(1, Math.trunc(value)));
|
|
122
|
+
}
|
|
87
123
|
function errorBody(error) {
|
|
88
|
-
if (error instanceof KiokukoError) {
|
|
89
|
-
|
|
90
|
-
return { error: { code: error.code, message: 'Authorization is invalid', details: {} } };
|
|
91
|
-
return { error: { code: error.code, message: error.message, details: error.details } };
|
|
124
|
+
if (!(error instanceof KiokukoError)) {
|
|
125
|
+
return { error: { code: 'INTEGRITY_ERROR', message: 'Unexpected server error', details: {} } };
|
|
92
126
|
}
|
|
93
|
-
|
|
127
|
+
if (error.code === 'AUTHENTICATION_ERROR')
|
|
128
|
+
return { error: { code: error.code, message: 'Authorization is invalid', details: {} } };
|
|
129
|
+
if (error.code === 'VALIDATION_ERROR' || error.code === 'USAGE_ERROR')
|
|
130
|
+
return { error: { code: error.code, message: 'Request is invalid', details: {} } };
|
|
131
|
+
if (error.code === 'NOT_FOUND')
|
|
132
|
+
return { error: { code: error.code, message: 'Resource not found', details: {} } };
|
|
133
|
+
if (error.code === 'CONFLICT')
|
|
134
|
+
return { error: { code: error.code, message: 'Request conflicts with current state', details: {} } };
|
|
135
|
+
if (error.code === 'BACKPRESSURE')
|
|
136
|
+
return { error: { code: error.code, message: 'Service is busy', details: { retryAfterSeconds: boundedRetryAfterSeconds(error.details.retryAfterSeconds) } } };
|
|
137
|
+
if (error.code === 'DATABASE_ERROR')
|
|
138
|
+
return { error: { code: error.code, message: 'Database unavailable', details: {} } };
|
|
139
|
+
if (error.code === 'SERVICE_UNAVAILABLE')
|
|
140
|
+
return { error: { code: error.code, message: 'Service unavailable', details: {} } };
|
|
141
|
+
if (error.code === 'SECURITY_REJECTION')
|
|
142
|
+
return { error: { code: error.code, message: 'Request rejected', details: {} } };
|
|
143
|
+
if (error.code === 'INTEGRITY_ERROR')
|
|
144
|
+
return { error: { code: error.code, message: 'Internal integrity error', details: {} } };
|
|
145
|
+
if (error.code === 'PARTIAL_FAILURE')
|
|
146
|
+
return { error: { code: error.code, message: 'Operation partially failed', details: {} } };
|
|
147
|
+
if (error.code === 'NOT_IMPLEMENTED')
|
|
148
|
+
return { error: { code: error.code, message: 'Operation is not implemented', details: {} } };
|
|
149
|
+
return { error: { code: 'INTEGRITY_ERROR', message: 'Unexpected server error', details: {} } };
|
|
94
150
|
}
|
|
95
151
|
function asRecord(value, label) {
|
|
96
152
|
if (typeof value !== 'object' || value === null || Array.isArray(value)) {
|
|
@@ -122,10 +178,104 @@ function limitQuery(value) {
|
|
|
122
178
|
}
|
|
123
179
|
return limit;
|
|
124
180
|
}
|
|
181
|
+
function invalidExternalSkillCursor() {
|
|
182
|
+
throw new KiokukoError('VALIDATION_ERROR', 'cursor is invalid');
|
|
183
|
+
}
|
|
184
|
+
function externalSkillCursor(record, listVersion, state) {
|
|
185
|
+
const value = [
|
|
186
|
+
1,
|
|
187
|
+
listVersion,
|
|
188
|
+
state ?? null,
|
|
189
|
+
record.sourceLocator,
|
|
190
|
+
record.slug,
|
|
191
|
+
record.provider,
|
|
192
|
+
record.skillId,
|
|
193
|
+
];
|
|
194
|
+
return Buffer.from(JSON.stringify(value), 'utf8').toString('base64url');
|
|
195
|
+
}
|
|
196
|
+
function externalSkillCursorQuery(url) {
|
|
197
|
+
const values = url.searchParams.getAll('cursor');
|
|
198
|
+
if (values.length === 0)
|
|
199
|
+
return undefined;
|
|
200
|
+
if (values.length !== 1 || !/^[A-Za-z0-9_-]{1,4096}$/u.test(values[0]))
|
|
201
|
+
invalidExternalSkillCursor();
|
|
202
|
+
let decoded;
|
|
203
|
+
let parsed;
|
|
204
|
+
try {
|
|
205
|
+
decoded = Buffer.from(values[0], 'base64url');
|
|
206
|
+
if (decoded.toString('base64url') !== values[0] || decoded.byteLength > 3_000 || hasUtf8Bom(decoded))
|
|
207
|
+
invalidExternalSkillCursor();
|
|
208
|
+
parsed = JSON.parse(new TextDecoder('utf-8', { fatal: true, ignoreBOM: true }).decode(decoded));
|
|
209
|
+
}
|
|
210
|
+
catch (error) {
|
|
211
|
+
if (error instanceof KiokukoError)
|
|
212
|
+
throw error;
|
|
213
|
+
if (error instanceof SyntaxError || isInvalidUtf8EncodingError(error))
|
|
214
|
+
invalidExternalSkillCursor();
|
|
215
|
+
throw error;
|
|
216
|
+
}
|
|
217
|
+
if (!Array.isArray(parsed) || parsed.length !== 7 || parsed[0] !== 1
|
|
218
|
+
|| typeof parsed[1] !== 'number' || !Number.isSafeInteger(parsed[1]) || parsed[1] < 0
|
|
219
|
+
|| parsed[2] !== null && (typeof parsed[2] !== 'string'
|
|
220
|
+
|| !['discovered', 'imported', 'blocked', 'stale', 'disabled'].includes(parsed[2]))
|
|
221
|
+
|| parsed.slice(3).some((value) => typeof value !== 'string' || value.length < 1 || value.length > 2_000 || /\p{Cc}/u.test(value))) {
|
|
222
|
+
invalidExternalSkillCursor();
|
|
223
|
+
}
|
|
224
|
+
return parsed;
|
|
225
|
+
}
|
|
226
|
+
function externalSkillListItem(record) {
|
|
227
|
+
const metadata = record.metadata;
|
|
228
|
+
const documents = record.sourceCommit === null ? 0 : metadata.documents;
|
|
229
|
+
const technology = record.sourceCommit === null ? null : metadata.technology;
|
|
230
|
+
if (typeof documents !== 'number' || !Number.isSafeInteger(documents) || documents < 0 || documents > 64
|
|
231
|
+
|| technology !== null && (typeof technology !== 'string' || technology.length < 1 || technology.length > 500)) {
|
|
232
|
+
throw new KiokukoError('INTEGRITY_ERROR', 'External skill list metadata is invalid');
|
|
233
|
+
}
|
|
234
|
+
return { ...record, metadata: { documents, technology } };
|
|
235
|
+
}
|
|
236
|
+
function listQuery(url, name, max = 50) {
|
|
237
|
+
const values = url.searchParams.getAll(name).map((value) => value.trim()).filter(Boolean);
|
|
238
|
+
if (values.length > max || values.some((value) => value.length > 300))
|
|
239
|
+
throw new KiokukoError('VALIDATION_ERROR', `${name} contains too many or too-large values`);
|
|
240
|
+
return [...new Set(values)];
|
|
241
|
+
}
|
|
242
|
+
function requireExactJsonMediaType(request) {
|
|
243
|
+
const contentTypes = [];
|
|
244
|
+
for (let index = 0; index < request.rawHeaders.length; index += 2) {
|
|
245
|
+
if (request.rawHeaders[index]?.toLowerCase() === 'content-type') {
|
|
246
|
+
contentTypes.push(request.rawHeaders[index + 1] ?? '');
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
if (contentTypes.length !== 1 || contentTypes[0].trim().toLowerCase() !== 'application/json') {
|
|
250
|
+
request.resume();
|
|
251
|
+
throw new KiokukoError('VALIDATION_ERROR', 'Content-Type must be exactly application/json');
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
function decodeJsonBody(bytes) {
|
|
255
|
+
if (hasUtf8Bom(bytes)) {
|
|
256
|
+
throw new KiokukoError('VALIDATION_ERROR', 'Request body must not contain a byte-order mark');
|
|
257
|
+
}
|
|
258
|
+
try {
|
|
259
|
+
return new TextDecoder('utf-8', { fatal: true, ignoreBOM: true }).decode(bytes);
|
|
260
|
+
}
|
|
261
|
+
catch (error) {
|
|
262
|
+
if (isInvalidUtf8EncodingError(error)) {
|
|
263
|
+
throw new KiokukoError('VALIDATION_ERROR', 'Request body must be valid UTF-8');
|
|
264
|
+
}
|
|
265
|
+
throw error;
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
function requireOnlyJsonFields(payload, allowed, label) {
|
|
269
|
+
const allowedFields = new Set(allowed);
|
|
270
|
+
if (Object.keys(payload).some((field) => !allowedFields.has(field))) {
|
|
271
|
+
throw new KiokukoError('VALIDATION_ERROR', `${label} contains an unknown field`);
|
|
272
|
+
}
|
|
273
|
+
}
|
|
125
274
|
async function readJsonBody(request) {
|
|
275
|
+
requireExactJsonMediaType(request);
|
|
126
276
|
const chunks = [];
|
|
127
277
|
let size = 0;
|
|
128
|
-
const
|
|
278
|
+
const bytes = await new Promise((resolve, reject) => {
|
|
129
279
|
request.on('data', (chunk) => {
|
|
130
280
|
const buffer = Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk);
|
|
131
281
|
size += buffer.byteLength;
|
|
@@ -136,33 +286,53 @@ async function readJsonBody(request) {
|
|
|
136
286
|
}
|
|
137
287
|
chunks.push(buffer);
|
|
138
288
|
});
|
|
139
|
-
request.on('end', () => resolve(Buffer.concat(chunks)
|
|
289
|
+
request.on('end', () => resolve(Buffer.concat(chunks)));
|
|
140
290
|
request.on('error', reject);
|
|
291
|
+
request.on('aborted', () => reject(new KiokukoError('VALIDATION_ERROR', 'Request body is incomplete')));
|
|
141
292
|
});
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
if (error instanceof KiokukoError)
|
|
149
|
-
throw error;
|
|
150
|
-
throw new KiokukoError('VALIDATION_ERROR', 'Request body is not valid JSON');
|
|
293
|
+
const parsed = parseStrictJson(decodeJsonBody(bytes), { allowTrailingComma: false, disallowComments: true, allowEmptyContent: false }, 'Request body is not valid strict JSON');
|
|
294
|
+
return asRecord(parsed, 'Request body');
|
|
295
|
+
}
|
|
296
|
+
function requireNoQueryParameters(url) {
|
|
297
|
+
if (url.searchParams.entries().next().done !== true) {
|
|
298
|
+
throw new KiokukoError('VALIDATION_ERROR', 'This endpoint does not accept query parameters');
|
|
151
299
|
}
|
|
152
300
|
}
|
|
301
|
+
async function requireEmptyBody(request) {
|
|
302
|
+
await new Promise((resolve, reject) => {
|
|
303
|
+
request.once('data', () => {
|
|
304
|
+
request.resume();
|
|
305
|
+
reject(new KiokukoError('VALIDATION_ERROR', 'Request body must be empty'));
|
|
306
|
+
});
|
|
307
|
+
request.once('end', resolve);
|
|
308
|
+
request.once('error', reject);
|
|
309
|
+
request.once('aborted', () => reject(new KiokukoError('VALIDATION_ERROR', 'Request body is incomplete')));
|
|
310
|
+
});
|
|
311
|
+
}
|
|
153
312
|
function workspaceSummaries(database) {
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
313
|
+
database.exec('BEGIN DEFERRED');
|
|
314
|
+
try {
|
|
315
|
+
const externalWorkspaces = new Set(listExternalSkills(database).map((skill) => skill.sourceWorkspace));
|
|
316
|
+
const summaries = new Map();
|
|
317
|
+
for (const row of database.prepare('SELECT workspace, display_name FROM repositories ORDER BY workspace ASC').all()) {
|
|
318
|
+
if (!externalWorkspaces.has(row.workspace))
|
|
319
|
+
summaries.set(row.workspace, { workspace: row.workspace, displayName: row.display_name, count: 0 });
|
|
320
|
+
}
|
|
321
|
+
for (const row of database.prepare("SELECT workspace, COUNT(*) AS count FROM entries WHERE status <> 'superseded' GROUP BY workspace").all()) {
|
|
322
|
+
if (externalWorkspaces.has(row.workspace))
|
|
323
|
+
continue;
|
|
324
|
+
const existing = summaries.get(row.workspace);
|
|
325
|
+
if (existing)
|
|
326
|
+
existing.count = Number(row.count);
|
|
327
|
+
else
|
|
328
|
+
summaries.set(row.workspace, { workspace: row.workspace, displayName: '', count: Number(row.count) });
|
|
329
|
+
}
|
|
330
|
+
database.exec('COMMIT');
|
|
331
|
+
return [...summaries.values()].sort((left, right) => compareCanonicalStrings(left.workspace, right.workspace));
|
|
157
332
|
}
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
if (existing)
|
|
161
|
-
existing.count = Number(row.count);
|
|
162
|
-
else
|
|
163
|
-
summaries.set(row.workspace, { workspace: row.workspace, displayName: '', count: Number(row.count) });
|
|
333
|
+
catch (error) {
|
|
334
|
+
rollbackFailedTransaction(database, error);
|
|
164
335
|
}
|
|
165
|
-
return [...summaries.values()].sort((left, right) => left.workspace.localeCompare(right.workspace));
|
|
166
336
|
}
|
|
167
337
|
function workspaceTags(database, workspace) {
|
|
168
338
|
return database
|
|
@@ -170,6 +340,12 @@ function workspaceTags(database, workspace) {
|
|
|
170
340
|
.all(workspace)
|
|
171
341
|
.map((row) => ({ tag: row.tag, count: Number(row.count) }));
|
|
172
342
|
}
|
|
343
|
+
function workspaceProject(database, workspace) {
|
|
344
|
+
const row = database.prepare('SELECT r.repository_id, r.workspace, l.canonical_root FROM repository_locations AS l JOIN repositories AS r ON r.repository_id = l.repository_id WHERE r.workspace = ? ORDER BY l.last_seen_at DESC, l.canonical_root ASC LIMIT 1').get(workspace);
|
|
345
|
+
if (!row)
|
|
346
|
+
return undefined;
|
|
347
|
+
return { repositoryId: row.repository_id, workspace: row.workspace, repositoryRoot: row.canonical_root, source: 'location' };
|
|
348
|
+
}
|
|
173
349
|
function listEntries(database, workspace, query, kind, status, tag, includeSuperseded, limit) {
|
|
174
350
|
if (query.trim().length > 0) {
|
|
175
351
|
const searchInput = { workspace, query, limit, includeSuperseded };
|
|
@@ -215,6 +391,112 @@ function entryIdFromPath(pathname) {
|
|
|
215
391
|
throw new KiokukoError('VALIDATION_ERROR', 'entry id is not valid URL encoding');
|
|
216
392
|
}
|
|
217
393
|
}
|
|
394
|
+
function externalSkillIdFromPath(pathname) {
|
|
395
|
+
const prefix = '/api/skills/';
|
|
396
|
+
if (!pathname.startsWith(prefix))
|
|
397
|
+
return undefined;
|
|
398
|
+
const encoded = pathname.slice(prefix.length);
|
|
399
|
+
if (encoded.length === 0 || encoded.includes('/'))
|
|
400
|
+
throw new KiokukoError('NOT_FOUND', 'Endpoint not found');
|
|
401
|
+
try {
|
|
402
|
+
const skillId = decodeURIComponent(encoded);
|
|
403
|
+
if (skillId.length === 0 || skillId.length > 500)
|
|
404
|
+
throw new Error('invalid');
|
|
405
|
+
return skillId;
|
|
406
|
+
}
|
|
407
|
+
catch {
|
|
408
|
+
throw new KiokukoError('VALIDATION_ERROR', 'skill id is not valid URL encoding');
|
|
409
|
+
}
|
|
410
|
+
}
|
|
411
|
+
function externalSkillSourceFailure(error, code, message) {
|
|
412
|
+
const failure = new KiokukoError(code, message, {
|
|
413
|
+
failureCode: error.code,
|
|
414
|
+
...(error.retryAfterSeconds === null ? {} : { retryAfterSeconds: error.retryAfterSeconds }),
|
|
415
|
+
});
|
|
416
|
+
Object.defineProperty(failure, 'cause', {
|
|
417
|
+
value: error,
|
|
418
|
+
enumerable: false,
|
|
419
|
+
configurable: false,
|
|
420
|
+
writable: false,
|
|
421
|
+
});
|
|
422
|
+
return failure;
|
|
423
|
+
}
|
|
424
|
+
function refreshExternalSkill(context, skillId, flights) {
|
|
425
|
+
if (flights.database !== context.database) {
|
|
426
|
+
throw new KiokukoError('INTEGRITY_ERROR', 'External skill refresh coordinator is bound to another database');
|
|
427
|
+
}
|
|
428
|
+
const detail = readExternalSkill(context.database, skillId);
|
|
429
|
+
if (!detail)
|
|
430
|
+
throw new KiokukoError('NOT_FOUND', 'External skill not found');
|
|
431
|
+
if (detail.skill.sourceType !== 'github')
|
|
432
|
+
throw new KiokukoError('NOT_IMPLEMENTED', 'Only GitHub external skills can be refreshed automatically');
|
|
433
|
+
const candidate = {
|
|
434
|
+
id: detail.skill.skillId,
|
|
435
|
+
provider: detail.skill.provider,
|
|
436
|
+
name: detail.skill.name,
|
|
437
|
+
slug: detail.skill.slug,
|
|
438
|
+
source: detail.skill.sourceLocator,
|
|
439
|
+
sourceType: 'github',
|
|
440
|
+
installUrl: detail.skill.installUrl,
|
|
441
|
+
installs: detail.skill.installs,
|
|
442
|
+
duplicate: detail.skill.duplicate,
|
|
443
|
+
officialStatus: detail.skill.officialStatus,
|
|
444
|
+
auditStatus: detail.skill.auditStatus,
|
|
445
|
+
};
|
|
446
|
+
const expected = { generation: detail.skill.generation, sourceCommit: detail.skill.sourceCommit, snapshotHash: detail.skill.snapshotHash, state: detail.skill.state, lastCheckedAt: detail.skill.lastCheckedAt };
|
|
447
|
+
const flightKey = JSON.stringify([
|
|
448
|
+
skillId,
|
|
449
|
+
expected.generation,
|
|
450
|
+
expected.sourceCommit,
|
|
451
|
+
expected.snapshotHash,
|
|
452
|
+
expected.state,
|
|
453
|
+
expected.lastCheckedAt,
|
|
454
|
+
]);
|
|
455
|
+
const existing = flights.operations.get(flightKey);
|
|
456
|
+
if (existing !== undefined)
|
|
457
|
+
return existing;
|
|
458
|
+
const operation = Promise.resolve().then(async () => {
|
|
459
|
+
try {
|
|
460
|
+
const materialized = await fetchMaterializableSkillSnapshot(context.database, candidate, {
|
|
461
|
+
provider: createSkillRegistryProvider(),
|
|
462
|
+
sourceFetcher: new GitHubSkillSourceFetcher({ token: readSkillDiscoveryConfig().githubToken }),
|
|
463
|
+
sourceRequest: externalSkillSourceFetchRequest(detail),
|
|
464
|
+
cacheWrite: (operation) => context.enqueueWrite(operation),
|
|
465
|
+
});
|
|
466
|
+
const snapshot = materialized.snapshot;
|
|
467
|
+
if (!snapshot.files.some((file) => file.primary))
|
|
468
|
+
throw new KiokukoError('VALIDATION_ERROR', 'Skill snapshot has no primary document');
|
|
469
|
+
const requirement = externalSkillRequirement(context.database, skillId);
|
|
470
|
+
return await context.enqueueWrite(() => refreshExternalSkillSnapshot(context.database, skillId, snapshot, documentsFromSkillSnapshot(snapshot), requirement, expected, undefined, materialized.authorization));
|
|
471
|
+
}
|
|
472
|
+
catch (error) {
|
|
473
|
+
if (!(error instanceof SkillSourceError))
|
|
474
|
+
throw error;
|
|
475
|
+
if (error.code === 'source_missing' || error.code === 'candidate_not_found_at_source') {
|
|
476
|
+
await context.enqueueWrite(() => markExternalSkillRefreshFailure(context.database, skillId, 'stale', expected));
|
|
477
|
+
throw externalSkillSourceFailure(error, 'CONFLICT', 'External skill source is stale');
|
|
478
|
+
}
|
|
479
|
+
if (error.code === 'skill_disabled_for_model_invocation' || error.code === 'skill_secret_detected' || error.code === 'skill_blocked') {
|
|
480
|
+
await context.enqueueWrite(() => markExternalSkillRefreshFailure(context.database, skillId, 'blocked', expected));
|
|
481
|
+
throw externalSkillSourceFailure(error, 'SECURITY_REJECTION', 'External skill snapshot was blocked');
|
|
482
|
+
}
|
|
483
|
+
if (error.code === 'source_rate_limited' || error.code === 'source_unavailable') {
|
|
484
|
+
throw externalSkillSourceFailure(error, 'SERVICE_UNAVAILABLE', 'External skill source is temporarily unavailable');
|
|
485
|
+
}
|
|
486
|
+
if (error.code === 'source_tree_truncated' || error.code === 'skill_too_large' || error.code === 'skill_validation_failed') {
|
|
487
|
+
throw externalSkillSourceFailure(error, 'SECURITY_REJECTION', 'External skill source failed validation');
|
|
488
|
+
}
|
|
489
|
+
throw error;
|
|
490
|
+
}
|
|
491
|
+
});
|
|
492
|
+
flights.operations.set(flightKey, operation);
|
|
493
|
+
const cleanup = () => {
|
|
494
|
+
if (flights.operations.get(flightKey) === operation)
|
|
495
|
+
flights.operations.delete(flightKey);
|
|
496
|
+
};
|
|
497
|
+
void operation.then(cleanup, cleanup);
|
|
498
|
+
return operation;
|
|
499
|
+
}
|
|
218
500
|
function operatorRunIdFromPath(pathname) {
|
|
219
501
|
const prefix = '/api/operator/runs/';
|
|
220
502
|
if (!pathname.startsWith(prefix) || pathname.slice(prefix.length).includes('/'))
|
|
@@ -308,7 +590,7 @@ function operatorRunDetail(context, runId) {
|
|
|
308
590
|
untrusted: true,
|
|
309
591
|
};
|
|
310
592
|
}
|
|
311
|
-
async function handleRequest(request, response, context, sessionToken) {
|
|
593
|
+
async function handleRequest(request, response, context, sessionToken, externalSkillRefreshFlights) {
|
|
312
594
|
if (request.method === 'OPTIONS') {
|
|
313
595
|
response.writeHead(204, { 'cache-control': 'no-store' });
|
|
314
596
|
response.end();
|
|
@@ -324,6 +606,72 @@ async function handleRequest(request, response, context, sessionToken) {
|
|
|
324
606
|
return;
|
|
325
607
|
}
|
|
326
608
|
requireUiSession(request, sessionToken);
|
|
609
|
+
if (request.method === 'GET' && url.pathname === '/api/skills') {
|
|
610
|
+
if ([...url.searchParams.keys()].some((key) => key !== 'state' && key !== 'limit' && key !== 'cursor')
|
|
611
|
+
|| url.searchParams.getAll('state').length > 1 || url.searchParams.getAll('limit').length > 1) {
|
|
612
|
+
throw new KiokukoError('VALIDATION_ERROR', 'External skill list query is invalid');
|
|
613
|
+
}
|
|
614
|
+
const state = enumQuery(url.searchParams.get('state'), ['discovered', 'imported', 'blocked', 'stale', 'disabled'], 'state');
|
|
615
|
+
const limit = limitQuery(url.searchParams.get('limit'));
|
|
616
|
+
const cursor = externalSkillCursorQuery(url);
|
|
617
|
+
const normalizedState = state;
|
|
618
|
+
if (cursor !== undefined && cursor[2] !== (normalizedState ?? null)) {
|
|
619
|
+
throw new KiokukoError('CONFLICT', 'External skill list filter changed; restart pagination');
|
|
620
|
+
}
|
|
621
|
+
const page = listExternalSkillsPage(context.database, {
|
|
622
|
+
...(normalizedState === undefined ? {} : { state: normalizedState }),
|
|
623
|
+
limit,
|
|
624
|
+
...(cursor === undefined ? {} : {
|
|
625
|
+
expectedVersion: cursor[1],
|
|
626
|
+
after: { sourceLocator: cursor[3], slug: cursor[4], provider: cursor[5], skillId: cursor[6] },
|
|
627
|
+
}),
|
|
628
|
+
});
|
|
629
|
+
const skills = page.skills.map(externalSkillListItem);
|
|
630
|
+
jsonResponse(response, 200, {
|
|
631
|
+
skills,
|
|
632
|
+
count: skills.length,
|
|
633
|
+
truncated: page.truncated,
|
|
634
|
+
nextCursor: page.truncated ? externalSkillCursor(page.skills.at(-1), page.version, normalizedState) : null,
|
|
635
|
+
untrusted: true,
|
|
636
|
+
});
|
|
637
|
+
return;
|
|
638
|
+
}
|
|
639
|
+
const isExternalSkillAction = url.pathname.endsWith('/refresh') || url.pathname.endsWith('/disable') || url.pathname.endsWith('/enable');
|
|
640
|
+
const externalSkillId = isExternalSkillAction ? undefined : externalSkillIdFromPath(url.pathname);
|
|
641
|
+
if (externalSkillId !== undefined && request.method === 'GET') {
|
|
642
|
+
requireNoQueryParameters(url);
|
|
643
|
+
const detail = readExternalSkill(context.database, externalSkillId);
|
|
644
|
+
if (!detail)
|
|
645
|
+
throw new KiokukoError('NOT_FOUND', 'External skill not found');
|
|
646
|
+
jsonResponse(response, 200, {
|
|
647
|
+
skill: externalSkillListItem(detail.skill),
|
|
648
|
+
entries: detail.entries.slice(0, MAX_WEB_ENTRIES),
|
|
649
|
+
entriesTruncated: detail.entries.length > MAX_WEB_ENTRIES,
|
|
650
|
+
untrusted: true,
|
|
651
|
+
});
|
|
652
|
+
return;
|
|
653
|
+
}
|
|
654
|
+
if (request.method === 'POST' && url.pathname.startsWith('/api/skills/') && url.pathname.endsWith('/refresh')) {
|
|
655
|
+
const skillId = externalSkillIdFromPath(url.pathname.slice(0, -'/refresh'.length));
|
|
656
|
+
if (skillId === undefined)
|
|
657
|
+
throw new KiokukoError('NOT_FOUND', 'Endpoint not found');
|
|
658
|
+
requireNoQueryParameters(url);
|
|
659
|
+
await requireEmptyBody(request);
|
|
660
|
+
jsonResponse(response, 200, await refreshExternalSkill(context, skillId, externalSkillRefreshFlights));
|
|
661
|
+
return;
|
|
662
|
+
}
|
|
663
|
+
if (request.method === 'POST' && url.pathname.startsWith('/api/skills/') && (url.pathname.endsWith('/disable') || url.pathname.endsWith('/enable'))) {
|
|
664
|
+
const suffix = url.pathname.endsWith('/disable') ? '/disable' : '/enable';
|
|
665
|
+
const skillId = externalSkillIdFromPath(url.pathname.slice(0, -suffix.length));
|
|
666
|
+
if (skillId === undefined)
|
|
667
|
+
throw new KiokukoError('NOT_FOUND', 'Endpoint not found');
|
|
668
|
+
requireNoQueryParameters(url);
|
|
669
|
+
await requireEmptyBody(request);
|
|
670
|
+
const state = suffix === '/disable' ? 'disabled' : 'imported';
|
|
671
|
+
const skill = await context.enqueueWrite(() => setExternalSkillState(context.database, skillId, state));
|
|
672
|
+
jsonResponse(response, 200, { skill, untrusted: true });
|
|
673
|
+
return;
|
|
674
|
+
}
|
|
327
675
|
if (request.method === 'GET' && url.pathname === '/api/operator/runs') {
|
|
328
676
|
jsonResponse(response, 200, operatorRunList(context, url));
|
|
329
677
|
return;
|
|
@@ -343,17 +691,71 @@ async function handleRequest(request, response, context, sessionToken) {
|
|
|
343
691
|
jsonResponse(response, 200, { workspace, tags });
|
|
344
692
|
return;
|
|
345
693
|
}
|
|
694
|
+
if (request.method === 'GET' && url.pathname === '/api/memory/recall') {
|
|
695
|
+
const workspace = requireWorkspace(url.searchParams.get('workspace') ?? '');
|
|
696
|
+
const query = url.searchParams.get('q')?.trim() ?? '';
|
|
697
|
+
if (query.length === 0)
|
|
698
|
+
throw new KiokukoError('VALIDATION_ERROR', 'q must be a non-empty search query');
|
|
699
|
+
const scope = enumQuery(url.searchParams.get('scope'), ['auto', 'project', 'ecosystem', 'global'], 'scope') ?? 'auto';
|
|
700
|
+
const project = workspace === GLOBAL_WORKSPACE ? undefined : workspaceProject(context.database, workspace);
|
|
701
|
+
if (scope !== 'global' && workspace !== GLOBAL_WORKSPACE && project === undefined)
|
|
702
|
+
throw new KiokukoError('NOT_FOUND', 'The selected workspace has no repository root for scoped recall');
|
|
703
|
+
const result = await recallScopedMemory(context.database, {
|
|
704
|
+
query,
|
|
705
|
+
scope,
|
|
706
|
+
...(project === undefined ? {} : { project }),
|
|
707
|
+
limit: Math.min(limitQuery(url.searchParams.get('limit')), 100),
|
|
708
|
+
maxChars: 50_000,
|
|
709
|
+
});
|
|
710
|
+
jsonResponse(response, 200, { workspace, ...result });
|
|
711
|
+
return;
|
|
712
|
+
}
|
|
346
713
|
if (request.method === 'GET' && url.pathname === '/api/curator/candidates') {
|
|
347
714
|
const workspaceParam = url.searchParams.get('workspace');
|
|
348
715
|
const skillReadyOnly = booleanQuery(url.searchParams.get('skillReadyOnly'), 'skillReadyOnly') ?? false;
|
|
349
|
-
const
|
|
350
|
-
|
|
351
|
-
|
|
716
|
+
const workspaces = listQuery(url, 'project');
|
|
717
|
+
const tags = listQuery(url, 'tag');
|
|
718
|
+
const frameworks = listQuery(url, 'framework');
|
|
719
|
+
const languages = listQuery(url, 'language');
|
|
720
|
+
const memoryClasses = listQuery(url, 'memoryClass').map((value) => enumQuery(value, MEMORY_CLASSES, 'memoryClass'));
|
|
721
|
+
const tiers = listQuery(url, 'tier').map((value) => enumQuery(value, ['unobserved', 'observed', 'repeated', 'portable'], 'tier'));
|
|
722
|
+
const tagMode = enumQuery(url.searchParams.get('tagMode'), ['any', 'all'], 'tagMode');
|
|
723
|
+
const includeGlobalized = booleanQuery(url.searchParams.get('includeGlobalized'), 'includeGlobalized') ?? false;
|
|
724
|
+
const cursor = url.searchParams.get('cursor');
|
|
725
|
+
const input = {
|
|
726
|
+
...(workspaceParam !== null && workspaceParam !== 'all' ? { workspace: requireWorkspace(workspaceParam) } : {}),
|
|
727
|
+
...(workspaces.length > 0 ? { workspaces } : {}),
|
|
728
|
+
...(tags.length > 0 ? { tags } : {}),
|
|
729
|
+
...(tagMode === undefined ? {} : { tagMode }),
|
|
730
|
+
...(frameworks.length > 0 ? { frameworks } : {}),
|
|
731
|
+
...(languages.length > 0 ? { languages } : {}),
|
|
732
|
+
...(memoryClasses.length > 0 ? { memoryClasses } : {}),
|
|
733
|
+
...(tiers.length > 0 ? { tiers } : {}),
|
|
734
|
+
...(url.searchParams.get('search') === null ? {} : { search: url.searchParams.get('search') ?? '' }),
|
|
735
|
+
...(cursor === null ? {} : { cursor }),
|
|
736
|
+
allWorkspaces: workspaceParam === null || workspaceParam === 'all' || workspaces.length > 0,
|
|
737
|
+
skillReadyOnly,
|
|
738
|
+
includeGlobalized,
|
|
739
|
+
limit: Math.min(limitQuery(url.searchParams.get('limit')), 50),
|
|
740
|
+
};
|
|
741
|
+
const result = await curateMemoryCandidates(context.database, input);
|
|
352
742
|
jsonResponse(response, 200, result);
|
|
353
743
|
return;
|
|
354
744
|
}
|
|
745
|
+
if (request.method === 'GET' && url.pathname === '/api/curator/facets') {
|
|
746
|
+
const workspaceParam = url.searchParams.get('workspace');
|
|
747
|
+
const projects = listQuery(url, 'project');
|
|
748
|
+
const includeGlobalized = booleanQuery(url.searchParams.get('includeGlobalized'), 'includeGlobalized') ?? false;
|
|
749
|
+
jsonResponse(response, 200, { facets: curatorFacets(context.database, {
|
|
750
|
+
...(workspaceParam !== null && workspaceParam !== 'all' ? { workspace: requireWorkspace(workspaceParam) } : {}),
|
|
751
|
+
...(projects.length > 0 ? { workspaces: projects } : {}),
|
|
752
|
+
includeGlobalized,
|
|
753
|
+
}) });
|
|
754
|
+
return;
|
|
755
|
+
}
|
|
355
756
|
if (request.method === 'POST' && url.pathname === '/api/curator/globalize') {
|
|
356
757
|
const payload = await readJsonBody(request);
|
|
758
|
+
requireOnlyJsonFields(payload, ['workspace', 'entryId', 'expectedRevision', 'actor'], 'Curator globalize request');
|
|
357
759
|
const workspace = requireWorkspace(url.searchParams.get('workspace') ?? (typeof payload.workspace === 'string' ? payload.workspace : ''));
|
|
358
760
|
const result = await context.enqueueWrite(() => globalizeCuratorCandidate(context.database, {
|
|
359
761
|
workspace,
|
|
@@ -384,6 +786,7 @@ async function handleRequest(request, response, context, sessionToken) {
|
|
|
384
786
|
return;
|
|
385
787
|
}
|
|
386
788
|
const payload = await readJsonBody(request);
|
|
789
|
+
requireOnlyJsonFields(payload, ['expectedRevision', 'kind', 'title', 'body', 'summary', 'scope', 'provenance', 'tags', 'actor'], 'Entry update request');
|
|
387
790
|
const expectedRevision = payload.expectedRevision;
|
|
388
791
|
const input = {
|
|
389
792
|
workspace,
|
|
@@ -412,16 +815,27 @@ async function handleRequest(request, response, context, sessionToken) {
|
|
|
412
815
|
function isSharedServerPath(pathname) {
|
|
413
816
|
return pathname.startsWith('/health/') || pathname === '/api/v1' || pathname.startsWith('/api/v1/');
|
|
414
817
|
}
|
|
415
|
-
function createLegacyApplication(context) {
|
|
818
|
+
function createLegacyApplication(context, trustedOrigin) {
|
|
416
819
|
const sharedApplication = context.createAuthenticatedApp(createAgentV1Handler(context));
|
|
417
820
|
const sessionToken = randomBytes(32).toString('base64url');
|
|
821
|
+
const externalSkillRefreshFlights = {
|
|
822
|
+
database: context.database,
|
|
823
|
+
operations: new Map(),
|
|
824
|
+
};
|
|
418
825
|
return (request, response) => {
|
|
826
|
+
try {
|
|
827
|
+
requireTrustedWebOrigin(request, trustedOrigin());
|
|
828
|
+
}
|
|
829
|
+
catch (error) {
|
|
830
|
+
jsonResponse(response, errorStatus(error), errorBody(error));
|
|
831
|
+
return;
|
|
832
|
+
}
|
|
419
833
|
const pathname = new URL(request.url ?? '/', 'http://127.0.0.1').pathname;
|
|
420
834
|
if (isSharedServerPath(pathname)) {
|
|
421
835
|
sharedApplication(request, response);
|
|
422
836
|
return;
|
|
423
837
|
}
|
|
424
|
-
void handleRequest(request, response, context, sessionToken).catch((error) => {
|
|
838
|
+
void handleRequest(request, response, context, sessionToken, externalSkillRefreshFlights).catch((error) => {
|
|
425
839
|
if (!response.headersSent)
|
|
426
840
|
jsonResponse(response, errorStatus(error), errorBody(error));
|
|
427
841
|
else
|
|
@@ -430,13 +844,15 @@ function createLegacyApplication(context) {
|
|
|
430
844
|
};
|
|
431
845
|
}
|
|
432
846
|
export async function startWebServer(options = {}) {
|
|
847
|
+
let trustedOrigin;
|
|
433
848
|
const runtime = await startHttpServer({
|
|
434
849
|
...(options.httpOptions ?? {}),
|
|
435
850
|
...(options.databasePath === undefined ? {} : { databasePath: options.databasePath }),
|
|
436
851
|
host: options.host ?? DEFAULT_HOST,
|
|
437
852
|
port: options.port ?? DEFAULT_PORT,
|
|
438
|
-
applicationFactory: createLegacyApplication,
|
|
853
|
+
applicationFactory: (context) => createLegacyApplication(context, () => trustedOrigin),
|
|
439
854
|
});
|
|
855
|
+
trustedOrigin = new URL(runtime.url).origin;
|
|
440
856
|
return {
|
|
441
857
|
server: runtime.server,
|
|
442
858
|
url: runtime.url,
|