@bubblebrain-ai/bubble 0.0.7 → 0.0.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (119) hide show
  1. package/dist/agent/categories.d.ts +34 -0
  2. package/dist/agent/categories.js +98 -0
  3. package/dist/agent/profiles.d.ts +4 -0
  4. package/dist/agent/profiles.js +2 -3
  5. package/dist/agent/subagent-control.d.ts +5 -0
  6. package/dist/agent/subagent-control.js +4 -0
  7. package/dist/agent/subagent-lifecycle-reminder.d.ts +3 -0
  8. package/dist/agent/subagent-lifecycle-reminder.js +102 -0
  9. package/dist/agent/subagent-route-format.d.ts +8 -0
  10. package/dist/agent/subagent-route-format.js +18 -0
  11. package/dist/agent/subtask-policy.d.ts +0 -1
  12. package/dist/agent/subtask-policy.js +0 -4
  13. package/dist/agent.d.ts +18 -0
  14. package/dist/agent.js +188 -16
  15. package/dist/config.d.ts +23 -3
  16. package/dist/config.js +59 -6
  17. package/dist/context/budget.d.ts +3 -2
  18. package/dist/context/budget.js +29 -15
  19. package/dist/context/compact.d.ts +23 -0
  20. package/dist/context/compact.js +129 -0
  21. package/dist/context/llm-compactor.d.ts +19 -0
  22. package/dist/context/llm-compactor.js +200 -0
  23. package/dist/context/projector.js +28 -12
  24. package/dist/context/token-estimator.d.ts +14 -0
  25. package/dist/context/token-estimator.js +106 -0
  26. package/dist/context/tool-output-truncate.d.ts +8 -0
  27. package/dist/context/tool-output-truncate.js +59 -0
  28. package/dist/context/usage.d.ts +34 -0
  29. package/dist/context/usage.js +213 -0
  30. package/dist/diff-stats.d.ts +5 -0
  31. package/dist/diff-stats.js +21 -0
  32. package/dist/main.js +68 -7
  33. package/dist/mcp/transports.d.ts +1 -0
  34. package/dist/mcp/transports.js +8 -0
  35. package/dist/model-catalog.d.ts +9 -0
  36. package/dist/model-catalog.js +17 -1
  37. package/dist/orchestrator/default-hooks.js +24 -18
  38. package/dist/prompt/compose.js +2 -1
  39. package/dist/prompt/provider-prompts/kimi.js +3 -1
  40. package/dist/provider-openai-codex.d.ts +13 -2
  41. package/dist/provider-openai-codex.js +81 -32
  42. package/dist/provider-registry.js +22 -6
  43. package/dist/provider-transform.d.ts +3 -1
  44. package/dist/provider-transform.js +15 -0
  45. package/dist/provider.d.ts +4 -1
  46. package/dist/provider.js +89 -4
  47. package/dist/reasoning-debug.d.ts +7 -0
  48. package/dist/reasoning-debug.js +30 -0
  49. package/dist/session-log.js +13 -2
  50. package/dist/session-types.d.ts +1 -1
  51. package/dist/slash-commands/commands.js +60 -2
  52. package/dist/slash-commands/types.d.ts +7 -0
  53. package/dist/tools/agent-lifecycle.js +22 -4
  54. package/dist/tools/edit.js +7 -2
  55. package/dist/tools/file-state.d.ts +19 -0
  56. package/dist/tools/file-state.js +15 -0
  57. package/dist/tools/glob.js +2 -1
  58. package/dist/tools/grep.js +2 -2
  59. package/dist/tools/lsp.js +2 -2
  60. package/dist/tools/path-utils.d.ts +2 -0
  61. package/dist/tools/path-utils.js +16 -0
  62. package/dist/tools/read.d.ts +1 -1
  63. package/dist/tools/read.js +207 -14
  64. package/dist/tools/write.js +3 -2
  65. package/dist/tui/escape-confirmation.d.ts +15 -0
  66. package/dist/tui/escape-confirmation.js +30 -0
  67. package/dist/tui/run.js +93 -23
  68. package/dist/tui-ink/app.d.ts +52 -0
  69. package/dist/tui-ink/app.js +1129 -0
  70. package/dist/tui-ink/approval/approval-dialog.d.ts +13 -0
  71. package/dist/tui-ink/approval/approval-dialog.js +132 -0
  72. package/dist/tui-ink/approval/diff-view.d.ts +7 -0
  73. package/dist/tui-ink/approval/diff-view.js +44 -0
  74. package/dist/tui-ink/approval/select.d.ts +35 -0
  75. package/dist/tui-ink/approval/select.js +88 -0
  76. package/dist/tui-ink/code-highlight.d.ts +8 -0
  77. package/dist/tui-ink/code-highlight.js +122 -0
  78. package/dist/tui-ink/detect-theme.d.ts +19 -0
  79. package/dist/tui-ink/detect-theme.js +123 -0
  80. package/dist/tui-ink/display-history.d.ts +38 -0
  81. package/dist/tui-ink/display-history.js +130 -0
  82. package/dist/tui-ink/edit-diff.d.ts +11 -0
  83. package/dist/tui-ink/edit-diff.js +52 -0
  84. package/dist/tui-ink/file-mentions.d.ts +29 -0
  85. package/dist/tui-ink/file-mentions.js +174 -0
  86. package/dist/tui-ink/footer.d.ts +19 -0
  87. package/dist/tui-ink/footer.js +45 -0
  88. package/dist/tui-ink/image-paste.d.ts +54 -0
  89. package/dist/tui-ink/image-paste.js +288 -0
  90. package/dist/tui-ink/input-box.d.ts +41 -0
  91. package/dist/tui-ink/input-box.js +694 -0
  92. package/dist/tui-ink/input-history.d.ts +16 -0
  93. package/dist/tui-ink/input-history.js +81 -0
  94. package/dist/tui-ink/markdown.d.ts +38 -0
  95. package/dist/tui-ink/markdown.js +394 -0
  96. package/dist/tui-ink/message-list.d.ts +33 -0
  97. package/dist/tui-ink/message-list.js +667 -0
  98. package/dist/tui-ink/model-picker.d.ts +43 -0
  99. package/dist/tui-ink/model-picker.js +331 -0
  100. package/dist/tui-ink/plan-confirm.d.ts +7 -0
  101. package/dist/tui-ink/plan-confirm.js +105 -0
  102. package/dist/tui-ink/question-dialog.d.ts +8 -0
  103. package/dist/tui-ink/question-dialog.js +99 -0
  104. package/dist/tui-ink/recent-activity.d.ts +8 -0
  105. package/dist/tui-ink/recent-activity.js +71 -0
  106. package/dist/tui-ink/run.d.ts +37 -0
  107. package/dist/tui-ink/run.js +53 -0
  108. package/dist/tui-ink/theme.d.ts +66 -0
  109. package/dist/tui-ink/theme.js +115 -0
  110. package/dist/tui-ink/todos.d.ts +7 -0
  111. package/dist/tui-ink/todos.js +46 -0
  112. package/dist/tui-ink/trace-groups.d.ts +27 -0
  113. package/dist/tui-ink/trace-groups.js +389 -0
  114. package/dist/tui-ink/use-terminal-size.d.ts +4 -0
  115. package/dist/tui-ink/use-terminal-size.js +21 -0
  116. package/dist/tui-ink/welcome.d.ts +18 -0
  117. package/dist/tui-ink/welcome.js +138 -0
  118. package/dist/types.d.ts +10 -0
  119. package/package.json +7 -1
