@harrylabsj/kiwi 0.6.0
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/LICENSE +201 -0
- package/README.md +150 -0
- package/contracts/candidate-agent-dto-1.0.README.md +39 -0
- package/contracts/candidate-agent-dto-1.0.schema.json +172 -0
- package/contracts/interop/kiwi-buyer-message-send.json +43 -0
- package/contracts/interop/knp-data-part-examples.json +243 -0
- package/contracts/kiwi-catalog/1.0/agent-record.schema.json +78 -0
- package/contracts/kiwi-catalog/1.0/listing-record.schema.json +88 -0
- package/contracts/kiwi-catalog/1.0/listing-search-result.schema.json +60 -0
- package/contracts/negotiation/1.0/schema.json +501 -0
- package/contracts/shopping.negotiation/0.1/capabilities.schema.json +47 -0
- package/contracts/shopping.negotiation/0.1/decision.schema.json +120 -0
- package/contracts/shopping.negotiation/0.1/policy-result.schema.json +52 -0
- package/contracts/shopping.negotiation/0.1/snapshot.schema.json +172 -0
- package/dist/a2a/client/client.d.ts +33 -0
- package/dist/a2a/client/client.js +161 -0
- package/dist/a2a/client/client.js.map +1 -0
- package/dist/a2a/client/error.d.ts +35 -0
- package/dist/a2a/client/error.js +34 -0
- package/dist/a2a/client/error.js.map +1 -0
- package/dist/a2a/client/index.d.ts +29 -0
- package/dist/a2a/client/index.js +26 -0
- package/dist/a2a/client/index.js.map +1 -0
- package/dist/a2a/client/jsonrpc.d.ts +49 -0
- package/dist/a2a/client/jsonrpc.js +85 -0
- package/dist/a2a/client/jsonrpc.js.map +1 -0
- package/dist/a2a/client/parse.d.ts +18 -0
- package/dist/a2a/client/parse.js +134 -0
- package/dist/a2a/client/parse.js.map +1 -0
- package/dist/a2a/client/types.d.ts +102 -0
- package/dist/a2a/client/types.js +26 -0
- package/dist/a2a/client/types.js.map +1 -0
- package/dist/a2a/client/url-policy.d.ts +44 -0
- package/dist/a2a/client/url-policy.js +242 -0
- package/dist/a2a/client/url-policy.js.map +1 -0
- package/dist/a2a/negotiate.d.ts +68 -0
- package/dist/a2a/negotiate.js +288 -0
- package/dist/a2a/negotiate.js.map +1 -0
- package/dist/a2a/node.d.ts +37 -0
- package/dist/a2a/node.js +155 -0
- package/dist/a2a/node.js.map +1 -0
- package/dist/a2a/server/auth.d.ts +38 -0
- package/dist/a2a/server/auth.js +112 -0
- package/dist/a2a/server/auth.js.map +1 -0
- package/dist/a2a/server/card.d.ts +19 -0
- package/dist/a2a/server/card.js +81 -0
- package/dist/a2a/server/card.js.map +1 -0
- package/dist/a2a/server/errors.d.ts +109 -0
- package/dist/a2a/server/errors.js +178 -0
- package/dist/a2a/server/errors.js.map +1 -0
- package/dist/a2a/server/handler.d.ts +22 -0
- package/dist/a2a/server/handler.js +57 -0
- package/dist/a2a/server/handler.js.map +1 -0
- package/dist/a2a/server/inbound-message.d.ts +37 -0
- package/dist/a2a/server/inbound-message.js +104 -0
- package/dist/a2a/server/inbound-message.js.map +1 -0
- package/dist/a2a/server/index.d.ts +43 -0
- package/dist/a2a/server/index.js +42 -0
- package/dist/a2a/server/index.js.map +1 -0
- package/dist/a2a/server/merchant-handler.d.ts +69 -0
- package/dist/a2a/server/merchant-handler.js +316 -0
- package/dist/a2a/server/merchant-handler.js.map +1 -0
- package/dist/a2a/server/pipeline.d.ts +69 -0
- package/dist/a2a/server/pipeline.js +329 -0
- package/dist/a2a/server/pipeline.js.map +1 -0
- package/dist/a2a/server/server.d.ts +64 -0
- package/dist/a2a/server/server.js +420 -0
- package/dist/a2a/server/server.js.map +1 -0
- package/dist/a2a/server/task-registry.d.ts +31 -0
- package/dist/a2a/server/task-registry.js +67 -0
- package/dist/a2a/server/task-registry.js.map +1 -0
- package/dist/a2a/server/throttle.d.ts +154 -0
- package/dist/a2a/server/throttle.js +289 -0
- package/dist/a2a/server/throttle.js.map +1 -0
- package/dist/a2a/server/types.d.ts +191 -0
- package/dist/a2a/server/types.js +17 -0
- package/dist/a2a/server/types.js.map +1 -0
- package/dist/a2a/server/ucp.d.ts +49 -0
- package/dist/a2a/server/ucp.js +85 -0
- package/dist/a2a/server/ucp.js.map +1 -0
- package/dist/a2a/task/index.d.ts +24 -0
- package/dist/a2a/task/index.js +22 -0
- package/dist/a2a/task/index.js.map +1 -0
- package/dist/a2a/task/ledger.d.ts +48 -0
- package/dist/a2a/task/ledger.js +65 -0
- package/dist/a2a/task/ledger.js.map +1 -0
- package/dist/a2a/task/poller.d.ts +93 -0
- package/dist/a2a/task/poller.js +184 -0
- package/dist/a2a/task/poller.js.map +1 -0
- package/dist/a2a/task/state.d.ts +72 -0
- package/dist/a2a/task/state.js +119 -0
- package/dist/a2a/task/state.js.map +1 -0
- package/dist/a2a/ucp-agent.d.ts +49 -0
- package/dist/a2a/ucp-agent.js +78 -0
- package/dist/a2a/ucp-agent.js.map +1 -0
- package/dist/agent/agent-db.d.ts +31 -0
- package/dist/agent/agent-db.js +91 -0
- package/dist/agent/agent-db.js.map +1 -0
- package/dist/agent/buyer/buyer-tools.d.ts +70 -0
- package/dist/agent/buyer/buyer-tools.js +1353 -0
- package/dist/agent/buyer/buyer-tools.js.map +1 -0
- package/dist/agent/buyer/ranker.d.ts +53 -0
- package/dist/agent/buyer/ranker.js +153 -0
- package/dist/agent/buyer/ranker.js.map +1 -0
- package/dist/agent/buyer/scheduler.d.ts +58 -0
- package/dist/agent/buyer/scheduler.js +317 -0
- package/dist/agent/buyer/scheduler.js.map +1 -0
- package/dist/agent/buyer/search-loop.d.ts +42 -0
- package/dist/agent/buyer/search-loop.js +280 -0
- package/dist/agent/buyer/search-loop.js.map +1 -0
- package/dist/agent/buyer/task-store.d.ts +178 -0
- package/dist/agent/buyer/task-store.js +637 -0
- package/dist/agent/buyer/task-store.js.map +1 -0
- package/dist/agent/buyer/types.d.ts +222 -0
- package/dist/agent/buyer/types.js +124 -0
- package/dist/agent/buyer/types.js.map +1 -0
- package/dist/agent/chat-tools.d.ts +41 -0
- package/dist/agent/chat-tools.js +193 -0
- package/dist/agent/chat-tools.js.map +1 -0
- package/dist/agent/chat-tui.d.ts +49 -0
- package/dist/agent/chat-tui.js +314 -0
- package/dist/agent/chat-tui.js.map +1 -0
- package/dist/agent/connector/fake-connector.d.ts +50 -0
- package/dist/agent/connector/fake-connector.js +138 -0
- package/dist/agent/connector/fake-connector.js.map +1 -0
- package/dist/agent/connector/http-connector.d.ts +49 -0
- package/dist/agent/connector/http-connector.js +208 -0
- package/dist/agent/connector/http-connector.js.map +1 -0
- package/dist/agent/connector/types.d.ts +103 -0
- package/dist/agent/connector/types.js +97 -0
- package/dist/agent/connector/types.js.map +1 -0
- package/dist/agent/fake-chat-model.d.ts +22 -0
- package/dist/agent/fake-chat-model.js +134 -0
- package/dist/agent/fake-chat-model.js.map +1 -0
- package/dist/agent/kernel.d.ts +258 -0
- package/dist/agent/kernel.js +1099 -0
- package/dist/agent/kernel.js.map +1 -0
- package/dist/agent/memory/schema.d.ts +32 -0
- package/dist/agent/memory/schema.js +291 -0
- package/dist/agent/memory/schema.js.map +1 -0
- package/dist/agent/memory/store.d.ts +193 -0
- package/dist/agent/memory/store.js +881 -0
- package/dist/agent/memory/store.js.map +1 -0
- package/dist/agent/memory/types.d.ts +139 -0
- package/dist/agent/memory/types.js +119 -0
- package/dist/agent/memory/types.js.map +1 -0
- package/dist/agent/memory/vault.d.ts +49 -0
- package/dist/agent/memory/vault.js +125 -0
- package/dist/agent/memory/vault.js.map +1 -0
- package/dist/agent/merchant/action-candidate.d.ts +106 -0
- package/dist/agent/merchant/action-candidate.js +241 -0
- package/dist/agent/merchant/action-candidate.js.map +1 -0
- package/dist/agent/merchant/credential-broker.d.ts +67 -0
- package/dist/agent/merchant/credential-broker.js +76 -0
- package/dist/agent/merchant/credential-broker.js.map +1 -0
- package/dist/agent/merchant/fake-merchant-client.d.ts +47 -0
- package/dist/agent/merchant/fake-merchant-client.js +143 -0
- package/dist/agent/merchant/fake-merchant-client.js.map +1 -0
- package/dist/agent/merchant/merchant-client.d.ts +49 -0
- package/dist/agent/merchant/merchant-client.js +186 -0
- package/dist/agent/merchant/merchant-client.js.map +1 -0
- package/dist/agent/merchant/merchant-tools.d.ts +74 -0
- package/dist/agent/merchant/merchant-tools.js +582 -0
- package/dist/agent/merchant/merchant-tools.js.map +1 -0
- package/dist/agent/merchant/types.d.ts +119 -0
- package/dist/agent/merchant/types.js +133 -0
- package/dist/agent/merchant/types.js.map +1 -0
- package/dist/agent/mode.d.ts +32 -0
- package/dist/agent/mode.js +34 -0
- package/dist/agent/mode.js.map +1 -0
- package/dist/agent/negotiation-chat.d.ts +81 -0
- package/dist/agent/negotiation-chat.js +330 -0
- package/dist/agent/negotiation-chat.js.map +1 -0
- package/dist/agent/session.d.ts +22 -0
- package/dist/agent/session.js +164 -0
- package/dist/agent/session.js.map +1 -0
- package/dist/agent/system-prompt.d.ts +26 -0
- package/dist/agent/system-prompt.js +77 -0
- package/dist/agent/system-prompt.js.map +1 -0
- package/dist/agent/write-gate.d.ts +98 -0
- package/dist/agent/write-gate.js +76 -0
- package/dist/agent/write-gate.js.map +1 -0
- package/dist/cli.d.ts +18 -0
- package/dist/cli.js +1139 -0
- package/dist/cli.js.map +1 -0
- package/dist/commerce/data-source.d.ts +88 -0
- package/dist/commerce/data-source.js +25 -0
- package/dist/commerce/data-source.js.map +1 -0
- package/dist/commerce/erp-source.d.ts +51 -0
- package/dist/commerce/erp-source.js +184 -0
- package/dist/commerce/erp-source.js.map +1 -0
- package/dist/commerce/fake-client.d.ts +167 -0
- package/dist/commerce/fake-client.js +549 -0
- package/dist/commerce/fake-client.js.map +1 -0
- package/dist/commerce/http-client.d.ts +73 -0
- package/dist/commerce/http-client.js +284 -0
- package/dist/commerce/http-client.js.map +1 -0
- package/dist/commerce/local-db-source.d.ts +50 -0
- package/dist/commerce/local-db-source.js +162 -0
- package/dist/commerce/local-db-source.js.map +1 -0
- package/dist/commerce/shopping-cli-source.d.ts +57 -0
- package/dist/commerce/shopping-cli-source.js +206 -0
- package/dist/commerce/shopping-cli-source.js.map +1 -0
- package/dist/commerce/types.d.ts +146 -0
- package/dist/commerce/types.js +31 -0
- package/dist/commerce/types.js.map +1 -0
- package/dist/config/profile.d.ts +122 -0
- package/dist/config/profile.js +386 -0
- package/dist/config/profile.js.map +1 -0
- package/dist/contracts/negotiation-schema.d.ts +28 -0
- package/dist/contracts/negotiation-schema.js +101 -0
- package/dist/contracts/negotiation-schema.js.map +1 -0
- package/dist/contracts/schemas.d.ts +31 -0
- package/dist/contracts/schemas.js +122 -0
- package/dist/contracts/schemas.js.map +1 -0
- package/dist/counterparty/a2a-direct/index.d.ts +41 -0
- package/dist/counterparty/a2a-direct/index.js +330 -0
- package/dist/counterparty/a2a-direct/index.js.map +1 -0
- package/dist/counterparty/channel.d.ts +200 -0
- package/dist/counterparty/channel.js +61 -0
- package/dist/counterparty/channel.js.map +1 -0
- package/dist/counterparty/index.d.ts +28 -0
- package/dist/counterparty/index.js +24 -0
- package/dist/counterparty/index.js.map +1 -0
- package/dist/counterparty/platform-api/index.d.ts +41 -0
- package/dist/counterparty/platform-api/index.js +65 -0
- package/dist/counterparty/platform-api/index.js.map +1 -0
- package/dist/counterparty/registry.d.ts +51 -0
- package/dist/counterparty/registry.js +71 -0
- package/dist/counterparty/registry.js.map +1 -0
- package/dist/counterparty/shopping-cli-hosted/index.d.ts +36 -0
- package/dist/counterparty/shopping-cli-hosted/index.js +337 -0
- package/dist/counterparty/shopping-cli-hosted/index.js.map +1 -0
- package/dist/discovery/agent-card/error.d.ts +28 -0
- package/dist/discovery/agent-card/error.js +31 -0
- package/dist/discovery/agent-card/error.js.map +1 -0
- package/dist/discovery/agent-card/extensions.d.ts +20 -0
- package/dist/discovery/agent-card/extensions.js +59 -0
- package/dist/discovery/agent-card/extensions.js.map +1 -0
- package/dist/discovery/agent-card/index.d.ts +29 -0
- package/dist/discovery/agent-card/index.js +38 -0
- package/dist/discovery/agent-card/index.js.map +1 -0
- package/dist/discovery/agent-card/secrets.d.ts +30 -0
- package/dist/discovery/agent-card/secrets.js +240 -0
- package/dist/discovery/agent-card/secrets.js.map +1 -0
- package/dist/discovery/agent-card/types.d.ts +110 -0
- package/dist/discovery/agent-card/types.js +37 -0
- package/dist/discovery/agent-card/types.js.map +1 -0
- package/dist/discovery/agent-card/validate.d.ts +31 -0
- package/dist/discovery/agent-card/validate.js +210 -0
- package/dist/discovery/agent-card/validate.js.map +1 -0
- package/dist/discovery/capability/error.d.ts +23 -0
- package/dist/discovery/capability/error.js +28 -0
- package/dist/discovery/capability/error.js.map +1 -0
- package/dist/discovery/capability/index.d.ts +21 -0
- package/dist/discovery/capability/index.js +21 -0
- package/dist/discovery/capability/index.js.map +1 -0
- package/dist/discovery/capability/intersect.d.ts +56 -0
- package/dist/discovery/capability/intersect.js +137 -0
- package/dist/discovery/capability/intersect.js.map +1 -0
- package/dist/discovery/catalog-source/errors.d.ts +32 -0
- package/dist/discovery/catalog-source/errors.js +41 -0
- package/dist/discovery/catalog-source/errors.js.map +1 -0
- package/dist/discovery/catalog-source/index.d.ts +30 -0
- package/dist/discovery/catalog-source/index.js +29 -0
- package/dist/discovery/catalog-source/index.js.map +1 -0
- package/dist/discovery/catalog-source/kiwi-record.d.ts +183 -0
- package/dist/discovery/catalog-source/kiwi-record.js +72 -0
- package/dist/discovery/catalog-source/kiwi-record.js.map +1 -0
- package/dist/discovery/catalog-source/kiwi-schema.d.ts +33 -0
- package/dist/discovery/catalog-source/kiwi-schema.js +106 -0
- package/dist/discovery/catalog-source/kiwi-schema.js.map +1 -0
- package/dist/discovery/catalog-source/kiwi-source.d.ts +38 -0
- package/dist/discovery/catalog-source/kiwi-source.js +318 -0
- package/dist/discovery/catalog-source/kiwi-source.js.map +1 -0
- package/dist/discovery/catalog-source/register.d.ts +48 -0
- package/dist/discovery/catalog-source/register.js +83 -0
- package/dist/discovery/catalog-source/register.js.map +1 -0
- package/dist/discovery/catalog-source/schema.d.ts +21 -0
- package/dist/discovery/catalog-source/schema.js +63 -0
- package/dist/discovery/catalog-source/schema.js.map +1 -0
- package/dist/discovery/catalog-source/source.d.ts +45 -0
- package/dist/discovery/catalog-source/source.js +197 -0
- package/dist/discovery/catalog-source/source.js.map +1 -0
- package/dist/discovery/catalog-source/types.d.ts +122 -0
- package/dist/discovery/catalog-source/types.js +30 -0
- package/dist/discovery/catalog-source/types.js.map +1 -0
- package/dist/discovery/index.d.ts +25 -0
- package/dist/discovery/index.js +25 -0
- package/dist/discovery/index.js.map +1 -0
- package/dist/discovery/resolve.d.ts +175 -0
- package/dist/discovery/resolve.js +367 -0
- package/dist/discovery/resolve.js.map +1 -0
- package/dist/discovery/ucp/error.d.ts +25 -0
- package/dist/discovery/ucp/error.js +27 -0
- package/dist/discovery/ucp/error.js.map +1 -0
- package/dist/discovery/ucp/index.d.ts +33 -0
- package/dist/discovery/ucp/index.js +28 -0
- package/dist/discovery/ucp/index.js.map +1 -0
- package/dist/discovery/ucp/intersect.d.ts +148 -0
- package/dist/discovery/ucp/intersect.js +312 -0
- package/dist/discovery/ucp/intersect.js.map +1 -0
- package/dist/discovery/ucp/resolver.d.ts +62 -0
- package/dist/discovery/ucp/resolver.js +214 -0
- package/dist/discovery/ucp/resolver.js.map +1 -0
- package/dist/discovery/ucp/types.d.ts +97 -0
- package/dist/discovery/ucp/types.js +103 -0
- package/dist/discovery/ucp/types.js.map +1 -0
- package/dist/discovery/ucp/validate.d.ts +38 -0
- package/dist/discovery/ucp/validate.js +232 -0
- package/dist/discovery/ucp/validate.js.map +1 -0
- package/dist/discovery/ucp/vendor.d.ts +60 -0
- package/dist/discovery/ucp/vendor.js +61 -0
- package/dist/discovery/ucp/vendor.js.map +1 -0
- package/dist/doctor.d.ts +26 -0
- package/dist/doctor.js +113 -0
- package/dist/doctor.js.map +1 -0
- package/dist/exit-codes.d.ts +26 -0
- package/dist/exit-codes.js +27 -0
- package/dist/exit-codes.js.map +1 -0
- package/dist/fanout/disclosure.d.ts +138 -0
- package/dist/fanout/disclosure.js +188 -0
- package/dist/fanout/disclosure.js.map +1 -0
- package/dist/fanout/index.d.ts +32 -0
- package/dist/fanout/index.js +30 -0
- package/dist/fanout/index.js.map +1 -0
- package/dist/fanout/orchestrator.d.ts +153 -0
- package/dist/fanout/orchestrator.js +439 -0
- package/dist/fanout/orchestrator.js.map +1 -0
- package/dist/fanout/policy.d.ts +128 -0
- package/dist/fanout/policy.js +130 -0
- package/dist/fanout/policy.js.map +1 -0
- package/dist/handoff/acp-commerce.d.ts +58 -0
- package/dist/handoff/acp-commerce.js +69 -0
- package/dist/handoff/acp-commerce.js.map +1 -0
- package/dist/handoff/authorization.d.ts +127 -0
- package/dist/handoff/authorization.js +107 -0
- package/dist/handoff/authorization.js.map +1 -0
- package/dist/handoff/candidate.d.ts +94 -0
- package/dist/handoff/candidate.js +172 -0
- package/dist/handoff/candidate.js.map +1 -0
- package/dist/handoff/channel.d.ts +88 -0
- package/dist/handoff/channel.js +189 -0
- package/dist/handoff/channel.js.map +1 -0
- package/dist/handoff/completion.d.ts +44 -0
- package/dist/handoff/completion.js +136 -0
- package/dist/handoff/completion.js.map +1 -0
- package/dist/handoff/delivery.d.ts +59 -0
- package/dist/handoff/delivery.js +185 -0
- package/dist/handoff/delivery.js.map +1 -0
- package/dist/handoff/destination.d.ts +39 -0
- package/dist/handoff/destination.js +99 -0
- package/dist/handoff/destination.js.map +1 -0
- package/dist/handoff/errors.d.ts +34 -0
- package/dist/handoff/errors.js +47 -0
- package/dist/handoff/errors.js.map +1 -0
- package/dist/handoff/idempotency.d.ts +51 -0
- package/dist/handoff/idempotency.js +168 -0
- package/dist/handoff/idempotency.js.map +1 -0
- package/dist/handoff/index.d.ts +46 -0
- package/dist/handoff/index.js +48 -0
- package/dist/handoff/index.js.map +1 -0
- package/dist/handoff/ledger.d.ts +94 -0
- package/dist/handoff/ledger.js +195 -0
- package/dist/handoff/ledger.js.map +1 -0
- package/dist/handoff/lifecycle.d.ts +29 -0
- package/dist/handoff/lifecycle.js +102 -0
- package/dist/handoff/lifecycle.js.map +1 -0
- package/dist/handoff/metrics.d.ts +56 -0
- package/dist/handoff/metrics.js +78 -0
- package/dist/handoff/metrics.js.map +1 -0
- package/dist/handoff/operator-approval.d.ts +143 -0
- package/dist/handoff/operator-approval.js +287 -0
- package/dist/handoff/operator-approval.js.map +1 -0
- package/dist/handoff/order-record.d.ts +104 -0
- package/dist/handoff/order-record.js +235 -0
- package/dist/handoff/order-record.js.map +1 -0
- package/dist/handoff/package.d.ts +102 -0
- package/dist/handoff/package.js +132 -0
- package/dist/handoff/package.js.map +1 -0
- package/dist/handoff/transaction.d.ts +96 -0
- package/dist/handoff/transaction.js +263 -0
- package/dist/handoff/transaction.js.map +1 -0
- package/dist/handoff/ucp-checkout/cart-channel.d.ts +111 -0
- package/dist/handoff/ucp-checkout/cart-channel.js +370 -0
- package/dist/handoff/ucp-checkout/cart-channel.js.map +1 -0
- package/dist/handoff/ucp-checkout/cart-parse.d.ts +22 -0
- package/dist/handoff/ucp-checkout/cart-parse.js +102 -0
- package/dist/handoff/ucp-checkout/cart-parse.js.map +1 -0
- package/dist/handoff/ucp-checkout/cart-types.d.ts +93 -0
- package/dist/handoff/ucp-checkout/cart-types.js +38 -0
- package/dist/handoff/ucp-checkout/cart-types.js.map +1 -0
- package/dist/handoff/ucp-checkout/channel.d.ts +159 -0
- package/dist/handoff/ucp-checkout/channel.js +636 -0
- package/dist/handoff/ucp-checkout/channel.js.map +1 -0
- package/dist/handoff/ucp-checkout/client.d.ts +88 -0
- package/dist/handoff/ucp-checkout/client.js +228 -0
- package/dist/handoff/ucp-checkout/client.js.map +1 -0
- package/dist/handoff/ucp-checkout/endpoint.d.ts +36 -0
- package/dist/handoff/ucp-checkout/endpoint.js +145 -0
- package/dist/handoff/ucp-checkout/endpoint.js.map +1 -0
- package/dist/handoff/ucp-checkout/index.d.ts +35 -0
- package/dist/handoff/ucp-checkout/index.js +36 -0
- package/dist/handoff/ucp-checkout/index.js.map +1 -0
- package/dist/handoff/ucp-checkout/parse.d.ts +71 -0
- package/dist/handoff/ucp-checkout/parse.js +349 -0
- package/dist/handoff/ucp-checkout/parse.js.map +1 -0
- package/dist/handoff/ucp-checkout/totals.d.ts +41 -0
- package/dist/handoff/ucp-checkout/totals.js +36 -0
- package/dist/handoff/ucp-checkout/totals.js.map +1 -0
- package/dist/handoff/ucp-checkout/types.d.ts +149 -0
- package/dist/handoff/ucp-checkout/types.js +58 -0
- package/dist/handoff/ucp-checkout/types.js.map +1 -0
- package/dist/handoff/url-safety.d.ts +44 -0
- package/dist/handoff/url-safety.js +121 -0
- package/dist/handoff/url-safety.js.map +1 -0
- package/dist/i18n.d.ts +24 -0
- package/dist/i18n.js +27 -0
- package/dist/i18n.js.map +1 -0
- package/dist/negotiation/action-candidate.d.ts +97 -0
- package/dist/negotiation/action-candidate.js +160 -0
- package/dist/negotiation/action-candidate.js.map +1 -0
- package/dist/negotiation/condition/evaluator.d.ts +36 -0
- package/dist/negotiation/condition/evaluator.js +123 -0
- package/dist/negotiation/condition/evaluator.js.map +1 -0
- package/dist/negotiation/context-map/index.d.ts +23 -0
- package/dist/negotiation/context-map/index.js +22 -0
- package/dist/negotiation/context-map/index.js.map +1 -0
- package/dist/negotiation/context-map/store.d.ts +51 -0
- package/dist/negotiation/context-map/store.js +186 -0
- package/dist/negotiation/context-map/store.js.map +1 -0
- package/dist/negotiation/context-map/types.d.ts +29 -0
- package/dist/negotiation/context-map/types.js +57 -0
- package/dist/negotiation/context-map/types.js.map +1 -0
- package/dist/negotiation/domain/common.d.ts +95 -0
- package/dist/negotiation/domain/common.js +216 -0
- package/dist/negotiation/domain/common.js.map +1 -0
- package/dist/negotiation/domain/envelope.d.ts +55 -0
- package/dist/negotiation/domain/envelope.js +110 -0
- package/dist/negotiation/domain/envelope.js.map +1 -0
- package/dist/negotiation/domain/identifiers.d.ts +65 -0
- package/dist/negotiation/domain/identifiers.js +130 -0
- package/dist/negotiation/domain/identifiers.js.map +1 -0
- package/dist/negotiation/domain/objects.d.ts +149 -0
- package/dist/negotiation/domain/objects.js +335 -0
- package/dist/negotiation/domain/objects.js.map +1 -0
- package/dist/negotiation/idempotency/index.d.ts +26 -0
- package/dist/negotiation/idempotency/index.js +25 -0
- package/dist/negotiation/idempotency/index.js.map +1 -0
- package/dist/negotiation/idempotency/store.d.ts +52 -0
- package/dist/negotiation/idempotency/store.js +189 -0
- package/dist/negotiation/idempotency/store.js.map +1 -0
- package/dist/negotiation/idempotency/types.d.ts +102 -0
- package/dist/negotiation/idempotency/types.js +47 -0
- package/dist/negotiation/idempotency/types.js.map +1 -0
- package/dist/negotiation/jcs.d.ts +21 -0
- package/dist/negotiation/jcs.js +114 -0
- package/dist/negotiation/jcs.js.map +1 -0
- package/dist/negotiation/ledger/event.d.ts +142 -0
- package/dist/negotiation/ledger/event.js +206 -0
- package/dist/negotiation/ledger/event.js.map +1 -0
- package/dist/negotiation/ledger/index.d.ts +26 -0
- package/dist/negotiation/ledger/index.js +25 -0
- package/dist/negotiation/ledger/index.js.map +1 -0
- package/dist/negotiation/ledger/store.d.ts +97 -0
- package/dist/negotiation/ledger/store.js +338 -0
- package/dist/negotiation/ledger/store.js.map +1 -0
- package/dist/negotiation/prompt.d.ts +34 -0
- package/dist/negotiation/prompt.js +113 -0
- package/dist/negotiation/prompt.js.map +1 -0
- package/dist/negotiation/recovery/index.d.ts +26 -0
- package/dist/negotiation/recovery/index.js +24 -0
- package/dist/negotiation/recovery/index.js.map +1 -0
- package/dist/negotiation/recovery/outbound.d.ts +49 -0
- package/dist/negotiation/recovery/outbound.js +34 -0
- package/dist/negotiation/recovery/outbound.js.map +1 -0
- package/dist/negotiation/recovery/recover.d.ts +59 -0
- package/dist/negotiation/recovery/recover.js +486 -0
- package/dist/negotiation/recovery/recover.js.map +1 -0
- package/dist/negotiation/recovery/types.d.ts +85 -0
- package/dist/negotiation/recovery/types.js +17 -0
- package/dist/negotiation/recovery/types.js.map +1 -0
- package/dist/negotiation/state/phase.d.ts +70 -0
- package/dist/negotiation/state/phase.js +200 -0
- package/dist/negotiation/state/phase.js.map +1 -0
- package/dist/negotiation/types.d.ts +139 -0
- package/dist/negotiation/types.js +24 -0
- package/dist/negotiation/types.js.map +1 -0
- package/dist/net/safe-http.d.ts +54 -0
- package/dist/net/safe-http.js +116 -0
- package/dist/net/safe-http.js.map +1 -0
- package/dist/operator/controller.d.ts +181 -0
- package/dist/operator/controller.js +784 -0
- package/dist/operator/controller.js.map +1 -0
- package/dist/operator/runner.d.ts +128 -0
- package/dist/operator/runner.js +248 -0
- package/dist/operator/runner.js.map +1 -0
- package/dist/operator/store.d.ts +39 -0
- package/dist/operator/store.js +169 -0
- package/dist/operator/store.js.map +1 -0
- package/dist/operator/strategy.d.ts +54 -0
- package/dist/operator/strategy.js +249 -0
- package/dist/operator/strategy.js.map +1 -0
- package/dist/operator/tui.d.ts +27 -0
- package/dist/operator/tui.js +395 -0
- package/dist/operator/tui.js.map +1 -0
- package/dist/operator/types.d.ts +224 -0
- package/dist/operator/types.js +17 -0
- package/dist/operator/types.js.map +1 -0
- package/dist/product-buyer.d.ts +74 -0
- package/dist/product-buyer.js +161 -0
- package/dist/product-buyer.js.map +1 -0
- package/dist/product-cli.d.ts +56 -0
- package/dist/product-cli.js +175 -0
- package/dist/product-cli.js.map +1 -0
- package/dist/product-compat.d.ts +50 -0
- package/dist/product-compat.js +63 -0
- package/dist/product-compat.js.map +1 -0
- package/dist/product-init.d.ts +73 -0
- package/dist/product-init.js +203 -0
- package/dist/product-init.js.map +1 -0
- package/dist/product-publish.d.ts +85 -0
- package/dist/product-publish.js +216 -0
- package/dist/product-publish.js.map +1 -0
- package/dist/protocol/legacy-shopping-negotiation/adapter.d.ts +42 -0
- package/dist/protocol/legacy-shopping-negotiation/adapter.js +561 -0
- package/dist/protocol/legacy-shopping-negotiation/adapter.js.map +1 -0
- package/dist/protocol/legacy-shopping-negotiation/mapping.d.ts +78 -0
- package/dist/protocol/legacy-shopping-negotiation/mapping.js +321 -0
- package/dist/protocol/legacy-shopping-negotiation/mapping.js.map +1 -0
- package/dist/protocol/legacy-shopping-negotiation/money.d.ts +49 -0
- package/dist/protocol/legacy-shopping-negotiation/money.js +70 -0
- package/dist/protocol/legacy-shopping-negotiation/money.js.map +1 -0
- package/dist/protocol/legacy-shopping-negotiation/types.d.ts +107 -0
- package/dist/protocol/legacy-shopping-negotiation/types.js +34 -0
- package/dist/protocol/legacy-shopping-negotiation/types.js.map +1 -0
- package/dist/runtime/buyer-policy.d.ts +58 -0
- package/dist/runtime/buyer-policy.js +89 -0
- package/dist/runtime/buyer-policy.js.map +1 -0
- package/dist/runtime/fake-model.d.ts +77 -0
- package/dist/runtime/fake-model.js +307 -0
- package/dist/runtime/fake-model.js.map +1 -0
- package/dist/runtime/foreground.d.ts +56 -0
- package/dist/runtime/foreground.js +97 -0
- package/dist/runtime/foreground.js.map +1 -0
- package/dist/runtime/heartbeat.d.ts +36 -0
- package/dist/runtime/heartbeat.js +49 -0
- package/dist/runtime/heartbeat.js.map +1 -0
- package/dist/runtime/merchant-turn.d.ts +35 -0
- package/dist/runtime/merchant-turn.js +20 -0
- package/dist/runtime/merchant-turn.js.map +1 -0
- package/dist/runtime/model.d.ts +40 -0
- package/dist/runtime/model.js +86 -0
- package/dist/runtime/model.js.map +1 -0
- package/dist/runtime/negotiation-turn.d.ts +101 -0
- package/dist/runtime/negotiation-turn.js +317 -0
- package/dist/runtime/negotiation-turn.js.map +1 -0
- package/dist/runtime/tools.d.ts +64 -0
- package/dist/runtime/tools.js +236 -0
- package/dist/runtime/tools.js.map +1 -0
- package/dist/supervisor/init.d.ts +31 -0
- package/dist/supervisor/init.js +222 -0
- package/dist/supervisor/init.js.map +1 -0
- package/dist/supervisor/logs.d.ts +28 -0
- package/dist/supervisor/logs.js +101 -0
- package/dist/supervisor/logs.js.map +1 -0
- package/dist/supervisor/manage.d.ts +72 -0
- package/dist/supervisor/manage.js +419 -0
- package/dist/supervisor/manage.js.map +1 -0
- package/dist/supervisor/manifest.d.ts +69 -0
- package/dist/supervisor/manifest.js +209 -0
- package/dist/supervisor/manifest.js.map +1 -0
- package/dist/supervisor/stack-config.d.ts +79 -0
- package/dist/supervisor/stack-config.js +262 -0
- package/dist/supervisor/stack-config.js.map +1 -0
- package/dist/supervisor/wrapper.d.ts +17 -0
- package/dist/supervisor/wrapper.js +138 -0
- package/dist/supervisor/wrapper.js.map +1 -0
- package/dist/trust/identity/auth-verifier.d.ts +96 -0
- package/dist/trust/identity/auth-verifier.js +166 -0
- package/dist/trust/identity/auth-verifier.js.map +1 -0
- package/dist/trust/identity/identity-binding.d.ts +63 -0
- package/dist/trust/identity/identity-binding.js +59 -0
- package/dist/trust/identity/identity-binding.js.map +1 -0
- package/dist/trust/identity/index.d.ts +38 -0
- package/dist/trust/identity/index.js +31 -0
- package/dist/trust/identity/index.js.map +1 -0
- package/dist/trust/identity/jws.d.ts +64 -0
- package/dist/trust/identity/jws.js +178 -0
- package/dist/trust/identity/jws.js.map +1 -0
- package/dist/trust/identity/keys.d.ts +71 -0
- package/dist/trust/identity/keys.js +118 -0
- package/dist/trust/identity/keys.js.map +1 -0
- package/dist/trust/identity/message-signature.d.ts +105 -0
- package/dist/trust/identity/message-signature.js +297 -0
- package/dist/trust/identity/message-signature.js.map +1 -0
- package/dist/trust/identity/nonce.d.ts +45 -0
- package/dist/trust/identity/nonce.js +50 -0
- package/dist/trust/identity/nonce.js.map +1 -0
- package/dist/trust/identity/signature-base.d.ts +84 -0
- package/dist/trust/identity/signature-base.js +261 -0
- package/dist/trust/identity/signature-base.js.map +1 -0
- package/dist/trust/identity/trust-policy.d.ts +92 -0
- package/dist/trust/identity/trust-policy.js +95 -0
- package/dist/trust/identity/trust-policy.js.map +1 -0
- package/dist/trust/index.d.ts +21 -0
- package/dist/trust/index.js +22 -0
- package/dist/trust/index.js.map +1 -0
- package/dist/trust/records/evaluator.d.ts +76 -0
- package/dist/trust/records/evaluator.js +122 -0
- package/dist/trust/records/evaluator.js.map +1 -0
- package/dist/trust/records/index.d.ts +28 -0
- package/dist/trust/records/index.js +26 -0
- package/dist/trust/records/index.js.map +1 -0
- package/dist/trust/records/store.d.ts +75 -0
- package/dist/trust/records/store.js +339 -0
- package/dist/trust/records/store.js.map +1 -0
- package/dist/trust/records/types.d.ts +159 -0
- package/dist/trust/records/types.js +40 -0
- package/dist/trust/records/types.js.map +1 -0
- package/dist/tui/banner.d.ts +46 -0
- package/dist/tui/banner.js +99 -0
- package/dist/tui/banner.js.map +1 -0
- package/dist/tui/styles.d.ts +70 -0
- package/dist/tui/styles.js +197 -0
- package/dist/tui/styles.js.map +1 -0
- package/dist/tui/theme.d.ts +63 -0
- package/dist/tui/theme.js +136 -0
- package/dist/tui/theme.js.map +1 -0
- package/examples/profiles/buyer.deepseek.yaml +34 -0
- package/examples/profiles/buyer.fake.yaml +36 -0
- package/examples/profiles/buyer.local.yaml +40 -0
- package/examples/profiles/merchant.deepseek.yaml +32 -0
- package/examples/profiles/merchant.fake.yaml +31 -0
- package/examples/profiles/merchant.local.yaml +34 -0
- package/package.json +55 -0
|
@@ -0,0 +1,637 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright 2026 harrylabsj
|
|
3
|
+
*
|
|
4
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
|
+
* you may not use this file except in compliance with the License.
|
|
6
|
+
* You may obtain a copy of the License at
|
|
7
|
+
*
|
|
8
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
9
|
+
*
|
|
10
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
11
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
12
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
|
+
* See the License for the specific language governing permissions and
|
|
14
|
+
* limitations under the License.
|
|
15
|
+
*/
|
|
16
|
+
import { uuidv7 } from "@earendil-works/pi-ai";
|
|
17
|
+
import { BuyerTaskError, DEFAULT_SEARCH_BUDGET, DEFAULT_TRACKING_POLICY, TASK_TRANSITIONS, } from "./types.js";
|
|
18
|
+
function opt(value) {
|
|
19
|
+
return value === null ? undefined : value;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Normalize a user/model-supplied RFC3339 to UTC ISO so the lexicographic
|
|
23
|
+
* due/expiry comparisons (next_run_at <= now, expires_at < now) are correct
|
|
24
|
+
* for mixed-offset inputs. Fail closed on non-timestamps.
|
|
25
|
+
*/
|
|
26
|
+
function normalizeIso(value) {
|
|
27
|
+
if (value === undefined || value === null)
|
|
28
|
+
return value;
|
|
29
|
+
const t = Date.parse(value);
|
|
30
|
+
if (Number.isNaN(t)) {
|
|
31
|
+
throw new BuyerTaskError("validation", "expires_at must be an RFC3339 timestamp");
|
|
32
|
+
}
|
|
33
|
+
return new Date(t).toISOString();
|
|
34
|
+
}
|
|
35
|
+
export class BuyerTaskStore {
|
|
36
|
+
db;
|
|
37
|
+
principalId;
|
|
38
|
+
now;
|
|
39
|
+
vault;
|
|
40
|
+
constructor(options) {
|
|
41
|
+
this.db = options.db;
|
|
42
|
+
this.principalId = options.principalId;
|
|
43
|
+
this.vault = options.vault;
|
|
44
|
+
// Normalize to UTC ISO: SQLite compares timestamps lexicographically,
|
|
45
|
+
// so mixed "+08:00"/"Z" spellings would silently break due checks.
|
|
46
|
+
const clock = options.now ?? (() => new Date().toISOString());
|
|
47
|
+
this.now = () => new Date(Date.parse(clock())).toISOString();
|
|
48
|
+
}
|
|
49
|
+
// ---- private budget sealing (design §11.2, §6.3) ---------------------------
|
|
50
|
+
/**
|
|
51
|
+
* A task-level private budget never lives in constraints_json as plaintext
|
|
52
|
+
* when a data key is available: it is sealed into the Vault and stored as
|
|
53
|
+
* `max_total_price_vault_ref`. Without a key it stays a number inside the
|
|
54
|
+
* per-agent 0600 database (the same tier as the profile's private config);
|
|
55
|
+
* either way the model-facing task output is redacted.
|
|
56
|
+
*/
|
|
57
|
+
sealConstraints(constraints) {
|
|
58
|
+
const price = constraints.max_total_price;
|
|
59
|
+
if (price === undefined || constraints.max_total_price_vault_ref !== undefined) {
|
|
60
|
+
return constraints;
|
|
61
|
+
}
|
|
62
|
+
if (!this.vault?.available)
|
|
63
|
+
return constraints;
|
|
64
|
+
return {
|
|
65
|
+
...constraints,
|
|
66
|
+
max_total_price: undefined,
|
|
67
|
+
max_total_price_vault_ref: this.sealVault("private_budget", String(price)),
|
|
68
|
+
};
|
|
69
|
+
}
|
|
70
|
+
sealVault(kind, plaintext) {
|
|
71
|
+
const vault = this.vault;
|
|
72
|
+
const now = this.now();
|
|
73
|
+
const fingerprint = vault.fingerprint(kind, plaintext);
|
|
74
|
+
const existing = this.db
|
|
75
|
+
.prepare("SELECT vault_ref FROM private_vault WHERE principal_id = ? AND kind = ? AND value_fingerprint = ?")
|
|
76
|
+
.get(this.principalId, kind, fingerprint);
|
|
77
|
+
if (existing !== undefined)
|
|
78
|
+
return existing.vault_ref;
|
|
79
|
+
const sealed = vault.seal(kind, plaintext);
|
|
80
|
+
const ref = `vr_${uuidv7()}`;
|
|
81
|
+
this.db
|
|
82
|
+
.prepare(`INSERT INTO private_vault
|
|
83
|
+
(vault_ref, principal_id, kind, ciphertext, nonce, key_version, value_fingerprint,
|
|
84
|
+
retention_json, created_at, updated_at)
|
|
85
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, '{}', ?, ?)`)
|
|
86
|
+
.run(ref, this.principalId, kind, sealed.ciphertext, sealed.nonce, sealed.key_version, sealed.value_fingerprint, now, now);
|
|
87
|
+
return ref;
|
|
88
|
+
}
|
|
89
|
+
/** Resolve the effective task budget: plaintext number, or the Vault value. */
|
|
90
|
+
resolveBudget(constraints) {
|
|
91
|
+
if (constraints.max_total_price !== undefined)
|
|
92
|
+
return constraints.max_total_price;
|
|
93
|
+
if (constraints.max_total_price_vault_ref === undefined)
|
|
94
|
+
return undefined;
|
|
95
|
+
if (this.vault === undefined) {
|
|
96
|
+
throw new BuyerTaskError("vault_unavailable", "task budget is vaulted but no vault is configured for this store");
|
|
97
|
+
}
|
|
98
|
+
const row = this.db
|
|
99
|
+
.prepare("SELECT * FROM private_vault WHERE vault_ref = ? AND principal_id = ?")
|
|
100
|
+
.get(constraints.max_total_price_vault_ref, this.principalId);
|
|
101
|
+
if (row === undefined) {
|
|
102
|
+
throw new BuyerTaskError("not_found", `no vault entry ${constraints.max_total_price_vault_ref}`);
|
|
103
|
+
}
|
|
104
|
+
const value = this.vault.open(row.key_version, row.nonce, row.ciphertext);
|
|
105
|
+
const n = Number(value);
|
|
106
|
+
return Number.isFinite(n) ? n : undefined;
|
|
107
|
+
}
|
|
108
|
+
// ---- tasks ----------------------------------------------------------------
|
|
109
|
+
createTask(input) {
|
|
110
|
+
if (input.goal_text.trim() === "") {
|
|
111
|
+
throw new BuyerTaskError("validation", "goal_text must not be empty");
|
|
112
|
+
}
|
|
113
|
+
const now = this.now();
|
|
114
|
+
const taskId = `task_${uuidv7()}`;
|
|
115
|
+
this.db.exec("BEGIN");
|
|
116
|
+
try {
|
|
117
|
+
// Content-addressed idempotency: a retried create with the same key is a
|
|
118
|
+
// replay — return the existing task instead of duplicating it.
|
|
119
|
+
const existing = this.eventByIdempotencyKey(input.idempotency_key);
|
|
120
|
+
if (existing !== undefined) {
|
|
121
|
+
const replayed = this.getTask(existing.task_id);
|
|
122
|
+
if (replayed !== undefined) {
|
|
123
|
+
this.db.exec("COMMIT");
|
|
124
|
+
return replayed;
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
this.db
|
|
128
|
+
.prepare(`INSERT INTO buyer_tasks
|
|
129
|
+
(task_id, principal_id, status, goal_text, intent_json, constraints_json,
|
|
130
|
+
ranking_policy_json, connector_scope_json, search_budget_json, tracking_policy_json,
|
|
131
|
+
next_run_at, expires_at, version, created_at, updated_at)
|
|
132
|
+
VALUES (?, ?, 'draft', ?, ?, ?, ?, ?, ?, ?, NULL, ?, 1, ?, ?)`)
|
|
133
|
+
.run(taskId, this.principalId, input.goal_text, JSON.stringify(input.intent), JSON.stringify(this.sealConstraints(input.constraints ?? {})), JSON.stringify(input.ranking_policy ?? { weights: {}, sources: {} }), JSON.stringify(input.connector_scope ?? { connectors: ["shopping-cli"] }), JSON.stringify({ ...DEFAULT_SEARCH_BUDGET, ...input.search_budget }), JSON.stringify({ ...DEFAULT_TRACKING_POLICY, ...input.tracking_policy }), normalizeIso(input.expires_at) ?? null, now, now);
|
|
134
|
+
this.appendEventTx(taskId, "created", { goal_text: input.goal_text }, "user", input.idempotency_key, now);
|
|
135
|
+
this.db.exec("COMMIT");
|
|
136
|
+
}
|
|
137
|
+
catch (err) {
|
|
138
|
+
this.db.exec("ROLLBACK");
|
|
139
|
+
throw err;
|
|
140
|
+
}
|
|
141
|
+
return this.getTask(taskId);
|
|
142
|
+
}
|
|
143
|
+
getTask(taskId) {
|
|
144
|
+
const row = this.db
|
|
145
|
+
.prepare("SELECT * FROM buyer_tasks WHERE task_id = ? AND principal_id = ?")
|
|
146
|
+
.get(taskId, this.principalId);
|
|
147
|
+
return row === undefined ? undefined : this.rowToTask(row);
|
|
148
|
+
}
|
|
149
|
+
listTasks(filter = {}) {
|
|
150
|
+
const statuses = filter.statuses ?? [
|
|
151
|
+
"draft",
|
|
152
|
+
"clarifying",
|
|
153
|
+
"ready",
|
|
154
|
+
"searching",
|
|
155
|
+
"tracking",
|
|
156
|
+
"shortlist_ready",
|
|
157
|
+
"awaiting_user",
|
|
158
|
+
"consulting",
|
|
159
|
+
"negotiating",
|
|
160
|
+
];
|
|
161
|
+
const rows = this.db
|
|
162
|
+
.prepare(`SELECT * FROM buyer_tasks
|
|
163
|
+
WHERE principal_id = ? AND (${statuses.map(() => "status = ?").join(" OR ")})
|
|
164
|
+
ORDER BY created_at`)
|
|
165
|
+
.all(this.principalId, ...statuses);
|
|
166
|
+
return rows.map((r) => this.rowToTask(r));
|
|
167
|
+
}
|
|
168
|
+
/**
|
|
169
|
+
* Legal-transition state machine with optimistic versioning (§11.3):
|
|
170
|
+
* the update carries expected_version so a background wakeup and a user
|
|
171
|
+
* command can never silently overwrite each other. The transition event
|
|
172
|
+
* is idempotent by idempotency_key (replays don't double-transition).
|
|
173
|
+
*/
|
|
174
|
+
transitionTask(input) {
|
|
175
|
+
const now = this.now();
|
|
176
|
+
this.db.exec("BEGIN");
|
|
177
|
+
try {
|
|
178
|
+
const existing = this.eventByIdempotencyKey(input.idempotency_key);
|
|
179
|
+
if (existing !== undefined) {
|
|
180
|
+
this.db.exec("COMMIT");
|
|
181
|
+
return this.getTask(input.task_id); // replay: no-op
|
|
182
|
+
}
|
|
183
|
+
const task = this.getTask(input.task_id);
|
|
184
|
+
if (task === undefined) {
|
|
185
|
+
throw new BuyerTaskError("not_found", `no task ${input.task_id}`);
|
|
186
|
+
}
|
|
187
|
+
const legal = TASK_TRANSITIONS[task.status];
|
|
188
|
+
if (!legal.includes(input.to)) {
|
|
189
|
+
throw new BuyerTaskError("illegal_transition", `task ${input.task_id}: ${task.status} -> ${input.to} is not a legal transition`);
|
|
190
|
+
}
|
|
191
|
+
const updated = this.db
|
|
192
|
+
.prepare(`UPDATE buyer_tasks
|
|
193
|
+
SET status = ?, next_run_at = COALESCE(?, next_run_at),
|
|
194
|
+
selected_candidate_id = COALESCE(?, selected_candidate_id),
|
|
195
|
+
version = version + 1, updated_at = ?
|
|
196
|
+
WHERE task_id = ? AND version = ?`)
|
|
197
|
+
.run(input.to, input.next_run_at === undefined ? null : input.next_run_at, input.selected_candidate_id ?? null, now, input.task_id, input.expected_version);
|
|
198
|
+
if (updated.changes !== 1) {
|
|
199
|
+
throw new BuyerTaskError("conflict", `task ${input.task_id} version conflict (expected ${input.expected_version}); another writer moved first`);
|
|
200
|
+
}
|
|
201
|
+
this.appendEventTx(input.task_id, input.event_type, { from: task.status, to: input.to, ...input.payload }, input.origin, input.idempotency_key, now);
|
|
202
|
+
this.db.exec("COMMIT");
|
|
203
|
+
return this.getTask(input.task_id);
|
|
204
|
+
}
|
|
205
|
+
catch (err) {
|
|
206
|
+
this.db.exec("ROLLBACK");
|
|
207
|
+
throw err;
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
/** Patch constraints / intent / policies (no status change; version-guarded). */
|
|
211
|
+
updateTask(taskId, patch, expectedVersion, idempotencyKey) {
|
|
212
|
+
const now = this.now();
|
|
213
|
+
this.db.exec("BEGIN");
|
|
214
|
+
try {
|
|
215
|
+
if (this.eventByIdempotencyKey(idempotencyKey) === undefined) {
|
|
216
|
+
const task = this.getTask(taskId);
|
|
217
|
+
if (task === undefined)
|
|
218
|
+
throw new BuyerTaskError("not_found", `no task ${taskId}`);
|
|
219
|
+
const stmt = this.db.prepare(`UPDATE buyer_tasks
|
|
220
|
+
SET intent_json = ?, constraints_json = ?, ranking_policy_json = ?,
|
|
221
|
+
next_run_at = ?, expires_at = ?, version = version + 1, updated_at = ?
|
|
222
|
+
WHERE task_id = ? AND version = ?`);
|
|
223
|
+
const res = stmt.run(JSON.stringify(patch.intent ?? task.intent), JSON.stringify(patch.constraints !== undefined ? this.sealConstraints(patch.constraints) : task.constraints), JSON.stringify(patch.ranking_policy ?? task.ranking_policy), patch.next_run_at === undefined ? (task.next_run_at ?? null) : patch.next_run_at, patch.expires_at === undefined
|
|
224
|
+
? (task.expires_at ?? null)
|
|
225
|
+
: (normalizeIso(patch.expires_at) ?? null), now, taskId, expectedVersion);
|
|
226
|
+
if (res.changes !== 1) {
|
|
227
|
+
throw new BuyerTaskError("conflict", `task ${taskId} version conflict`);
|
|
228
|
+
}
|
|
229
|
+
this.appendEventTx(taskId, "clarified", { patch: Object.keys(patch) }, "user", idempotencyKey, now);
|
|
230
|
+
}
|
|
231
|
+
this.db.exec("COMMIT");
|
|
232
|
+
return this.getTask(taskId);
|
|
233
|
+
}
|
|
234
|
+
catch (err) {
|
|
235
|
+
this.db.exec("ROLLBACK");
|
|
236
|
+
throw err;
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
// ---- events -----------------------------------------------------------------
|
|
240
|
+
appendEventTx(taskId, type, payload, origin, idempotencyKey, now) {
|
|
241
|
+
this.db
|
|
242
|
+
.prepare(`INSERT OR IGNORE INTO task_events
|
|
243
|
+
(event_id, task_id, type, payload_json, origin, idempotency_key, created_at)
|
|
244
|
+
VALUES (?, ?, ?, ?, ?, ?, ?)`)
|
|
245
|
+
.run(`tev_${uuidv7()}`, taskId, type, JSON.stringify(payload), origin, idempotencyKey, now);
|
|
246
|
+
}
|
|
247
|
+
/**
|
|
248
|
+
* Idempotent standalone event (notifications, observations, merges).
|
|
249
|
+
* Returns whether the row was newly inserted (false = idempotency replay),
|
|
250
|
+
* so callers can skip duplicate user-visible notifications.
|
|
251
|
+
*/
|
|
252
|
+
appendEvent(taskId, type, payload, origin, idempotencyKey) {
|
|
253
|
+
const res = this.db
|
|
254
|
+
.prepare(`INSERT OR IGNORE INTO task_events
|
|
255
|
+
(event_id, task_id, type, payload_json, origin, idempotency_key, created_at)
|
|
256
|
+
VALUES (?, ?, ?, ?, ?, ?, ?)`)
|
|
257
|
+
.run(`tev_${uuidv7()}`, taskId, type, JSON.stringify(payload), origin, idempotencyKey, this.now());
|
|
258
|
+
return res.changes === 1;
|
|
259
|
+
}
|
|
260
|
+
eventByIdempotencyKey(key) {
|
|
261
|
+
const row = this.db
|
|
262
|
+
.prepare("SELECT * FROM task_events WHERE idempotency_key = ?")
|
|
263
|
+
.get(key);
|
|
264
|
+
return row === undefined ? undefined : this.rowToEvent(row);
|
|
265
|
+
}
|
|
266
|
+
taskEvents(taskId) {
|
|
267
|
+
const rows = this.db
|
|
268
|
+
.prepare("SELECT * FROM task_events WHERE task_id = ? ORDER BY created_at, event_id")
|
|
269
|
+
.all(taskId);
|
|
270
|
+
return rows.map((r) => this.rowToEvent(r));
|
|
271
|
+
}
|
|
272
|
+
// ---- candidates & observations --------------------------------------------
|
|
273
|
+
/**
|
|
274
|
+
* Upsert by (task_id, canonical_key) — canonical_key is connector + SKU
|
|
275
|
+
* (or connector + external product id), never the title (§11.5).
|
|
276
|
+
*/
|
|
277
|
+
upsertCandidate(input) {
|
|
278
|
+
const now = this.now();
|
|
279
|
+
const canonicalKey = `${input.connector_id}:${input.sku ?? input.external_product_id}`;
|
|
280
|
+
const existing = this.db
|
|
281
|
+
.prepare("SELECT * FROM product_candidates WHERE task_id = ? AND canonical_key = ?")
|
|
282
|
+
.get(input.task_id, canonicalKey);
|
|
283
|
+
if (existing !== undefined) {
|
|
284
|
+
this.db
|
|
285
|
+
.prepare("UPDATE product_candidates SET last_seen_at = ? WHERE candidate_id = ?")
|
|
286
|
+
.run(now, existing.candidate_id);
|
|
287
|
+
return this.getCandidate(existing.candidate_id);
|
|
288
|
+
}
|
|
289
|
+
const candidateId = `cand_${uuidv7()}`;
|
|
290
|
+
this.db
|
|
291
|
+
.prepare(`INSERT INTO product_candidates
|
|
292
|
+
(candidate_id, task_id, connector_id, platform, external_product_id, sku, merchant_id,
|
|
293
|
+
canonical_key, eligibility, candidate_status, first_seen_at, last_seen_at)
|
|
294
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?, 'unknown', 'discovered', ?, ?)`)
|
|
295
|
+
.run(candidateId, input.task_id, input.connector_id, input.platform, input.external_product_id, input.sku ?? null, input.merchant_id ?? null, canonicalKey, now, now);
|
|
296
|
+
return this.getCandidate(candidateId);
|
|
297
|
+
}
|
|
298
|
+
getCandidate(candidateId) {
|
|
299
|
+
const row = this.db
|
|
300
|
+
.prepare("SELECT * FROM product_candidates WHERE candidate_id = ?")
|
|
301
|
+
.get(candidateId);
|
|
302
|
+
return row === undefined ? undefined : this.rowToCandidate(row);
|
|
303
|
+
}
|
|
304
|
+
listCandidates(taskId, filter = {}) {
|
|
305
|
+
const rows = this.db
|
|
306
|
+
.prepare("SELECT * FROM product_candidates WHERE task_id = ? ORDER BY first_seen_at, candidate_id")
|
|
307
|
+
.all(taskId);
|
|
308
|
+
return rows
|
|
309
|
+
.map((r) => this.rowToCandidate(r))
|
|
310
|
+
.filter((c) => filter.statuses === undefined || filter.statuses.includes(c.candidate_status));
|
|
311
|
+
}
|
|
312
|
+
updateCandidate(candidateId, patch) {
|
|
313
|
+
const c = this.getCandidate(candidateId);
|
|
314
|
+
if (c === undefined)
|
|
315
|
+
throw new BuyerTaskError("not_found", `no candidate ${candidateId}`);
|
|
316
|
+
this.db
|
|
317
|
+
.prepare(`UPDATE product_candidates
|
|
318
|
+
SET eligibility = ?, candidate_status = ?, score = ?, score_explanation_json = ?,
|
|
319
|
+
rejection_reasons_json = ?, latest_observation_id = ?, last_seen_at = ?
|
|
320
|
+
WHERE candidate_id = ?`)
|
|
321
|
+
.run(patch.eligibility ?? c.eligibility, patch.candidate_status ?? c.candidate_status, patch.score ?? c.score ?? null, patch.score_explanation !== undefined
|
|
322
|
+
? JSON.stringify(patch.score_explanation)
|
|
323
|
+
: c.score_explanation !== undefined
|
|
324
|
+
? JSON.stringify(c.score_explanation)
|
|
325
|
+
: null, patch.rejection_reasons !== undefined
|
|
326
|
+
? JSON.stringify(patch.rejection_reasons)
|
|
327
|
+
: JSON.stringify(c.rejection_reasons), patch.latest_observation_id ?? c.latest_observation_id ?? null, this.now(), candidateId);
|
|
328
|
+
return this.getCandidate(candidateId);
|
|
329
|
+
}
|
|
330
|
+
/** Dedup by content_hash: an identical observation is never stored twice (§11.6). */
|
|
331
|
+
addObservation(input) {
|
|
332
|
+
const existing = this.db
|
|
333
|
+
.prepare("SELECT observation_id FROM product_observations WHERE candidate_id = ? AND content_hash = ?")
|
|
334
|
+
.get(input.candidate_id, input.content_hash);
|
|
335
|
+
if (existing !== undefined) {
|
|
336
|
+
// Same facts re-verified: keep observed_at for trend, but EXTEND the
|
|
337
|
+
// freshness window — otherwise a repeatedly-rechecked unchanged fact
|
|
338
|
+
// stays permanently stale and is misreported as "过期" (§11.6).
|
|
339
|
+
this.db
|
|
340
|
+
.prepare("UPDATE product_observations SET fresh_until = ? WHERE observation_id = ?")
|
|
341
|
+
.run(input.fresh_until, existing.observation_id);
|
|
342
|
+
return { added: false, observation_id: existing.observation_id };
|
|
343
|
+
}
|
|
344
|
+
const observationId = `obs_${uuidv7()}`;
|
|
345
|
+
this.db
|
|
346
|
+
.prepare(`INSERT INTO product_observations
|
|
347
|
+
(observation_id, candidate_id, observed_at, source_url_or_ref, title,
|
|
348
|
+
price_json, promotion_json, stock_json, delivery_json, after_sales_json,
|
|
349
|
+
merchant_json, content_hash, fresh_until)
|
|
350
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`)
|
|
351
|
+
.run(observationId, input.candidate_id, input.observed_at, input.source_url_or_ref, input.title, JSON.stringify(input.price), JSON.stringify(input.promotion), JSON.stringify(input.stock), JSON.stringify(input.delivery), JSON.stringify(input.after_sales), JSON.stringify(input.merchant), input.content_hash, input.fresh_until);
|
|
352
|
+
return { added: true, observation_id: observationId };
|
|
353
|
+
}
|
|
354
|
+
latestObservation(candidateId) {
|
|
355
|
+
const row = this.db
|
|
356
|
+
.prepare("SELECT * FROM product_observations WHERE candidate_id = ? ORDER BY observed_at DESC LIMIT 1")
|
|
357
|
+
.get(candidateId);
|
|
358
|
+
return row === undefined ? undefined : this.rowToObservation(row);
|
|
359
|
+
}
|
|
360
|
+
observations(candidateId, limit = 20) {
|
|
361
|
+
const rows = this.db
|
|
362
|
+
.prepare("SELECT * FROM product_observations WHERE candidate_id = ? ORDER BY observed_at DESC LIMIT ?")
|
|
363
|
+
.all(candidateId, limit);
|
|
364
|
+
return rows.map((r) => this.rowToObservation(r));
|
|
365
|
+
}
|
|
366
|
+
// ---- tracking rules ---------------------------------------------------------
|
|
367
|
+
addTrackingRule(input) {
|
|
368
|
+
if (!Number.isInteger(input.interval_seconds) || input.interval_seconds <= 0) {
|
|
369
|
+
throw new BuyerTaskError("validation", "interval_seconds must be a positive integer");
|
|
370
|
+
}
|
|
371
|
+
const now = this.now();
|
|
372
|
+
const ruleId = `rule_${uuidv7()}`;
|
|
373
|
+
const next = new Date(Date.parse(now) + input.interval_seconds * 1000).toISOString();
|
|
374
|
+
this.db
|
|
375
|
+
.prepare(`INSERT INTO tracking_rules
|
|
376
|
+
(rule_id, task_id, candidate_id, rule_type, condition_json, interval_seconds,
|
|
377
|
+
next_check_at, cooldown_seconds, status)
|
|
378
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?, 'active')`)
|
|
379
|
+
.run(ruleId, input.task_id, input.candidate_id ?? null, input.rule_type, JSON.stringify(input.condition), input.interval_seconds, next, input.cooldown_seconds ?? 0);
|
|
380
|
+
return this.getRule(ruleId);
|
|
381
|
+
}
|
|
382
|
+
getRule(ruleId) {
|
|
383
|
+
const row = this.db
|
|
384
|
+
.prepare("SELECT * FROM tracking_rules WHERE rule_id = ?")
|
|
385
|
+
.get(ruleId);
|
|
386
|
+
return row === undefined ? undefined : this.rowToRule(row);
|
|
387
|
+
}
|
|
388
|
+
rulesForTask(taskId) {
|
|
389
|
+
const rows = this.db
|
|
390
|
+
.prepare("SELECT * FROM tracking_rules WHERE task_id = ? ORDER BY rule_id")
|
|
391
|
+
.all(taskId);
|
|
392
|
+
return rows.map((r) => this.rowToRule(r));
|
|
393
|
+
}
|
|
394
|
+
/** Rules due for a check (scheduler input). */
|
|
395
|
+
dueRules(now, limit) {
|
|
396
|
+
const rows = this.db
|
|
397
|
+
.prepare(`SELECT * FROM tracking_rules
|
|
398
|
+
WHERE status = 'active' AND next_check_at <= ?
|
|
399
|
+
ORDER BY next_check_at, rule_id LIMIT ?`)
|
|
400
|
+
.all(now, limit);
|
|
401
|
+
return rows.map((r) => this.rowToRule(r));
|
|
402
|
+
}
|
|
403
|
+
/** Tasks due for a scheduler wakeup (restart recovery derives the queue from this). */
|
|
404
|
+
dueTasks(now, limit) {
|
|
405
|
+
const rows = this.db
|
|
406
|
+
.prepare(`SELECT * FROM buyer_tasks
|
|
407
|
+
WHERE principal_id = ? AND next_run_at IS NOT NULL AND next_run_at <= ?
|
|
408
|
+
AND status IN ('ready','searching','tracking')
|
|
409
|
+
ORDER BY next_run_at, task_id LIMIT ?`)
|
|
410
|
+
.all(this.principalId, now, limit);
|
|
411
|
+
return rows.map((r) => this.rowToTask(r));
|
|
412
|
+
}
|
|
413
|
+
/** Tracking tasks whose expires_at passed (only tracking -> expired is legal, §11.3). */
|
|
414
|
+
expirableTasks(now) {
|
|
415
|
+
const rows = this.db
|
|
416
|
+
.prepare(`SELECT * FROM buyer_tasks
|
|
417
|
+
WHERE principal_id = ? AND expires_at IS NOT NULL AND expires_at < ?
|
|
418
|
+
AND status = 'tracking'`)
|
|
419
|
+
.all(this.principalId, now);
|
|
420
|
+
return rows.map((r) => this.rowToTask(r));
|
|
421
|
+
}
|
|
422
|
+
pauseRule(ruleId) {
|
|
423
|
+
return this.setRuleStatus(ruleId, "paused");
|
|
424
|
+
}
|
|
425
|
+
completeRule(ruleId) {
|
|
426
|
+
return this.setRuleStatus(ruleId, "completed");
|
|
427
|
+
}
|
|
428
|
+
setRuleStatus(ruleId, status) {
|
|
429
|
+
const res = this.db
|
|
430
|
+
.prepare("UPDATE tracking_rules SET status = ? WHERE rule_id = ?")
|
|
431
|
+
.run(status, ruleId);
|
|
432
|
+
if (res.changes !== 1)
|
|
433
|
+
throw new BuyerTaskError("not_found", `no rule ${ruleId}`);
|
|
434
|
+
return this.getRule(ruleId);
|
|
435
|
+
}
|
|
436
|
+
/** Mark a rule checked: reschedule next_check_at; record trigger time when fired. */
|
|
437
|
+
markRuleChecked(ruleId, triggered, now) {
|
|
438
|
+
const rule = this.getRule(ruleId);
|
|
439
|
+
if (rule === undefined)
|
|
440
|
+
throw new BuyerTaskError("not_found", `no rule ${ruleId}`);
|
|
441
|
+
const next = new Date(Date.parse(now) + rule.interval_seconds * 1000).toISOString();
|
|
442
|
+
this.db
|
|
443
|
+
.prepare(`UPDATE tracking_rules
|
|
444
|
+
SET next_check_at = ?, last_triggered_at = CASE WHEN ? THEN ? ELSE last_triggered_at END
|
|
445
|
+
WHERE rule_id = ?`)
|
|
446
|
+
.run(next, triggered ? 1 : 0, now, ruleId);
|
|
447
|
+
}
|
|
448
|
+
// ---- consultation links (design §11.8) -----------------------------------
|
|
449
|
+
/**
|
|
450
|
+
* Associate a Buyer task + candidate with an authoritative Marketplace
|
|
451
|
+
* Conversation. Idempotent per (task_id, conversation_id): a retried link
|
|
452
|
+
* returns the existing row instead of duplicating it.
|
|
453
|
+
*/
|
|
454
|
+
createConsultationLink(input) {
|
|
455
|
+
const now = this.now();
|
|
456
|
+
this.db.exec("BEGIN");
|
|
457
|
+
try {
|
|
458
|
+
if (this.eventByIdempotencyKey(input.idempotency_key) !== undefined) {
|
|
459
|
+
const existing = this.db
|
|
460
|
+
.prepare("SELECT * FROM consultation_links WHERE task_id = ? AND conversation_id = ?")
|
|
461
|
+
.get(input.task_id, input.conversation_id);
|
|
462
|
+
this.db.exec("COMMIT");
|
|
463
|
+
if (existing !== undefined)
|
|
464
|
+
return this.rowToLink(existing);
|
|
465
|
+
}
|
|
466
|
+
const task = this.getTask(input.task_id);
|
|
467
|
+
if (task === undefined)
|
|
468
|
+
throw new BuyerTaskError("not_found", `no task ${input.task_id}`);
|
|
469
|
+
if (input.candidate_id !== undefined) {
|
|
470
|
+
const candidate = this.getCandidate(input.candidate_id);
|
|
471
|
+
if (candidate === undefined || candidate.task_id !== input.task_id) {
|
|
472
|
+
throw new BuyerTaskError("not_found", `no candidate ${input.candidate_id} in task`);
|
|
473
|
+
}
|
|
474
|
+
}
|
|
475
|
+
const linkId = `link_${uuidv7()}`;
|
|
476
|
+
this.db
|
|
477
|
+
.prepare(`INSERT INTO consultation_links
|
|
478
|
+
(link_id, task_id, candidate_id, connector_id, conversation_id, status, created_at, updated_at)
|
|
479
|
+
VALUES (?, ?, ?, ?, ?, 'consulting', ?, ?)`)
|
|
480
|
+
.run(linkId, input.task_id, input.candidate_id ?? null, input.connector_id, input.conversation_id, now, now);
|
|
481
|
+
this.appendEventTx(input.task_id, "consultation_linked", { link_id: linkId, conversation_id: input.conversation_id, candidate_id: input.candidate_id ?? null }, "model", input.idempotency_key, now);
|
|
482
|
+
this.db.exec("COMMIT");
|
|
483
|
+
return this.getConsultationLink(linkId);
|
|
484
|
+
}
|
|
485
|
+
catch (err) {
|
|
486
|
+
this.db.exec("ROLLBACK");
|
|
487
|
+
throw err;
|
|
488
|
+
}
|
|
489
|
+
}
|
|
490
|
+
getConsultationLink(linkId) {
|
|
491
|
+
const row = this.db
|
|
492
|
+
.prepare("SELECT * FROM consultation_links WHERE link_id = ?")
|
|
493
|
+
.get(linkId);
|
|
494
|
+
return row === undefined ? undefined : this.rowToLink(row);
|
|
495
|
+
}
|
|
496
|
+
linksForTask(taskId) {
|
|
497
|
+
const rows = this.db
|
|
498
|
+
.prepare("SELECT * FROM consultation_links WHERE task_id = ? ORDER BY created_at, link_id")
|
|
499
|
+
.all(taskId);
|
|
500
|
+
return rows.map((r) => this.rowToLink(r));
|
|
501
|
+
}
|
|
502
|
+
linkByConversation(conversationId) {
|
|
503
|
+
const row = this.db
|
|
504
|
+
.prepare("SELECT * FROM consultation_links WHERE conversation_id = ? LIMIT 1")
|
|
505
|
+
.get(conversationId);
|
|
506
|
+
return row === undefined ? undefined : this.rowToLink(row);
|
|
507
|
+
}
|
|
508
|
+
updateConsultationLink(linkId, patch) {
|
|
509
|
+
const link = this.getConsultationLink(linkId);
|
|
510
|
+
if (link === undefined)
|
|
511
|
+
throw new BuyerTaskError("not_found", `no consultation link ${linkId}`);
|
|
512
|
+
this.db
|
|
513
|
+
.prepare(`UPDATE consultation_links
|
|
514
|
+
SET status = ?, last_message_id = ?, updated_at = ?
|
|
515
|
+
WHERE link_id = ?`)
|
|
516
|
+
.run(patch.status ?? link.status, patch.last_message_id === undefined ? (link.last_message_id ?? null) : patch.last_message_id, this.now(), linkId);
|
|
517
|
+
return this.getConsultationLink(linkId);
|
|
518
|
+
}
|
|
519
|
+
// ---- row mapping -------------------------------------------------------------
|
|
520
|
+
rowToTask(row) {
|
|
521
|
+
const task = {
|
|
522
|
+
task_id: row.task_id,
|
|
523
|
+
principal_id: row.principal_id,
|
|
524
|
+
status: row.status,
|
|
525
|
+
goal_text: row.goal_text,
|
|
526
|
+
intent: JSON.parse(row.intent_json),
|
|
527
|
+
constraints: JSON.parse(row.constraints_json),
|
|
528
|
+
ranking_policy: JSON.parse(row.ranking_policy_json),
|
|
529
|
+
connector_scope: JSON.parse(row.connector_scope_json),
|
|
530
|
+
search_budget: JSON.parse(row.search_budget_json),
|
|
531
|
+
tracking_policy: JSON.parse(row.tracking_policy_json),
|
|
532
|
+
version: row.version,
|
|
533
|
+
created_at: row.created_at,
|
|
534
|
+
updated_at: row.updated_at,
|
|
535
|
+
};
|
|
536
|
+
const selected = opt(row.selected_candidate_id);
|
|
537
|
+
if (selected !== undefined)
|
|
538
|
+
task.selected_candidate_id = selected;
|
|
539
|
+
const nextRun = opt(row.next_run_at);
|
|
540
|
+
if (nextRun !== undefined)
|
|
541
|
+
task.next_run_at = nextRun;
|
|
542
|
+
const expires = opt(row.expires_at);
|
|
543
|
+
if (expires !== undefined)
|
|
544
|
+
task.expires_at = expires;
|
|
545
|
+
return task;
|
|
546
|
+
}
|
|
547
|
+
rowToEvent(row) {
|
|
548
|
+
return {
|
|
549
|
+
event_id: row.event_id,
|
|
550
|
+
task_id: row.task_id,
|
|
551
|
+
type: row.type,
|
|
552
|
+
payload: JSON.parse(row.payload_json),
|
|
553
|
+
origin: row.origin,
|
|
554
|
+
idempotency_key: row.idempotency_key,
|
|
555
|
+
created_at: row.created_at,
|
|
556
|
+
};
|
|
557
|
+
}
|
|
558
|
+
rowToCandidate(row) {
|
|
559
|
+
const c = {
|
|
560
|
+
candidate_id: row.candidate_id,
|
|
561
|
+
task_id: row.task_id,
|
|
562
|
+
connector_id: row.connector_id,
|
|
563
|
+
platform: row.platform,
|
|
564
|
+
external_product_id: row.external_product_id,
|
|
565
|
+
canonical_key: row.canonical_key,
|
|
566
|
+
eligibility: row.eligibility,
|
|
567
|
+
candidate_status: row.candidate_status,
|
|
568
|
+
rejection_reasons: JSON.parse(row.rejection_reasons_json ?? "[]"),
|
|
569
|
+
first_seen_at: row.first_seen_at,
|
|
570
|
+
last_seen_at: row.last_seen_at,
|
|
571
|
+
};
|
|
572
|
+
if (row.sku !== null)
|
|
573
|
+
c.sku = row.sku;
|
|
574
|
+
if (row.merchant_id !== null)
|
|
575
|
+
c.merchant_id = row.merchant_id;
|
|
576
|
+
if (row.score !== null)
|
|
577
|
+
c.score = row.score;
|
|
578
|
+
if (row.score_explanation_json !== null) {
|
|
579
|
+
c.score_explanation = JSON.parse(row.score_explanation_json);
|
|
580
|
+
}
|
|
581
|
+
if (row.latest_observation_id !== null) {
|
|
582
|
+
c.latest_observation_id = row.latest_observation_id;
|
|
583
|
+
}
|
|
584
|
+
return c;
|
|
585
|
+
}
|
|
586
|
+
rowToObservation(row) {
|
|
587
|
+
return {
|
|
588
|
+
observation_id: row.observation_id,
|
|
589
|
+
candidate_id: row.candidate_id,
|
|
590
|
+
observed_at: row.observed_at,
|
|
591
|
+
source_url_or_ref: row.source_url_or_ref,
|
|
592
|
+
title: row.title,
|
|
593
|
+
price: JSON.parse(row.price_json),
|
|
594
|
+
promotion: JSON.parse(row.promotion_json),
|
|
595
|
+
stock: JSON.parse(row.stock_json),
|
|
596
|
+
delivery: JSON.parse(row.delivery_json),
|
|
597
|
+
after_sales: JSON.parse(row.after_sales_json),
|
|
598
|
+
merchant: JSON.parse(row.merchant_json),
|
|
599
|
+
content_hash: row.content_hash,
|
|
600
|
+
fresh_until: row.fresh_until,
|
|
601
|
+
};
|
|
602
|
+
}
|
|
603
|
+
rowToRule(row) {
|
|
604
|
+
const rule = {
|
|
605
|
+
rule_id: row.rule_id,
|
|
606
|
+
task_id: row.task_id,
|
|
607
|
+
rule_type: row.rule_type,
|
|
608
|
+
condition: JSON.parse(row.condition_json),
|
|
609
|
+
interval_seconds: row.interval_seconds,
|
|
610
|
+
next_check_at: row.next_check_at,
|
|
611
|
+
cooldown_seconds: row.cooldown_seconds,
|
|
612
|
+
status: row.status,
|
|
613
|
+
};
|
|
614
|
+
if (row.candidate_id !== null)
|
|
615
|
+
rule.candidate_id = row.candidate_id;
|
|
616
|
+
if (row.last_triggered_at !== null)
|
|
617
|
+
rule.last_triggered_at = row.last_triggered_at;
|
|
618
|
+
return rule;
|
|
619
|
+
}
|
|
620
|
+
rowToLink(row) {
|
|
621
|
+
const link = {
|
|
622
|
+
link_id: row.link_id,
|
|
623
|
+
task_id: row.task_id,
|
|
624
|
+
connector_id: row.connector_id,
|
|
625
|
+
conversation_id: row.conversation_id,
|
|
626
|
+
status: row.status,
|
|
627
|
+
created_at: row.created_at,
|
|
628
|
+
updated_at: row.updated_at,
|
|
629
|
+
};
|
|
630
|
+
if (row.candidate_id !== null)
|
|
631
|
+
link.candidate_id = row.candidate_id;
|
|
632
|
+
if (row.last_message_id !== null)
|
|
633
|
+
link.last_message_id = row.last_message_id;
|
|
634
|
+
return link;
|
|
635
|
+
}
|
|
636
|
+
}
|
|
637
|
+
//# sourceMappingURL=task-store.js.map
|