@muxoai/sdk 1.3.0 → 1.4.3

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 (76) hide show
  1. package/.agents/plugins/marketplace.json +2 -2
  2. package/.claude-plugin/marketplace.json +19 -4
  3. package/.codex/config.toml +9 -2
  4. package/ARCHITECTURE.md +16 -6
  5. package/README.md +69 -24
  6. package/dist/clerk.d.ts +35 -0
  7. package/dist/clerk.js +201 -0
  8. package/dist/cli.js +1677 -103
  9. package/dist/composio-catalog.d.ts +234 -0
  10. package/dist/composio-catalog.js +1894 -0
  11. package/dist/config.d.ts +16 -0
  12. package/dist/config.js +27 -1
  13. package/dist/durable-workflow.d.ts +112 -0
  14. package/dist/durable-workflow.js +284 -0
  15. package/dist/engine.d.ts +377 -6
  16. package/dist/engine.js +1919 -94
  17. package/dist/index.d.ts +3 -0
  18. package/dist/index.js +3 -0
  19. package/dist/mcp-schema.d.ts +286 -0
  20. package/dist/mcp-schema.js +2580 -0
  21. package/dist/mcp.d.ts +2 -25
  22. package/dist/mcp.js +1008 -507
  23. package/dist/memory-graph.d.ts +45 -0
  24. package/dist/memory-graph.js +293 -0
  25. package/dist/nl.js +214 -35
  26. package/dist/oauth.d.ts +32 -0
  27. package/dist/oauth.js +134 -0
  28. package/dist/oss-suite.d.ts +217 -0
  29. package/dist/oss-suite.js +836 -0
  30. package/dist/policy.d.ts +190 -0
  31. package/dist/policy.js +1597 -0
  32. package/dist/providers/composio-instant.d.ts +4 -0
  33. package/dist/providers/composio-instant.js +890 -535
  34. package/dist/providers/composio-sdk.d.ts +126 -5
  35. package/dist/providers/composio-sdk.js +902 -79
  36. package/dist/providers/microsoft-governance.d.ts +89 -3
  37. package/dist/providers/microsoft-governance.js +673 -26
  38. package/dist/providers/stripe-billing.d.ts +42 -0
  39. package/dist/providers/stripe-billing.js +244 -5
  40. package/dist/providers/stripe-projects.d.ts +459 -4
  41. package/dist/providers/stripe-projects.js +2674 -122
  42. package/dist/providers/supermemory.d.ts +102 -6
  43. package/dist/providers/supermemory.js +609 -55
  44. package/dist/provisioning-managed.d.ts +50 -0
  45. package/dist/provisioning-managed.js +155 -0
  46. package/dist/sdk.d.ts +728 -7
  47. package/dist/sdk.js +539 -10
  48. package/dist/server.js +2744 -321
  49. package/dist/store.d.ts +138 -6
  50. package/dist/store.js +932 -58
  51. package/dist/types.d.ts +330 -4
  52. package/dist/ui/console-html.d.ts +62 -0
  53. package/dist/ui/console-html.js +3742 -2228
  54. package/dist/ui/design-tokens.d.ts +177 -0
  55. package/dist/ui/design-tokens.js +210 -0
  56. package/dist/version.d.ts +1 -0
  57. package/dist/version.js +1 -0
  58. package/package.json +6 -5
  59. package/plugins/muxo/.app.json +1 -1
  60. package/plugins/muxo/.claude-plugin/plugin.json +3 -3
  61. package/plugins/muxo/.codex-plugin/plugin.json +19 -10
  62. package/plugins/muxo/.cursor-plugin/plugin.json +30 -0
  63. package/plugins/muxo/.mcp.json +1 -33
  64. package/plugins/muxo/assets/logo.png +0 -0
  65. package/plugins/muxo/hooks/session-start.sh +16 -4
  66. package/plugins/muxo/hooks/user-prompt-submit.sh +14 -1
  67. package/plugins/muxo/mcp.json +0 -10
  68. package/plugins/muxo/plugin.json +65 -8
  69. package/plugins/muxo/skills/muxo/SKILL.md +142 -14
  70. package/plugins/muxo/skills/muxo/agents/openai.yaml +12 -0
  71. package/plugins/muxo/skills/muxo/references/cli.md +9 -3
  72. package/plugins/muxo/skills/muxo/references/mcp.md +22 -10
  73. package/plugins/muxo/skills/muxo-activity-summary/SKILL.md +81 -0
  74. package/plugins/muxo/skills/setup/SKILL.md +17 -3
  75. package/plugins/muxo/skills/setup/agents/openai.yaml +12 -0
  76. package/src/catalogues/stripe-projects-catalog.json +140 -0
