@ixo/editor 5.37.1 → 5.39.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.
@@ -116,7 +116,12 @@ var CAN_TO_TYPE = {
116
116
  "pod/governance-config": "qi/pod.governance-config",
117
117
  "pod/member-multi-select": "qi/pod.member-multi-select",
118
118
  "pod/list-domain-flows": "qi/pod.list-domain-flows",
119
- // Calendar integration
119
+ // Delegated integrations (author connects once, runners execute on their behalf)
120
+ "gmail.email/send": "qi/gmail.email.send",
121
+ "outlook.email/send": "qi/outlook.email.send",
122
+ "slack.message/send": "qi/slack.message.send",
123
+ "googlecalendar.event/create": "qi/googlecalendar.event.create",
124
+ // Calendar integration (self-connected)
120
125
  "calendar.event/create": "qi/calendar.event.create",
121
126
  "calendar.event/update": "qi/calendar.event.update",
122
127
  "calendar.event/list": "qi/calendar.event.list",
@@ -238,7 +243,8 @@ function buildServicesFromHandlers(handlers) {
238
243
  integrations: handlers?.integrations?.executeTool ? {
239
244
  executeTool: async (args) => handlers.integrations.executeTool(args),
240
245
  fetchCurrentState: handlers.integrations.fetchCurrentState ? async (args) => handlers.integrations.fetchCurrentState(args) : void 0,
241
- getEntityDid: handlers?.getEntityDid ? () => handlers.getEntityDid() : void 0
246
+ getEntityDid: handlers?.getEntityDid ? () => handlers.getEntityDid() : void 0,
247
+ executeBinding: handlers.integrations.executeBinding ? async (args) => handlers.integrations.executeBinding(args) : void 0
242
248
  } : void 0,
243
249
  oracle: handlers?.generateWallet ? {
244
250
  generateWallet: async () => handlers.generateWallet(),
@@ -1157,6 +1163,10 @@ function registerFormSubmitAction(type, can) {
1157
1163
  sideEffect: true,
1158
1164
  defaultRequiresConfirmation: false,
1159
1165
  requiredCapability: "flow/execute",
1166
+ // Additive: makes the form an event SOURCE so downstream blocks can
1167
+ // auto-trigger on submission (e.g. form → send email). Nothing existing
1168
+ // consumes this; it only enables new event wiring.
1169
+ eligibleForEventTrigger: true,
1160
1170
  inputSchema: {
1161
1171
  type: "object",
1162
1172
  required: [],
@@ -1168,6 +1178,15 @@ function registerFormSubmitAction(type, can) {
1168
1178
  { path: "form.answers", displayName: "Form Answers JSON", type: "string", description: "JSON stringified form answers, matching form block runtime output." },
1169
1179
  { path: "answers", displayName: "Form Answers", type: "object", description: "Parsed form answers object for convenience." }
1170
1180
  ],
1181
+ events: [
1182
+ {
1183
+ name: "form.submitted",
1184
+ displayName: "Form submitted",
1185
+ description: "Fires when the human submits the form. Payload carries the parsed answers.",
1186
+ payloadSchema: [{ path: "answers", displayName: "Form Answers", type: "object" }],
1187
+ pendingDisplayFields: ["answers"]
1188
+ }
1189
+ ],
1171
1190
  run: async (inputs) => {
1172
1191
  const answers = normalizeAnswers(inputs.answers ?? inputs.form?.answers);
1173
1192
  const answersJson = JSON.stringify(answers);
@@ -1177,7 +1196,8 @@ function registerFormSubmitAction(type, can) {
1177
1196
  answers: answersJson
1178
1197
  },
1179
1198
  answers
1180
- }
1199
+ },
1200
+ events: [{ name: "form.submitted", payload: { answers } }]
1181
1201
  };
1182
1202
  }
1183
1203
  });
