ft-scout 9.0.3 → 9.0.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/.firebase/hosting.d2Vi.cache +7 -7
- package/README.md +76 -83
- package/bin/src/commands/agent.d.ts.map +1 -1
- package/bin/src/commands/agent.js +31 -228
- package/bin/src/commands/agent.js.map +1 -1
- package/bin/src/commands/plan.d.ts.map +1 -1
- package/bin/src/commands/plan.js +45 -18
- package/bin/src/commands/plan.js.map +1 -1
- package/bin/src/engine/actionVerifier.d.ts.map +1 -1
- package/bin/src/engine/actionVerifier.js +61 -9
- package/bin/src/engine/actionVerifier.js.map +1 -1
- package/bin/src/engine/agentEngine.d.ts.map +1 -1
- package/bin/src/engine/agentEngine.js +701 -553
- package/bin/src/engine/agentEngine.js.map +1 -1
- package/bin/src/engine/agentState.d.ts.map +1 -1
- package/bin/src/engine/agentState.js +0 -64
- package/bin/src/engine/agentState.js.map +1 -1
- package/bin/src/engine/browser/browserController.d.ts.map +1 -1
- package/bin/src/engine/browser/browserController.js +8 -0
- package/bin/src/engine/browser/browserController.js.map +1 -1
- package/bin/src/engine/computer/computerController.d.ts.map +1 -1
- package/bin/src/engine/computer/computerController.js +686 -240
- package/bin/src/engine/computer/computerController.js.map +1 -1
- package/bin/src/engine/computer/computerDiagnostic.d.ts.map +1 -0
- package/bin/src/engine/computer/computerDiagnostic.js +71 -0
- package/bin/src/engine/computer/computerDiagnostic.js.map +1 -0
- package/bin/src/engine/computer/index.d.ts.map +1 -1
- package/bin/src/engine/computer/index.js +2 -0
- package/bin/src/engine/computer/index.js.map +1 -1
- package/bin/src/engine/computer/mockComputer.d.ts.map +1 -0
- package/bin/src/engine/computer/mockComputer.js +260 -0
- package/bin/src/engine/computer/mockComputer.js.map +1 -0
- package/bin/src/engine/computer/scoutDriver.cs +873 -0
- package/bin/src/engine/computer/scout_driver.exe +0 -0
- package/bin/src/engine/runtime/agentRuntime.d.ts.map +1 -0
- package/bin/src/engine/runtime/agentRuntime.js +1160 -0
- package/bin/src/engine/runtime/agentRuntime.js.map +1 -0
- package/bin/src/engine/runtime/index.d.ts.map +1 -0
- package/bin/src/engine/runtime/index.js +2 -0
- package/bin/src/engine/runtime/index.js.map +1 -0
- package/bin/src/engine/safety.d.ts.map +1 -1
- package/bin/src/engine/safety.js +59 -25
- package/bin/src/engine/safety.js.map +1 -1
- package/bin/src/engine/toolRegistry.d.ts.map +1 -1
- package/bin/src/engine/toolRegistry.js +293 -68
- package/bin/src/engine/toolRegistry.js.map +1 -1
- package/bin/src/engine/voiceEngine.d.ts.map +1 -1
- package/bin/src/engine/voiceEngine.js +0 -1
- package/bin/src/engine/voiceEngine.js.map +1 -1
- package/bin/src/engine/workspace/agentWorkspace.d.ts.map +1 -0
- package/bin/src/engine/workspace/agentWorkspace.js +505 -0
- package/bin/src/engine/workspace/agentWorkspace.js.map +1 -0
- package/bin/src/engine/workspace/index.d.ts.map +1 -0
- package/bin/src/engine/workspace/index.js +2 -0
- package/bin/src/engine/workspace/index.js.map +1 -0
- package/bin/src/index.js +4 -5
- package/bin/src/index.js.map +1 -1
- package/bin/src/server/server.d.ts.map +1 -1
- package/bin/src/server/server.js +25 -4
- package/bin/src/server/server.js.map +1 -1
- package/bin/src/utils/auth.d.ts.map +1 -1
- package/bin/src/utils/auth.js +81 -50
- package/bin/src/utils/auth.js.map +1 -1
- package/bin/src/utils/branding.js +1 -1
- package/bin/src/utils/payment.d.ts.map +1 -1
- package/bin/src/utils/payment.js +15 -1
- package/bin/src/utils/payment.js.map +1 -1
- package/bin/src/utils/pricing.js +1 -1
- package/bin/src/utils/pricing.js.map +1 -1
- package/bin/src/utils/razorpay.d.ts.map +1 -1
- package/bin/src/utils/razorpay.js +10 -2
- package/bin/src/utils/razorpay.js.map +1 -1
- package/downloads/invoice-2026-03.pdf +1 -0
- package/package.json +1 -1
- package/web/app.js +54 -135
- package/web/styles.css +2 -2
- package/bin/src/engine/appControl.d.ts.map +0 -1
- package/bin/src/engine/appControl.js +0 -2413
- package/bin/src/engine/appControl.js.map +0 -1
- package/bin/src/engine/liveScreenEngine.d.ts.map +0 -1
- package/bin/src/engine/liveScreenEngine.js +0 -421
- package/bin/src/engine/liveScreenEngine.js.map +0 -1
- package/bin/src/engine/scripts/winCapture.ps1 +0 -248
- package/downloads/INVOICE_2026_ACME.pdf +0 -1
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import fs from 'fs';
|
|
2
2
|
import path from 'path';
|
|
3
|
-
import readline from 'readline';
|
|
4
3
|
import { spinner, text, isCancel, select, confirm } from '@clack/prompts';
|
|
5
4
|
import chalk from 'chalk';
|
|
6
5
|
import { simpleGit } from 'simple-git';
|
|
@@ -9,12 +8,11 @@ import { loadContext, recordHistoryAction, saveAgentSession, getDirectoryFiles }
|
|
|
9
8
|
import { renderMarkdown, safeNote } from '../utils/markdown.js';
|
|
10
9
|
import { normalizeLanguage } from '../utils/language.js';
|
|
11
10
|
import { createPullRequest } from '../engine/git.js';
|
|
12
|
-
import { consumeCredit, checkTierAccess } from '../utils/auth.js';
|
|
11
|
+
import { consumeCredit, checkTierAccess, loadAuthConfig, isProOrHigher } from '../utils/auth.js';
|
|
13
12
|
import { handleUndo } from './undo.js';
|
|
14
13
|
import { AgentExecutionLoop, buildDirectoryTree, AGENT_TOOLS } from '../engine/agentEngine.js';
|
|
15
14
|
import { verifyAndSelfHealFiles, executeSmartCommand, runProjectVerification } from '../engine/verifier.js';
|
|
16
15
|
import { speakText, listenSpeechToText, promptInteractionMode } from '../engine/voiceEngine.js';
|
|
17
|
-
import { startLiveScreenShare, stopLiveScreenShare, isLiveScreenShareActive } from '../engine/liveScreenEngine.js';
|
|
18
16
|
import { exec } from 'child_process';
|
|
19
17
|
import { promisify } from 'util';
|
|
20
18
|
const execAsync = promisify(exec);
|
|
@@ -98,13 +96,6 @@ export function parseUserPromptIntent(rawGoal, filesList) {
|
|
|
98
96
|
if (!cleaned)
|
|
99
97
|
cleaned = rawGoal.trim();
|
|
100
98
|
const lowerCleaned = cleaned.toLowerCase();
|
|
101
|
-
const isAppControl = /\b(?:open|launch|take\s*over|takeover|control|switch\s+to|click|type|send\s+keys|scratchpad|desktop|keystroke|interact\s+with|automate)\s+(?:the\s+)?(?:app|apps|browser|chrome|edge|firefox|brave|safari|terminal|cmd|powershell|vscode|code|editor|notepad|desktop|window|screen|cursor|mouse|site|website|url|tab|page|maps|youtube|instagram|whatsapp|twitter|google)\b/i.test(lowerCleaned) ||
|
|
102
|
-
/\b(?:scratchpad|desktop\s+automation|click_app|type_text|send_keys|takeover|take\s*over|mouse_cursor|mouse\s+cursor|screen\s+takeover|take\s+over\s+(?:the\s+)?screen)\b/i.test(lowerCleaned) ||
|
|
103
|
-
/^(?:take\s*over|takeover)\b/i.test(lowerCleaned) ||
|
|
104
|
-
/^(?:open|launch)\s+https?:\/\//i.test(lowerCleaned) ||
|
|
105
|
-
/\b(?:open|launch)\s+(?:browser|chrome|edge|firefox|brave|maps|google|youtube|notepad|calc|terminal)\b/i.test(lowerCleaned);
|
|
106
|
-
if (isAppControl)
|
|
107
|
-
return { cleanGoal: cleaned, intentType: 'app' };
|
|
108
99
|
let targetFiles = extractCreateTargetFiles(cleaned);
|
|
109
100
|
if (targetFiles.length === 0) {
|
|
110
101
|
targetFiles = extractCreateTargetFiles(rawGoal);
|
|
@@ -239,173 +230,10 @@ export function findTargetFilesFromPrompt(userPrompt, specifiedFile, filesList)
|
|
|
239
230
|
return [];
|
|
240
231
|
}
|
|
241
232
|
export async function getAgentGoalInput(placeholderStr) {
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
validate: (val) => (!val || !val.trim() ? 'Please enter a prompt or /exit to quit' : undefined),
|
|
247
|
-
});
|
|
248
|
-
}
|
|
249
|
-
return new Promise((resolve) => {
|
|
250
|
-
let buffer = '';
|
|
251
|
-
let cursorIndex = 0;
|
|
252
|
-
let isDone = false;
|
|
253
|
-
const rl = readline.createInterface({
|
|
254
|
-
input: process.stdin,
|
|
255
|
-
output: undefined,
|
|
256
|
-
});
|
|
257
|
-
readline.emitKeypressEvents(process.stdin, rl);
|
|
258
|
-
if (process.stdin.setRawMode) {
|
|
259
|
-
process.stdin.setRawMode(true);
|
|
260
|
-
}
|
|
261
|
-
const prefix = `${chalk.cyan('│')} `;
|
|
262
|
-
const prefixVisibleLen = 3;
|
|
263
|
-
process.stdout.write(`\n${chalk.cyan('◇')} ${chalk.bold('Agent Prompt:')}\n${prefix}`);
|
|
264
|
-
const renderLine = () => {
|
|
265
|
-
readline.cursorTo(process.stdout, 0);
|
|
266
|
-
readline.clearLine(process.stdout, 0);
|
|
267
|
-
process.stdout.write(prefix + buffer);
|
|
268
|
-
readline.cursorTo(process.stdout, prefixVisibleLen + cursorIndex);
|
|
269
|
-
};
|
|
270
|
-
const cleanup = () => {
|
|
271
|
-
process.stdin.removeListener('keypress', onKeypress);
|
|
272
|
-
if (process.stdin.setRawMode) {
|
|
273
|
-
process.stdin.setRawMode(false);
|
|
274
|
-
}
|
|
275
|
-
rl.close();
|
|
276
|
-
};
|
|
277
|
-
const onKeypress = (str, key) => {
|
|
278
|
-
if (isDone)
|
|
279
|
-
return;
|
|
280
|
-
const isCtrlC = str === '\u0003' || (key && key.ctrl && key.name === 'c');
|
|
281
|
-
if (isCtrlC) {
|
|
282
|
-
isDone = true;
|
|
283
|
-
cleanup();
|
|
284
|
-
process.stdout.write('\n');
|
|
285
|
-
resolve(Symbol.for('clack:cancel'));
|
|
286
|
-
return;
|
|
287
|
-
}
|
|
288
|
-
// Immediately catch '/' keypress as the very first typed character without requiring Enter!
|
|
289
|
-
if (buffer.length === 0 && str === '/') {
|
|
290
|
-
isDone = true;
|
|
291
|
-
cleanup();
|
|
292
|
-
readline.cursorTo(process.stdout, 0);
|
|
293
|
-
readline.clearLine(process.stdout, 0);
|
|
294
|
-
process.stdout.write(`${prefix}/\n`);
|
|
295
|
-
resolve('/');
|
|
296
|
-
return;
|
|
297
|
-
}
|
|
298
|
-
const isEnter = key && (key.name === 'return' || key.name === 'enter');
|
|
299
|
-
if (isEnter) {
|
|
300
|
-
isDone = true;
|
|
301
|
-
cleanup();
|
|
302
|
-
process.stdout.write('\n');
|
|
303
|
-
resolve(buffer.trim());
|
|
304
|
-
return;
|
|
305
|
-
}
|
|
306
|
-
// Left Arrow Navigation
|
|
307
|
-
if (key && key.name === 'left') {
|
|
308
|
-
if (key.ctrl || key.meta) {
|
|
309
|
-
let newPos = cursorIndex;
|
|
310
|
-
while (newPos > 0 && buffer[newPos - 1] === ' ')
|
|
311
|
-
newPos--;
|
|
312
|
-
while (newPos > 0 && buffer[newPos - 1] !== ' ')
|
|
313
|
-
newPos--;
|
|
314
|
-
cursorIndex = newPos;
|
|
315
|
-
}
|
|
316
|
-
else if (cursorIndex > 0) {
|
|
317
|
-
cursorIndex--;
|
|
318
|
-
}
|
|
319
|
-
renderLine();
|
|
320
|
-
return;
|
|
321
|
-
}
|
|
322
|
-
// Right Arrow Navigation
|
|
323
|
-
if (key && key.name === 'right') {
|
|
324
|
-
if (key.ctrl || key.meta) {
|
|
325
|
-
let newPos = cursorIndex;
|
|
326
|
-
while (newPos < buffer.length && buffer[newPos] === ' ')
|
|
327
|
-
newPos++;
|
|
328
|
-
while (newPos < buffer.length && buffer[newPos] !== ' ')
|
|
329
|
-
newPos++;
|
|
330
|
-
cursorIndex = newPos;
|
|
331
|
-
}
|
|
332
|
-
else if (cursorIndex < buffer.length) {
|
|
333
|
-
cursorIndex++;
|
|
334
|
-
}
|
|
335
|
-
renderLine();
|
|
336
|
-
return;
|
|
337
|
-
}
|
|
338
|
-
// Home / Ctrl+A
|
|
339
|
-
if ((key && key.name === 'home') || (key && key.ctrl && key.name === 'a')) {
|
|
340
|
-
cursorIndex = 0;
|
|
341
|
-
renderLine();
|
|
342
|
-
return;
|
|
343
|
-
}
|
|
344
|
-
// End / Ctrl+E
|
|
345
|
-
if ((key && key.name === 'end') || (key && key.ctrl && key.name === 'e')) {
|
|
346
|
-
cursorIndex = buffer.length;
|
|
347
|
-
renderLine();
|
|
348
|
-
return;
|
|
349
|
-
}
|
|
350
|
-
// Up / Down arrow keys (ignore to prevent terminal escape sequences from polluting buffer)
|
|
351
|
-
if (key && (key.name === 'up' || key.name === 'down')) {
|
|
352
|
-
return;
|
|
353
|
-
}
|
|
354
|
-
// Clear to start (Ctrl+U)
|
|
355
|
-
if (key && key.ctrl && key.name === 'u') {
|
|
356
|
-
buffer = buffer.slice(cursorIndex);
|
|
357
|
-
cursorIndex = 0;
|
|
358
|
-
renderLine();
|
|
359
|
-
return;
|
|
360
|
-
}
|
|
361
|
-
// Clear to end (Ctrl+K)
|
|
362
|
-
if (key && key.ctrl && key.name === 'k') {
|
|
363
|
-
buffer = buffer.slice(0, cursorIndex);
|
|
364
|
-
renderLine();
|
|
365
|
-
return;
|
|
366
|
-
}
|
|
367
|
-
// Delete word left (Ctrl+W)
|
|
368
|
-
if (key && key.ctrl && key.name === 'w') {
|
|
369
|
-
let newPos = cursorIndex;
|
|
370
|
-
while (newPos > 0 && buffer[newPos - 1] === ' ')
|
|
371
|
-
newPos--;
|
|
372
|
-
while (newPos > 0 && buffer[newPos - 1] !== ' ')
|
|
373
|
-
newPos--;
|
|
374
|
-
buffer = buffer.slice(0, newPos) + buffer.slice(cursorIndex);
|
|
375
|
-
cursorIndex = newPos;
|
|
376
|
-
renderLine();
|
|
377
|
-
return;
|
|
378
|
-
}
|
|
379
|
-
// Backspace
|
|
380
|
-
const isBackspace = (key && key.name === 'backspace') || str === '\b' || str === '\x7f';
|
|
381
|
-
if (isBackspace) {
|
|
382
|
-
if (cursorIndex > 0) {
|
|
383
|
-
buffer = buffer.slice(0, cursorIndex - 1) + buffer.slice(cursorIndex);
|
|
384
|
-
cursorIndex--;
|
|
385
|
-
renderLine();
|
|
386
|
-
}
|
|
387
|
-
return;
|
|
388
|
-
}
|
|
389
|
-
// Delete (Forward delete)
|
|
390
|
-
if (key && key.name === 'delete') {
|
|
391
|
-
if (cursorIndex < buffer.length) {
|
|
392
|
-
buffer = buffer.slice(0, cursorIndex) + buffer.slice(cursorIndex + 1);
|
|
393
|
-
renderLine();
|
|
394
|
-
}
|
|
395
|
-
return;
|
|
396
|
-
}
|
|
397
|
-
// Regular character insertion
|
|
398
|
-
if (str && !key?.ctrl && !key?.meta && key?.name !== 'escape' && !isEnter && !isBackspace) {
|
|
399
|
-
const cleanStr = str.replace(/[\r\n]/g, '');
|
|
400
|
-
if (cleanStr.length > 0) {
|
|
401
|
-
buffer = buffer.slice(0, cursorIndex) + cleanStr + buffer.slice(cursorIndex);
|
|
402
|
-
cursorIndex += cleanStr.length;
|
|
403
|
-
renderLine();
|
|
404
|
-
}
|
|
405
|
-
return;
|
|
406
|
-
}
|
|
407
|
-
};
|
|
408
|
-
process.stdin.on('keypress', onKeypress);
|
|
233
|
+
return await text({
|
|
234
|
+
message: chalk.bold('Agent Prompt:'),
|
|
235
|
+
placeholder: placeholderStr,
|
|
236
|
+
validate: (val) => (!val || !val.trim() ? 'Please enter a prompt or /exit to quit' : undefined),
|
|
409
237
|
});
|
|
410
238
|
}
|
|
411
239
|
export async function handleAgent(goalInput, options) {
|
|
@@ -449,21 +277,18 @@ export async function handleAgent(goalInput, options) {
|
|
|
449
277
|
let initialGoal = goalInput || options?.goal;
|
|
450
278
|
let isFirstRun = true;
|
|
451
279
|
let isAudioMode = options?.voice;
|
|
452
|
-
|
|
453
|
-
if (isAudioMode === undefined && isScreenShareMode === undefined && !initialGoal && process.stdout.isTTY) {
|
|
280
|
+
if (isAudioMode === undefined && !initialGoal && process.stdout.isTTY) {
|
|
454
281
|
const selectedMode = await promptInteractionMode();
|
|
455
282
|
isAudioMode = selectedMode === 'audio';
|
|
456
|
-
isScreenShareMode = selectedMode === 'screen_share';
|
|
457
|
-
}
|
|
458
|
-
if (isScreenShareMode) {
|
|
459
|
-
await startLiveScreenShare();
|
|
460
283
|
}
|
|
284
|
+
const authCfg = loadAuthConfig();
|
|
285
|
+
const userTier = (authCfg.currentTier || 'free').toLowerCase();
|
|
286
|
+
const isPro = isProOrHigher(userTier);
|
|
461
287
|
const agentLoop = new AgentExecutionLoop({
|
|
462
288
|
autoApprove: options?.yes,
|
|
463
289
|
maxSteps: options?.steps || options?.maxSteps || 30,
|
|
464
290
|
language: targetLang,
|
|
465
|
-
|
|
466
|
-
screenShare: isScreenShareMode,
|
|
291
|
+
tier: userTier,
|
|
467
292
|
});
|
|
468
293
|
if (options?.resume) {
|
|
469
294
|
const loaded = agentLoop.getStateManager().loadTaskState(options.resume);
|
|
@@ -480,14 +305,17 @@ export async function handleAgent(goalInput, options) {
|
|
|
480
305
|
}
|
|
481
306
|
const modelInfo = getActiveModelInfo();
|
|
482
307
|
const fallbackPipeline = modelInfo.fallbackChain.slice(1).join(' ➔ ');
|
|
308
|
+
const tierBadge = isPro
|
|
309
|
+
? chalk.bold.magenta(`[Plan: ${userTier.toUpperCase()} - Autonomous & Scratchpad Enabled]`)
|
|
310
|
+
: chalk.bold.yellow(`[Plan: FREE - Basic Dev Ops (Edit/Create/Run)]`);
|
|
483
311
|
const welcomeBanner = `
|
|
484
|
-
${chalk.bold.cyan('Scout Autonomous AI Agent')} ${targetLang ? `(${targetLang})` : ''} [${
|
|
312
|
+
${chalk.bold.cyan('Scout Autonomous AI Agent')} ${targetLang ? `(${targetLang})` : ''} [${isAudioMode ? '🎤 Audio Mode' : '📝 Text Mode'}] ${tierBadge}
|
|
485
313
|
${chalk.bold('Active Model:')} ${chalk.bold.green(modelInfo.currentActiveModel)}
|
|
314
|
+
${chalk.bold('Capabilities:')} ${isPro ? chalk.green('Autonomous Computer/Browser Control + AI Scratchpad Working Memory') : chalk.dim('Basic Dev Ops (Code editing, creating files/folders, running commands - Max 5 steps)')}
|
|
486
315
|
${chalk.bold('Fallback Pipeline:')} ${chalk.dim(fallbackPipeline)}
|
|
487
316
|
|
|
488
317
|
${chalk.dim('Type your goal, or use slash commands:')}
|
|
489
318
|
${chalk.cyan('/help')} - Show agent tools & commands (${AGENT_TOOLS.length} tools)
|
|
490
|
-
${chalk.cyan('/screenshare')} - Toggle real-time live screen share stream with model
|
|
491
319
|
${chalk.cyan('/tree')} - View workspace directory tree
|
|
492
320
|
${chalk.cyan('/stats')} - View real-time session & model telemetry
|
|
493
321
|
${chalk.cyan('/test')} - Run automated project test suite
|
|
@@ -532,8 +360,8 @@ ${chalk.cyan('/exit')} - Exit session
|
|
|
532
360
|
const KNOWN_SLASH_COMMANDS = [
|
|
533
361
|
'/help', '/tree', '/status', '/stats', '/test', '/explain',
|
|
534
362
|
'/export', '/save-session', '/diff', '/clear', '/compact',
|
|
535
|
-
'/undo', '/history', '/scan', '/plan', '/
|
|
536
|
-
'/
|
|
363
|
+
'/undo', '/history', '/scan', '/plan', '/tasks', '/resume', '/voice', '/speak',
|
|
364
|
+
'/exit', '/quit'
|
|
537
365
|
];
|
|
538
366
|
if (trimmedInput.startsWith('/')) {
|
|
539
367
|
const cmdName = trimmedInput.split(/\s+/)[0].toLowerCase();
|
|
@@ -543,8 +371,6 @@ ${chalk.cyan('/exit')} - Exit session
|
|
|
543
371
|
{ value: '/help', label: '/help', hint: 'Show agent tools & commands guide' },
|
|
544
372
|
{ value: '/tasks', label: '/tasks', hint: 'List saved autonomous tasks in .ft/tasks/' },
|
|
545
373
|
{ value: '/resume', label: '/resume', hint: 'Resume saved autonomous task by task ID' },
|
|
546
|
-
{ value: '/scratchpad', label: '/scratchpad', hint: 'View current agent working memory & plan (.ft/scratchpad.md)' },
|
|
547
|
-
{ value: '/screenshare', label: '/screenshare', hint: 'Toggle real-time live screen share stream with model' },
|
|
548
374
|
{ value: '/voice', label: '/voice', hint: 'Activate microphone STT speech input' },
|
|
549
375
|
{ value: '/speak', label: '/speak', hint: 'Speak text out loud via TTS' },
|
|
550
376
|
{ value: '/tree', label: '/tree', hint: 'Display workspace directory tree' },
|
|
@@ -621,24 +447,28 @@ ${chalk.cyan('/exit')} - Exit session
|
|
|
621
447
|
}
|
|
622
448
|
if (trimmedInput.toLowerCase() === '/help') {
|
|
623
449
|
const helpText = `
|
|
624
|
-
### 🛠️
|
|
450
|
+
### 🛠️ Basic Developer Tools (Available on All Plans)
|
|
625
451
|
- **read_file**: Read content & line ranges of workspace files.
|
|
626
|
-
- **write_file**: Create new files
|
|
452
|
+
- **write_file**: Create new files and directories.
|
|
627
453
|
- **edit_file**: Search & replace exact target code snippets.
|
|
628
454
|
- **multi_edit_file**: Apply batch snippet replacements in a single step.
|
|
629
|
-
- **run_command**: Execute
|
|
455
|
+
- **run_command**: Execute terminal commands (\`npm test\`, \`npm run build\`).
|
|
630
456
|
- **tree_view**: Generate visual ASCII directory tree structures.
|
|
631
457
|
- **file_info**: Get file statistics, size, lines, & modification time.
|
|
632
458
|
- **grep_search**: String/regex pattern search across codebase.
|
|
633
459
|
- **glob_search**: Filter workspace files by file pattern.
|
|
634
|
-
- **fetch_url**: Fetch web API documentation or URL content.
|
|
635
460
|
- **git_diff**: Retrieve uncommitted workspace git diff.
|
|
636
461
|
- **ask_user**: Request missing secret credentials or API keys.
|
|
637
|
-
- **task_completed**: Conclude
|
|
462
|
+
- **task_completed**: Conclude task execution with teardown summary.
|
|
463
|
+
|
|
464
|
+
### ⚡ Pro & Enterprise Exclusive Features
|
|
465
|
+
- **scratchpad**: Persistent working memory & reasoning scratchpad for multi-phase tasks.
|
|
466
|
+
- **computer_***: Autonomous desktop & GUI app control (screenshot, click, type, open app).
|
|
467
|
+
- **browser_***: Autonomous browser automation (navigate, scrape, interact).
|
|
468
|
+
- **Autonomous Loops**: Extended multi-step execution loops (30+ steps).
|
|
638
469
|
|
|
639
470
|
### 🚀 Interactive Slash Commands
|
|
640
471
|
- \`/help\`: Show this tools & commands guide.
|
|
641
|
-
- \`/screenshare\` or \`/live\`: Toggle real-time live screen share stream with model.
|
|
642
472
|
- \`/tree [dir]\`: Display workspace directory tree structure.
|
|
643
473
|
- \`/status\` or \`/stats\`: Show session telemetry & statistics.
|
|
644
474
|
- \`/test [cmd]\`: Run project verification test suite.
|
|
@@ -649,7 +479,6 @@ ${chalk.cyan('/exit')} - Exit session
|
|
|
649
479
|
- \`/undo\`: Revert last file modifications.
|
|
650
480
|
- \`/history\`: View recent Scout action logs.
|
|
651
481
|
- \`/plan\`: Generate implementation roadmap.
|
|
652
|
-
- \`/scratchpad\`: View current working memory plan & checklist (\`.ft/scratchpad.md\`).
|
|
653
482
|
- \`/voice\`: Speak goal into microphone (STT).
|
|
654
483
|
- \`/speak <text>\`: Speak text out loud (TTS).
|
|
655
484
|
- \`/exit\`: End Scout Agent session.
|
|
@@ -657,19 +486,6 @@ ${chalk.cyan('/exit')} - Exit session
|
|
|
657
486
|
safeNote(renderMarkdown(helpText), ' Scout Slash Commands & Tools');
|
|
658
487
|
continue;
|
|
659
488
|
}
|
|
660
|
-
if (trimmedInput.toLowerCase() === '/screenshare' || trimmedInput.toLowerCase() === '/livescreen' || trimmedInput.toLowerCase() === '/live') {
|
|
661
|
-
if (isLiveScreenShareActive()) {
|
|
662
|
-
const stopRes = stopLiveScreenShare();
|
|
663
|
-
isScreenShareMode = false;
|
|
664
|
-
safeNote(chalk.yellow(stopRes.summary), ' Live Screen Share Stopped');
|
|
665
|
-
}
|
|
666
|
-
else {
|
|
667
|
-
const startRes = await startLiveScreenShare();
|
|
668
|
-
isScreenShareMode = true;
|
|
669
|
-
safeNote(chalk.green(startRes.message), ' Live Screen Share Active');
|
|
670
|
-
}
|
|
671
|
-
continue;
|
|
672
|
-
}
|
|
673
489
|
if (trimmedInput.toLowerCase().startsWith('/speak')) {
|
|
674
490
|
const phrase = trimmedInput.slice(6).trim();
|
|
675
491
|
if (phrase) {
|
|
@@ -700,17 +516,6 @@ ${chalk.cyan('/exit')} - Exit session
|
|
|
700
516
|
continue;
|
|
701
517
|
}
|
|
702
518
|
}
|
|
703
|
-
if (trimmedInput.toLowerCase() === '/scratchpad') {
|
|
704
|
-
const scratchpadPath = path.join(process.cwd(), '.ft', 'scratchpad.md');
|
|
705
|
-
if (fs.existsSync(scratchpadPath)) {
|
|
706
|
-
const content = fs.readFileSync(scratchpadPath, 'utf-8');
|
|
707
|
-
safeNote(renderMarkdown(content), ' Active Agent Scratchpad (.ft/scratchpad.md)');
|
|
708
|
-
}
|
|
709
|
-
else {
|
|
710
|
-
safeNote('No active scratchpad found (.ft/scratchpad.md). The agent will create one during multi-step goal execution.', ' Agent Scratchpad');
|
|
711
|
-
}
|
|
712
|
-
continue;
|
|
713
|
-
}
|
|
714
519
|
if (trimmedInput.toLowerCase() === '/tasks') {
|
|
715
520
|
const tasks = agentLoop.getStateManager().listSavedTasks();
|
|
716
521
|
if (tasks.length === 0) {
|
|
@@ -1242,12 +1047,10 @@ ${filePreviews}
|
|
|
1242
1047
|
}
|
|
1243
1048
|
// Standard Agent Goal Execution: Pre-scan & identify target files
|
|
1244
1049
|
let targetFiles = [];
|
|
1245
|
-
|
|
1246
|
-
|
|
1247
|
-
|
|
1248
|
-
|
|
1249
|
-
idSpinner.stop(targetFiles.length > 0 ? `Target files resolved: ${targetFiles.map(f => `\`${f}\``).join(', ')}` : 'Analysis complete.');
|
|
1250
|
-
}
|
|
1050
|
+
const idSpinner = spinner();
|
|
1051
|
+
idSpinner.start('Scout Agent: Thinking');
|
|
1052
|
+
targetFiles = await identifyTargetFiles(finalGoal, projectName, filesList, targetLang, options?.native);
|
|
1053
|
+
idSpinner.stop(targetFiles.length > 0 ? `Target files resolved: ${targetFiles.map(f => `\`${f}\``).join(', ')}` : 'Analysis complete.');
|
|
1251
1054
|
safeNote(`${chalk.bold.cyan(' Scout Autonomous Execution Initialized')}\n` +
|
|
1252
1055
|
`${chalk.dim('Goal:')} ${finalGoal}` +
|
|
1253
1056
|
(targetFiles.length > 0 ? `\n${chalk.dim('Target Files:')} ${targetFiles.map(f => `\`${f}\``).join(', ')}` : ''), ' Scout Agent Execution');
|