@bubblebrain-ai/bubble 0.0.33 → 0.0.35
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/dist/agent/abort-errors.d.ts +2 -2
- package/dist/agent/budget-ledger.d.ts +4 -45
- package/dist/agent/budget-ledger.js +5 -75
- package/dist/agent/child-runner.d.ts +1 -3
- package/dist/agent/child-runner.js +6 -37
- package/dist/agent/profiles.d.ts +0 -2
- package/dist/agent/profiles.js +0 -3
- package/dist/agent/subagent-control.d.ts +5 -12
- package/dist/agent/subagent-control.js +0 -2
- package/dist/agent/subagent-store.d.ts +1 -1
- package/dist/agent/subagent-store.js +1 -3
- package/dist/agent/workflow/control.d.ts +7 -0
- package/dist/agent/workflow/control.js +22 -1
- package/dist/agent/workflow/runtime.d.ts +15 -2
- package/dist/agent/workflow/runtime.js +112 -30
- package/dist/agent.d.ts +7 -43
- package/dist/agent.js +50 -176
- package/dist/config.d.ts +1 -3
- package/dist/config.js +6 -5
- package/dist/context/overflow.js +2 -0
- package/dist/main.js +9 -1
- package/dist/model-catalog.d.ts +1 -1
- package/dist/model-catalog.js +25 -18
- package/dist/orchestrator/default-hooks.js +7 -1
- package/dist/prompt/delegation.d.ts +1 -1
- package/dist/prompt/delegation.js +21 -7
- package/dist/prompt/task-reminders.d.ts +1 -0
- package/dist/prompt/task-reminders.js +24 -1
- package/dist/provider-ai-sdk.d.ts +56 -0
- package/dist/provider-ai-sdk.js +518 -0
- package/dist/provider-registry.js +49 -3
- package/dist/provider-transform.d.ts +1 -1
- package/dist/provider-transform.js +8 -13
- package/dist/provider.js +4 -0
- package/dist/slash-commands/commands.js +3 -7
- package/dist/slash-commands/types.d.ts +1 -1
- package/dist/tools/agent-lifecycle.d.ts +1 -9
- package/dist/tools/agent-lifecycle.js +35 -263
- package/dist/tui-ink/app.js +51 -13
- package/dist/tui-ink/approval/approval-dialog.js +1 -1
- package/dist/tui-ink/approval/diff-view.js +4 -4
- package/dist/tui-ink/approval/select.js +2 -2
- package/dist/tui-ink/feedback-dialog.js +2 -2
- package/dist/tui-ink/feishu-setup-picker.js +3 -3
- package/dist/tui-ink/input-box.d.ts +1 -6
- package/dist/tui-ink/input-box.js +14 -35
- package/dist/tui-ink/markdown.js +11 -9
- package/dist/tui-ink/message-list.d.ts +5 -1
- package/dist/tui-ink/message-list.js +15 -2
- package/dist/tui-ink/model-picker.d.ts +3 -1
- package/dist/tui-ink/model-picker.js +25 -14
- package/dist/tui-ink/plan-confirm.js +1 -1
- package/dist/tui-ink/subagent-view.d.ts +3 -1
- package/dist/tui-ink/theme.d.ts +19 -2
- package/dist/tui-ink/theme.js +25 -8
- package/dist/tui-ink/welcome.d.ts +3 -2
- package/dist/tui-ink/welcome.js +10 -6
- package/dist/types.d.ts +16 -30
- package/dist/variant/variant-resolver.d.ts +13 -0
- package/dist/variant/variant-resolver.js +26 -0
- package/package.json +9 -3
package/dist/config.js
CHANGED
|
@@ -45,9 +45,6 @@ function sanitizeSubagentsConfig(value) {
|
|
|
45
45
|
if (typeof raw.maxActiveSubagents === "number" && Number.isFinite(raw.maxActiveSubagents)) {
|
|
46
46
|
out.maxActiveSubagents = Math.max(1, Math.floor(raw.maxActiveSubagents));
|
|
47
47
|
}
|
|
48
|
-
if (typeof raw.childTokenCap === "number" && Number.isFinite(raw.childTokenCap)) {
|
|
49
|
-
out.childTokenCap = Math.max(1_000, Math.floor(raw.childTokenCap));
|
|
50
|
-
}
|
|
51
48
|
return Object.keys(out).length > 0 ? out : undefined;
|
|
52
49
|
}
|
|
53
50
|
function sanitizeTheme(value) {
|
|
@@ -211,8 +208,12 @@ export class UserConfig {
|
|
|
211
208
|
return sanitizeSubagentsConfig(this.data.subagents) ?? {};
|
|
212
209
|
}
|
|
213
210
|
}
|
|
214
|
-
export function shouldProbeTerminalTheme(
|
|
215
|
-
|
|
211
|
+
export function shouldProbeTerminalTheme(_config) {
|
|
212
|
+
// Always probe: even a forced theme needs the real terminal background to
|
|
213
|
+
// decide between inheriting it (theme matches the terminal) and painting
|
|
214
|
+
// its own canvas (forced theme mismatching the terminal, where the
|
|
215
|
+
// palette's foregrounds would otherwise be unreadable).
|
|
216
|
+
return true;
|
|
216
217
|
}
|
|
217
218
|
export function effectiveThemeModeForTerminal(config, detectedTheme) {
|
|
218
219
|
if (isLegacyBareDarkTheme(config) && detectedTheme === "light")
|
package/dist/context/overflow.js
CHANGED
|
@@ -12,6 +12,8 @@ const OVERFLOW_PATTERNS = [
|
|
|
12
12
|
/prompt is too long/i,
|
|
13
13
|
/maximum context length/i,
|
|
14
14
|
/too many tokens/i,
|
|
15
|
+
// Gemini: "The input token count (N) exceeds the maximum number of tokens allowed (M)."
|
|
16
|
+
/input token count.*exceeds the maximum/i,
|
|
15
17
|
];
|
|
16
18
|
export function isContextOverflowError(error) {
|
|
17
19
|
if (!error)
|
package/dist/main.js
CHANGED
|
@@ -235,12 +235,20 @@ async function main() {
|
|
|
235
235
|
const pickerThemeMode = effectiveThemeModeForTerminal(themeConfig, preResolvedTheme);
|
|
236
236
|
const pickerResolvedTheme = pickerThemeMode === "auto" ? preResolvedTheme : pickerThemeMode;
|
|
237
237
|
const { runSessionPicker } = await import("./tui-ink/run-session-picker.js");
|
|
238
|
+
const { canvasBackgroundFor } = await import("./tui-ink/theme.js");
|
|
239
|
+
// Same rule as the main TUI: a forced theme mismatching the terminal
|
|
240
|
+
// paints its canvas so its foregrounds stay readable.
|
|
241
|
+
const pickerCanvas = themeConfig.overrides?.background
|
|
242
|
+
? undefined
|
|
243
|
+
: canvasBackgroundFor(pickerThemeMode, pickerResolvedTheme, preResolvedTheme);
|
|
238
244
|
const picked = await runSessionPicker({
|
|
239
245
|
currentCwd: args.cwd,
|
|
240
246
|
currentSessions,
|
|
241
247
|
allSessions,
|
|
242
248
|
resolvedTheme: pickerResolvedTheme,
|
|
243
|
-
themeOverrides:
|
|
249
|
+
themeOverrides: pickerCanvas
|
|
250
|
+
? { ...themeConfig.overrides, background: pickerCanvas }
|
|
251
|
+
: themeConfig.overrides,
|
|
244
252
|
});
|
|
245
253
|
if (picked) {
|
|
246
254
|
sessionManager = new SessionManager(picked);
|
package/dist/model-catalog.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { ReasoningEffort } from "./types.js";
|
|
2
|
-
export type ProviderProtocol = "openai-chat" | "anthropic-messages" | "ark-responses";
|
|
2
|
+
export type ProviderProtocol = "openai-chat" | "anthropic-messages" | "ark-responses" | "ai-sdk";
|
|
3
3
|
export interface BuiltinProviderDefinition {
|
|
4
4
|
id: string;
|
|
5
5
|
name: string;
|
package/dist/model-catalog.js
CHANGED
|
@@ -4,7 +4,10 @@ export const BUILTIN_PROVIDERS = [
|
|
|
4
4
|
{ id: "openai-codex", name: "OpenAI Codex (ChatGPT)", baseURL: "https://chatgpt.com/backend-api" },
|
|
5
5
|
{ id: "anthropic", name: "Anthropic", baseURL: "https://api.anthropic.com", protocol: "anthropic-messages" },
|
|
6
6
|
{ id: "deepseek", name: "DeepSeek", baseURL: "https://api.deepseek.com" },
|
|
7
|
-
|
|
7
|
+
// Native Gemini API via the AI SDK google provider. Users who configured the
|
|
8
|
+
// old OpenAI-compat endpoint can keep it by setting protocol "openai-chat"
|
|
9
|
+
// and the /openai baseURL explicitly in models.json.
|
|
10
|
+
{ id: "google", name: "Google Gemini", baseURL: "https://generativelanguage.googleapis.com/v1beta", protocol: "ai-sdk" },
|
|
8
11
|
{ id: "zhipuai", name: "Zhipu AI", baseURL: "https://open.bigmodel.cn/api/paas/v4" },
|
|
9
12
|
{ id: "zhipuai-coding-plan", name: "Zhipu AI Coding Plan", baseURL: "https://open.bigmodel.cn/api/coding/paas/v4" },
|
|
10
13
|
{ id: "zai", name: "Z.AI", baseURL: "https://api.z.ai/api/paas/v4" },
|
|
@@ -27,6 +30,8 @@ const GPT51_LEVELS = ["off", "low", "medium", "high"];
|
|
|
27
30
|
const GPT51_CODEX_MAX_LEVELS = ["off", "low", "medium", "high", "xhigh"];
|
|
28
31
|
const GPT51_CODEX_MINI_LEVELS = ["off", "medium", "high"];
|
|
29
32
|
const OPENAI_CHAT_LEVELS = ["off"];
|
|
33
|
+
// Internal representation for APIs that expose thinking as enabled/disabled.
|
|
34
|
+
// UI code must render supported toggle models as on/off, not as "medium" effort.
|
|
30
35
|
const TOGGLE_THINKING_LEVELS = ["off", "medium"];
|
|
31
36
|
// GLM-5.2 is the first GLM to accept OpenAI-style `reasoning_effort`. The API
|
|
32
37
|
// enum is none/minimal/low/medium/high/xhigh/max; we expose high and max (the
|
|
@@ -35,8 +40,8 @@ const TOGGLE_THINKING_LEVELS = ["off", "medium"];
|
|
|
35
40
|
// is first so it is the default (getDefaultThinkingLevel falls back to levels[0]
|
|
36
41
|
// when "medium" is absent), since GLM-5.2 is a thinking-on-by-default model.
|
|
37
42
|
const GLM_5_2_LEVELS = ["high", "max", "off"];
|
|
38
|
-
//
|
|
39
|
-
// not offered — the model is always in its thinking variant.
|
|
43
|
+
// Kimi K2.7 Code variants only support thinking mode (disabling it errors), so
|
|
44
|
+
// "off" is not offered — the model is always in its thinking variant.
|
|
40
45
|
const KIMI_THINKING_ONLY_LEVELS = ["medium"];
|
|
41
46
|
const DEEPSEEK_V4_LEVELS = ["high", "max"];
|
|
42
47
|
const STEPFUN_REASONING_LEVELS = ["off", "low", "medium", "high"];
|
|
@@ -51,6 +56,10 @@ const ANTHROPIC_OPUS_EFFORT_LEVELS = ["off", "low", "medium", "high", "xhigh", "
|
|
|
51
56
|
const ANTHROPIC_SONNET_EFFORT_LEVELS = ["off", "low", "medium", "high", "max"];
|
|
52
57
|
const ANTHROPIC_FABLE_EFFORT_LEVELS = ["low", "medium", "high", "xhigh", "max"];
|
|
53
58
|
const ANTHROPIC_CHAT_LEVELS = ["off"];
|
|
59
|
+
const GEMINI_3_LEVELS = ["low", "medium", "high"];
|
|
60
|
+
const GEMINI_3_FLASH_LEVELS = ["minimal", "low", "medium", "high"];
|
|
61
|
+
const GEMINI_25_PRO_LEVELS = ["low", "medium", "high"];
|
|
62
|
+
const GEMINI_25_FLASH_LEVELS = ["off", "low", "medium", "high"];
|
|
54
63
|
export const BUILTIN_MODELS = [
|
|
55
64
|
{ id: "gpt-5.5", name: "gpt-5.5", providerId: "openai-codex", reasoningLevels: ALL_OPENAI_LEVELS, contextWindow: 272000, toolOutputTokenLimit: 10000 },
|
|
56
65
|
{ id: "gpt-5.4", name: "gpt-5.4", providerId: "openai-codex", reasoningLevels: ALL_OPENAI_LEVELS, contextWindow: 272000 },
|
|
@@ -73,9 +82,15 @@ export const BUILTIN_MODELS = [
|
|
|
73
82
|
{ id: "claude-haiku-4-5-20251001", name: "Claude Haiku 4.5", providerId: "anthropic", reasoningLevels: ANTHROPIC_CHAT_LEVELS, contextWindow: 200000 },
|
|
74
83
|
{ id: "deepseek-v4-flash", name: "deepseek-v4-flash", providerId: "deepseek", reasoningLevels: DEEPSEEK_V4_LEVELS, contextWindow: 1048576 },
|
|
75
84
|
{ id: "deepseek-v4-pro", name: "deepseek-v4-pro", providerId: "deepseek", reasoningLevels: DEEPSEEK_V4_LEVELS, contextWindow: 1048576 },
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
85
|
+
// Offline/no-key fallback only: with an API key the registry replaces this
|
|
86
|
+
// list via fetchGeminiModels (GET /v1beta/models, newest five). Gemini 3
|
|
87
|
+
// exposes thinking_level (minimal/low/medium/high); 2.5 Pro cannot disable
|
|
88
|
+
// thinking (no "off"), 2.5 Flash can (thinkingBudget 0).
|
|
89
|
+
{ id: "gemini-3.5-flash", name: "Gemini 3.5 Flash", providerId: "google", reasoningLevels: GEMINI_3_FLASH_LEVELS, contextWindow: 1048576 },
|
|
90
|
+
{ id: "gemini-3.1-pro-preview", name: "Gemini 3.1 Pro", providerId: "google", reasoningLevels: GEMINI_3_LEVELS, defaultReasoningLevel: "high", contextWindow: 1048576 },
|
|
91
|
+
{ id: "gemini-3-flash-preview", name: "Gemini 3 Flash", providerId: "google", reasoningLevels: GEMINI_3_FLASH_LEVELS, contextWindow: 1048576 },
|
|
92
|
+
{ id: "gemini-2.5-pro", name: "Gemini 2.5 Pro", providerId: "google", reasoningLevels: GEMINI_25_PRO_LEVELS, defaultReasoningLevel: "high", contextWindow: 1048576 },
|
|
93
|
+
{ id: "gemini-2.5-flash", name: "Gemini 2.5 Flash", providerId: "google", reasoningLevels: GEMINI_25_FLASH_LEVELS, contextWindow: 1048576 },
|
|
79
94
|
{ id: "glm-5.2", name: "GLM-5.2", providerId: "zhipuai", reasoningLevels: GLM_5_2_LEVELS, contextWindow: 1000000 },
|
|
80
95
|
{ id: "glm-5.1", name: "GLM-5.1", providerId: "zhipuai", reasoningLevels: TOGGLE_THINKING_LEVELS, contextWindow: 200000 },
|
|
81
96
|
{ id: "glm-4.7", name: "GLM-4.7", providerId: "zhipuai", reasoningLevels: TOGGLE_THINKING_LEVELS, contextWindow: 204800 },
|
|
@@ -106,25 +121,17 @@ export const BUILTIN_MODELS = [
|
|
|
106
121
|
{ id: "step-3.5-flash", name: "Step 3.5 Flash", providerId: "stepfun", reasoningLevels: STEPFUN_REASONING_LEVELS },
|
|
107
122
|
{ id: "step-router-v1", name: "Step Router V1", providerId: "stepfun", reasoningLevels: STEPFUN_REASONING_LEVELS },
|
|
108
123
|
{ id: "kimi-k2.7-code", name: "Kimi K2.7 Code", providerId: "moonshot-cn", reasoningLevels: KIMI_THINKING_ONLY_LEVELS, contextWindow: 262144 },
|
|
124
|
+
{ id: "kimi-k2.7-code-highspeed", name: "Kimi K2.7 Code Highspeed", providerId: "moonshot-cn", reasoningLevels: KIMI_THINKING_ONLY_LEVELS, contextWindow: 262144 },
|
|
109
125
|
{ id: "kimi-k2.6", name: "Kimi K2.6", providerId: "moonshot-cn", reasoningLevels: TOGGLE_THINKING_LEVELS, contextWindow: 256000 },
|
|
110
|
-
{ id: "k2.6-code-preview", name: "Kimi K2.6 Code Preview", providerId: "moonshot-cn", reasoningLevels: TOGGLE_THINKING_LEVELS, contextWindow: 256000 },
|
|
111
126
|
{ id: "kimi-k2.5", name: "Kimi K2.5", providerId: "moonshot-cn", reasoningLevels: TOGGLE_THINKING_LEVELS, contextWindow: 256000 },
|
|
112
|
-
{ id: "kimi-k2-turbo-preview", name: "Kimi K2 Turbo", providerId: "moonshot-cn", reasoningLevels: ["off"], contextWindow: 256000 },
|
|
113
|
-
{ id: "kimi-k2-0905-preview", name: "Kimi K2 0905", providerId: "moonshot-cn", reasoningLevels: ["off"], contextWindow: 256000 },
|
|
114
|
-
{ id: "kimi-k2-thinking", name: "Kimi K2 Thinking", providerId: "moonshot-cn", reasoningLevels: TOGGLE_THINKING_LEVELS, contextWindow: 256000 },
|
|
115
127
|
{ id: "kimi-k2.7-code", name: "Kimi K2.7 Code", providerId: "moonshot-intl", reasoningLevels: KIMI_THINKING_ONLY_LEVELS, contextWindow: 262144 },
|
|
128
|
+
{ id: "kimi-k2.7-code-highspeed", name: "Kimi K2.7 Code Highspeed", providerId: "moonshot-intl", reasoningLevels: KIMI_THINKING_ONLY_LEVELS, contextWindow: 262144 },
|
|
116
129
|
{ id: "kimi-k2.6", name: "Kimi K2.6", providerId: "moonshot-intl", reasoningLevels: TOGGLE_THINKING_LEVELS, contextWindow: 256000 },
|
|
117
|
-
{ id: "k2.6-code-preview", name: "Kimi K2.6 Code Preview", providerId: "moonshot-intl", reasoningLevels: TOGGLE_THINKING_LEVELS, contextWindow: 256000 },
|
|
118
130
|
{ id: "kimi-k2.5", name: "Kimi K2.5", providerId: "moonshot-intl", reasoningLevels: TOGGLE_THINKING_LEVELS, contextWindow: 256000 },
|
|
119
|
-
{ id: "kimi-k2-turbo-preview", name: "Kimi K2 Turbo", providerId: "moonshot-intl", reasoningLevels: ["off"], contextWindow: 256000 },
|
|
120
|
-
{ id: "kimi-k2-0905-preview", name: "Kimi K2 0905", providerId: "moonshot-intl", reasoningLevels: ["off"], contextWindow: 256000 },
|
|
121
|
-
{ id: "kimi-k2-thinking", name: "Kimi K2 Thinking", providerId: "moonshot-intl", reasoningLevels: TOGGLE_THINKING_LEVELS, contextWindow: 256000 },
|
|
122
131
|
{ id: "kimi-k2.7-code", name: "Kimi K2.7 Code", providerId: "kimi-for-coding", reasoningLevels: KIMI_THINKING_ONLY_LEVELS, contextWindow: 262144 },
|
|
132
|
+
{ id: "kimi-k2.7-code-highspeed", name: "Kimi K2.7 Code Highspeed", providerId: "kimi-for-coding", reasoningLevels: KIMI_THINKING_ONLY_LEVELS, contextWindow: 262144 },
|
|
123
133
|
{ id: "kimi-k2.6", name: "Kimi K2.6", providerId: "kimi-for-coding", reasoningLevels: TOGGLE_THINKING_LEVELS, contextWindow: 256000 },
|
|
124
|
-
{ id: "k2.
|
|
125
|
-
{ id: "kimi-k2-turbo-preview", name: "Kimi K2 Turbo", providerId: "kimi-for-coding", reasoningLevels: ["off"], contextWindow: 256000 },
|
|
126
|
-
{ id: "kimi-k2-0905-preview", name: "Kimi K2 0905", providerId: "kimi-for-coding", reasoningLevels: ["off"], contextWindow: 256000 },
|
|
127
|
-
{ id: "kimi-k2-thinking", name: "Kimi K2 Thinking", providerId: "kimi-for-coding", reasoningLevels: TOGGLE_THINKING_LEVELS, contextWindow: 256000 },
|
|
134
|
+
{ id: "kimi-k2.5", name: "Kimi K2.5", providerId: "kimi-for-coding", reasoningLevels: TOGGLE_THINKING_LEVELS, contextWindow: 256000 },
|
|
128
135
|
{ id: "llama-3.3-70b-versatile", name: "llama-3.3-70b-versatile", providerId: "groq", reasoningLevels: ["off"], contextWindow: 32768 },
|
|
129
136
|
{ id: "mixtral-8x7b-32768", name: "mixtral-8x7b-32768", providerId: "groq", reasoningLevels: ["off"], contextWindow: 32768 },
|
|
130
137
|
{ id: "gemma-2-9b-it", name: "gemma-2-9b-it", providerId: "groq", reasoningLevels: ["off"], contextWindow: 32768 },
|
|
@@ -5,7 +5,7 @@ import { ExecutionGovernor } from "../agent/execution-governor.js";
|
|
|
5
5
|
import { DiscoveryBarrier } from "../agent/discovery-barrier.js";
|
|
6
6
|
import { arbitrateToolCall } from "../agent/tool-arbiter.js";
|
|
7
7
|
import { buildEditRetryEscalationReminder, buildSmallTaskHint, buildTaskSummaryReminder, buildWorkflowPhaseReminder, } from "../prompt/reminders.js";
|
|
8
|
-
import { reminderForTaskType } from "../prompt/task-reminders.js";
|
|
8
|
+
import { orchestrationRequestReminder, reminderForTaskType } from "../prompt/task-reminders.js";
|
|
9
9
|
import { formatCoverageSummary, resolveWorkflowPhase } from "./workflow.js";
|
|
10
10
|
import { buildSubagentLifecycleReminder } from "../agent/subagent-lifecycle-reminder.js";
|
|
11
11
|
export function createDefaultHooks() {
|
|
@@ -28,6 +28,12 @@ export function createDefaultHooks() {
|
|
|
28
28
|
if (taskReminder) {
|
|
29
29
|
ctx.queueReminder(taskReminder);
|
|
30
30
|
}
|
|
31
|
+
// User named the mechanism ("agent team" / workflow / 编排): remind at
|
|
32
|
+
// the decision turn, where it outweighs the parallel-spawns prior.
|
|
33
|
+
const orchestrationReminder = orchestrationRequestReminder(ctx.input, ctx.agent.hasToolAvailable("run_workflow"));
|
|
34
|
+
if (orchestrationReminder) {
|
|
35
|
+
ctx.queueReminder(orchestrationReminder);
|
|
36
|
+
}
|
|
31
37
|
// Small-task hint: counterweight to the default protocol's exploration
|
|
32
38
|
// bias, only fires once per run on focused one-shot requests like
|
|
33
39
|
// "写个 HTML 介绍元旦". Don't issue for the same input twice.
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
* and read-only-scoped, negative clauses get equal weight — the user's hard
|
|
6
6
|
* constraint is "proactive, but never delegate-everything". Gated on the
|
|
7
7
|
* delegation tools being present, so child agents (whose tool sets never
|
|
8
|
-
* include spawn_agent/
|
|
8
|
+
* include spawn_agent/run_workflow) never see it.
|
|
9
9
|
*/
|
|
10
10
|
/**
|
|
11
11
|
* Returns the delegation policy section when the agent actually has the
|
|
@@ -5,12 +5,19 @@
|
|
|
5
5
|
* and read-only-scoped, negative clauses get equal weight — the user's hard
|
|
6
6
|
* constraint is "proactive, but never delegate-everything". Gated on the
|
|
7
7
|
* delegation tools being present, so child agents (whose tool sets never
|
|
8
|
-
* include spawn_agent/
|
|
8
|
+
* include spawn_agent/run_workflow) never see it.
|
|
9
9
|
*/
|
|
10
10
|
const DELEGATION_POLICY = `## Delegation policy (subagents)
|
|
11
11
|
|
|
12
|
-
You can delegate work
|
|
13
|
-
|
|
12
|
+
You can delegate work two ways: a single background subagent (spawn_agent),
|
|
13
|
+
or an orchestration script coordinating many subagents (run_workflow).
|
|
14
|
+
Delegate deliberately, not by default.
|
|
15
|
+
|
|
16
|
+
Explicit requests win, before any other rule: when the user names a
|
|
17
|
+
coordinated multi-agent run in any phrasing — a workflow, an orchestration,
|
|
18
|
+
an agent team, "fan out agents" — that means run_workflow, NOT a row of
|
|
19
|
+
spawn_agent calls. When they ask for a subagent, spawn one. Only when the
|
|
20
|
+
user has not named a mechanism do you choose by shape (below).
|
|
14
21
|
|
|
15
22
|
Delegate when:
|
|
16
23
|
- An investigation will clearly require more than four search or read
|
|
@@ -18,9 +25,16 @@ Delegate when:
|
|
|
18
25
|
needs the conclusion — delegate to a subagent so the intermediate noise
|
|
19
26
|
stays out of the main context. Launch multiple subagents concurrently for
|
|
20
27
|
independent questions.
|
|
21
|
-
- The task
|
|
22
|
-
|
|
23
|
-
|
|
28
|
+
- The task fans out over many independent items (review, audit, summarize
|
|
29
|
+
across files, modules, endpoints) or needs staged orchestration — consider
|
|
30
|
+
run_workflow. Choose by shape, not by rule: a handful of subagents whose
|
|
31
|
+
results you want to read and react to individually favor spawn_agent; a
|
|
32
|
+
uniform sweep over many items, results that should be aggregated or
|
|
33
|
+
filtered before they reach this conversation, or control flow between
|
|
34
|
+
stages (pipelines, loops, retry rounds) favor a run_workflow script — each
|
|
35
|
+
member's full handoff stays out of your context and the script returns one
|
|
36
|
+
digested result. Failed agent() calls resolve to null, so report which
|
|
37
|
+
items came back null instead of silently dropping them.
|
|
24
38
|
- A side-investigation is independent of your current main-line work and can
|
|
25
39
|
run in the background while you continue.
|
|
26
40
|
|
|
@@ -51,7 +65,7 @@ Do NOT delegate when:
|
|
|
51
65
|
When in doubt about a one-off task, do it yourself. When a task is clearly
|
|
52
66
|
the same read-only operation over three or more independent items — where
|
|
53
67
|
each item alone would take more than a couple of tool calls — prefer
|
|
54
|
-
|
|
68
|
+
run_workflow over doing them sequentially yourself. For just two small items,
|
|
55
69
|
do them yourself with parallel tool calls.`;
|
|
56
70
|
/**
|
|
57
71
|
* Returns the delegation policy section when the agent actually has the
|
|
@@ -4,3 +4,4 @@ export interface TaskReminderOptions {
|
|
|
4
4
|
canDelegate?: boolean;
|
|
5
5
|
}
|
|
6
6
|
export declare function reminderForTaskType(taskType: TaskType, options?: TaskReminderOptions): string | undefined;
|
|
7
|
+
export declare function orchestrationRequestReminder(input: string | import("../types.js").ContentPart[], canRunWorkflow: boolean): string | undefined;
|
|
@@ -6,7 +6,7 @@ import { wrapInSystemReminder } from "./reminders.js";
|
|
|
6
6
|
* keeps it away from ordinary implementation/debugging turns, so it cannot
|
|
7
7
|
* amplify over-delegation.
|
|
8
8
|
*/
|
|
9
|
-
const DELEGATION_NUDGE = "- If answering needs scanning many files and only the conclusion matters, delegate to a background subagent (spawn_agent); when it is the same read-only question over several independent items, fan out with
|
|
9
|
+
const DELEGATION_NUDGE = "- If answering needs scanning many files and only the conclusion matters, delegate to a background subagent (spawn_agent); when it is the same read-only question over several independent items, fan out with a run_workflow script.";
|
|
10
10
|
export function reminderForTaskType(taskType, options = {}) {
|
|
11
11
|
switch (taskType) {
|
|
12
12
|
case "debugging":
|
|
@@ -62,3 +62,26 @@ Product discussion workflow:
|
|
|
62
62
|
return undefined;
|
|
63
63
|
}
|
|
64
64
|
}
|
|
65
|
+
/**
|
|
66
|
+
* Deterministic detector for an explicit user request for a coordinated
|
|
67
|
+
* multi-agent run. Three rounds of prompt wording lost to the model's
|
|
68
|
+
* "agent team = parallel spawns" prior in live tests (opus-4.8, 2026-07-06);
|
|
69
|
+
* per the task-reminder principle above, a reminder injected at the decision
|
|
70
|
+
* turn is the lever that actually works — the harness remembers so the model
|
|
71
|
+
* does not have to.
|
|
72
|
+
*/
|
|
73
|
+
const ORCHESTRATION_REQUEST = /\b(?:workflows?|orchestrat\w*|agent[ -]?teams?|fan[ -]?out)\b|工作流|编排|(?:智能体|代理|agent)\s*(?:团队|小队)/i;
|
|
74
|
+
export function orchestrationRequestReminder(input, canRunWorkflow) {
|
|
75
|
+
if (!canRunWorkflow)
|
|
76
|
+
return undefined;
|
|
77
|
+
const text = typeof input === "string"
|
|
78
|
+
? input
|
|
79
|
+
: input.map((part) => ("text" in part ? String(part.text ?? "") : "")).join(" ");
|
|
80
|
+
if (!ORCHESTRATION_REQUEST.test(text))
|
|
81
|
+
return undefined;
|
|
82
|
+
return [
|
|
83
|
+
"- This message explicitly asks for a coordinated multi-agent run (a workflow / orchestration / agent team).",
|
|
84
|
+
"Honor it with ONE run_workflow call whose script covers the whole fan-out.",
|
|
85
|
+
"Do not substitute parallel spawn_agent calls this turn — the user named the mechanism.",
|
|
86
|
+
].join(" ");
|
|
87
|
+
}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* AI SDK provider backend ("ai-sdk" protocol).
|
|
3
|
+
*
|
|
4
|
+
* Consumes AI SDK provider packages at the LanguageModelV3 spec layer
|
|
5
|
+
* (`model.doStream`) rather than through the high-level `streamText` API:
|
|
6
|
+
* pre-stream HTTP errors throw natively (which our retry/rate-limit contract
|
|
7
|
+
* needs), tool-call inputs arrive as JSON strings (matching `argumentsFull`),
|
|
8
|
+
* and no step machinery or extra dependencies come along.
|
|
9
|
+
*
|
|
10
|
+
* Registered providers: google (Gemini native API). Adding another AI SDK
|
|
11
|
+
* provider is one entry in AI_SDK_PROVIDER_FACTORIES.
|
|
12
|
+
*/
|
|
13
|
+
import { type ProviderFetch } from "./network/provider-transport.js";
|
|
14
|
+
import type { Provider, ReasoningEffort, ThinkingLevel } from "./types.js";
|
|
15
|
+
export interface AiSdkProviderOptions {
|
|
16
|
+
providerId?: string;
|
|
17
|
+
apiKey: string;
|
|
18
|
+
baseURL?: string;
|
|
19
|
+
thinkingLevel?: ThinkingLevel;
|
|
20
|
+
/** Transport override for tests; defaults to the shared provider fetch. */
|
|
21
|
+
fetch?: ProviderFetch;
|
|
22
|
+
}
|
|
23
|
+
export declare function isAiSdkProviderId(providerId: string | undefined): boolean;
|
|
24
|
+
export declare function createAiSdkProvider(options: AiSdkProviderOptions): Provider;
|
|
25
|
+
export interface GeminiModelDescriptor {
|
|
26
|
+
id: string;
|
|
27
|
+
name: string;
|
|
28
|
+
contextWindow?: number;
|
|
29
|
+
reasoningLevels: ReasoningEffort[];
|
|
30
|
+
defaultReasoningLevel?: ReasoningEffort;
|
|
31
|
+
}
|
|
32
|
+
interface GeminiModelListEntry {
|
|
33
|
+
name?: string;
|
|
34
|
+
displayName?: string;
|
|
35
|
+
inputTokenLimit?: number;
|
|
36
|
+
supportedGenerationMethods?: string[];
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Fetch Google's model list and keep the newest general-purpose text models.
|
|
40
|
+
* Newly released Gemini versions appear without a catalog change; the static
|
|
41
|
+
* BUILTIN_MODELS entries stay as the offline/no-key fallback.
|
|
42
|
+
*/
|
|
43
|
+
export declare function fetchGeminiModels(options: {
|
|
44
|
+
apiKey: string;
|
|
45
|
+
baseURL?: string;
|
|
46
|
+
fetch?: ProviderFetch;
|
|
47
|
+
limit?: number;
|
|
48
|
+
}): Promise<GeminiModelDescriptor[]>;
|
|
49
|
+
/**
|
|
50
|
+
* Ranking: one entry per (version, tier) family — GA ids beat dated previews —
|
|
51
|
+
* then newest version first, pro before flash before flash-lite, top N.
|
|
52
|
+
*/
|
|
53
|
+
export declare function selectLatestGeminiModels(entries: GeminiModelListEntry[], limit?: number): GeminiModelDescriptor[];
|
|
54
|
+
/** Mirrors the static catalog's per-family thinking support. */
|
|
55
|
+
export declare function geminiReasoningLevels(modelId: string): ReasoningEffort[];
|
|
56
|
+
export {};
|