package/dist/config.d.ts CHANGED
@@ -1,11 +1,23 @@
1
+ import type { ClerkEnv } from "./clerk.js";
1
2
  export declare const ROOT_DIR: string;
2
3
  export interface MuxoConfig {
3
4
  port: number;
4
5
  baseUrl: string;
5
6
  dbPath: string;
6
7
  composioApiKey: string;
8
+ composioInstantApiKey: string;
7
9
  composioBaseUrl: string;
10
+ composioWebhookSecret: string;
11
+ composioWebhookSubscriptionId: string;
12
+ composioProjectId: string;
13
+ composioOrgId: string;
14
+ composioUserId: string;
8
15
  stripeSecretKey: string;
16
+ stripePublishableKey: string;
17
+ stripeApiBaseUrl: string;
18
+ stripeProvisioningApiVersion: string;
19
+ stripeProjectId: string;
20
+ stripeConnectedAccountId?: string;
9
21
  stripeStarterPriceId: string;
10
22
  stripeCreditsPriceId: string;
11
23
  stripeWebhookSecret: string;
@@ -16,5 +28,9 @@ export interface MuxoConfig {
16
28
  publicWebUrl: string;
17
29
  docsUrl: string;
18
30
  vaultMasterKey: Buffer;
31
+ /** Clerk sign-in settings; sign-in stays password-based unless CLERK_PUBLISHABLE_KEY is set. */
32
+ clerkEnv?: ClerkEnv & {
33
+ MUXO_OWNER_EMAILS?: string;
34
+ };
19
35
  }
20
36
  export declare function getConfig(): MuxoConfig;
package/dist/config.js CHANGED
@@ -65,11 +65,30 @@ export function getConfig() {
65
65
  dbPath: process.env.MUXO_DB_PATH || path.join(dataDir, "muxo.db"),
66
66
  composioApiKey: process.env.MUXO_EXTERNAL_MODE === "1"
67
67
  ? ""
68
- : process.env.COMPOSIO_API_KEY || "",
68
+ : process.env.COMPOSIO_API_KEY || process.env.COMPOSIO_INSTANT_API_KEY || "",
69
+ composioInstantApiKey: process.env.MUXO_EXTERNAL_MODE === "1"
70
+ ? ""
71
+ : process.env.COMPOSIO_INSTANT_API_KEY || process.env.COMPOSIO_API_KEY || "",
69
72
  composioBaseUrl: process.env.COMPOSIO_BASE_URL || "https://backend.composio.dev/api/v3",
73
+ composioWebhookSecret: process.env.MUXO_EXTERNAL_MODE === "1"
74
+ ? ""
75
+ : process.env.COMPOSIO_WEBHOOK_SECRET || "",
76
+ composioWebhookSubscriptionId: process.env.COMPOSIO_WEBHOOK_SUBSCRIPTION_ID || "",
77
+ composioProjectId: process.env.COMPOSIO_PROJECT_ID || "",
78
+ composioOrgId: process.env.COMPOSIO_ORG_ID || "",
79
+ composioUserId: process.env.COMPOSIO_USER_ID || "",
70
80
  stripeSecretKey: process.env.MUXO_EXTERNAL_MODE === "1"
71
81
  ? ""
72
82
  : process.env.STRIPE_SECRET_KEY || "",
83
+ stripePublishableKey: process.env.MUXO_EXTERNAL_MODE === "1"
84
+ ? ""
85
+ : process.env.STRIPE_PUBLISHABLE_KEY || "",
86
+ stripeApiBaseUrl: process.env.STRIPE_API_BASE_URL || "https://api.stripe.com",
87
+ stripeProvisioningApiVersion: process.env.STRIPE_PROVISIONING_API_VERSION || "2026-09-30.preview",
88
+ stripeProjectId: process.env.STRIPE_PROJECT_ID || "",
89
+ stripeConnectedAccountId: process.env.STRIPE_CONNECTED_ACCOUNT_ID ||
90
+ process.env.STRIPE_CONTEXT ||
91
+ "",
73
92
  stripeStarterPriceId: process.env.STRIPE_STARTER_PRICE_ID || "",
74
93
  stripeCreditsPriceId: process.env.STRIPE_CREDITS_PRICE_ID || "",
75
94
  stripeWebhookSecret: process.env.STRIPE_WEBHOOK_SECRET || "",
@@ -85,5 +104,12 @@ export function getConfig() {
85
104
  publicWebUrl: process.env.MUXO_PUBLIC_WEB_URL || "https://muxo.ai",
86
105
  docsUrl: process.env.MUXO_DOCS_URL || "https://docs.muxo.ai",
87
106
  vaultMasterKey: deriveVaultMasterKey(),
107
+ clerkEnv: {
108
+ CLERK_PUBLISHABLE_KEY: process.env.CLERK_PUBLISHABLE_KEY,
109
+ CLERK_SECRET_KEY: process.env.CLERK_SECRET_KEY,
110
+ CLERK_JWT_KEY: process.env.CLERK_JWT_KEY,
111
+ CLERK_AUTHORIZED_PARTIES: process.env.CLERK_AUTHORIZED_PARTIES,
112
+ MUXO_OWNER_EMAILS: process.env.MUXO_OWNER_EMAILS,
113
+ },
88
114
  };
89
115
  }
@@ -0,0 +1,112 @@
1
+ /**
2
+ * Temporal-compatible Durable Workflows, Saga Compensations, Signals, and Cloudflare Workflows primitives,
3
+ * shared by the Node engine (src/engine.ts) and the Cloudflare Edge Worker (worker/index.ts).
4
+ */
5
+ import { MuxoToolError } from "./mcp-schema.js";
6
+ export type DurableWorkflowStepStatus = "completed" | "waiting" | "pending" | "failed" | "compensated";
7
+ export interface DurableWorkflowStep {
8
+ name: string;
9
+ primitive: "step.do" | "step.waitForEvent" | "step.sleep";
10
+ status: DurableWorkflowStepStatus;
11
+ output?: Record<string, unknown>;
12
+ completedAt?: string;
13
+ compensationAction?: string;
14
+ compensatedAt?: string;
15
+ }
16
+ export type TemporalEventType = "EVENT_TYPE_WORKFLOW_EXECUTION_STARTED" | "EVENT_TYPE_ACTIVITY_TASK_SCHEDULED" | "EVENT_TYPE_ACTIVITY_TASK_COMPLETED" | "EVENT_TYPE_ACTIVITY_TASK_FAILED" | "EVENT_TYPE_WORKFLOW_EXECUTION_SIGNALED" | "EVENT_TYPE_TIMER_STARTED" | "EVENT_TYPE_TIMER_FIRED" | "EVENT_TYPE_WORKFLOW_EXECUTION_COMPLETED" | "EVENT_TYPE_WORKFLOW_EXECUTION_CANCELED" | "EVENT_TYPE_WORKFLOW_EXECUTION_FAILED";
17
+ export interface TemporalHistoryEvent {
18
+ eventId: number;
19
+ eventTime: string;
20
+ eventType: TemporalEventType;
21
+ taskQueue: string;
22
+ attributes: Record<string, unknown>;
23
+ }
24
+ export interface SagaCompensationRecord {
25
+ stepName: string;
26
+ compensationAction: string;
27
+ status: "registered" | "executed" | "skipped";
28
+ description: string;
29
+ output?: Record<string, unknown>;
30
+ executedAt?: string;
31
+ }
32
+ export interface DurableWorkflowSignalRecord {
33
+ signalName: string;
34
+ payload: Record<string, unknown>;
35
+ receivedAt: string;
36
+ }
37
+ export interface DurableWorkflow {
38
+ id: string;
39
+ runId?: string;
40
+ workspaceId: string;
41
+ workflowType: "cloud_provisioning_pipeline" | "approval_handoff_pipeline" | "commercial_playbook_saga";
42
+ playbookSlug?: string | null;
43
+ status: "running" | "waiting_for_event" | "completed" | "failed" | "rolled_back";
44
+ provider: string;
45
+ serviceRef: string;
46
+ resourceId: string | null;
47
+ steps: DurableWorkflowStep[];
48
+ compensations?: SagaCompensationRecord[];
49
+ signals?: DurableWorkflowSignalRecord[];
50
+ temporalEventHistory?: TemporalHistoryEvent[];
51
+ rollbackReason?: string | null;
52
+ createdAt: string;
53
+ updatedAt: string;
54
+ }
55
+ export declare const WORKFLOW_RESOURCE_COMPLETED_EVENT = "v2.provisioning.resource.completed";
56
+ export declare function workflowNotFoundError(workflowId: string): MuxoToolError;
57
+ export declare function normalizeWorkflowTarget(params: {
58
+ provider?: string;
59
+ serviceRef?: string;
60
+ }): {
61
+ provider: string;
62
+ serviceRef: string;
63
+ };
64
+ export declare function createCloudProvisioningWorkflow(params: {
65
+ id: string;
66
+ workspaceId: string;
67
+ resourceId: string;
68
+ provider: string;
69
+ serviceRef: string;
70
+ region?: string;
71
+ apiVersion?: string;
72
+ }): DurableWorkflow;
73
+ /** Completes every outstanding step once the resource-completed event (or a manual advance) arrives. */
74
+ export declare function completeCloudProvisioningWorkflow(wf: DurableWorkflow, params: {
75
+ secretKeys: string[];
76
+ triggerEvent?: unknown;
77
+ }): DurableWorkflow;
78
+ /**
79
+ * Executes LIFO Saga Compensations on a DurableWorkflow, rolling back completed steps in reverse order
80
+ * and recording Temporal compensation activity events.
81
+ */
82
+ export declare function rollbackDurableWorkflow(wf: DurableWorkflow, params?: {
83
+ reason?: string;
84
+ failedStepName?: string;
85
+ failedStep?: string;
86
+ }): DurableWorkflow;
87
+ /**
88
+ * Sends a named Temporal signal to a DurableWorkflow (`human.approval.granted`, `oauth.connection.active`,
89
+ * `saga.abort`, or `v2.provisioning.resource.completed`).
90
+ */
91
+ export declare function signalDurableWorkflow(wf: DurableWorkflow, params: {
92
+ signalName: string;
93
+ payload?: Record<string, unknown>;
94
+ secretKeys?: string[];
95
+ }): DurableWorkflow;
96
+ /**
97
+ * Exports a DurableWorkflow in Temporal Web UI / `temporal workflow show` compatible EventHistory JSON format.
98
+ */
99
+ export declare function exportTemporalEventHistory(wf: DurableWorkflow): {
100
+ namespace: string;
101
+ workflowExecution: {
102
+ workflowId: string;
103
+ runId: string;
104
+ };
105
+ workflowType: {
106
+ name: string;
107
+ };
108
+ status: DurableWorkflow["status"];
109
+ eventsCount: number;
110
+ compensationsCount: number;
111
+ events: TemporalHistoryEvent[];
112
+ };
@@ -0,0 +1,284 @@
1
+ /**
2
+ * Temporal-compatible Durable Workflows, Saga Compensations, Signals, and Cloudflare Workflows primitives,
3
+ * shared by the Node engine (src/engine.ts) and the Cloudflare Edge Worker (worker/index.ts).
4
+ */
5
+ import { MuxoToolError } from "./mcp-schema.js";
6
+ export const WORKFLOW_RESOURCE_COMPLETED_EVENT = "v2.provisioning.resource.completed";
7
+ export function workflowNotFoundError(workflowId) {
8
+ return new MuxoToolError(`Durable workflow not found: ${workflowId}`, {
9
+ code: "workflow_not_found",
10
+ statusCode: 404,
11
+ payload: { workflowId },
12
+ });
13
+ }
14
+ export function normalizeWorkflowTarget(params) {
15
+ return {
16
+ provider: (params.provider || "neon").toLowerCase().trim(),
17
+ serviceRef: (params.serviceRef || "postgres").toLowerCase().trim(),
18
+ };
19
+ }
20
+ function appendTemporalEvent(history, eventType, attributes, now = new Date().toISOString()) {
21
+ history.push({
22
+ eventId: history.length + 1,
23
+ eventTime: now,
24
+ eventType,
25
+ taskQueue: "muxo-durable-execution-queue",
26
+ attributes,
27
+ });
28
+ }
29
+ export function createCloudProvisioningWorkflow(params) {
30
+ const now = new Date().toISOString();
31
+ const region = params.region || "aws-us-east-1";
32
+ const apiVersion = params.apiVersion || "2026-09-30.preview";
33
+ const history = [];
34
+ appendTemporalEvent(history, "EVENT_TYPE_WORKFLOW_EXECUTION_STARTED", {
35
+ workflowType: "cloud_provisioning_pipeline",
36
+ workflowId: params.id,
37
+ workspaceId: params.workspaceId,
38
+ provider: params.provider,
39
+ serviceRef: params.serviceRef,
40
+ region,
41
+ }, now);
42
+ appendTemporalEvent(history, "EVENT_TYPE_ACTIVITY_TASK_COMPLETED", {
43
+ activityName: "check_stripe_v2_eligibility",
44
+ result: { status: "eligible", apiVersion },
45
+ }, now);
46
+ appendTemporalEvent(history, "EVENT_TYPE_ACTIVITY_TASK_COMPLETED", {
47
+ activityName: "ensure_payment_profile_and_provider_connection",
48
+ result: { provider: params.provider, paymentProfileStatus: "active" },
49
+ }, now);
50
+ appendTemporalEvent(history, "EVENT_TYPE_ACTIVITY_TASK_COMPLETED", {
51
+ activityName: "create_v2_provisioning_resource",
52
+ result: {
53
+ resourceId: params.resourceId,
54
+ provider: params.provider,
55
+ service_ref: params.serviceRef,
56
+ region,
57
+ },
58
+ compensationAction: `resource.${params.provider}.remove`,
59
+ }, now);
60
+ appendTemporalEvent(history, "EVENT_TYPE_TIMER_STARTED", {
61
+ waitingForSignal: WORKFLOW_RESOURCE_COMPLETED_EVENT,
62
+ resourceId: params.resourceId,
63
+ }, now);
64
+ const compensations = [
65
+ {
66
+ stepName: "ensure_payment_profile_and_provider_connection",
67
+ compensationAction: `provisioning.provider_connection.unlink`,
68
+ status: "registered",
69
+ description: `Unlink provider connection for ${params.provider} if downstream provisioning aborts`,
70
+ },
71
+ {
72
+ stepName: "create_v2_provisioning_resource",
73
+ compensationAction: `resource.${params.provider}.remove`,
74
+ status: "registered",
75
+ description: `Deprovision ${params.provider}/${params.serviceRef} (${params.resourceId}) and release reservation`,
76
+ },
77
+ ];
78
+ return {
79
+ id: params.id,
80
+ runId: `run_${params.id}`,
81
+ workspaceId: params.workspaceId,
82
+ workflowType: "cloud_provisioning_pipeline",
83
+ playbookSlug: null,
84
+ status: "waiting_for_event",
85
+ provider: params.provider,
86
+ serviceRef: params.serviceRef,
87
+ resourceId: params.resourceId,
88
+ steps: [
89
+ {
90
+ name: "check_stripe_v2_eligibility",
91
+ primitive: "step.do",
92
+ status: "completed",
93
+ output: { status: "eligible", apiVersion },
94
+ completedAt: now,
95
+ },
96
+ {
97
+ name: "ensure_payment_profile_and_provider_connection",
98
+ primitive: "step.do",
99
+ status: "completed",
100
+ output: { provider: params.provider, paymentProfileStatus: "active" },
101
+ completedAt: now,
102
+ compensationAction: "provisioning.provider_connection.unlink",
103
+ },
104
+ {
105
+ name: "create_v2_provisioning_resource",
106
+ primitive: "step.do",
107
+ status: "completed",
108
+ output: {
109
+ resourceId: params.resourceId,
110
+ provider: params.provider,
111
+ service_ref: params.serviceRef,
112
+ region,
113
+ },
114
+ completedAt: now,
115
+ compensationAction: `resource.${params.provider}.remove`,
116
+ },
117
+ {
118
+ name: "wait_for_v2_provisioning_resource_completed",
119
+ primitive: "step.waitForEvent",
120
+ status: "waiting",
121
+ output: {
122
+ expectedEvent: WORKFLOW_RESOURCE_COMPLETED_EVENT,
123
+ resourceId: params.resourceId,
124
+ },
125
+ },
126
+ {
127
+ name: "reveal_access_configuration_and_seal_vault",
128
+ primitive: "step.do",
129
+ status: "pending",
130
+ compensationAction: "vault.revoke_secrets",
131
+ },
132
+ ],
133
+ compensations,
134
+ signals: [],
135
+ temporalEventHistory: history,
136
+ rollbackReason: null,
137
+ createdAt: now,
138
+ updatedAt: now,
139
+ };
140
+ }
141
+ /** Completes every outstanding step once the resource-completed event (or a manual advance) arrives. */
142
+ export function completeCloudProvisioningWorkflow(wf, params) {
143
+ const now = new Date().toISOString();
144
+ const history = wf.temporalEventHistory || [];
145
+ const trigger = String(params.triggerEvent || WORKFLOW_RESOURCE_COMPLETED_EVENT);
146
+ appendTemporalEvent(history, "EVENT_TYPE_WORKFLOW_EXECUTION_SIGNALED", {
147
+ signalName: trigger,
148
+ resourceId: wf.resourceId,
149
+ }, now);
150
+ for (const step of wf.steps) {
151
+ if (step.status === "completed")
152
+ continue;
153
+ step.status = "completed";
154
+ step.completedAt = now;
155
+ if (step.name === "reveal_access_configuration_and_seal_vault") {
156
+ step.output = {
157
+ vaultEncrypted: true,
158
+ cipher: "AES-256-GCM",
159
+ secretKeys: params.secretKeys,
160
+ triggerEvent: trigger,
161
+ };
162
+ }
163
+ appendTemporalEvent(history, "EVENT_TYPE_ACTIVITY_TASK_COMPLETED", {
164
+ activityName: step.name,
165
+ result: step.output || { status: "completed" },
166
+ }, now);
167
+ }
168
+ appendTemporalEvent(history, "EVENT_TYPE_WORKFLOW_EXECUTION_COMPLETED", {
169
+ workflowId: wf.id,
170
+ status: "completed",
171
+ secretKeysSealed: params.secretKeys,
172
+ }, now);
173
+ wf.temporalEventHistory = history;
174
+ wf.status = "completed";
175
+ wf.updatedAt = now;
176
+ return wf;
177
+ }
178
+ /**
179
+ * Executes LIFO Saga Compensations on a DurableWorkflow, rolling back completed steps in reverse order
180
+ * and recording Temporal compensation activity events.
181
+ */
182
+ export function rollbackDurableWorkflow(wf, params) {
183
+ const now = new Date().toISOString();
184
+ const failedStepName = params?.failedStepName || params?.failedStep;
185
+ const reason = params?.reason ||
186
+ "Saga rollback requested by operator or downstream step failure";
187
+ const history = wf.temporalEventHistory || [];
188
+ const compensations = wf.compensations || [];
189
+ if (failedStepName) {
190
+ appendTemporalEvent(history, "EVENT_TYPE_ACTIVITY_TASK_FAILED", {
191
+ activityName: failedStepName,
192
+ reason,
193
+ }, now);
194
+ }
195
+ // Execute registered compensations in reverse (LIFO) order
196
+ for (let i = compensations.length - 1; i >= 0; i--) {
197
+ const comp = compensations[i];
198
+ if (comp.status === "executed")
199
+ continue;
200
+ comp.status = "executed";
201
+ comp.executedAt = now;
202
+ comp.output = {
203
+ rolledBack: true,
204
+ action: comp.compensationAction,
205
+ resourceId: wf.resourceId,
206
+ reason,
207
+ };
208
+ appendTemporalEvent(history, "EVENT_TYPE_ACTIVITY_TASK_COMPLETED", {
209
+ activityName: `compensate:${comp.stepName}`,
210
+ compensationAction: comp.compensationAction,
211
+ result: comp.output,
212
+ }, now);
213
+ }
214
+ for (const step of wf.steps) {
215
+ if (step.status === "completed" && step.compensationAction) {
216
+ step.status = "compensated";
217
+ step.compensatedAt = now;
218
+ }
219
+ else if (step.status === "waiting" || step.status === "pending") {
220
+ step.status = "failed";
221
+ }
222
+ }
223
+ appendTemporalEvent(history, "EVENT_TYPE_WORKFLOW_EXECUTION_CANCELED", {
224
+ workflowId: wf.id,
225
+ status: "rolled_back",
226
+ reason,
227
+ compensatedStepsCount: compensations.filter((c) => c.status === "executed")
228
+ .length,
229
+ }, now);
230
+ wf.compensations = compensations;
231
+ wf.temporalEventHistory = history;
232
+ wf.rollbackReason = reason;
233
+ wf.status = "rolled_back";
234
+ wf.updatedAt = now;
235
+ return wf;
236
+ }
237
+ /**
238
+ * Sends a named Temporal signal to a DurableWorkflow (`human.approval.granted`, `oauth.connection.active`,
239
+ * `saga.abort`, or `v2.provisioning.resource.completed`).
240
+ */
241
+ export function signalDurableWorkflow(wf, params) {
242
+ const now = new Date().toISOString();
243
+ const signalName = String(params.signalName || WORKFLOW_RESOURCE_COMPLETED_EVENT).trim();
244
+ const payload = params.payload || {};
245
+ wf.signals = wf.signals || [];
246
+ wf.signals.push({
247
+ signalName,
248
+ payload,
249
+ receivedAt: now,
250
+ });
251
+ if (signalName === "saga.abort" ||
252
+ signalName === "human.approval.rejected" ||
253
+ payload.action === "rollback") {
254
+ return rollbackDurableWorkflow(wf, {
255
+ reason: String(payload.reason || `Rolled back via signal ${signalName}`),
256
+ });
257
+ }
258
+ return completeCloudProvisioningWorkflow(wf, {
259
+ secretKeys: params.secretKeys || ["DATABASE_URL"],
260
+ triggerEvent: signalName,
261
+ });
262
+ }
263
+ /**
264
+ * Exports a DurableWorkflow in Temporal Web UI / `temporal workflow show` compatible EventHistory JSON format.
265
+ */
266
+ export function exportTemporalEventHistory(wf) {
267
+ const events = wf.temporalEventHistory || [];
268
+ return {
269
+ namespace: `muxo.${wf.workspaceId}`,
270
+ workflowExecution: {
271
+ workflowId: wf.id,
272
+ runId: wf.runId || `run_${wf.id}`,
273
+ },
274
+ workflowType: {
275
+ name: wf.playbookSlug
276
+ ? `MuxoPlaybookSaga::${wf.playbookSlug}`
277
+ : `MuxoWorkflow::${wf.workflowType}`,
278
+ },
279
+ status: wf.status,
280
+ eventsCount: events.length,
281
+ compensationsCount: (wf.compensations || []).length,
282
+ events,
283
+ };
284
+ }