@trusty-squire/mcp 1.1.13-rc.8 → 1.1.13

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 (162) hide show
  1. package/README.md +139 -62
  2. package/assets/login/vnc-input.js +9 -0
  3. package/assets/login/vnc.html +214 -202
  4. package/assets/screencaps/connect-walkthrough.png +0 -0
  5. package/assets/screencaps/connect-walkthrough.svg +1 -1
  6. package/dist/api-client.d.ts +26 -3
  7. package/dist/api-client.d.ts.map +1 -1
  8. package/dist/api-client.js +19 -31
  9. package/dist/api-client.js.map +1 -1
  10. package/dist/bin.js +2 -3
  11. package/dist/bin.js.map +1 -1
  12. package/dist/bot/browser.d.ts +134 -77
  13. package/dist/bot/browser.d.ts.map +1 -1
  14. package/dist/bot/browser.js +1788 -1543
  15. package/dist/bot/browser.js.map +1 -1
  16. package/dist/bot/compact-observation-v2.d.ts +167 -0
  17. package/dist/bot/compact-observation-v2.d.ts.map +1 -0
  18. package/dist/bot/compact-observation-v2.js +1038 -0
  19. package/dist/bot/compact-observation-v2.js.map +1 -0
  20. package/dist/bot/credential-shape.d.ts +2 -0
  21. package/dist/bot/credential-shape.d.ts.map +1 -1
  22. package/dist/bot/credential-shape.js +21 -8
  23. package/dist/bot/credential-shape.js.map +1 -1
  24. package/dist/bot/element-fingerprint.d.ts +9 -0
  25. package/dist/bot/element-fingerprint.d.ts.map +1 -0
  26. package/dist/bot/element-fingerprint.js +147 -0
  27. package/dist/bot/element-fingerprint.js.map +1 -0
  28. package/dist/bot/email-verification.d.ts +7 -1
  29. package/dist/bot/email-verification.d.ts.map +1 -1
  30. package/dist/bot/email-verification.js +48 -14
  31. package/dist/bot/email-verification.js.map +1 -1
  32. package/dist/bot/google-login.d.ts +28 -52
  33. package/dist/bot/google-login.d.ts.map +1 -1
  34. package/dist/bot/google-login.js +246 -1119
  35. package/dist/bot/google-login.js.map +1 -1
  36. package/dist/bot/install-completion.d.ts +1 -2
  37. package/dist/bot/install-completion.d.ts.map +1 -1
  38. package/dist/bot/install-completion.js +1 -2
  39. package/dist/bot/install-completion.js.map +1 -1
  40. package/dist/bot/login-state.d.ts +13 -7
  41. package/dist/bot/login-state.d.ts.map +1 -1
  42. package/dist/bot/login-state.js +50 -114
  43. package/dist/bot/login-state.js.map +1 -1
  44. package/dist/bot/oauth-providers.d.ts +1 -1
  45. package/dist/bot/oauth-providers.d.ts.map +1 -1
  46. package/dist/bot/oauth-providers.js +3 -3
  47. package/dist/bot/oauth-providers.js.map +1 -1
  48. package/dist/bot/oauth-scope.d.ts +4 -0
  49. package/dist/bot/oauth-scope.d.ts.map +1 -0
  50. package/dist/bot/oauth-scope.js +58 -0
  51. package/dist/bot/oauth-scope.js.map +1 -0
  52. package/dist/bot/operator-browser-watchdog.d.ts +127 -0
  53. package/dist/bot/operator-browser-watchdog.d.ts.map +1 -0
  54. package/dist/bot/operator-browser-watchdog.js +438 -0
  55. package/dist/bot/operator-browser-watchdog.js.map +1 -0
  56. package/dist/bot/owner-process-reaper-worker.d.ts +2 -0
  57. package/dist/bot/owner-process-reaper-worker.d.ts.map +1 -0
  58. package/dist/bot/owner-process-reaper-worker.js +17 -0
  59. package/dist/bot/owner-process-reaper-worker.js.map +1 -0
  60. package/dist/bot/owner-process-reaper.d.ts +103 -0
  61. package/dist/bot/owner-process-reaper.d.ts.map +1 -0
  62. package/dist/bot/owner-process-reaper.js +1058 -0
  63. package/dist/bot/owner-process-reaper.js.map +1 -0
  64. package/dist/bot/pay-operator.d.ts +13 -2
  65. package/dist/bot/pay-operator.d.ts.map +1 -1
  66. package/dist/bot/pay-operator.js +319 -123
  67. package/dist/bot/pay-operator.js.map +1 -1
  68. package/dist/bot/profile.d.ts +10 -1
  69. package/dist/bot/profile.d.ts.map +1 -1
  70. package/dist/bot/profile.js +137 -11
  71. package/dist/bot/profile.js.map +1 -1
  72. package/dist/bot/promote-to-skill.js +1 -1
  73. package/dist/bot/promote-to-skill.js.map +1 -1
  74. package/dist/bot/provision-session.d.ts +60 -164
  75. package/dist/bot/provision-session.d.ts.map +1 -1
  76. package/dist/bot/provision-session.js +2049 -1546
  77. package/dist/bot/provision-session.js.map +1 -1
  78. package/dist/bot/remote-login-display.d.ts +61 -0
  79. package/dist/bot/remote-login-display.d.ts.map +1 -0
  80. package/dist/bot/remote-login-display.js +765 -0
  81. package/dist/bot/remote-login-display.js.map +1 -0
  82. package/dist/bot/session/hosts.d.ts +8 -0
  83. package/dist/bot/session/hosts.d.ts.map +1 -0
  84. package/dist/bot/session/hosts.js +36 -0
  85. package/dist/bot/session/hosts.js.map +1 -0
  86. package/dist/bot/session/lifecycle.d.ts +56 -0
  87. package/dist/bot/session/lifecycle.d.ts.map +1 -0
  88. package/dist/bot/session/lifecycle.js +962 -0
  89. package/dist/bot/session/lifecycle.js.map +1 -0
  90. package/dist/bot/session/model.d.ts +175 -0
  91. package/dist/bot/session/model.d.ts.map +1 -0
  92. package/dist/bot/session/model.js +77 -0
  93. package/dist/bot/session/model.js.map +1 -0
  94. package/dist/install/cli.d.ts +29 -9
  95. package/dist/install/cli.d.ts.map +1 -1
  96. package/dist/install/cli.js +243 -322
  97. package/dist/install/cli.js.map +1 -1
  98. package/dist/install/interactive.d.ts +1 -0
  99. package/dist/install/interactive.d.ts.map +1 -1
  100. package/dist/install/interactive.js +19 -5
  101. package/dist/install/interactive.js.map +1 -1
  102. package/dist/install/ui.d.ts.map +1 -1
  103. package/dist/install/ui.js +3 -15
  104. package/dist/install/ui.js.map +1 -1
  105. package/dist/operator-env.js +1 -1
  106. package/dist/operator-env.js.map +1 -1
  107. package/dist/server-instance-registry.d.ts +103 -0
  108. package/dist/server-instance-registry.d.ts.map +1 -0
  109. package/dist/server-instance-registry.js +392 -0
  110. package/dist/server-instance-registry.js.map +1 -0
  111. package/dist/server.d.ts +15 -1
  112. package/dist/server.d.ts.map +1 -1
  113. package/dist/server.js +164 -62
  114. package/dist/server.js.map +1 -1
  115. package/dist/session-guard.d.ts +28 -0
  116. package/dist/session-guard.d.ts.map +1 -0
  117. package/dist/session-guard.js +84 -0
  118. package/dist/session-guard.js.map +1 -0
  119. package/dist/session.d.ts +57 -13
  120. package/dist/session.d.ts.map +1 -1
  121. package/dist/session.js +246 -127
  122. package/dist/session.js.map +1 -1
  123. package/dist/tools/audit-log.d.ts +16 -2
  124. package/dist/tools/audit-log.d.ts.map +1 -1
  125. package/dist/tools/audit-log.js +223 -13
  126. package/dist/tools/audit-log.js.map +1 -1
  127. package/dist/tools/audit-rollup.d.ts +80 -0
  128. package/dist/tools/audit-rollup.d.ts.map +1 -0
  129. package/dist/tools/audit-rollup.js +0 -0
  130. package/dist/tools/audit-rollup.js.map +1 -0
  131. package/dist/tools/fetch-credential.d.ts +37 -0
  132. package/dist/tools/fetch-credential.d.ts.map +1 -0
  133. package/dist/tools/fetch-credential.js +153 -0
  134. package/dist/tools/fetch-credential.js.map +1 -0
  135. package/dist/tools/index.d.ts +3 -1
  136. package/dist/tools/index.d.ts.map +1 -1
  137. package/dist/tools/index.js +7 -3
  138. package/dist/tools/index.js.map +1 -1
  139. package/dist/tools/operate-pay.d.ts +4 -4
  140. package/dist/tools/operate-pay.d.ts.map +1 -1
  141. package/dist/tools/operate-pay.js +163 -96
  142. package/dist/tools/operate-pay.js.map +1 -1
  143. package/dist/tools/provision-drive.d.ts +43 -35
  144. package/dist/tools/provision-drive.d.ts.map +1 -1
  145. package/dist/tools/provision-drive.js +268 -164
  146. package/dist/tools/provision-drive.js.map +1 -1
  147. package/dist/tools/use-credential.d.ts.map +1 -1
  148. package/dist/tools/use-credential.js +3 -2
  149. package/dist/tools/use-credential.js.map +1 -1
  150. package/package.json +4 -6
  151. package/dist/bot/operator-direct-identity.d.ts +0 -26
  152. package/dist/bot/operator-direct-identity.d.ts.map +0 -1
  153. package/dist/bot/operator-direct-identity.js +0 -120
  154. package/dist/bot/operator-direct-identity.js.map +0 -1
  155. package/dist/bot/operator-profile-pool.d.ts +0 -97
  156. package/dist/bot/operator-profile-pool.d.ts.map +0 -1
  157. package/dist/bot/operator-profile-pool.js +0 -855
  158. package/dist/bot/operator-profile-pool.js.map +0 -1
  159. package/dist/bot/xvfb.d.ts +0 -13
  160. package/dist/bot/xvfb.d.ts.map +0 -1
  161. package/dist/bot/xvfb.js +0 -146
  162. package/dist/bot/xvfb.js.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/tools/index.ts"],"names":[],"mappings":"AAUA,OAAO,EAAE,CAAC,EAAE,KAAK,QAAQ,EAAE,KAAK,UAAU,EAAE,MAAM,KAAK,CAAC;AACxD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAClD,OAAO,EAAE,mBAAmB,EAAE,MAAM,uBAAuB,CAAC;AAC5D,OAAO,EAAE,uBAAuB,EAAE,qBAAqB,EAAE,MAAM,uBAAuB,CAAC;AACvF,OAAO,EAAE,mBAAmB,EAAE,MAAM,uBAAuB,CAAC;AAC5D,OAAO,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AACxD,OAAO,EAAE,kBAAkB,EAAE,MAAM,uBAAuB,CAAC;AAC3D,OAAO,EAAE,mBAAmB,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;AAChF,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAE9C,OAAO,EAAE,oBAAoB,EAAE,cAAc,EAAE,wBAAwB,EAAE,MAAM,kBAAkB,CAAC;AAClG,OAAO,EAAE,oBAAoB,EAAE,kBAAkB,EAAE,MAAM,2BAA2B,CAAC;AAErF,MAAM,WAAW,IAAI,CAAC,KAAK,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;IACnF,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,UAAU,CAAC;IACxB,eAAe,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAGzC,WAAW,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAItC,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAG/B,YAAY,CAAC,EAAE,CAAC,IAAI,EAAE,OAAO,EAAE,MAAM,EAAE,SAAS,QAAQ,EAAE,KAAK,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACvF,OAAO,EAAE,CAAC,IAAI,EAAE,KAAK,EAAE,GAAG,EAAE,SAAS,GAAG,IAAI,EAAE,OAAO,CAAC,EAAE,WAAW,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;CAC1F;AAED,MAAM,WAAW,WAAW;IAC1B,UAAU,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;CAChF;AAID,OAAO,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AAMpD,wBAAgB,SAAS,CAAC,GAAG,EAAE,SAAS,GAAG,IAAI,GAAG,OAAO,CAAC,GAAG,IAAI,SAAS,CAMzE;AAaD,wBAAgB,iBAAiB,CAAC,GAAG,GAAE,MAAM,CAAC,UAAwB,GAAG,IAAI,EAAE,CAwB9E;AAID,eAAO,MAAM,KAAK,EAAE,IAAI,EAA0B,CAAC;AAEnD,wBAAgB,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,GAAE,SAAS,IAAI,EAAU,GAAG,IAAI,GAAG,IAAI,CAElF;AAGD,OAAO,EAAE,CAAC,EAAE,CAAC;AAIb,OAAO,EACL,mBAAmB,EACnB,mBAAmB,EACnB,kBAAkB,EAClB,oBAAoB,EACpB,iBAAiB,EACjB,kBAAkB,EAClB,iBAAiB,EACjB,mBAAmB,EACnB,YAAY,EACZ,uBAAuB,EACvB,qBAAqB,EACrB,oBAAoB,EACpB,cAAc,EACd,wBAAwB,GACzB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/tools/index.ts"],"names":[],"mappings":"AAUA,OAAO,EAAE,CAAC,EAAE,KAAK,QAAQ,EAAE,KAAK,UAAU,EAAE,MAAM,KAAK,CAAC;AACxD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAClD,OAAO,EAAE,mBAAmB,EAAE,MAAM,uBAAuB,CAAC;AAC5D,OAAO,EAAE,uBAAuB,EAAE,qBAAqB,EAAE,MAAM,uBAAuB,CAAC;AACvF,OAAO,EAAE,mBAAmB,EAAE,MAAM,uBAAuB,CAAC;AAC5D,OAAO,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AACxD,OAAO,EAAE,kBAAkB,EAAE,MAAM,uBAAuB,CAAC;AAC3D,OAAO,EAAE,mBAAmB,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;AAChF,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAE9C,OAAO,EAAE,oBAAoB,EAAE,cAAc,EAAE,wBAAwB,EAAE,MAAM,kBAAkB,CAAC;AAClG,OAAO,EAAE,oBAAoB,EAAE,kBAAkB,EAAE,MAAM,2BAA2B,CAAC;AACrF,OAAO,EAAE,mBAAmB,EAAE,MAAM,uBAAuB,CAAC;AAE5D,MAAM,WAAW,IAAI,CAAC,KAAK,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;IACnF,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,UAAU,CAAC;IACxB,eAAe,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAGzC,WAAW,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAItC,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAG/B,YAAY,CAAC,EAAE,CAAC,IAAI,EAAE,OAAO,EAAE,MAAM,EAAE,SAAS,QAAQ,EAAE,KAAK,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACvF,OAAO,EAAE,CAAC,IAAI,EAAE,KAAK,EAAE,GAAG,EAAE,SAAS,GAAG,IAAI,EAAE,OAAO,CAAC,EAAE,WAAW,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;CAC1F;AAED,MAAM,WAAW,WAAW;IAC1B,UAAU,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAG/E,qBAAqB,CAAC,EAAE,MAAM,CAAC;CAChC;AAID,OAAO,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AAMpD,wBAAgB,SAAS,CAAC,GAAG,EAAE,SAAS,GAAG,IAAI,GAAG,OAAO,CAAC,GAAG,IAAI,SAAS,CAMzE;AAaD,wBAAgB,iBAAiB,CAAC,GAAG,GAAE,MAAM,CAAC,UAAwB,GAAG,IAAI,EAAE,CA2B9E;AAID,eAAO,MAAM,KAAK,EAAE,IAAI,EAA0B,CAAC;AAEnD,wBAAgB,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,GAAE,SAAS,IAAI,EAAU,GAAG,IAAI,GAAG,IAAI,CAElF;AAGD,OAAO,EAAE,CAAC,EAAE,CAAC;AAIb,OAAO,EACL,mBAAmB,EACnB,mBAAmB,EACnB,kBAAkB,EAClB,oBAAoB,EACpB,iBAAiB,EACjB,mBAAmB,EACnB,kBAAkB,EAClB,iBAAiB,EACjB,mBAAmB,EACnB,YAAY,EACZ,uBAAuB,EACvB,qBAAqB,EACrB,oBAAoB,EACpB,cAAc,EACd,wBAAwB,GACzB,CAAC"}
