@builder.io/ai-utils 0.32.1 → 0.33.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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@builder.io/ai-utils",
3
- "version": "0.32.1",
3
+ "version": "0.33.0",
4
4
  "description": "Builder.io AI utils",
5
5
  "type": "module",
6
6
  "main": "src/index.js",
package/src/claw.d.ts CHANGED
@@ -44,7 +44,39 @@ export interface ParsedChannelId {
44
44
  * "inbox/user/builder-user-id" → { platform: "inbox", type: "user", ids: ["builder-user-id"] }
45
45
  */
46
46
  export declare function parseChannelId(channelId: string): ParsedChannelId;
47
+ /**
48
+ * Converts a Builder channel_id URI to a clickable URL for the
49
+ * corresponding platform (Slack, Jira, etc.).
50
+ *
51
+ * Supported formats:
52
+ *
53
+ * Slack (uses app_redirect URLs - works for all workspaces):
54
+ * slack/thread/TEAM_ID/CHANNEL_ID/THREAD_TS
55
+ * → https://slack.com/app_redirect?team=TEAM_ID&channel=CHANNEL_ID&message_ts=THREAD_TS
56
+ * slack/channel/TEAM_ID/CHANNEL_ID
57
+ * → https://slack.com/app_redirect?team=TEAM_ID&channel=CHANNEL_ID
58
+ * slack/dm/TEAM_ID/USER_ID
59
+ * → https://slack.com/app_redirect?team=TEAM_ID&channel=USER_ID
60
+ *
61
+ * Jira:
62
+ * Returns null - needs integration.baseUrl from database
63
+ * (Future: jira/comment/CLOUD_ID/ISSUE_KEY → {baseUrl}/browse/ISSUE_KEY)
64
+ *
65
+ * Returns null for unsupported platforms or malformed channel IDs.
66
+ *
67
+ * TODO: Accept optional integration metadata parameter to construct proper
68
+ * workspace-specific URLs (Slack teamDomain, Jira baseUrl).
69
+ */
70
+ export declare function convertChannelIdToUrl(channelId: string): string | null;
47
71
  export interface WorkerReportOptions {
72
+ /** The original user's channel that triggered this work. */
73
+ originChannelId?: string;
74
+ /** The report content. */
75
+ content: string;
76
+ /** Agent/tool ID (for sub-agent reports). */
77
+ agentId: string;
78
+ }
79
+ export interface WorkerMessageOptions {
48
80
  /** The original user's channel that triggered this work. */
49
81
  originChannelId?: string;
50
82
  /** The report content. */
@@ -53,8 +85,6 @@ export interface WorkerReportOptions {
53
85
  projectId?: string;
54
86
  /** Branch name (for branch reports). */
55
87
  branchName?: string;
56
- /** Agent/tool ID (for sub-agent reports). */
57
- agentId?: string;
58
88
  }
59
89
  /**
60
90
  * Formats a `<worker_report>` message for the org-agent.
@@ -64,6 +94,7 @@ export interface WorkerReportOptions {
64
94
  * correct user channel.
65
95
  */
66
96
  export declare function formatWorkerReport(opts: WorkerReportOptions): string;
97
+ export declare function formatWorkerMessage(opts: WorkerMessageOptions): string;
67
98
  export interface IncomingMessageOptions {
68
99
  /** The source channel (e.g. slack/thread/TEAM/CHANNEL/TS). */
69
100
  channelId: string;
package/src/claw.js CHANGED
@@ -16,6 +16,78 @@ export function parseChannelId(channelId) {
16
16
  const [platform, type, ...ids] = parts;
17
17
  return { platform, type, ids };
18
18
  }
19
+ /**
20
+ * Converts a Builder channel_id URI to a clickable URL for the
21
+ * corresponding platform (Slack, Jira, etc.).
22
+ *
23
+ * Supported formats:
24
+ *
25
+ * Slack (uses app_redirect URLs - works for all workspaces):
26
+ * slack/thread/TEAM_ID/CHANNEL_ID/THREAD_TS
27
+ * → https://slack.com/app_redirect?team=TEAM_ID&channel=CHANNEL_ID&message_ts=THREAD_TS
28
+ * slack/channel/TEAM_ID/CHANNEL_ID
29
+ * → https://slack.com/app_redirect?team=TEAM_ID&channel=CHANNEL_ID
30
+ * slack/dm/TEAM_ID/USER_ID
31
+ * → https://slack.com/app_redirect?team=TEAM_ID&channel=USER_ID
32
+ *
33
+ * Jira:
34
+ * Returns null - needs integration.baseUrl from database
35
+ * (Future: jira/comment/CLOUD_ID/ISSUE_KEY → {baseUrl}/browse/ISSUE_KEY)
36
+ *
37
+ * Returns null for unsupported platforms or malformed channel IDs.
38
+ *
39
+ * TODO: Accept optional integration metadata parameter to construct proper
40
+ * workspace-specific URLs (Slack teamDomain, Jira baseUrl).
41
+ */
42
+ export function convertChannelIdToUrl(channelId) {
43
+ let parsed;
44
+ try {
45
+ parsed = parseChannelId(channelId);
46
+ }
47
+ catch (_a) {
48
+ return null;
49
+ }
50
+ const { platform, type, ids } = parsed;
51
+ if (platform === "slack") {
52
+ return slackChannelIdToUrl(type, ids);
53
+ }
54
+ // Jira URLs need integration.baseUrl from database - not available here
55
+ // TODO: Add integration metadata parameter to support Jira URLs
56
+ if (platform === "jira") {
57
+ return null;
58
+ }
59
+ return null;
60
+ }
61
+ function slackChannelIdToUrl(type, ids) {
62
+ // Use app_redirect URLs for all Slack types - they work universally across
63
+ // all workspaces without needing to know the workspace domain.
64
+ // These URLs open in the Slack app or web client automatically.
65
+ if (type === "thread") {
66
+ // slack/thread/TEAM_ID/CHANNEL_ID/THREAD_TS
67
+ const [teamId, slackChannelId, threadTs] = ids;
68
+ if (!teamId || !slackChannelId || !threadTs) {
69
+ return null;
70
+ }
71
+ return `https://slack.com/app_redirect?team=${teamId}&channel=${slackChannelId}&message_ts=${threadTs}`;
72
+ }
73
+ if (type === "channel") {
74
+ // slack/channel/TEAM_ID/CHANNEL_ID
75
+ const [teamId, slackChannelId] = ids;
76
+ if (!teamId || !slackChannelId) {
77
+ return null;
78
+ }
79
+ return `https://slack.com/app_redirect?team=${teamId}&channel=${slackChannelId}`;
80
+ }
81
+ if (type === "dm") {
82
+ // slack/dm/TEAM_ID/USER_ID
83
+ const [teamId, userId] = ids;
84
+ if (!teamId || !userId) {
85
+ return null;
86
+ }
87
+ return `https://slack.com/app_redirect?team=${teamId}&channel=${userId}`;
88
+ }
89
+ return null;
90
+ }
19
91
  // ── Org-agent message formatting ──
20
92
  //
21
93
  // The org-agent receives two kinds of messages in its conversation:
@@ -36,19 +108,33 @@ export function formatWorkerReport(opts) {
36
108
  let xml = `<worker_report>\n`;
37
109
  if (opts.originChannelId) {
38
110
  xml += `<origin_channel_id>${opts.originChannelId}</origin_channel_id>\n`;
111
+ const url = convertChannelIdToUrl(opts.originChannelId);
112
+ if (url) {
113
+ xml += `<origin_channel_url>${url}</origin_channel_url>\n`;
114
+ }
39
115
  }
40
- if (opts.projectId) {
41
- xml += `<project_id>${opts.projectId}</project_id>\n`;
116
+ xml += `<agent_id>${opts.agentId}</agent_id>\n`;
117
+ xml += `<content>${opts.content}</content>\n`;
118
+ xml += `</worker_report>\n`;
119
+ xml += WORKER_REPORT_TRAILER;
120
+ return xml;
121
+ }
122
+ export function formatWorkerMessage(opts) {
123
+ let xml = `<worker_message>\n`;
124
+ if (opts.originChannelId) {
125
+ xml += `<origin_channel_id>${opts.originChannelId}</origin_channel_id>\n`;
126
+ const url = convertChannelIdToUrl(opts.originChannelId);
127
+ if (url) {
128
+ xml += `<origin_channel_url>${url}</origin_channel_url>\n`;
129
+ }
42
130
  }
43
- if (opts.branchName && opts.projectId) {
131
+ if (opts.projectId && opts.branchName) {
132
+ xml += `<project_id>${opts.projectId}</project_id>\n`;
44
133
  xml += `<branch_name>${opts.branchName}</branch_name>\n`;
45
134
  xml += `<channel_id>builder/branch/${opts.projectId}/${opts.branchName}</channel_id>\n`;
46
135
  }
47
- if (opts.agentId) {
48
- xml += `<agent_id>${opts.agentId}</agent_id>\n`;
49
- }
50
136
  xml += `<content>${opts.content}</content>\n`;
51
- xml += `</worker_report>\n`;
137
+ xml += `</worker_message>\n`;
52
138
  xml += WORKER_REPORT_TRAILER;
53
139
  return xml;
54
140
  }
@@ -65,6 +151,10 @@ export function formatIncomingMessage(opts) {
65
151
  }
66
152
  result += `<incoming_message>\n`;
67
153
  result += `<channel_id>${opts.channelId}</channel_id>\n`;
154
+ const channelUrl = convertChannelIdToUrl(opts.channelId);
155
+ if (channelUrl) {
156
+ result += `<channel_url>${channelUrl}</channel_url>\n`;
157
+ }
68
158
  if (opts.dmId) {
69
159
  result += `<dm_id>${opts.dmId}</dm_id>\n`;
70
160
  }
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,200 @@
1
+ import { describe, it, expect } from "vitest";
2
+ import { convertChannelIdToUrl, formatIncomingMessage, formatWorkerMessage, formatWorkerReport, } from "./claw";
3
+ describe("convertChannelIdToUrl", () => {
4
+ describe("slack/thread format", () => {
5
+ it("converts a thread channel ID to a Slack app_redirect URL", () => {
6
+ const url = convertChannelIdToUrl("slack/thread/T01ABC123/C01DEF456/1700000000.123456");
7
+ expect(url).toBe("https://slack.com/app_redirect?team=T01ABC123&channel=C01DEF456&message_ts=1700000000.123456");
8
+ });
9
+ it("handles timestamps with dots correctly", () => {
10
+ const url = convertChannelIdToUrl("slack/thread/TTEAM/CCHAN/1234567890.000100");
11
+ expect(url).toBe("https://slack.com/app_redirect?team=TTEAM&channel=CCHAN&message_ts=1234567890.000100");
12
+ });
13
+ it("returns null when teamId is missing", () => {
14
+ expect(convertChannelIdToUrl("slack/thread/CCHAN/1234567890.000100")).toBeNull();
15
+ });
16
+ it("returns null when channelId is missing", () => {
17
+ expect(convertChannelIdToUrl("slack/thread/TTEAM/1234567890.000100")).toBeNull();
18
+ });
19
+ it("returns null when threadTs is missing", () => {
20
+ expect(convertChannelIdToUrl("slack/thread/TTEAM/CCHAN")).toBeNull();
21
+ });
22
+ });
23
+ describe("slack/channel format", () => {
24
+ it("converts a channel ID to a Slack app_redirect URL", () => {
25
+ const url = convertChannelIdToUrl("slack/channel/T01ABC123/C01DEF456");
26
+ expect(url).toBe("https://slack.com/app_redirect?team=T01ABC123&channel=C01DEF456");
27
+ });
28
+ it("returns null when teamId is missing", () => {
29
+ expect(convertChannelIdToUrl("slack/channel/C01DEF456")).toBeNull();
30
+ });
31
+ it("returns null when channelId is missing", () => {
32
+ expect(convertChannelIdToUrl("slack/channel/TTEAM")).toBeNull();
33
+ });
34
+ });
35
+ describe("slack/dm format", () => {
36
+ it("converts a DM channel ID to a Slack app_redirect URL", () => {
37
+ const url = convertChannelIdToUrl("slack/dm/T01ABC123/U01XYZ789");
38
+ expect(url).toBe("https://slack.com/app_redirect?team=T01ABC123&channel=U01XYZ789");
39
+ });
40
+ it("returns null when teamId is missing", () => {
41
+ expect(convertChannelIdToUrl("slack/dm/U01XYZ789")).toBeNull();
42
+ });
43
+ it("returns null when userId is missing", () => {
44
+ expect(convertChannelIdToUrl("slack/dm/TTEAM")).toBeNull();
45
+ });
46
+ });
47
+ describe("jira/comment format", () => {
48
+ it("returns null (needs integration.baseUrl from database)", () => {
49
+ const url = convertChannelIdToUrl("jira/comment/cloud-id/PROJ-123");
50
+ expect(url).toBeNull();
51
+ });
52
+ });
53
+ describe("unsupported platforms", () => {
54
+ it("returns null for telegram channel IDs", () => {
55
+ expect(convertChannelIdToUrl("telegram/chat/123456")).toBeNull();
56
+ });
57
+ it("returns null for builder branch channel IDs", () => {
58
+ expect(convertChannelIdToUrl("builder/branch/proj-id/my-branch")).toBeNull();
59
+ });
60
+ it("returns null for inbox channel IDs", () => {
61
+ expect(convertChannelIdToUrl("inbox/user/user-id")).toBeNull();
62
+ });
63
+ it("returns null for internal channel IDs", () => {
64
+ expect(convertChannelIdToUrl("internal/support")).toBeNull();
65
+ });
66
+ it("returns null for completely invalid input", () => {
67
+ expect(convertChannelIdToUrl("not-a-channel-id")).toBeNull();
68
+ });
69
+ it("returns null for empty string", () => {
70
+ expect(convertChannelIdToUrl("")).toBeNull();
71
+ });
72
+ });
73
+ });
74
+ describe("formatIncomingMessage", () => {
75
+ it("includes channel_url for Slack thread channel IDs", () => {
76
+ const result = formatIncomingMessage({
77
+ channelId: "slack/thread/TTEAM/CCHAN/1234567890.000100",
78
+ sender: "Alice",
79
+ timestamp: "Monday, January 1, 2024 at 10:00 AM PST",
80
+ content: "Hello!",
81
+ });
82
+ expect(result).toContain("<channel_url>https://slack.com/app_redirect?team=TTEAM&channel=CCHAN&message_ts=1234567890.000100</channel_url>");
83
+ });
84
+ it("includes channel_url for Slack channel IDs", () => {
85
+ const result = formatIncomingMessage({
86
+ channelId: "slack/channel/TTEAM/CCHAN",
87
+ sender: "Bob",
88
+ timestamp: "Tuesday, January 2, 2024 at 11:00 AM PST",
89
+ content: "Hey there",
90
+ });
91
+ expect(result).toContain("<channel_url>https://slack.com/app_redirect?team=TTEAM&channel=CCHAN</channel_url>");
92
+ });
93
+ it("does not include channel_url for Jira (needs integration.baseUrl)", () => {
94
+ const result = formatIncomingMessage({
95
+ channelId: "jira/comment/cloud-id/PROJ-123",
96
+ sender: "Charlie",
97
+ timestamp: "Wednesday, January 3, 2024 at 12:00 PM PST",
98
+ content: "Jira comment",
99
+ });
100
+ expect(result).not.toContain("<channel_url>");
101
+ });
102
+ it("does not include channel_url for unsupported platforms", () => {
103
+ const result = formatIncomingMessage({
104
+ channelId: "telegram/chat/123456",
105
+ sender: "Charlie",
106
+ timestamp: "Wednesday, January 3, 2024 at 12:00 PM PST",
107
+ content: "Telegram message",
108
+ });
109
+ expect(result).not.toContain("<channel_url>");
110
+ });
111
+ it("includes dm_id without generating dm_url", () => {
112
+ const result = formatIncomingMessage({
113
+ channelId: "slack/thread/TTEAM/CCHAN/1234567890.000100",
114
+ dmId: "slack/dm/TTEAM/UUSER",
115
+ sender: "Dave",
116
+ timestamp: "Thursday, January 4, 2024 at 1:00 PM PST",
117
+ content: "DM context",
118
+ });
119
+ expect(result).toContain("<dm_id>slack/dm/TTEAM/UUSER</dm_id>");
120
+ expect(result).not.toContain("<dm_url>");
121
+ });
122
+ it("preserves all other fields unchanged", () => {
123
+ const result = formatIncomingMessage({
124
+ channelId: "slack/thread/TTEAM/CCHAN/1234567890.000100",
125
+ sender: "Frank",
126
+ timestamp: "Saturday, January 6, 2024 at 3:00 PM PST",
127
+ content: "Test message",
128
+ messageContext: "Prior context",
129
+ });
130
+ expect(result).toContain("<channel_id>slack/thread/TTEAM/CCHAN/1234567890.000100</channel_id>");
131
+ expect(result).toContain("<sender>Frank</sender>");
132
+ expect(result).toContain("Prior context");
133
+ });
134
+ });
135
+ describe("formatWorkerMessage", () => {
136
+ it("includes origin_channel_url for Slack originChannelId", () => {
137
+ const result = formatWorkerMessage({
138
+ originChannelId: "slack/thread/TTEAM/CCHAN/1234567890.000100",
139
+ content: "Worker result",
140
+ projectId: "proj-123",
141
+ branchName: "feat/my-feature",
142
+ });
143
+ expect(result).toContain("<origin_channel_url>https://slack.com/app_redirect?team=TTEAM&channel=CCHAN&message_ts=1234567890.000100</origin_channel_url>");
144
+ });
145
+ it("does not include origin_channel_url for Jira (needs integration.baseUrl)", () => {
146
+ const result = formatWorkerMessage({
147
+ originChannelId: "jira/comment/cloud-id/PROJ-456",
148
+ content: "Worker result",
149
+ });
150
+ expect(result).not.toContain("<origin_channel_url>");
151
+ });
152
+ it("does not include origin_channel_url for unsupported platforms", () => {
153
+ const result = formatWorkerMessage({
154
+ originChannelId: "builder/branch/proj-id/my-branch",
155
+ content: "Worker result",
156
+ });
157
+ expect(result).not.toContain("<origin_channel_url>");
158
+ });
159
+ it("omits origin_channel_url when originChannelId is absent", () => {
160
+ const result = formatWorkerMessage({
161
+ content: "Worker result without origin",
162
+ });
163
+ expect(result).not.toContain("<origin_channel_url>");
164
+ expect(result).not.toContain("<origin_channel_id>");
165
+ });
166
+ it("uses matching XML tags (worker_message, not worker_report)", () => {
167
+ const result = formatWorkerMessage({
168
+ content: "Test content",
169
+ });
170
+ expect(result).toContain("<worker_message>");
171
+ expect(result).toContain("</worker_message>");
172
+ expect(result).not.toContain("</worker_report>");
173
+ });
174
+ });
175
+ describe("formatWorkerReport", () => {
176
+ it("includes origin_channel_url for Slack originChannelId", () => {
177
+ const result = formatWorkerReport({
178
+ originChannelId: "slack/channel/TTEAM/CCHAN",
179
+ content: "Report content",
180
+ agentId: "agent-abc",
181
+ });
182
+ expect(result).toContain("<origin_channel_url>https://slack.com/app_redirect?team=TTEAM&channel=CCHAN</origin_channel_url>");
183
+ });
184
+ it("does not include origin_channel_url for Jira (needs integration.baseUrl)", () => {
185
+ const result = formatWorkerReport({
186
+ originChannelId: "jira/comment/cloud-id/PROJ-789",
187
+ content: "Report content",
188
+ agentId: "agent-xyz",
189
+ });
190
+ expect(result).not.toContain("<origin_channel_url>");
191
+ });
192
+ it("does not include origin_channel_url for unsupported platforms", () => {
193
+ const result = formatWorkerReport({
194
+ originChannelId: "telegram/chat/123456",
195
+ content: "Report content",
196
+ agentId: "agent-xyz",
197
+ });
198
+ expect(result).not.toContain("<origin_channel_url>");
199
+ });
200
+ });
package/src/codegen.d.ts CHANGED
@@ -45,6 +45,7 @@ export interface CustomAgentDefinition {
45
45
  systemPrompt?: string;
46
46
  tools?: string[];
47
47
  model?: string;
48
+ roundRobinModels?: string[];
48
49
  mode?: CodeGenMode;
49
50
  position?: string;
50
51
  needDevServer?: boolean;
@@ -554,6 +555,11 @@ export interface SendMessageToolInput {
554
555
  markdown: string;
555
556
  status: "starting" | "question" | "will-follow-up" | "done:success" | "done:error";
556
557
  loadingMessage?: string;
558
+ /**
559
+ * When true, send the response as a voice message using text-to-speech.
560
+ * Only supported for Telegram channels.
561
+ */
562
+ voiceResponse?: boolean;
557
563
  }
558
564
  export interface SpawnBranchToolInput {
559
565
  projectId: string;
@@ -782,6 +788,17 @@ export interface CodeGenInputOptions {
782
788
  projectId?: string;
783
789
  branchName?: string;
784
790
  repoHash?: string;
791
+ /**
792
+ * Server-side branch.agentType cached from middleware Firestore lookup.
793
+ * Used to avoid redundant getBranch calls for billing exemption checks.
794
+ * @internal - Set by middleware, not by clients
795
+ */
796
+ branchAgentType?: string | null;
797
+ /**
798
+ * True when middleware performed a Firestore branch lookup; do not use source-based exemption.
799
+ * @internal - Set by middleware, not by clients
800
+ */
801
+ branchAgentTypeChecked?: boolean;
785
802
  /** @deprecated */
786
803
  prevId?: string;
787
804
  /** @deprecated */
@@ -1177,6 +1194,8 @@ export interface GenerateCompletionStepToolCallRequest {
1177
1194
  id: string;
1178
1195
  name: string;
1179
1196
  input: any;
1197
+ /** When true, this tool call can be resolved by a user message if no client handler exists */
1198
+ messageValid?: boolean;
1180
1199
  }
1181
1200
  export interface GenerateCompletionStepTerminals {
1182
1201
  type: "terminals";
@@ -1223,10 +1242,11 @@ export interface UserSourceBase {
1223
1242
  principals?: string[];
1224
1243
  jobs?: string[];
1225
1244
  permissions?: UserSourcePermission[];
1245
+ channelId?: string;
1226
1246
  }
1227
1247
  /** All integration sources: Slack, Teams, Jira, Linear, and git providers (GitHub, GitLab, Azure, Bitbucket). */
1228
1248
  export interface UserSourceOther extends UserSourceBase {
1229
- source: "slack" | "telegram" | "teams" | "jira" | "linear" | "github" | "gitlab" | "azure" | "bitbucket";
1249
+ source: "slack" | "telegram" | "whatsapp" | "teams" | "jira" | "linear" | "github" | "gitlab" | "azure" | "bitbucket";
1230
1250
  /** User ID from the external platform (Slack user ID, GitHub user id, etc.) */
1231
1251
  userId?: string;
1232
1252
  userName?: string;
package/src/events.d.ts CHANGED
@@ -530,7 +530,6 @@ export declare const ForceSetupAgentV1: {
530
530
  };
531
531
  export type ClawMessageSentV1 = FusionEventVariant<"claw.message.sent", {
532
532
  branchName: string;
533
- messageType: "text" | "task-result" | "cron-trigger";
534
533
  content: string;
535
534
  senderType: "user" | "sub-agent" | "system";
536
535
  senderId?: string;
@@ -538,6 +537,8 @@ export type ClawMessageSentV1 = FusionEventVariant<"claw.message.sent", {
538
537
  channelId?: string;
539
538
  dmId?: string;
540
539
  senderDisplayName?: string;
540
+ agentBranchName?: string;
541
+ agentProjectId?: string;
541
542
  userSource?: UserSource;
542
543
  /** Optional context to include alongside the message (e.g. Slack thread history). */
543
544
  messageContext?: string;
@@ -548,13 +549,62 @@ export declare const ClawMessageSentV1: {
548
549
  eventName: "claw.message.sent";
549
550
  version: "1";
550
551
  };
552
+ export type CodegenCompletionV1 = FusionEventVariant<"codegen.completion", {
553
+ completionId: string;
554
+ role?: string;
555
+ projectId?: string;
556
+ branchName?: string;
557
+ sessionId: string;
558
+ userSourceUserId?: string;
559
+ model?: string;
560
+ compact?: boolean;
561
+ usedTokens?: number;
562
+ category?: string;
563
+ userPrompt?: string;
564
+ }, {
565
+ projectId?: string;
566
+ branchName?: string;
567
+ sessionId: string;
568
+ }, 1>;
569
+ export declare const CodegenCompletionV1: {
570
+ eventName: "codegen.completion";
571
+ version: "1";
572
+ };
573
+ export type CodegenUserPromptV1 = FusionEventVariant<"codegen.user.prompt", {
574
+ completionId: string;
575
+ role?: string;
576
+ projectId?: string;
577
+ branchName?: string;
578
+ sessionId: string;
579
+ userSourceUserId?: string;
580
+ model?: string;
581
+ compact?: boolean;
582
+ usedTokens?: number;
583
+ category?: string;
584
+ userPrompt: string;
585
+ }, {
586
+ projectId?: string;
587
+ branchName?: string;
588
+ sessionId: string;
589
+ }, 1>;
590
+ export declare const CodegenUserPromptV1: {
591
+ eventName: "codegen.user.prompt";
592
+ version: "1";
593
+ };
551
594
  export interface SendMessageToOrgAgentInput {
595
+ agentBranchName?: string;
596
+ agentProjectId?: string;
552
597
  content: string;
598
+ senderType?: "user" | "sub-agent" | "system";
553
599
  channelId?: string;
554
600
  senderDisplayName?: string;
555
601
  messageContext?: string;
602
+ senderId?: string;
603
+ dmId?: string;
604
+ userSource?: UserSource;
605
+ attachments?: FileUpload[];
556
606
  }
557
- export type FusionEvent = AiTaskCompletedEvent | AiTaskFailedEvent | GitPrCreatedEvent | ClientDevtoolsSessionStartedEvent | ClientDevtoolsSessionIdleEventV1 | FusionProjectCreatedV1 | SetupAgentCompletedV1 | ForceSetupAgentV1 | ClawMessageSentV1;
607
+ export type FusionEvent = AiTaskCompletedEvent | AiTaskFailedEvent | GitPrCreatedEvent | ClientDevtoolsSessionStartedEvent | ClientDevtoolsSessionIdleEventV1 | FusionProjectCreatedV1 | SetupAgentCompletedV1 | ForceSetupAgentV1 | ClawMessageSentV1 | CodegenCompletionV1 | CodegenUserPromptV1;
558
608
  export interface ModelPermissionRequiredEvent {
559
609
  type: "assistant.model.permission.required";
560
610
  data: {
package/src/events.js CHANGED
@@ -34,3 +34,11 @@ export const ClawMessageSentV1 = {
34
34
  eventName: "claw.message.sent",
35
35
  version: "1",
36
36
  };
37
+ export const CodegenCompletionV1 = {
38
+ eventName: "codegen.completion",
39
+ version: "1",
40
+ };
41
+ export const CodegenUserPromptV1 = {
42
+ eventName: "codegen.user.prompt",
43
+ version: "1",
44
+ };
@@ -84,6 +84,10 @@ interface OrganizationSettings {
84
84
  enabled?: boolean;
85
85
  };
86
86
  disableFigmaImageUpload?: boolean;
87
+ prReviewer?: {
88
+ instructions?: string;
89
+ model?: string;
90
+ };
87
91
  enableTicketAssessment?: boolean;
88
92
  ticketAssessmentPrompt?: string;
89
93
  ticketAssessmentModel?: string;
@@ -292,6 +296,7 @@ export interface FeatureMap {
292
296
  enterpriseGitProviders?: boolean;
293
297
  agentCreditsRollover?: boolean;
294
298
  selfHostedGitProviders?: boolean;
299
+ reviewAgent?: boolean;
295
300
  }
296
301
  export interface SubscriptionInfo {
297
302
  price?: number;
package/src/projects.d.ts CHANGED
@@ -569,6 +569,7 @@ export interface Project {
569
569
  /** MIGRATION: accepts both string and number during migration period */
570
570
  updatedAt: InMigrationDate;
571
571
  pinned?: boolean;
572
+ pinOrder?: number;
572
573
  archived?: boolean;
573
574
  createdBy: string;
574
575
  lastUpdateBy?: string;
@@ -644,6 +645,7 @@ export interface Project {
644
645
  prReviewer?: {
645
646
  enabled: boolean;
646
647
  instructions?: string;
648
+ model?: string;
647
649
  };
648
650
  enableSnapshots?: boolean;
649
651
  postMergeMemories?: boolean;
@@ -867,6 +869,7 @@ export interface SendMessageOptions {
867
869
  featureFlags?: Record<string, boolean>;
868
870
  webhook?: WebhookConfig;
869
871
  fireAndForget?: boolean;
872
+ skipPromptAnalysis?: boolean;
870
873
  canHandleTools?: (keyof CodeGenToolMap)[];
871
874
  }
872
875
  export interface MemoryData {
package/src/projects.js CHANGED
@@ -30,6 +30,7 @@ export const EXAMPLE_REPOS = [
30
30
  "BuilderIO/fusion-angular-tailwind-starter",
31
31
  "BuilderIO/fusion-svelte-tailwind-starter",
32
32
  "BuilderIO/fusion-vue-tailwind-starter",
33
+ "BuilderIO/org-agent-starter",
33
34
  ];
34
35
  export const STARTER_REPO = "BuilderIO/fusion-starter";
35
36
  export const EXAMPLE_OR_STARTER_REPOS = [...EXAMPLE_REPOS, STARTER_REPO];