@builder.io/ai-utils 0.54.0 → 0.56.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 +1 -1
- package/src/claw.d.ts +6 -7
- package/src/claw.js +6 -15
- package/src/claw.spec.js +13 -7
- package/src/codegen.d.ts +159 -29
- package/src/codegen.js +24 -1
- package/src/codegen.spec.d.ts +1 -0
- package/src/codegen.spec.js +58 -0
- package/src/events.d.ts +4 -0
- package/src/organization.d.ts +6 -0
package/package.json
CHANGED
package/src/claw.d.ts
CHANGED
|
@@ -70,19 +70,14 @@ export declare function parseChannelId(channelId: string): ParsedChannelId;
|
|
|
70
70
|
* slack/dm/TEAM_ID/USER_ID
|
|
71
71
|
* → https://slack.com/app_redirect?team=TEAM_ID&channel=USER_ID
|
|
72
72
|
*
|
|
73
|
-
* Jira:
|
|
74
|
-
* Returns null - needs integration.baseUrl from database
|
|
75
|
-
* (Future: jira/comment/CLOUD_ID/ISSUE_KEY → {baseUrl}/browse/ISSUE_KEY)
|
|
76
|
-
*
|
|
77
73
|
* Returns null for unsupported platforms or malformed channel IDs.
|
|
78
|
-
*
|
|
79
|
-
* TODO: Accept optional integration metadata parameter to construct proper
|
|
80
|
-
* workspace-specific URLs (Slack teamDomain, Jira baseUrl).
|
|
81
74
|
*/
|
|
82
75
|
export declare function convertChannelIdToUrl(channelId: string): string | null;
|
|
83
76
|
export interface WorkerReportOptions {
|
|
84
77
|
/** The original user's channel that triggered this work. */
|
|
85
78
|
originChannelId?: string;
|
|
79
|
+
/** Clickable URL for the origin channel, if the integration already has one. */
|
|
80
|
+
channelUrl?: string;
|
|
86
81
|
/** The report content. */
|
|
87
82
|
content: string;
|
|
88
83
|
/** Agent/tool ID (for sub-agent reports). */
|
|
@@ -91,6 +86,8 @@ export interface WorkerReportOptions {
|
|
|
91
86
|
export interface WorkerMessageOptions {
|
|
92
87
|
/** The original user's channel that triggered this work. */
|
|
93
88
|
originChannelId?: string;
|
|
89
|
+
/** Clickable URL for the origin channel, if the integration already has one. */
|
|
90
|
+
channelUrl?: string;
|
|
94
91
|
/** The report content. */
|
|
95
92
|
content: string;
|
|
96
93
|
/** Project ID (for branch reports). */
|
|
@@ -129,6 +126,8 @@ export declare function formatSystemMessage(opts: SystemMessageOptions): string;
|
|
|
129
126
|
export interface IncomingMessageOptions {
|
|
130
127
|
/** The source channel (e.g. slack/thread/TEAM/CHANNEL/TS). */
|
|
131
128
|
channelId: string;
|
|
129
|
+
/** Clickable URL for channelId, if the integration already has one. */
|
|
130
|
+
channelUrl?: string;
|
|
132
131
|
/** DM channel ID, if the message was a direct message. */
|
|
133
132
|
dmId?: string;
|
|
134
133
|
/** Display name of the sender. */
|
package/src/claw.js
CHANGED
|
@@ -30,14 +30,7 @@ export function parseChannelId(channelId) {
|
|
|
30
30
|
* slack/dm/TEAM_ID/USER_ID
|
|
31
31
|
* → https://slack.com/app_redirect?team=TEAM_ID&channel=USER_ID
|
|
32
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
33
|
* 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
34
|
*/
|
|
42
35
|
export function convertChannelIdToUrl(channelId) {
|
|
43
36
|
let parsed;
|
|
@@ -51,11 +44,6 @@ export function convertChannelIdToUrl(channelId) {
|
|
|
51
44
|
if (platform === "slack") {
|
|
52
45
|
return slackChannelIdToUrl(type, ids);
|
|
53
46
|
}
|
|
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
47
|
return null;
|
|
60
48
|
}
|
|
61
49
|
function slackChannelIdToUrl(type, ids) {
|
|
@@ -105,10 +93,11 @@ const WORKER_REPORT_TRAILER = "This is a report from a background worker, NOT a
|
|
|
105
93
|
* correct user channel.
|
|
106
94
|
*/
|
|
107
95
|
export function formatWorkerReport(opts) {
|
|
96
|
+
var _a;
|
|
108
97
|
let xml = `<worker_report>\n`;
|
|
109
98
|
if (opts.originChannelId) {
|
|
110
99
|
xml += `<origin_channel_id>${opts.originChannelId}</origin_channel_id>\n`;
|
|
111
|
-
const url = convertChannelIdToUrl(opts.originChannelId);
|
|
100
|
+
const url = (_a = opts.channelUrl) !== null && _a !== void 0 ? _a : convertChannelIdToUrl(opts.originChannelId);
|
|
112
101
|
if (url) {
|
|
113
102
|
xml += `<origin_channel_url>${url}</origin_channel_url>\n`;
|
|
114
103
|
}
|
|
@@ -120,10 +109,11 @@ export function formatWorkerReport(opts) {
|
|
|
120
109
|
return xml;
|
|
121
110
|
}
|
|
122
111
|
export function formatWorkerMessage(opts) {
|
|
112
|
+
var _a;
|
|
123
113
|
let xml = `<worker_message>\n`;
|
|
124
114
|
if (opts.originChannelId) {
|
|
125
115
|
xml += `<origin_channel_id>${opts.originChannelId}</origin_channel_id>\n`;
|
|
126
|
-
const url = convertChannelIdToUrl(opts.originChannelId);
|
|
116
|
+
const url = (_a = opts.channelUrl) !== null && _a !== void 0 ? _a : convertChannelIdToUrl(opts.originChannelId);
|
|
127
117
|
if (url) {
|
|
128
118
|
xml += `<origin_channel_url>${url}</origin_channel_url>\n`;
|
|
129
119
|
}
|
|
@@ -165,13 +155,14 @@ export function formatSystemMessage(opts) {
|
|
|
165
155
|
* The org-agent uses `<channel_id>` to reply in the same medium.
|
|
166
156
|
*/
|
|
167
157
|
export function formatIncomingMessage(opts) {
|
|
158
|
+
var _a;
|
|
168
159
|
let result = "";
|
|
169
160
|
if (opts.messageContext) {
|
|
170
161
|
result += `${opts.messageContext}\n\n`;
|
|
171
162
|
}
|
|
172
163
|
result += `<incoming_message>\n`;
|
|
173
164
|
result += `<channel_id>${opts.channelId}</channel_id>\n`;
|
|
174
|
-
const channelUrl = convertChannelIdToUrl(opts.channelId);
|
|
165
|
+
const channelUrl = (_a = opts.channelUrl) !== null && _a !== void 0 ? _a : convertChannelIdToUrl(opts.channelId);
|
|
175
166
|
if (channelUrl) {
|
|
176
167
|
result += `<channel_url>${channelUrl}</channel_url>\n`;
|
|
177
168
|
}
|
package/src/claw.spec.js
CHANGED
|
@@ -45,10 +45,13 @@ describe("convertChannelIdToUrl", () => {
|
|
|
45
45
|
});
|
|
46
46
|
});
|
|
47
47
|
describe("jira/comment format", () => {
|
|
48
|
-
it("returns null
|
|
48
|
+
it("returns null because Jira URLs are provided by the integration", () => {
|
|
49
49
|
const url = convertChannelIdToUrl("jira/comment/cloud-id/PROJ-123");
|
|
50
50
|
expect(url).toBeNull();
|
|
51
51
|
});
|
|
52
|
+
it("returns null even when the issue key is present", () => {
|
|
53
|
+
expect(convertChannelIdToUrl("jira/comment/cloud-id/PROJ-123")).toBeNull();
|
|
54
|
+
});
|
|
52
55
|
});
|
|
53
56
|
describe("unsupported platforms", () => {
|
|
54
57
|
it("returns null for telegram channel IDs", () => {
|
|
@@ -90,14 +93,15 @@ describe("formatIncomingMessage", () => {
|
|
|
90
93
|
});
|
|
91
94
|
expect(result).toContain("<channel_url>https://slack.com/app_redirect?team=TTEAM&channel=CCHAN</channel_url>");
|
|
92
95
|
});
|
|
93
|
-
it("
|
|
96
|
+
it("includes channel_url when provided by the integration", () => {
|
|
94
97
|
const result = formatIncomingMessage({
|
|
95
98
|
channelId: "jira/comment/cloud-id/PROJ-123",
|
|
99
|
+
channelUrl: "https://test.atlassian.net/browse/PROJ-123",
|
|
96
100
|
sender: "Charlie",
|
|
97
101
|
timestamp: "Wednesday, January 3, 2024 at 12:00 PM PST",
|
|
98
102
|
content: "Jira comment",
|
|
99
103
|
});
|
|
100
|
-
expect(result).
|
|
104
|
+
expect(result).toContain("<channel_url>https://test.atlassian.net/browse/PROJ-123</channel_url>");
|
|
101
105
|
});
|
|
102
106
|
it("does not include channel_url for unsupported platforms", () => {
|
|
103
107
|
const result = formatIncomingMessage({
|
|
@@ -142,12 +146,13 @@ describe("formatWorkerMessage", () => {
|
|
|
142
146
|
});
|
|
143
147
|
expect(result).toContain("<origin_channel_url>https://slack.com/app_redirect?team=TTEAM&channel=CCHAN&message_ts=1234567890.000100</origin_channel_url>");
|
|
144
148
|
});
|
|
145
|
-
it("
|
|
149
|
+
it("includes origin_channel_url when provided by the integration", () => {
|
|
146
150
|
const result = formatWorkerMessage({
|
|
147
151
|
originChannelId: "jira/comment/cloud-id/PROJ-456",
|
|
152
|
+
channelUrl: "https://test.atlassian.net/browse/PROJ-456",
|
|
148
153
|
content: "Worker result",
|
|
149
154
|
});
|
|
150
|
-
expect(result).
|
|
155
|
+
expect(result).toContain("<origin_channel_url>https://test.atlassian.net/browse/PROJ-456</origin_channel_url>");
|
|
151
156
|
});
|
|
152
157
|
it("does not include origin_channel_url for unsupported platforms", () => {
|
|
153
158
|
const result = formatWorkerMessage({
|
|
@@ -181,13 +186,14 @@ describe("formatWorkerReport", () => {
|
|
|
181
186
|
});
|
|
182
187
|
expect(result).toContain("<origin_channel_url>https://slack.com/app_redirect?team=TTEAM&channel=CCHAN</origin_channel_url>");
|
|
183
188
|
});
|
|
184
|
-
it("
|
|
189
|
+
it("includes origin_channel_url when provided by the integration", () => {
|
|
185
190
|
const result = formatWorkerReport({
|
|
186
191
|
originChannelId: "jira/comment/cloud-id/PROJ-789",
|
|
192
|
+
channelUrl: "https://test.atlassian.net/browse/PROJ-789",
|
|
187
193
|
content: "Report content",
|
|
188
194
|
agentId: "agent-xyz",
|
|
189
195
|
});
|
|
190
|
-
expect(result).
|
|
196
|
+
expect(result).toContain("<origin_channel_url>https://test.atlassian.net/browse/PROJ-789</origin_channel_url>");
|
|
191
197
|
});
|
|
192
198
|
it("does not include origin_channel_url for unsupported platforms", () => {
|
|
193
199
|
const result = formatWorkerReport({
|
package/src/codegen.d.ts
CHANGED
|
@@ -35,13 +35,29 @@ export interface CustomInstruction {
|
|
|
35
35
|
isSkill?: boolean;
|
|
36
36
|
disableModelInvocation?: boolean;
|
|
37
37
|
userInvocable?: boolean;
|
|
38
|
+
/**
|
|
39
|
+
* Where this instruction was discovered. Drives precedence on name
|
|
40
|
+
* collision: `project` > `user` > `plugin`. Set by the discovery loader,
|
|
41
|
+
* not by the parsed file itself.
|
|
42
|
+
*/
|
|
43
|
+
scope?: "project" | "user" | "plugin";
|
|
44
|
+
/**
|
|
45
|
+
* Name of the plugin that contributed this instruction, if any. Set by
|
|
46
|
+
* the plugin loader (Phase 2); always `undefined` for project-level and
|
|
47
|
+
* user-level standalone files (Phase 1).
|
|
48
|
+
*/
|
|
49
|
+
pluginName?: string;
|
|
38
50
|
}
|
|
39
51
|
/** Reasoning effort level for LLM completions. */
|
|
40
52
|
export declare const ReasoningEffortSchema: z.ZodEnum<{
|
|
53
|
+
none: "none";
|
|
41
54
|
low: "low";
|
|
42
55
|
medium: "medium";
|
|
43
56
|
high: "high";
|
|
57
|
+
auto: "auto";
|
|
44
58
|
minimal: "minimal";
|
|
59
|
+
xhigh: "xhigh";
|
|
60
|
+
max: "max";
|
|
45
61
|
}>;
|
|
46
62
|
export type ReasoningEffort = z.infer<typeof ReasoningEffortSchema>;
|
|
47
63
|
export interface CustomAgentInfo {
|
|
@@ -64,7 +80,6 @@ export interface CustomAgentDefinition {
|
|
|
64
80
|
tools?: string[];
|
|
65
81
|
model?: string;
|
|
66
82
|
roundRobinModels?: string[];
|
|
67
|
-
mode?: CodeGenMode;
|
|
68
83
|
position?: CodeGenPosition;
|
|
69
84
|
needDevServer?: boolean;
|
|
70
85
|
needValidation?: boolean;
|
|
@@ -72,6 +87,17 @@ export interface CustomAgentDefinition {
|
|
|
72
87
|
resetAfterRun?: boolean;
|
|
73
88
|
mcpServers?: boolean;
|
|
74
89
|
asyncSubAgents?: boolean;
|
|
90
|
+
/**
|
|
91
|
+
* Expressive queue behavior for messages sent to this agent. See
|
|
92
|
+
* {@link QueueBehavior}. When both `queueBehavior` and `queueMode` are
|
|
93
|
+
* provided, `queueBehavior` wins.
|
|
94
|
+
*/
|
|
95
|
+
queueBehavior?: QueueBehavior;
|
|
96
|
+
/**
|
|
97
|
+
* @deprecated Use {@link CustomAgentDefinition.queueBehavior} instead.
|
|
98
|
+
* Kept as a string alias for backwards compatibility with existing agent
|
|
99
|
+
* definitions in the wild.
|
|
100
|
+
*/
|
|
75
101
|
queueMode?: QueueMode;
|
|
76
102
|
softContextWindow?: number;
|
|
77
103
|
filePath?: string;
|
|
@@ -84,13 +110,31 @@ export interface CustomAgentDefinition {
|
|
|
84
110
|
maxCompletions?: number;
|
|
85
111
|
/** Default reasoning effort level for this agent type. Overrides the session default. */
|
|
86
112
|
reasoning?: ReasoningEffort;
|
|
113
|
+
/**
|
|
114
|
+
* Where this agent was discovered. Drives precedence on name collision:
|
|
115
|
+
* `project` > `user` > `plugin`. Set by the discovery loader, not by the
|
|
116
|
+
* parsed file itself.
|
|
117
|
+
*/
|
|
118
|
+
scope?: "project" | "user" | "plugin";
|
|
119
|
+
/**
|
|
120
|
+
* Name of the plugin that contributed this agent, if any. Set by the
|
|
121
|
+
* plugin loader (Phase 2); always `undefined` for project-level and
|
|
122
|
+
* user-level standalone files (Phase 1).
|
|
123
|
+
*/
|
|
124
|
+
pluginName?: string;
|
|
87
125
|
}
|
|
88
126
|
export type CodeGenFramework = "react" | "html" | "mitosis" | "react-native" | "angular" | "vue" | "svelte" | "qwik" | "solid" | "marko" | "swiftui" | "jetpack-compose" | "flutter";
|
|
89
127
|
export type CodeGenStyleLibrary = "tailwind" | "tailwind-precise" | "emotion" | "styled-components" | "styled-jsx" | "react-native" | undefined;
|
|
90
128
|
export type CompletionStopReason = "max_tokens" | "stop_sequence" | "tool_use" | "end_turn" | "content_filter" | "error" | "aborted" | "pause_turn" | "refusal" | "compaction" | "model_context_window_exceeded" | null;
|
|
91
129
|
export interface ReadToolInput {
|
|
130
|
+
/**
|
|
131
|
+
* Path of the file. Accepts a path relative to the project working directory,
|
|
132
|
+
* an absolute path (e.g. `/Users/.../skill.md`), or a tilde path
|
|
133
|
+
* (e.g. `~/.builder/skills/.../SKILL.md`). User-level Builder state under
|
|
134
|
+
* `~/.builder/**` is allowed by default for plugin operations; other absolute
|
|
135
|
+
* paths require an explicit ACL policy.
|
|
136
|
+
*/
|
|
92
137
|
file_path: string;
|
|
93
|
-
view_range?: [number, number];
|
|
94
138
|
offset?: number | null;
|
|
95
139
|
limit?: number | null;
|
|
96
140
|
}
|
|
@@ -145,11 +189,23 @@ export interface WebSearchToolInput {
|
|
|
145
189
|
}
|
|
146
190
|
export interface WriteFileInput {
|
|
147
191
|
title: string;
|
|
192
|
+
/**
|
|
193
|
+
* Path of the file. Accepts a path relative to the project working directory,
|
|
194
|
+
* an absolute path, or a tilde path (e.g. `~/.builder/...`). User-level Builder
|
|
195
|
+
* state under `~/.builder/**` is allowed by default; other absolute paths
|
|
196
|
+
* require an explicit ACL policy.
|
|
197
|
+
*/
|
|
148
198
|
file_path: string;
|
|
149
199
|
content: string;
|
|
150
200
|
}
|
|
151
201
|
export interface SearchReplaceInput {
|
|
152
202
|
title: string;
|
|
203
|
+
/**
|
|
204
|
+
* Path of the file. Accepts a path relative to the project working directory,
|
|
205
|
+
* an absolute path, or a tilde path (e.g. `~/.builder/...`). User-level Builder
|
|
206
|
+
* state under `~/.builder/**` is allowed by default; other absolute paths
|
|
207
|
+
* require an explicit ACL policy.
|
|
208
|
+
*/
|
|
153
209
|
file_path: string;
|
|
154
210
|
old_str: string;
|
|
155
211
|
new_str: string;
|
|
@@ -158,6 +214,12 @@ export interface SearchReplaceInput {
|
|
|
158
214
|
}
|
|
159
215
|
export interface MultiSearchReplaceInput {
|
|
160
216
|
title: string;
|
|
217
|
+
/**
|
|
218
|
+
* Path of the file. Accepts a path relative to the project working directory,
|
|
219
|
+
* an absolute path, or a tilde path (e.g. `~/.builder/...`). User-level Builder
|
|
220
|
+
* state under `~/.builder/**` is allowed by default; other absolute paths
|
|
221
|
+
* require an explicit ACL policy.
|
|
222
|
+
*/
|
|
161
223
|
file_path: string;
|
|
162
224
|
edits: {
|
|
163
225
|
old_str: string;
|
|
@@ -737,19 +799,6 @@ export interface ReportIssueToolInput {
|
|
|
737
799
|
body: string;
|
|
738
800
|
}
|
|
739
801
|
export interface CodeGenToolMap {
|
|
740
|
-
view_path: ReadToolInput;
|
|
741
|
-
glob_search: GlobSearchToolInput;
|
|
742
|
-
grep_search: GrepSearchToolInput;
|
|
743
|
-
get_rule: GetRuleToolInput;
|
|
744
|
-
get_style_inspiration: GetStyleInspirationToolInput;
|
|
745
|
-
get_screenshot: GetScreenshotToolInput;
|
|
746
|
-
dev_server_control: DevServerControlInput;
|
|
747
|
-
bash: BashToolInput;
|
|
748
|
-
powershell: PowerShellToolInput;
|
|
749
|
-
web_search: WebSearchToolInput;
|
|
750
|
-
write_file: WriteFileInput;
|
|
751
|
-
search_replace_file: SearchReplaceInput;
|
|
752
|
-
find_media: FindMediaToolInput;
|
|
753
802
|
Read: ReadToolInput;
|
|
754
803
|
Write: WriteFileInput;
|
|
755
804
|
Edit: SearchReplaceInput;
|
|
@@ -812,6 +861,7 @@ export interface CodeGenToolMap {
|
|
|
812
861
|
IDEDiagnostics: IDEDiagnosticsToolInput;
|
|
813
862
|
EscalateToPlanner: EscalateToPlanner;
|
|
814
863
|
PullPrototype: PullPrototypeToolInput;
|
|
864
|
+
ConnectMCP: ConnectMCPToolInput;
|
|
815
865
|
}
|
|
816
866
|
export interface EscalateToPlanner {
|
|
817
867
|
/** What's blocking execution */
|
|
@@ -825,17 +875,80 @@ export interface EscalateToPlanner {
|
|
|
825
875
|
}
|
|
826
876
|
export interface GetLastBrowserTestToolInput {
|
|
827
877
|
}
|
|
878
|
+
export interface ConnectMCPToolInput {
|
|
879
|
+
/** Human-readable name of the MCP service, e.g. "Jira", "Linear", "Sentry" */
|
|
880
|
+
name: string;
|
|
881
|
+
/** Remote MCP endpoint URL. When omitted, discovery is performed for the named service. */
|
|
882
|
+
url?: string;
|
|
883
|
+
}
|
|
828
884
|
export type CodeGenTools = keyof CodeGenToolMap;
|
|
829
885
|
export type AllCodeGenTools = CodeGenTools | "web_search";
|
|
830
886
|
export type SessionMode = "planning" | "normal" | "auto-planning" | "deep-research";
|
|
831
|
-
export type CodeGenMode = "quality" | "quality-
|
|
887
|
+
export type CodeGenMode = "quality" | "quality-v4"
|
|
832
888
|
/**
|
|
833
889
|
* @deprecated Use `quality-v4` instead. Kept for backwards compatibility
|
|
834
890
|
* with older dev-tools clients in the wild that may still request this mode
|
|
835
891
|
* for sub-agents. New code should not produce this value.
|
|
836
892
|
*/
|
|
837
893
|
| "quality-v4-agent";
|
|
838
|
-
|
|
894
|
+
/**
|
|
895
|
+
* When a queued message gets picked up by the scheduler.
|
|
896
|
+
*
|
|
897
|
+
* - `next-turn`: process queued messages as soon as the current LLM turn
|
|
898
|
+
* finishes (i.e. between turns of an in-flight run).
|
|
899
|
+
* - `until-idle`: hold queued messages until the agent is fully idle
|
|
900
|
+
* (current run has ended). Messages never interrupt an in-flight run.
|
|
901
|
+
* - `interrupt`: abort the in-flight run as soon as a new message arrives
|
|
902
|
+
* and start processing it. Reserved for high-priority/reactive cases.
|
|
903
|
+
* - `interrupt-clear`: like `interrupt`, but also clears the session
|
|
904
|
+
* (turn history, queued messages, last user, accumulated credits) before
|
|
905
|
+
* processing the new message. Use when the new message should start from
|
|
906
|
+
* a clean slate.
|
|
907
|
+
* - `interrupt-replace`: equivalent to abort + rewind to the previous
|
|
908
|
+
* user message + replace it with the new one. Use when a fresh
|
|
909
|
+
* request supersedes the in-flight one (e.g. incremental code-review
|
|
910
|
+
* requests where a newer review should replace the still-running
|
|
911
|
+
* previous review). The in-flight user prompt and any partial
|
|
912
|
+
* assistant output for it are discarded.
|
|
913
|
+
*/
|
|
914
|
+
export type QueueSchedule = "next-turn" | "until-idle" | "interrupt" | "interrupt-clear" | "interrupt-replace";
|
|
915
|
+
/**
|
|
916
|
+
* What happens when multiple messages are pending in the queue.
|
|
917
|
+
*
|
|
918
|
+
* - `merge`: combine all pending messages into a single user message before
|
|
919
|
+
* the next turn. This is the historical default for `"next-turn"`.
|
|
920
|
+
* - `replace-latest`: discard older pending messages and keep only the
|
|
921
|
+
* most recently queued one (useful when stale inputs are obsolete, e.g.
|
|
922
|
+
* a typing user replacing their previous draft).
|
|
923
|
+
* - `preserve-order`: never merge; pop one message at a time in FIFO order.
|
|
924
|
+
* This is the historical behavior for `"until-idle"`.
|
|
925
|
+
*/
|
|
926
|
+
export type QueueCoalesce = "merge" | "replace-latest" | "preserve-order";
|
|
927
|
+
/**
|
|
928
|
+
* Expressive queue behavior built from two orthogonal axes:
|
|
929
|
+
* `schedule` (when to dispatch) and `coalesce` (how to combine pending).
|
|
930
|
+
*/
|
|
931
|
+
export interface QueueBehavior {
|
|
932
|
+
schedule: QueueSchedule;
|
|
933
|
+
coalesce: QueueCoalesce;
|
|
934
|
+
}
|
|
935
|
+
/**
|
|
936
|
+
* Backwards-compatible queue mode. Accepts either a legacy string alias
|
|
937
|
+
* or the full {@link QueueBehavior} object.
|
|
938
|
+
*
|
|
939
|
+
* Legacy aliases:
|
|
940
|
+
* - `"next-turn"` → `{ schedule: "next-turn", coalesce: "merge" }`
|
|
941
|
+
* - `"until-idle"` → `{ schedule: "until-idle", coalesce: "preserve-order" }`
|
|
942
|
+
*/
|
|
943
|
+
export type QueueMode = "next-turn" | "until-idle" | QueueBehavior;
|
|
944
|
+
export declare const DEFAULT_QUEUE_BEHAVIOR: QueueBehavior;
|
|
945
|
+
/**
|
|
946
|
+
* Normalize any accepted queue-mode shape into a concrete {@link QueueBehavior}.
|
|
947
|
+
* `undefined` resolves to {@link DEFAULT_QUEUE_BEHAVIOR}.
|
|
948
|
+
*/
|
|
949
|
+
/** True for any schedule that aborts the in-flight run on enqueue. */
|
|
950
|
+
export declare function isInterruptSchedule(schedule: QueueSchedule): boolean;
|
|
951
|
+
export declare function normalizeQueueMode(mode: QueueMode | undefined): QueueBehavior;
|
|
839
952
|
export declare const BASE_CODEGEN_POSITIONS: readonly ["fusion", "editor-ai", "repo-indexing", "cli", "create-app-firebase", "create-app-lovable", "builder-code-panel", "setup-project", "code-review-orchestrator", "project-configuration", "org-agent", "browser-testing", "projects-scheduler-memory-extraction", "builder-code", "unknown", "dsi-mcp"];
|
|
840
953
|
export type BaseCodeGenPosition = (typeof BASE_CODEGEN_POSITIONS)[number];
|
|
841
954
|
export type CodeGenPosition = BaseCodeGenPosition | `${BaseCodeGenPosition}-agent`;
|
|
@@ -941,17 +1054,6 @@ export interface CodeGenInputOptions {
|
|
|
941
1054
|
branchName?: string;
|
|
942
1055
|
repoHash?: string;
|
|
943
1056
|
repoBranch?: string;
|
|
944
|
-
/**
|
|
945
|
-
* Server-side branch.agentType cached from middleware Firestore lookup.
|
|
946
|
-
* Used to avoid redundant getBranch calls for billing exemption checks.
|
|
947
|
-
* @internal - Set by middleware, not by clients
|
|
948
|
-
*/
|
|
949
|
-
branchAgentType?: string | null;
|
|
950
|
-
/**
|
|
951
|
-
* True when middleware performed a Firestore branch lookup; do not use source-based exemption.
|
|
952
|
-
* @internal - Set by middleware, not by clients
|
|
953
|
-
*/
|
|
954
|
-
branchAgentTypeChecked?: boolean;
|
|
955
1057
|
/** Immediate parent session id when this completion runs inside a sub-agent. */
|
|
956
1058
|
parentSessionId?: string;
|
|
957
1059
|
/**
|
|
@@ -1108,7 +1210,7 @@ export interface ContextWindow {
|
|
|
1108
1210
|
* the proportion (0-1) of total tokens used by that category.
|
|
1109
1211
|
*
|
|
1110
1212
|
* Common keys include:
|
|
1111
|
-
* - `tool:<name>` - Tokens from tool calls and results (e.g., `tool:
|
|
1213
|
+
* - `tool:<name>` - Tokens from tool calls and results (e.g., `tool:Read`, `tool:Bash`)
|
|
1112
1214
|
* - `tools:builtin` - Tokens from built-in tool definitions/schemas
|
|
1113
1215
|
* - `tools:mcp:<server>` - Tokens from MCP server tool definitions (e.g., `tools:mcp:browser`)
|
|
1114
1216
|
* - `images` - Tokens from image content (estimated at ~1200 tokens per image)
|
|
@@ -1902,6 +2004,17 @@ export interface MCPServerDefinition {
|
|
|
1902
2004
|
env?: Record<string, string>;
|
|
1903
2005
|
envFile?: string;
|
|
1904
2006
|
retries?: number;
|
|
2007
|
+
/**
|
|
2008
|
+
* Where this server was discovered. Drives precedence on name collision:
|
|
2009
|
+
* `project` > `user` > `plugin`. Set by the loader, not by the config file.
|
|
2010
|
+
*/
|
|
2011
|
+
scope?: "project" | "user" | "plugin";
|
|
2012
|
+
/**
|
|
2013
|
+
* Name of the plugin that contributed this server, if any. Set by the
|
|
2014
|
+
* plugin loader (Phase 2); always `undefined` for project-level and
|
|
2015
|
+
* user-level standalone configs (Phase 1).
|
|
2016
|
+
*/
|
|
2017
|
+
pluginName?: string;
|
|
1905
2018
|
}
|
|
1906
2019
|
export type MCPServerConfig = Record<string, MCPServerDefinition>;
|
|
1907
2020
|
export interface FusionConfig {
|
|
@@ -2236,6 +2349,23 @@ export interface SyncChangesFromRemote {
|
|
|
2236
2349
|
uncommittedChanges?: "stash" | "commit" | "fail";
|
|
2237
2350
|
requestRefresh?: boolean;
|
|
2238
2351
|
allowUnrelatedHistory?: boolean;
|
|
2352
|
+
/**
|
|
2353
|
+
* When true, reset the AI branch hard to the remote feature/base branch instead
|
|
2354
|
+
* of merging. This gives a clean slate that exactly matches the checked-out
|
|
2355
|
+
* feature branch on remote, avoiding any merge-style conflicts or divergence.
|
|
2356
|
+
* Fails clearly if the feature/base branch cannot be determined or is absent
|
|
2357
|
+
* from the remote.
|
|
2358
|
+
*/
|
|
2359
|
+
resetToBase?: boolean;
|
|
2360
|
+
/**
|
|
2361
|
+
* Whether to update the internal "last AI commits" baseline after the sync
|
|
2362
|
+
* completes. Defaults to `true` for backwards compatibility.
|
|
2363
|
+
*
|
|
2364
|
+
* Set to `false` when the caller wants `getChangesReport()` to keep diffing
|
|
2365
|
+
* from the pre-sync baseline (e.g. so a downstream prompt can see exactly
|
|
2366
|
+
* what changed since the last reset/sync).
|
|
2367
|
+
*/
|
|
2368
|
+
updateLastCommits?: boolean;
|
|
2239
2369
|
}
|
|
2240
2370
|
export type PushChangesArgs = PushChangesOptions | boolean;
|
|
2241
2371
|
export type CodegenApiResult = CodegenApiSuccess | CodegenApiFailure;
|
package/src/codegen.js
CHANGED
|
@@ -1,8 +1,31 @@
|
|
|
1
1
|
import { z } from "zod";
|
|
2
2
|
/** Reasoning effort level for LLM completions. */
|
|
3
3
|
export const ReasoningEffortSchema = z
|
|
4
|
-
.enum(["low", "medium", "high", "
|
|
4
|
+
.enum(["auto", "none", "minimal", "low", "medium", "high", "xhigh", "max"])
|
|
5
5
|
.meta({ title: "ReasoningEffort" });
|
|
6
|
+
export const DEFAULT_QUEUE_BEHAVIOR = {
|
|
7
|
+
schedule: "next-turn",
|
|
8
|
+
coalesce: "merge",
|
|
9
|
+
};
|
|
10
|
+
/**
|
|
11
|
+
* Normalize any accepted queue-mode shape into a concrete {@link QueueBehavior}.
|
|
12
|
+
* `undefined` resolves to {@link DEFAULT_QUEUE_BEHAVIOR}.
|
|
13
|
+
*/
|
|
14
|
+
/** True for any schedule that aborts the in-flight run on enqueue. */
|
|
15
|
+
export function isInterruptSchedule(schedule) {
|
|
16
|
+
return (schedule === "interrupt" ||
|
|
17
|
+
schedule === "interrupt-clear" ||
|
|
18
|
+
schedule === "interrupt-replace");
|
|
19
|
+
}
|
|
20
|
+
export function normalizeQueueMode(mode) {
|
|
21
|
+
if (mode === undefined)
|
|
22
|
+
return { ...DEFAULT_QUEUE_BEHAVIOR };
|
|
23
|
+
if (mode === "next-turn")
|
|
24
|
+
return { schedule: "next-turn", coalesce: "merge" };
|
|
25
|
+
if (mode === "until-idle")
|
|
26
|
+
return { schedule: "until-idle", coalesce: "preserve-order" };
|
|
27
|
+
return { schedule: mode.schedule, coalesce: mode.coalesce };
|
|
28
|
+
}
|
|
6
29
|
export const BASE_CODEGEN_POSITIONS = [
|
|
7
30
|
"fusion",
|
|
8
31
|
"editor-ai",
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import { describe, it, expect } from "vitest";
|
|
2
|
+
import { DEFAULT_QUEUE_BEHAVIOR, isInterruptSchedule, normalizeQueueMode, } from "./codegen";
|
|
3
|
+
describe("normalizeQueueMode", () => {
|
|
4
|
+
it("returns the default behavior when input is undefined", () => {
|
|
5
|
+
expect(normalizeQueueMode(undefined)).toEqual(DEFAULT_QUEUE_BEHAVIOR);
|
|
6
|
+
});
|
|
7
|
+
it("maps the legacy 'next-turn' alias to merge between turns", () => {
|
|
8
|
+
expect(normalizeQueueMode("next-turn")).toEqual({
|
|
9
|
+
schedule: "next-turn",
|
|
10
|
+
coalesce: "merge",
|
|
11
|
+
});
|
|
12
|
+
});
|
|
13
|
+
it("maps the legacy 'until-idle' alias to FIFO at idle", () => {
|
|
14
|
+
expect(normalizeQueueMode("until-idle")).toEqual({
|
|
15
|
+
schedule: "until-idle",
|
|
16
|
+
coalesce: "preserve-order",
|
|
17
|
+
});
|
|
18
|
+
});
|
|
19
|
+
it("returns an object input as a normalized copy", () => {
|
|
20
|
+
const input = {
|
|
21
|
+
schedule: "interrupt",
|
|
22
|
+
coalesce: "replace-latest",
|
|
23
|
+
};
|
|
24
|
+
const out = normalizeQueueMode(input);
|
|
25
|
+
expect(out).toEqual(input);
|
|
26
|
+
expect(out).not.toBe(input);
|
|
27
|
+
});
|
|
28
|
+
it("supports next-turn + preserve-order (FIFO between turns)", () => {
|
|
29
|
+
expect(normalizeQueueMode({ schedule: "next-turn", coalesce: "preserve-order" })).toEqual({ schedule: "next-turn", coalesce: "preserve-order" });
|
|
30
|
+
});
|
|
31
|
+
it("supports until-idle + replace-latest (debounce on idle)", () => {
|
|
32
|
+
expect(normalizeQueueMode({
|
|
33
|
+
schedule: "until-idle",
|
|
34
|
+
coalesce: "replace-latest",
|
|
35
|
+
})).toEqual({ schedule: "until-idle", coalesce: "replace-latest" });
|
|
36
|
+
});
|
|
37
|
+
it("supports interrupt-clear and interrupt-replace schedules", () => {
|
|
38
|
+
expect(normalizeQueueMode({
|
|
39
|
+
schedule: "interrupt-clear",
|
|
40
|
+
coalesce: "merge",
|
|
41
|
+
})).toEqual({ schedule: "interrupt-clear", coalesce: "merge" });
|
|
42
|
+
expect(normalizeQueueMode({
|
|
43
|
+
schedule: "interrupt-replace",
|
|
44
|
+
coalesce: "merge",
|
|
45
|
+
})).toEqual({ schedule: "interrupt-replace", coalesce: "merge" });
|
|
46
|
+
});
|
|
47
|
+
});
|
|
48
|
+
describe("isInterruptSchedule", () => {
|
|
49
|
+
it("returns true for every interrupt-* schedule", () => {
|
|
50
|
+
expect(isInterruptSchedule("interrupt")).toBe(true);
|
|
51
|
+
expect(isInterruptSchedule("interrupt-clear")).toBe(true);
|
|
52
|
+
expect(isInterruptSchedule("interrupt-replace")).toBe(true);
|
|
53
|
+
});
|
|
54
|
+
it("returns false for non-interrupt schedules", () => {
|
|
55
|
+
expect(isInterruptSchedule("next-turn")).toBe(false);
|
|
56
|
+
expect(isInterruptSchedule("until-idle")).toBe(false);
|
|
57
|
+
});
|
|
58
|
+
});
|
package/src/events.d.ts
CHANGED
|
@@ -623,6 +623,8 @@ export type ClawMessageSentV1 = FusionEventVariant<"claw.message.sent", {
|
|
|
623
623
|
senderId?: string;
|
|
624
624
|
correlationId?: string;
|
|
625
625
|
channelId?: string;
|
|
626
|
+
/** Optional clickable URL for channelId. */
|
|
627
|
+
channelUrl?: string;
|
|
626
628
|
dmId?: string;
|
|
627
629
|
senderDisplayName?: string;
|
|
628
630
|
agentBranchName?: string;
|
|
@@ -771,6 +773,8 @@ export interface SendMessageToOrgAgentInput {
|
|
|
771
773
|
content: string;
|
|
772
774
|
senderType?: "user" | "sub-agent" | "system";
|
|
773
775
|
channelId?: string;
|
|
776
|
+
/** Optional clickable URL for channelId. */
|
|
777
|
+
channelUrl?: string;
|
|
774
778
|
senderDisplayName?: string;
|
|
775
779
|
messageContext?: string;
|
|
776
780
|
senderId?: string;
|
package/src/organization.d.ts
CHANGED
|
@@ -461,5 +461,11 @@ export interface Organization {
|
|
|
461
461
|
fusionReferrals?: string;
|
|
462
462
|
githubInstallationIds?: number[];
|
|
463
463
|
disableFigmaImageUpload?: boolean;
|
|
464
|
+
blocked?: boolean;
|
|
465
|
+
archived?: boolean;
|
|
466
|
+
gatewaySuspended?: boolean;
|
|
467
|
+
gatewaySuspendedAt?: number;
|
|
468
|
+
gatewaySuspendedBy?: string;
|
|
469
|
+
gatewaySuspendedReason?: string;
|
|
464
470
|
}
|
|
465
471
|
export {};
|