@@ -0,0 +1,34 @@
1
+ import type { ThinkingLevel } from "../types.js";
2
+ export interface AgentCategoryConfig {
3
+ model?: string;
4
+ thinkingLevel?: ThinkingLevel;
5
+ maxConcurrent?: number;
6
+ }
7
+ export type AgentCategoriesConfig = Record<string, AgentCategoryConfig>;
8
+ export interface ModelRoute {
9
+ providerId: string;
10
+ model: string;
11
+ thinkingLevel: ThinkingLevel;
12
+ }
13
+ export interface ResolvedSubagentRoute extends ModelRoute {
14
+ category?: string;
15
+ inherited: boolean;
16
+ }
17
+ export type CategoryResolution = {
18
+ route: ResolvedSubagentRoute;
19
+ } | {
20
+ error: string;
21
+ };
22
+ export interface ResolvedModelSelection {
23
+ providerId: string;
24
+ model: string | "inherit";
25
+ }
26
+ export declare function builtinAgentCategories(): AgentCategoriesConfig;
27
+ export declare function mergeAgentCategories(userCategories?: AgentCategoriesConfig): AgentCategoriesConfig;
28
+ export declare function sanitizeAgentCategories(value: unknown): AgentCategoriesConfig;
29
+ export declare function resolveSubagentRoute(category: string | undefined, parent: ModelRoute, categories?: AgentCategoriesConfig): CategoryResolution;
30
+ export declare function resolveModelRoute(model: string | undefined, parentProviderId: string): ResolvedModelSelection;
31
+ export declare function resolveSameProviderModelRoute(model: string | undefined, parentProviderId: string): {
32
+ model: string | "inherit";
33
+ };
34
+ export declare function normalizeCategoryName(value: unknown): string | undefined;
@@ -0,0 +1,98 @@
1
+ const THINKING_LEVELS = new Set([
2
+ "off",
3
+ "minimal",
4
+ "low",
5
+ "medium",
6
+ "high",
7
+ "xhigh",
8
+ "max",
9
+ ]);
10
+ const BUILTIN_CATEGORIES = {
11
+ quick: { model: "inherit", thinkingLevel: "low", maxConcurrent: 3 },
12
+ deep: { model: "inherit", thinkingLevel: "high", maxConcurrent: 2 },
13
+ explore: { model: "inherit", thinkingLevel: "low", maxConcurrent: 3 },
14
+ review: { model: "inherit", thinkingLevel: "high", maxConcurrent: 2 },
15
+ frontend: { model: "inherit", thinkingLevel: "high", maxConcurrent: 1 },
16
+ writing: { model: "inherit", thinkingLevel: "medium", maxConcurrent: 2 },
17
+ };
18
+ export function builtinAgentCategories() {
19
+ return cloneCategories(BUILTIN_CATEGORIES);
20
+ }
21
+ export function mergeAgentCategories(userCategories) {
22
+ const merged = builtinAgentCategories();
23
+ for (const [name, config] of Object.entries(sanitizeAgentCategories(userCategories))) {
24
+ merged[name] = {
25
+ ...(merged[name] ?? {}),
26
+ ...config,
27
+ };
28
+ }
29
+ return merged;
30
+ }
31
+ export function sanitizeAgentCategories(value) {
32
+ if (!value || typeof value !== "object" || Array.isArray(value))
33
+ return {};
34
+ const out = {};
35
+ for (const [name, raw] of Object.entries(value)) {
36
+ const normalizedName = normalizeCategoryName(name);
37
+ if (!normalizedName || !raw || typeof raw !== "object" || Array.isArray(raw))
38
+ continue;
39
+ const record = raw;
40
+ const config = {};
41
+ if (typeof record.model === "string" && record.model.trim()) {
42
+ config.model = record.model.trim();
43
+ }
44
+ if (isThinkingLevel(record.thinkingLevel)) {
45
+ config.thinkingLevel = record.thinkingLevel;
46
+ }
47
+ if (typeof record.maxConcurrent === "number" && Number.isFinite(record.maxConcurrent)) {
48
+ config.maxConcurrent = Math.max(1, Math.floor(record.maxConcurrent));
49
+ }
50
+ out[normalizedName] = config;
51
+ }
52
+ return out;
53
+ }
54
+ export function resolveSubagentRoute(category, parent, categories) {
55
+ const normalizedCategory = normalizeCategoryName(category);
56
+ if (!normalizedCategory) {
57
+ return { route: { ...parent, inherited: true } };
58
+ }
59
+ const merged = mergeAgentCategories(categories);
60
+ const config = merged[normalizedCategory];
61
+ if (!config) {
62
+ return { error: `Unknown subagent category "${normalizedCategory}".` };
63
+ }
64
+ const modelSelection = parseModelSelection(config.model, parent.providerId);
65
+ return {
66
+ route: {
67
+ category: normalizedCategory,
68
+ providerId: modelSelection.providerId,
69
+ model: modelSelection.model === "inherit" ? parent.model : modelSelection.model,
70
+ thinkingLevel: config.thinkingLevel ?? parent.thinkingLevel,
71
+ inherited: modelSelection.model === "inherit" && config.thinkingLevel === undefined,
72
+ },
73
+ };
74
+ }
75
+ export function resolveModelRoute(model, parentProviderId) {
76
+ return parseModelSelection(model, parentProviderId);
77
+ }
78
+ export function resolveSameProviderModelRoute(model, parentProviderId) {
79
+ return { model: parseModelSelection(model, parentProviderId).model };
80
+ }
81
+ export function normalizeCategoryName(value) {
82
+ return typeof value === "string" && value.trim() ? value.trim().toLowerCase() : undefined;
83
+ }
84
+ function parseModelSelection(model, parentProviderId) {
85
+ if (!model || model === "inherit")
86
+ return { providerId: parentProviderId, model: "inherit" };
87
+ if (model.includes(":")) {
88
+ const [providerId, ...rest] = model.split(":");
89
+ return { providerId: providerId || parentProviderId, model: rest.join(":") };
90
+ }
91
+ return { providerId: parentProviderId, model };
92
+ }
93
+ function isThinkingLevel(value) {
94
+ return typeof value === "string" && THINKING_LEVELS.has(value);
95
+ }
96
+ function cloneCategories(categories) {
97
+ return Object.fromEntries(Object.entries(categories).map(([name, config]) => [name, { ...config }]));
98
+ }
@@ -1,4 +1,5 @@
1
1
  import type { ToolRegistryEntry, TokenUsage } from "../types.js";
