@compilr-dev/cli 0.7.3 → 0.7.5
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.d.ts +7 -2
- package/dist/agent.js +55 -39
- package/dist/commands-v2/handlers/project.js +65 -2
- package/dist/commands-v2/handlers/settings.js +18 -26
- package/dist/compilr-diff-companion.vsix +0 -0
- package/dist/db/schema.d.ts +1 -1
- package/dist/episodes/index.d.ts +13 -13
- package/dist/episodes/index.js +13 -14
- package/dist/guide/cli-guide-entries.js +54 -2
- package/dist/handlers/delegation-handlers.js +228 -50
- package/dist/handlers/interactive-flow-handlers.d.ts +26 -0
- package/dist/handlers/interactive-flow-handlers.js +61 -0
- package/dist/handlers/propose-alternatives-handlers.d.ts +36 -0
- package/dist/handlers/propose-alternatives-handlers.js +65 -0
- package/dist/index.js +13 -2
- package/dist/repl-v2.d.ts +66 -0
- package/dist/repl-v2.js +382 -53
- package/dist/shared-handlers.d.ts +57 -5
- package/dist/shared-handlers.js +50 -0
- package/dist/tools/consult.d.ts +14 -0
- package/dist/tools/consult.js +73 -0
- package/dist/tools/delegate.d.ts +12 -6
- package/dist/tools/delegate.js +35 -19
- package/dist/tools/interactive-flow.d.ts +13 -0
- package/dist/tools/interactive-flow.js +19 -0
- package/dist/tools/platform-adapter.d.ts +14 -2
- package/dist/tools/platform-adapter.js +16 -4
- package/dist/tools/propose-alternatives.d.ts +13 -0
- package/dist/tools/propose-alternatives.js +19 -0
- package/dist/tools.d.ts +22 -98
- package/dist/tools.js +27 -382
- package/dist/ui/markdown-renderer.js +26 -7
- package/dist/ui/overlay/data/tutorial-registry.js +2 -0
- package/dist/ui/overlay/data/tutorials/projects/interactive-flows.d.ts +9 -0
- package/dist/ui/overlay/data/tutorials/projects/interactive-flows.js +94 -0
- package/dist/ui/overlay/data/tutorials/projects/new-project.js +56 -20
- package/dist/ui/overlay/impl/interactive-flow-overlay-v2.d.ts +79 -0
- package/dist/ui/overlay/impl/interactive-flow-overlay-v2.js +580 -0
- package/dist/ui/overlay/impl/new-overlay-v2.d.ts +32 -0
- package/dist/ui/overlay/impl/new-overlay-v2.js +305 -66
- package/dist/ui/overlay/impl/propose-alternatives-overlay-v2.d.ts +53 -0
- package/dist/ui/overlay/impl/propose-alternatives-overlay-v2.js +326 -0
- package/dist/ui/overlay/index.d.ts +2 -0
- package/dist/ui/overlay/index.js +2 -0
- package/dist/ui/tool-formatters.js +61 -3
- package/package.json +3 -3
package/dist/tools.js
CHANGED
|
@@ -1,387 +1,32 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Tool Registry
|
|
2
|
+
* Tool Registry Helpers (slim).
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
4
|
+
* Pre-SDK migration this file owned the full HOT_TOOLS / WARM_TOOLS /
|
|
5
|
+
* DIRECT_TOOLS / META_REGISTRY_TOOLS arrays and a token-saving registry
|
|
6
|
+
* (~15K → ~2K per turn). That optimisation moved to the SDK as the
|
|
7
|
+
* capability-manager direct/meta tier split (`TOOL_GROUPS.<id>.tier`),
|
|
8
|
+
* and `createCompilrAgent({ capabilities: ... })` now handles tool
|
|
9
|
+
* registration end-to-end. See `src/agent.ts` and
|
|
10
|
+
* `@compilr-dev/sdk/src/capabilities/packs.ts`.
|
|
6
11
|
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
12
|
+
* What remains here is the small surface CLI code outside agent.ts still
|
|
13
|
+
* touches:
|
|
14
|
+
* - `todoStore` — alias for the SDK's `getDefaultTodoStore()` singleton,
|
|
15
|
+
* read by the footer renderer (see `repl-v2.ts`).
|
|
16
|
+
* - `TOOL_NAMES` / `ToolName` / `getAllToolNames` — re-exported from
|
|
17
|
+
* `./tool-names.js` for convenience.
|
|
10
18
|
*
|
|
11
|
-
*
|
|
19
|
+
* Audit refs: TODO-4 (HOT/WARM cleanup), TODO-15 (deleted the parallel
|
|
20
|
+
* dead MetaToolsRegistry singleton + its setMetaToolFilter /
|
|
21
|
+
* getRegisteredMetaTools / isMetaToolSilent surface — the SDK's
|
|
22
|
+
* per-agent CapabilityManager already handles tool filtering at agent
|
|
23
|
+
* factory time, so the CLI re-exports here were always no-ops).
|
|
12
24
|
*
|
|
13
|
-
*
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
//
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
// TOOL IMPORTS
|
|
22
|
-
// =============================================================================
|
|
23
|
-
import { readFileTool, writeFileTool, createBashTool, bashOutputTool, killShellTool, grepTool, globTool, editTool, createTodoTools, defineTool, } from '@compilr-dev/sdk';
|
|
24
|
-
// Create todo tools with shared store (includes claim/handoff)
|
|
25
|
-
const todoToolsResult = createTodoTools();
|
|
26
|
-
const originalTodoWriteTool = todoToolsResult.todoWrite;
|
|
27
|
-
const todoReadTool = todoToolsResult.todoRead;
|
|
28
|
-
const todoClaimTool = todoToolsResult.todoClaim;
|
|
29
|
-
const todoHandoffTool = todoToolsResult.todoHandoff;
|
|
30
|
-
// Explicit type annotation avoids TS2742 when importing createTodoTools via @compilr-dev/sdk
|
|
31
|
-
export const todoStore = todoToolsResult.store;
|
|
32
|
-
const todoWriteTool = defineTool({
|
|
33
|
-
name: 'todo_write',
|
|
34
|
-
description: 'Update the SESSION todo list (shown in footer). These are ephemeral tasks for the current session only. ' +
|
|
35
|
-
'For persistent project backlog items, use workitem_* tools instead. ' +
|
|
36
|
-
'Provide the complete list of todos to replace the current list.',
|
|
37
|
-
inputSchema: {
|
|
38
|
-
type: 'object',
|
|
39
|
-
properties: {
|
|
40
|
-
todos: {
|
|
41
|
-
type: 'array',
|
|
42
|
-
description: 'The complete list of todos',
|
|
43
|
-
items: {
|
|
44
|
-
type: 'object',
|
|
45
|
-
properties: {
|
|
46
|
-
content: {
|
|
47
|
-
type: 'string',
|
|
48
|
-
description: 'Task description (imperative form, e.g., "Fix bug in login")',
|
|
49
|
-
},
|
|
50
|
-
status: {
|
|
51
|
-
type: 'string',
|
|
52
|
-
enum: ['pending', 'in_progress', 'completed'],
|
|
53
|
-
description: 'Task status',
|
|
54
|
-
},
|
|
55
|
-
activeForm: {
|
|
56
|
-
type: 'string',
|
|
57
|
-
description: 'Active form (present continuous, e.g., "Fixing bug in login")',
|
|
58
|
-
},
|
|
59
|
-
priority: {
|
|
60
|
-
type: 'number',
|
|
61
|
-
description: 'Priority (higher = more important)',
|
|
62
|
-
},
|
|
63
|
-
owner: {
|
|
64
|
-
type: 'string',
|
|
65
|
-
description: 'Owner agent ID (e.g., "dev", "pm", "arch"). Omit for unassigned.',
|
|
66
|
-
},
|
|
67
|
-
blockedBy: {
|
|
68
|
-
type: 'array',
|
|
69
|
-
items: { type: 'number' },
|
|
70
|
-
description: 'Array of 1-based task numbers this task depends on (e.g., [3, 4] means blocked by task #3 and #4)',
|
|
71
|
-
},
|
|
72
|
-
},
|
|
73
|
-
required: ['content', 'status'],
|
|
74
|
-
},
|
|
75
|
-
},
|
|
76
|
-
},
|
|
77
|
-
required: ['todos'],
|
|
78
|
-
},
|
|
79
|
-
execute: async (input) => {
|
|
80
|
-
// Normalize todos - accept alternative property names
|
|
81
|
-
const normalizedTodos = input.todos.map((todo) => ({
|
|
82
|
-
content: (todo.content || todo.title || todo.description || todo.task || todo.text || '').trim(),
|
|
83
|
-
status: todo.status,
|
|
84
|
-
activeForm: todo.activeForm,
|
|
85
|
-
priority: todo.priority,
|
|
86
|
-
owner: todo.owner,
|
|
87
|
-
blockedBy: todo.blockedBy,
|
|
88
|
-
}));
|
|
89
|
-
// Filter out empty todos and provide fallback
|
|
90
|
-
const validTodos = normalizedTodos.map((todo) => ({
|
|
91
|
-
...todo,
|
|
92
|
-
content: todo.content || 'Untitled task',
|
|
93
|
-
}));
|
|
94
|
-
// Call the original tool with normalized input
|
|
95
|
-
const result = await originalTodoWriteTool.execute({ todos: validTodos });
|
|
96
|
-
return result;
|
|
97
|
-
},
|
|
98
|
-
silent: true,
|
|
99
|
-
});
|
|
100
|
-
// Create bash tool with longer timeout (2 minutes instead of 30 seconds)
|
|
101
|
-
const bashTool = createBashTool({
|
|
102
|
-
timeout: 120000, // 2 minutes
|
|
103
|
-
});
|
|
104
|
-
import {
|
|
105
|
-
// Git tools (basic)
|
|
106
|
-
gitStatusTool, gitDiffTool, gitLogTool, gitCommitTool, gitBranchTool,
|
|
107
|
-
// Git tools (advanced)
|
|
108
|
-
gitStashTool, gitBlameTool, gitFileHistoryTool,
|
|
109
|
-
// Project detection
|
|
110
|
-
detectProjectTool, findProjectRootTool,
|
|
111
|
-
// Smart runners
|
|
112
|
-
runTestsTool, runLintTool, runBuildTool, runFormatTool,
|
|
113
|
-
// Code search
|
|
114
|
-
findDefinitionTool, findReferencesTool, findTodosTool,
|
|
115
|
-
// Dependency analysis
|
|
116
|
-
checkOutdatedTool, findVulnerabilitiesTool,
|
|
117
|
-
// Testing analysis
|
|
118
|
-
analyzeTestCoverageTool,
|
|
119
|
-
// Unified analysis (auto-detect language)
|
|
120
|
-
getFileStructureTool, getComplexityTool, } from '@compilr-dev/sdk';
|
|
121
|
-
// Local tools
|
|
122
|
-
import { askUserTool } from './tools/ask-user.js';
|
|
123
|
-
import { askUserSimpleTool } from './tools/ask-user-simple.js';
|
|
124
|
-
import { delegateTool } from './tools/delegate.js';
|
|
125
|
-
import { delegateBackgroundTool } from './tools/delegate-background.js';
|
|
126
|
-
import { delegationStatusTool } from './tools/delegation-status.js';
|
|
127
|
-
import { handoffTool } from './tools/handoff.js';
|
|
128
|
-
import { createGuideTool } from '@compilr-dev/sdk';
|
|
129
|
-
import { CLI_GUIDE_ENTRIES } from './guide/cli-guide-entries.js';
|
|
130
|
-
const guideTool = createGuideTool({
|
|
131
|
-
environment: 'cli',
|
|
132
|
-
additionalEntries: CLI_GUIDE_ENTRIES,
|
|
133
|
-
});
|
|
134
|
-
// DB tools for project, work item, document, plan, backlog, anchor, artifact, and episode management
|
|
135
|
-
import { allDbTools, allFactoryTools } from './tools/db-tools.js';
|
|
136
|
-
// Meta-tools for dynamic tool loading
|
|
137
|
-
import { initializeMetaToolRegistry, generateToolIndex, generateFilteredToolIndex, getMetaToolCount, META_TOOLS_SYSTEM_PROMPT_PREFIX, setMetaToolFilter, getRegisteredMetaTools, createMetaToolFallback, getToolInfoTool, } from './tools/meta-tools.js';
|
|
138
|
-
// Re-export for use in agent.ts
|
|
139
|
-
export { setMetaToolFilter, getRegisteredMetaTools };
|
|
140
|
-
/**
|
|
141
|
-
* Check if a tool in the meta-registry is marked as silent.
|
|
142
|
-
* Used by the repl to suppress output for warm tools like todo_write/todo_read.
|
|
143
|
-
*/
|
|
144
|
-
export function isMetaToolSilent(name) {
|
|
145
|
-
const tools = getRegisteredMetaTools();
|
|
146
|
-
const tool = tools.find((t) => t.definition.name === name);
|
|
147
|
-
return tool?.silent === true;
|
|
148
|
-
}
|
|
149
|
-
// =============================================================================
|
|
150
|
-
// DIRECT TOOLS - Always available, called by name
|
|
151
|
-
// =============================================================================
|
|
152
|
-
/**
|
|
153
|
-
* Hot tools — used in >50% of turns. Always declared as direct schemas.
|
|
154
|
-
* Estimated: ~2,100 tokens for definitions
|
|
155
|
-
*/
|
|
156
|
-
const HOT_TOOLS = [
|
|
157
|
-
// File operations (most common)
|
|
158
|
-
readFileTool,
|
|
159
|
-
writeFileTool,
|
|
160
|
-
editTool,
|
|
161
|
-
// Shell (very common)
|
|
162
|
-
bashTool,
|
|
163
|
-
// Search (very common)
|
|
164
|
-
globTool,
|
|
165
|
-
grepTool,
|
|
166
|
-
// User interaction (always needed)
|
|
167
|
-
askUserTool,
|
|
168
|
-
];
|
|
169
|
-
/**
|
|
170
|
-
* Warm tools — used occasionally. In hot-tools mode these move to meta-registry.
|
|
171
|
-
* Estimated: ~3,300 tokens for definitions
|
|
172
|
-
*/
|
|
173
|
-
const WARM_TOOLS = [
|
|
174
|
-
// Shell management
|
|
175
|
-
bashOutputTool,
|
|
176
|
-
killShellTool,
|
|
177
|
-
// Task tracking
|
|
178
|
-
todoWriteTool,
|
|
179
|
-
todoReadTool,
|
|
180
|
-
todoClaimTool,
|
|
181
|
-
todoHandoffTool,
|
|
182
|
-
// User interaction (simple variant)
|
|
183
|
-
askUserSimpleTool,
|
|
184
|
-
// Delegation (coordinator only)
|
|
185
|
-
delegateTool,
|
|
186
|
-
// Background delegation (coordinator mode)
|
|
187
|
-
delegateBackgroundTool,
|
|
188
|
-
// Handoff (specialist-to-specialist)
|
|
189
|
-
handoffTool,
|
|
190
|
-
// CLI documentation
|
|
191
|
-
guideTool,
|
|
192
|
-
];
|
|
193
|
-
/**
|
|
194
|
-
* All direct tools combined (hot + warm).
|
|
195
|
-
* Used in legacy mode (no meta-tools) and for backwards compatibility.
|
|
196
|
-
*/
|
|
197
|
-
const DIRECT_TOOLS = [...HOT_TOOLS, ...WARM_TOOLS];
|
|
198
|
-
// =============================================================================
|
|
199
|
-
// META-REGISTRY TOOLS - Available via use_tool()
|
|
200
|
-
// =============================================================================
|
|
201
|
-
/**
|
|
202
|
-
* Meta-registry tools are specialized tools available via use_tool().
|
|
203
|
-
* Instead of declaring their full schemas (~12K tokens), we:
|
|
204
|
-
* 1. Add them to a registry
|
|
205
|
-
* 2. Generate a tool index for the system prompt (~800 tokens)
|
|
206
|
-
* 3. Let the agent call them via use_tool("tool_name", {args})
|
|
207
|
-
*/
|
|
208
|
-
const META_REGISTRY_TOOLS = [
|
|
209
|
-
// Git operations (basic)
|
|
210
|
-
gitStatusTool,
|
|
211
|
-
gitDiffTool,
|
|
212
|
-
gitLogTool,
|
|
213
|
-
gitCommitTool,
|
|
214
|
-
gitBranchTool,
|
|
215
|
-
// Git operations (advanced)
|
|
216
|
-
gitStashTool,
|
|
217
|
-
gitBlameTool,
|
|
218
|
-
gitFileHistoryTool,
|
|
219
|
-
// Project detection
|
|
220
|
-
detectProjectTool,
|
|
221
|
-
findProjectRootTool,
|
|
222
|
-
// Smart runners
|
|
223
|
-
runTestsTool,
|
|
224
|
-
runLintTool,
|
|
225
|
-
runBuildTool,
|
|
226
|
-
runFormatTool,
|
|
227
|
-
// Code search (language-agnostic)
|
|
228
|
-
findDefinitionTool,
|
|
229
|
-
findReferencesTool,
|
|
230
|
-
findTodosTool,
|
|
231
|
-
// Dependency analysis
|
|
232
|
-
checkOutdatedTool,
|
|
233
|
-
findVulnerabilitiesTool,
|
|
234
|
-
// Testing analysis
|
|
235
|
-
analyzeTestCoverageTool,
|
|
236
|
-
// Unified analysis (auto-detect language: TS/JS/Python/Go)
|
|
237
|
-
getFileStructureTool,
|
|
238
|
-
getComplexityTool,
|
|
239
|
-
// DB tools (project, workitem, document, plan, backlog, anchor, artifact, episode)
|
|
240
|
-
...allDbTools,
|
|
241
|
-
// Factory tools (app_model_get, app_model_update, app_model_validate, factory_scaffold, factory_list_toolkits)
|
|
242
|
-
...allFactoryTools,
|
|
243
|
-
// Delegation status (coordinator query)
|
|
244
|
-
delegationStatusTool,
|
|
245
|
-
];
|
|
246
|
-
// =============================================================================
|
|
247
|
-
// LEGACY API (for backwards compatibility)
|
|
248
|
-
// =============================================================================
|
|
249
|
-
/**
|
|
250
|
-
* Creates the tool registry with all available tools.
|
|
251
|
-
* Returns tools as-is - the Agent.registerTools() method handles typing.
|
|
252
|
-
*
|
|
253
|
-
* @deprecated Use createDirectToolRegistry() + initializeMetaTools() instead
|
|
254
|
-
*/
|
|
255
|
-
export function createToolRegistry() {
|
|
256
|
-
return [
|
|
257
|
-
...DIRECT_TOOLS,
|
|
258
|
-
...META_REGISTRY_TOOLS,
|
|
259
|
-
];
|
|
260
|
-
}
|
|
261
|
-
/**
|
|
262
|
-
* Returns a minimal set of tools for basic testing.
|
|
263
|
-
*/
|
|
264
|
-
export function createMinimalToolRegistry() {
|
|
265
|
-
return [
|
|
266
|
-
readFileTool,
|
|
267
|
-
writeFileTool,
|
|
268
|
-
bashTool,
|
|
269
|
-
globTool,
|
|
270
|
-
];
|
|
271
|
-
}
|
|
272
|
-
// =============================================================================
|
|
273
|
-
// META-TOOLS API (new architecture)
|
|
274
|
-
// =============================================================================
|
|
275
|
-
/**
|
|
276
|
-
* Get direct tools that are always available.
|
|
277
|
-
* When hotOnly is true, returns only hot tools (7 tools, ~2.1K tokens).
|
|
278
|
-
* When false/undefined, returns all direct tools (18 tools, ~5.4K tokens).
|
|
279
|
-
*/
|
|
280
|
-
export function getDirectTools(hotOnly) {
|
|
281
|
-
if (hotOnly)
|
|
282
|
-
return HOT_TOOLS;
|
|
283
|
-
return DIRECT_TOOLS;
|
|
284
|
-
}
|
|
285
|
-
/**
|
|
286
|
-
* Get meta-tools for agent registration.
|
|
287
|
-
* Only get_tool_info is kept as a direct tool — use_tool and list_tools
|
|
288
|
-
* are no longer needed since the fallback handler routes calls transparently.
|
|
289
|
-
*/
|
|
290
|
-
export function getMetaTools() {
|
|
291
|
-
return [getToolInfoTool];
|
|
292
|
-
}
|
|
293
|
-
/**
|
|
294
|
-
* Create a fallback handler for the tool registry.
|
|
295
|
-
* When the agent calls a tool not in the direct registry, this handler
|
|
296
|
-
* checks the meta-registry and executes it transparently.
|
|
297
|
-
*
|
|
298
|
-
* Auto-loading of capability packs for filtered tools is handled by the
|
|
299
|
-
* shared onFilteredTool callback in meta-tools.ts (covers both use_tool
|
|
300
|
-
* and direct fallback paths).
|
|
301
|
-
*/
|
|
302
|
-
export function createToolFallback() {
|
|
303
|
-
return createMetaToolFallback();
|
|
304
|
-
}
|
|
305
|
-
/** Whether hot-tools mode is active (warm tools in meta-registry) */
|
|
306
|
-
let hotToolsModeActive = false;
|
|
307
|
-
/**
|
|
308
|
-
* Check if hot-tools mode is active.
|
|
309
|
-
* When true, only hot tools are declared as direct schemas; warm tools are in meta-registry.
|
|
310
|
-
*/
|
|
311
|
-
export function isHotToolsMode() {
|
|
312
|
-
return hotToolsModeActive;
|
|
313
|
-
}
|
|
314
|
-
/**
|
|
315
|
-
* Initialize the meta-tool registry with specialized tools.
|
|
316
|
-
* When includeWarmTools is true, warm tools are also added to the meta-registry
|
|
317
|
-
* (enabling hot-tools mode where only 7 core tools are declared directly).
|
|
318
|
-
* Call this once at startup.
|
|
319
|
-
*/
|
|
320
|
-
export function initializeMetaTools(includeWarmTools) {
|
|
321
|
-
const tools = includeWarmTools
|
|
322
|
-
? [...WARM_TOOLS, ...META_REGISTRY_TOOLS]
|
|
323
|
-
: META_REGISTRY_TOOLS;
|
|
324
|
-
initializeMetaToolRegistry(tools);
|
|
325
|
-
if (includeWarmTools) {
|
|
326
|
-
hotToolsModeActive = true;
|
|
327
|
-
}
|
|
328
|
-
}
|
|
329
|
-
/**
|
|
330
|
-
* Get the tool index for the system prompt.
|
|
331
|
-
* This lists all meta-registry tools with their signatures.
|
|
332
|
-
*/
|
|
333
|
-
export function getToolIndexForSystemPrompt() {
|
|
334
|
-
return META_TOOLS_SYSTEM_PROMPT_PREFIX + generateToolIndex();
|
|
335
|
-
}
|
|
336
|
-
/**
|
|
337
|
-
* Get a filtered tool index for the system prompt.
|
|
338
|
-
* Only includes tools whose names are in the given set.
|
|
339
|
-
* Used by the capability-aware BeforeLLM hook.
|
|
340
|
-
*/
|
|
341
|
-
export function getFilteredToolIndexForSystemPrompt(activeToolNames) {
|
|
342
|
-
return META_TOOLS_SYSTEM_PROMPT_PREFIX + generateFilteredToolIndex(activeToolNames);
|
|
343
|
-
}
|
|
344
|
-
/**
|
|
345
|
-
* Get count of meta-registry tools.
|
|
346
|
-
*/
|
|
347
|
-
export function getMetaToolsCount() {
|
|
348
|
-
return getMetaToolCount();
|
|
349
|
-
}
|
|
350
|
-
/**
|
|
351
|
-
* Check if meta-tools mode is enabled.
|
|
352
|
-
* Returns true if the meta-tool registry has been initialized.
|
|
353
|
-
*/
|
|
354
|
-
export function isMetaToolsEnabled() {
|
|
355
|
-
return getMetaToolCount() > 0;
|
|
356
|
-
}
|
|
357
|
-
// =============================================================================
|
|
358
|
-
// STATISTICS
|
|
359
|
-
// =============================================================================
|
|
360
|
-
/**
|
|
361
|
-
* Get tool statistics for debugging/display.
|
|
362
|
-
*/
|
|
363
|
-
export function getToolStats() {
|
|
364
|
-
const hotCount = HOT_TOOLS.length;
|
|
365
|
-
const warmCount = WARM_TOOLS.length;
|
|
366
|
-
const directCount = hotToolsModeActive ? hotCount : hotCount + warmCount;
|
|
367
|
-
const metaCount = hotToolsModeActive
|
|
368
|
-
? META_REGISTRY_TOOLS.length + warmCount
|
|
369
|
-
: META_REGISTRY_TOOLS.length;
|
|
370
|
-
const totalCount = hotCount + warmCount + META_REGISTRY_TOOLS.length;
|
|
371
|
-
// Rough estimates: ~300 tokens per tool definition
|
|
372
|
-
const tokensPerTool = 300;
|
|
373
|
-
const estimatedDirectTokens = directCount * tokensPerTool;
|
|
374
|
-
const estimatedMetaTokens = 1000; // Tool index + meta-tool definitions
|
|
375
|
-
const estimatedLegacyTokens = totalCount * tokensPerTool;
|
|
376
|
-
return {
|
|
377
|
-
directTools: directCount,
|
|
378
|
-
hotTools: hotCount,
|
|
379
|
-
warmTools: warmCount,
|
|
380
|
-
metaRegistryTools: metaCount,
|
|
381
|
-
totalTools: totalCount,
|
|
382
|
-
estimatedDirectTokens,
|
|
383
|
-
estimatedMetaTokens,
|
|
384
|
-
estimatedLegacyTokens,
|
|
385
|
-
tokenSavings: estimatedLegacyTokens - estimatedDirectTokens - estimatedMetaTokens,
|
|
386
|
-
};
|
|
387
|
-
}
|
|
25
|
+
* See `project-docs/00-requirements/compilr-dev-sdk/architecture-audit-cli-vs-desktop.md`.
|
|
26
|
+
*/
|
|
27
|
+
import { getDefaultTodoStore } from '@compilr-dev/sdk';
|
|
28
|
+
// Tool-name constants — re-exported from the dependency-free module.
|
|
29
|
+
export { TOOL_NAMES, getAllToolNames } from './tool-names.js';
|
|
30
|
+
// Footer + UI reads this; the SDK preset's todo tools write through the
|
|
31
|
+
// same singleton (audit TODO-9).
|
|
32
|
+
export const todoStore = getDefaultTodoStore();
|
|
@@ -112,22 +112,40 @@ function reflowText(text, width, gfm) {
|
|
|
112
112
|
const fragments = sec.split(/(\u001b\[(?:\d{1,3})(?:;\d{1,3})*m)/g);
|
|
113
113
|
let column = 0;
|
|
114
114
|
let currentLine = '';
|
|
115
|
-
|
|
115
|
+
// Carries through ANSI fragments so the space-before-word decision for
|
|
116
|
+
// the next text fragment knows whether boundary whitespace existed in
|
|
117
|
+
// the source. Fixes the bug where "the `consult` tool" rendered as
|
|
118
|
+
// "theconsulttool" — the trailing space of "the " and leading space of
|
|
119
|
+
// " tool" were both discarded by the split-on-whitespace, and the old
|
|
120
|
+
// `lastWasEscape` flag suppressed re-inserting them.
|
|
121
|
+
let prevTextEndedWithWs = false;
|
|
116
122
|
for (const fragment of fragments) {
|
|
117
|
-
if (fragment === '')
|
|
118
|
-
lastWasEscape = false;
|
|
123
|
+
if (fragment === '')
|
|
119
124
|
continue;
|
|
120
|
-
}
|
|
121
125
|
if (!textLength(fragment)) {
|
|
126
|
+
// ANSI escape sequence — append untouched. We deliberately do NOT
|
|
127
|
+
// reset prevTextEndedWithWs here, so the next text fragment can
|
|
128
|
+
// still re-introduce a space across the ANSI boundary if needed.
|
|
122
129
|
currentLine += fragment;
|
|
123
|
-
lastWasEscape = true;
|
|
124
130
|
continue;
|
|
125
131
|
}
|
|
132
|
+
// Plain text fragment.
|
|
133
|
+
const startsWithWs = /^[ \t\n]/.test(fragment);
|
|
134
|
+
const endsWithWs = /[ \t\n]$/.test(fragment);
|
|
126
135
|
const words = fragment.split(/[ \t\n]+/);
|
|
136
|
+
let isFirstWordInFragment = true;
|
|
127
137
|
for (const word of words) {
|
|
128
138
|
if (!word)
|
|
129
139
|
continue;
|
|
130
|
-
|
|
140
|
+
// Insert a space before this word when column > 0 AND one of:
|
|
141
|
+
// - it's NOT the first word in this fragment (intra-fragment
|
|
142
|
+
// whitespace existed), OR
|
|
143
|
+
// - this fragment had leading whitespace (e.g. " tool" after a
|
|
144
|
+
// closing ANSI), OR
|
|
145
|
+
// - the previous text fragment ended with whitespace (e.g.
|
|
146
|
+
// "the " before an opening ANSI).
|
|
147
|
+
const addSpace = column !== 0 &&
|
|
148
|
+
(!isFirstWordInFragment || startsWithWs || prevTextEndedWithWs);
|
|
131
149
|
const neededWidth = word.length + (addSpace ? 1 : 0);
|
|
132
150
|
if (column + neededWidth > width && word.length <= width) {
|
|
133
151
|
reflowed.push(currentLine);
|
|
@@ -160,8 +178,9 @@ function reflowText(text, width, gfm) {
|
|
|
160
178
|
currentLine += word;
|
|
161
179
|
column += word.length;
|
|
162
180
|
}
|
|
163
|
-
|
|
181
|
+
isFirstWordInFragment = false;
|
|
164
182
|
}
|
|
183
|
+
prevTextEndedWithWs = endsWithWs;
|
|
165
184
|
}
|
|
166
185
|
if (textLength(currentLine))
|
|
167
186
|
reflowed.push(currentLine);
|
|
@@ -16,6 +16,7 @@ import { sessionManagementTutorial } from './tutorials/projects/session-manageme
|
|
|
16
16
|
import { anchorsTutorial } from './tutorials/projects/anchors.js';
|
|
17
17
|
import { importProjectTutorial } from './tutorials/projects/import-project.js';
|
|
18
18
|
import { appModelTutorial } from './tutorials/projects/app-model.js';
|
|
19
|
+
import { interactiveFlowsTutorial } from './tutorials/projects/interactive-flows.js';
|
|
19
20
|
import { designTutorial } from './tutorials/planning/design.js';
|
|
20
21
|
import { backlogTutorial } from './tutorials/planning/backlog.js';
|
|
21
22
|
import { sketchTutorial } from './tutorials/planning/sketch.js';
|
|
@@ -69,6 +70,7 @@ export function buildTutorialRegistry(s) {
|
|
|
69
70
|
sessionManagementTutorial(s),
|
|
70
71
|
anchorsTutorial(s),
|
|
71
72
|
appModelTutorial(s),
|
|
73
|
+
interactiveFlowsTutorial(s),
|
|
72
74
|
],
|
|
73
75
|
},
|
|
74
76
|
// =========================================================================
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Interactive Flows Tutorial
|
|
3
|
+
*
|
|
4
|
+
* Explains the `build_interactive_flow` agent tool — when an agent uses it,
|
|
5
|
+
* what to expect when the modal opens, and how it differs from `/ask_user`.
|
|
6
|
+
* Desktop-only feature in Phase 1 (CLI degradation lands in Phase 3).
|
|
7
|
+
*/
|
|
8
|
+
import type { TutorialBuilder } from '../../tutorial-types.js';
|
|
9
|
+
export declare const interactiveFlowsTutorial: TutorialBuilder;
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Interactive Flows Tutorial
|
|
3
|
+
*
|
|
4
|
+
* Explains the `build_interactive_flow` agent tool — when an agent uses it,
|
|
5
|
+
* what to expect when the modal opens, and how it differs from `/ask_user`.
|
|
6
|
+
* Desktop-only feature in Phase 1 (CLI degradation lands in Phase 3).
|
|
7
|
+
*/
|
|
8
|
+
export const interactiveFlowsTutorial = (s) => ({
|
|
9
|
+
id: 'interactive-flows',
|
|
10
|
+
title: 'Interactive Flows',
|
|
11
|
+
description: 'Agent-driven decision trees',
|
|
12
|
+
pages: [
|
|
13
|
+
// Page 1: What it is
|
|
14
|
+
{
|
|
15
|
+
title: 'What is an Interactive Flow?',
|
|
16
|
+
lines: [
|
|
17
|
+
'',
|
|
18
|
+
` Sometimes an agent needs to walk you through a ${s.primaryBold('branching decision')}`,
|
|
19
|
+
` — picking a database, choosing a stack, navigating a tradeoff.`,
|
|
20
|
+
'',
|
|
21
|
+
` Instead of asking 5 questions in a row, the agent can build a`,
|
|
22
|
+
` ${s.primary('navigable tree')} you step through with Back/Forward.`,
|
|
23
|
+
'',
|
|
24
|
+
` ${s.secondary('Each step shows up as a modal on the desktop app:')}`,
|
|
25
|
+
'',
|
|
26
|
+
` ${s.muted('•')} Single-choice questions ${s.muted('(pick one)')}`,
|
|
27
|
+
` ${s.muted('•')} Multi-select questions ${s.muted('(pick several)')}`,
|
|
28
|
+
` ${s.muted('•')} Free-text questions ${s.muted('(type your answer)')}`,
|
|
29
|
+
` ${s.muted('•')} Info screens ${s.muted('(read context, click Next)')}`,
|
|
30
|
+
` ${s.muted('•')} A summary at the end recapping your choices`,
|
|
31
|
+
'',
|
|
32
|
+
` ${s.warning('Desktop-only for now.')} CLI rendering arrives later — when the`,
|
|
33
|
+
` agent uses this tool from a CLI session, you'll see a degraded`,
|
|
34
|
+
` text-prompt fallback.`,
|
|
35
|
+
'',
|
|
36
|
+
],
|
|
37
|
+
},
|
|
38
|
+
// Page 2: When agents use it
|
|
39
|
+
{
|
|
40
|
+
title: 'When the Agent Uses This',
|
|
41
|
+
lines: [
|
|
42
|
+
'',
|
|
43
|
+
` Agents pick ${s.primaryBold('build_interactive_flow')} over plain ${s.primary('ask_user')} when:`,
|
|
44
|
+
'',
|
|
45
|
+
` ${s.primary('1.')} The decision has ${s.primaryBold('2+ branching considerations')} —`,
|
|
46
|
+
` "if you pick A, the next question changes"`,
|
|
47
|
+
'',
|
|
48
|
+
` ${s.primary('2.')} You'd benefit from ${s.primaryBold('exploring before committing')} —`,
|
|
49
|
+
` Back/Forward lets you revisit prior steps`,
|
|
50
|
+
'',
|
|
51
|
+
` ${s.primary('3.')} The reasoning ${s.primaryBold('matters as much as the answer')} —`,
|
|
52
|
+
` the agent gets back your full path through the tree, not`,
|
|
53
|
+
` just your final choice`,
|
|
54
|
+
'',
|
|
55
|
+
` ${s.secondary('Typical patterns:')}`,
|
|
56
|
+
'',
|
|
57
|
+
` ${s.muted('•')} Tech stack selection ${s.muted('(database type → vendor → details)')}`,
|
|
58
|
+
` ${s.muted('•')} Architecture trade-offs ${s.muted('(monolith vs microservices)')}`,
|
|
59
|
+
` ${s.muted('•')} Backlog item refinement ${s.muted('(complexity, dependencies, scope)')}`,
|
|
60
|
+
` ${s.muted('•')} Project type selection during ${s.primary('/design')}`,
|
|
61
|
+
'',
|
|
62
|
+
],
|
|
63
|
+
},
|
|
64
|
+
// Page 3: Navigation + result
|
|
65
|
+
{
|
|
66
|
+
title: 'What to Expect',
|
|
67
|
+
lines: [
|
|
68
|
+
'',
|
|
69
|
+
` ${s.secondary('In the modal:')}`,
|
|
70
|
+
'',
|
|
71
|
+
` ${s.primaryBold('Single-choice')} Click an option → auto-advance to next step`,
|
|
72
|
+
` ${s.primaryBold('Multi-select')} Tick boxes → ${s.primary('Next')} button to advance`,
|
|
73
|
+
` ${s.primaryBold('Free text')} Type → ${s.muted('Enter')} (single-line) or`,
|
|
74
|
+
` ${s.muted('Cmd/Ctrl+Enter')} (multi-line) to submit`,
|
|
75
|
+
` ${s.primaryBold('Summary')} Confirm your path, or ${s.primary('Back')} to revise`,
|
|
76
|
+
'',
|
|
77
|
+
` ${s.secondary('Cancel anytime:')}`,
|
|
78
|
+
'',
|
|
79
|
+
` ${s.muted('•')} ${s.primary('Esc')} key`,
|
|
80
|
+
` ${s.muted('•')} ${s.primary('X')} icon in the header`,
|
|
81
|
+
` ${s.muted('•')} Click outside the modal`,
|
|
82
|
+
'',
|
|
83
|
+
` Canceling sends the agent ${s.primaryBold('completed: false')} with your`,
|
|
84
|
+
` partial answers. The agent can resume the same flow or ask`,
|
|
85
|
+
` again with adjustments.`,
|
|
86
|
+
'',
|
|
87
|
+
` ${s.warning('TIP:')} The agent gets your full path back — including any`,
|
|
88
|
+
` nodes you backtracked through. That's intentional: the path is`,
|
|
89
|
+
` ${s.primaryBold('reasoning data')}, not just answer data.`,
|
|
90
|
+
'',
|
|
91
|
+
],
|
|
92
|
+
},
|
|
93
|
+
],
|
|
94
|
+
});
|