@muxoai/platform 0.0.0-stage → 1.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (173) hide show
  1. package/ARCHITECTURE.md +111 -0
  2. package/README.md +53 -2
  3. package/dist/cli.d.ts +2 -0
  4. package/dist/cli.js +527 -0
  5. package/dist/config.d.ts +20 -0
  6. package/dist/config.js +89 -0
  7. package/dist/engine.d.ts +128 -0
  8. package/dist/engine.js +709 -0
  9. package/dist/index.d.ts +7 -0
  10. package/dist/index.js +7 -0
  11. package/dist/mcp.d.ts +9 -0
  12. package/dist/mcp.js +401 -0
  13. package/dist/providers/composio-instant.d.ts +14 -0
  14. package/dist/providers/composio-instant.js +372 -0
  15. package/dist/providers/composio-sdk.d.ts +41 -0
  16. package/dist/providers/composio-sdk.js +514 -0
  17. package/dist/providers/microsoft-governance.d.ts +66 -0
  18. package/dist/providers/microsoft-governance.js +415 -0
  19. package/dist/providers/stripe-billing.d.ts +31 -0
  20. package/dist/providers/stripe-billing.js +168 -0
  21. package/dist/providers/stripe-projects.d.ts +53 -0
  22. package/dist/providers/stripe-projects.js +607 -0
  23. package/dist/providers/supermemory.d.ts +64 -0
  24. package/dist/providers/supermemory.js +224 -0
  25. package/dist/sdk.d.ts +115 -0
  26. package/dist/sdk.js +117 -0
  27. package/dist/server.d.ts +10 -0
  28. package/dist/server.js +816 -0
  29. package/dist/store.d.ts +200 -0
  30. package/dist/store.js +1260 -0
  31. package/dist/types.d.ts +273 -0
  32. package/dist/types.js +1 -0
  33. package/dist/ui/console-html.d.ts +2 -0
  34. package/dist/ui/console-html.js +2153 -0
  35. package/package.json +74 -4
  36. package/plugins/muxo/.app.json +8 -0
  37. package/plugins/muxo/.claude-plugin/plugin.json +16 -0
  38. package/plugins/muxo/.codex-plugin/plugin.json +51 -0
  39. package/plugins/muxo/.mcp.json +8 -0
  40. package/plugins/muxo/assets/logo.png +0 -0
  41. package/plugins/muxo/assets/logo.svg +6 -0
  42. package/plugins/muxo/hooks/hooks.json +27 -0
  43. package/plugins/muxo/hooks/session-start.sh +85 -0
  44. package/plugins/muxo/hooks/user-prompt-submit.sh +45 -0
  45. package/plugins/muxo/skills/muxo/SKILL.md +25 -0
  46. package/plugins/muxo/skills/muxo/references/cli.md +57 -0
  47. package/plugins/muxo/skills/muxo/references/mcp.md +25 -0
  48. package/src/catalogues/stripe-projects-catalog.json +9832 -0
  49. package/vendor/microsoft-governance/README.md +363 -0
  50. package/vendor/microsoft-governance/dist/audit.d.ts +26 -0
  51. package/vendor/microsoft-governance/dist/audit.d.ts.map +1 -0
  52. package/vendor/microsoft-governance/dist/audit.js +107 -0
  53. package/vendor/microsoft-governance/dist/audit.js.map +1 -0
  54. package/vendor/microsoft-governance/dist/cascade-containment.d.ts +84 -0
  55. package/vendor/microsoft-governance/dist/cascade-containment.d.ts.map +1 -0
  56. package/vendor/microsoft-governance/dist/cascade-containment.js +387 -0
  57. package/vendor/microsoft-governance/dist/cascade-containment.js.map +1 -0
  58. package/vendor/microsoft-governance/dist/client.d.ts +34 -0
  59. package/vendor/microsoft-governance/dist/client.d.ts.map +1 -0
  60. package/vendor/microsoft-governance/dist/client.js +112 -0
  61. package/vendor/microsoft-governance/dist/client.js.map +1 -0
  62. package/vendor/microsoft-governance/dist/context-poisoning.d.ts +58 -0
  63. package/vendor/microsoft-governance/dist/context-poisoning.d.ts.map +1 -0
  64. package/vendor/microsoft-governance/dist/context-poisoning.js +410 -0
  65. package/vendor/microsoft-governance/dist/context-poisoning.js.map +1 -0
  66. package/vendor/microsoft-governance/dist/credential-vault.d.ts +213 -0
  67. package/vendor/microsoft-governance/dist/credential-vault.d.ts.map +1 -0
  68. package/vendor/microsoft-governance/dist/credential-vault.js +567 -0
  69. package/vendor/microsoft-governance/dist/credential-vault.js.map +1 -0
  70. package/vendor/microsoft-governance/dist/discovery.d.ts +80 -0
  71. package/vendor/microsoft-governance/dist/discovery.d.ts.map +1 -0
  72. package/vendor/microsoft-governance/dist/discovery.js +404 -0
  73. package/vendor/microsoft-governance/dist/discovery.js.map +1 -0
  74. package/vendor/microsoft-governance/dist/encryption/channel.d.ts +29 -0
  75. package/vendor/microsoft-governance/dist/encryption/channel.d.ts.map +1 -0
  76. package/vendor/microsoft-governance/dist/encryption/channel.js +78 -0
  77. package/vendor/microsoft-governance/dist/encryption/channel.js.map +1 -0
  78. package/vendor/microsoft-governance/dist/encryption/index.d.ts +9 -0
  79. package/vendor/microsoft-governance/dist/encryption/index.d.ts.map +1 -0
  80. package/vendor/microsoft-governance/dist/encryption/index.js +23 -0
  81. package/vendor/microsoft-governance/dist/encryption/index.js.map +1 -0
  82. package/vendor/microsoft-governance/dist/encryption/mesh-client.d.ts +267 -0
  83. package/vendor/microsoft-governance/dist/encryption/mesh-client.d.ts.map +1 -0
  84. package/vendor/microsoft-governance/dist/encryption/mesh-client.js +1001 -0
  85. package/vendor/microsoft-governance/dist/encryption/mesh-client.js.map +1 -0
  86. package/vendor/microsoft-governance/dist/encryption/ratchet.d.ts +38 -0
  87. package/vendor/microsoft-governance/dist/encryption/ratchet.d.ts.map +1 -0
  88. package/vendor/microsoft-governance/dist/encryption/ratchet.js +223 -0
  89. package/vendor/microsoft-governance/dist/encryption/ratchet.js.map +1 -0
  90. package/vendor/microsoft-governance/dist/encryption/registry-client.d.ts +136 -0
  91. package/vendor/microsoft-governance/dist/encryption/registry-client.d.ts.map +1 -0
  92. package/vendor/microsoft-governance/dist/encryption/registry-client.js +369 -0
  93. package/vendor/microsoft-governance/dist/encryption/registry-client.js.map +1 -0
  94. package/vendor/microsoft-governance/dist/encryption/x3dh.d.ts +80 -0
  95. package/vendor/microsoft-governance/dist/encryption/x3dh.d.ts.map +1 -0
  96. package/vendor/microsoft-governance/dist/encryption/x3dh.js +238 -0
  97. package/vendor/microsoft-governance/dist/encryption/x3dh.js.map +1 -0
  98. package/vendor/microsoft-governance/dist/framework-adapter.d.ts +63 -0
  99. package/vendor/microsoft-governance/dist/framework-adapter.d.ts.map +1 -0
  100. package/vendor/microsoft-governance/dist/framework-adapter.js +253 -0
  101. package/vendor/microsoft-governance/dist/framework-adapter.js.map +1 -0
  102. package/vendor/microsoft-governance/dist/identity.d.ts +124 -0
  103. package/vendor/microsoft-governance/dist/identity.d.ts.map +1 -0
  104. package/vendor/microsoft-governance/dist/identity.js +446 -0
  105. package/vendor/microsoft-governance/dist/identity.js.map +1 -0
  106. package/vendor/microsoft-governance/dist/index.d.ts +39 -0
  107. package/vendor/microsoft-governance/dist/index.d.ts.map +1 -0
  108. package/vendor/microsoft-governance/dist/index.js +95 -0
  109. package/vendor/microsoft-governance/dist/index.js.map +1 -0
  110. package/vendor/microsoft-governance/dist/kill-switch.d.ts +22 -0
  111. package/vendor/microsoft-governance/dist/kill-switch.d.ts.map +1 -0
  112. package/vendor/microsoft-governance/dist/kill-switch.js +60 -0
  113. package/vendor/microsoft-governance/dist/kill-switch.js.map +1 -0
  114. package/vendor/microsoft-governance/dist/lifecycle.d.ts +50 -0
  115. package/vendor/microsoft-governance/dist/lifecycle.d.ts.map +1 -0
  116. package/vendor/microsoft-governance/dist/lifecycle.js +113 -0
  117. package/vendor/microsoft-governance/dist/lifecycle.js.map +1 -0
  118. package/vendor/microsoft-governance/dist/mcp.d.ts +41 -0
  119. package/vendor/microsoft-governance/dist/mcp.d.ts.map +1 -0
  120. package/vendor/microsoft-governance/dist/mcp.js +233 -0
  121. package/vendor/microsoft-governance/dist/mcp.js.map +1 -0
  122. package/vendor/microsoft-governance/dist/metrics.d.ts +123 -0
  123. package/vendor/microsoft-governance/dist/metrics.d.ts.map +1 -0
  124. package/vendor/microsoft-governance/dist/metrics.js +289 -0
  125. package/vendor/microsoft-governance/dist/metrics.js.map +1 -0
  126. package/vendor/microsoft-governance/dist/oci-manifest.d.ts +49 -0
  127. package/vendor/microsoft-governance/dist/oci-manifest.d.ts.map +1 -0
  128. package/vendor/microsoft-governance/dist/oci-manifest.js +182 -0
  129. package/vendor/microsoft-governance/dist/oci-manifest.js.map +1 -0
  130. package/vendor/microsoft-governance/dist/policy-backends/cedar.d.ts +15 -0
  131. package/vendor/microsoft-governance/dist/policy-backends/cedar.d.ts.map +1 -0
  132. package/vendor/microsoft-governance/dist/policy-backends/cedar.js +88 -0
  133. package/vendor/microsoft-governance/dist/policy-backends/cedar.js.map +1 -0
  134. package/vendor/microsoft-governance/dist/policy-backends/opa.d.ts +17 -0
  135. package/vendor/microsoft-governance/dist/policy-backends/opa.d.ts.map +1 -0
  136. package/vendor/microsoft-governance/dist/policy-backends/opa.js +74 -0
  137. package/vendor/microsoft-governance/dist/policy-backends/opa.js.map +1 -0
  138. package/vendor/microsoft-governance/dist/policy.d.ts +77 -0
  139. package/vendor/microsoft-governance/dist/policy.d.ts.map +1 -0
  140. package/vendor/microsoft-governance/dist/policy.js +760 -0
  141. package/vendor/microsoft-governance/dist/policy.js.map +1 -0
  142. package/vendor/microsoft-governance/dist/prompt-defense.d.ts +37 -0
  143. package/vendor/microsoft-governance/dist/prompt-defense.d.ts.map +1 -0
  144. package/vendor/microsoft-governance/dist/prompt-defense.js +229 -0
  145. package/vendor/microsoft-governance/dist/prompt-defense.js.map +1 -0
  146. package/vendor/microsoft-governance/dist/protocol-facets.d.ts +87 -0
  147. package/vendor/microsoft-governance/dist/protocol-facets.d.ts.map +1 -0
  148. package/vendor/microsoft-governance/dist/protocol-facets.js +728 -0
  149. package/vendor/microsoft-governance/dist/protocol-facets.js.map +1 -0
  150. package/vendor/microsoft-governance/dist/rings.d.ts +17 -0
  151. package/vendor/microsoft-governance/dist/rings.d.ts.map +1 -0
  152. package/vendor/microsoft-governance/dist/rings.js +61 -0
  153. package/vendor/microsoft-governance/dist/rings.js.map +1 -0
  154. package/vendor/microsoft-governance/dist/sandbox.d.ts +61 -0
  155. package/vendor/microsoft-governance/dist/sandbox.d.ts.map +1 -0
  156. package/vendor/microsoft-governance/dist/sandbox.js +199 -0
  157. package/vendor/microsoft-governance/dist/sandbox.js.map +1 -0
  158. package/vendor/microsoft-governance/dist/surface-parity.d.ts +45 -0
  159. package/vendor/microsoft-governance/dist/surface-parity.d.ts.map +1 -0
  160. package/vendor/microsoft-governance/dist/surface-parity.js +216 -0
  161. package/vendor/microsoft-governance/dist/surface-parity.js.map +1 -0
  162. package/vendor/microsoft-governance/dist/trust.d.ts +28 -0
  163. package/vendor/microsoft-governance/dist/trust.d.ts.map +1 -0
  164. package/vendor/microsoft-governance/dist/trust.js +209 -0
  165. package/vendor/microsoft-governance/dist/trust.js.map +1 -0
  166. package/vendor/microsoft-governance/dist/types.d.ts +422 -0
  167. package/vendor/microsoft-governance/dist/types.d.ts.map +1 -0
  168. package/vendor/microsoft-governance/dist/types.js +29 -0
  169. package/vendor/microsoft-governance/dist/types.js.map +1 -0
  170. package/vendor/microsoft-governance/dist/verify.d.ts +135 -0
  171. package/vendor/microsoft-governance/dist/verify.d.ts.map +1 -0
  172. package/vendor/microsoft-governance/dist/verify.js +356 -0
  173. package/vendor/microsoft-governance/dist/verify.js.map +1 -0
