linkque-cli-v2 1.1.5 → 1.2.1

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.
@@ -11823,6 +11823,8 @@ function describeRuntimeEnv(env, hasRequestKey = false) {
11823
11823
  lines.push(envLine("SESSION_LEASE_TABLE_ID", envValue(env, "SESSION_LEASE_TABLE_ID")));
11824
11824
  lines.push(envLine("CLIENT_CAPABILITY_DATABASE_ID", envValue(env, "CLIENT_CAPABILITY_DATABASE_ID")));
11825
11825
  lines.push(envLine("CLIENT_CAPABILITY_TABLE_ID", envValue(env, "CLIENT_CAPABILITY_TABLE_ID")));
11826
+ lines.push(envLine("A2UI_ACTION_DATABASE_ID", envValue(env, "A2UI_ACTION_DATABASE_ID")));
11827
+ lines.push(envLine("A2UI_ACTION_TABLE_ID", envValue(env, "A2UI_ACTION_TABLE_ID")));
11826
11828
  lines.push(envLine("RUN_INDEX_DATABASE_ID", envValue(env, "RUN_INDEX_DATABASE_ID")));
11827
11829
  lines.push(envLine("RUN_INDEX_TABLE_ID", envValue(env, "RUN_INDEX_TABLE_ID")));
11828
11830
  lines.push(envLine("SEARCH_DATABASE_ID", envValue(env, "SEARCH_DATABASE_ID")));
@@ -11889,6 +11891,145 @@ function parsePositiveInt(raw, def, name) {
11889
11891
  return n;
11890
11892
  }
11891
11893
 
11894
+ // ../linkque-agent-appwrite-integrate/dist/esm/runtime/paymentActionStore.js
11895
+ import { createHash } from "node:crypto";
11896
+ var PAYMENT_INVOCATION_TTL_MS = 24 * 60 * 60 * 1e3;
11897
+ function createPaymentInvocation(ownerId, request, now = /* @__PURE__ */ new Date()) {
11898
+ const invocationId = createPaymentInvocationId(ownerId, request);
11899
+ return {
11900
+ invocationId,
11901
+ ownerId,
11902
+ agentId: request.agentId,
11903
+ threadId: request.threadId,
11904
+ actionId: request.actionId,
11905
+ cardRef: request.source.cardRef,
11906
+ cardRevision: request.source.cardRevision,
11907
+ cardInstanceId: request.source.cardInstanceId,
11908
+ surfaceId: request.source.surfaceId,
11909
+ componentId: request.source.componentId,
11910
+ actionContext: request.actionContext,
11911
+ status: "executing",
11912
+ createdAt: now.toISOString(),
11913
+ expiresAt: new Date(now.getTime() + PAYMENT_INVOCATION_TTL_MS).toISOString()
11914
+ };
11915
+ }
11916
+ function createPaymentInvocationId(ownerId, request) {
11917
+ const material = stableStringify({
11918
+ ownerId,
11919
+ agentId: request.agentId,
11920
+ threadId: request.threadId,
11921
+ cardInstanceId: request.source.cardInstanceId,
11922
+ actionId: request.actionId,
11923
+ actionContext: request.actionContext
11924
+ });
11925
+ return `pa_${createHash("sha256").update(material).digest("hex").slice(0, 32)}`;
11926
+ }
11927
+ function createPaymentActionStore(databases, databaseId, tableId) {
11928
+ return {
11929
+ async begin(invocation) {
11930
+ const { invocationId, actionContext, ...fields } = invocation;
11931
+ try {
11932
+ const document = await databases.createDocument(databaseId, tableId, invocationId, { ...fields, actionContext: JSON.stringify(actionContext) }, []);
11933
+ return { kind: "created", invocation: readInvocation2(document) ?? invocation };
11934
+ } catch (error) {
11935
+ if (!isConflict2(error))
11936
+ throw error;
11937
+ const existing = await this.get(invocationId);
11938
+ if (!existing)
11939
+ throw error;
11940
+ return { kind: "existing", invocation: existing };
11941
+ }
11942
+ },
11943
+ async get(invocationId) {
11944
+ try {
11945
+ return readInvocation2(await databases.getDocument(databaseId, tableId, invocationId));
11946
+ } catch (error) {
11947
+ if (isNotFound2(error))
11948
+ return void 0;
11949
+ throw error;
11950
+ }
11951
+ },
11952
+ async update(invocationId, patch) {
11953
+ const data = { ...patch };
11954
+ if (patch.callback)
11955
+ data.callback = JSON.stringify(patch.callback);
11956
+ if (patch.verification)
11957
+ data.verification = JSON.stringify(patch.verification);
11958
+ const document = await databases.updateDocument(databaseId, tableId, invocationId, data);
11959
+ const invocation = readInvocation2(document);
11960
+ if (!invocation)
11961
+ throw new Error("\u652F\u4ED8 invocation \u6301\u4E45\u5316\u7ED3\u679C\u65E0\u6548");
11962
+ return invocation;
11963
+ },
11964
+ async cleanup(now) {
11965
+ const result = await databases.listDocuments(databaseId, tableId, [
11966
+ Query.lessThanEqual("expiresAt", now),
11967
+ Query.limit(500)
11968
+ ]);
11969
+ for (const document of result.documents) {
11970
+ await databases.deleteDocument(databaseId, tableId, document.$id);
11971
+ }
11972
+ return result.documents.length;
11973
+ }
11974
+ };
11975
+ }
11976
+ function readInvocation2(value) {
11977
+ if (!value || typeof value !== "object" || Array.isArray(value))
11978
+ return void 0;
11979
+ const row = value;
11980
+ if (typeof row.$id !== "string" || typeof row.ownerId !== "string" || typeof row.agentId !== "string" || typeof row.threadId !== "string" || typeof row.actionId !== "string" || typeof row.cardRef !== "string" || typeof row.cardRevision !== "string" || typeof row.cardInstanceId !== "string" || typeof row.surfaceId !== "string" || typeof row.componentId !== "string" || typeof row.actionContext !== "string" || typeof row.status !== "string" || typeof row.createdAt !== "string" || typeof row.expiresAt !== "string")
11981
+ return void 0;
11982
+ const actionContext = parseJsonObject(row.actionContext);
11983
+ if (!actionContext)
11984
+ return void 0;
11985
+ return {
11986
+ invocationId: row.$id,
11987
+ ownerId: row.ownerId,
11988
+ agentId: row.agentId,
11989
+ threadId: row.threadId,
11990
+ actionId: row.actionId,
11991
+ cardRef: row.cardRef,
11992
+ cardRevision: row.cardRevision,
11993
+ cardInstanceId: row.cardInstanceId,
11994
+ surfaceId: row.surfaceId,
11995
+ componentId: row.componentId,
11996
+ actionContext,
11997
+ status: row.status,
11998
+ ...typeof row.tradeNO === "string" ? { tradeNO: row.tradeNO } : {},
11999
+ ...typeof row.callback === "string" && parseJsonObject(row.callback) ? { callback: parseJsonObject(row.callback) } : {},
12000
+ ...typeof row.verification === "string" && parseVerification(row.verification) ? { verification: parseVerification(row.verification) } : {},
12001
+ createdAt: row.createdAt,
12002
+ expiresAt: row.expiresAt
12003
+ };
12004
+ }
12005
+ function parseJsonObject(value) {
12006
+ try {
12007
+ const parsed = JSON.parse(value);
12008
+ return parsed && typeof parsed === "object" && !Array.isArray(parsed) ? parsed : void 0;
12009
+ } catch {
12010
+ return void 0;
12011
+ }
12012
+ }
12013
+ function parseVerification(value) {
12014
+ const parsed = parseJsonObject(value);
12015
+ return parsed && typeof parsed.paid === "boolean" ? parsed : void 0;
12016
+ }
12017
+ function stableStringify(value) {
12018
+ if (Array.isArray(value))
12019
+ return `[${value.map(stableStringify).join(",")}]`;
12020
+ if (value && typeof value === "object") {
12021
+ return `{${Object.entries(value).sort(([left], [right]) => left.localeCompare(right)).map(([key, item]) => `${JSON.stringify(key)}:${stableStringify(item)}`).join(",")}}`;
12022
+ }
12023
+ return JSON.stringify(value);
12024
+ }
12025
+ function isNotFound2(error) {
12026
+ return Boolean(error && typeof error === "object" && "code" in error && error.code === 404);
12027
+ }
12028
+ function isConflict2(error) {
12029
+ const value = error;
12030
+ return value?.code === 409 || /already exists|conflict|duplicate|409/i.test(value?.message ?? "");
12031
+ }
12032
+
11892
12033
  // ../linkque-agent-appwrite-integrate/dist/esm/runtime/handler/handlerUtils.js
11893
12034
  function resolveBodyJSON(req) {
11894
12035
  if (req.bodyJSON !== void 0 && typeof req.bodyJSON !== "string") {
@@ -12056,7 +12197,18 @@ async function clientCapability(ctx) {
12056
12197
  try {
12057
12198
  const handle = createAppBaseClient(process.env, { log: ctx.log, error: ctx.error }, readAppwriteApiKey(ctx.req.headers));
12058
12199
  const store = createClientCapabilityStore(handle.databases, requiredEnv("CLIENT_CAPABILITY_DATABASE_ID"), requiredEnv("CLIENT_CAPABILITY_TABLE_ID"));
12059
- result = await runClientCapability(readAppwriteTrigger(ctx.req.headers), ctx.req.method, resolveBodyJSON(ctx.req), readAuthenticatedUserId(ctx.req.headers), store);
12200
+ const trigger = readAppwriteTrigger(ctx.req.headers);
12201
+ result = await runClientCapability(trigger, ctx.req.method, resolveBodyJSON(ctx.req), readAuthenticatedUserId(ctx.req.headers), store);
12202
+ if (trigger === "schedule" && process.env.A2UI_ACTION_DATABASE_ID && process.env.A2UI_ACTION_TABLE_ID) {
12203
+ const paymentDeleted = await createPaymentActionStore(handle.databases, process.env.A2UI_ACTION_DATABASE_ID, process.env.A2UI_ACTION_TABLE_ID).cleanup((/* @__PURE__ */ new Date()).toISOString());
12204
+ result = {
12205
+ status: 200,
12206
+ body: {
12207
+ ...result.body,
12208
+ paymentDeleted
12209
+ }
12210
+ };
12211
+ }
12060
12212
  } catch (error) {
12061
12213
  ctx.error?.(error);
12062
12214
  result = error instanceof LinkqueGatewayAuthError || error instanceof LinkqueGatewayAuthUnconfiguredError ? jsonError(error.status, error.code, error.message) : jsonError(500, "internal_error", error instanceof Error ? error.message : "unknown error");
@@ -12116,6 +12268,8 @@ export {
12116
12268
  createAppBaseClient,
12117
12269
  createClientCapabilityStore,
12118
12270
  parseStoredClientCapabilityResult,
12271
+ createPaymentInvocation,
12272
+ createPaymentActionStore,
12119
12273
  runClientCapability,
12120
12274
  runClientCapabilityResult,
12121
12275
  runClientCapabilityCleanup,
@@ -4,6 +4,8 @@ import {
4
4
  Query,
5
5
  createAppBaseClient,
6
6
  createClientCapabilityStore,
7
+ createPaymentActionStore,
8
+ createPaymentInvocation,
7
9
  describeRuntimeEnv,
8
10
  isDebugLogLevel,
9
11
  jsonError,
@@ -17,11 +19,12 @@ import {
17
19
  resolveLinkqueGatewayAuth,
18
20
  resolveRunStorage,
19
21
  toAgentRunMessages
20
- } from "../../chunk-B56A2RV5.js";
22
+ } from "../../chunk-NRTXRI33.js";
21
23
  import "../../chunk-MKS245OU.js";
22
24
  import "../../chunk-YDKZZ6EH.js";
23
25
  import "../../chunk-2NGJGNYB.js";
24
26
  import {
27
+ A2UI_PAYMENT_RESULT_EVENT_NAME,
25
28
  AgentRuntime,
26
29
  CANCEL_CONVERSATION_RUN_OPERATION,
27
30
  CONVERSATION_HISTORY_VERSION,
@@ -43,15 +46,19 @@ import {
43
46
  RemoteGatewayMcpServerProvider,
44
47
  WebSkillLoader,
45
48
  encodeConversationSseEvent,
49
+ executeCardAction,
46
50
  executeHomeData,
47
51
  getBakedProtocol,
52
+ parseA2UIActionExecuteRequest,
53
+ parseA2UIPaymentResultEventPayload,
48
54
  parseCancelConversationRunRequest,
49
55
  parseConversationFollowUpQuestions,
50
56
  parseConversationHistoryRequest,
51
57
  parseConversationRunRequest,
52
58
  parseSkillFile,
53
- streamToConversationEvents
54
- } from "../../chunk-IMZDZMKV.js";
59
+ streamToConversationEvents,
60
+ verifyPaymentResult
61
+ } from "../../chunk-IXJFWSVE.js";
55
62
  import "../../chunk-XUFLSZM4.js";
56
63
  import "../../chunk-I64V3ICJ.js";
57
64
  import "../../chunk-6MHDOBWO.js";
@@ -1707,6 +1714,101 @@ async function runHomeData(method, body, userId, deps = {}, env = process.env, e
1707
1714
  return { status: 200, body: response };
1708
1715
  }
1709
1716
 
1717
+ // ../linkque-agent-appwrite-integrate/dist/esm/runtime/handler/a2uiAction.js
1718
+ var A2UI_ACTION_EXECUTE_OPERATION = "a2uiAction.execute";
1719
+ async function runA2UIAction(method, body, userId, deps = {}, env = process.env, appwriteApiKey, envSelector = "PROD", gatewayAuth) {
1720
+ if (method.toUpperCase() !== "POST") {
1721
+ return jsonError(405, "method_not_allowed", "\u4EC5\u652F\u6301 POST");
1722
+ }
1723
+ if (!userId)
1724
+ return paymentFailure(401, "AUTH_REQUIRED", "\u7F3A\u5C11 Appwrite \u8BA4\u8BC1\u7528\u6237", false);
1725
+ let request;
1726
+ try {
1727
+ request = parseA2UIActionExecuteRequest(body);
1728
+ } catch (error) {
1729
+ return paymentFailure(400, "INVALID_INPUT", errorMessage(error, "\u652F\u4ED8\u52A8\u4F5C\u8BF7\u6C42\u65E0\u6548"), false);
1730
+ }
1731
+ const protocol = deps.protocol ?? getBakedProtocol();
1732
+ if (request.agentId !== protocol.agentId) {
1733
+ return paymentFailure(403, "AGENT_MISMATCH", "\u652F\u4ED8\u52A8\u4F5C\u4E0E\u5F53\u524D Agent \u4E0D\u5339\u914D", false);
1734
+ }
1735
+ const store = deps.paymentActionStore ?? resolveStore(env, appwriteApiKey);
1736
+ if (!store) {
1737
+ return paymentFailure(503, "EXECUTION_FAILED", "\u652F\u4ED8\u52A8\u4F5C\u5B58\u50A8\u672A\u914D\u7F6E", true);
1738
+ }
1739
+ const provider = deps.mcpServerProvider ?? resolveProvider(protocol, env, envSelector, gatewayAuth);
1740
+ if (!provider) {
1741
+ return paymentFailure(503, "MCP_NOT_BOUND", "\u652F\u4ED8 MCP \u8FDE\u63A5\u672A\u914D\u7F6E", true);
1742
+ }
1743
+ const begin = await store.begin(createPaymentInvocation(userId, request));
1744
+ if (begin.kind === "existing") {
1745
+ const current = begin.invocation;
1746
+ if (current.tradeNO && ["trade-created", "payment-reported", "verified-paid", "verified-unpaid"].includes(current.status)) {
1747
+ return { status: 200, body: success(current.invocationId, current.tradeNO) };
1748
+ }
1749
+ if (current.status === "executing") {
1750
+ return paymentFailure(409, "ACTION_IN_PROGRESS", "\u652F\u4ED8\u52A8\u4F5C\u6B63\u5728\u5904\u7406\u4E2D", true);
1751
+ }
1752
+ if (current.status === "uncertain") {
1753
+ return paymentFailure(409, "EXECUTION_UNCERTAIN", "\u521B\u5EFA\u4EA4\u6613\u7ED3\u679C\u4E0D\u786E\u5B9A\uFF0C\u8BF7\u52FF\u91CD\u590D\u652F\u4ED8", false);
1754
+ }
1755
+ return paymentFailure(409, "EXECUTION_FAILED", "\u652F\u4ED8\u52A8\u4F5C\u5DF2\u5931\u8D25\uFF0C\u8BF7\u5237\u65B0\u5361\u7247\u540E\u91CD\u8BD5", false);
1756
+ }
1757
+ const invocationId = begin.invocation.invocationId;
1758
+ const response = await executeCardAction({
1759
+ request: { ...request, invocationId },
1760
+ protocol,
1761
+ runtimeContext: {
1762
+ agentId: protocol.agentId,
1763
+ threadId: request.threadId,
1764
+ userId
1765
+ },
1766
+ mcpServerProvider: provider
1767
+ });
1768
+ if (response.ok) {
1769
+ await store.update(invocationId, {
1770
+ status: "trade-created",
1771
+ tradeNO: response.result.tradeNO
1772
+ });
1773
+ return { status: 200, body: response };
1774
+ }
1775
+ await store.update(invocationId, {
1776
+ status: response.error.code === "EXECUTION_FAILED" ? "uncertain" : "failed-before-execute"
1777
+ });
1778
+ return { status: response.error.code === "EXECUTION_FAILED" ? 502 : 400, body: response };
1779
+ }
1780
+ function resolveStore(env, appwriteApiKey) {
1781
+ if (!env.A2UI_ACTION_DATABASE_ID || !env.A2UI_ACTION_TABLE_ID)
1782
+ return void 0;
1783
+ const handle = createAppBaseClient(env, void 0, appwriteApiKey);
1784
+ return createPaymentActionStore(handle.databases, env.A2UI_ACTION_DATABASE_ID, env.A2UI_ACTION_TABLE_ID);
1785
+ }
1786
+ function resolveProvider(protocol, env, envSelector, gatewayAuth) {
1787
+ let auth;
1788
+ try {
1789
+ auth = resolveGatewayAuthContext(gatewayAuth, env, void 0, "a2ui-action");
1790
+ } catch {
1791
+ return void 0;
1792
+ }
1793
+ const { mcpSignEndpoint } = resolveLinkqueEndpoints(env, envSelector);
1794
+ return createAppbaseMcpProvider({
1795
+ resolveConfig: createAppbaseMcpConfigResolver({
1796
+ agentId: protocol.agentId,
1797
+ ...mcpSignEndpoint ? { signEndpoint: mcpSignEndpoint } : {}
1798
+ }),
1799
+ getAuthorizationHeader: async () => auth.authorizationHeader
1800
+ });
1801
+ }
1802
+ function success(invocationId, tradeNO) {
1803
+ return { ok: true, invocationId, result: { kind: "payment", tradeNO } };
1804
+ }
1805
+ function paymentFailure(status, code, message, retryable) {
1806
+ return { status, body: { ok: false, error: { code, message, retryable } } };
1807
+ }
1808
+ function errorMessage(error, fallback) {
1809
+ return error instanceof Error && error.message.trim() ? error.message : fallback;
1810
+ }
1811
+
1710
1812
  // ../linkque-agent-appwrite-integrate/dist/esm/runtime/handler/chatConfig.js
1711
1813
  function resolveChatDeps(env, deps, logCtx, historyOwnerId, appwriteApiKey, envSelector, gatewayAuth) {
1712
1814
  const log = (...a) => logCtx?.log?.("[chat]", ...a);
@@ -1728,6 +1830,7 @@ function resolveChatDeps(env, deps, logCtx, historyOwnerId, appwriteApiKey, envS
1728
1830
  let sessionLease = deps?.sessionLease;
1729
1831
  let historyStore = deps?.historyStore;
1730
1832
  let clientCapabilityStore = deps?.clientCapabilityStore;
1833
+ let paymentActionStore = deps?.paymentActionStore;
1731
1834
  let chunkSize = 30;
1732
1835
  if (!store) {
1733
1836
  let storage;
@@ -1748,6 +1851,9 @@ function resolveChatDeps(env, deps, logCtx, historyOwnerId, appwriteApiKey, envS
1748
1851
  if (env.CLIENT_CAPABILITY_DATABASE_ID && env.CLIENT_CAPABILITY_TABLE_ID) {
1749
1852
  clientCapabilityStore ??= createClientCapabilityStore(handle.databases, env.CLIENT_CAPABILITY_DATABASE_ID, env.CLIENT_CAPABILITY_TABLE_ID);
1750
1853
  }
1854
+ if (env.A2UI_ACTION_DATABASE_ID && env.A2UI_ACTION_TABLE_ID) {
1855
+ paymentActionStore ??= createPaymentActionStore(handle.databases, env.A2UI_ACTION_DATABASE_ID, env.A2UI_ACTION_TABLE_ID);
1856
+ }
1751
1857
  try {
1752
1858
  historyStore ??= createConversationHistoryStore(handle.databases, resolveConversationHistoryStorage(env), historyOwnerId);
1753
1859
  } catch (err) {
@@ -1770,6 +1876,10 @@ function resolveChatDeps(env, deps, logCtx, historyOwnerId, appwriteApiKey, envS
1770
1876
  agentId: protocol.agentId,
1771
1877
  ...mcpSignEndpoint ? { signEndpoint: mcpSignEndpoint } : {}
1772
1878
  });
1879
+ const mcpServerProvider = deps?.mcpServerProvider ?? createAppbaseMcpProvider({
1880
+ resolveConfig: mcpConfigResolver,
1881
+ getAuthorizationHeader: mcpAuthorizationHeaderProvider
1882
+ });
1773
1883
  const runtime = deps?.runtime ?? createAppBaseRuntime(protocol, env, {
1774
1884
  ...appwriteApiKey ? { appBaseApiKey: appwriteApiKey } : {},
1775
1885
  mcpConfigResolver,
@@ -1790,6 +1900,8 @@ function resolveChatDeps(env, deps, logCtx, historyOwnerId, appwriteApiKey, envS
1790
1900
  sessionLease,
1791
1901
  historyStore,
1792
1902
  clientCapabilityStore,
1903
+ paymentActionStore,
1904
+ mcpServerProvider,
1793
1905
  chunkSize
1794
1906
  };
1795
1907
  }
@@ -2119,7 +2231,7 @@ async function runChat(method, bodyJSON, env, deps, logCtx, historyOwnerId, appw
2119
2231
  const guarded = guardChatRequest(method, bodyJSON, logCtx);
2120
2232
  if ("status" in guarded)
2121
2233
  return guarded;
2122
- const request = guarded;
2234
+ let request = guarded;
2123
2235
  const isPresentationRun = request.executionScope === "presentation";
2124
2236
  const cfg = resolveChatDeps(env, deps, logCtx, historyOwnerId, appwriteApiKey, envSelector, gatewayAuth);
2125
2237
  if ("status" in cfg)
@@ -2153,6 +2265,10 @@ async function runChat(method, bodyJSON, env, deps, logCtx, historyOwnerId, appw
2153
2265
  }
2154
2266
  };
2155
2267
  try {
2268
+ const preparedPayment = await preparePaymentResultRequest(request, cfg, historyOwnerId, logCtx);
2269
+ if ("status" in preparedPayment)
2270
+ return preparedPayment;
2271
+ request = preparedPayment;
2156
2272
  if (cfg.historyStore && !isPresentationRun) {
2157
2273
  try {
2158
2274
  await cfg.historyStore.beginRun(request, cfg.protocol.agentId);
@@ -2289,6 +2405,100 @@ async function runChat(method, bodyJSON, env, deps, logCtx, historyOwnerId, appw
2289
2405
  await releaseLease();
2290
2406
  }
2291
2407
  }
2408
+ async function preparePaymentResultRequest(request, cfg, ownerId, logCtx) {
2409
+ const message = request.messages.at(-1);
2410
+ const content = message?.content;
2411
+ if (!content || typeof content === "string" || content.type !== "a2ui.event" || content.event.name !== A2UI_PAYMENT_RESULT_EVENT_NAME)
2412
+ return request;
2413
+ if (!ownerId)
2414
+ return jsonError(401, "authentication_required", "\u652F\u4ED8\u7ED3\u679C\u7F3A\u5C11\u8BA4\u8BC1\u7528\u6237");
2415
+ let payload;
2416
+ try {
2417
+ payload = parseA2UIPaymentResultEventPayload(content.event.payload);
2418
+ } catch (error) {
2419
+ return jsonError(400, "payment_result_invalid", error instanceof Error ? error.message : "\u652F\u4ED8\u7ED3\u679C\u683C\u5F0F\u65E0\u6548");
2420
+ }
2421
+ if (payload.callback.resultCode !== "9000") {
2422
+ return jsonError(400, "payment_result_invalid", "\u4EC5\u63A5\u53D7 resultCode=9000 \u7684\u652F\u4ED8\u7ED3\u679C\u4E8B\u4EF6");
2423
+ }
2424
+ const source = content.source;
2425
+ if (!source.cardRef || !source.cardRevision || !source.cardInstanceId) {
2426
+ return jsonError(400, "payment_source_invalid", "\u652F\u4ED8\u7ED3\u679C\u7F3A\u5C11\u5B8C\u6574 CARD source identity");
2427
+ }
2428
+ const store = cfg.paymentActionStore;
2429
+ if (!store) {
2430
+ return enrichPaymentRequest(request, payload, {
2431
+ verificationError: { code: "PAYMENT_VERIFICATION_UNAVAILABLE", message: "\u652F\u4ED8\u72B6\u6001\u6682\u672A\u786E\u8BA4" }
2432
+ });
2433
+ }
2434
+ const invocation = await store.get(payload.actionInvocationId);
2435
+ if (!invocation || invocation.ownerId !== ownerId || invocation.agentId !== cfg.protocol.agentId || invocation.threadId !== request.threadId || invocation.actionId !== payload.actionId || invocation.tradeNO !== payload.tradeNO || invocation.cardRef !== source.cardRef || invocation.cardRevision !== source.cardRevision || invocation.cardInstanceId !== source.cardInstanceId || invocation.surfaceId !== source.surfaceId || invocation.componentId !== source.componentId || stableJson(invocation.actionContext) !== stableJson(payload.actionContext)) {
2436
+ return jsonError(403, "payment_result_forbidden", "\u652F\u4ED8\u7ED3\u679C\u4E0E\u5DF2\u521B\u5EFA\u7684\u4EA4\u6613\u4E0D\u5339\u914D");
2437
+ }
2438
+ if (invocation.verification) {
2439
+ return enrichPaymentRequest(request, payload, { verification: invocation.verification });
2440
+ }
2441
+ if (invocation.status === "payment-reported") {
2442
+ return enrichPaymentRequest(request, payload, {
2443
+ verificationError: { code: "PAYMENT_VERIFICATION_IN_PROGRESS", message: "\u652F\u4ED8\u72B6\u6001\u6682\u672A\u786E\u8BA4" }
2444
+ });
2445
+ }
2446
+ try {
2447
+ await store.update(invocation.invocationId, {
2448
+ status: "payment-reported",
2449
+ callback: payload.callback
2450
+ });
2451
+ const verification = await verifyPaymentResult({
2452
+ payload,
2453
+ source: {
2454
+ cardRef: source.cardRef,
2455
+ cardRevision: source.cardRevision,
2456
+ cardInstanceId: source.cardInstanceId,
2457
+ surfaceId: source.surfaceId,
2458
+ componentId: source.componentId
2459
+ },
2460
+ protocol: cfg.protocol,
2461
+ runtimeContext: {
2462
+ agentId: cfg.protocol.agentId,
2463
+ threadId: request.threadId,
2464
+ userId: ownerId
2465
+ },
2466
+ mcpServerProvider: cfg.mcpServerProvider
2467
+ });
2468
+ await store.update(invocation.invocationId, {
2469
+ status: verification.paid ? "verified-paid" : "verified-unpaid",
2470
+ verification
2471
+ });
2472
+ return enrichPaymentRequest(request, payload, { verification });
2473
+ } catch {
2474
+ logCtx?.error?.("[chat] \u652F\u4ED8\u7ED3\u679C\u670D\u52A1\u7AEF\u6838\u9A8C\u5931\u8D25", "PAYMENT_VERIFICATION_FAILED");
2475
+ return enrichPaymentRequest(request, payload, {
2476
+ verificationError: { code: "PAYMENT_VERIFICATION_FAILED", message: "\u652F\u4ED8\u72B6\u6001\u6682\u672A\u786E\u8BA4" }
2477
+ });
2478
+ }
2479
+ }
2480
+ function enrichPaymentRequest(request, payload, enrichment) {
2481
+ const messages = request.messages.slice();
2482
+ const last = messages.at(-1);
2483
+ if (!last || !last.content || typeof last.content === "string")
2484
+ return request;
2485
+ messages[messages.length - 1] = {
2486
+ ...last,
2487
+ content: {
2488
+ ...last.content,
2489
+ event: { ...last.content.event, payload: { ...payload, ...enrichment } }
2490
+ }
2491
+ };
2492
+ return { ...request, messages };
2493
+ }
2494
+ function stableJson(value) {
2495
+ if (Array.isArray(value))
2496
+ return `[${value.map(stableJson).join(",")}]`;
2497
+ if (value && typeof value === "object") {
2498
+ return `{${Object.entries(value).sort(([left], [right]) => left.localeCompare(right)).map(([key, item]) => `${JSON.stringify(key)}:${stableJson(item)}`).join(",")}}`;
2499
+ }
2500
+ return JSON.stringify(value);
2501
+ }
2292
2502
  function readSearchableUserContent(request) {
2293
2503
  const content = request.messages.at(-1)?.content;
2294
2504
  if (typeof content === "string")
@@ -2363,6 +2573,14 @@ async function runGateway(method, bodyJSON, env, deps, logCtx, historyOwnerId, a
2363
2573
  ...deps?.mcpServerProvider ? { mcpServerProvider: deps.mcpServerProvider } : {}
2364
2574
  }, env, envSelector === "PRE" ? "PRE" : "PROD");
2365
2575
  }
2576
+ if (operation === A2UI_ACTION_EXECUTE_OPERATION) {
2577
+ const request = readOperationPayload(bodyJSON);
2578
+ return runA2UIAction(method, request, historyOwnerId, {
2579
+ ...deps?.protocol ? { protocol: deps.protocol } : {},
2580
+ ...deps?.mcpServerProvider ? { mcpServerProvider: deps.mcpServerProvider } : {},
2581
+ ...deps?.paymentActionStore ? { paymentActionStore: deps.paymentActionStore } : {}
2582
+ }, env, appwriteApiKey, envSelector === "PRE" ? "PRE" : "PROD", gatewayAuth);
2583
+ }
2366
2584
  if (operation && HISTORY_OPERATIONS.has(operation)) {
2367
2585
  return runHistory(method, bodyJSON, env, deps ? { protocol: deps.protocol, store: deps.historyStore } : void 0, logCtx, historyOwnerId, appwriteApiKey);
2368
2586
  }
@@ -3,7 +3,7 @@ import {
3
3
  runClientCapability,
4
4
  runClientCapabilityCleanup,
5
5
  runClientCapabilityResult
6
- } from "../../chunk-B56A2RV5.js";
6
+ } from "../../chunk-NRTXRI33.js";
7
7
  import "../../chunk-MKS245OU.js";
8
8
  import "../../chunk-YDKZZ6EH.js";
9
9
  import "../../chunk-2NGJGNYB.js";
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  getBakedProtocol,
3
3
  setBakedProtocol
4
- } from "../chunk-IMZDZMKV.js";
4
+ } from "../chunk-IXJFWSVE.js";
5
5
  import "../chunk-XUFLSZM4.js";
6
6
  import "../chunk-I64V3ICJ.js";
7
7
  import "../chunk-6MHDOBWO.js";