@@ -18,6 +18,7 @@ import { auditLogTool } from "./audit-log.js";
18
18
  import { OPERATE_TOOLS } from "./provision-drive.js";
19
19
  import { listPaymentCardsTool, operatePayTool, operatePaymentStatusTool } from "./operate-pay.js";
20
20
  import { deleteCredentialTool, editCredentialTool } from "./credential-mutations.js";
21
+ import { fetchCredentialTool } from "./fetch-credential.js";
21
22
  // Re-exported for convenience; defined in its own module to avoid a
22
23
  // circular import (tool files import it; index imports the tool files).
23
24
  export { ALWAYS_LOAD_META } from "./always-load.js";
@@ -47,6 +48,9 @@ export function buildToolRegistry(env = process.env) {
47
48
  editCredentialTool,
48
49
  deleteCredentialTool,
49
50
  useCredentialTool,
51
+ // The one approval-gated raw-value path. Listed AFTER use_credential so
52
+ // the cheaper, never-exposed route is the one the model reads first.
53
+ fetchCredentialTool,
50
54
  // Egress grants: a deployed app uses a vaulted credential via the proxy.
51
55
  grantAppAccessTool,
52
56
  listAppAccessTool,
@@ -56,8 +60,8 @@ export function buildToolRegistry(env = process.env) {
56
60
  ...(diagnosticsProfileEnabled(env) ? diagnosticsTools : []),
57
61
  listPaymentCardsTool,
58
62
  operatePayTool,
59
- // [P0] Non-blocking payment approval: read-only status + a bounded wait,
60
- // so a host never has to block an RPC on the human's phone tap.
63
+ // Non-charging bounded status for pre-charge approval and post-submit
64
+ // outcomes; operate_pay owns approval continuation and charge execution.
61
65
  operatePaymentStatusTool,
62
66
  // Interactive host-driven provisioning (operate_start/observe/act/finish
63
67
  // plus recipe save/run; workflow kinds are consolidated under operate_act).
@@ -74,5 +78,5 @@ export function findTool(name, tools = TOOLS) {
74
78
  export { z };
75
79
  // Per-tool re-exports so callers (tests, custom integrations) can
76
80
  // import a single tool without going through the TOOLS array.
77
- export { listCredentialsTool, storeCredentialTool, editCredentialTool, deleteCredentialTool, useCredentialTool, grantAppAccessTool, listAppAccessTool, revokeAppAccessTool, auditLogTool, listExtractFailuresTool, getExtractFailureTool, listPaymentCardsTool, operatePayTool, operatePaymentStatusTool, };
81
+ export { listCredentialsTool, storeCredentialTool, editCredentialTool, deleteCredentialTool, useCredentialTool, fetchCredentialTool, grantAppAccessTool, listAppAccessTool, revokeAppAccessTool, auditLogTool, listExtractFailuresTool, getExtractFailureTool, listPaymentCardsTool, operatePayTool, operatePaymentStatusTool, };
78
82
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/tools/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/tools/index.ts"],"names":[],"mappings":"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"}
@@ -18,7 +18,7 @@ declare const inputSchema: z.ZodEffects<z.ZodObject<{
18
18
  amount_cents?: number | undefined;
19
19
  merchant?: string | undefined;
20
20
  card_ref?: string | undefined;
21
- phase?: "single" | "fill_card" | "confirm" | undefined;
21
+ phase?: "single" | "confirm" | "fill_card" | undefined;
22
22
  three_ds_wait_seconds?: number | undefined;
23
23
  session_id?: string | undefined;
24
24
  card_label?: string | undefined;
@@ -29,7 +29,7 @@ declare const inputSchema: z.ZodEffects<z.ZodObject<{
29
29
  amount_cents?: number | undefined;
30
30
  merchant?: string | undefined;
31
31
  card_ref?: string | undefined;
32
- phase?: "single" | "fill_card" | "confirm" | undefined;
32
+ phase?: "single" | "confirm" | "fill_card" | undefined;
33
33
  three_ds_wait_seconds?: number | undefined;
34
34
  session_id?: string | undefined;
35
35
  card_label?: string | undefined;
@@ -40,7 +40,7 @@ declare const inputSchema: z.ZodEffects<z.ZodObject<{
40
40
  amount_cents?: number | undefined;
41
41
  merchant?: string | undefined;
42
42
  card_ref?: string | undefined;
43
- phase?: "single" | "fill_card" | "confirm" | undefined;
43
+ phase?: "single" | "confirm" | "fill_card" | undefined;
44
44
  three_ds_wait_seconds?: number | undefined;
45
45
  session_id?: string | undefined;
46
46
  card_label?: string | undefined;
@@ -51,7 +51,7 @@ declare const inputSchema: z.ZodEffects<z.ZodObject<{
51
51
  amount_cents?: number | undefined;
52
52
  merchant?: string | undefined;
53
53
  card_ref?: string | undefined;
54
- phase?: "single" | "fill_card" | "confirm" | undefined;
54
+ phase?: "single" | "confirm" | "fill_card" | undefined;
55
55
  three_ds_wait_seconds?: number | undefined;
56
56
  session_id?: string | undefined;
57
57
  card_label?: string | undefined;
@@ -1 +1 @@
1
- {"version":3,"file":"operate-pay.d.ts","sourceRoot":"","sources":["../../src/tools/operate-pay.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AA6BxB,OAAO,EAAa,KAAK,IAAI,EAAE,MAAM,YAAY,CAAC;AAElD,QAAA,MAAM,WAAW;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EA+Bb,CAAC;AAiDL,eAAO,MAAM,oBAAoB,EAAE,IAYlC,CAAC;AAEF,eAAO,MAAM,cAAc,EAAE,IAAI,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,WAAW,CAAC,CAwV5D,CAAC;AA+OF,QAAA,MAAM,wBAAwB;;;;;;;;;EAG5B,CAAC;AAEH,eAAO,MAAM,wBAAwB,EAAE,IAAI,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,wBAAwB,CAAC,CA2CnF,CAAC"}
1
+ {"version":3,"file":"operate-pay.d.ts","sourceRoot":"","sources":["../../src/tools/operate-pay.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAoCxB,OAAO,EAAa,KAAK,IAAI,EAAE,MAAM,YAAY,CAAC;AASlD,QAAA,MAAM,WAAW;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EA+Bb,CAAC;AAiDL,eAAO,MAAM,oBAAoB,EAAE,IAYlC,CAAC;AAEF,eAAO,MAAM,cAAc,EAAE,IAAI,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,WAAW,CAAC,CAqX5D,CAAC;AAsSF,QAAA,MAAM,wBAAwB;;;;;;;;;EAG5B,CAAC;AAEH,eAAO,MAAM,wBAAwB,EAAE,IAAI,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,wBAAwB,CAAC,CAiCnF,CAAC"}
@@ -1,7 +1,14 @@
1
1
  import { z } from "zod";
2
- import { activeCartCheckoutForOrigin, activeProvisionBrowserForPayment, claimActivePaymentForOperatePay, clearActivePendingCardFill, clearActivePendingThreeDsIfCurrent, completeActivePaymentLeaseWithPendingApproval, completeActivePaymentLeaseWithPendingFill, getActivePendingApproval, getActivePendingThreeDs, recordActivePaymentProvenance, releaseActivePaymentLease, retainActivePaymentFieldSeal, restoreActivePendingCardFillAfterConfirmThrow, setActivePendingThreeDs, withPaymentSessionCall, } from "../bot/provision-session.js";
2
+ import { armPaymentDispatchHandoff, activeCartCheckoutForOrigin, activeProvisionBrowserForPayment, claimActivePaymentForOperatePay, clearActivePendingCardFill, clearActivePendingThreeDsIfCurrent, completeActivePendingApprovalWithTerminalStatus, completeActivePaymentLeaseWithPendingApproval, completeActivePaymentLeaseWithPendingFill, completeActivePaymentLeaseWithTerminalApproval, coordinatePaymentDispatchAudit, finishPaymentDispatchHandoff, getActivePendingApproval, getActivePendingThreeDs, getTerminalPaymentApproval, recordActivePaymentProvenance, releaseActivePaymentLease, retainActivePaymentFieldSeal, restoreActivePendingCardFillAfterConfirmThrow, setActivePendingThreeDs, withPaymentSessionCall, } from "../bot/provision-session.js";
3
3
  import { classifyApprovalCandidate, executeOperatePay, executeOperatePayConfirm, } from "../bot/pay-operator.js";
4
+ import { isPaymentApprovalTransportTimeout } from "../api-client.js";
4
5
  import { assertApi } from "./index.js";
6
+ // Long enough for a ready human to approve without making the MCP request as
7
+ // long-lived as the approval itself (five minutes for saved-card ceremonies,
8
+ // longer for JIT). If this bound expires, session state retains the same
9
+ // approval and the next operate_pay call continues waiting on it.
10
+ const OPERATE_PAY_APPROVAL_WAIT_MS = 60_000;
11
+ const PAYMENT_APPROVAL_RESPONSE_RESERVE_MS = 500;
5
12
  const inputSchema = z
6
13
  .object({
7
14
  session_id: z.string().uuid().optional(),
@@ -78,38 +85,18 @@ export const listPaymentCardsTool = {
78
85
  };
79
86
  export const operatePayTool = {
80
87
  name: "operate_pay",
81
- description: "Pay the checkout in the addressed operate_start browser session. session_id is required " +
82
- "when multiple operator sessions are active (and optional only for a sole local session). " +
83
- 'phase="single" (the default, also implied by omitting phase) is an ordinary one-step checkout. ' +
84
- "Reads the live merchant and checkout total independently of informational checkout_state. " +
85
- "When the live total cannot be machine-read, caller-supplied amount_cents and currency become " +
86
- "the authoritative approval amount and take precedence over a prior cart observation. " +
87
- "creates a phone approval link, waits for approval, " +
88
- "verifies the passkey-signed purchase mandate, opens the card only in this process, " +
89
- "fills common checkout fields, submits, and audits only the last four digits. Never " +
90
- "solves 3-D Secure; waits for user completion, then returns a needs_user handoff if unresolved " +
91
- "— including a decoupled/out-of-band app-push challenge that had not resolved yet, in which " +
92
- "case call operate_payment_status (not operate_pay again) to keep checking the same already-" +
93
- "submitted charge. If the issuer/app challenge shows issuer, network, or last-four evidence " +
94
- "for a different card, returns a structured payment_instrument_mismatch warning without " +
95
- "altering or cancelling the challenge; the cardholder retains the decision. " +
96
- "With no card_ref/card_label and no card on file, the approval link becomes a first-time " +
97
- "add-card ceremony and the card is bound server-side before the mandate is signed. " +
98
- "On approval resume, an unreadable live checkout reuses the original mandate-bound checkout; " +
99
- "a successfully-read checkout with a different amount, currency, merchant, or origin returns " +
100
- "payment_amount_mismatch without filling the card. " +
101
- "For a SPLIT checkout (a card-entry step with no visible total, e.g. Rakuten): call with " +
102
- 'phase="fill_card" on that step — the approval amount is sourced from the most recent real ' +
103
- "total this session observed (e.g. the cart page) only when the card-entry page itself shows " +
104
- "none and amount_cents plus currency were not supplied, and releases the card into recognized " +
105
- "payment-provider fields without charging. Then drive the checkout to the order-confirmation " +
106
- "step, VERIFY the live final total there matches the returned approved amount_cents and " +
107
- "currency, and place the order yourself via operate_act, handling any 3-D Secure challenge " +
108
- "directly — Trusty Squire never re-reads the total or clicks the pay/place-order control. Call " +
109
- 'phase="confirm" any time after the fill to close out the approval; it is not a prerequisite ' +
110
- "to placing the order. Exactly one human approval per purchase. If the payment gets stuck or " +
111
- "the card is declined, recover with operate_finish and start a fresh session — operate_pay " +
112
- "does not support refilling a different card mid-session.",
88
+ description: "Pay the live checkout in an operate_start session (session_id is required when more than one " +
89
+ "session exists). The default single phase reads the merchant and total, surfaces one phone " +
90
+ "approval, and waits server-side for up to one minute; re-calling after a pending result resumes " +
91
+ "that same approval. It verifies the signed mandate, opens the card only in this process, " +
92
+ "rechecks approval immediately before the charge click, and reports submitted, 3-D Secure, or " +
93
+ "unknown outcomes truthfully. Use operate_payment_status for an unresolved submitted charge. " +
94
+ "Without a stored card, the approval link performs first-time card binding. A resumed approval " +
95
+ "keeps its original terms and fails closed if a readable live checkout differs. For split " +
96
+ 'checkouts, phase="fill_card" fills recognized provider fields without charging; verify the ' +
97
+ 'final total and place the order with operate_act, then phase="confirm" closes the approval. ' +
98
+ "Exactly one human approval is valid per purchase attempt; finish the session before retrying " +
99
+ "a stuck, denied, expired, or ambiguous attempt.",
113
100
  inputSchema,
114
101
  jsonInputSchema: {
115
102
  type: "object",
@@ -161,6 +148,24 @@ export const operatePayTool = {
161
148
  const phase = args.phase === "single" ? undefined : args.phase;
162
149
  return await withPaymentSessionCall(args.session_id, async (session) => {
163
150
  const paymentClaim = claimActivePaymentForOperatePay(phase, session);
151
+ if (paymentClaim.kind === "terminal") {
152
+ const state = paymentClaim.state;
153
+ return paymentResult(session, {
154
+ status: paymentClaim.terminalStatus === "denied"
155
+ ? "payment_approval_denied"
156
+ : paymentClaim.terminalStatus === "expired"
157
+ ? "payment_approval_timeout"
158
+ : "payment_confirmation_failed",
159
+ approval_id: state.approval_id,
160
+ approval_url: state.approval_url,
161
+ merchant: state.checkout.merchant,
162
+ amount_cents: state.checkout.amount_cents,
163
+ currency: state.checkout.currency,
164
+ ...(paymentClaim.terminalStatus === "expired" && state.jit && state.boundCardRef !== null
165
+ ? { card_persisted: true }
166
+ : {}),
167
+ });
168
+ }
164
169
  // Confirm step of a split checkout: the card is already filled (and the
165
170
  // mandate already signed), so no card resolution and no PayPal gate.
166
171
  // confirm no longer touches the browser or charges anything — it only
@@ -197,6 +202,7 @@ export const operatePayTool = {
197
202
  let paymentLeaseCompleted = false;
198
203
  let paymentFieldsCleared = true;
199
204
  let approvalPending = null;
205
+ let paymentDispatchHandoff = null;
200
206
  let operatorStarted = false;
201
207
  try {
202
208
  const browser = await activeProvisionBrowserForPayment(session);
@@ -324,18 +330,37 @@ export const operatePayTool = {
324
330
  onApprovalPending: (state) => {
325
331
  approvalPending = state;
326
332
  },
333
+ onApprovalTerminal: (state, terminalStatus) => {
334
+ completeActivePaymentLeaseWithTerminalApproval(paymentLease, state, terminalStatus, session);
335
+ paymentLeaseCompleted = true;
336
+ },
337
+ onThreeDsHandoffArmed: (state) => {
338
+ paymentDispatchHandoff = state;
339
+ armPaymentDispatchHandoff(state, session);
340
+ },
341
+ coordinateThreeDsAudit: async (state, recordAudit) => await coordinatePaymentDispatchAudit(state, recordAudit, session),
327
342
  onThreeDsPending: (state) => {
328
343
  setActivePendingThreeDs(state, session);
329
344
  },
345
+ onThreeDsCleared: (state) => {
346
+ clearActivePendingThreeDsIfCurrent(state, session);
347
+ },
330
348
  ...(cartFallbackCheckout !== undefined ? { cartFallbackCheckout } : {}),
331
349
  ...(paymentClaim.resumeApproval !== undefined
332
350
  ? { resumeFrom: paymentClaim.resumeApproval }
333
351
  : {}),
334
- // [P0] Never block the RPC waiting on the human — one live check,
335
- // then hand back approval_pending. operate_payment_status (or
336
- // simply calling operate_pay again, which resumes this SAME
337
- // approval) is how the host finds out when the phone responds.
338
- pollBudgetMs: 0,
352
+ // Approval detection belongs here, not in an agent polling loop.
353
+ // The URL is surfaced before executeOperatePay enters this bounded
354
+ // wait. On exhaustion, onApprovalPending persists the SAME approval
355
+ // so a later operate_pay call continues without another passkey gate.
356
+ // A client without progress notifications must receive the newly
357
+ // minted URL before it can ask a human to act. Its first call may
358
+ // therefore return immediately; the resumed call already has the
359
+ // URL and uses the normal system-owned wait.
360
+ pollBudgetMs: context?.paymentApprovalWaitMs ??
361
+ (context?.notifyUser !== undefined || paymentClaim.resumeApproval !== undefined
362
+ ? OPERATE_PAY_APPROVAL_WAIT_MS
363
+ : 0),
339
364
  });
340
365
  if (result.payment_fields_cleared === false)
341
366
  paymentFieldsCleared = false;
@@ -383,6 +408,9 @@ export const operatePayTool = {
383
408
  throw error;
384
409
  }
385
410
  finally {
411
+ if (paymentDispatchHandoff !== null) {
412
+ finishPaymentDispatchHandoff(paymentDispatchHandoff, session);
413
+ }
386
414
  if (!paymentLeaseCompleted) {
387
415
  releaseActivePaymentLease(paymentLease, paymentFieldsCleared, session);
388
416
  }
@@ -393,17 +421,20 @@ export const operatePayTool = {
393
421
  // [P0] Used by operate_payment_status: maps the LIVE server record
394
422
  // (never the locally-cached approval terms) to a status the host can act on.
395
423
  // Never opens the sealed card or calls confirm — read-only, no side effects.
396
- // `boundMs`, when given, races the server call so this can never outlast the
397
- // caller's own bound even though the server's wait_for_submission window is
398
- // a fixed ~15s.
399
- async function readApprovalStatus(api, state, sessionId, waitForSubmission, boundMs) {
400
- const fetchApproval = api.getPaymentApproval(state.approval_id, waitForSubmission ? "wait-peek" : "peek");
401
- const approval = boundMs === undefined
402
- ? await fetchApproval
403
- : await Promise.race([
404
- fetchApproval,
405
- new Promise((resolve) => setTimeout(() => resolve(null), boundMs)),
406
- ]);
424
+ // `serverWaitMs`, when given, uses one server wait plus one transport grace.
425
+ async function readApprovalStatus(api, state, sessionId, waitForSubmission, serverWaitMs) {
426
+ const fetchApproval = waitForSubmission
427
+ ? api
428
+ .getPaymentApproval(state.approval_id, "wait-peek", serverWaitMs, serverWaitMs === undefined
429
+ ? undefined
430
+ : serverWaitMs + PAYMENT_APPROVAL_RESPONSE_RESERVE_MS)
431
+ .catch((error) => {
432
+ if (isPaymentApprovalTransportTimeout(error))
433
+ return null;
434
+ throw error;
435
+ })
436
+ : api.getPaymentApproval(state.approval_id, "peek");
437
+ const approval = await fetchApproval;
407
438
  if (approval === null) {
408
439
  return {
409
440
  status: "pending",
@@ -416,7 +447,13 @@ async function readApprovalStatus(api, state, sessionId, waitForSubmission, boun
416
447
  candidate_submitted: false,
417
448
  candidate_kind: state.reviewVerified === true ? "review" : "none",
418
449
  ready_to_charge: false,
419
- next: { tool: "operate_payment_status", session_id: sessionId, wait_seconds: 15 },
450
+ next: {
451
+ tool: "operate_pay",
452
+ session_id: sessionId,
453
+ hint: "The bounded status wait ended before the human responded. Call operate_pay again " +
454
+ "with the same arguments; it resumes this approval, waits server-side, and proceeds " +
455
+ "to charge after approval.",
456
+ },
420
457
  };
421
458
  }
422
459
  const candidateSubmitted = typeof approval.jws === "string" && typeof approval.sealed_card === "string";
@@ -426,6 +463,7 @@ async function readApprovalStatus(api, state, sessionId, waitForSubmission, boun
426
463
  : observedCandidateKind;
427
464
  const readyToCharge = observedCandidateKind === "approval";
428
465
  const expired = approval.status === "expired";
466
+ const terminalWithoutCharge = expired || approval.status === "denied";
429
467
  return {
430
468
  status: expired ? "expired" : approval.status,
431
469
  approval_id: state.approval_id,
@@ -438,7 +476,7 @@ async function readApprovalStatus(api, state, sessionId, waitForSubmission, boun
438
476
  candidate_submitted: candidateSubmitted,
439
477
  candidate_kind: candidateKind,
440
478
  ready_to_charge: readyToCharge,
441
- ...(expired
479
+ ...(terminalWithoutCharge
442
480
  ? {}
443
481
  : readyToCharge
444
482
  ? {
@@ -464,11 +502,11 @@ async function readApprovalStatus(api, state, sessionId, waitForSubmission, boun
464
502
  : candidateKind === "review"
465
503
  ? {
466
504
  next: {
467
- tool: "operate_payment_status",
505
+ tool: "operate_pay",
468
506
  session_id: sessionId,
469
- wait_seconds: 15,
470
507
  hint: "The review signature was verified. Final payment approval is still required; " +
471
- "refresh the approval page if the final prompt is not visible.",
508
+ "refresh the approval page if the final prompt is not visible, then call " +
509
+ "operate_pay once to wait and continue this same approval.",
472
510
  },
473
511
  }
474
512
  : candidateKind === "invalid"
@@ -481,9 +519,10 @@ async function readApprovalStatus(api, state, sessionId, waitForSubmission, boun
481
519
  }
482
520
  : {
483
521
  next: {
484
- tool: "operate_payment_status",
522
+ tool: "operate_pay",
485
523
  session_id: sessionId,
486
- wait_seconds: 15,
524
+ hint: "Call operate_pay again with the same arguments. It resumes this approval " +
525
+ "and waits server-side instead of requiring an agent polling loop.",
487
526
  },
488
527
  }),
489
528
  };
@@ -507,6 +546,8 @@ async function threeDsStatusResult(api, session, state, waitSeconds) {
507
546
  const expiredAtEntry = Date.now() >= state.deadline;
508
547
  const boundMs = expiredAtEntry || waitSeconds <= 0 ? 0 : Math.min(Math.max(waitSeconds * 1000, 1_000), 15_000);
509
548
  const resolution = await browser.waitForThreeDsResolution(boundMs);
549
+ if (resolution === "challenge_pending")
550
+ state.outcome = "three_ds";
510
551
  const mismatch = browser.paymentInstrumentMismatch?.();
511
552
  if (mismatch !== undefined)
512
553
  state.payment_instrument_mismatch ??= mismatch;
@@ -514,7 +555,7 @@ async function threeDsStatusResult(api, session, state, waitSeconds) {
514
555
  const unresolvedPastDeadline = terminalStatus === null && (expiredAtEntry || Date.now() >= state.deadline);
515
556
  if (terminalStatus === null && !unresolvedPastDeadline) {
516
557
  return {
517
- status: "payment_3ds_pending",
558
+ status: state.outcome === "three_ds" ? "payment_3ds_pending" : "payment_outcome_unknown",
518
559
  approval_url: state.approval_url,
519
560
  merchant: state.checkout.merchant,
520
561
  amount_cents: state.checkout.amount_cents,
@@ -525,16 +566,24 @@ async function threeDsStatusResult(api, session, state, waitSeconds) {
525
566
  next: { tool: "operate_payment_status", session_id: session.id, wait_seconds: 15 },
526
567
  };
527
568
  }
528
- const finalStatus = terminalStatus ?? "payment_3ds_unresolved";
569
+ const finalStatus = terminalStatus ??
570
+ (state.outcome === "three_ds" ? "payment_3ds_unresolved" : "payment_outcome_unknown");
529
571
  let auditRecorded = true;
530
572
  if (terminalStatus === null) {
531
- await api.auditPayment({
532
- ...state.checkout,
533
- last4: state.last4,
534
- status: finalStatus,
535
- approval_id: state.approval_id,
536
- ...(state.mandate_id !== undefined ? { mandate_id: state.mandate_id } : {}),
537
- });
573
+ try {
574
+ await api.auditPayment({
575
+ ...state.checkout,
576
+ last4: state.last4,
577
+ status: finalStatus,
578
+ approval_id: state.approval_id,
579
+ ...(state.mandate_id !== undefined ? { mandate_id: state.mandate_id } : {}),
580
+ });
581
+ }
582
+ catch (error) {
583
+ if (state.outcome === "three_ds")
584
+ throw error;
585
+ auditRecorded = false;
586
+ }
538
587
  }
539
588
  else {
540
589
  try {
@@ -550,7 +599,10 @@ async function threeDsStatusResult(api, session, state, waitSeconds) {
550
599
  auditRecorded = false;
551
600
  }
552
601
  }
553
- clearActivePendingThreeDsIfCurrent(state, session);
602
+ const merchantReconciliationRequired = terminalStatus === null && state.outcome === "unknown";
603
+ if (!merchantReconciliationRequired) {
604
+ clearActivePendingThreeDsIfCurrent(state, session);
605
+ }
554
606
  return {
555
607
  status: finalStatus,
556
608
  audit_recorded: auditRecorded,
@@ -564,29 +616,54 @@ async function threeDsStatusResult(api, session, state, waitSeconds) {
564
616
  ...(terminalStatus === null
565
617
  ? {
566
618
  needs_user: {
567
- wall: "3ds",
568
- message: "The 3-D Secure challenge never reached a confirmed outcome within the resumable " +
569
- "window. Check the merchant account directly for whether the order was placed " +
570
- "before retrying — Trusty Squire will not re-release this card without a fresh " +
571
- "approval.",
619
+ wall: state.outcome === "three_ds" ? "3ds" : "merchant_reconciliation",
620
+ message: state.outcome === "three_ds"
621
+ ? "The 3-D Secure challenge never reached a confirmed outcome within the resumable " +
622
+ "window. Check the merchant account directly for whether the order was placed " +
623
+ "before retrying — Trusty Squire will not re-release this card without a fresh " +
624
+ "approval."
625
+ : "The merchant outcome remains unknown. Check the merchant account directly for " +
626
+ "whether the order was placed before retrying; this payment attempt remains " +
627
+ "reserved until the session is closed.",
572
628
  resume: "checkout",
573
629
  },
574
630
  }
575
631
  : {}),
576
632
  };
577
633
  }
578
- // Backs operate_payment_status: an immediate peek (waitSeconds <= 0) never
579
- // blocks, a positive waitSeconds bound-waits (clamped to [1s, 15s] — the
580
- // server's wait-peek window is a fixed ~15s regardless of what's requested,
581
- // and threeDsStatusResult clamps to the same shape for its own live check).
634
+ // Backs operate_payment_status with an immediate peek or one server wait.
582
635
  async function paymentStatusResult(api, session, waitSeconds) {
583
636
  const state = getActivePendingApproval(session);
584
637
  if (state !== null) {
585
638
  if (waitSeconds <= 0) {
586
- return paymentResult(session, await readApprovalStatus(api, state, session.id, false));
639
+ const result = await readApprovalStatus(api, state, session.id, false);
640
+ if (result.status === "denied" || result.status === "expired") {
641
+ completeActivePendingApprovalWithTerminalStatus(state, result.status, session);
642
+ }
643
+ return paymentResult(session, result);
644
+ }
645
+ const result = await readApprovalStatus(api, state, session.id, true, Math.min(Math.max(waitSeconds * 1000, 1_000), 15_000));
646
+ if (result.status === "denied" || result.status === "expired") {
647
+ completeActivePendingApprovalWithTerminalStatus(state, result.status, session);
587
648
  }
588
- const boundMs = Math.min(Math.max(waitSeconds * 1000, 1_000), 15_000);
589
- return paymentResult(session, await readApprovalStatus(api, state, session.id, true, boundMs));
649
+ return paymentResult(session, result);
650
+ }
651
+ const terminalApproval = getTerminalPaymentApproval(session);
652
+ if (terminalApproval !== null) {
653
+ const state = terminalApproval.state;
654
+ return paymentResult(session, {
655
+ status: terminalApproval.terminalStatus,
656
+ approval_id: state.approval_id,
657
+ approval_url: state.approval_url,
658
+ expires_at: new Date(state.deadline).toISOString(),
659
+ phase: state.phase ?? null,
660
+ merchant: state.checkout.merchant,
661
+ amount_cents: state.checkout.amount_cents,
662
+ currency: state.checkout.currency,
663
+ candidate_submitted: false,
664
+ candidate_kind: state.reviewVerified === true ? "review" : "none",
665
+ ready_to_charge: false,
666
+ });
590
667
  }
591
668
  const threeDsState = getActivePendingThreeDs(session);
592
669
  if (threeDsState !== null) {
@@ -596,25 +673,15 @@ async function paymentStatusResult(api, session, waitSeconds) {
596
673
  }
597
674
  const paymentStatusInputSchema = z.object({
598
675
  session_id: z.string().uuid().optional(),
599
- wait_seconds: z.number().int().min(0).max(15).optional(),
676
+ wait_seconds: z.number().int().min(0).max(60).optional(),
600
677
  });
601
678
  export const operatePaymentStatusTool = {
602
679
  name: "operate_payment_status",
603
- description: "Report the status of the addressed session's payment approval currently awaiting " +
604
- "the human's phone tap, if any — started by an operate_pay call that returned approval_pending. " +
605
- "Also covers an already-submitted charge whose 3-D Secure challenge (including a decoupled/" +
606
- "out-of-band app-push) had not resolved when a prior operate_pay call's own wait ended (that " +
607
- 'call returns payment_3ds_required or payment_outcome_unknown with needs_user.wall="3ds" and ' +
608
- "a next hint pointing here) — call this again to keep checking rather than re-calling " +
609
- "operate_pay, which does not resume a post-submit 3DS wait; reports payment_3ds_pending while " +
610
- "still unresolved. Never re-releases the card or creates a new approval. Pass `wait_seconds` " +
611
- "(0-15, default 0) to bound-wait for a change instead of an instant peek; never blocks longer " +
612
- "than that. Never verifies a mandate or opens a card. Only candidate_kind=approval with " +
613
- "ready_to_charge=true is a final authorization; a review candidate still requires final " +
614
- "approval. Preserves any passively observed payment_instrument_mismatch warning from issuer/" +
615
- "app evidence without altering the challenge. When a pending 3-D Secure outcome resolves or " +
616
- "reaches its deadline, this records " +
617
- "a terminal payment audit and clears that session's pending tracking.",
680
+ description: "Read the addressed session's pending approval or already-submitted outcome without opening a " +
681
+ "card, confirming a mandate, or creating another approval. Prefer re-calling operate_pay for a " +
682
+ "pending approval; this tool performs only one server wait. Use it repeatedly only for a " +
683
+ "submitted 3-D Secure or unknown outcome. It reports 3DS only from observed evidence, preserves " +
684
+ "instrument-mismatch warnings, and retains custody until a terminal audit or reconciliation.",
618
685
  inputSchema: paymentStatusInputSchema,
619
686
  jsonInputSchema: {
620
687
  type: "object",
@@ -627,8 +694,8 @@ export const operatePaymentStatusTool = {
627
694
  wait_seconds: {
628
695
  type: "integer",
629
696
  minimum: 0,
630
- maximum: 15,
631
- description: "Upper bound on this call's wait. 0 (default) is an instant peek; 1-15 bound-waits for a change.",
697
+ maximum: 60,
698
+ description: "Upper bound in seconds. Approval status uses one wait of at most 15 seconds; 0 is an instant peek.",
632
699
  },
633
700
  },
634
701
  },