package/dist/engine.js ADDED
@@ -0,0 +1,709 @@
1
+ import { ComposioInstantAdapter } from "./providers/composio-instant.js";
2
+ import { ComposioSdkAdapter } from "./providers/composio-sdk.js";
3
+ import { MicrosoftGovernanceAdapter } from "./providers/microsoft-governance.js";
4
+ import { StripeBillingAdapter } from "./providers/stripe-billing.js";
5
+ import { StripeProjectsAdapter } from "./providers/stripe-projects.js";
6
+ import { SupermemoryAdapter } from "./providers/supermemory.js";
7
+ export class MuxoEngine {
8
+ config;
9
+ store;
10
+ composioSdk;
11
+ composioInstant;
12
+ stripeProjects;
13
+ stripeBilling;
14
+ governance;
15
+ supermemory;
16
+ constructor(config, store) {
17
+ this.config = config;
18
+ this.store = store;
19
+ this.composioSdk = new ComposioSdkAdapter(config);
20
+ this.composioInstant = new ComposioInstantAdapter(config);
21
+ this.stripeProjects = new StripeProjectsAdapter(config);
22
+ this.stripeBilling = new StripeBillingAdapter(config, store);
23
+ this.governance = new MicrosoftGovernanceAdapter(config.vaultMasterKey);
24
+ this.supermemory = new SupermemoryAdapter(config);
25
+ }
26
+ // 1. get_profile
27
+ getProfile(ctx) {
28
+ return {
29
+ user: ctx.user,
30
+ actorId: ctx.actorId,
31
+ authType: ctx.authType,
32
+ workspaceId: ctx.workspace.id,
33
+ workspaceName: ctx.workspace.name,
34
+ tier: ctx.workspace.tier,
35
+ };
36
+ }
37
+ // 2. get_organization
38
+ getOrganization(ctx) {
39
+ const ws = this.store.getWorkspace(ctx.workspace.id);
40
+ const resources = this.store.listResources(ws.id);
41
+ const connections = this.store.listConnections(ws.id);
42
+ const supplierSettlementSummary = this.store.getSupplierSettlementSummary(ws.id);
43
+ return {
44
+ organization: {
45
+ id: ws.id,
46
+ name: ws.name,
47
+ slug: ws.slug,
48
+ tier: ws.tier,
49
+ usage: {
50
+ monthlyActionsUsed: ws.monthlyActionsUsed,
51
+ monthlyActionsLimit: ws.monthlyActionsLimit,
52
+ monthlyActionsRemaining: Math.max(0, ws.monthlyActionsLimit - ws.monthlyActionsUsed),
53
+ creditsBalance: ws.creditsBalance,
54
+ },
55
+ supplierSettlementSummary,
56
+ policy: ws.policy,
57
+ activeConnectionsCount: connections.filter((c) => c.status === "active").length,
58
+ provisionedResourcesCount: resources.filter((r) => r.status === "active").length,
59
+ projectsEnvironment: ws.projectsEnvName,
60
+ createdAt: ws.createdAt,
61
+ },
62
+ };
63
+ }
64
+ // 3. search_tools
65
+ async searchTools(params) {
66
+ const limit = Math.min(100, Math.max(1, Number(params.limit || 25)));
67
+ const lane = params.lane || "all";
68
+ const query = params.query?.trim();
69
+ const results = [];
70
+ if (lane === "all" || lane === "composio_instant") {
71
+ results.push(...this.composioInstant.searchTools(query, limit));
72
+ }
73
+ if (lane === "all" || lane === "composio_sdk") {
74
+ const sdkTools = await this.composioSdk.searchTools(query, limit);
75
+ results.push(...sdkTools);
76
+ }
77
+ if (lane === "all" || lane === "stripe_projects") {
78
+ results.push(...this.stripeProjects.searchTools(query, limit));
79
+ }
80
+ const filtered = params.riskLevel
81
+ ? results.filter((t) => t.riskLevel === params.riskLevel)
82
+ : results;
83
+ return {
84
+ tools: filtered.slice(0, limit),
85
+ total: filtered.length,
86
+ };
87
+ }
88
+ // 4. inspect_tool
89
+ async inspectTool(slug) {
90
+ const normalized = slug.trim();
91
+ const instant = this.composioInstant.inspectTool(normalized);
92
+ if (instant)
93
+ return instant;
94
+ const proj = this.stripeProjects.inspectTool(normalized);
95
+ if (proj)
96
+ return proj;
97
+ const sdk = await this.composioSdk.inspectTool(normalized);
98
+ if (sdk)
99
+ return sdk;
100
+ throw new Error(`Tool '${normalized}' not found in Muxo catalog. Use search_tools to discover valid slugs.`);
101
+ }
102
+ // 5. connection_status
103
+ async connectionStatus(ctx, params) {
104
+ if (params?.syncLive !== false) {
105
+ // Sync live Composio connected accounts for this workspace
106
+ const liveComposio = await this.composioSdk.listLiveConnections(ctx.workspace.id);
107
+ for (const c of liveComposio) {
108
+ this.store.upsertConnection({
109
+ workspaceId: ctx.workspace.id,
110
+ lane: "composio_sdk",
111
+ providerSlug: c.providerSlug,
112
+ providerName: c.providerName,
113
+ status: c.status,
114
+ externalAccountId: c.externalAccountId,
115
+ });
116
+ }
117
+ // Sync live Stripe Projects linked providers
118
+ try {
119
+ const projStatus = await this.stripeProjects.getLiveStatus();
120
+ for (const p of projStatus.providers) {
121
+ this.store.upsertConnection({
122
+ workspaceId: ctx.workspace.id,
123
+ lane: "stripe_projects",
124
+ providerSlug: p.slug,
125
+ providerName: p.name,
126
+ status: p.status,
127
+ externalAccountId: p.id,
128
+ redirectUrl: p.redirectUrl,
129
+ });
130
+ }
131
+ }
132
+ catch {
133
+ // Keep cached connections if CLI is busy
134
+ }
135
+ }
136
+ let connections = this.store.listConnections(ctx.workspace.id);
137
+ if (params?.provider) {
138
+ const target = params.provider.toLowerCase();
139
+ connections = connections.filter((c) => c.providerSlug.toLowerCase() === target ||
140
+ c.providerName.toLowerCase().includes(target));
141
+ }
142
+ return {
143
+ workspaceId: ctx.workspace.id,
144
+ instantWalletStatus: "active",
145
+ connections,
146
+ summary: {
147
+ total: connections.length,
148
+ active: connections.filter((c) => c.status === "active").length,
149
+ pending: connections.filter((c) => c.status === "pending").length,
150
+ expired: connections.filter((c) => c.status === "expired").length,
151
+ },
152
+ };
153
+ }
154
+ // 6. start_connection
155
+ async startConnection(ctx, params) {
156
+ const rawProvider = params.provider.trim().toLowerCase();
157
+ const isProjectsLane = params.lane === "stripe_projects" || rawProvider.startsWith("resource.");
158
+ const cleanSlug = rawProvider.replace(/^(app\.|resource\.)/, "");
159
+ if (isProjectsLane) {
160
+ const linked = await this.stripeProjects.linkProvider(cleanSlug);
161
+ const record = this.store.upsertConnection({
162
+ workspaceId: ctx.workspace.id,
163
+ lane: "stripe_projects",
164
+ providerSlug: linked.providerSlug,
165
+ providerName: linked.providerSlug.charAt(0).toUpperCase() +
166
+ linked.providerSlug.slice(1),
167
+ status: linked.status,
168
+ redirectUrl: linked.redirectUrl,
169
+ });
170
+ return { ...record, message: linked.message };
171
+ }
172
+ const started = await this.composioSdk.startConnection({
173
+ workspaceId: ctx.workspace.id,
174
+ providerSlug: cleanSlug,
175
+ callbackUrl: params.callbackUrl,
176
+ });
177
+ const record = this.store.upsertConnection({
178
+ workspaceId: ctx.workspace.id,
179
+ lane: "composio_sdk",
180
+ providerSlug: started.providerSlug,
181
+ providerName: started.providerName,
182
+ status: started.status,
183
+ externalAccountId: started.externalAccountId,
184
+ redirectUrl: started.redirectUrl,
185
+ metadata: { callbackUrl: started.callbackUrl },
186
+ });
187
+ return {
188
+ ...record,
189
+ callbackUrl: started.callbackUrl,
190
+ message: started.message,
191
+ };
192
+ }
193
+ // 6b. wait_for_connection (OAuth handoff polling & recovery, like COMPOSIO_WAIT_FOR_CONNECTIONS)
194
+ async waitForConnection(ctx, params) {
195
+ const cleanSlug = params.provider
196
+ .trim()
197
+ .toLowerCase()
198
+ .replace(/^(app\.|resource\.)/, "");
199
+ const timeoutMs = Math.min(120, Math.max(0, Number(params.timeoutSeconds ?? 15))) * 1000;
200
+ const pollIntervalMs = Math.min(5000, Math.max(200, Number(params.pollIntervalMs ?? 1500)));
201
+ const deadline = Date.now() + timeoutMs;
202
+ let current = this.store
203
+ .listConnections(ctx.workspace.id)
204
+ .find((c) => c.providerSlug.toLowerCase() === cleanSlug);
205
+ if (!current || (!current.redirectUrl && current.status !== "active")) {
206
+ try {
207
+ current = await this.startConnection(ctx, { provider: cleanSlug });
208
+ }
209
+ catch {
210
+ // Proceed with status check
211
+ }
212
+ }
213
+ while (true) {
214
+ const latestLocal = this.store
215
+ .listConnections(ctx.workspace.id)
216
+ .find((c) => c.providerSlug.toLowerCase() === cleanSlug);
217
+ if (latestLocal) {
218
+ current = latestLocal;
219
+ if (latestLocal.status === "active") {
220
+ return {
221
+ connected: true,
222
+ provider: cleanSlug,
223
+ status: "active",
224
+ connection: latestLocal,
225
+ redirectUrl: null,
226
+ message: `${latestLocal.providerName} OAuth handoff completed and connection is active.`,
227
+ };
228
+ }
229
+ }
230
+ if (current?.externalAccountId && current.lane === "composio_sdk") {
231
+ const direct = await this.composioSdk.getConnectedAccountStatus(current.externalAccountId);
232
+ if (direct && direct.status === "active") {
233
+ current = this.store.upsertConnection({
234
+ workspaceId: ctx.workspace.id,
235
+ lane: "composio_sdk",
236
+ providerSlug: cleanSlug,
237
+ providerName: cleanSlug.charAt(0).toUpperCase() + cleanSlug.slice(1),
238
+ status: "active",
239
+ externalAccountId: direct.id,
240
+ redirectUrl: null,
241
+ });
242
+ return {
243
+ connected: true,
244
+ provider: cleanSlug,
245
+ status: "active",
246
+ connection: current,
247
+ redirectUrl: null,
248
+ message: `${current.providerName} OAuth handoff completed and connection is active.`,
249
+ };
250
+ }
251
+ }
252
+ const synced = await this.connectionStatus(ctx, {
253
+ provider: cleanSlug,
254
+ syncLive: true,
255
+ });
256
+ const list = synced.connections || [];
257
+ const found = list.find((c) => c.providerSlug.toLowerCase() === cleanSlug);
258
+ if (found) {
259
+ current = found;
260
+ if (found.status === "active") {
261
+ return {
262
+ connected: true,
263
+ provider: cleanSlug,
264
+ status: "active",
265
+ connection: found,
266
+ redirectUrl: null,
267
+ message: `${found.providerName} connection is active and ready for governed execution.`,
268
+ };
269
+ }
270
+ }
271
+ if (Date.now() >= deadline) {
272
+ break;
273
+ }
274
+ await new Promise((r) => setTimeout(r, pollIntervalMs));
275
+ }
276
+ if (!current) {
277
+ current = await this.startConnection(ctx, { provider: cleanSlug });
278
+ }
279
+ return {
280
+ connected: false,
281
+ provider: cleanSlug,
282
+ status: current.status,
283
+ connection: current,
284
+ redirectUrl: current.redirectUrl,
285
+ message: current.redirectUrl
286
+ ? `Awaiting user OAuth authorization for ${current.providerName}. Open ${current.redirectUrl} in a browser, then re-run wait_for_connection.`
287
+ : `Connection for ${current.providerName} is currently ${current.status}.`,
288
+ };
289
+ }
290
+ // 6c. Browser OAuth callback handoff handler (GET /oauth/callback)
291
+ async handleOAuthCallback(params) {
292
+ const cleanSlug = params.provider
293
+ .trim()
294
+ .toLowerCase()
295
+ .replace(/^(app\.|resource\.)/, "");
296
+ const providerName = cleanSlug.charAt(0).toUpperCase() + cleanSlug.slice(1);
297
+ const ws = this.store.getWorkspace(params.workspaceId);
298
+ if (!ws) {
299
+ throw new Error(`Workspace '${params.workspaceId}' not found`);
300
+ }
301
+ const existing = this.store
302
+ .listConnections(ws.id)
303
+ .find((c) => c.providerSlug.toLowerCase() === cleanSlug);
304
+ const accountId = params.connectedAccountId || existing?.externalAccountId || null;
305
+ let resolvedStatus = "pending";
306
+ if (accountId) {
307
+ const live = await this.composioSdk.getConnectedAccountStatus(accountId);
308
+ if (live) {
309
+ resolvedStatus = live.status;
310
+ }
311
+ }
312
+ if (resolvedStatus !== "active") {
313
+ const liveList = await this.composioSdk.listLiveConnections(ws.id);
314
+ const match = liveList.find((c) => c.providerSlug === cleanSlug);
315
+ if (match) {
316
+ resolvedStatus = match.status;
317
+ }
318
+ }
319
+ const rawCallbackStatus = String(params.status || "").toLowerCase();
320
+ if (rawCallbackStatus === "success" ||
321
+ rawCallbackStatus === "active" ||
322
+ rawCallbackStatus === "connected") {
323
+ resolvedStatus = "active";
324
+ }
325
+ const updated = this.store.upsertConnection({
326
+ workspaceId: ws.id,
327
+ lane: "composio_sdk",
328
+ providerSlug: cleanSlug,
329
+ providerName,
330
+ status: resolvedStatus,
331
+ externalAccountId: accountId,
332
+ redirectUrl: resolvedStatus === "active" ? null : existing?.redirectUrl,
333
+ });
334
+ return {
335
+ ok: true,
336
+ workspaceId: ws.id,
337
+ providerSlug: cleanSlug,
338
+ providerName,
339
+ status: updated.status,
340
+ externalAccountId: updated.externalAccountId,
341
+ };
342
+ }
343
+ // 7. plan_action
344
+ async planAction(ctx, params) {
345
+ const ws = this.store.getWorkspace(ctx.workspace.id);
346
+ const tool = await this.inspectTool(params.toolSlug);
347
+ if (ws.monthlyActionsUsed >= ws.monthlyActionsLimit) {
348
+ throw new Error(`Monthly action limit reached (${ws.monthlyActionsUsed}/${ws.monthlyActionsLimit}). Upgrade to Starter ($29/mo) to unlock 5,000 actions/mo.`);
349
+ }
350
+ if (tool.creditCost > ws.creditsBalance) {
351
+ throw new Error(`Insufficient workspace credits for ${tool.slug} (requires ${tool.creditCost}, available ${ws.creditsBalance}). Top up credits or upgrade plan.`);
352
+ }
353
+ if (tool.creditCost > ws.policy.maxCreditsPerRun) {
354
+ throw new Error(`Tool credit cost (${tool.creditCost}) exceeds workspace policy maxCreditsPerRun (${ws.policy.maxCreditsPerRun}).`);
355
+ }
356
+ // 1. Evaluate Microsoft Agent Governance Pipeline:
357
+ // Agent -> McpSecurityScanner -> PolicyEngine -> AgentIdentity (Ed25519 DID) -> AuditLogger -> DecisionRecord
358
+ const decisionRecord = this.governance.evaluatePlan({
359
+ workspace: ws,
360
+ actorId: ctx.actorId,
361
+ tool,
362
+ input: params.input || {},
363
+ reason: params.reason || `Planned execution of ${tool.slug}`,
364
+ });
365
+ if (decisionRecord.verdict === "deny") {
366
+ throw new Error(`Microsoft Agent Governance denied plan for ${tool.slug} (rule: ${decisionRecord.matchedRule}): ${decisionRecord.reason}`);
367
+ }
368
+ // 2. Recall Supermemory v5 contextual brain for this workspace + tool intent
369
+ const memoryQuery = `${tool.slug} ${tool.name} ${params.reason || ""}`.trim();
370
+ const memoryContext = await this.supermemory.getContextForWorkspace(ws.id, memoryQuery);
371
+ const requiresHumanApproval = decisionRecord.verdict === "escalate" ||
372
+ (ws.policy.mode === "enforce" &&
373
+ ws.policy.requireApprovalFor.includes(tool.riskLevel));
374
+ const approvalStatus = requiresHumanApproval
375
+ ? "pending_approval"
376
+ : "auto_approved";
377
+ const plan = this.store.createPlan({
378
+ workspaceId: ws.id,
379
+ actorId: ctx.actorId,
380
+ toolSlug: tool.slug,
381
+ upstreamSlug: tool.upstreamSlug,
382
+ lane: tool.lane,
383
+ riskLevel: tool.riskLevel,
384
+ input: params.input || {},
385
+ reason: params.reason || `Planned execution of ${tool.slug}`,
386
+ creditCost: tool.creditCost,
387
+ approvalStatus,
388
+ decisionRecord,
389
+ memoryContext,
390
+ });
391
+ // 3. Check external user OAuth connection state for Connected Apps (composio_sdk)
392
+ let authHandoff;
393
+ if (tool.lane === "composio_sdk" && tool.requiresAuth) {
394
+ let existingConn = this.store
395
+ .listConnections(ws.id)
396
+ .find((c) => c.lane === "composio_sdk" &&
397
+ c.providerSlug.toLowerCase() === tool.providerSlug.toLowerCase());
398
+ if (!existingConn || existingConn.status !== "active") {
399
+ try {
400
+ if (!existingConn || !existingConn.redirectUrl) {
401
+ existingConn = await this.startConnection(ctx, {
402
+ provider: tool.providerSlug,
403
+ });
404
+ }
405
+ }
406
+ catch {
407
+ // Keep existing connection state if offline
408
+ }
409
+ if (!existingConn || existingConn.status !== "active") {
410
+ authHandoff = {
411
+ required: true,
412
+ provider: tool.providerSlug,
413
+ status: existingConn?.status || "pending",
414
+ redirectUrl: existingConn?.redirectUrl || null,
415
+ externalAccountId: existingConn?.externalAccountId || null,
416
+ instructions: existingConn?.redirectUrl
417
+ ? `Ask the user to authorize ${tool.providerName} at ${existingConn.redirectUrl}, then call wait_for_connection({ provider: "${tool.providerSlug}" }) before executing ${plan.id}.`
418
+ : `Call start_connection({ provider: "${tool.providerSlug}" }) to authorize ${tool.providerName} before executing ${plan.id}.`,
419
+ };
420
+ }
421
+ }
422
+ }
423
+ const executeToolName = `execute_${tool.riskLevel}`;
424
+ let nextStep = approvalStatus === "pending_approval"
425
+ ? `Plan ${plan.id} requires human owner approval in the Muxo Console or via approve_plan before calling ${executeToolName}.`
426
+ : `Plan ${plan.id} is auto-approved. Call ${executeToolName}({ plan_id: "${plan.id}" }) to execute.`;
427
+ if (authHandoff?.required) {
428
+ nextStep = `${authHandoff.instructions} Once connected, ${nextStep}`;
429
+ }
430
+ return {
431
+ plan,
432
+ tool,
433
+ decisionRecord,
434
+ memoryContext,
435
+ ...(authHandoff ? { authHandoff } : {}),
436
+ nextStep,
437
+ };
438
+ }
439
+ // 8. get_plan
440
+ getPlan(ctx, planId) {
441
+ const plan = this.store.getPlan(ctx.workspace.id, planId);
442
+ if (!plan)
443
+ throw new Error(`Plan '${planId}' not found in workspace.`);
444
+ return plan;
445
+ }
446
+ // Human owner approval / rejection
447
+ approvePlan(ctx, planId, decision = "approved") {
448
+ const plan = this.getPlan(ctx, planId);
449
+ if (plan.approvalStatus === "executed") {
450
+ throw new Error(`Plan '${planId}' has already been executed.`);
451
+ }
452
+ return this.store.updatePlanApproval({
453
+ workspaceId: ctx.workspace.id,
454
+ planId,
455
+ approvalStatus: decision,
456
+ approvedBy: ctx.user.email,
457
+ });
458
+ }
459
+ // 9. get_run_context
460
+ async getRunContext(ctx, query) {
461
+ const ws = this.store.getWorkspace(ctx.workspace.id);
462
+ const resources = this.store.listResources(ws.id);
463
+ const activeEnv = this.store.getDecryptedWorkspaceEnv(ws.id);
464
+ const redactedEnv = {};
465
+ for (const [k, v] of Object.entries(activeEnv)) {
466
+ redactedEnv[k] =
467
+ v.length > 8 ? `${v.slice(0, 4)}••••${v.slice(-3)}` : "••••••••";
468
+ }
469
+ const memoryContext = await this.supermemory.getContextForWorkspace(ws.id, query);
470
+ return {
471
+ workspaceId: ws.id,
472
+ workspaceSlug: ws.slug,
473
+ projectsEnvironment: ws.projectsEnvName,
474
+ policy: ws.policy,
475
+ creditsBalance: ws.creditsBalance,
476
+ monthlyActionsRemaining: Math.max(0, ws.monthlyActionsLimit - ws.monthlyActionsUsed),
477
+ provisionedResources: resources.filter((r) => r.status === "active"),
478
+ environmentVariablesRedacted: redactedEnv,
479
+ supermemoryBrain: memoryContext,
480
+ governance: this.governance.getStatus(ws),
481
+ envPullHint: "Run `muxo env pull` or call GET /api/v1/resources/env to write decrypted credentials to your local .env file.",
482
+ };
483
+ }
484
+ // Supermemory Workspace Brain Operations
485
+ async getMemoryOverview(ctx, query) {
486
+ const context = await this.supermemory.getContextForWorkspace(ctx.workspace.id, query);
487
+ const recentMemories = this.store.listMemoryRecords(ctx.workspace.id, 25);
488
+ return {
489
+ enabled: context.enabled,
490
+ namespace: context.namespace,
491
+ context,
492
+ recentMemories,
493
+ memories: recentMemories,
494
+ };
495
+ }
496
+ async addWorkspaceMemory(ctx, params) {
497
+ const kind = params.kind || "fact";
498
+ const remote = await this.supermemory.addMemory({
499
+ workspaceId: ctx.workspace.id,
500
+ title: params.title,
501
+ content: params.content,
502
+ kind,
503
+ metadata: params.metadata,
504
+ });
505
+ return this.store.saveMemoryRecord({
506
+ workspaceId: ctx.workspace.id,
507
+ namespace: remote.namespace,
508
+ documentId: remote.documentId,
509
+ title: params.title,
510
+ content: remote.sanitizedContent,
511
+ kind,
512
+ metadata: {
513
+ ...(params.metadata || {}),
514
+ supermemoryStatus: remote.status,
515
+ },
516
+ });
517
+ }
518
+ async deleteWorkspaceMemory(ctx, idOrDocId) {
519
+ const local = this.store.deleteMemoryRecord(ctx.workspace.id, idOrDocId);
520
+ const docId = local?.documentId || idOrDocId;
521
+ const remote = await this.supermemory.deleteMemory(ctx.workspace.id, docId);
522
+ return {
523
+ deleted: Boolean(local || remote.deleted),
524
+ record: local,
525
+ };
526
+ }
527
+ // 10-15. execute_<risk_level>
528
+ async executePlanForRisk(ctx, planId, expectedRisk) {
529
+ const plan = this.getPlan(ctx, planId);
530
+ if (plan.riskLevel !== expectedRisk) {
531
+ throw new Error(`Risk lane mismatch: Plan '${plan.id}' has risk level '${plan.riskLevel}', so it must be executed with 'execute_${plan.riskLevel}' instead of 'execute_${expectedRisk}'.`);
532
+ }
533
+ if (plan.runId) {
534
+ const existingRun = this.store.getRun(ctx.workspace.id, plan.runId);
535
+ const existingReceipt = this.store.getReceipt(ctx.workspace.id, plan.runId);
536
+ if (existingRun && existingReceipt) {
537
+ return { run: existingRun, receipt: existingReceipt };
538
+ }
539
+ throw new Error(`Plan '${plan.id}' was already claimed by run '${plan.runId}' (execute-once invariant).`);
540
+ }
541
+ if (plan.approvalStatus === "pending_approval") {
542
+ throw new Error(`Plan '${plan.id}' (${plan.riskLevel}) is awaiting human approval. Approve it in the Muxo Console or via CLI 'muxo approve ${plan.id}' before executing.`);
543
+ }
544
+ if (plan.approvalStatus === "rejected") {
545
+ throw new Error(`Plan '${plan.id}' was rejected and cannot be executed.`);
546
+ }
547
+ const ws = this.store.getWorkspace(ctx.workspace.id);
548
+ const tool = await this.inspectTool(plan.toolSlug);
549
+ const execDecisionRecord = this.governance.evaluateExecution({
550
+ workspace: ws,
551
+ actorId: ctx.actorId,
552
+ plan,
553
+ tool,
554
+ });
555
+ if (execDecisionRecord.verdict === "deny") {
556
+ throw new Error(`Microsoft Agent Governance denied execution of plan '${plan.id}': ${execDecisionRecord.reason}`);
557
+ }
558
+ const run = this.store.createRun(plan, ctx.actorId);
559
+ const startedMs = Date.now();
560
+ try {
561
+ let output;
562
+ if (plan.lane === "composio_instant") {
563
+ output = await this.composioInstant.executeTool({
564
+ workspaceId: ctx.workspace.id,
565
+ tool,
566
+ input: plan.input,
567
+ });
568
+ }
569
+ else if (plan.lane === "composio_sdk") {
570
+ let connections = this.store.listConnections(ctx.workspace.id);
571
+ let activeConn = connections.find((c) => c.lane === "composio_sdk" &&
572
+ c.providerSlug === tool.providerSlug &&
573
+ c.status === "active");
574
+ if (!activeConn) {
575
+ await this.waitForConnection(ctx, {
576
+ provider: tool.providerSlug,
577
+ timeoutSeconds: 0,
578
+ }).catch(() => { });
579
+ connections = this.store.listConnections(ctx.workspace.id);
580
+ activeConn = connections.find((c) => c.lane === "composio_sdk" &&
581
+ c.providerSlug === tool.providerSlug &&
582
+ c.status === "active");
583
+ }
584
+ output = await this.composioSdk.executeTool({
585
+ workspaceId: ctx.workspace.id,
586
+ tool,
587
+ input: plan.input,
588
+ connectedAccountId: activeConn?.externalAccountId || null,
589
+ });
590
+ }
591
+ else if (plan.lane === "stripe_projects") {
592
+ const projResult = await this.stripeProjects.executeTool({
593
+ workspaceId: ctx.workspace.id,
594
+ tool,
595
+ input: plan.input,
596
+ });
597
+ output = projResult.output;
598
+ if (projResult.provisionedResource) {
599
+ this.store.upsertResource({
600
+ workspaceId: ctx.workspace.id,
601
+ ...projResult.provisionedResource,
602
+ });
603
+ }
604
+ }
605
+ else {
606
+ throw new Error(`Unsupported execution lane: ${plan.lane}`);
607
+ }
608
+ const durationMs = Date.now() - startedMs;
609
+ const finalized = this.store.finalizeRun({
610
+ workspaceId: ctx.workspace.id,
611
+ runId: run.id,
612
+ status: "succeeded",
613
+ output,
614
+ actionsMetered: 1,
615
+ creditsMetered: plan.creditCost,
616
+ durationMs,
617
+ decisionRecord: execDecisionRecord,
618
+ });
619
+ // Record secret-redacted post-run memory in Supermemory for stateful actions
620
+ if (plan.riskLevel !== "read") {
621
+ const summary = `Executed ${plan.toolSlug} (${plan.lane}, risk=${plan.riskLevel}) for reason "${plan.reason}" -> status=succeeded (receipt=${finalized.receipt.id}).`;
622
+ this.supermemory
623
+ .recordExecutionMemory({
624
+ workspaceId: ctx.workspace.id,
625
+ toolSlug: plan.toolSlug,
626
+ lane: plan.lane,
627
+ riskLevel: plan.riskLevel,
628
+ reason: plan.reason,
629
+ status: "succeeded",
630
+ summary,
631
+ })
632
+ .then((docId) => {
633
+ if (docId) {
634
+ this.store.saveMemoryRecord({
635
+ workspaceId: ctx.workspace.id,
636
+ namespace: this.supermemory.getWorkspaceNamespace(ctx.workspace.id),
637
+ documentId: docId,
638
+ title: `Execution: ${plan.toolSlug} (succeeded)`,
639
+ content: this.supermemory.sanitizeContent(summary),
640
+ kind: "execution_outcome",
641
+ metadata: {
642
+ runId: finalized.run.id,
643
+ receiptId: finalized.receipt.id,
644
+ toolSlug: plan.toolSlug,
645
+ },
646
+ });
647
+ }
648
+ })
649
+ .catch(() => { });
650
+ }
651
+ return finalized;
652
+ }
653
+ catch (err) {
654
+ const durationMs = Date.now() - startedMs;
655
+ const errorMessage = String(err?.message || err || "Execution failed");
656
+ return this.store.finalizeRun({
657
+ workspaceId: ctx.workspace.id,
658
+ runId: run.id,
659
+ status: "failed",
660
+ output: { error: errorMessage },
661
+ error: errorMessage,
662
+ actionsMetered: 1,
663
+ creditsMetered: 0,
664
+ durationMs,
665
+ decisionRecord: execDecisionRecord,
666
+ });
667
+ }
668
+ }
669
+ // 16. get_run
670
+ getRun(ctx, runId) {
671
+ const run = this.store.getRun(ctx.workspace.id, runId);
672
+ if (!run)
673
+ throw new Error(`Run '${runId}' not found in workspace.`);
674
+ return run;
675
+ }
676
+ // 17. cancel_run
677
+ cancelRun(ctx, runId) {
678
+ const run = this.getRun(ctx, runId);
679
+ if (run.status === "succeeded" || run.status === "failed" || run.status === "cancelled") {
680
+ return {
681
+ run,
682
+ receipt: this.store.getReceipt(ctx.workspace.id, run.id),
683
+ };
684
+ }
685
+ const finalized = this.store.finalizeRun({
686
+ workspaceId: ctx.workspace.id,
687
+ runId: run.id,
688
+ status: "cancelled",
689
+ output: { cancelledBy: ctx.actorId },
690
+ error: "Cancelled by operator",
691
+ actionsMetered: 0,
692
+ creditsMetered: 0,
693
+ durationMs: Date.now() - new Date(run.startedAt).getTime(),
694
+ });
695
+ return finalized;
696
+ }
697
+ // 18. get_receipt
698
+ getReceipt(ctx, receiptOrRunId) {
699
+ const receipt = this.store.getReceipt(ctx.workspace.id, receiptOrRunId);
700
+ if (!receipt) {
701
+ throw new Error(`Receipt '${receiptOrRunId}' not found in workspace.`);
702
+ }
703
+ const signatureValid = this.store.verifyReceipt(receipt);
704
+ const governanceSignatureValid = receipt.decisionRecord
705
+ ? this.governance.verifyDecisionRecord(receipt.decisionRecord)
706
+ : true;
707
+ return { receipt, signatureValid, governanceSignatureValid };
708
+ }
709
+ }