@harrylabsj/kiwi 0.7.22 → 0.9.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/README.md +45 -10
- package/dist/a2a/negotiate.d.ts +6 -2
- package/dist/a2a/negotiate.js +10 -3
- package/dist/a2a/negotiate.js.map +1 -1
- package/dist/a2a/node.d.ts +4 -1
- package/dist/a2a/node.js +57 -4
- package/dist/a2a/node.js.map +1 -1
- package/dist/a2a/server/merchant-handler.d.ts +11 -3
- package/dist/a2a/server/merchant-handler.js +84 -26
- package/dist/a2a/server/merchant-handler.js.map +1 -1
- package/dist/agent/buyer/buyer-tools.js +17 -10
- package/dist/agent/buyer/buyer-tools.js.map +1 -1
- package/dist/agent/buyer/scheduler.d.ts +1 -0
- package/dist/agent/buyer/scheduler.js +5 -1
- package/dist/agent/buyer/scheduler.js.map +1 -1
- package/dist/agent/buyer/task-store.js +5 -2
- package/dist/agent/buyer/task-store.js.map +1 -1
- package/dist/agent/chat-tools.js +10 -3
- package/dist/agent/chat-tools.js.map +1 -1
- package/dist/agent/context/fencing.d.ts +27 -0
- package/dist/agent/context/fencing.js +126 -0
- package/dist/agent/context/fencing.js.map +1 -0
- package/dist/agent/context/grounding.d.ts +18 -0
- package/dist/agent/context/grounding.js +22 -0
- package/dist/agent/context/grounding.js.map +1 -0
- package/dist/agent/host/events.d.ts +31 -0
- package/dist/agent/host/events.js +62 -0
- package/dist/agent/host/events.js.map +1 -0
- package/dist/agent/host/tui-renderer.d.ts +17 -0
- package/dist/agent/host/tui-renderer.js +125 -0
- package/dist/agent/host/tui-renderer.js.map +1 -0
- package/dist/agent/host/web-renderer.d.ts +71 -0
- package/dist/agent/host/web-renderer.js +185 -0
- package/dist/agent/host/web-renderer.js.map +1 -0
- package/dist/agent/kernel-builder.d.ts +3 -1
- package/dist/agent/kernel-builder.js +4 -1
- package/dist/agent/kernel-builder.js.map +1 -1
- package/dist/agent/kernel.d.ts +20 -1
- package/dist/agent/kernel.js +255 -14
- package/dist/agent/kernel.js.map +1 -1
- package/dist/agent/memory/schema.d.ts +1 -1
- package/dist/agent/memory/schema.js +9 -1
- package/dist/agent/memory/schema.js.map +1 -1
- package/dist/agent/merchant/action-candidate.d.ts +18 -0
- package/dist/agent/merchant/action-candidate.js +51 -0
- package/dist/agent/merchant/action-candidate.js.map +1 -1
- package/dist/agent/merchant/fake-merchant-client.js +6 -1
- package/dist/agent/merchant/fake-merchant-client.js.map +1 -1
- package/dist/agent/merchant/intelligence/backend.d.ts +40 -0
- package/dist/agent/merchant/intelligence/backend.js +2 -0
- package/dist/agent/merchant/intelligence/backend.js.map +1 -0
- package/dist/agent/merchant/intelligence/default-backend.d.ts +38 -0
- package/dist/agent/merchant/intelligence/default-backend.js +477 -0
- package/dist/agent/merchant/intelligence/default-backend.js.map +1 -0
- package/dist/agent/merchant/intelligence/http-analytics-source.d.ts +55 -0
- package/dist/agent/merchant/intelligence/http-analytics-source.js +193 -0
- package/dist/agent/merchant/intelligence/http-analytics-source.js.map +1 -0
- package/dist/agent/merchant/intelligence/types.d.ts +109 -0
- package/dist/agent/merchant/intelligence/types.js +2 -0
- package/dist/agent/merchant/intelligence/types.js.map +1 -0
- package/dist/agent/merchant/merchant-client.d.ts +50 -1
- package/dist/agent/merchant/merchant-client.js +157 -8
- package/dist/agent/merchant/merchant-client.js.map +1 -1
- package/dist/agent/merchant/merchant-enrichment.d.ts +10 -0
- package/dist/agent/merchant/merchant-enrichment.js +38 -0
- package/dist/agent/merchant/merchant-enrichment.js.map +1 -0
- package/dist/agent/merchant/merchant-grounding.d.ts +5 -0
- package/dist/agent/merchant/merchant-grounding.js +76 -0
- package/dist/agent/merchant/merchant-grounding.js.map +1 -0
- package/dist/agent/merchant/merchant-presentations.d.ts +8 -0
- package/dist/agent/merchant/merchant-presentations.js +207 -0
- package/dist/agent/merchant/merchant-presentations.js.map +1 -0
- package/dist/agent/merchant/merchant-tools.d.ts +8 -0
- package/dist/agent/merchant/merchant-tools.js +291 -178
- package/dist/agent/merchant/merchant-tools.js.map +1 -1
- package/dist/agent/merchant/types.d.ts +6 -2
- package/dist/agent/merchant/types.js +45 -0
- package/dist/agent/merchant/types.js.map +1 -1
- package/dist/agent/presentation/registry.d.ts +14 -0
- package/dist/agent/presentation/registry.js +24 -0
- package/dist/agent/presentation/registry.js.map +1 -0
- package/dist/agent/presentation/runner.d.ts +11 -0
- package/dist/agent/presentation/runner.js +17 -0
- package/dist/agent/presentation/runner.js.map +1 -0
- package/dist/agent/presentation/sanitize.d.ts +16 -0
- package/dist/agent/presentation/sanitize.js +37 -0
- package/dist/agent/presentation/sanitize.js.map +1 -0
- package/dist/agent/presentation/types.d.ts +28 -0
- package/dist/agent/presentation/types.js +8 -0
- package/dist/agent/presentation/types.js.map +1 -0
- package/dist/agent/session.d.ts +1 -1
- package/dist/agent/session.js +2 -2
- package/dist/agent/session.js.map +1 -1
- package/dist/agent/skills/registry.d.ts +11 -0
- package/dist/agent/skills/registry.js +119 -0
- package/dist/agent/skills/registry.js.map +1 -0
- package/dist/agent/skills/tools.d.ts +6 -0
- package/dist/agent/skills/tools.js +36 -0
- package/dist/agent/skills/tools.js.map +1 -0
- package/dist/agent/skills/types.d.ts +9 -0
- package/dist/agent/skills/types.js +2 -0
- package/dist/agent/skills/types.js.map +1 -0
- package/dist/agent/supplier/scheduler.d.ts +2 -0
- package/dist/agent/supplier/scheduler.js +101 -22
- package/dist/agent/supplier/scheduler.js.map +1 -1
- package/dist/agent/supplier/store.d.ts +2 -0
- package/dist/agent/supplier/store.js +44 -0
- package/dist/agent/supplier/store.js.map +1 -1
- package/dist/agent/system-prompt.d.ts +5 -1
- package/dist/agent/system-prompt.js +20 -3
- package/dist/agent/system-prompt.js.map +1 -1
- package/dist/auth/merchant-authorization.d.ts +49 -0
- package/dist/auth/merchant-authorization.js +61 -0
- package/dist/auth/merchant-authorization.js.map +1 -0
- package/dist/auth/merchant-oauth.d.ts +255 -0
- package/dist/auth/merchant-oauth.js +764 -0
- package/dist/auth/merchant-oauth.js.map +1 -0
- package/dist/auth/merchant-pairing.d.ts +62 -0
- package/dist/auth/merchant-pairing.js +199 -0
- package/dist/auth/merchant-pairing.js.map +1 -0
- package/dist/auth/merchant-sessions.d.ts +71 -0
- package/dist/auth/merchant-sessions.js +168 -0
- package/dist/auth/merchant-sessions.js.map +1 -0
- package/dist/buyer-core/build-service.d.ts +5 -0
- package/dist/buyer-core/build-service.js +12 -0
- package/dist/buyer-core/build-service.js.map +1 -1
- package/dist/buyer-core/errors.d.ts +1 -1
- package/dist/buyer-core/errors.js +2 -0
- package/dist/buyer-core/errors.js.map +1 -1
- package/dist/buyer-core/merchant-index.d.ts +19 -4
- package/dist/buyer-core/merchant-index.js +137 -16
- package/dist/buyer-core/merchant-index.js.map +1 -1
- package/dist/buyer-core/negotiator.d.ts +0 -10
- package/dist/buyer-core/negotiator.js +12 -1
- package/dist/buyer-core/negotiator.js.map +1 -1
- package/dist/buyer-core/quote-fetcher.js +2 -1
- package/dist/buyer-core/quote-fetcher.js.map +1 -1
- package/dist/buyer-core/service.d.ts +104 -0
- package/dist/buyer-core/service.js +105 -1
- package/dist/buyer-core/service.js.map +1 -1
- package/dist/cli.d.ts +4 -2
- package/dist/cli.js +644 -32
- package/dist/cli.js.map +1 -1
- package/dist/config/profile.d.ts +51 -0
- package/dist/config/profile.js +185 -61
- package/dist/config/profile.js.map +1 -1
- package/dist/demo/demo-runner.js +12 -9
- package/dist/demo/demo-runner.js.map +1 -1
- package/dist/discovery/catalog-source/buyer-follows.d.ts +82 -0
- package/dist/discovery/catalog-source/buyer-follows.js +228 -0
- package/dist/discovery/catalog-source/buyer-follows.js.map +1 -0
- package/dist/discovery/catalog-source/connector-identity.d.ts +75 -0
- package/dist/discovery/catalog-source/connector-identity.js +175 -0
- package/dist/discovery/catalog-source/connector-identity.js.map +1 -0
- package/dist/discovery/catalog-source/errors.d.ts +1 -1
- package/dist/discovery/catalog-source/errors.js +2 -0
- package/dist/discovery/catalog-source/errors.js.map +1 -1
- package/dist/discovery/catalog-source/kiwi-record.d.ts +2 -0
- package/dist/discovery/catalog-source/kiwi-record.js.map +1 -1
- package/dist/discovery/catalog-source/kiwi-source.js +2 -0
- package/dist/discovery/catalog-source/kiwi-source.js.map +1 -1
- package/dist/discovery/catalog-source/merchant-publications.d.ts +65 -0
- package/dist/discovery/catalog-source/merchant-publications.js +207 -0
- package/dist/discovery/catalog-source/merchant-publications.js.map +1 -0
- package/dist/discovery/catalog-source/register.d.ts +24 -0
- package/dist/discovery/catalog-source/register.js +46 -0
- package/dist/discovery/catalog-source/register.js.map +1 -1
- package/dist/discovery/catalog-source/source.js +2 -1
- package/dist/discovery/catalog-source/source.js.map +1 -1
- package/dist/fs/atomic-write.d.ts +18 -0
- package/dist/fs/atomic-write.js +29 -0
- package/dist/fs/atomic-write.js.map +1 -0
- package/dist/handoff/authorization.js +1 -1
- package/dist/http/merchant-server.d.ts +65 -0
- package/dist/http/merchant-server.js +346 -0
- package/dist/http/merchant-server.js.map +1 -0
- package/dist/http/server.js +4 -1
- package/dist/http/server.js.map +1 -1
- package/dist/mcp/cli.d.ts +2 -0
- package/dist/mcp/cli.js +7 -6
- package/dist/mcp/cli.js.map +1 -1
- package/dist/mcp/merchant-auth.d.ts +78 -0
- package/dist/mcp/merchant-auth.js +146 -0
- package/dist/mcp/merchant-auth.js.map +1 -0
- package/dist/mcp/merchant-dirs.d.ts +26 -0
- package/dist/mcp/merchant-dirs.js +44 -0
- package/dist/mcp/merchant-dirs.js.map +1 -0
- package/dist/mcp/merchant-resources.d.ts +38 -0
- package/dist/mcp/merchant-resources.js +146 -0
- package/dist/mcp/merchant-resources.js.map +1 -0
- package/dist/mcp/merchant-server.d.ts +106 -0
- package/dist/mcp/merchant-server.js +615 -0
- package/dist/mcp/merchant-server.js.map +1 -0
- package/dist/mcp/merchant-tools.d.ts +103 -0
- package/dist/mcp/merchant-tools.js +517 -0
- package/dist/mcp/merchant-tools.js.map +1 -0
- package/dist/mcp/server.js +4 -3
- package/dist/mcp/server.js.map +1 -1
- package/dist/mcp/tools.d.ts +5 -3
- package/dist/mcp/tools.js +102 -5
- package/dist/mcp/tools.js.map +1 -1
- package/dist/mcp/types.d.ts +1 -1
- package/dist/mcp/types.js +4 -0
- package/dist/mcp/types.js.map +1 -1
- package/dist/merchant/ops.d.ts +0 -11
- package/dist/merchant/ops.js +13 -1
- package/dist/merchant/ops.js.map +1 -1
- package/dist/merchant/stats-store.d.ts +7 -0
- package/dist/merchant/stats-store.js +11 -0
- package/dist/merchant/stats-store.js.map +1 -1
- package/dist/merchant/workbench-service.d.ts +189 -0
- package/dist/merchant/workbench-service.js +417 -0
- package/dist/merchant/workbench-service.js.map +1 -0
- package/dist/merchant-admin/pending-page.d.ts +35 -0
- package/dist/merchant-admin/pending-page.js +69 -0
- package/dist/merchant-admin/pending-page.js.map +1 -0
- package/dist/merchant-core/commands.d.ts +99 -0
- package/dist/merchant-core/commands.js +179 -0
- package/dist/merchant-core/commands.js.map +1 -0
- package/dist/merchant-core/executor.d.ts +69 -0
- package/dist/merchant-core/executor.js +218 -0
- package/dist/merchant-core/executor.js.map +1 -0
- package/dist/merchant-core/negotiation-adapters.d.ts +55 -0
- package/dist/merchant-core/negotiation-adapters.js +55 -0
- package/dist/merchant-core/negotiation-adapters.js.map +1 -0
- package/dist/merchant-core/network-checks.d.ts +65 -0
- package/dist/merchant-core/network-checks.js +111 -0
- package/dist/merchant-core/network-checks.js.map +1 -0
- package/dist/merchant-core/operations.d.ts +64 -0
- package/dist/merchant-core/operations.js +136 -0
- package/dist/merchant-core/operations.js.map +1 -0
- package/dist/merchant-core/policy-runtime.d.ts +70 -0
- package/dist/merchant-core/policy-runtime.js +181 -0
- package/dist/merchant-core/policy-runtime.js.map +1 -0
- package/dist/merchant-core/product-import.d.ts +67 -0
- package/dist/merchant-core/product-import.js +160 -0
- package/dist/merchant-core/product-import.js.map +1 -0
- package/dist/merchant-core/service.d.ts +203 -0
- package/dist/merchant-core/service.js +402 -0
- package/dist/merchant-core/service.js.map +1 -0
- package/dist/merchant-gateway/catalog-publications.d.ts +71 -0
- package/dist/merchant-gateway/catalog-publications.js +175 -0
- package/dist/merchant-gateway/catalog-publications.js.map +1 -0
- package/dist/merchant-gateway/catalog-tools.d.ts +46 -0
- package/dist/merchant-gateway/catalog-tools.js +277 -0
- package/dist/merchant-gateway/catalog-tools.js.map +1 -0
- package/dist/merchant-gateway/cli.d.ts +75 -0
- package/dist/merchant-gateway/cli.js +458 -0
- package/dist/merchant-gateway/cli.js.map +1 -0
- package/dist/merchant-gateway/credential-vault.d.ts +44 -0
- package/dist/merchant-gateway/credential-vault.js +111 -0
- package/dist/merchant-gateway/credential-vault.js.map +1 -0
- package/dist/merchant-gateway/entry-server.d.ts +117 -0
- package/dist/merchant-gateway/entry-server.js +710 -0
- package/dist/merchant-gateway/entry-server.js.map +1 -0
- package/dist/merchant-gateway/instance-registration.d.ts +143 -0
- package/dist/merchant-gateway/instance-registration.js +382 -0
- package/dist/merchant-gateway/instance-registration.js.map +1 -0
- package/dist/merchant-gateway/instance-tools.d.ts +58 -0
- package/dist/merchant-gateway/instance-tools.js +184 -0
- package/dist/merchant-gateway/instance-tools.js.map +1 -0
- package/dist/merchant-gateway/mcp-proxy.d.ts +25 -0
- package/dist/merchant-gateway/mcp-proxy.js +192 -0
- package/dist/merchant-gateway/mcp-proxy.js.map +1 -0
- package/dist/merchant-gateway/pinned-fetch.d.ts +52 -0
- package/dist/merchant-gateway/pinned-fetch.js +212 -0
- package/dist/merchant-gateway/pinned-fetch.js.map +1 -0
- package/dist/merchant-gateway/tenant-registry.d.ts +82 -0
- package/dist/merchant-gateway/tenant-registry.js +190 -0
- package/dist/merchant-gateway/tenant-registry.js.map +1 -0
- package/dist/merchant-gateway/tool-bundle.d.ts +26 -0
- package/dist/merchant-gateway/tool-bundle.js +56 -0
- package/dist/merchant-gateway/tool-bundle.js.map +1 -0
- package/dist/merchant-runtime/backup.d.ts +48 -0
- package/dist/merchant-runtime/backup.js +226 -0
- package/dist/merchant-runtime/backup.js.map +1 -0
- package/dist/merchant-runtime/health.d.ts +99 -0
- package/dist/merchant-runtime/health.js +206 -0
- package/dist/merchant-runtime/health.js.map +1 -0
- package/dist/merchant-runtime/jobs.d.ts +64 -0
- package/dist/merchant-runtime/jobs.js +107 -0
- package/dist/merchant-runtime/jobs.js.map +1 -0
- package/dist/merchant-runtime/manager.d.ts +94 -0
- package/dist/merchant-runtime/manager.js +305 -0
- package/dist/merchant-runtime/manager.js.map +1 -0
- package/dist/merchant-runtime/services.d.ts +30 -0
- package/dist/merchant-runtime/services.js +51 -0
- package/dist/merchant-runtime/services.js.map +1 -0
- package/dist/negotiation/action-candidate.js +1 -1
- package/dist/net/url.d.ts +26 -0
- package/dist/net/url.js +32 -0
- package/dist/net/url.js.map +1 -0
- package/dist/operator/types.d.ts +1 -1
- package/dist/product-cli.d.ts +2 -2
- package/dist/product-cli.js +27 -6
- package/dist/product-cli.js.map +1 -1
- package/dist/product-compat.d.ts +9 -1
- package/dist/product-compat.js +12 -1
- package/dist/product-compat.js.map +1 -1
- package/dist/product-init.js +17 -5
- package/dist/product-init.js.map +1 -1
- package/dist/product-publish.js +2 -1
- package/dist/product-publish.js.map +1 -1
- package/dist/product-supplier.d.ts +73 -0
- package/dist/product-supplier.js +224 -5
- package/dist/product-supplier.js.map +1 -1
- package/dist/runtime/fake-model.d.ts +1 -1
- package/dist/trust/identity/jwk.d.ts +11 -0
- package/dist/trust/identity/jwk.js +2 -0
- package/dist/trust/identity/jwk.js.map +1 -0
- package/dist/trust/identity/jws.d.ts +2 -1
- package/dist/trust/identity/jws.js.map +1 -1
- package/dist/trust/identity/keys.d.ts +2 -1
- package/dist/trust/identity/keys.js.map +1 -1
- package/dist/trust/identity/message-signature.d.ts +1 -14
- package/dist/trust/identity/message-signature.js.map +1 -1
- package/dist/weixin/channel.d.ts +3 -0
- package/dist/weixin/channel.js +18 -2
- package/dist/weixin/channel.js.map +1 -1
- package/examples/profiles/merchant.deepseek.yaml +6 -0
- package/examples/profiles/merchant.fake.yaml +6 -0
- package/examples/profiles/merchant.local.yaml +6 -0
- package/package.json +9 -7
- package/skills/kiwi-buyer/SKILL.md +68 -0
- package/skills/merchant/catalog-operations/SKILL.md +17 -0
- package/skills/merchant/change-approval/SKILL.md +16 -0
- package/skills/merchant/human-review/SKILL.md +17 -0
- package/skills/merchant/inventory-operations/SKILL.md +17 -0
- package/skills/merchant/negotiation-review/SKILL.md +18 -0
- package/skills/merchant/performance-insights/SKILL.md +19 -0
- package/contracts/candidate-agent-dto-1.0.README.md +0 -43
- package/contracts/conformance/python-service/README.md +0 -19
|
@@ -0,0 +1,417 @@
|
|
|
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 { CommerceError } from "../commerce/data-source.js";
|
|
17
|
+
import { LedgerStore } from "../negotiation/ledger/index.js";
|
|
18
|
+
import { TERMINAL_PHASES } from "../negotiation/state/phase.js";
|
|
19
|
+
import { executeApprovedCandidate, WriteApprovalCandidateError, } from "../agent/merchant/action-candidate.js";
|
|
20
|
+
import { MerchantClientError } from "../agent/merchant/types.js";
|
|
21
|
+
import { routeWriteCandidate } from "../agent/write-gate.js";
|
|
22
|
+
/** Facade 统一错误(kind 为跨调用方语义不变量)。 */
|
|
23
|
+
export class MerchantWorkbenchError extends Error {
|
|
24
|
+
kind;
|
|
25
|
+
constructor(kind, message) {
|
|
26
|
+
super(message);
|
|
27
|
+
this.name = "MerchantWorkbenchError";
|
|
28
|
+
this.kind = kind;
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
/** MerchantClientError / CommerceError / WriteApprovalCandidateError / 底层异常 → MerchantWorkbenchError。 */
|
|
32
|
+
function toWorkbenchError(err) {
|
|
33
|
+
if (err instanceof MerchantWorkbenchError)
|
|
34
|
+
return err;
|
|
35
|
+
if (err instanceof MerchantClientError) {
|
|
36
|
+
const kind = err.kind === "transient" ? "unavailable" : err.kind;
|
|
37
|
+
return new MerchantWorkbenchError(kind, err.message);
|
|
38
|
+
}
|
|
39
|
+
if (err instanceof CommerceError) {
|
|
40
|
+
return new MerchantWorkbenchError("unavailable", err.message);
|
|
41
|
+
}
|
|
42
|
+
if (err instanceof WriteApprovalCandidateError) {
|
|
43
|
+
return new MerchantWorkbenchError(err.code === "not_found" ? "not_found" : "validation", err.message);
|
|
44
|
+
}
|
|
45
|
+
return new MerchantWorkbenchError("unavailable", err instanceof Error ? err.message : String(err));
|
|
46
|
+
}
|
|
47
|
+
/** Public precondition snapshot of a product (no private values). */
|
|
48
|
+
export function publicProductView(product) {
|
|
49
|
+
return {
|
|
50
|
+
sku: product.sku,
|
|
51
|
+
merchant_id: product.merchant_id,
|
|
52
|
+
title: product.title,
|
|
53
|
+
price: product.price,
|
|
54
|
+
stock: product.stock,
|
|
55
|
+
paused: product.paused,
|
|
56
|
+
};
|
|
57
|
+
}
|
|
58
|
+
/** 解析商品变更 patch(等价于原 merchant-tools.parseChanges;静默忽略未知字段)。 */
|
|
59
|
+
export function parseProductPatch(value) {
|
|
60
|
+
if (value === null || typeof value !== "object" || Array.isArray(value)) {
|
|
61
|
+
throw new MerchantWorkbenchError("validation", "changes 必须是对象");
|
|
62
|
+
}
|
|
63
|
+
const v = value;
|
|
64
|
+
const patch = {};
|
|
65
|
+
if (typeof v.title === "string")
|
|
66
|
+
patch.title = v.title;
|
|
67
|
+
if (typeof v.price === "number" && Number.isFinite(v.price))
|
|
68
|
+
patch.price = v.price;
|
|
69
|
+
if (typeof v.stock === "number" && Number.isInteger(v.stock))
|
|
70
|
+
patch.stock = v.stock;
|
|
71
|
+
if (typeof v.currency === "string")
|
|
72
|
+
patch.currency = v.currency;
|
|
73
|
+
if (typeof v.category === "string")
|
|
74
|
+
patch.category = v.category;
|
|
75
|
+
if (Array.isArray(v.tags))
|
|
76
|
+
patch.tags = v.tags.map(String);
|
|
77
|
+
if (typeof v.description === "string")
|
|
78
|
+
patch.description = v.description;
|
|
79
|
+
if (Array.isArray(v.delivery_attributes))
|
|
80
|
+
patch.delivery_attributes = v.delivery_attributes.map(String);
|
|
81
|
+
// 审查 P1:上游 PATCH /products 无 paused/active 字段(2.x/3.x 实测),
|
|
82
|
+
// draft 路径带 paused 会「批准执行成功但实际不生效」。显式拒绝并引导到
|
|
83
|
+
// prepare_listing_change(销售状态语义;当前引擎无端点时报「不可得」)。
|
|
84
|
+
if ("paused" in v) {
|
|
85
|
+
throw new MerchantWorkbenchError("validation", "changes.paused 不受商品变更支持(上游 PATCH 无该字段,执行不会生效);" +
|
|
86
|
+
"上下架请使用 kiwi_merchant_prepare_listing_change(销售状态语义)。");
|
|
87
|
+
}
|
|
88
|
+
return patch;
|
|
89
|
+
}
|
|
90
|
+
export class MerchantWorkbenchService {
|
|
91
|
+
profile;
|
|
92
|
+
merchantClient;
|
|
93
|
+
dataSource;
|
|
94
|
+
approvals;
|
|
95
|
+
mode;
|
|
96
|
+
now;
|
|
97
|
+
registerPending;
|
|
98
|
+
a2aLedgerDir;
|
|
99
|
+
intelligence;
|
|
100
|
+
ownerId;
|
|
101
|
+
/**
|
|
102
|
+
* 本进程内的候选执行钩子(draft_product_change)。钩子是进程级的,但
|
|
103
|
+
* draft 候选的参数在 store 里、钩子可从参数确定性重建——因此本服务
|
|
104
|
+
* (MCP 进程)内也能批准并执行自己的候选(阶段四最小闭环)。
|
|
105
|
+
* 外部 registerPending(如 chat kernel)照常透传。
|
|
106
|
+
*/
|
|
107
|
+
pendingHooks = new Map();
|
|
108
|
+
constructor(deps) {
|
|
109
|
+
this.profile = deps.profile;
|
|
110
|
+
this.merchantClient = deps.merchantClient;
|
|
111
|
+
this.approvals = deps.approvals;
|
|
112
|
+
this.mode = deps.mode;
|
|
113
|
+
this.now = deps.now;
|
|
114
|
+
this.ownerId = deps.profile.owner_id;
|
|
115
|
+
if (deps.dataSource !== undefined)
|
|
116
|
+
this.dataSource = deps.dataSource;
|
|
117
|
+
if (deps.registerPending !== undefined)
|
|
118
|
+
this.registerPending = deps.registerPending;
|
|
119
|
+
if (deps.a2aLedgerDir !== undefined)
|
|
120
|
+
this.a2aLedgerDir = deps.a2aLedgerDir;
|
|
121
|
+
if (deps.intelligence !== undefined)
|
|
122
|
+
this.intelligence = deps.intelligence;
|
|
123
|
+
}
|
|
124
|
+
/** 内部依赖只读访问(merchant-core 包装层/两轨适配用;不提供写路径)。 */
|
|
125
|
+
get merchantClientRef() {
|
|
126
|
+
return this.merchantClient;
|
|
127
|
+
}
|
|
128
|
+
get ownerIdRef() {
|
|
129
|
+
return this.ownerId;
|
|
130
|
+
}
|
|
131
|
+
/** 列出本商家目录商品(白名单);dataSource 优先,否则公开搜索端点按 owner 过滤。 */
|
|
132
|
+
async listPublicProducts() {
|
|
133
|
+
try {
|
|
134
|
+
if (this.dataSource !== undefined) {
|
|
135
|
+
const facts = await this.dataSource.getProducts({ limit: 100 });
|
|
136
|
+
return {
|
|
137
|
+
items: facts.map((p) => ({
|
|
138
|
+
sku: p.sku,
|
|
139
|
+
merchant_id: this.ownerId,
|
|
140
|
+
title: p.title ?? "",
|
|
141
|
+
price: p.price_minor ?? 0,
|
|
142
|
+
stock: p.stock ?? null,
|
|
143
|
+
paused: false,
|
|
144
|
+
})),
|
|
145
|
+
source: "data_source",
|
|
146
|
+
};
|
|
147
|
+
}
|
|
148
|
+
const products = await this.merchantClient.listProducts(this.ownerId);
|
|
149
|
+
return { items: products.map(publicProductView), source: "merchant_client" };
|
|
150
|
+
}
|
|
151
|
+
catch (err) {
|
|
152
|
+
throw toWorkbenchError(err);
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
/** 按 SKU 读取一个商品(白名单)。审查 P2:非本商家的 SKU 按未找到处理
|
|
156
|
+
* (工具语义是「本商家目录中的商品」,不校验会返回其他商家的公开商品)。 */
|
|
157
|
+
async getPublicProduct(sku, merchantId) {
|
|
158
|
+
try {
|
|
159
|
+
this.assertMerchantId(merchantId);
|
|
160
|
+
const product = await this.merchantClient.getProduct(sku);
|
|
161
|
+
if (product.merchant_id !== this.ownerId) {
|
|
162
|
+
throw new MerchantWorkbenchError("not_found", `商品 ${sku} 不属于本商家`);
|
|
163
|
+
}
|
|
164
|
+
return publicProductView(product);
|
|
165
|
+
}
|
|
166
|
+
catch (err) {
|
|
167
|
+
throw toWorkbenchError(err);
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
/** 读取一个商品的当前库存快照(含观察时间,不是永恒事实)。 */
|
|
171
|
+
async getInventorySnapshot(sku) {
|
|
172
|
+
try {
|
|
173
|
+
const snapshot = await this.merchantClient.getInventorySnapshot(sku);
|
|
174
|
+
return { sku: snapshot.sku, stock: snapshot.stock, observed_at: snapshot.observed_at };
|
|
175
|
+
}
|
|
176
|
+
catch (err) {
|
|
177
|
+
throw toWorkbenchError(err);
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
/**
|
|
181
|
+
* 列出商家节点的 A2A 磋商记录(结构化行,按最近落账时间倒序)。
|
|
182
|
+
* limit 缺省 20,clamp 1..100。未配置 ledger 目录时 fail-closed 抛 unavailable。
|
|
183
|
+
*/
|
|
184
|
+
async listA2aNegotiations(limit) {
|
|
185
|
+
const clamped = Math.min(Math.max(Number(limit ?? 20) || 20, 1), 100);
|
|
186
|
+
const rows = this.scanLedger(false);
|
|
187
|
+
return { total: rows.length, items: rows.slice(0, clamped) };
|
|
188
|
+
}
|
|
189
|
+
/** 只留**进行中**(非终态)的磋商。未配置 ledger 目录时 fail-closed 抛 unavailable。 */
|
|
190
|
+
async listActiveConsultations() {
|
|
191
|
+
return this.scanLedger(true);
|
|
192
|
+
}
|
|
193
|
+
/** 商家人工处理队列(白名单:review_id / conversation_id / sku / severity / reason)。 */
|
|
194
|
+
async listHumanReviews() {
|
|
195
|
+
try {
|
|
196
|
+
const reviews = await this.merchantClient.getHumanReviewQueue(this.ownerId);
|
|
197
|
+
return reviews.map((r) => ({
|
|
198
|
+
review_id: r.review_id,
|
|
199
|
+
conversation_id: r.conversation_id,
|
|
200
|
+
sku: r.sku,
|
|
201
|
+
severity: r.severity,
|
|
202
|
+
reason: r.reason,
|
|
203
|
+
}));
|
|
204
|
+
}
|
|
205
|
+
catch (err) {
|
|
206
|
+
throw toWorkbenchError(err);
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
/** 经营摘要(intelligence);未配置时 fail-closed 抛 unavailable,不返回演示数据。 */
|
|
210
|
+
async getAnalytics(period) {
|
|
211
|
+
try {
|
|
212
|
+
if (this.intelligence === undefined) {
|
|
213
|
+
throw new MerchantWorkbenchError("unavailable", "未配置经营指标后端,无法读取经营摘要。");
|
|
214
|
+
}
|
|
215
|
+
if (period !== undefined && !/^(?:[1-9]|[1-8][0-9]|90)d$/.test(period)) {
|
|
216
|
+
throw new MerchantWorkbenchError("validation", "period 必须是 1d 到 90d,例如 7d、14d、30d");
|
|
217
|
+
}
|
|
218
|
+
return await this.intelligence.getBusinessSnapshot({
|
|
219
|
+
merchant_id: this.ownerId,
|
|
220
|
+
...(period === undefined ? {} : { period }),
|
|
221
|
+
});
|
|
222
|
+
}
|
|
223
|
+
catch (err) {
|
|
224
|
+
throw toWorkbenchError(err);
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
/**
|
|
228
|
+
* 商品变更草稿:校验 changes、确认商品存在,经 approvals + routeWriteCandidate
|
|
229
|
+
* 以 force_pending 生成审批候选(任何模式都不自动执行)。只返回候选元数据
|
|
230
|
+
* 与当前商品公开快照。
|
|
231
|
+
*/
|
|
232
|
+
async draftProductChange(input) {
|
|
233
|
+
try {
|
|
234
|
+
this.assertMerchantId(input.merchant_id);
|
|
235
|
+
if (typeof input.sku !== "string" || input.sku === "") {
|
|
236
|
+
throw new MerchantWorkbenchError("validation", "sku 必须是非空字符串");
|
|
237
|
+
}
|
|
238
|
+
const patch = parseProductPatch(input.changes);
|
|
239
|
+
if (Object.keys(patch).length === 0) {
|
|
240
|
+
throw new MerchantWorkbenchError("validation", "changes 没有任何可修改字段。");
|
|
241
|
+
}
|
|
242
|
+
const current = await this.merchantClient.getProduct(input.sku);
|
|
243
|
+
const args = { sku: input.sku, changes: { ...patch }, reason: input.reason ?? "" };
|
|
244
|
+
const hooks = this.buildDraftHooks(input.sku);
|
|
245
|
+
const outcome = await routeWriteCandidate({
|
|
246
|
+
mode: this.mode,
|
|
247
|
+
approvals: this.approvals,
|
|
248
|
+
profile: this.profile,
|
|
249
|
+
now: this.now,
|
|
250
|
+
registerPending: (candidateId, pendingHooks) => {
|
|
251
|
+
this.pendingHooks.set(candidateId, pendingHooks);
|
|
252
|
+
this.registerPending?.(candidateId, pendingHooks);
|
|
253
|
+
},
|
|
254
|
+
}, {
|
|
255
|
+
tool: "draft_product_change",
|
|
256
|
+
arguments: args,
|
|
257
|
+
preconditions: publicProductView(current),
|
|
258
|
+
risk: "write_catalog",
|
|
259
|
+
// Drafts are ALWAYS pending (never auto-execute), even in autopilot.
|
|
260
|
+
force_pending: true,
|
|
261
|
+
execute: hooks.execute,
|
|
262
|
+
readPreconditions: hooks.readPreconditions,
|
|
263
|
+
});
|
|
264
|
+
return { outcome, product: publicProductView(current) };
|
|
265
|
+
}
|
|
266
|
+
catch (err) {
|
|
267
|
+
throw toWorkbenchError(err);
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
/** draft 候选的执行钩子(execute 只执行库内已批准参数;preconditions 重读重哈希)。 */
|
|
271
|
+
buildDraftHooks(sku) {
|
|
272
|
+
return {
|
|
273
|
+
readPreconditions: async () => {
|
|
274
|
+
const fresh = await this.merchantClient.getProduct(sku);
|
|
275
|
+
return publicProductView(fresh);
|
|
276
|
+
},
|
|
277
|
+
execute: (approvedArgs) => {
|
|
278
|
+
const a = approvedArgs;
|
|
279
|
+
return this.merchantClient.updateProduct(a.sku, a.changes);
|
|
280
|
+
},
|
|
281
|
+
};
|
|
282
|
+
}
|
|
283
|
+
/**
|
|
284
|
+
* 启动恢复(MCP 进程重启后):为 store 里本服务可执行工具
|
|
285
|
+
* (draft_product_change)的 pending 候选从库存参数重建执行钩子,返回恢复
|
|
286
|
+
* 条数。其他工具的候选不处理(由调用方按 expireForRecovery 语义失效)。
|
|
287
|
+
*/
|
|
288
|
+
recoverPendingDrafts() {
|
|
289
|
+
let recovered = 0;
|
|
290
|
+
for (const candidate of this.approvals.listPending()) {
|
|
291
|
+
if (candidate.tool !== "draft_product_change")
|
|
292
|
+
continue;
|
|
293
|
+
const sku = typeof candidate.arguments.sku === "string" ? candidate.arguments.sku : undefined;
|
|
294
|
+
if (sku === undefined || sku === "") {
|
|
295
|
+
// 参数缺 sku 的候选无法重建钩子——fail-closed 失效,不留死候选。
|
|
296
|
+
this.approvals.expireCandidate(candidate.candidate_id);
|
|
297
|
+
continue;
|
|
298
|
+
}
|
|
299
|
+
this.pendingHooks.set(candidate.candidate_id, this.buildDraftHooks(sku));
|
|
300
|
+
recovered += 1;
|
|
301
|
+
}
|
|
302
|
+
return recovered;
|
|
303
|
+
}
|
|
304
|
+
/**
|
|
305
|
+
* 批准并执行一个 pending 候选(语义对齐 chat kernel 的 /approve:重读前置
|
|
306
|
+
* 状态并重哈希,stale/expired 的候选 supersede、绝不执行;只执行库内已
|
|
307
|
+
* 批准参数)。候选没有本进程执行钩子时按恢复语义失效(fail-closed)。
|
|
308
|
+
* 幂等:重复批准不会重复执行(executed 后返回 not_approvable)。
|
|
309
|
+
*/
|
|
310
|
+
async approveCandidate(candidateId) {
|
|
311
|
+
// 审查 P2:同候选并发批准串行化——前一个执行的 await 窗口内第二个调用
|
|
312
|
+
// 会看到 approved 状态而重复进入执行(与 kernel 的 enqueue 语义对齐)。
|
|
313
|
+
const pending = this.approveInFlight.get(candidateId);
|
|
314
|
+
if (pending !== undefined)
|
|
315
|
+
await pending;
|
|
316
|
+
const exec = this.doApproveCandidate(candidateId);
|
|
317
|
+
this.approveInFlight.set(candidateId, exec.then(() => undefined, () => undefined));
|
|
318
|
+
try {
|
|
319
|
+
return await exec;
|
|
320
|
+
}
|
|
321
|
+
finally {
|
|
322
|
+
this.approveInFlight.delete(candidateId);
|
|
323
|
+
}
|
|
324
|
+
}
|
|
325
|
+
approveInFlight = new Map();
|
|
326
|
+
async doApproveCandidate(candidateId) {
|
|
327
|
+
try {
|
|
328
|
+
const candidate = this.approvals.get(candidateId);
|
|
329
|
+
if (candidate === undefined) {
|
|
330
|
+
throw new MerchantWorkbenchError("not_found", `未知审批候选 ${candidateId}`);
|
|
331
|
+
}
|
|
332
|
+
// manual 模式语义(对齐 kernel 评审项 P3-3):manual = advice only。
|
|
333
|
+
if (this.mode() === "manual") {
|
|
334
|
+
return {
|
|
335
|
+
kind: "not_approvable",
|
|
336
|
+
candidate,
|
|
337
|
+
reason: "manual 模式只提供建议,不自动执行(批准拒绝 advice-only 候选)",
|
|
338
|
+
};
|
|
339
|
+
}
|
|
340
|
+
const hooks = this.pendingHooks.get(candidateId);
|
|
341
|
+
if (hooks === undefined) {
|
|
342
|
+
if (candidate.status === "expired")
|
|
343
|
+
return { kind: "expired", candidate };
|
|
344
|
+
if (candidate.status !== "pending_approval" && candidate.status !== "approved") {
|
|
345
|
+
return {
|
|
346
|
+
kind: "not_approvable",
|
|
347
|
+
candidate,
|
|
348
|
+
reason: `候选 ${candidateId} 状态为 ${candidate.status},不可批准。`,
|
|
349
|
+
};
|
|
350
|
+
}
|
|
351
|
+
const expired = this.approvals.expireCandidate(candidateId);
|
|
352
|
+
return { kind: "expired", candidate: expired };
|
|
353
|
+
}
|
|
354
|
+
this.approvals.markApproved(candidateId);
|
|
355
|
+
const outcome = await executeApprovedCandidate(this.approvals, candidateId, hooks);
|
|
356
|
+
// 候选生命周期终结(executed / stale / expired)后释放钩子闭包(评审项 P3-5)。
|
|
357
|
+
if (outcome.kind !== "not_approvable")
|
|
358
|
+
this.pendingHooks.delete(candidateId);
|
|
359
|
+
return outcome;
|
|
360
|
+
}
|
|
361
|
+
catch (err) {
|
|
362
|
+
throw toWorkbenchError(err);
|
|
363
|
+
}
|
|
364
|
+
}
|
|
365
|
+
/** 租户校验:入参 merchant_id 提供时必须等于本商家 owner_id。 */
|
|
366
|
+
assertMerchantId(merchantId) {
|
|
367
|
+
if (merchantId !== undefined && merchantId !== this.ownerId) {
|
|
368
|
+
throw new MerchantWorkbenchError("validation", `merchant_id ${merchantId} 不属于本商家(${this.ownerId})`);
|
|
369
|
+
}
|
|
370
|
+
}
|
|
371
|
+
/** 扫 A2A ledger 生成结构化行(按最近落账时间倒序);activeOnly 时剔除非终态以外的记录。 */
|
|
372
|
+
scanLedger(activeOnly) {
|
|
373
|
+
if (this.a2aLedgerDir === undefined) {
|
|
374
|
+
throw new MerchantWorkbenchError("unavailable", "未配置 A2A ledger 目录,无法读取磋商记录。");
|
|
375
|
+
}
|
|
376
|
+
const ledger = new LedgerStore({ dir: this.a2aLedgerDir, now: this.now });
|
|
377
|
+
const rows = [];
|
|
378
|
+
for (const negotiationId of ledger.listNegotiations()) {
|
|
379
|
+
const row = {
|
|
380
|
+
negotiation_id: negotiationId,
|
|
381
|
+
phase: "OPEN",
|
|
382
|
+
last_action: "",
|
|
383
|
+
sku: "",
|
|
384
|
+
agreement: false,
|
|
385
|
+
recorded_at: "",
|
|
386
|
+
};
|
|
387
|
+
for (const e of ledger.events(negotiationId)) {
|
|
388
|
+
if (e.recorded_at > row.recorded_at)
|
|
389
|
+
row.recorded_at = e.recorded_at;
|
|
390
|
+
if (e.state_transition?.to_phase !== undefined) {
|
|
391
|
+
row.phase = e.state_transition.to_phase;
|
|
392
|
+
if (e.state_transition.to_phase === "AGREEMENT_REACHED")
|
|
393
|
+
row.agreement = true;
|
|
394
|
+
}
|
|
395
|
+
if (e.event_kind === "message_sent") {
|
|
396
|
+
const wp = e.wire_payload;
|
|
397
|
+
if (wp?.action !== undefined)
|
|
398
|
+
row.last_action = wp.action;
|
|
399
|
+
const item = wp?.payload?.terms?.items?.[0];
|
|
400
|
+
if (item?.sku !== undefined && item.sku !== "")
|
|
401
|
+
row.sku = item.sku;
|
|
402
|
+
if (item?.quantity?.value !== undefined)
|
|
403
|
+
row.quantity = item.quantity.value;
|
|
404
|
+
if (item?.unit_price?.amount_minor !== undefined)
|
|
405
|
+
row.price_minor = item.unit_price.amount_minor;
|
|
406
|
+
}
|
|
407
|
+
}
|
|
408
|
+
// 已到终态(AGREEMENT_REACHED/DECLINED/WITHDRAWN/CANCELLED/EXPIRED)不算进行中
|
|
409
|
+
if (activeOnly && TERMINAL_PHASES.includes(row.phase))
|
|
410
|
+
continue;
|
|
411
|
+
rows.push(row);
|
|
412
|
+
}
|
|
413
|
+
rows.sort((a, b) => a.recorded_at > b.recorded_at ? -1 : a.recorded_at < b.recorded_at ? 1 : 0);
|
|
414
|
+
return rows;
|
|
415
|
+
}
|
|
416
|
+
}
|
|
417
|
+
//# sourceMappingURL=workbench-service.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"workbench-service.js","sourceRoot":"","sources":["../../src/merchant/workbench-service.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,35 @@
|
|
|
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
|
+
/**
|
|
17
|
+
* 配套商家确认页面(V2 阶段三:src/merchant-admin/)。
|
|
18
|
+
*
|
|
19
|
+
* 宿主(WorkBuddy)没有可验证确认接口时的确认通道:最小可用 HTML 页面,
|
|
20
|
+
* 列出待批准命令(预览:tool、参数、前置版本、有效期)+ 批准/拒绝表单。
|
|
21
|
+
* 批准/拒绝经 MCP server 的 Bearer 认证(OAuth access_token,write scope 由
|
|
22
|
+
* 服务端强制)——模型自报「已批准」不作证据,approved 只能由本通道写入。
|
|
23
|
+
*/
|
|
24
|
+
import type { WriteApprovalCandidate } from "../agent/merchant/action-candidate.js";
|
|
25
|
+
import type { MerchantCoreService } from "../merchant-core/service.js";
|
|
26
|
+
export interface MerchantAdminSurface {
|
|
27
|
+
listPending(): WriteApprovalCandidate[];
|
|
28
|
+
/** 批准并执行(认证主体 + 一次性确认凭证逐次传入,执行层逐项核对)。 */
|
|
29
|
+
executeApproved(commandId: string, principalId: string, confirmationToken?: string): Promise<unknown>;
|
|
30
|
+
rejectCandidate(commandId: string, principalId: string, confirmationToken?: string): Promise<unknown>;
|
|
31
|
+
}
|
|
32
|
+
/** 从 merchant-core 构造管理面(确认通道 = core 的命令日志)。 */
|
|
33
|
+
export declare function merchantAdminSurface(core: MerchantCoreService): MerchantAdminSurface;
|
|
34
|
+
/** 待批准命令页(最小可用;与 OAuth 授权页同风格)。 */
|
|
35
|
+
export declare function renderPendingPage(merchantName: string, commands: WriteApprovalCandidate[], tokenFor?: (candidateId: string, action: "approve" | "reject") => string): string;
|
|
@@ -0,0 +1,69 @@
|
|
|
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
|
+
/** 从 merchant-core 构造管理面(确认通道 = core 的命令日志)。 */
|
|
17
|
+
export function merchantAdminSurface(core) {
|
|
18
|
+
return {
|
|
19
|
+
listPending: () => core.listPendingCommands(),
|
|
20
|
+
executeApproved: (id, principalId, token) => core.commands.executeApproved(id, principalId, token),
|
|
21
|
+
rejectCandidate: (id, principalId, token) => core.commands.reject(id, principalId, token),
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
function escapeHtml(text) {
|
|
25
|
+
return text
|
|
26
|
+
.replaceAll("&", "&")
|
|
27
|
+
.replaceAll("<", "<")
|
|
28
|
+
.replaceAll(">", ">")
|
|
29
|
+
.replaceAll('"', """);
|
|
30
|
+
}
|
|
31
|
+
/** 待批准命令页(最小可用;与 OAuth 授权页同风格)。 */
|
|
32
|
+
export function renderPendingPage(merchantName, commands, tokenFor) {
|
|
33
|
+
const rows = commands
|
|
34
|
+
.map((c) => `<tr>
|
|
35
|
+
<td>${escapeHtml(c.candidate_id)}</td>
|
|
36
|
+
<td>${escapeHtml(c.tool)}</td>
|
|
37
|
+
<td><pre>${escapeHtml(JSON.stringify(c.arguments, null, 2))}</pre></td>
|
|
38
|
+
<td><pre>${escapeHtml(JSON.stringify(c.preconditions, null, 2))}</pre></td>
|
|
39
|
+
<td>${escapeHtml(c.expires_at)}</td>
|
|
40
|
+
<td>
|
|
41
|
+
<form method="post" action="/admin/decision" style="display:inline">
|
|
42
|
+
<input type="hidden" name="command_id" value="${escapeHtml(c.candidate_id)}">
|
|
43
|
+
<input type="hidden" name="confirmation" value="${escapeHtml(tokenFor?.(c.candidate_id, "approve") ?? "")}">
|
|
44
|
+
<button type="submit" name="decision" value="approve">批准并执行</button>
|
|
45
|
+
</form>
|
|
46
|
+
<form method="post" action="/admin/decision" style="display:inline">
|
|
47
|
+
<input type="hidden" name="command_id" value="${escapeHtml(c.candidate_id)}">
|
|
48
|
+
<input type="hidden" name="confirmation" value="${escapeHtml(tokenFor?.(c.candidate_id, "reject") ?? "")}">
|
|
49
|
+
<button type="submit" name="decision" value="reject">拒绝</button>
|
|
50
|
+
</form>
|
|
51
|
+
</td>
|
|
52
|
+
</tr>`)
|
|
53
|
+
.join("\n");
|
|
54
|
+
return `<!doctype html>
|
|
55
|
+
<html lang="zh-CN">
|
|
56
|
+
<head><meta charset="utf-8"><title>待批准命令 — ${escapeHtml(merchantName)}</title></head>
|
|
57
|
+
<body>
|
|
58
|
+
<h1>${escapeHtml(merchantName)}:待批准命令</h1>
|
|
59
|
+
<p>展示预览 ≠ 批准;批准 ≠ 执行成功(执行前重校验前置版本与硬策略)。</p>
|
|
60
|
+
${commands.length === 0
|
|
61
|
+
? "<p>当前没有待批准命令。</p>"
|
|
62
|
+
: `<table border="1" cellpadding="6">
|
|
63
|
+
<tr><th>command_id</th><th>工具</th><th>参数</th><th>前置版本</th><th>有效期至</th><th>操作</th></tr>
|
|
64
|
+
${rows}
|
|
65
|
+
</table>`}
|
|
66
|
+
</body>
|
|
67
|
+
</html>`;
|
|
68
|
+
}
|
|
69
|
+
//# sourceMappingURL=pending-page.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pending-page.js","sourceRoot":"","sources":["../../src/merchant-admin/pending-page.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AA6BH,gDAAgD;AAChD,MAAM,UAAU,oBAAoB,CAAC,IAAyB;IAC5D,OAAO;QACL,WAAW,EAAE,GAAG,EAAE,CAAC,IAAI,CAAC,mBAAmB,EAAE;QAC7C,eAAe,EAAE,CAAC,EAAE,EAAE,WAAW,EAAE,KAAK,EAAE,EAAE,CAC1C,IAAI,CAAC,QAAQ,CAAC,eAAe,CAAC,EAAE,EAAE,WAAW,EAAE,KAAK,CAAC;QACvD,eAAe,EAAE,CAAC,EAAE,EAAE,WAAW,EAAE,KAAK,EAAE,EAAE,CAAC,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,EAAE,WAAW,EAAE,KAAK,CAAC;KAC1F,CAAC;AACJ,CAAC;AAED,SAAS,UAAU,CAAC,IAAY;IAC9B,OAAO,IAAI;SACR,UAAU,CAAC,GAAG,EAAE,OAAO,CAAC;SACxB,UAAU,CAAC,GAAG,EAAE,MAAM,CAAC;SACvB,UAAU,CAAC,GAAG,EAAE,MAAM,CAAC;SACvB,UAAU,CAAC,GAAG,EAAE,QAAQ,CAAC,CAAC;AAC/B,CAAC;AAED,mCAAmC;AACnC,MAAM,UAAU,iBAAiB,CAC/B,YAAoB,EACpB,QAAkC,EAClC,QAAwE;IAExE,MAAM,IAAI,GAAG,QAAQ;SAClB,GAAG,CACF,CAAC,CAAC,EAAE,EAAE,CAAC;QACL,UAAU,CAAC,CAAC,CAAC,YAAY,CAAC;QAC1B,UAAU,CAAC,CAAC,CAAC,IAAI,CAAC;aACb,UAAU,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC;aAChD,UAAU,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,aAAa,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC;QACzD,UAAU,CAAC,CAAC,CAAC,UAAU,CAAC;;;sDAGsB,UAAU,CAAC,CAAC,CAAC,YAAY,CAAC;wDACxB,UAAU,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC,YAAY,EAAE,SAAS,CAAC,IAAI,EAAE,CAAC;;;;sDAIzD,UAAU,CAAC,CAAC,CAAC,YAAY,CAAC;wDACxB,UAAU,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC,YAAY,EAAE,QAAQ,CAAC,IAAI,EAAE,CAAC;;;;MAIxG,CACD;SACA,IAAI,CAAC,IAAI,CAAC,CAAC;IACd,OAAO;;6CAEoC,UAAU,CAAC,YAAY,CAAC;;QAE7D,UAAU,CAAC,YAAY,CAAC;;IAG5B,QAAQ,CAAC,MAAM,KAAK,CAAC;QACnB,CAAC,CAAC,mBAAmB;QACrB,CAAC,CAAC;;EAEN,IAAI;SAEJ;;QAEM,CAAC;AACT,CAAC"}
|
|
@@ -0,0 +1,99 @@
|
|
|
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
|
+
/**
|
|
17
|
+
* 持久命令记录与执行闭环(V2 阶段三:src/merchant-core/commands.ts)。
|
|
18
|
+
*
|
|
19
|
+
* 命令记录复用 `WriteApprovalCandidateStore`(state.sqlite 单 owner 写;
|
|
20
|
+
* 字段即命令记录:tool、arguments(含 hash)、preconditions(含 hash)、
|
|
21
|
+
* risk、principal_id、expires_at、状态机
|
|
22
|
+
* prepared→approved→executed / rejected / superseded / expired——store 里
|
|
23
|
+
* pending_approval 即 prepared)。单次用途:executed 后不可再执行。
|
|
24
|
+
*
|
|
25
|
+
* 写链路时序:
|
|
26
|
+
* prepare(登记候选 + 前置版本快照 + 预览)→ 可信确认通道写入 approved
|
|
27
|
+
* (模型自报「已批准」不作证据——只能经 executeApproved 由已认证主体触发)→
|
|
28
|
+
* 执行器校验(授权主体一致 / 前置版本重读重哈希 / 有效期 / 硬策略)→
|
|
29
|
+
* 幂等执行(executed 后重放返回 not_approvable,绝不二次执行)→ 回读校验 →
|
|
30
|
+
* 审计(store 状态流转 + content hash 即审计记录)。
|
|
31
|
+
*
|
|
32
|
+
* 恢复:进程重启后 recoverPending() 从命令记录恢复全部已注册工具的 pending
|
|
33
|
+
* 命令——钩子由固定执行器注册表按存储的 tool/arguments 确定性重建;未注册
|
|
34
|
+
* tool 的命令 fail-closed 标 expired(不展示成仍可批准)。V1 的
|
|
35
|
+
* recoverPendingDrafts 语义被本机制覆盖并推广到全部写工具。
|
|
36
|
+
*/
|
|
37
|
+
import type { AgentProfile } from "../config/profile.js";
|
|
38
|
+
import type { AgentMode } from "../agent/mode.js";
|
|
39
|
+
import { WriteApprovalCandidateError, type ApprovalExecutionResult, type WriteApprovalCandidate, type WriteApprovalCandidateStore } from "../agent/merchant/action-candidate.js";
|
|
40
|
+
import { type WriteGateResult } from "../agent/write-gate.js";
|
|
41
|
+
import type { MerchantOAuthStore } from "../auth/merchant-oauth.js";
|
|
42
|
+
import type { ExecutorContext, MerchantExecutorRegistry } from "./executor.js";
|
|
43
|
+
export interface MerchantCommandLogDeps {
|
|
44
|
+
store: WriteApprovalCandidateStore;
|
|
45
|
+
executors: MerchantExecutorRegistry;
|
|
46
|
+
executorContext: ExecutorContext;
|
|
47
|
+
profile: AgentProfile;
|
|
48
|
+
mode: () => AgentMode;
|
|
49
|
+
now: () => string;
|
|
50
|
+
/** 批准动作的调用主体(确认通道认证身份;必须等于命令记录主体)。 */
|
|
51
|
+
principalId: string;
|
|
52
|
+
/**
|
|
53
|
+
* 一次性确认凭证存储(BUG-02):配置后 execute/reject 必须携带有效确认
|
|
54
|
+
* 凭证(绑定候选内容摘要 + 主体 + 商家 + 动作,单次用途,过期/重复/不
|
|
55
|
+
* 匹配拒绝)——没有可信用户确认记录时,写操作无法执行。
|
|
56
|
+
*/
|
|
57
|
+
confirmations?: MerchantOAuthStore;
|
|
58
|
+
}
|
|
59
|
+
export interface PreparedCommand {
|
|
60
|
+
candidate: WriteApprovalCandidate;
|
|
61
|
+
/** 预览(具体改动对照;prepare 只产生候选与预览,不改业务状态)。 */
|
|
62
|
+
preview: Record<string, unknown>;
|
|
63
|
+
outcome: WriteGateResult;
|
|
64
|
+
}
|
|
65
|
+
export declare class MerchantCommandLog {
|
|
66
|
+
private readonly deps;
|
|
67
|
+
constructor(deps: MerchantCommandLogDeps);
|
|
68
|
+
/**
|
|
69
|
+
* 登记写命令(prepare):校验工具已注册 → 执行器重读前置版本 → 写门
|
|
70
|
+
* force_pending 产候选(任何模式都不自动执行)。
|
|
71
|
+
*/
|
|
72
|
+
prepare(input: {
|
|
73
|
+
tool: string;
|
|
74
|
+
arguments: Record<string, unknown>;
|
|
75
|
+
reason?: string;
|
|
76
|
+
}): Promise<PreparedCommand>;
|
|
77
|
+
/**
|
|
78
|
+
* 批准并执行(确认通道;管理页面调用)。
|
|
79
|
+
* 授权主体一致性:调用主体必须等于命令记录主体(store 按 principal 绑定)。
|
|
80
|
+
* 配置了确认凭证存储时,必须携带与该候选内容/主体/动作匹配的一次性凭证。
|
|
81
|
+
*/
|
|
82
|
+
executeApproved(commandId: string, callerPrincipalId: string, confirmationToken?: string): Promise<ApprovalExecutionResult>;
|
|
83
|
+
/** 拒绝候选(确认通道;同样需确认凭证)。 */
|
|
84
|
+
reject(commandId: string, callerPrincipalId: string, confirmationToken?: string): Promise<WriteApprovalCandidate>;
|
|
85
|
+
/**
|
|
86
|
+
* 重启恢复:从命令记录恢复全部已注册工具的 pending 命令(钩子按存储
|
|
87
|
+
* 参数经注册表确定性重建);未注册 tool 的命令 fail-closed 标 expired。
|
|
88
|
+
* 崩溃时停留在 executing 的候选一律 superseded(外部副作用不可判定,
|
|
89
|
+
* 绝不放行二次执行)。返回 { recovered, expiredUnknown, supersededExecuting }。
|
|
90
|
+
*/
|
|
91
|
+
recoverPending(): {
|
|
92
|
+
recovered: number;
|
|
93
|
+
expiredUnknown: number;
|
|
94
|
+
supersededExecuting: number;
|
|
95
|
+
};
|
|
96
|
+
listPending(): WriteApprovalCandidate[];
|
|
97
|
+
get(commandId: string): WriteApprovalCandidate | undefined;
|
|
98
|
+
}
|
|
99
|
+
export { WriteApprovalCandidateError };
|