2
+ import type { ResolvedSubagentRoute } from "./categories.js";
2
3
  import { type SubtaskType } from "./subtask-policy.js";
3
4
  export type AgentProfileSource = "user" | "project" | "builtin";
4
5
  export type AgentProfileMode = "readonly" | "write_patch" | "write_worktree";
@@ -16,6 +17,7 @@ export interface AgentProfile {
16
17
  filePath?: string;
17
18
  mode: AgentProfileMode;
18
19
  model?: string | "inherit";
20
+ category?: string;
19
21
  tools: AgentProfileTools;
20
22
  maxTurns?: number;
21
23
  approval: AgentProfileApproval;
@@ -29,6 +31,8 @@ export interface SubagentRunResult {
29
31
  nickname?: string;
30
32
  status: "completed" | "failed" | "blocked" | "cancelled";
31
33
  profileSource: AgentProfileSource;
34
+ category?: string;
35
+ route?: ResolvedSubagentRoute;
32
36
  task: string;
33
37
  summary: string;
34
38
  toolNotes: string[];
@@ -85,7 +85,6 @@ export function builtinAgentProfiles() {
85
85
  include: [...policy.allowedTools],
86
86
  exclude: [],
87
87
  },
88
- maxTurns: policy.maxTurns,
89
88
  approval: "fail",
90
89
  nicknameCandidates: DEFAULT_NICKNAME_CANDIDATES,
91
90
  prompt: policy.reminder,
@@ -103,7 +102,6 @@ export function builtinAgentProfiles() {
103
102
  include,
104
103
  exclude: [],
105
104
  },
106
- maxTurns: 8,
107
105
  approval: "fail",
108
106
  nicknameCandidates: DEFAULT_NICKNAME_CANDIDATES,
109
107
  prompt,
@@ -119,7 +117,7 @@ export function builtinAgentProfiles() {
119
117
  "Answer the specific question by inspecting the repository directly. Prefer precise file paths and line-level evidence.",
120
118
  "Keep the answer compact and avoid broad refactors or implementation plans unless asked.",
121
119
  ].join("\n"), ["read", "glob", "grep", "lsp", "memory_search", "memory_read_summary", "skill", "todo_write"]),
122
- roleProfile("worker", "Bounded implementation worker subagent", [
120
+ roleProfile("worker", "Implementation-planning worker subagent", [
123
121
  "You are a worker subagent. In this Phase 1 runtime you are read-only, so you must not modify files.",
124
122
  "Analyze the assigned implementation slice, identify exact files to change, and return a concrete patch plan or findings.",
125
123
  "If write-capable worker mode is needed, say so explicitly.",
@@ -298,6 +296,7 @@ function parseAgentProfileFile(raw, source, filePath) {
298
296
  filePath,
299
297
  mode: modeValue(frontmatter.mode),
300
298
  model: stringValue(frontmatter.model) || "inherit",
299
+ category: stringValue(frontmatter.category),
301
300
  tools: toolsValue(frontmatter.tools),
302
301
  maxTurns: numberValue(frontmatter.maxTurns),
303
302
  approval: approvalValue(frontmatter.approval),
@@ -1,4 +1,5 @@
1
1
  import type { AgentProfile, AgentProfileSource, SubagentRunResult } from "./profiles.js";
2
+ import type { ResolvedSubagentRoute } from "./categories.js";
2
3
  import type { AgentEvent, ContentPart, Message, ToolUpdate } from "../types.js";
3
4
  export type SubagentThreadStatus = "queued" | "running" | "completed" | "failed" | "blocked" | "cancelled" | "closed";
4
5
  export interface SubagentThreadSnapshot {
@@ -7,6 +8,8 @@ export interface SubagentThreadSnapshot {
7
8
  nickname: string;
8
9
  agentName: string;
9
10
  profileSource: AgentProfileSource;
11
+ category?: string;
12
+ route?: ResolvedSubagentRoute;
10
13
  status: SubagentThreadStatus;
11
14
  task: string;
12
15
  summary: string;
@@ -21,6 +24,8 @@ export interface SubagentThreadRecord {
21
24
  runId: string;
22
25
  nickname: string;
23
26
  profile: AgentProfile;
27
+ category?: string;
28
+ route?: ResolvedSubagentRoute;
24
29
  parentToolCallId: string;
25
30
  parentToolName: string;
26
31
  status: SubagentThreadStatus;
@@ -5,6 +5,8 @@ export function snapshotSubagentThread(record) {
5
5
  nickname: record.nickname,
6
6
  agentName: record.profile.name,
7
7
  profileSource: record.profile.source,
8
+ category: record.category,
9
+ route: record.route,
8
10
  status: record.status,
9
11
  task: record.task,
10
12
  summary: record.summary,
@@ -29,6 +31,8 @@ export function subagentResultFromThread(record) {
29
31
  nickname: record.nickname,
30
32
  status,
31
33
  profileSource: record.profile.source,
34
+ category: record.category,
35
+ route: record.route,
32
36
  task: record.task,
33
37
  summary: record.summary,
34
38
  toolNotes: [...record.toolNotes],
@@ -0,0 +1,3 @@
1
+ import type { SubagentThreadSnapshot } from "./subagent-control.js";
2
+ import type { ToolResult } from "../types.js";
3
+ export declare function buildSubagentLifecycleReminder(snapshots: SubagentThreadSnapshot[], toolResults: ToolResult[]): string | undefined;
@@ -0,0 +1,102 @@
1
+ const STATUS_ORDER = ["queued", "running", "completed", "blocked", "failed", "cancelled", "closed"];
2
+ export function buildSubagentLifecycleReminder(snapshots, toolResults) {
3
+ const subagents = collectUniqueSubagents(snapshots, toolResults);
4
+ if (subagents.length === 0)
5
+ return undefined;
6
+ const counts = statusCounts(subagents);
7
+ const lines = [
8
+ "Subagent lifecycle truth:",
9
+ `- Unique subagents currently tracked: ${subagents.length}.`,
10
+ `- Status counts: ${formatStatusCounts(counts)}.`,
11
+ "- Agents:",
12
+ ...subagents.map(formatSubagentLine),
13
+ "- Count unique agent_id values only; do not count repeated spawn_agent/wait_agent tool calls or repeated UI Subagents blocks as additional subagents.",
14
+ "- Do not describe a subagent as running or still working if its status above is completed, failed, blocked, cancelled, or closed.",
15
+ "- After spawn_agent, call wait_agent before user-facing progress narration unless you are doing concrete non-overlapping local work.",
16
+ "- When writing a synthesis, use the exact unique subagent count and statuses above.",
17
+ ];
18
+ return lines.join("\n");
19
+ }
20
+ function collectUniqueSubagents(snapshots, toolResults) {
21
+ const byId = new Map();
22
+ for (const result of toolResults) {
23
+ for (const subagent of subagentsFromMetadata(result.metadata)) {
24
+ byId.set(subagent.agentId, {
25
+ ...byId.get(subagent.agentId),
26
+ ...subagent,
27
+ });
28
+ }
29
+ }
30
+ for (const snapshot of snapshots) {
31
+ byId.set(snapshot.agentId, {
32
+ ...byId.get(snapshot.agentId),
33
+ agentId: snapshot.agentId,
34
+ nickname: snapshot.nickname,
35
+ agentName: snapshot.agentName,
36
+ category: snapshot.category,
37
+ status: snapshot.status,
38
+ summary: snapshot.summary,
39
+ error: snapshot.error,
40
+ });
41
+ }
42
+ return [...byId.values()].sort((a, b) => a.agentId.localeCompare(b.agentId));
43
+ }
44
+ function subagentsFromMetadata(metadata) {
45
+ const raw = metadata?.subagents;
46
+ if (!Array.isArray(raw))
47
+ return [];
48
+ const out = [];
49
+ for (const item of raw) {
50
+ if (!item || typeof item !== "object")
51
+ continue;
52
+ const record = item;
53
+ const agentId = stringField(record.subAgentId) ?? stringField(record.agentId);
54
+ if (!agentId)
55
+ continue;
56
+ out.push({
57
+ agentId,
58
+ nickname: stringField(record.nickname),
59
+ agentName: stringField(record.agentName),
60
+ category: stringField(record.category),
61
+ status: stringField(record.status),
62
+ summary: stringField(record.summary),
63
+ error: stringField(record.error),
64
+ });
65
+ }
66
+ return out;
67
+ }
68
+ function statusCounts(subagents) {
69
+ const counts = new Map();
70
+ for (const subagent of subagents) {
71
+ const status = subagent.status || "unknown";
72
+ counts.set(status, (counts.get(status) ?? 0) + 1);
73
+ }
74
+ return counts;
75
+ }
76
+ function formatStatusCounts(counts) {
77
+ const known = STATUS_ORDER
78
+ .filter((status) => counts.has(status))
79
+ .map((status) => `${status}=${counts.get(status)}`);
80
+ const extra = [...counts.keys()]
81
+ .filter((status) => !STATUS_ORDER.includes(status))
82
+ .sort()
83
+ .map((status) => `${status}=${counts.get(status)}`);
84
+ return [...known, ...extra].join(", ") || "none";
85
+ }
86
+ function formatSubagentLine(subagent) {
87
+ const label = subagent.nickname || subagent.agentName || subagent.agentId;
88
+ const role = [subagent.agentName, subagent.category ? `/${subagent.category}` : ""].join("") || "default";
89
+ const status = subagent.status || "unknown";
90
+ const note = subagent.error || subagent.summary;
91
+ const suffix = note ? `; note=${truncateForReminder(oneLine(note))}` : "";
92
+ return ` - ${label} (${role}) agent_id=${subagent.agentId} status=${status}${suffix}`;
93
+ }
94
+ function stringField(value) {
95
+ return typeof value === "string" && value.trim() ? value.trim() : undefined;
96
+ }
97
+ function oneLine(value) {
98
+ return value.replace(/\s+/g, " ").trim();
99
+ }
100
+ function truncateForReminder(value, max = 180) {
101
+ return value.length <= max ? value : `${value.slice(0, max - 3)}...`;
102
+ }
@@ -0,0 +1,8 @@
1
+ export interface SubagentRouteLike {
2
+ providerId?: unknown;
3
+ model?: unknown;
4
+ thinkingLevel?: unknown;
5
+ }
6
+ export declare function formatSubagentRoute(route: SubagentRouteLike | undefined, options?: {
7
+ includeThinking?: boolean;
8
+ }): string | undefined;
@@ -0,0 +1,18 @@
1
+ export function formatSubagentRoute(route, options = {}) {
2
+ if (!route || typeof route !== "object")
3
+ return undefined;
4
+ const providerId = stringField(route.providerId);
5
+ const model = stringField(route.model);
6
+ if (!providerId && !model)
7
+ return undefined;
8
+ const modelLabel = providerId && model
9
+ ? `${providerId}:${model}`
10
+ : providerId || model;
11
+ if (!options.includeThinking)
12
+ return modelLabel;
13
+ const thinkingLevel = stringField(route.thinkingLevel);
14
+ return thinkingLevel ? `${modelLabel} (thinking: ${thinkingLevel})` : modelLabel;
15
+ }
16
+ function stringField(value) {
17
+ return typeof value === "string" && value.trim() ? value.trim() : undefined;
18
+ }
@@ -5,7 +5,6 @@ export interface SubtaskPolicy {
5
5
  allowedTools: string[];
6
6
  reminder: string;
7
7
  resultStatus: ToolResultStatus;
8
- maxTurns?: number;
9
8
  taskBudget?: {
10
9
  total: number;
11
10
  };
@@ -9,7 +9,6 @@ const POLICY_MAP = {
9
9
  "- Return a concise summary of what you found and where.",
10
10
  ].join("\n"),
11
11
  resultStatus: "success",
12
- maxTurns: 6,
13
12
  taskBudget: { total: 180_000 },
14
13
  },
15
14
  security_investigation: {
@@ -22,7 +21,6 @@ const POLICY_MAP = {
22
21
  "- Do not loop on broad keyword search; summarize evidence and uncertainty.",
23
22
  ].join("\n"),
24
23
  resultStatus: "success",
25
- maxTurns: 8,
26
24
  taskBudget: { total: 220_000 },
27
25
  },
28
26
  evidence_correlation: {
@@ -35,7 +33,6 @@ const POLICY_MAP = {
35
33
  "- Produce a reasoning-focused summary that states what the evidence supports.",
36
34
  ].join("\n"),
37
35
  resultStatus: "success",
38
- maxTurns: 4,
39
36
  taskBudget: { total: 120_000 },
40
37
  },
41
38
  general_readonly: {
@@ -47,7 +44,6 @@ const POLICY_MAP = {
47
44
  "- Keep the scope tightly bounded and summarize findings concisely.",
48
45
  ].join("\n"),
49
46
  resultStatus: "success",
50
- maxTurns: 6,
51
47
  taskBudget: { total: 180_000 },
52
48
  },
53
49
  };
package/dist/agent.d.ts CHANGED
@@ -2,12 +2,15 @@
2
2
  * Agent - The core decision loop.
3
3
  * It maintains message state, calls the LLM, executes tools, and auto-continues.
4
4
  */
5
+ import { type ContextUsageSnapshot } from "./context/usage.js";
5
6
  import type { AgentEvent, ContentPart, PermissionMode, Message, Provider, ThinkingLevel, Todo, ToolResult, ToolRegistryEntry, ToolUpdate } from "./types.js";
6
7
  import { type TurnHooks } from "./orchestrator/hooks.js";
8
+ import { type AgentCategoriesConfig, type ResolvedSubagentRoute } from "./agent/categories.js";
7
9
  import { BudgetLedger } from "./agent/budget-ledger.js";
8
10
  import { type AgentProfile, type SubagentRunResult } from "./agent/profiles.js";
9
11
  import { type SubagentThreadSnapshot } from "./agent/subagent-control.js";
10
12
  import type { SkillSummary } from "./skills/types.js";
13
+ import type { FileStateTracker } from "./tools/file-state.js";
11
14
  export declare class AgentAbortError extends Error {
12
15
  constructor(message?: string);
13
16
  }
@@ -39,6 +42,9 @@ export interface AgentOptions {
39
42
  };
40
43
  skills?: SkillSummary[];
41
44
  memoryPrompt?: string;
45
+ fileStateTracker?: FileStateTracker;
46
+ agentCategories?: AgentCategoriesConfig;
47
+ providerFactory?: (route: ResolvedSubagentRoute) => Provider | Promise<Provider>;
42
48
  }
43
49
  export declare class Agent {
44
50
  messages: Message[];
@@ -65,6 +71,9 @@ export declare class Agent {
65
71
  private budgetSource;
66
72
  private skillSummaries;
67
73
  private memoryPrompt?;
74
+ private fileStateTracker?;
75
+ private agentCategories;
76
+ private providerFactory?;
68
77
  private subagentThreads;
69
78
  private pendingSubagentUpdates;
70
79
  private lastInputTokens;
@@ -74,8 +83,10 @@ export declare class Agent {
74
83
  unlockDeferredTools(names: string[]): void;
75
84
  /** All deferred tools in this session (for tool_search to inspect). */
76
85
  listDeferredTools(): ToolRegistryEntry[];
86
+ getContextUsageSnapshot(): ContextUsageSnapshot;
77
87
  /** Whether a given tool is deferred and not yet unlocked. */
78
88
  isDeferredAndLocked(name: string): boolean;
89
+ private getActiveToolEntries;
79
90
  injectSystemReminder(content: string): void;
80
91
  injectModeReminder(): void;
81
92
  get model(): string;
@@ -109,6 +120,7 @@ export declare class Agent {
109
120
  }): AsyncIterable<AgentEvent>;
110
121
  private recoverFromOverflow;
111
122
  compactResidentHistory(): void;
123
+ private maybeCompactWithLLM;
112
124
  runSubtask(input: string | ContentPart[], cwd: string, options?: {
113
125
  subtaskType?: string;
114
126
  description?: string;
@@ -118,6 +130,8 @@ export declare class Agent {
118
130
  runId: string;
119
131
  subAgentId: string;
120
132
  parentToolCallId: string;
133
+ category?: string;
134
+ route?: ResolvedSubagentRoute;
121
135
  approval?: "fail" | "disabled";
122
136
  emitUpdate?: (update: ToolUpdate) => void;
123
137
  description?: string;
@@ -128,6 +142,8 @@ export declare class Agent {
128
142
  spawnSubAgent(input: string | ContentPart[], cwd: string, options: {
129
143
  profile: AgentProfile;
130
144
  parentToolCallId: string;
145
+ category?: string;
146
+ route?: ResolvedSubagentRoute;
131
147
  approval?: "fail" | "disabled";
132
148
  description?: string;
133
149
  abortSignal?: AbortSignal;
@@ -144,10 +160,12 @@ export declare class Agent {
144
160
  }): Promise<SubagentThreadSnapshot>;
145
161
  closeSubAgent(agentId: string): Promise<SubagentThreadSnapshot>;
146
162
  listSubAgents(): SubagentThreadSnapshot[];
163
+ private resolveRouteForSubagent;
147
164
  private createSubagentThreadRecord;
148
165
  private runSubagentThread;
149
166
  private runSubagentFinalSummaryTurn;
150
167
  private createSubAgentInstance;
168
+ private resolveProviderForRoute;
151
169
  private forkMessagesForSubagent;
152
170
  private buildSubagentUpdate;
153
171
  private queueSubagentUpdate;