@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.
Files changed (332) hide show
  1. package/README.md +45 -10
  2. package/dist/a2a/negotiate.d.ts +6 -2
  3. package/dist/a2a/negotiate.js +10 -3
  4. package/dist/a2a/negotiate.js.map +1 -1
  5. package/dist/a2a/node.d.ts +4 -1
  6. package/dist/a2a/node.js +57 -4
  7. package/dist/a2a/node.js.map +1 -1
  8. package/dist/a2a/server/merchant-handler.d.ts +11 -3
  9. package/dist/a2a/server/merchant-handler.js +84 -26
  10. package/dist/a2a/server/merchant-handler.js.map +1 -1
  11. package/dist/agent/buyer/buyer-tools.js +17 -10
  12. package/dist/agent/buyer/buyer-tools.js.map +1 -1
  13. package/dist/agent/buyer/scheduler.d.ts +1 -0
  14. package/dist/agent/buyer/scheduler.js +5 -1
  15. package/dist/agent/buyer/scheduler.js.map +1 -1
  16. package/dist/agent/buyer/task-store.js +5 -2
  17. package/dist/agent/buyer/task-store.js.map +1 -1
  18. package/dist/agent/chat-tools.js +10 -3
  19. package/dist/agent/chat-tools.js.map +1 -1
  20. package/dist/agent/context/fencing.d.ts +27 -0
  21. package/dist/agent/context/fencing.js +126 -0
  22. package/dist/agent/context/fencing.js.map +1 -0
  23. package/dist/agent/context/grounding.d.ts +18 -0
  24. package/dist/agent/context/grounding.js +22 -0
  25. package/dist/agent/context/grounding.js.map +1 -0
  26. package/dist/agent/host/events.d.ts +31 -0
  27. package/dist/agent/host/events.js +62 -0
  28. package/dist/agent/host/events.js.map +1 -0
  29. package/dist/agent/host/tui-renderer.d.ts +17 -0
  30. package/dist/agent/host/tui-renderer.js +125 -0
  31. package/dist/agent/host/tui-renderer.js.map +1 -0
  32. package/dist/agent/host/web-renderer.d.ts +71 -0
  33. package/dist/agent/host/web-renderer.js +185 -0
  34. package/dist/agent/host/web-renderer.js.map +1 -0
  35. package/dist/agent/kernel-builder.d.ts +3 -1
  36. package/dist/agent/kernel-builder.js +4 -1
  37. package/dist/agent/kernel-builder.js.map +1 -1
  38. package/dist/agent/kernel.d.ts +20 -1
  39. package/dist/agent/kernel.js +255 -14
  40. package/dist/agent/kernel.js.map +1 -1
  41. package/dist/agent/memory/schema.d.ts +1 -1
  42. package/dist/agent/memory/schema.js +9 -1
  43. package/dist/agent/memory/schema.js.map +1 -1
  44. package/dist/agent/merchant/action-candidate.d.ts +18 -0
  45. package/dist/agent/merchant/action-candidate.js +51 -0
  46. package/dist/agent/merchant/action-candidate.js.map +1 -1
  47. package/dist/agent/merchant/fake-merchant-client.js +6 -1
  48. package/dist/agent/merchant/fake-merchant-client.js.map +1 -1
  49. package/dist/agent/merchant/intelligence/backend.d.ts +40 -0
  50. package/dist/agent/merchant/intelligence/backend.js +2 -0
  51. package/dist/agent/merchant/intelligence/backend.js.map +1 -0
  52. package/dist/agent/merchant/intelligence/default-backend.d.ts +38 -0
  53. package/dist/agent/merchant/intelligence/default-backend.js +477 -0
  54. package/dist/agent/merchant/intelligence/default-backend.js.map +1 -0
  55. package/dist/agent/merchant/intelligence/http-analytics-source.d.ts +55 -0
  56. package/dist/agent/merchant/intelligence/http-analytics-source.js +193 -0
  57. package/dist/agent/merchant/intelligence/http-analytics-source.js.map +1 -0
  58. package/dist/agent/merchant/intelligence/types.d.ts +109 -0
  59. package/dist/agent/merchant/intelligence/types.js +2 -0
  60. package/dist/agent/merchant/intelligence/types.js.map +1 -0
  61. package/dist/agent/merchant/merchant-client.d.ts +50 -1
  62. package/dist/agent/merchant/merchant-client.js +157 -8
  63. package/dist/agent/merchant/merchant-client.js.map +1 -1
  64. package/dist/agent/merchant/merchant-enrichment.d.ts +10 -0
  65. package/dist/agent/merchant/merchant-enrichment.js +38 -0
  66. package/dist/agent/merchant/merchant-enrichment.js.map +1 -0
  67. package/dist/agent/merchant/merchant-grounding.d.ts +5 -0
  68. package/dist/agent/merchant/merchant-grounding.js +76 -0
  69. package/dist/agent/merchant/merchant-grounding.js.map +1 -0
  70. package/dist/agent/merchant/merchant-presentations.d.ts +8 -0
  71. package/dist/agent/merchant/merchant-presentations.js +207 -0
  72. package/dist/agent/merchant/merchant-presentations.js.map +1 -0
  73. package/dist/agent/merchant/merchant-tools.d.ts +8 -0
  74. package/dist/agent/merchant/merchant-tools.js +291 -178
  75. package/dist/agent/merchant/merchant-tools.js.map +1 -1
  76. package/dist/agent/merchant/types.d.ts +6 -2
  77. package/dist/agent/merchant/types.js +45 -0
  78. package/dist/agent/merchant/types.js.map +1 -1
  79. package/dist/agent/presentation/registry.d.ts +14 -0
  80. package/dist/agent/presentation/registry.js +24 -0
  81. package/dist/agent/presentation/registry.js.map +1 -0
  82. package/dist/agent/presentation/runner.d.ts +11 -0
  83. package/dist/agent/presentation/runner.js +17 -0
  84. package/dist/agent/presentation/runner.js.map +1 -0
  85. package/dist/agent/presentation/sanitize.d.ts +16 -0
  86. package/dist/agent/presentation/sanitize.js +37 -0
  87. package/dist/agent/presentation/sanitize.js.map +1 -0
  88. package/dist/agent/presentation/types.d.ts +28 -0
  89. package/dist/agent/presentation/types.js +8 -0
  90. package/dist/agent/presentation/types.js.map +1 -0
  91. package/dist/agent/session.d.ts +1 -1
  92. package/dist/agent/session.js +2 -2
  93. package/dist/agent/session.js.map +1 -1
  94. package/dist/agent/skills/registry.d.ts +11 -0
  95. package/dist/agent/skills/registry.js +119 -0
  96. package/dist/agent/skills/registry.js.map +1 -0
  97. package/dist/agent/skills/tools.d.ts +6 -0
  98. package/dist/agent/skills/tools.js +36 -0
  99. package/dist/agent/skills/tools.js.map +1 -0
  100. package/dist/agent/skills/types.d.ts +9 -0
  101. package/dist/agent/skills/types.js +2 -0
  102. package/dist/agent/skills/types.js.map +1 -0
  103. package/dist/agent/supplier/scheduler.d.ts +2 -0
  104. package/dist/agent/supplier/scheduler.js +101 -22
  105. package/dist/agent/supplier/scheduler.js.map +1 -1
  106. package/dist/agent/supplier/store.d.ts +2 -0
  107. package/dist/agent/supplier/store.js +44 -0
  108. package/dist/agent/supplier/store.js.map +1 -1
  109. package/dist/agent/system-prompt.d.ts +5 -1
  110. package/dist/agent/system-prompt.js +20 -3
  111. package/dist/agent/system-prompt.js.map +1 -1
  112. package/dist/auth/merchant-authorization.d.ts +49 -0
  113. package/dist/auth/merchant-authorization.js +61 -0
  114. package/dist/auth/merchant-authorization.js.map +1 -0
  115. package/dist/auth/merchant-oauth.d.ts +255 -0
  116. package/dist/auth/merchant-oauth.js +764 -0
  117. package/dist/auth/merchant-oauth.js.map +1 -0
  118. package/dist/auth/merchant-pairing.d.ts +62 -0
  119. package/dist/auth/merchant-pairing.js +199 -0
  120. package/dist/auth/merchant-pairing.js.map +1 -0
  121. package/dist/auth/merchant-sessions.d.ts +71 -0
  122. package/dist/auth/merchant-sessions.js +168 -0
  123. package/dist/auth/merchant-sessions.js.map +1 -0
  124. package/dist/buyer-core/build-service.d.ts +5 -0
  125. package/dist/buyer-core/build-service.js +12 -0
  126. package/dist/buyer-core/build-service.js.map +1 -1
  127. package/dist/buyer-core/errors.d.ts +1 -1
  128. package/dist/buyer-core/errors.js +2 -0
  129. package/dist/buyer-core/errors.js.map +1 -1
  130. package/dist/buyer-core/merchant-index.d.ts +19 -4
  131. package/dist/buyer-core/merchant-index.js +137 -16
  132. package/dist/buyer-core/merchant-index.js.map +1 -1
  133. package/dist/buyer-core/negotiator.d.ts +0 -10
  134. package/dist/buyer-core/negotiator.js +12 -1
  135. package/dist/buyer-core/negotiator.js.map +1 -1
  136. package/dist/buyer-core/quote-fetcher.js +2 -1
  137. package/dist/buyer-core/quote-fetcher.js.map +1 -1
  138. package/dist/buyer-core/service.d.ts +104 -0
  139. package/dist/buyer-core/service.js +105 -1
  140. package/dist/buyer-core/service.js.map +1 -1
  141. package/dist/cli.d.ts +4 -2
  142. package/dist/cli.js +644 -32
  143. package/dist/cli.js.map +1 -1
  144. package/dist/config/profile.d.ts +51 -0
  145. package/dist/config/profile.js +185 -61
  146. package/dist/config/profile.js.map +1 -1
  147. package/dist/demo/demo-runner.js +12 -9
  148. package/dist/demo/demo-runner.js.map +1 -1
  149. package/dist/discovery/catalog-source/buyer-follows.d.ts +82 -0
  150. package/dist/discovery/catalog-source/buyer-follows.js +228 -0
  151. package/dist/discovery/catalog-source/buyer-follows.js.map +1 -0
  152. package/dist/discovery/catalog-source/connector-identity.d.ts +75 -0
  153. package/dist/discovery/catalog-source/connector-identity.js +175 -0
  154. package/dist/discovery/catalog-source/connector-identity.js.map +1 -0
  155. package/dist/discovery/catalog-source/errors.d.ts +1 -1
  156. package/dist/discovery/catalog-source/errors.js +2 -0
  157. package/dist/discovery/catalog-source/errors.js.map +1 -1
  158. package/dist/discovery/catalog-source/kiwi-record.d.ts +2 -0
  159. package/dist/discovery/catalog-source/kiwi-record.js.map +1 -1
  160. package/dist/discovery/catalog-source/kiwi-source.js +2 -0
  161. package/dist/discovery/catalog-source/kiwi-source.js.map +1 -1
  162. package/dist/discovery/catalog-source/merchant-publications.d.ts +65 -0
  163. package/dist/discovery/catalog-source/merchant-publications.js +207 -0
  164. package/dist/discovery/catalog-source/merchant-publications.js.map +1 -0
  165. package/dist/discovery/catalog-source/register.d.ts +24 -0
  166. package/dist/discovery/catalog-source/register.js +46 -0
  167. package/dist/discovery/catalog-source/register.js.map +1 -1
  168. package/dist/discovery/catalog-source/source.js +2 -1
  169. package/dist/discovery/catalog-source/source.js.map +1 -1
  170. package/dist/fs/atomic-write.d.ts +18 -0
  171. package/dist/fs/atomic-write.js +29 -0
  172. package/dist/fs/atomic-write.js.map +1 -0
  173. package/dist/handoff/authorization.js +1 -1
  174. package/dist/http/merchant-server.d.ts +65 -0
  175. package/dist/http/merchant-server.js +346 -0
  176. package/dist/http/merchant-server.js.map +1 -0
  177. package/dist/http/server.js +4 -1
  178. package/dist/http/server.js.map +1 -1
  179. package/dist/mcp/cli.d.ts +2 -0
  180. package/dist/mcp/cli.js +7 -6
  181. package/dist/mcp/cli.js.map +1 -1
  182. package/dist/mcp/merchant-auth.d.ts +78 -0
  183. package/dist/mcp/merchant-auth.js +146 -0
  184. package/dist/mcp/merchant-auth.js.map +1 -0
  185. package/dist/mcp/merchant-dirs.d.ts +26 -0
  186. package/dist/mcp/merchant-dirs.js +44 -0
  187. package/dist/mcp/merchant-dirs.js.map +1 -0
  188. package/dist/mcp/merchant-resources.d.ts +38 -0
  189. package/dist/mcp/merchant-resources.js +146 -0
  190. package/dist/mcp/merchant-resources.js.map +1 -0
  191. package/dist/mcp/merchant-server.d.ts +106 -0
  192. package/dist/mcp/merchant-server.js +615 -0
  193. package/dist/mcp/merchant-server.js.map +1 -0
  194. package/dist/mcp/merchant-tools.d.ts +103 -0
  195. package/dist/mcp/merchant-tools.js +517 -0
  196. package/dist/mcp/merchant-tools.js.map +1 -0
  197. package/dist/mcp/server.js +4 -3
  198. package/dist/mcp/server.js.map +1 -1
  199. package/dist/mcp/tools.d.ts +5 -3
  200. package/dist/mcp/tools.js +102 -5
  201. package/dist/mcp/tools.js.map +1 -1
  202. package/dist/mcp/types.d.ts +1 -1
  203. package/dist/mcp/types.js +4 -0
  204. package/dist/mcp/types.js.map +1 -1
  205. package/dist/merchant/ops.d.ts +0 -11
  206. package/dist/merchant/ops.js +13 -1
  207. package/dist/merchant/ops.js.map +1 -1
  208. package/dist/merchant/stats-store.d.ts +7 -0
  209. package/dist/merchant/stats-store.js +11 -0
  210. package/dist/merchant/stats-store.js.map +1 -1
  211. package/dist/merchant/workbench-service.d.ts +189 -0
  212. package/dist/merchant/workbench-service.js +417 -0
  213. package/dist/merchant/workbench-service.js.map +1 -0
  214. package/dist/merchant-admin/pending-page.d.ts +35 -0
  215. package/dist/merchant-admin/pending-page.js +69 -0
  216. package/dist/merchant-admin/pending-page.js.map +1 -0
  217. package/dist/merchant-core/commands.d.ts +99 -0
  218. package/dist/merchant-core/commands.js +179 -0
  219. package/dist/merchant-core/commands.js.map +1 -0
  220. package/dist/merchant-core/executor.d.ts +69 -0
  221. package/dist/merchant-core/executor.js +218 -0
  222. package/dist/merchant-core/executor.js.map +1 -0
  223. package/dist/merchant-core/negotiation-adapters.d.ts +55 -0
  224. package/dist/merchant-core/negotiation-adapters.js +55 -0
  225. package/dist/merchant-core/negotiation-adapters.js.map +1 -0
  226. package/dist/merchant-core/network-checks.d.ts +65 -0
  227. package/dist/merchant-core/network-checks.js +111 -0
  228. package/dist/merchant-core/network-checks.js.map +1 -0
  229. package/dist/merchant-core/operations.d.ts +64 -0
  230. package/dist/merchant-core/operations.js +136 -0
  231. package/dist/merchant-core/operations.js.map +1 -0
  232. package/dist/merchant-core/policy-runtime.d.ts +70 -0
  233. package/dist/merchant-core/policy-runtime.js +181 -0
  234. package/dist/merchant-core/policy-runtime.js.map +1 -0
  235. package/dist/merchant-core/product-import.d.ts +67 -0
  236. package/dist/merchant-core/product-import.js +160 -0
  237. package/dist/merchant-core/product-import.js.map +1 -0
  238. package/dist/merchant-core/service.d.ts +203 -0
  239. package/dist/merchant-core/service.js +402 -0
  240. package/dist/merchant-core/service.js.map +1 -0
  241. package/dist/merchant-gateway/catalog-publications.d.ts +71 -0
  242. package/dist/merchant-gateway/catalog-publications.js +175 -0
  243. package/dist/merchant-gateway/catalog-publications.js.map +1 -0
  244. package/dist/merchant-gateway/catalog-tools.d.ts +46 -0
  245. package/dist/merchant-gateway/catalog-tools.js +277 -0
  246. package/dist/merchant-gateway/catalog-tools.js.map +1 -0
  247. package/dist/merchant-gateway/cli.d.ts +75 -0
  248. package/dist/merchant-gateway/cli.js +458 -0
  249. package/dist/merchant-gateway/cli.js.map +1 -0
  250. package/dist/merchant-gateway/credential-vault.d.ts +44 -0
  251. package/dist/merchant-gateway/credential-vault.js +111 -0
  252. package/dist/merchant-gateway/credential-vault.js.map +1 -0
  253. package/dist/merchant-gateway/entry-server.d.ts +117 -0
  254. package/dist/merchant-gateway/entry-server.js +710 -0
  255. package/dist/merchant-gateway/entry-server.js.map +1 -0
  256. package/dist/merchant-gateway/instance-registration.d.ts +143 -0
  257. package/dist/merchant-gateway/instance-registration.js +382 -0
  258. package/dist/merchant-gateway/instance-registration.js.map +1 -0
  259. package/dist/merchant-gateway/instance-tools.d.ts +58 -0
  260. package/dist/merchant-gateway/instance-tools.js +184 -0
  261. package/dist/merchant-gateway/instance-tools.js.map +1 -0
  262. package/dist/merchant-gateway/mcp-proxy.d.ts +25 -0
  263. package/dist/merchant-gateway/mcp-proxy.js +192 -0
  264. package/dist/merchant-gateway/mcp-proxy.js.map +1 -0
  265. package/dist/merchant-gateway/pinned-fetch.d.ts +52 -0
  266. package/dist/merchant-gateway/pinned-fetch.js +212 -0
  267. package/dist/merchant-gateway/pinned-fetch.js.map +1 -0
  268. package/dist/merchant-gateway/tenant-registry.d.ts +82 -0
  269. package/dist/merchant-gateway/tenant-registry.js +190 -0
  270. package/dist/merchant-gateway/tenant-registry.js.map +1 -0
  271. package/dist/merchant-gateway/tool-bundle.d.ts +26 -0
  272. package/dist/merchant-gateway/tool-bundle.js +56 -0
  273. package/dist/merchant-gateway/tool-bundle.js.map +1 -0
  274. package/dist/merchant-runtime/backup.d.ts +48 -0
  275. package/dist/merchant-runtime/backup.js +226 -0
  276. package/dist/merchant-runtime/backup.js.map +1 -0
  277. package/dist/merchant-runtime/health.d.ts +99 -0
  278. package/dist/merchant-runtime/health.js +206 -0
  279. package/dist/merchant-runtime/health.js.map +1 -0
  280. package/dist/merchant-runtime/jobs.d.ts +64 -0
  281. package/dist/merchant-runtime/jobs.js +107 -0
  282. package/dist/merchant-runtime/jobs.js.map +1 -0
  283. package/dist/merchant-runtime/manager.d.ts +94 -0
  284. package/dist/merchant-runtime/manager.js +305 -0
  285. package/dist/merchant-runtime/manager.js.map +1 -0
  286. package/dist/merchant-runtime/services.d.ts +30 -0
  287. package/dist/merchant-runtime/services.js +51 -0
  288. package/dist/merchant-runtime/services.js.map +1 -0
  289. package/dist/negotiation/action-candidate.js +1 -1
  290. package/dist/net/url.d.ts +26 -0
  291. package/dist/net/url.js +32 -0
  292. package/dist/net/url.js.map +1 -0
  293. package/dist/operator/types.d.ts +1 -1
  294. package/dist/product-cli.d.ts +2 -2
  295. package/dist/product-cli.js +27 -6
  296. package/dist/product-cli.js.map +1 -1
  297. package/dist/product-compat.d.ts +9 -1
  298. package/dist/product-compat.js +12 -1
  299. package/dist/product-compat.js.map +1 -1
  300. package/dist/product-init.js +17 -5
  301. package/dist/product-init.js.map +1 -1
  302. package/dist/product-publish.js +2 -1
  303. package/dist/product-publish.js.map +1 -1
  304. package/dist/product-supplier.d.ts +73 -0
  305. package/dist/product-supplier.js +224 -5
  306. package/dist/product-supplier.js.map +1 -1
  307. package/dist/runtime/fake-model.d.ts +1 -1
  308. package/dist/trust/identity/jwk.d.ts +11 -0
  309. package/dist/trust/identity/jwk.js +2 -0
  310. package/dist/trust/identity/jwk.js.map +1 -0
  311. package/dist/trust/identity/jws.d.ts +2 -1
  312. package/dist/trust/identity/jws.js.map +1 -1
  313. package/dist/trust/identity/keys.d.ts +2 -1
  314. package/dist/trust/identity/keys.js.map +1 -1
  315. package/dist/trust/identity/message-signature.d.ts +1 -14
  316. package/dist/trust/identity/message-signature.js.map +1 -1
  317. package/dist/weixin/channel.d.ts +3 -0
  318. package/dist/weixin/channel.js +18 -2
  319. package/dist/weixin/channel.js.map +1 -1
  320. package/examples/profiles/merchant.deepseek.yaml +6 -0
  321. package/examples/profiles/merchant.fake.yaml +6 -0
  322. package/examples/profiles/merchant.local.yaml +6 -0
  323. package/package.json +9 -7
  324. package/skills/kiwi-buyer/SKILL.md +68 -0
  325. package/skills/merchant/catalog-operations/SKILL.md +17 -0
  326. package/skills/merchant/change-approval/SKILL.md +16 -0
  327. package/skills/merchant/human-review/SKILL.md +17 -0
  328. package/skills/merchant/inventory-operations/SKILL.md +17 -0
  329. package/skills/merchant/negotiation-review/SKILL.md +18 -0
  330. package/skills/merchant/performance-insights/SKILL.md +19 -0
  331. package/contracts/candidate-agent-dto-1.0.README.md +0 -43
  332. package/contracts/conformance/python-service/README.md +0 -19
@@ -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 registerPending = (id, hooks) => {
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
- * (docs/operator-tui-v0.2.md §8).
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
- ...(budget.max_requests !== undefined ? { max_requests: budget.max_requests } : {}),
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
- this.briefingSetter(renderMemoryBriefing(memories));
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
  }