@@ -4483,7 +4503,7 @@ registerAction({
4483
4503
  if (!ctx.services.matrix?.storeCredential) {
4484
4504
  throw new Error("Matrix credential storage service not configured");
4485
4505
  }
4486
- const { computeJsonCID } = await import("./cid-6O646X2I.mjs");
4506
+ const { computeJsonCID } = await import("./cid-HDAVQ43S.js");
4487
4507
  const cid = await computeJsonCID(parsedCredential);
4488
4508
  const result = await ctx.services.matrix.storeCredential({
4489
4509
  roomId: roomId || "",
@@ -6292,6 +6312,379 @@ registerAction({
6292
6312
  }
6293
6313
  });
6294
6314
 
6315
+ // src/core/lib/actionRegistry/actions/_shared/delegatedTool.ts
6316
+ function parseBoundConnection(raw) {
6317
+ if (!raw || typeof raw !== "object") return null;
6318
+ const c = raw;
6319
+ if (typeof c.bindingId !== "string" || !c.bindingId) return null;
6320
+ if (typeof c.connectedAccountId !== "string") return null;
6321
+ if (typeof c.toolkit !== "string") return null;
6322
+ return {
6323
+ bindingId: c.bindingId,
6324
+ connectedAccountId: c.connectedAccountId,
6325
+ toolkit: c.toolkit,
6326
+ label: typeof c.label === "string" ? c.label : null
6327
+ };
6328
+ }
6329
+ function parseDelegatedToolInputs(raw) {
6330
+ let parsed = {};
6331
+ try {
6332
+ parsed = typeof raw === "string" ? JSON.parse(raw || "{}") : raw || {};
6333
+ } catch {
6334
+ parsed = {};
6335
+ }
6336
+ return { ...parsed, connection: parseBoundConnection(parsed.connection) };
6337
+ }
6338
+ function serializeDelegatedToolInputs(inputs) {
6339
+ return JSON.stringify(inputs);
6340
+ }
6341
+ function fieldValues(inputs) {
6342
+ const out = {};
6343
+ for (const [k, v] of Object.entries(inputs)) {
6344
+ if (k === "connection") continue;
6345
+ if (typeof v === "string") out[k] = v;
6346
+ }
6347
+ return out;
6348
+ }
6349
+ function missingRequired(schema, values) {
6350
+ return (schema.parameters.required || []).filter((name) => !(values[name] ?? "").trim());
6351
+ }
6352
+ function coerceToolArgs(schema, values) {
6353
+ const out = {};
6354
+ for (const [name, prop] of Object.entries(schema.parameters.properties || {})) {
6355
+ const raw = values[name];
6356
+ if (typeof raw !== "string" || raw.trim() === "") continue;
6357
+ const type = prop.type;
6358
+ if (type === "boolean") {
6359
+ out[name] = raw === "true";
6360
+ } else if (type === "array") {
6361
+ out[name] = raw.split(/[\n,]+/).map((s) => s.trim()).filter(Boolean);
6362
+ } else if (type === "number" || type === "integer") {
6363
+ const n = Number(raw);
6364
+ if (!Number.isNaN(n)) out[name] = n;
6365
+ } else {
6366
+ out[name] = raw;
6367
+ }
6368
+ }
6369
+ return out;
6370
+ }
6371
+ async function executeDelegatedTool(ctx, opts) {
6372
+ const svc = ctx.services.integrations;
6373
+ if (!svc?.executeBinding) {
6374
+ throw new Error(`${opts.toolkitLabel} integration is not configured.`);
6375
+ }
6376
+ const bindingId = opts.connection?.bindingId;
6377
+ if (!bindingId) {
6378
+ throw new Error(`No ${opts.toolkitLabel} account is bound. The template author must connect and bind ${opts.toolkitLabel}.`);
6379
+ }
6380
+ const missing = missingRequired(opts.schema, opts.values);
6381
+ if (missing.length > 0) {
6382
+ throw new Error(`Missing required field${missing.length === 1 ? "" : "s"}: ${missing.join(", ")}`);
6383
+ }
6384
+ const args = coerceToolArgs(opts.schema, opts.values);
6385
+ const result = await svc.executeBinding({ bindingId, toolSlug: opts.toolSlug, arguments: args });
6386
+ if (!result.successful) {
6387
+ if (result.code === "AUTH_EXPIRED") {
6388
+ throw new Error(`The template author's ${opts.toolkitLabel} access expired \u2014 they need to reconnect it in the template.`);
6389
+ }
6390
+ if (result.code === "UPSTREAM_4XX" && /not found|removed/i.test(result.error || "")) {
6391
+ throw new Error(`This ${opts.toolkitLabel} integration was removed by the template author.`);
6392
+ }
6393
+ throw new Error(result.error || `${opts.toolkitLabel} action failed.`);
6394
+ }
6395
+ return result.data ?? {};
6396
+ }
6397
+
6398
+ // src/core/lib/actionRegistry/actions/gmail/emailSend.types.ts
6399
+ var GMAIL_SEND_SLUG = "GMAIL_SEND_EMAIL";
6400
+ var GMAIL_SENT_EVENT = "email.sent";
6401
+ var GMAIL_SEND_SCHEMA = {
6402
+ slug: GMAIL_SEND_SLUG,
6403
+ name: "Send Email",
6404
+ description: "Send an email from the template author's Gmail account.",
6405
+ parameters: {
6406
+ type: "object",
6407
+ required: ["recipient_email", "body"],
6408
+ properties: {
6409
+ recipient_email: { type: "string", title: "To", description: "Recipient's email address." },
6410
+ subject: { type: "string", title: "Subject" },
6411
+ body: { type: "string", title: "Body", description: 'Email body. Plain text unless "HTML body" is set.' },
6412
+ cc: { type: "array", title: "Cc", description: "Comma-separated email addresses." },
6413
+ bcc: { type: "array", title: "Bcc", description: "Comma-separated email addresses." },
6414
+ is_html: { type: "boolean", title: "HTML body", description: "Render the body as HTML." }
6415
+ }
6416
+ }
6417
+ };
6418
+ var GMAIL_SEND_OUTPUT_SCHEMA = [
6419
+ { path: "messageId", displayName: "Message ID", type: "string", description: "Gmail id of the sent message" },
6420
+ { path: "threadId", displayName: "Thread ID", type: "string" },
6421
+ { path: "sentAt", displayName: "Sent At", type: "string", description: "ISO timestamp when sent" }
6422
+ ];
6423
+
6424
+ // src/core/lib/actionRegistry/actions/gmail/emailSend.ts
6425
+ registerAction({
6426
+ type: "qi/gmail.email.send",
6427
+ can: "gmail.email/send",
6428
+ sideEffect: true,
6429
+ defaultRequiresConfirmation: true,
6430
+ requiredCapability: "flow/block/execute",
6431
+ // Can be wired to another block's event (e.g. form submitted → send email).
6432
+ eligibleForEventTrigger: true,
6433
+ outputSchema: GMAIL_SEND_OUTPUT_SCHEMA,
6434
+ events: [
6435
+ {
6436
+ name: GMAIL_SENT_EVENT,
6437
+ displayName: "Email sent",
6438
+ description: "Fired after the email is sent from the author\u2019s Gmail.",
6439
+ payloadSchema: [
6440
+ { path: "messageId", displayName: "Message ID", type: "string" },
6441
+ { path: "recipient_email", displayName: "To", type: "string" }
6442
+ ],
6443
+ pendingDisplayFields: ["messageId"]
6444
+ }
6445
+ ],
6446
+ run: async (inputs, ctx) => {
6447
+ const parsed = parseDelegatedToolInputs(inputs);
6448
+ const values = fieldValues(parsed);
6449
+ const data = await executeDelegatedTool(ctx, {
6450
+ connection: parsed.connection,
6451
+ schema: GMAIL_SEND_SCHEMA,
6452
+ toolSlug: GMAIL_SEND_SLUG,
6453
+ values,
6454
+ toolkitLabel: "Gmail"
6455
+ });
6456
+ const envelope = data.response_data ?? data;
6457
+ const messageId = String(envelope.id ?? envelope.messageId ?? "");
6458
+ const threadId = String(envelope.threadId ?? "");
6459
+ return {
6460
+ output: {
6461
+ messageId,
6462
+ threadId,
6463
+ sentAt: (/* @__PURE__ */ new Date()).toISOString()
6464
+ },
6465
+ events: messageId ? [{ name: GMAIL_SENT_EVENT, payload: { messageId, recipient_email: values.recipient_email ?? "" } }] : void 0
6466
+ };
6467
+ }
6468
+ });
6469
+
6470
+ // src/core/lib/actionRegistry/actions/outlook/emailSend.types.ts
6471
+ var OUTLOOK_SEND_SLUG = "OUTLOOK_OUTLOOK_SEND_EMAIL";
6472
+ var OUTLOOK_SENT_EVENT = "email.sent";
6473
+ var OUTLOOK_SEND_SCHEMA = {
6474
+ slug: OUTLOOK_SEND_SLUG,
6475
+ name: "Send Email",
6476
+ description: "Send an email from the template author's Outlook account.",
6477
+ parameters: {
6478
+ type: "object",
6479
+ required: ["subject", "body", "to_email"],
6480
+ properties: {
6481
+ to_email: { type: "string", title: "To", description: "Recipient's email address." },
6482
+ to_name: { type: "string", title: "To name", description: "Optional display name for the recipient." },
6483
+ subject: { type: "string", title: "Subject" },
6484
+ body: { type: "string", title: "Body", description: 'Email body. Plain text unless "HTML body" is set.' },
6485
+ cc_emails: { type: "array", title: "Cc", description: "Comma-separated email addresses." },
6486
+ bcc_emails: { type: "array", title: "Bcc", description: "Comma-separated email addresses." },
6487
+ is_html: { type: "boolean", title: "HTML body", description: "Render the body as HTML." }
6488
+ }
6489
+ }
6490
+ };
6491
+ var OUTLOOK_SEND_OUTPUT_SCHEMA = [
6492
+ { path: "messageId", displayName: "Message ID", type: "string" },
6493
+ { path: "sentAt", displayName: "Sent At", type: "string", description: "ISO timestamp when sent" }
6494
+ ];
6495
+
6496
+ // src/core/lib/actionRegistry/actions/outlook/emailSend.ts
6497
+ registerAction({
6498
+ type: "qi/outlook.email.send",
6499
+ can: "outlook.email/send",
6500
+ sideEffect: true,
6501
+ defaultRequiresConfirmation: true,
6502
+ requiredCapability: "flow/block/execute",
6503
+ // Can be wired to another block's event (e.g. form submitted → send email).
6504
+ eligibleForEventTrigger: true,
6505
+ outputSchema: OUTLOOK_SEND_OUTPUT_SCHEMA,
6506
+ events: [
6507
+ {
6508
+ name: OUTLOOK_SENT_EVENT,
6509
+ displayName: "Email sent",
6510
+ description: "Fired after the email is sent from the author\u2019s Outlook.",
6511
+ payloadSchema: [
6512
+ { path: "messageId", displayName: "Message ID", type: "string" },
6513
+ { path: "to_email", displayName: "To", type: "string" }
6514
+ ],
6515
+ pendingDisplayFields: ["messageId"]
6516
+ }
6517
+ ],
6518
+ run: async (inputs, ctx) => {
6519
+ const parsed = parseDelegatedToolInputs(inputs);
6520
+ const values = fieldValues(parsed);
6521
+ const data = await executeDelegatedTool(ctx, {
6522
+ connection: parsed.connection,
6523
+ schema: OUTLOOK_SEND_SCHEMA,
6524
+ toolSlug: OUTLOOK_SEND_SLUG,
6525
+ values,
6526
+ toolkitLabel: "Outlook"
6527
+ });
6528
+ const envelope = data.response_data ?? data;
6529
+ const messageId = String(envelope.id ?? envelope.messageId ?? "");
6530
+ return {
6531
+ output: {
6532
+ messageId,
6533
+ sentAt: (/* @__PURE__ */ new Date()).toISOString()
6534
+ },
6535
+ // Outlook often returns no id, so emit unconditionally.
6536
+ events: [{ name: OUTLOOK_SENT_EVENT, payload: { messageId, to_email: values.to_email ?? "" } }]
6537
+ };
6538
+ }
6539
+ });
6540
+
6541
+ // src/core/lib/actionRegistry/actions/slack/messageSend.types.ts
6542
+ var SLACK_SEND_SLUG = "SLACK_CHAT_POST_MESSAGE";
6543
+ var SLACK_SENT_EVENT = "message.sent";
6544
+ var SLACK_SEND_SCHEMA = {
6545
+ slug: SLACK_SEND_SLUG,
6546
+ name: "Post Message",
6547
+ description: "Post a message to a Slack channel from the template author's Slack account.",
6548
+ parameters: {
6549
+ type: "object",
6550
+ required: ["channel"],
6551
+ properties: {
6552
+ channel: { type: "string", title: "Channel", description: "Channel ID or name, e.g. #general or C0123456." },
6553
+ markdown_text: {
6554
+ type: "string",
6555
+ title: "Message",
6556
+ description: "Message text in Slack markdown. Preferred over the deprecated plain text field."
6557
+ },
6558
+ thread_ts: { type: "string", title: "Thread", description: "Optional parent message timestamp to reply within a thread." }
6559
+ }
6560
+ }
6561
+ };
6562
+ var SLACK_SEND_OUTPUT_SCHEMA = [
6563
+ { path: "messageTs", displayName: "Message ts", type: "string" },
6564
+ { path: "channel", displayName: "Channel", type: "string" },
6565
+ { path: "sentAt", displayName: "Sent At", type: "string", description: "ISO timestamp when sent" }
6566
+ ];
6567
+
6568
+ // src/core/lib/actionRegistry/actions/slack/messageSend.ts
6569
+ registerAction({
6570
+ type: "qi/slack.message.send",
6571
+ can: "slack.message/send",
6572
+ sideEffect: true,
6573
+ defaultRequiresConfirmation: true,
6574
+ requiredCapability: "flow/block/execute",
6575
+ // Can be wired to another block's event (e.g. form submitted → post message).
6576
+ eligibleForEventTrigger: true,
6577
+ outputSchema: SLACK_SEND_OUTPUT_SCHEMA,
6578
+ events: [
6579
+ {
6580
+ name: SLACK_SENT_EVENT,
6581
+ displayName: "Message posted",
6582
+ description: "Fired after the message is posted to Slack.",
6583
+ payloadSchema: [
6584
+ { path: "messageTs", displayName: "Message ts", type: "string" },
6585
+ { path: "channel", displayName: "Channel", type: "string" }
6586
+ ],
6587
+ pendingDisplayFields: ["messageTs"]
6588
+ }
6589
+ ],
6590
+ run: async (inputs, ctx) => {
6591
+ const parsed = parseDelegatedToolInputs(inputs);
6592
+ const values = fieldValues(parsed);
6593
+ const data = await executeDelegatedTool(ctx, {
6594
+ connection: parsed.connection,
6595
+ schema: SLACK_SEND_SCHEMA,
6596
+ toolSlug: SLACK_SEND_SLUG,
6597
+ values,
6598
+ toolkitLabel: "Slack"
6599
+ });
6600
+ const envelope = data.response_data ?? data;
6601
+ const messageTs = String(envelope.ts ?? "");
6602
+ const channel = String(envelope.channel ?? values.channel ?? "");
6603
+ return {
6604
+ output: {
6605
+ messageTs,
6606
+ channel,
6607
+ sentAt: (/* @__PURE__ */ new Date()).toISOString()
6608
+ },
6609
+ events: messageTs ? [{ name: SLACK_SENT_EVENT, payload: { messageTs, channel } }] : void 0
6610
+ };
6611
+ }
6612
+ });
6613
+
6614
+ // src/core/lib/actionRegistry/actions/googlecalendar/eventCreate.types.ts
6615
+ var GOOGLECALENDAR_CREATE_SLUG = "GOOGLECALENDAR_CREATE_EVENT";
6616
+ var GOOGLECALENDAR_CREATED_EVENT = "event.created";
6617
+ var GOOGLECALENDAR_CREATE_SCHEMA = {
6618
+ slug: GOOGLECALENDAR_CREATE_SLUG,
6619
+ name: "Create Event",
6620
+ description: "Create an event on the template author's Google Calendar.",
6621
+ parameters: {
6622
+ type: "object",
6623
+ required: ["start_datetime"],
6624
+ properties: {
6625
+ start_datetime: { type: "string", title: "Start time", description: "ISO 8601, e.g. 2026-05-12T09:00:00." },
6626
+ summary: { type: "string", title: "Title" },
6627
+ description: { type: "string", title: "Description" },
6628
+ location: { type: "string", title: "Location" },
6629
+ timezone: { type: "string", title: "Timezone", description: "IANA name, e.g. Europe/London." },
6630
+ attendees: { type: "array", title: "Attendees", description: "Comma-separated email addresses." },
6631
+ calendar_id: { type: "string", title: "Calendar", description: "Use 'primary' for the author's main calendar." },
6632
+ event_duration_minutes: { type: "number", title: "Duration (minutes)", description: "Defaults to the calendar default if blank." }
6633
+ }
6634
+ }
6635
+ };
6636
+ var GOOGLECALENDAR_CREATE_OUTPUT_SCHEMA = [
6637
+ { path: "eventId", displayName: "Event ID", type: "string" },
6638
+ { path: "htmlLink", displayName: "Event link", type: "string" },
6639
+ { path: "summary", displayName: "Summary", type: "string" },
6640
+ { path: "startIso", displayName: "Start", type: "string" }
6641
+ ];
6642
+
6643
+ // src/core/lib/actionRegistry/actions/googlecalendar/eventCreate.ts
6644
+ registerAction({
6645
+ type: "qi/googlecalendar.event.create",
6646
+ can: "googlecalendar.event/create",
6647
+ sideEffect: true,
6648
+ defaultRequiresConfirmation: true,
6649
+ requiredCapability: "flow/block/execute",
6650
+ eligibleForEventTrigger: true,
6651
+ outputSchema: GOOGLECALENDAR_CREATE_OUTPUT_SCHEMA,
6652
+ events: [
6653
+ {
6654
+ name: GOOGLECALENDAR_CREATED_EVENT,
6655
+ displayName: "Calendar event created",
6656
+ description: "Fired after the event is created on the author\u2019s calendar.",
6657
+ payloadSchema: [
6658
+ { path: "eventId", displayName: "Event ID", type: "string" },
6659
+ { path: "htmlLink", displayName: "Event link", type: "string" },
6660
+ { path: "summary", displayName: "Summary", type: "string" }
6661
+ ],
6662
+ pendingDisplayFields: ["summary", "eventId"]
6663
+ }
6664
+ ],
6665
+ run: async (inputs, ctx) => {
6666
+ const parsed = parseDelegatedToolInputs(inputs);
6667
+ const values = fieldValues(parsed);
6668
+ const data = await executeDelegatedTool(ctx, {
6669
+ connection: parsed.connection,
6670
+ schema: GOOGLECALENDAR_CREATE_SCHEMA,
6671
+ toolSlug: GOOGLECALENDAR_CREATE_SLUG,
6672
+ values,
6673
+ toolkitLabel: "Google Calendar"
6674
+ });
6675
+ const envelope = data.response_data ?? data;
6676
+ const eventId = String(envelope.id ?? "");
6677
+ const htmlLink = String(envelope.htmlLink ?? "");
6678
+ const summary = String(envelope.summary ?? values.summary ?? "");
6679
+ const start = envelope.start;
6680
+ const startIso = String(start?.dateTime ?? start?.date ?? values.start_datetime ?? "");
6681
+ return {
6682
+ output: { eventId, htmlLink, summary, startIso },
6683
+ events: eventId ? [{ name: GOOGLECALENDAR_CREATED_EVENT, payload: { eventId, htmlLink, summary } }] : void 0
6684
+ };
6685
+ }
6686
+ });
6687
+
6295
6688
  // src/core/lib/actionRegistry/actions/calendar/eventCreate.types.ts
6296
6689
  var EMPTY = {
6297
6690
  connection: null,
@@ -10725,6 +11118,9 @@ function compileBaseUcanFlow(plan, registry) {
10725
11118
  if (cap.condition) {
10726
11119
  props.conditions = compileCondition(cap.condition, blockIndex);
10727
11120
  }
11121
+ if (cap.trigger) {
11122
+ props.trigger = compileTrigger(cap.trigger, blockIndex);
11123
+ }
10728
11124
  props.triggerMode = cap.trigger?.type || "manual";
10729
11125
  blocks.push({
10730
11126
  id: blockId,
@@ -10795,6 +11191,18 @@ function compileCondition(condition, blockIndex) {
10795
11191
  };
10796
11192
  return JSON.stringify(conditionConfig);
10797
11193
  }
11194
+ function compileTrigger(trigger, blockIndex) {
11195
+ if (trigger.type === "block.event" && trigger.sourceBlockId) {
11196
+ return JSON.stringify({ ...trigger, sourceBlockId: blockIndex[trigger.sourceBlockId.trim()] });
11197
+ }
11198
+ if (trigger.type === "block.event.all" && trigger.sources) {
11199
+ return JSON.stringify({
11200
+ ...trigger,
11201
+ sources: trigger.sources.map((src) => ({ ...src, sourceBlockId: blockIndex[src.sourceBlockId.trim()] }))
11202
+ });
11203
+ }
11204
+ return JSON.stringify(trigger);
11205
+ }
10798
11206
  function collectOutputRefs(value) {
10799
11207
  const refs = [];
10800
11208
  walk(value);
@@ -11150,9 +11558,13 @@ function mergeCompiledFlows(existing, incoming, strategy) {
11150
11558
 
11151
11559
  // src/core/lib/flowCompiler/decompile.ts
11152
11560
  function decompileToBaseUcanFlow(compiled) {
11561
+ const nodeIdByBlockId = {};
11562
+ for (const [nodeId, blockId] of Object.entries(compiled.blockIndex)) {
11563
+ nodeIdByBlockId[blockId] = nodeId;
11564
+ }
11153
11565
  const capabilities = compiled.order.map((nodeId) => {
11154
11566
  const node = compiled.nodes[nodeId];
11155
- return nodeToCapability(node);
11567
+ return nodeToCapability(node, nodeIdByBlockId);
11156
11568
  });
11157
11569
  return {
11158
11570
  kind: "qi.flow.base-ucan",
@@ -11167,7 +11579,7 @@ function decompileToBaseUcanFlow(compiled) {
11167
11579
  capabilities
11168
11580
  };
11169
11581
  }
11170
- function nodeToCapability(node) {
11582
+ function nodeToCapability(node, nodeIdByBlockId) {
11171
11583
  const cap = {
11172
11584
  id: node.id,
11173
11585
  can: node.can,
@@ -11202,7 +11614,7 @@ function nodeToCapability(node) {
11202
11614
  try {
11203
11615
  const trigger = JSON.parse(node.props.trigger);
11204
11616
  if (trigger && typeof trigger === "object" && typeof trigger.type === "string") {
11205
- cap.trigger = trigger;
11617
+ cap.trigger = triggerToNodeIds(trigger, nodeIdByBlockId);
11206
11618
  }
11207
11619
  } catch {
11208
11620
  }
@@ -11218,6 +11630,18 @@ function nodeToCapability(node) {
11218
11630
  }
11219
11631
  return cap;
11220
11632
  }
11633
+ function triggerToNodeIds(trigger, nodeIdByBlockId) {
11634
+ if (trigger.type === "block.event" && trigger.sourceBlockId) {
11635
+ return { ...trigger, sourceBlockId: nodeIdByBlockId[trigger.sourceBlockId] ?? trigger.sourceBlockId };
11636
+ }
11637
+ if (trigger.type === "block.event.all" && trigger.sources) {
11638
+ return {
11639
+ ...trigger,
11640
+ sources: trigger.sources.map((src) => ({ ...src, sourceBlockId: nodeIdByBlockId[src.sourceBlockId] ?? src.sourceBlockId }))
11641
+ };
11642
+ }
11643
+ return trigger;
11644
+ }
11221
11645
 
11222
11646
  // src/core/lib/flowCompiler/setup.ts
11223
11647
  import * as Y7 from "yjs";
@@ -12851,6 +13275,14 @@ export {
12851
13275
  didToMatrixUserId,
12852
13276
  findOrCreateDMRoom,
12853
13277
  sendDirectMessage,
13278
+ parseDelegatedToolInputs,
13279
+ serializeDelegatedToolInputs,
13280
+ fieldValues,
13281
+ missingRequired,
13282
+ GMAIL_SEND_SCHEMA,
13283
+ OUTLOOK_SEND_SCHEMA,
13284
+ SLACK_SEND_SCHEMA,
13285
+ GOOGLECALENDAR_CREATE_SCHEMA,
12854
13286
  parseCalendarEventCreateInputs,
12855
13287
  serializeCalendarEventCreateInputs,
12856
13288
  parseAttendeesField,
@@ -12942,4 +13374,4 @@ export {
12942
13374
  executeQueuedFlowAgentCoreCommands,
12943
13375
  FlowAgentService
12944
13376
  };
12945
- //# sourceMappingURL=chunk-OOPKMGYW.mjs.map
13377
+ //# sourceMappingURL=chunk-YWZJYSOP.js.map