@compilr-dev/cli 0.7.4 → 0.7.6
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/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 +2 -2
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);
|
|
@@ -88,24 +88,30 @@ export const newProjectTutorial = (s) => ({
|
|
|
88
88
|
'',
|
|
89
89
|
],
|
|
90
90
|
},
|
|
91
|
-
// Page 5:
|
|
91
|
+
// Page 5: Project Type [3/8]
|
|
92
92
|
{
|
|
93
|
-
title: '
|
|
93
|
+
title: 'Project Type',
|
|
94
94
|
lines: [
|
|
95
95
|
'',
|
|
96
96
|
` ${s.primaryBold('Initialize New Project')} ${s.muted('[3/8]')}`,
|
|
97
97
|
'',
|
|
98
|
-
` ${s.primary('
|
|
98
|
+
` ${s.primary('What kind of project are you starting?')}`,
|
|
99
99
|
'',
|
|
100
|
-
` ${s.primary('>')}
|
|
101
|
-
`
|
|
102
|
-
''
|
|
103
|
-
`
|
|
104
|
-
`
|
|
100
|
+
` ${s.primary('>')} Software Development ${s.muted('Web apps, APIs, CLIs, libraries')}`,
|
|
101
|
+
` General Purpose ${s.muted('Blank workspace — define your own')}`,
|
|
102
|
+
` Research Paper ${s.muted('Academic / analytical document')}`,
|
|
103
|
+
` Content & Marketing ${s.muted('Blog posts, social copy, content')}`,
|
|
104
|
+
` Technical Documentation ${s.muted('API docs, user guides, tutorials')}`,
|
|
105
|
+
` Book ${s.muted('Long-form writing, fiction / nonfic')}`,
|
|
106
|
+
` Business Plan ${s.muted('Vision, market, financials, pitch')}`,
|
|
107
|
+
` Course ${s.muted('Curriculum, modules, lessons')}`,
|
|
105
108
|
'',
|
|
106
109
|
` ${s.muted('Up/Down Navigate | Enter Select | Esc Back')}`,
|
|
107
110
|
'',
|
|
108
|
-
` ${s.warning('TIP:')}
|
|
111
|
+
` ${s.warning('TIP:')} Picking a type tailors the wizard. Software types ask about`,
|
|
112
|
+
` tech stack + coding standards; non-software types skip those`,
|
|
113
|
+
` steps. The type also drives the team-roster suggestion two`,
|
|
114
|
+
` steps from now.`,
|
|
109
115
|
'',
|
|
110
116
|
],
|
|
111
117
|
},
|
|
@@ -178,24 +184,50 @@ export const newProjectTutorial = (s) => ({
|
|
|
178
184
|
'',
|
|
179
185
|
],
|
|
180
186
|
},
|
|
181
|
-
// Page 9:
|
|
187
|
+
// Page 9: Team Roster [7/8]
|
|
182
188
|
{
|
|
183
|
-
title: '
|
|
189
|
+
title: 'Team Roster',
|
|
184
190
|
lines: [
|
|
185
191
|
'',
|
|
186
192
|
` ${s.primaryBold('Initialize New Project')} ${s.muted('[7/8]')}`,
|
|
187
193
|
'',
|
|
188
|
-
` ${s.primary('
|
|
194
|
+
` ${s.primary('Team roster')}`,
|
|
189
195
|
'',
|
|
190
|
-
` ${s.
|
|
191
|
-
` 2. Guided (structured step-by-step workflow)`,
|
|
196
|
+
` ${s.muted('Software Development suggests these specialists:')}`,
|
|
192
197
|
'',
|
|
193
|
-
`
|
|
194
|
-
`
|
|
198
|
+
` ${s.muted('[▲_▲] Developer Writes and debugs code')}`,
|
|
199
|
+
` ${s.muted('[◈_◈] Architect System design')}`,
|
|
200
|
+
` ${s.muted('[◉_◉] QA Testing and quality')}`,
|
|
201
|
+
` ${s.muted('[▣_▣] PM Project planning')}`,
|
|
195
202
|
'',
|
|
196
|
-
` ${s.
|
|
203
|
+
` ${s.primary('How should we set up the team?')}`,
|
|
204
|
+
'',
|
|
205
|
+
` ${s.primary('>')} Add all suggested (4) ${s.muted('← recommended')}`,
|
|
206
|
+
` Customize selection`,
|
|
207
|
+
` Skip — start with just $default`,
|
|
208
|
+
'',
|
|
209
|
+
` ${s.muted('Up/Down Navigate | Enter Confirm | Esc Back')}`,
|
|
210
|
+
'',
|
|
211
|
+
` ${s.secondary('Three options:')}`,
|
|
197
212
|
'',
|
|
198
|
-
` ${s.
|
|
213
|
+
` ${s.primary('1.')} ${s.primaryBold('Add all suggested')} (default)`,
|
|
214
|
+
` Specialists are spawned automatically when the project is created.`,
|
|
215
|
+
` A chat with each agent is ready as soon as you finish.`,
|
|
216
|
+
'',
|
|
217
|
+
` ${s.primary('2.')} ${s.primaryBold('Customize selection')}`,
|
|
218
|
+
` Opens a checklist of the suggested agents. Use ${s.primary('Space')} to`,
|
|
219
|
+
` toggle each one on/off. ${s.primary('Enter')} when done. You can still`,
|
|
220
|
+
` run ${s.primary('/team add <role>')} later for roles outside the suggestion.`,
|
|
221
|
+
'',
|
|
222
|
+
` ${s.primary('3.')} ${s.primaryBold('Skip')}`,
|
|
223
|
+
` The project starts with only ${s.primary('$default')}. Useful for very`,
|
|
224
|
+
` small projects or when you prefer to add agents one at a time.`,
|
|
225
|
+
'',
|
|
226
|
+
` For project types with no default team (like General Purpose), this`,
|
|
227
|
+
` step is skipped automatically.`,
|
|
228
|
+
'',
|
|
229
|
+
` ${s.warning('TIP:')} If you accidentally skip and want the team back, run`,
|
|
230
|
+
` ${s.primary('/team add')} for each role you want.`,
|
|
199
231
|
'',
|
|
200
232
|
],
|
|
201
233
|
},
|
|
@@ -209,13 +241,13 @@ export const newProjectTutorial = (s) => ({
|
|
|
209
241
|
` ${s.primary('Ready to create project?')}`,
|
|
210
242
|
'',
|
|
211
243
|
` Project: ${s.primary('my-first-project')}`,
|
|
244
|
+
` Type: ${s.primary('Software Development')}`,
|
|
212
245
|
` Location: ${s.primary('./my-first-project/')}`,
|
|
213
|
-
` Structure: ${s.primary('Single repo')}`,
|
|
214
246
|
` Tech: ${s.primary('React + Node.js + PostgreSQL')}`,
|
|
215
247
|
` Standards: ${s.primary('TypeScript Strict (recommended)')}`,
|
|
216
248
|
` Git: ${s.primary('Yes')}`,
|
|
217
249
|
` Remote: ${s.primary('https://github.com/user/my-first-project')}`,
|
|
218
|
-
`
|
|
250
|
+
` Team: ${s.primary('4 specialists')} ${s.muted('($dev, $arch, $qa, $pm)')}`,
|
|
219
251
|
'',
|
|
220
252
|
` ${s.primary('>')} Create`,
|
|
221
253
|
` Cancel`,
|
|
@@ -243,6 +275,10 @@ export const newProjectTutorial = (s) => ({
|
|
|
243
275
|
` ${s.success('✓')} ${s.primary('Git repository')} with initial commit`,
|
|
244
276
|
` ${s.muted('Remote configured if you provided a URL')}`,
|
|
245
277
|
'',
|
|
278
|
+
` ${s.success('✓')} ${s.primary('Team specialists')} added to the project's team`,
|
|
279
|
+
` ${s.muted('Based on the type you picked + roster option chosen')}`,
|
|
280
|
+
` ${s.muted('Run /team to see them')}`,
|
|
281
|
+
'',
|
|
246
282
|
` You'll return to the Dashboard with your new project selected.`,
|
|
247
283
|
'',
|
|
248
284
|
],
|