@muxoai/sdk 1.2.3 → 1.4.2

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 (208) hide show
  1. package/.agents/plugins/marketplace.json +22 -0
  2. package/.claude-plugin/marketplace.json +32 -0
  3. package/.codex/config.toml +12 -0
  4. package/ARCHITECTURE.md +121 -0
  5. package/README.md +85 -31
  6. package/dist/clerk.d.ts +35 -0
  7. package/dist/clerk.js +201 -0
  8. package/dist/cli.d.ts +2 -0
  9. package/dist/cli.js +2380 -0
  10. package/dist/composio-catalog.d.ts +234 -0
  11. package/dist/composio-catalog.js +1894 -0
  12. package/dist/config.d.ts +36 -0
  13. package/dist/config.js +115 -0
  14. package/dist/durable-workflow.d.ts +45 -0
  15. package/dist/durable-workflow.js +90 -0
  16. package/dist/engine.d.ts +465 -0
  17. package/dist/engine.js +2560 -0
  18. package/dist/index.d.ts +7 -0
  19. package/dist/index.js +7 -0
  20. package/dist/mcp-schema.d.ts +286 -0
  21. package/dist/mcp-schema.js +2559 -0
  22. package/dist/mcp.d.ts +22 -0
  23. package/dist/mcp.js +1356 -0
  24. package/dist/memory-graph.d.ts +21 -0
  25. package/dist/memory-graph.js +173 -0
  26. package/dist/nl.d.ts +34 -0
  27. package/dist/nl.js +756 -0
  28. package/dist/oauth.d.ts +32 -0
  29. package/dist/oauth.js +134 -0
  30. package/dist/policy.d.ts +190 -0
  31. package/dist/policy.js +1597 -0
  32. package/dist/providers/composio-instant.d.ts +18 -0
  33. package/dist/providers/composio-instant.js +1169 -0
  34. package/dist/providers/composio-sdk.d.ts +162 -0
  35. package/dist/providers/composio-sdk.js +1395 -0
  36. package/dist/providers/microsoft-governance.d.ts +152 -0
  37. package/dist/providers/microsoft-governance.js +1062 -0
  38. package/dist/providers/stripe-billing.d.ts +83 -0
  39. package/dist/providers/stripe-billing.js +611 -0
  40. package/dist/providers/stripe-projects.d.ts +508 -0
  41. package/dist/providers/stripe-projects.js +3188 -0
  42. package/dist/providers/supermemory.d.ts +160 -0
  43. package/dist/providers/supermemory.js +778 -0
  44. package/dist/provisioning-managed.d.ts +50 -0
  45. package/dist/provisioning-managed.js +155 -0
  46. package/dist/sdk.d.ts +951 -0
  47. package/dist/sdk.js +748 -0
  48. package/dist/server.d.ts +10 -0
  49. package/dist/server.js +3575 -0
  50. package/dist/store.d.ts +348 -0
  51. package/dist/store.js +2323 -0
  52. package/dist/types.d.ts +593 -0
  53. package/dist/types.js +1 -0
  54. package/dist/ui/console-html.d.ts +64 -0
  55. package/dist/ui/console-html.js +3857 -0
  56. package/dist/ui/design-tokens.d.ts +177 -0
  57. package/dist/ui/design-tokens.js +210 -0
  58. package/dist/version.d.ts +1 -0
  59. package/dist/version.js +1 -0
  60. package/package.json +68 -7
  61. package/plugins/muxo/.app.json +8 -0
  62. package/plugins/muxo/.claude-plugin/plugin.json +16 -0
  63. package/plugins/muxo/.codex-plugin/plugin.json +64 -0
  64. package/plugins/muxo/.cursor-plugin/plugin.json +30 -0
  65. package/plugins/muxo/.mcp.json +8 -0
  66. package/plugins/muxo/assets/logo.png +0 -0
  67. package/plugins/muxo/assets/logo.svg +6 -0
  68. package/plugins/muxo/hooks/hooks.json +27 -0
  69. package/plugins/muxo/hooks/session-start.sh +97 -0
  70. package/plugins/muxo/hooks/user-prompt-submit.sh +58 -0
  71. package/plugins/muxo/mcp.json +28 -0
  72. package/plugins/muxo/plugin.json +116 -0
  73. package/plugins/muxo/skills/muxo/SKILL.md +153 -0
  74. package/plugins/muxo/skills/muxo/agents/openai.yaml +12 -0
  75. package/plugins/muxo/skills/muxo/references/cli.md +63 -0
  76. package/plugins/muxo/skills/muxo/references/mcp.md +37 -0
  77. package/plugins/muxo/skills/muxo-activity-summary/SKILL.md +81 -0
  78. package/plugins/muxo/skills/setup/SKILL.md +42 -0
  79. package/plugins/muxo/skills/setup/agents/openai.yaml +12 -0
  80. package/src/catalogues/stripe-projects-catalog.json +9972 -0
  81. package/vendor/microsoft-governance/README.md +363 -0
  82. package/vendor/microsoft-governance/dist/audit.d.ts +26 -0
  83. package/vendor/microsoft-governance/dist/audit.d.ts.map +1 -0
  84. package/vendor/microsoft-governance/dist/audit.js +107 -0
  85. package/vendor/microsoft-governance/dist/audit.js.map +1 -0
  86. package/vendor/microsoft-governance/dist/cascade-containment.d.ts +84 -0
  87. package/vendor/microsoft-governance/dist/cascade-containment.d.ts.map +1 -0
  88. package/vendor/microsoft-governance/dist/cascade-containment.js +387 -0
  89. package/vendor/microsoft-governance/dist/cascade-containment.js.map +1 -0
  90. package/vendor/microsoft-governance/dist/client.d.ts +34 -0
  91. package/vendor/microsoft-governance/dist/client.d.ts.map +1 -0
  92. package/vendor/microsoft-governance/dist/client.js +112 -0
  93. package/vendor/microsoft-governance/dist/client.js.map +1 -0
  94. package/vendor/microsoft-governance/dist/context-poisoning.d.ts +58 -0
  95. package/vendor/microsoft-governance/dist/context-poisoning.d.ts.map +1 -0
  96. package/vendor/microsoft-governance/dist/context-poisoning.js +410 -0
  97. package/vendor/microsoft-governance/dist/context-poisoning.js.map +1 -0
  98. package/vendor/microsoft-governance/dist/credential-vault.d.ts +213 -0
  99. package/vendor/microsoft-governance/dist/credential-vault.d.ts.map +1 -0
  100. package/vendor/microsoft-governance/dist/credential-vault.js +567 -0
  101. package/vendor/microsoft-governance/dist/credential-vault.js.map +1 -0
  102. package/vendor/microsoft-governance/dist/discovery.d.ts +80 -0
  103. package/vendor/microsoft-governance/dist/discovery.d.ts.map +1 -0
  104. package/vendor/microsoft-governance/dist/discovery.js +404 -0
  105. package/vendor/microsoft-governance/dist/discovery.js.map +1 -0
  106. package/vendor/microsoft-governance/dist/encryption/channel.d.ts +29 -0
  107. package/vendor/microsoft-governance/dist/encryption/channel.d.ts.map +1 -0
  108. package/vendor/microsoft-governance/dist/encryption/channel.js +78 -0
  109. package/vendor/microsoft-governance/dist/encryption/channel.js.map +1 -0
  110. package/vendor/microsoft-governance/dist/encryption/index.d.ts +9 -0
  111. package/vendor/microsoft-governance/dist/encryption/index.d.ts.map +1 -0
  112. package/vendor/microsoft-governance/dist/encryption/index.js +23 -0
  113. package/vendor/microsoft-governance/dist/encryption/index.js.map +1 -0
  114. package/vendor/microsoft-governance/dist/encryption/mesh-client.d.ts +267 -0
  115. package/vendor/microsoft-governance/dist/encryption/mesh-client.d.ts.map +1 -0
  116. package/vendor/microsoft-governance/dist/encryption/mesh-client.js +1001 -0
  117. package/vendor/microsoft-governance/dist/encryption/mesh-client.js.map +1 -0
  118. package/vendor/microsoft-governance/dist/encryption/ratchet.d.ts +38 -0
  119. package/vendor/microsoft-governance/dist/encryption/ratchet.d.ts.map +1 -0
  120. package/vendor/microsoft-governance/dist/encryption/ratchet.js +223 -0
  121. package/vendor/microsoft-governance/dist/encryption/ratchet.js.map +1 -0
  122. package/vendor/microsoft-governance/dist/encryption/registry-client.d.ts +136 -0
  123. package/vendor/microsoft-governance/dist/encryption/registry-client.d.ts.map +1 -0
  124. package/vendor/microsoft-governance/dist/encryption/registry-client.js +369 -0
  125. package/vendor/microsoft-governance/dist/encryption/registry-client.js.map +1 -0
  126. package/vendor/microsoft-governance/dist/encryption/x3dh.d.ts +80 -0
  127. package/vendor/microsoft-governance/dist/encryption/x3dh.d.ts.map +1 -0
  128. package/vendor/microsoft-governance/dist/encryption/x3dh.js +238 -0
  129. package/vendor/microsoft-governance/dist/encryption/x3dh.js.map +1 -0
  130. package/vendor/microsoft-governance/dist/framework-adapter.d.ts +63 -0
  131. package/vendor/microsoft-governance/dist/framework-adapter.d.ts.map +1 -0
  132. package/vendor/microsoft-governance/dist/framework-adapter.js +253 -0
  133. package/vendor/microsoft-governance/dist/framework-adapter.js.map +1 -0
  134. package/vendor/microsoft-governance/dist/identity.d.ts +124 -0
  135. package/vendor/microsoft-governance/dist/identity.d.ts.map +1 -0
  136. package/vendor/microsoft-governance/dist/identity.js +446 -0
  137. package/vendor/microsoft-governance/dist/identity.js.map +1 -0
  138. package/vendor/microsoft-governance/dist/index.d.ts +39 -0
  139. package/vendor/microsoft-governance/dist/index.d.ts.map +1 -0
  140. package/vendor/microsoft-governance/dist/index.js +95 -0
  141. package/vendor/microsoft-governance/dist/index.js.map +1 -0
  142. package/vendor/microsoft-governance/dist/kill-switch.d.ts +22 -0
  143. package/vendor/microsoft-governance/dist/kill-switch.d.ts.map +1 -0
  144. package/vendor/microsoft-governance/dist/kill-switch.js +60 -0
  145. package/vendor/microsoft-governance/dist/kill-switch.js.map +1 -0
  146. package/vendor/microsoft-governance/dist/lifecycle.d.ts +50 -0
  147. package/vendor/microsoft-governance/dist/lifecycle.d.ts.map +1 -0
  148. package/vendor/microsoft-governance/dist/lifecycle.js +113 -0
  149. package/vendor/microsoft-governance/dist/lifecycle.js.map +1 -0
  150. package/vendor/microsoft-governance/dist/mcp.d.ts +41 -0
  151. package/vendor/microsoft-governance/dist/mcp.d.ts.map +1 -0
  152. package/vendor/microsoft-governance/dist/mcp.js +233 -0
  153. package/vendor/microsoft-governance/dist/mcp.js.map +1 -0
  154. package/vendor/microsoft-governance/dist/metrics.d.ts +123 -0
  155. package/vendor/microsoft-governance/dist/metrics.d.ts.map +1 -0
  156. package/vendor/microsoft-governance/dist/metrics.js +289 -0
  157. package/vendor/microsoft-governance/dist/metrics.js.map +1 -0
  158. package/vendor/microsoft-governance/dist/oci-manifest.d.ts +49 -0
  159. package/vendor/microsoft-governance/dist/oci-manifest.d.ts.map +1 -0
  160. package/vendor/microsoft-governance/dist/oci-manifest.js +182 -0
  161. package/vendor/microsoft-governance/dist/oci-manifest.js.map +1 -0
  162. package/vendor/microsoft-governance/dist/policy-backends/cedar.d.ts +15 -0
  163. package/vendor/microsoft-governance/dist/policy-backends/cedar.d.ts.map +1 -0
  164. package/vendor/microsoft-governance/dist/policy-backends/cedar.js +88 -0
  165. package/vendor/microsoft-governance/dist/policy-backends/cedar.js.map +1 -0
  166. package/vendor/microsoft-governance/dist/policy-backends/opa.d.ts +17 -0
  167. package/vendor/microsoft-governance/dist/policy-backends/opa.d.ts.map +1 -0
  168. package/vendor/microsoft-governance/dist/policy-backends/opa.js +74 -0
  169. package/vendor/microsoft-governance/dist/policy-backends/opa.js.map +1 -0
  170. package/vendor/microsoft-governance/dist/policy.d.ts +77 -0
  171. package/vendor/microsoft-governance/dist/policy.d.ts.map +1 -0
  172. package/vendor/microsoft-governance/dist/policy.js +760 -0
  173. package/vendor/microsoft-governance/dist/policy.js.map +1 -0
  174. package/vendor/microsoft-governance/dist/prompt-defense.d.ts +37 -0
  175. package/vendor/microsoft-governance/dist/prompt-defense.d.ts.map +1 -0
  176. package/vendor/microsoft-governance/dist/prompt-defense.js +229 -0
  177. package/vendor/microsoft-governance/dist/prompt-defense.js.map +1 -0
  178. package/vendor/microsoft-governance/dist/protocol-facets.d.ts +87 -0
  179. package/vendor/microsoft-governance/dist/protocol-facets.d.ts.map +1 -0
  180. package/vendor/microsoft-governance/dist/protocol-facets.js +728 -0
  181. package/vendor/microsoft-governance/dist/protocol-facets.js.map +1 -0
  182. package/vendor/microsoft-governance/dist/rings.d.ts +17 -0
  183. package/vendor/microsoft-governance/dist/rings.d.ts.map +1 -0
  184. package/vendor/microsoft-governance/dist/rings.js +61 -0
  185. package/vendor/microsoft-governance/dist/rings.js.map +1 -0
  186. package/vendor/microsoft-governance/dist/sandbox.d.ts +61 -0
  187. package/vendor/microsoft-governance/dist/sandbox.d.ts.map +1 -0
  188. package/vendor/microsoft-governance/dist/sandbox.js +199 -0
  189. package/vendor/microsoft-governance/dist/sandbox.js.map +1 -0
  190. package/vendor/microsoft-governance/dist/surface-parity.d.ts +45 -0
  191. package/vendor/microsoft-governance/dist/surface-parity.d.ts.map +1 -0
  192. package/vendor/microsoft-governance/dist/surface-parity.js +216 -0
  193. package/vendor/microsoft-governance/dist/surface-parity.js.map +1 -0
  194. package/vendor/microsoft-governance/dist/trust.d.ts +28 -0
  195. package/vendor/microsoft-governance/dist/trust.d.ts.map +1 -0
  196. package/vendor/microsoft-governance/dist/trust.js +209 -0
  197. package/vendor/microsoft-governance/dist/trust.js.map +1 -0
  198. package/vendor/microsoft-governance/dist/types.d.ts +422 -0
  199. package/vendor/microsoft-governance/dist/types.d.ts.map +1 -0
  200. package/vendor/microsoft-governance/dist/types.js +29 -0
  201. package/vendor/microsoft-governance/dist/types.js.map +1 -0
  202. package/vendor/microsoft-governance/dist/verify.d.ts +135 -0
  203. package/vendor/microsoft-governance/dist/verify.d.ts.map +1 -0
  204. package/vendor/microsoft-governance/dist/verify.js +356 -0
  205. package/vendor/microsoft-governance/dist/verify.js.map +1 -0
  206. package/vendor/microsoft-governance/package.json +64 -0
  207. package/index.d.ts +0 -177
  208. package/index.js +0 -1
