@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
package/dist/agent/kernel.js
CHANGED
|
@@ -29,6 +29,7 @@
|
|
|
29
29
|
import { AgentHarness } from "@earendil-works/pi-agent-core";
|
|
30
30
|
import { existsSync, readFileSync, rmSync } from "node:fs";
|
|
31
31
|
import path from "node:path";
|
|
32
|
+
import { fileURLToPath } from "node:url";
|
|
32
33
|
import { ensureAgentPaths, openAgentDatabase } from "./agent-db.js";
|
|
33
34
|
import { HandoffEventStore, HandoffIdempotencyStore, foldCandidateLifecycle, deliveryState, recordLaunch, recordOpenEvidence, } from "../handoff/index.js";
|
|
34
35
|
import { buildBuyerTools } from "./buyer/buyer-tools.js";
|
|
@@ -41,6 +42,14 @@ import { buildMemoryTools } from "./chat-tools.js";
|
|
|
41
42
|
import { AGENT_MODES, DEFAULT_AGENT_MODE, isAgentMode } from "./mode.js";
|
|
42
43
|
import { WriteApprovalCandidateStore, executeApprovedCandidate, } from "./merchant/action-candidate.js";
|
|
43
44
|
import { buildMerchantTools } from "./merchant/merchant-tools.js";
|
|
45
|
+
import { publicCandidatePreview } from "./merchant/merchant-enrichment.js";
|
|
46
|
+
import { DefaultMerchantIntelligenceBackend } from "./merchant/intelligence/default-backend.js";
|
|
47
|
+
import { emitHostEvent, sanitizeHostEventData, SerializedEventSink } from "./host/events.js";
|
|
48
|
+
import { fenceModelPayload } from "./context/fencing.js";
|
|
49
|
+
import { groundingReads } from "./context/grounding.js";
|
|
50
|
+
import { MERCHANT_GROUNDING_RULES, merchantGroundingContext } from "./merchant/merchant-grounding.js";
|
|
51
|
+
import { SkillRegistry } from "./skills/registry.js";
|
|
52
|
+
import { buildSkillTools } from "./skills/tools.js";
|
|
44
53
|
import { DeterministicNegotiationRunner } from "../operator/runner.js";
|
|
45
54
|
import { MemoryStore } from "./memory/store.js";
|
|
46
55
|
import { MemoryError } from "./memory/types.js";
|
|
@@ -48,7 +57,7 @@ import { PrivateVault } from "./memory/vault.js";
|
|
|
48
57
|
import { openMainSession } from "./session.js";
|
|
49
58
|
import { registerCatalogAgent } from "../discovery/catalog-source/register.js";
|
|
50
59
|
import { KiwiCatalogSource } from "../discovery/catalog-source/kiwi-source.js";
|
|
51
|
-
import { baseSystemPrompt, renderMemoryBriefing } from "./system-prompt.js";
|
|
60
|
+
import { baseSystemPrompt, combineDynamicBriefing, renderMemoryBriefing } from "./system-prompt.js";
|
|
52
61
|
export const MAIN_SESSION_ID = "main";
|
|
53
62
|
/** 审查 P2-I:autopilot 对网关权威门持续拒绝的消息——连续失败上限与冷却窗口。 */
|
|
54
63
|
export const AUTOPILOT_MAX_SUBMIT_FAILURES = 3;
|
|
@@ -97,6 +106,61 @@ function assistantText(message) {
|
|
|
97
106
|
.join("\n")
|
|
98
107
|
.trim();
|
|
99
108
|
}
|
|
109
|
+
const PRIVATE_TOOL_RESULT_NAMES = new Set(["view_private_thresholds"]);
|
|
110
|
+
export function toolResultSummary(toolName, result) {
|
|
111
|
+
if (PRIVATE_TOOL_RESULT_NAMES.has(toolName))
|
|
112
|
+
return "工具调用已完成。";
|
|
113
|
+
if (result !== null && typeof result === "object") {
|
|
114
|
+
const content = result.content;
|
|
115
|
+
if (Array.isArray(content)) {
|
|
116
|
+
const text = content
|
|
117
|
+
.filter((item) => item !== null && typeof item === "object" &&
|
|
118
|
+
item.type === "text" &&
|
|
119
|
+
typeof item.text === "string")
|
|
120
|
+
.map((item) => item.text)
|
|
121
|
+
.join("\n")
|
|
122
|
+
.trim();
|
|
123
|
+
if (text !== "")
|
|
124
|
+
return text.slice(0, 1_000);
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
return "工具调用已完成。";
|
|
128
|
+
}
|
|
129
|
+
/** Bridge the stable AgentHarness stream/tool hooks into the optional host protocol. */
|
|
130
|
+
function attachHarnessHostEvents(harness, emitEvent) {
|
|
131
|
+
return harness.subscribe(async (event) => {
|
|
132
|
+
if (event.type === "message_update" && event.assistantMessageEvent.type === "text_delta") {
|
|
133
|
+
if (event.assistantMessageEvent.delta !== "") {
|
|
134
|
+
await emitEvent("text_delta", { text: event.assistantMessageEvent.delta });
|
|
135
|
+
}
|
|
136
|
+
return;
|
|
137
|
+
}
|
|
138
|
+
if (event.type === "tool_execution_start") {
|
|
139
|
+
await emitEvent("tool_call", {
|
|
140
|
+
tool: event.toolName,
|
|
141
|
+
call_id: event.toolCallId,
|
|
142
|
+
input: event.args,
|
|
143
|
+
});
|
|
144
|
+
return;
|
|
145
|
+
}
|
|
146
|
+
if (event.type === "tool_execution_update") {
|
|
147
|
+
await emitEvent("ui_partial", {
|
|
148
|
+
tool: event.toolName,
|
|
149
|
+
call_id: event.toolCallId,
|
|
150
|
+
partial: event.partialResult,
|
|
151
|
+
});
|
|
152
|
+
return;
|
|
153
|
+
}
|
|
154
|
+
if (event.type === "tool_execution_end") {
|
|
155
|
+
await emitEvent("tool_result", {
|
|
156
|
+
tool: event.toolName,
|
|
157
|
+
call_id: event.toolCallId,
|
|
158
|
+
status: event.isError ? "error" : "ok",
|
|
159
|
+
summary: toolResultSummary(event.toolName, event.result),
|
|
160
|
+
});
|
|
161
|
+
}
|
|
162
|
+
});
|
|
163
|
+
}
|
|
100
164
|
/** The owner's own Restricted memory values (Vault). Owner-only by isolation. */
|
|
101
165
|
function listRestrictedValues(store) {
|
|
102
166
|
const out = [];
|
|
@@ -212,6 +276,11 @@ export class AgentKernel {
|
|
|
212
276
|
commerceClient;
|
|
213
277
|
merchantClient;
|
|
214
278
|
broker;
|
|
279
|
+
merchantIntelligence;
|
|
280
|
+
/** Optional host event projection; it never owns business state. */
|
|
281
|
+
emitEvent;
|
|
282
|
+
/** Removes the optional AgentHarness stream bridge during kernel shutdown. */
|
|
283
|
+
unsubscribeHarnessEvents;
|
|
215
284
|
/** Shared mutable mode ref (tools read it via a getter before the kernel exists). */
|
|
216
285
|
modeRef = { value: DEFAULT_AGENT_MODE };
|
|
217
286
|
/** Live execution hooks for pending candidates (v0.3.0-C /approve). */
|
|
@@ -266,6 +335,10 @@ export class AgentKernel {
|
|
|
266
335
|
this.merchantClient = options.merchantClient;
|
|
267
336
|
if (options.broker !== undefined)
|
|
268
337
|
this.broker = options.broker;
|
|
338
|
+
if (options.merchantIntelligence !== undefined)
|
|
339
|
+
this.merchantIntelligence = options.merchantIntelligence;
|
|
340
|
+
this.emitEvent = options.emitEvent;
|
|
341
|
+
this.unsubscribeHarnessEvents = options.unsubscribeHarnessEvents;
|
|
269
342
|
if (options.modeRef !== undefined)
|
|
270
343
|
this.modeRef = options.modeRef;
|
|
271
344
|
this.pendingHooks = options.pendingHooks ?? new Map();
|
|
@@ -294,7 +367,7 @@ export class AgentKernel {
|
|
|
294
367
|
store.bindPrincipal(principal.principal_id);
|
|
295
368
|
let session;
|
|
296
369
|
try {
|
|
297
|
-
session = await openMainSession(paths);
|
|
370
|
+
session = await openMainSession(paths, options.eventSessionId ?? MAIN_SESSION_ID);
|
|
298
371
|
}
|
|
299
372
|
catch (err) {
|
|
300
373
|
db.close(); // never leak the SQLite handle on a fail-closed open
|
|
@@ -307,14 +380,38 @@ export class AgentKernel {
|
|
|
307
380
|
const modeRef = { value: options.mode ?? DEFAULT_AGENT_MODE };
|
|
308
381
|
const pendingHooks = new Map();
|
|
309
382
|
const turnId = { current: MAIN_SESSION_ID };
|
|
310
|
-
const
|
|
383
|
+
const registerPendingHooks = (id, hooks) => {
|
|
311
384
|
pendingHooks.set(id, hooks);
|
|
312
385
|
};
|
|
386
|
+
const hostSequence = { value: 0 };
|
|
387
|
+
const hostSink = options.eventSink === undefined ? undefined : new SerializedEventSink(options.eventSink);
|
|
388
|
+
const emitEvent = options.eventSink === undefined
|
|
389
|
+
? undefined
|
|
390
|
+
: async (type, data) => {
|
|
391
|
+
hostSequence.value += 1;
|
|
392
|
+
await emitHostEvent(hostSink, {
|
|
393
|
+
eventId: `host-${hostSequence.value}`,
|
|
394
|
+
sessionId: options.eventSessionId ?? MAIN_SESSION_ID,
|
|
395
|
+
sequence: hostSequence.value,
|
|
396
|
+
type,
|
|
397
|
+
occurredAt: clock(),
|
|
398
|
+
data: sanitizeHostEventData(type, data),
|
|
399
|
+
});
|
|
400
|
+
};
|
|
313
401
|
const approvals = new WriteApprovalCandidateStore({
|
|
314
402
|
db,
|
|
315
403
|
principalId: principal.principal_id,
|
|
316
404
|
now: clock,
|
|
317
405
|
});
|
|
406
|
+
const registerPending = (id, hooks) => {
|
|
407
|
+
registerPendingHooks(id, hooks);
|
|
408
|
+
const candidate = approvals.get(id);
|
|
409
|
+
void emitEvent?.("candidate_update", {
|
|
410
|
+
candidate_id: id,
|
|
411
|
+
status: candidate?.status ?? "pending_approval",
|
|
412
|
+
preview: publicCandidatePreview(candidate),
|
|
413
|
+
});
|
|
414
|
+
};
|
|
318
415
|
// Execution hooks are deliberately process-local. Invalidate durable
|
|
319
416
|
// candidates before wiring tools so a restarted kernel never exposes a
|
|
320
417
|
// /pending item that its /approve path cannot execute.
|
|
@@ -324,6 +421,14 @@ export class AgentKernel {
|
|
|
324
421
|
let supplierScheduler;
|
|
325
422
|
let buyerTools = [];
|
|
326
423
|
let merchantTools = [];
|
|
424
|
+
let merchantSkillTools = [];
|
|
425
|
+
let merchantIntelligence;
|
|
426
|
+
const merchantSkillRegistry = options.profile.role === "merchant" &&
|
|
427
|
+
options.profile.merchant_experience?.enabled === true &&
|
|
428
|
+
options.profile.merchant_experience.skills === true
|
|
429
|
+
? SkillRegistry.fromDir(path.resolve(path.dirname(fileURLToPath(import.meta.url)), "../../skills/merchant"), "merchant")
|
|
430
|
+
: new SkillRegistry([]);
|
|
431
|
+
merchantSkillTools = buildSkillTools(merchantSkillRegistry);
|
|
327
432
|
let handoffRuntime;
|
|
328
433
|
if (options.profile.role === "buyer" && options.connector !== undefined) {
|
|
329
434
|
taskStore = new BuyerTaskStore({
|
|
@@ -359,6 +464,7 @@ export class AgentKernel {
|
|
|
359
464
|
? { catalogSource: new KiwiCatalogSource({ baseUrl: options.catalog }) }
|
|
360
465
|
: {}),
|
|
361
466
|
trustStore: new TrustRecordStore({ dir: path.dirname(paths.db), now: clock }),
|
|
467
|
+
...(options.allowLoopback === true ? { allowLoopback: true } : {}),
|
|
362
468
|
});
|
|
363
469
|
// v0.7.0 KTH:handoff 存储(Ledger 事件 + 执行幂等)落在 agent data dir,
|
|
364
470
|
// 注入 buyer 工具(handoff_agreement 工具挂载)。
|
|
@@ -393,6 +499,24 @@ export class AgentKernel {
|
|
|
393
499
|
else if (options.profile.role === "merchant" &&
|
|
394
500
|
options.merchantClient !== undefined &&
|
|
395
501
|
options.broker !== undefined) {
|
|
502
|
+
if (options.profile.merchant_experience?.enabled === true &&
|
|
503
|
+
options.profile.merchant_experience.intelligence !== false) {
|
|
504
|
+
merchantIntelligence = new DefaultMerchantIntelligenceBackend({
|
|
505
|
+
merchant_id: principal.owner_id,
|
|
506
|
+
data_dir: path.dirname(paths.db),
|
|
507
|
+
// 口径修复(V2 阶段二遗留核查):presentation enrich 以
|
|
508
|
+
// context.principalId 作为商家读取键(merchant_id 口径),backend 的
|
|
509
|
+
// principal 校验键必须同口径——用 agent_id 会让 digest/catalog 展示
|
|
510
|
+
// 在真实商家 profile(agent_id ≠ owner_id)下必然校验失败/读空。
|
|
511
|
+
principal_id: principal.owner_id,
|
|
512
|
+
merchant_client: options.merchantClient,
|
|
513
|
+
approvals,
|
|
514
|
+
...(options.merchantAnalyticsSource !== undefined
|
|
515
|
+
? { analytics_source: options.merchantAnalyticsSource }
|
|
516
|
+
: {}),
|
|
517
|
+
now: clock,
|
|
518
|
+
});
|
|
519
|
+
}
|
|
396
520
|
merchantTools = buildMerchantTools({
|
|
397
521
|
profile: options.profile,
|
|
398
522
|
merchantClient: options.merchantClient,
|
|
@@ -400,17 +524,20 @@ export class AgentKernel {
|
|
|
400
524
|
// fail closed,目录/库存只读与审批式写工具照常可用(见 §15.3/§15.4)。
|
|
401
525
|
...(options.commerceClient !== undefined ? { commerceClient: options.commerceClient } : {}),
|
|
402
526
|
broker: options.broker,
|
|
527
|
+
principalId: principal.principal_id,
|
|
403
528
|
approvals,
|
|
404
529
|
mode: () => modeRef.value,
|
|
405
530
|
registerPending,
|
|
406
531
|
now: clock,
|
|
407
532
|
privateValues: () => listRestrictedValues(store),
|
|
533
|
+
...(merchantIntelligence !== undefined ? { intelligence: merchantIntelligence } : {}),
|
|
534
|
+
...(emitEvent !== undefined ? { emitEvent } : {}),
|
|
408
535
|
// 商家 A2A 节点 ledger 基础目录(<dataDir>/a2a)——LedgerStore 会再拼
|
|
409
536
|
// /ledger 到 <dataDir>/a2a/ledger,list_a2a_negotiations 用。
|
|
410
537
|
a2aLedgerDir: path.join(path.dirname(paths.db), "a2a"),
|
|
411
538
|
});
|
|
412
539
|
}
|
|
413
|
-
const base = baseSystemPrompt(options.profile, principal);
|
|
540
|
+
const base = baseSystemPrompt(options.profile, principal, merchantSkillRegistry.names.length > 0 ? merchantSkillRegistry : undefined);
|
|
414
541
|
let briefing;
|
|
415
542
|
const harness = new AgentHarness({
|
|
416
543
|
session,
|
|
@@ -420,12 +547,19 @@ export class AgentKernel {
|
|
|
420
547
|
...buildMemoryTools(store, { turnId: () => turnId.current }),
|
|
421
548
|
...buyerTools,
|
|
422
549
|
...merchantTools,
|
|
550
|
+
...merchantSkillTools,
|
|
423
551
|
],
|
|
424
552
|
systemPrompt: async () => (briefing === undefined ? base : `${base}\n\n${briefing}`),
|
|
425
553
|
// §18.1: a hung model/provider request must NOT wedge the chat forever —
|
|
426
554
|
// abort after the profile's turn timeout and surface an error text.
|
|
427
555
|
streamOptions: {
|
|
428
556
|
timeoutMs: options.profile.runtime.turn_timeout_seconds * 1000,
|
|
557
|
+
...(options.profile.merchant_experience?.prompt_cache_retention !== undefined
|
|
558
|
+
? {
|
|
559
|
+
cacheRetention: options.profile.merchant_experience.prompt_cache_retention,
|
|
560
|
+
sessionId: options.eventSessionId ?? MAIN_SESSION_ID,
|
|
561
|
+
}
|
|
562
|
+
: {}),
|
|
429
563
|
},
|
|
430
564
|
...(options.thinkingLevel !== undefined ? { thinkingLevel: options.thinkingLevel } : {}),
|
|
431
565
|
});
|
|
@@ -435,6 +569,9 @@ export class AgentKernel {
|
|
|
435
569
|
if (options.model !== undefined) {
|
|
436
570
|
await harness.setModel(options.model);
|
|
437
571
|
}
|
|
572
|
+
const unsubscribeHarnessEvents = emitEvent === undefined
|
|
573
|
+
? undefined
|
|
574
|
+
: attachHarnessHostEvents(harness, emitEvent);
|
|
438
575
|
const kernel = new AgentKernel({
|
|
439
576
|
profile: options.profile,
|
|
440
577
|
paths,
|
|
@@ -455,6 +592,9 @@ export class AgentKernel {
|
|
|
455
592
|
...(options.commerceClient !== undefined ? { commerceClient: options.commerceClient } : {}),
|
|
456
593
|
...(options.merchantClient !== undefined ? { merchantClient: options.merchantClient } : {}),
|
|
457
594
|
...(options.broker !== undefined ? { broker: options.broker } : {}),
|
|
595
|
+
...(merchantIntelligence !== undefined ? { merchantIntelligence } : {}),
|
|
596
|
+
emitEvent,
|
|
597
|
+
...(unsubscribeHarnessEvents !== undefined ? { unsubscribeHarnessEvents } : {}),
|
|
458
598
|
});
|
|
459
599
|
kernel.briefingSetter = (value) => {
|
|
460
600
|
briefing = value;
|
|
@@ -605,7 +745,7 @@ export class AgentKernel {
|
|
|
605
745
|
/**
|
|
606
746
|
* Change the runtime mode. Switching INTO autopilot requires an explicit
|
|
607
747
|
* `confirm` — the same fail-closed rule as the operator control plane
|
|
608
|
-
* (
|
|
748
|
+
* (operator control-plane design §8).
|
|
609
749
|
*/
|
|
610
750
|
setMode(mode, options) {
|
|
611
751
|
if (!isAgentMode(mode)) {
|
|
@@ -658,17 +798,26 @@ export class AgentKernel {
|
|
|
658
798
|
if (candidate === undefined) {
|
|
659
799
|
throw new MemoryError("validation", `未知审批候选 ${candidateId}`);
|
|
660
800
|
}
|
|
801
|
+
const report = async (result) => {
|
|
802
|
+
const current = this.approvals?.get(candidateId);
|
|
803
|
+
await this.emitEvent?.("candidate_update", {
|
|
804
|
+
candidate_id: candidateId,
|
|
805
|
+
status: current?.status ?? result.candidate.status,
|
|
806
|
+
preview: publicCandidatePreview(current ?? result.candidate),
|
|
807
|
+
});
|
|
808
|
+
return result;
|
|
809
|
+
};
|
|
661
810
|
// manual 模式语义(评审项 P3-3):manual = advice only(never executes)。
|
|
662
811
|
// routeWriteCandidate 在 manual 分支仍注册执行钩子(供 /pending 显示与
|
|
663
812
|
// /revise 重算),但批准路径必须拒绝——此前 /approve 绕过模式直接执行,
|
|
664
813
|
// 与 operator 平面分叉(controller 对 advice_only 候选明确拒绝批准:
|
|
665
814
|
// "manual 模式只提供建议,不自动提交")。
|
|
666
815
|
if (this.getMode() === "manual") {
|
|
667
|
-
return {
|
|
816
|
+
return report({
|
|
668
817
|
kind: "not_approvable",
|
|
669
818
|
candidate,
|
|
670
819
|
reason: "manual 模式只提供建议,不自动执行(/approve 拒绝 advice-only 候选)",
|
|
671
|
-
};
|
|
820
|
+
});
|
|
672
821
|
}
|
|
673
822
|
const hooks = this.pendingHooks.get(candidateId);
|
|
674
823
|
if (hooks === undefined) {
|
|
@@ -676,19 +825,19 @@ export class AgentKernel {
|
|
|
676
825
|
// candidate cannot be re-validated against the current marketplace.
|
|
677
826
|
if (candidate.status === "expired") {
|
|
678
827
|
this.releasePending(candidateId);
|
|
679
|
-
return { kind: "expired", candidate };
|
|
828
|
+
return report({ kind: "expired", candidate });
|
|
680
829
|
}
|
|
681
830
|
if (candidate.status !== "pending_approval" && candidate.status !== "approved") {
|
|
682
831
|
this.releasePending(candidateId);
|
|
683
|
-
return {
|
|
832
|
+
return report({
|
|
684
833
|
kind: "not_approvable",
|
|
685
834
|
candidate,
|
|
686
835
|
reason: `候选 ${candidateId} 状态为 ${candidate.status},不可批准。`,
|
|
687
|
-
};
|
|
836
|
+
});
|
|
688
837
|
}
|
|
689
838
|
const expired = this.approvals.expireCandidate(candidateId);
|
|
690
839
|
this.releasePending(candidateId);
|
|
691
|
-
return { kind: "expired", candidate: expired };
|
|
840
|
+
return report({ kind: "expired", candidate: expired });
|
|
692
841
|
}
|
|
693
842
|
this.approvals.markApproved(candidateId);
|
|
694
843
|
const outcome = await executeApprovedCandidate(this.approvals, candidateId, hooks);
|
|
@@ -697,7 +846,7 @@ export class AgentKernel {
|
|
|
697
846
|
if (outcome.kind !== "not_approvable") {
|
|
698
847
|
this.releasePending(candidateId);
|
|
699
848
|
}
|
|
700
|
-
return outcome;
|
|
849
|
+
return report(outcome);
|
|
701
850
|
}
|
|
702
851
|
/** Reject a pending/advice-only WriteApprovalCandidate. Never executes. */
|
|
703
852
|
rejectCandidate(candidateId) {
|
|
@@ -711,6 +860,11 @@ export class AgentKernel {
|
|
|
711
860
|
}
|
|
712
861
|
this.approvals.reject(candidateId);
|
|
713
862
|
this.releasePending(candidateId);
|
|
863
|
+
void this.emitEvent?.("candidate_update", {
|
|
864
|
+
candidate_id: candidateId,
|
|
865
|
+
status: this.approvals.get(candidateId)?.status ?? "rejected",
|
|
866
|
+
preview: publicCandidatePreview(this.approvals.get(candidateId)),
|
|
867
|
+
});
|
|
714
868
|
return { ok: true };
|
|
715
869
|
}
|
|
716
870
|
/**
|
|
@@ -728,6 +882,7 @@ export class AgentKernel {
|
|
|
728
882
|
this.handoffRuntime?.ledger.sweepExpiredHandoffs(this.clock());
|
|
729
883
|
const empty = {
|
|
730
884
|
checked_rules: 0,
|
|
885
|
+
requests_used: 0,
|
|
731
886
|
notifications: [],
|
|
732
887
|
tasks_searched: [],
|
|
733
888
|
tasks_expired: [],
|
|
@@ -737,8 +892,9 @@ export class AgentKernel {
|
|
|
737
892
|
// M1:供应商关系 pull tick 走同一 kernel 串行链,共享请求预算;
|
|
738
893
|
// supplier tick 失败不影响 task tick 结果(错误进 supplier.errors)。
|
|
739
894
|
if (this.supplierScheduler !== undefined) {
|
|
895
|
+
const totalBudget = budget.max_requests ?? 20;
|
|
740
896
|
result.supplier = await this.supplierScheduler.tick({
|
|
741
|
-
|
|
897
|
+
max_requests: Math.max(0, totalBudget - result.requests_used),
|
|
742
898
|
});
|
|
743
899
|
}
|
|
744
900
|
return result;
|
|
@@ -921,6 +1077,71 @@ export class AgentKernel {
|
|
|
921
1077
|
timestamp: Date.now(),
|
|
922
1078
|
});
|
|
923
1079
|
}
|
|
1080
|
+
async runMerchantGroundingRead(read) {
|
|
1081
|
+
await this.emitEvent?.("grounding_started", {
|
|
1082
|
+
rule: read.tool,
|
|
1083
|
+
tool: read.tool,
|
|
1084
|
+
reason: read.reason,
|
|
1085
|
+
});
|
|
1086
|
+
try {
|
|
1087
|
+
let payload;
|
|
1088
|
+
if (read.tool === "get_business_snapshot" && this.merchantIntelligence !== undefined) {
|
|
1089
|
+
payload = await this.merchantIntelligence.getBusinessSnapshot({ merchant_id: this.principal.owner_id });
|
|
1090
|
+
}
|
|
1091
|
+
else if (read.tool === "get_negotiation_digest" && this.merchantIntelligence !== undefined) {
|
|
1092
|
+
payload = await this.merchantIntelligence.getNegotiationDigest({
|
|
1093
|
+
merchant_id: this.principal.owner_id,
|
|
1094
|
+
status: "active",
|
|
1095
|
+
limit: 20,
|
|
1096
|
+
});
|
|
1097
|
+
}
|
|
1098
|
+
else if (read.tool === "get_pending_actions" && this.merchantIntelligence !== undefined) {
|
|
1099
|
+
payload = await this.merchantIntelligence.getPendingActions();
|
|
1100
|
+
}
|
|
1101
|
+
else if (read.tool === "get_catalog_health" && this.merchantIntelligence !== undefined) {
|
|
1102
|
+
payload = await this.merchantIntelligence.getCatalogHealth({ merchant_id: this.principal.owner_id });
|
|
1103
|
+
}
|
|
1104
|
+
else if (read.tool === "get_human_review_queue" && this.merchantClient !== undefined) {
|
|
1105
|
+
payload = await this.merchantClient.getHumanReviewQueue(this.principal.owner_id);
|
|
1106
|
+
}
|
|
1107
|
+
else if (read.tool === "list_catalog_products" && this.merchantClient !== undefined) {
|
|
1108
|
+
payload = await this.merchantClient.listProducts(this.principal.owner_id);
|
|
1109
|
+
}
|
|
1110
|
+
else {
|
|
1111
|
+
throw new Error("grounding dependency is unavailable");
|
|
1112
|
+
}
|
|
1113
|
+
await this.emitEvent?.("grounding_completed", {
|
|
1114
|
+
rule: read.tool,
|
|
1115
|
+
tool: read.tool,
|
|
1116
|
+
status: "ok",
|
|
1117
|
+
});
|
|
1118
|
+
return [
|
|
1119
|
+
`[Grounding · ${read.reason}]`,
|
|
1120
|
+
fenceModelPayload(read.tool === "get_negotiation_digest" ? "a2a_message" : "merchant_api", payload, { maxChars: this.profile.merchant_experience?.max_external_context_chars ?? 12_000 }),
|
|
1121
|
+
].join("\n");
|
|
1122
|
+
}
|
|
1123
|
+
catch {
|
|
1124
|
+
await this.emitEvent?.("grounding_completed", {
|
|
1125
|
+
rule: read.tool,
|
|
1126
|
+
tool: read.tool,
|
|
1127
|
+
status: "error",
|
|
1128
|
+
retryable: true,
|
|
1129
|
+
});
|
|
1130
|
+
return `[Grounding · ${read.reason}] 当前权威读取不可用,不要把缺失数据当作零值。`;
|
|
1131
|
+
}
|
|
1132
|
+
}
|
|
1133
|
+
/** Run at most two deterministic, read-only merchant grounding reads per turn. */
|
|
1134
|
+
async merchantGrounding(text) {
|
|
1135
|
+
if (this.profile.role !== "merchant" ||
|
|
1136
|
+
this.profile.merchant_experience?.enabled !== true ||
|
|
1137
|
+
this.profile.merchant_experience.grounding === false) {
|
|
1138
|
+
return undefined;
|
|
1139
|
+
}
|
|
1140
|
+
const reads = groundingReads(MERCHANT_GROUNDING_RULES, merchantGroundingContext(this.profile, text), 2);
|
|
1141
|
+
if (reads.length === 0)
|
|
1142
|
+
return undefined;
|
|
1143
|
+
return (await Promise.all(reads.map((read) => this.runMerchantGroundingRead(read)))).join("\n\n");
|
|
1144
|
+
}
|
|
924
1145
|
/**
|
|
925
1146
|
* 把一轮 A2A 磋商结果写入记忆(episode namespace,active 无需人工确认):
|
|
926
1147
|
* 持久上下文,`/why` 可查、跨重启可恢复。
|
|
@@ -935,12 +1156,16 @@ export class AgentKernel {
|
|
|
935
1156
|
if (text.startsWith("/")) {
|
|
936
1157
|
return await this.handleSlash(text);
|
|
937
1158
|
}
|
|
1159
|
+
const startedAt = Date.now();
|
|
1160
|
+
await this.emitEvent?.("message", { role: "user", text });
|
|
938
1161
|
const memories = this.store.retrieve({
|
|
939
1162
|
session_id: MAIN_SESSION_ID,
|
|
940
1163
|
purpose: "clarify",
|
|
941
1164
|
text,
|
|
942
1165
|
});
|
|
943
|
-
|
|
1166
|
+
const memoryBriefing = renderMemoryBriefing(memories);
|
|
1167
|
+
const groundingBriefing = await this.merchantGrounding(text);
|
|
1168
|
+
this.briefingSetter(combineDynamicBriefing([memoryBriefing, groundingBriefing]));
|
|
944
1169
|
// Advance the turn id so several remember calls inside this one turn
|
|
945
1170
|
// dedup into a single evidence piece (§9.3).
|
|
946
1171
|
this.turnId.current = `${MAIN_SESSION_ID}:${++this.turnSeq}`;
|
|
@@ -950,20 +1175,35 @@ export class AgentKernel {
|
|
|
950
1175
|
// §18.1: a model failure (throw OR empty response) must leave the
|
|
951
1176
|
// conversation and TUI intact.
|
|
952
1177
|
if (reply === "") {
|
|
1178
|
+
await this.emitEvent?.("error", {
|
|
1179
|
+
code: "empty_model_response",
|
|
1180
|
+
message: "model returned an empty response",
|
|
1181
|
+
retryable: true,
|
|
1182
|
+
});
|
|
953
1183
|
return {
|
|
954
1184
|
text: "暂时没能给出有效回复——当前目录里可能没有匹配的商品或商家,也可能是这条需求还不够具体。补充品牌、型号或预算范围后再问我一次即可。",
|
|
955
1185
|
quit: false,
|
|
956
1186
|
};
|
|
957
1187
|
}
|
|
1188
|
+
await this.emitEvent?.("message", { role: "assistant", text: reply });
|
|
958
1189
|
return { text: reply, quit: false };
|
|
959
1190
|
}
|
|
960
1191
|
catch (err) {
|
|
1192
|
+
await this.emitEvent?.("error", {
|
|
1193
|
+
code: "model_turn_failed",
|
|
1194
|
+
message: err instanceof Error ? err.message : String(err),
|
|
1195
|
+
retryable: true,
|
|
1196
|
+
});
|
|
961
1197
|
return {
|
|
962
1198
|
text: `模型处理失败:${err instanceof Error ? err.message : String(err)}。对话状态未改变,请重试。`,
|
|
963
1199
|
quit: false,
|
|
964
1200
|
};
|
|
965
1201
|
}
|
|
966
1202
|
finally {
|
|
1203
|
+
await this.emitEvent?.("turn_complete", {
|
|
1204
|
+
elapsed_ms: Date.now() - startedAt,
|
|
1205
|
+
stop_reason: "complete",
|
|
1206
|
+
});
|
|
967
1207
|
this.briefingSetter(undefined);
|
|
968
1208
|
}
|
|
969
1209
|
});
|
|
@@ -1293,6 +1533,7 @@ export class AgentKernel {
|
|
|
1293
1533
|
catch {
|
|
1294
1534
|
// best-effort flush; closing the store is what must not be skipped
|
|
1295
1535
|
}
|
|
1536
|
+
this.unsubscribeHarnessEvents?.();
|
|
1296
1537
|
this.db.close();
|
|
1297
1538
|
}
|
|
1298
1539
|
}
|