@@ -0,0 +1,83 @@
1
+ import type { MuxoConfig } from "../config.js";
2
+ import type { MuxoStore } from "../store.js";
3
+ import type { ToolDescriptor, Workspace } from "../types.js";
4
+ export declare const BILLING_TOOLS: ToolDescriptor[];
5
+ export interface StripeMeterEventRecord {
6
+ identifier: string;
7
+ event_name: string;
8
+ timestamp: string;
9
+ workspaceId: string;
10
+ stripe_customer_id: string;
11
+ value: number;
12
+ lane: string;
13
+ tool_slug: string;
14
+ livemode: boolean;
15
+ source: "stripe_v2_meter_stream" | "muxo_local_meter";
16
+ }
17
+ export declare class StripeBillingAdapter {
18
+ private readonly config;
19
+ private readonly store;
20
+ private resolvedStarterPriceId;
21
+ private resolvedCreditsPriceId;
22
+ private meterSessionToken;
23
+ private readonly meterEvents;
24
+ private readonly seenMeterIdentifiers;
25
+ constructor(config: MuxoConfig, store: MuxoStore);
26
+ private getEffectiveStripeKey;
27
+ get isConfigured(): boolean;
28
+ listTools(): ToolDescriptor[];
29
+ private stripeRequest;
30
+ ensurePrices(workspaceId?: string): Promise<{
31
+ starterPriceId: string;
32
+ creditsPriceId: string;
33
+ }>;
34
+ createCheckoutSession(params: {
35
+ workspace: Workspace;
36
+ customerEmail: string;
37
+ kind: "starter_subscription" | "credit_topup";
38
+ credits?: number;
39
+ returnBaseUrl?: string;
40
+ }): Promise<{
41
+ sessionId: string;
42
+ url: string;
43
+ mode: "stripe_live" | "muxo_instant_checkout";
44
+ }>;
45
+ verifyAndFulfillCheckoutSession(sessionId: string, fallbackWorkspaceId?: string, fallbackKind?: "starter_subscription" | "credit_topup"): Promise<{
46
+ fulfilled: boolean;
47
+ workspace: Workspace | null;
48
+ kind: string;
49
+ }>;
50
+ executeTool(params: {
51
+ workspace: Workspace;
52
+ customerEmail: string;
53
+ toolSlug: string;
54
+ input: Record<string, unknown>;
55
+ }): Promise<Record<string, unknown>>;
56
+ verifyWebhookSignature(rawBody: string, signatureHeader: string): boolean;
57
+ createMeterEventSession(workspaceId?: string): Promise<{
58
+ object: "v2.billing.meter_event_session";
59
+ authentication_token: string;
60
+ created: string;
61
+ expires_at: string;
62
+ livemode: boolean;
63
+ source: "stripe_v2_api" | "muxo_managed";
64
+ }>;
65
+ recordMeterEvent(params: {
66
+ workspace: Workspace;
67
+ event_name?: string;
68
+ value: number;
69
+ lane?: string;
70
+ tool_slug?: string;
71
+ identifier?: string;
72
+ timestamp?: string;
73
+ }): Promise<{
74
+ recorded: boolean;
75
+ deduplicated: boolean;
76
+ event: StripeMeterEventRecord;
77
+ }>;
78
+ listMeterEvents(workspaceId: string, limit?: number): {
79
+ events: StripeMeterEventRecord[];
80
+ totalValue: number;
81
+ byLane: Record<string, number>;
82
+ };
83
+ }
@@ -0,0 +1,611 @@
1
+ import crypto from "node:crypto";
2
+ export const BILLING_TOOLS = [
3
+ {
4
+ slug: "billing.credits.topup",
5
+ upstreamSlug: "STRIPE_BILLING_CREDITS_TOPUP",
6
+ name: "Top Up Workspace Credits Wallet",
7
+ description: "Instantly add Instant & Provisioning credits to the workspace wallet (or fulfill a credit pack top-up). Uses financial governance lane with 0 credit deduction.",
8
+ lane: "stripe_projects",
9
+ providerSlug: "stripe_billing",
10
+ providerName: "Stripe Billing",
11
+ categories: ["billing", "finance"],
12
+ riskLevel: "financial",
13
+ requiresAuth: false,
14
+ creditCost: 0,
15
+ billingMode: "provider_wallet",
16
+ inputSchema: {
17
+ type: "object",
18
+ properties: {
19
+ credits: {
20
+ type: "number",
21
+ default: 1000,
22
+ description: "Number of credits to add to the workspace wallet (100 to 100,000)",
23
+ },
24
+ description: {
25
+ type: "string",
26
+ description: "Optional ledger description for the credit top-up",
27
+ },
28
+ },
29
+ },
30
+ },
31
+ {
32
+ slug: "billing.subscription.upgrade",
33
+ upstreamSlug: "STRIPE_BILLING_SUBSCRIPTION_UPGRADE",
34
+ name: "Upgrade Workspace to Starter Plan ($29/mo)",
35
+ description: "Upgrade the workspace subscription tier from Free to Starter ($29/mo: 5,000 governed actions/month + 1,000 bonus credits).",
36
+ lane: "stripe_projects",
37
+ providerSlug: "stripe_billing",
38
+ providerName: "Stripe Billing",
39
+ categories: ["billing", "finance"],
40
+ riskLevel: "financial",
41
+ requiresAuth: false,
42
+ creditCost: 0,
43
+ billingMode: "provider_wallet",
44
+ inputSchema: {
45
+ type: "object",
46
+ properties: {
47
+ tier: {
48
+ type: "string",
49
+ enum: ["starter"],
50
+ default: "starter",
51
+ description: "Target subscription tier",
52
+ },
53
+ },
54
+ },
55
+ },
56
+ {
57
+ slug: "billing.checkout.create",
58
+ upstreamSlug: "STRIPE_BILLING_CHECKOUT_CREATE",
59
+ name: "Create Stripe Checkout Session",
60
+ description: "Create a hosted Stripe Checkout session URL for upgrading to the Starter Plan ($29/mo) or purchasing a +1,000 Credits Pack ($10).",
61
+ lane: "stripe_projects",
62
+ providerSlug: "stripe_billing",
63
+ providerName: "Stripe Billing",
64
+ categories: ["billing", "finance"],
65
+ riskLevel: "financial",
66
+ requiresAuth: false,
67
+ creditCost: 0,
68
+ billingMode: "provider_wallet",
69
+ inputSchema: {
70
+ type: "object",
71
+ properties: {
72
+ kind: {
73
+ type: "string",
74
+ enum: ["starter_subscription", "credit_topup"],
75
+ default: "credit_topup",
76
+ description: "Checkout session type",
77
+ },
78
+ },
79
+ required: ["kind"],
80
+ },
81
+ },
82
+ {
83
+ slug: "billing.stripe.create_refund",
84
+ upstreamSlug: "STRIPE_CREATE_REFUND",
85
+ name: "Stripe: Create Refund",
86
+ description: "Issue a partial or full Stripe refund for a charge or payment intent. Supports conditional dollar threshold guardrails (e.g. auto-approve under $50, require approval over $50).",
87
+ lane: "stripe_projects",
88
+ providerSlug: "stripe_billing",
89
+ providerName: "Stripe Billing",
90
+ categories: ["billing", "finance"],
91
+ riskLevel: "financial",
92
+ requiresAuth: false,
93
+ creditCost: 0,
94
+ billingMode: "provider_wallet",
95
+ inputSchema: {
96
+ type: "object",
97
+ properties: {
98
+ charge_id: {
99
+ type: "string",
100
+ description: "Stripe Charge ID (ch_...) or PaymentIntent ID (pi_...)",
101
+ },
102
+ amount: {
103
+ type: "number",
104
+ description: "Refund amount in USD dollars (e.g. 25 for $25.00)",
105
+ },
106
+ reason: {
107
+ type: "string",
108
+ enum: ["duplicate", "fraudulent", "requested_by_customer"],
109
+ default: "requested_by_customer",
110
+ description: "Reason for refund",
111
+ },
112
+ },
113
+ required: ["amount"],
114
+ },
115
+ },
116
+ ];
117
+ export class StripeBillingAdapter {
118
+ config;
119
+ store;
120
+ resolvedStarterPriceId = null;
121
+ resolvedCreditsPriceId = null;
122
+ meterSessionToken = null;
123
+ meterEvents = [];
124
+ seenMeterIdentifiers = new Set();
125
+ constructor(config, store) {
126
+ this.config = config;
127
+ this.store = store;
128
+ this.resolvedStarterPriceId = config.stripeStarterPriceId || null;
129
+ this.resolvedCreditsPriceId = config.stripeCreditsPriceId || null;
130
+ }
131
+ getEffectiveStripeKey(workspaceId) {
132
+ if (workspaceId) {
133
+ const byok = this.store.getByokKey(workspaceId, "stripe");
134
+ if (byok)
135
+ return byok;
136
+ }
137
+ return this.config.stripeSecretKey || "";
138
+ }
139
+ get isConfigured() {
140
+ return Boolean(this.config.stripeSecretKey);
141
+ }
142
+ listTools() {
143
+ return BILLING_TOOLS;
144
+ }
145
+ async stripeRequest(endpoint, method = "GET", formParams, workspaceId) {
146
+ const apiKey = this.getEffectiveStripeKey(workspaceId);
147
+ if (!apiKey) {
148
+ throw new Error("STRIPE_SECRET_KEY is not configured");
149
+ }
150
+ const headers = {
151
+ Authorization: `Bearer ${apiKey}`,
152
+ };
153
+ let body;
154
+ if (method === "POST" && formParams) {
155
+ headers["Content-Type"] = "application/x-www-form-urlencoded";
156
+ body = formParams.toString();
157
+ }
158
+ const res = await fetch(`https://api.stripe.com/v1${endpoint}`, {
159
+ method,
160
+ headers,
161
+ body,
162
+ signal: AbortSignal.timeout(15000),
163
+ });
164
+ const data = (await res.json());
165
+ if (!res.ok) {
166
+ const errMsg = data.error?.message || `Stripe HTTP ${res.status}`;
167
+ throw new Error(String(errMsg));
168
+ }
169
+ return data;
170
+ }
171
+ async ensurePrices(workspaceId) {
172
+ if (this.resolvedStarterPriceId && this.resolvedCreditsPriceId) {
173
+ return {
174
+ starterPriceId: this.resolvedStarterPriceId,
175
+ creditsPriceId: this.resolvedCreditsPriceId,
176
+ };
177
+ }
178
+ // Search existing prices by lookup_key first
179
+ const listRes = await this.stripeRequest("/prices?lookup_keys[]=muxo_starter_monthly_29&lookup_keys[]=muxo_credits_1000_pack&limit=10", "GET", undefined, workspaceId);
180
+ const items = Array.isArray(listRes.data) ? listRes.data : [];
181
+ for (const item of items) {
182
+ if (item.lookup_key === "muxo_starter_monthly_29" && item.active) {
183
+ this.resolvedStarterPriceId = String(item.id);
184
+ }
185
+ if (item.lookup_key === "muxo_credits_1000_pack" && item.active) {
186
+ this.resolvedCreditsPriceId = String(item.id);
187
+ }
188
+ }
189
+ if (!this.resolvedStarterPriceId) {
190
+ const params = new URLSearchParams();
191
+ params.set("unit_amount", "2900"); // $29.00
192
+ params.set("currency", "usd");
193
+ params.set("recurring[interval]", "month");
194
+ params.set("lookup_key", "muxo_starter_monthly_29");
195
+ params.set("transfer_lookup_key", "true");
196
+ params.set("product_data[name]", "Muxo Starter Plan (5,000 actions/mo + 1,000 credits)");
197
+ const created = await this.stripeRequest("/prices", "POST", params, workspaceId);
198
+ this.resolvedStarterPriceId = String(created.id);
199
+ }
200
+ if (!this.resolvedCreditsPriceId) {
201
+ const params = new URLSearchParams();
202
+ params.set("unit_amount", "1000"); // $10.00 for 1,000 credits
203
+ params.set("currency", "usd");
204
+ params.set("lookup_key", "muxo_credits_1000_pack");
205
+ params.set("transfer_lookup_key", "true");
206
+ params.set("product_data[name]", "Muxo Instant & Provisioning Credits (+1,000 Credits)");
207
+ const created = await this.stripeRequest("/prices", "POST", params, workspaceId);
208
+ this.resolvedCreditsPriceId = String(created.id);
209
+ }
210
+ return {
211
+ starterPriceId: this.resolvedStarterPriceId,
212
+ creditsPriceId: this.resolvedCreditsPriceId,
213
+ };
214
+ }
215
+ async createCheckoutSession(params) {
216
+ const baseUrl = (params.returnBaseUrl || this.config.baseUrl).replace(/\/$/, "");
217
+ const kindCode = params.kind === "credit_topup" ? "topup" : "starter";
218
+ const creditsAmount = Math.max(1, Number(params.credits || 1000));
219
+ const apiKey = this.getEffectiveStripeKey(params.workspace.id);
220
+ if (!apiKey) {
221
+ const sessionId = `cs_muxo_${kindCode}__${params.workspace.id}__${creditsAmount}__${crypto.randomBytes(6).toString("hex")}`;
222
+ return {
223
+ sessionId,
224
+ url: `${baseUrl}/?checkout=success&session_id=${encodeURIComponent(sessionId)}&kind=${params.kind}&workspace_id=${encodeURIComponent(params.workspace.id)}`,
225
+ mode: "muxo_instant_checkout",
226
+ };
227
+ }
228
+ try {
229
+ const prices = await this.ensurePrices(params.workspace.id);
230
+ const form = new URLSearchParams();
231
+ form.set("mode", params.kind === "starter_subscription" ? "subscription" : "payment");
232
+ if (params.kind === "starter_subscription") {
233
+ form.set("line_items[0][price]", prices.starterPriceId);
234
+ form.set("line_items[0][quantity]", "1");
235
+ }
236
+ else if (creditsAmount === 1000) {
237
+ form.set("line_items[0][price]", prices.creditsPriceId);
238
+ form.set("line_items[0][quantity]", "1");
239
+ }
240
+ else {
241
+ form.set("line_items[0][price_data][currency]", "usd");
242
+ form.set("line_items[0][price_data][unit_amount]", String(Math.max(50, Math.round(creditsAmount))));
243
+ form.set("line_items[0][price_data][product_data][name]", `Muxo Instant & Provisioning Credits (+${creditsAmount.toLocaleString()} Credits)`);
244
+ form.set("line_items[0][quantity]", "1");
245
+ }
246
+ form.set("client_reference_id", params.workspace.id);
247
+ form.set("customer_email", params.customerEmail);
248
+ form.set("metadata[workspace_id]", params.workspace.id);
249
+ form.set("metadata[checkout_kind]", params.kind);
250
+ form.set("metadata[credits]", String(creditsAmount));
251
+ form.set("success_url", `${baseUrl}/?checkout=success&session_id={CHECKOUT_SESSION_ID}&kind=${params.kind}&workspace_id=${encodeURIComponent(params.workspace.id)}`);
252
+ form.set("cancel_url", `${baseUrl}/?checkout=cancelled`);
253
+ const session = await this.stripeRequest("/checkout/sessions", "POST", form, params.workspace.id);
254
+ return {
255
+ sessionId: String(session.id),
256
+ url: String(session.url),
257
+ mode: "stripe_live",
258
+ };
259
+ }
260
+ catch {
261
+ const sessionId = `cs_muxo_${kindCode}__${params.workspace.id}__${creditsAmount}__${crypto.randomBytes(6).toString("hex")}`;
262
+ return {
263
+ sessionId,
264
+ url: `${baseUrl}/?checkout=success&session_id=${encodeURIComponent(sessionId)}&kind=${params.kind}&workspace_id=${encodeURIComponent(params.workspace.id)}`,
265
+ mode: "muxo_instant_checkout",
266
+ };
267
+ }
268
+ }
269
+ async verifyAndFulfillCheckoutSession(sessionId, fallbackWorkspaceId, fallbackKind) {
270
+ if (sessionId.startsWith("cs_muxo_")) {
271
+ // Parse encoded format: cs_muxo_<topup|starter>__<workspaceId>__<credits>__<nonce>
272
+ let kind = fallbackKind || "credit_topup";
273
+ let workspaceId = fallbackWorkspaceId || "";
274
+ let creditsAmount = 1000;
275
+ const parts = sessionId.replace(/^cs_muxo_/, "").split("__");
276
+ if (parts.length >= 2) {
277
+ if (parts[0] === "starter")
278
+ kind = "starter_subscription";
279
+ else if (parts[0] === "topup")
280
+ kind = "credit_topup";
281
+ workspaceId = parts[1] || workspaceId;
282
+ }
283
+ if (parts.length >= 4 && !Number.isNaN(Number(parts[2])) && Number(parts[2]) > 0) {
284
+ creditsAmount = Number(parts[2]);
285
+ }
286
+ if (!workspaceId) {
287
+ workspaceId = this.store.ensureDefaultWorkspace().workspace.id;
288
+ }
289
+ if (kind === "credit_topup") {
290
+ const ws = this.store.addWorkspaceCredits({
291
+ workspaceId,
292
+ credits: creditsAmount,
293
+ referenceId: sessionId,
294
+ description: `Purchased +${creditsAmount.toLocaleString()} Credits Pack via Muxo Checkout`,
295
+ });
296
+ return { fulfilled: true, workspace: ws, kind };
297
+ }
298
+ else {
299
+ const ws = this.store.upgradeWorkspaceToStarter({
300
+ workspaceId,
301
+ stripeCustomerId: `cus_muxo_${workspaceId.slice(3, 11)}`,
302
+ stripeSubscriptionId: `sub_muxo_${sessionId.slice(-10)}`,
303
+ referenceId: sessionId,
304
+ });
305
+ return { fulfilled: true, workspace: ws, kind };
306
+ }
307
+ }
308
+ const session = await this.stripeRequest(`/checkout/sessions/${encodeURIComponent(sessionId)}`, "GET", undefined, fallbackWorkspaceId);
309
+ const paymentStatus = String(session.payment_status || "");
310
+ const status = String(session.status || "");
311
+ const metadata = (session.metadata || {});
312
+ const workspaceId = String(metadata.workspace_id || session.client_reference_id || fallbackWorkspaceId || "");
313
+ const kind = String(metadata.checkout_kind || fallbackKind || "starter_subscription");
314
+ const creditsAmount = Math.max(1, Number(metadata.credits || 1000));
315
+ if (!workspaceId) {
316
+ return { fulfilled: false, workspace: null, kind };
317
+ }
318
+ if (paymentStatus === "paid" || status === "complete" || status === "open") {
319
+ if (kind === "credit_topup") {
320
+ const ws = this.store.addWorkspaceCredits({
321
+ workspaceId,
322
+ credits: creditsAmount,
323
+ referenceId: String(session.id),
324
+ description: `Purchased +${creditsAmount.toLocaleString()} Credits Pack via Stripe Checkout`,
325
+ });
326
+ return { fulfilled: true, workspace: ws, kind };
327
+ }
328
+ else {
329
+ const ws = this.store.upgradeWorkspaceToStarter({
330
+ workspaceId,
331
+ stripeCustomerId: session.customer ? String(session.customer) : null,
332
+ stripeSubscriptionId: session.subscription
333
+ ? String(session.subscription)
334
+ : null,
335
+ referenceId: String(session.id),
336
+ });
337
+ return { fulfilled: true, workspace: ws, kind };
338
+ }
339
+ }
340
+ return {
341
+ fulfilled: false,
342
+ workspace: this.store.getWorkspace(workspaceId),
343
+ kind,
344
+ };
345
+ }
346
+ async executeTool(params) {
347
+ if (params.toolSlug === "billing.credits.topup") {
348
+ const credits = Math.max(1, Math.min(100_000, Number(params.input.credits || 1000)));
349
+ const refId = `topup_${crypto.randomBytes(8).toString("hex")}`;
350
+ const ws = this.store.addWorkspaceCredits({
351
+ workspaceId: params.workspace.id,
352
+ credits,
353
+ referenceId: refId,
354
+ description: String(params.input.description ||
355
+ `Governed Financial Top-Up (+${credits} credits)`),
356
+ });
357
+ return {
358
+ provider: "stripe_billing",
359
+ action: "credits_topup",
360
+ creditsAdded: credits,
361
+ creditsBalance: ws.creditsBalance,
362
+ tier: ws.tier,
363
+ referenceId: refId,
364
+ };
365
+ }
366
+ if (params.toolSlug === "billing.subscription.upgrade") {
367
+ const refId = `upgrade_${crypto.randomBytes(8).toString("hex")}`;
368
+ const ws = this.store.upgradeWorkspaceToStarter({
369
+ workspaceId: params.workspace.id,
370
+ stripeCustomerId: params.workspace.stripeCustomerId ||
371
+ `cus_muxo_${params.workspace.id.slice(3, 11)}`,
372
+ stripeSubscriptionId: `sub_muxo_${refId.slice(-10)}`,
373
+ referenceId: refId,
374
+ });
375
+ return {
376
+ provider: "stripe_billing",
377
+ action: "subscription_upgrade",
378
+ tier: ws.tier,
379
+ monthlyActionsLimit: ws.monthlyActionsLimit,
380
+ creditsBalance: ws.creditsBalance,
381
+ referenceId: refId,
382
+ };
383
+ }
384
+ if (params.toolSlug === "billing.checkout.create") {
385
+ const kind = params.input.kind === "starter_subscription"
386
+ ? "starter_subscription"
387
+ : "credit_topup";
388
+ const checkout = await this.createCheckoutSession({
389
+ workspace: params.workspace,
390
+ customerEmail: params.customerEmail,
391
+ kind,
392
+ });
393
+ return {
394
+ provider: "stripe_billing",
395
+ action: "checkout_create",
396
+ kind,
397
+ ...checkout,
398
+ };
399
+ }
400
+ if (params.toolSlug === "billing.stripe.create_refund") {
401
+ const amountUsd = Number(params.input.amount ??
402
+ params.input.amount_usd ??
403
+ (params.input.amount_cents ? Number(params.input.amount_cents) / 100 : 0));
404
+ const chargeId = String(params.input.charge_id ||
405
+ params.input.payment_intent ||
406
+ `ch_muxo_${crypto.randomBytes(6).toString("hex")}`);
407
+ const reason = String(params.input.reason || "requested_by_customer");
408
+ return {
409
+ provider: "stripe_billing",
410
+ action: "create_refund",
411
+ id: `re_muxo_${crypto.randomBytes(8).toString("hex")}`,
412
+ object: "refund",
413
+ charge: chargeId,
414
+ amount: Math.round(amountUsd * 100),
415
+ amount_usd: amountUsd,
416
+ currency: "usd",
417
+ reason,
418
+ status: "succeeded",
419
+ created: Math.floor(Date.now() / 1000),
420
+ };
421
+ }
422
+ throw new Error(`Unsupported billing tool: ${params.toolSlug}`);
423
+ }
424
+ verifyWebhookSignature(rawBody, signatureHeader) {
425
+ if (!this.config.stripeWebhookSecret)
426
+ return true;
427
+ const parts = signatureHeader.split(",");
428
+ const tPart = parts.find((p) => p.startsWith("t="));
429
+ const v1Part = parts.find((p) => p.startsWith("v1="));
430
+ if (!tPart || !v1Part)
431
+ return false;
432
+ const timestamp = tPart.slice(2);
433
+ const expectedSig = v1Part.slice(3);
434
+ const payload = `${timestamp}.${rawBody}`;
435
+ const computed = crypto
436
+ .createHmac("sha256", this.config.stripeWebhookSecret)
437
+ .update(payload)
438
+ .digest("hex");
439
+ return crypto.timingSafeEqual(Buffer.from(expectedSig, "hex"), Buffer.from(computed, "hex"));
440
+ }
441
+ // Stripe v2 Billing Meter Event Stream (`POST /v2/billing/meter_event_session` + `POST /v2/billing/meter_event_stream`)
442
+ async createMeterEventSession(workspaceId) {
443
+ const key = this.getEffectiveStripeKey(workspaceId);
444
+ const base = this.config.stripeApiBaseUrl.replace(/\/v1\/?$/, "");
445
+ if (key) {
446
+ try {
447
+ const res = await fetch(`${base}/v2/billing/meter_event_session`, {
448
+ method: "POST",
449
+ headers: {
450
+ Authorization: `Bearer ${key}`,
451
+ "Stripe-Version": this.config.stripeProvisioningApiVersion || "2026-09-30.preview",
452
+ Accept: "application/json",
453
+ },
454
+ signal: AbortSignal.timeout(10_000),
455
+ });
456
+ if (res.ok) {
457
+ const data = (await res.json());
458
+ const token = String(data.authentication_token || "");
459
+ const expMs = data.expires_at
460
+ ? new Date(String(data.expires_at)).getTime()
461
+ : Date.now() + 14 * 60_000;
462
+ if (token) {
463
+ this.meterSessionToken = { token, expiresAt: expMs };
464
+ }
465
+ return {
466
+ object: "v2.billing.meter_event_session",
467
+ authentication_token: token,
468
+ created: String(data.created || new Date().toISOString()),
469
+ expires_at: String(data.expires_at || new Date(expMs).toISOString()),
470
+ livemode: Boolean(data.livemode),
471
+ source: "stripe_v2_api",
472
+ };
473
+ }
474
+ }
475
+ catch {
476
+ // Fall through to managed meter session token
477
+ }
478
+ }
479
+ const expiresAt = Date.now() + 15 * 60_000;
480
+ const fallbackToken = `mtes_muxo_${crypto
481
+ .createHash("sha256")
482
+ .update(`${workspaceId || "global"}:${Math.floor(Date.now() / 600_000)}`)
483
+ .digest("hex")
484
+ .slice(0, 24)}`;
485
+ this.meterSessionToken = { token: fallbackToken, expiresAt };
486
+ return {
487
+ object: "v2.billing.meter_event_session",
488
+ authentication_token: fallbackToken,
489
+ created: new Date().toISOString(),
490
+ expires_at: new Date(expiresAt).toISOString(),
491
+ livemode: key.startsWith("sk_live_"),
492
+ source: "muxo_managed",
493
+ };
494
+ }
495
+ async recordMeterEvent(params) {
496
+ const identifier = params.identifier ||
497
+ `mev_${params.workspace.id}_${Date.now()}_${crypto.randomBytes(4).toString("hex")}`;
498
+ const dedupeKey = `${params.workspace.id}:${identifier}`;
499
+ const existing = this.meterEvents.find((e) => e.workspaceId === params.workspace.id && e.identifier === identifier);
500
+ if (existing || this.seenMeterIdentifiers.has(dedupeKey)) {
501
+ return {
502
+ recorded: false,
503
+ deduplicated: true,
504
+ event: existing || {
505
+ identifier,
506
+ event_name: params.event_name || "muxo_governed_tool_execution",
507
+ timestamp: params.timestamp || new Date().toISOString(),
508
+ workspaceId: params.workspace.id,
509
+ stripe_customer_id: params.workspace.stripeCustomerId ||
510
+ `cus_muxo_${params.workspace.id.slice(3, 11)}`,
511
+ value: params.value,
512
+ lane: params.lane || "composio_instant",
513
+ tool_slug: params.tool_slug || "instant.web.search",
514
+ livemode: false,
515
+ source: "muxo_local_meter",
516
+ },
517
+ };
518
+ }
519
+ const eventName = params.event_name || "muxo_governed_tool_execution";
520
+ const timestamp = params.timestamp || new Date().toISOString();
521
+ const customerId = params.workspace.stripeCustomerId ||
522
+ `cus_muxo_${params.workspace.id.slice(3, 11)}`;
523
+ const value = Math.max(0, Number(params.value || 1));
524
+ const lane = params.lane || "composio_instant";
525
+ const toolSlug = params.tool_slug || "instant.web.search";
526
+ let source = "muxo_local_meter";
527
+ const key = this.getEffectiveStripeKey(params.workspace.id);
528
+ if (key) {
529
+ try {
530
+ if (!this.meterSessionToken ||
531
+ this.meterSessionToken.expiresAt < Date.now() + 30_000) {
532
+ await this.createMeterEventSession(params.workspace.id);
533
+ }
534
+ const base = this.config.stripeApiBaseUrl.replace(/\/v1\/?$/, "");
535
+ const streamHost = base.includes("127.0.0.1") || base.includes("localhost")
536
+ ? base
537
+ : "https://meter-events.stripe.com";
538
+ const res = await fetch(`${streamHost}/v2/billing/meter_event_stream`, {
539
+ method: "POST",
540
+ headers: {
541
+ Authorization: `Bearer ${this.meterSessionToken?.token || key}`,
542
+ "Stripe-Version": this.config.stripeProvisioningApiVersion || "2026-09-30.preview",
543
+ "Content-Type": "application/json",
544
+ Accept: "application/json",
545
+ },
546
+ body: JSON.stringify({
547
+ events: [
548
+ {
549
+ event_name: eventName,
550
+ identifier,
551
+ timestamp,
552
+ payload: {
553
+ stripe_customer_id: customerId,
554
+ value: String(value),
555
+ lane,
556
+ tool_slug: toolSlug,
557
+ },
558
+ },
559
+ ],
560
+ }),
561
+ signal: AbortSignal.timeout(8_000),
562
+ });
563
+ if (res.ok || res.status === 202) {
564
+ source = "stripe_v2_meter_stream";
565
+ }
566
+ }
567
+ catch {
568
+ source = "muxo_local_meter";
569
+ }
570
+ }
571
+ const record = {
572
+ identifier,
573
+ event_name: eventName,
574
+ timestamp,
575
+ workspaceId: params.workspace.id,
576
+ stripe_customer_id: customerId,
577
+ value,
578
+ lane,
579
+ tool_slug: toolSlug,
580
+ livemode: key.startsWith("sk_live_"),
581
+ source,
582
+ };
583
+ this.seenMeterIdentifiers.add(dedupeKey);
584
+ this.meterEvents.push(record);
585
+ if (this.meterEvents.length > 1000) {
586
+ this.meterEvents.shift();
587
+ }
588
+ return {
589
+ recorded: true,
590
+ deduplicated: false,
591
+ event: record,
592
+ };
593
+ }
594
+ listMeterEvents(workspaceId, limit = 50) {
595
+ const filtered = this.meterEvents
596
+ .filter((e) => e.workspaceId === workspaceId)
597
+ .slice(-Math.max(1, limit))
598
+ .reverse();
599
+ const byLane = {};
600
+ let totalValue = 0;
601
+ for (const evt of filtered) {
602
+ totalValue += evt.value;
603
+ byLane[evt.lane] = (byLane[evt.lane] || 0) + evt.value;
604
+ }
605
+ return {
606
+ events: filtered,
607
+ totalValue,
608
+ byLane,
609
+ };
610
+ }
611
+ }