diff --git a/apps/cli/src/commands/show.command.ts b/apps/cli/src/commands/show.command.ts index d9bace90..14ebbba1 100644 --- a/apps/cli/src/commands/show.command.ts +++ b/apps/cli/src/commands/show.command.ts @@ -9,6 +9,14 @@ import boxen from 'boxen'; import { createTaskMasterCore, type Task, type TaskMasterCore } from '@tm/core'; import type { StorageType } from '@tm/core/types'; import * as ui from '../utils/ui.js'; +import { + displayTaskHeader, + displayTaskProperties, + displayImplementationDetails, + displayTestStrategy, + displaySubtasks, + displaySuggestedActions +} from '../ui/components/task-detail.component.js'; /** * Options interface for the show command @@ -258,46 +266,26 @@ export class ShowCommand extends Command { const task = result.task; - // Header - console.log( - boxen(chalk.white.bold(`Task #${task.id} - ${task.title}`), { - padding: { top: 0, bottom: 0, left: 1, right: 1 }, - borderColor: 'blue', - borderStyle: 'round', - margin: { top: 1 } - }) - ); + // Display header with tag + displayTaskHeader(task.id, task.title); - // Task details - console.log( - `\n${chalk.blue.bold('Status:')} ${ui.getStatusWithColor(task.status)}` - ); - console.log( - `${chalk.blue.bold('Priority:')} ${ui.getPriorityWithColor(task.priority)}` - ); - - if (task.description) { - console.log(`\n${chalk.blue.bold('Description:')}`); - console.log(task.description); - } + // Display task properties in table format + displayTaskProperties(task); + // Display implementation details if available if (task.details) { - console.log(`\n${chalk.blue.bold('Details:')}`); - console.log(task.details); + console.log(); // Empty line for spacing + displayImplementationDetails(task.details); } - // Dependencies - if (task.dependencies && task.dependencies.length > 0) { - console.log(`\n${chalk.blue.bold('Dependencies:')}`); - task.dependencies.forEach((dep) => { - console.log(` - ${chalk.cyan(dep)}`); - }); + // Display test strategy if available + if ('testStrategy' in task && task.testStrategy) { + console.log(); // Empty line for spacing + displayTestStrategy(task.testStrategy as string); } - // Subtasks + // Display subtasks if available if (task.subtasks && task.subtasks.length > 0) { - console.log(`\n${chalk.blue.bold('Subtasks:')}`); - // Filter subtasks by status if provided const filteredSubtasks = options.status ? task.subtasks.filter((sub) => sub.status === options.status) @@ -308,23 +296,12 @@ export class ShowCommand extends Command { chalk.gray(` No subtasks with status '${options.status}'`) ); } else { - filteredSubtasks.forEach((subtask) => { - console.log( - ` ${chalk.cyan(`${task.id}.${subtask.id}`)} ${ui.getStatusWithColor(subtask.status)} ${subtask.title}` - ); - if (subtask.description) { - console.log(` ${chalk.gray(subtask.description)}`); - } - }); + displaySubtasks(filteredSubtasks, task.id); } } - if (task.testStrategy) { - console.log(`\n${chalk.blue.bold('Test Strategy:')}`); - console.log(task.testStrategy); - } - - console.log(`\n${chalk.gray('Storage: ' + result.storageType)}`); + // Display suggested actions + displaySuggestedActions(task.id); } /** diff --git a/apps/cli/src/ui/components/index.ts b/apps/cli/src/ui/components/index.ts index 268a96a1..b5efbcda 100644 --- a/apps/cli/src/ui/components/index.ts +++ b/apps/cli/src/ui/components/index.ts @@ -5,4 +5,5 @@ export * from './header.component.js'; export * from './dashboard.component.js'; export * from './next-task.component.js'; -export * from './suggested-steps.component.js'; \ No newline at end of file +export * from './suggested-steps.component.js'; +export * from './task-detail.component.js'; diff --git a/apps/cli/src/ui/components/task-detail.component.ts b/apps/cli/src/ui/components/task-detail.component.ts new file mode 100644 index 00000000..7f1f1d20 --- /dev/null +++ b/apps/cli/src/ui/components/task-detail.component.ts @@ -0,0 +1,264 @@ +/** + * @fileoverview Task detail component for show command + * Displays detailed task information in a structured format + */ + +import chalk from 'chalk'; +import boxen from 'boxen'; +import Table from 'cli-table3'; +import { marked, MarkedExtension } from 'marked'; +import { markedTerminal } from 'marked-terminal'; +import type { Task } from '@tm/core/types'; +import { getStatusWithColor, getPriorityWithColor } from '../../utils/ui.js'; + +// Configure marked to use terminal renderer with subtle colors +marked.use( + markedTerminal({ + // More subtle colors that match the overall design + code: (code: string) => { + // Custom code block handler to preserve formatting + return code + .split('\n') + .map((line) => ' ' + chalk.cyan(line)) + .join('\n'); + }, + blockquote: chalk.gray.italic, + html: chalk.gray, + heading: chalk.white.bold, // White bold for headings + hr: chalk.gray, + listitem: chalk.white, // White for list items + paragraph: chalk.white, // White for paragraphs (default text color) + strong: chalk.white.bold, // White bold for strong text + em: chalk.white.italic, // White italic for emphasis + codespan: chalk.cyan, // Cyan for inline code (no background) + del: chalk.dim.strikethrough, + link: chalk.blue, + href: chalk.blue.underline, + // Add more explicit code block handling + showSectionPrefix: false, + unescape: true, + emoji: false, + // Try to preserve whitespace in code blocks + tab: 4, + width: 120 + }) as MarkedExtension +); + +// Also set marked options to preserve whitespace +marked.setOptions({ + breaks: true, + gfm: true +}); + +/** + * Display the task header with tag + */ +export function displayTaskHeader( + taskId: string | number, + title: string +): void { + // Display task header box + console.log( + boxen(chalk.white.bold(`Task: #${taskId} - ${title}`), { + padding: { top: 0, bottom: 0, left: 1, right: 1 }, + borderColor: 'blue', + borderStyle: 'round' + }) + ); +} + +/** + * Display task properties in a table format + */ +export function displayTaskProperties(task: Task): void { + const terminalWidth = process.stdout.columns * 0.95 || 100; + // Create table for task properties - simple 2-column layout + const table = new Table({ + head: [], + style: { + head: [], + border: ['grey'] + }, + colWidths: [ + Math.floor(terminalWidth * 0.2), + Math.floor(terminalWidth * 0.8) + ], + wordWrap: true + }); + + const deps = + task.dependencies && task.dependencies.length > 0 + ? task.dependencies.map((d) => String(d)).join(', ') + : 'None'; + + // Build the left column (labels) and right column (values) + const labels = [ + chalk.cyan('ID:'), + chalk.cyan('Title:'), + chalk.cyan('Status:'), + chalk.cyan('Priority:'), + chalk.cyan('Dependencies:'), + chalk.cyan('Complexity:'), + chalk.cyan('Description:') + ].join('\n'); + + const values = [ + String(task.id), + task.title, + getStatusWithColor(task.status), + getPriorityWithColor(task.priority), + deps, + 'N/A', + task.description || '' + ].join('\n'); + + table.push([labels, values]); + + console.log(table.toString()); +} + +/** + * Display implementation details in a box + */ +export function displayImplementationDetails(details: string): void { + // Handle all escaped characters properly + const cleanDetails = details + .replace(/\\n/g, '\n') // Convert \n to actual newlines + .replace(/\\t/g, '\t') // Convert \t to actual tabs + .replace(/\\"/g, '"') // Convert \" to actual quotes + .replace(/\\\\/g, '\\'); // Convert \\ to single backslash + + const terminalWidth = process.stdout.columns * 0.95 || 100; + + // Parse markdown to terminal-friendly format + const markdownResult = marked(cleanDetails); + const formattedDetails = + typeof markdownResult === 'string' ? markdownResult.trim() : cleanDetails; // Fallback to original if Promise + + console.log( + boxen( + chalk.white.bold('Implementation Details:') + '\n\n' + formattedDetails, + { + padding: 1, + borderStyle: 'round', + borderColor: 'cyan', // Changed to cyan to match the original + width: terminalWidth // Fixed width to match the original + } + ) + ); +} + +/** + * Display test strategy in a box + */ +export function displayTestStrategy(testStrategy: string): void { + // Handle all escaped characters properly (same as implementation details) + const cleanStrategy = testStrategy + .replace(/\\n/g, '\n') // Convert \n to actual newlines + .replace(/\\t/g, '\t') // Convert \t to actual tabs + .replace(/\\"/g, '"') // Convert \" to actual quotes + .replace(/\\\\/g, '\\'); // Convert \\ to single backslash + + const terminalWidth = process.stdout.columns * 0.95 || 100; + + // Parse markdown to terminal-friendly format (same as implementation details) + const markdownResult = marked(cleanStrategy); + const formattedStrategy = + typeof markdownResult === 'string' ? markdownResult.trim() : cleanStrategy; // Fallback to original if Promise + + console.log( + boxen(chalk.white.bold('Test Strategy:') + '\n\n' + formattedStrategy, { + padding: 1, + borderStyle: 'round', + borderColor: 'cyan', // Changed to cyan to match implementation details + width: terminalWidth + }) + ); +} + +/** + * Display subtasks in a table format + */ +export function displaySubtasks( + subtasks: Array<{ + id: string | number; + title: string; + status: any; + description?: string; + dependencies?: string[]; + }>, + parentId: string | number +): void { + const terminalWidth = process.stdout.columns * 0.95 || 100; + // Display subtasks header + console.log( + boxen(chalk.magenta.bold('Subtasks'), { + padding: { top: 0, bottom: 0, left: 1, right: 1 }, + borderColor: 'magenta', + borderStyle: 'round', + margin: { top: 1, bottom: 0 } + }) + ); + + // Create subtasks table + const table = new Table({ + head: [ + chalk.magenta.bold('ID'), + chalk.magenta.bold('Status'), + chalk.magenta.bold('Title'), + chalk.magenta.bold('Deps') + ], + style: { + head: [], + border: ['grey'] + }, + colWidths: [ + Math.floor(terminalWidth * 0.1), + Math.floor(terminalWidth * 0.15), + Math.floor(terminalWidth * 0.6), + Math.floor(terminalWidth * 0.15) + ], + wordWrap: true + }); + + subtasks.forEach((subtask) => { + const subtaskId = `${parentId}.${subtask.id}`; + + // Format dependencies + const deps = + subtask.dependencies && subtask.dependencies.length > 0 + ? subtask.dependencies.join(', ') + : 'None'; + + table.push([ + subtaskId, + getStatusWithColor(subtask.status), + subtask.title, + deps + ]); + }); + + console.log(table.toString()); +} + +/** + * Display suggested actions + */ +export function displaySuggestedActions(taskId: string | number): void { + console.log( + boxen( + chalk.white.bold('Suggested Actions:') + + '\n\n' + + `${chalk.cyan('1.')} Run ${chalk.yellow(`task-master set-status --id=${taskId} --status=in-progress`)} to start working\n` + + `${chalk.cyan('2.')} Run ${chalk.yellow(`task-master expand --id=${taskId}`)} to break down into subtasks\n` + + `${chalk.cyan('3.')} Run ${chalk.yellow(`task-master update-task --id=${taskId} --prompt="..."`)} to update details`, + { + padding: 1, + margin: { top: 1 }, + borderStyle: 'round', + borderColor: 'green', + width: process.stdout.columns * 0.95 || 100 + } + ) + ); +} diff --git a/apps/cli/src/ui/index.ts b/apps/cli/src/ui/index.ts index f345a7b4..f735fa4b 100644 --- a/apps/cli/src/ui/index.ts +++ b/apps/cli/src/ui/index.ts @@ -6,4 +6,4 @@ export * from './components/index.js'; // Re-export existing UI utilities -export * from '../utils/ui.js'; \ No newline at end of file +export * from '../utils/ui.js'; diff --git a/apps/cli/tsconfig.json b/apps/cli/tsconfig.json index 31016db7..ec5cee3e 100644 --- a/apps/cli/tsconfig.json +++ b/apps/cli/tsconfig.json @@ -1,27 +1,27 @@ { - "compilerOptions": { - "target": "ES2022", - "module": "ESNext", - "lib": ["ES2022"], - "moduleResolution": "bundler", - "allowSyntheticDefaultImports": true, - "esModuleInterop": true, - "strict": true, - "skipLibCheck": true, - "forceConsistentCasingInFileNames": true, - "declaration": true, - "declarationMap": true, - "sourceMap": true, - "outDir": "./dist", - "rootDir": "./src", - "resolveJsonModule": true, - "allowJs": false, - "noUnusedLocals": true, - "noUnusedParameters": true, - "noImplicitReturns": true, - "noFallthroughCasesInSwitch": true, - "types": ["node"] - }, - "include": ["src/**/*"], - "exclude": ["node_modules", "dist", "tests"] + "compilerOptions": { + "target": "ES2022", + "module": "ESNext", + "lib": ["ES2022"], + "moduleResolution": "bundler", + "allowSyntheticDefaultImports": true, + "esModuleInterop": true, + "strict": true, + "skipLibCheck": true, + "forceConsistentCasingInFileNames": true, + "declaration": true, + "declarationMap": true, + "sourceMap": true, + "outDir": "./dist", + "rootDir": "./src", + "resolveJsonModule": true, + "allowJs": false, + "noUnusedLocals": true, + "noUnusedParameters": true, + "noImplicitReturns": true, + "noFallthroughCasesInSwitch": true, + "types": ["node"] + }, + "include": ["src/**/*"], + "exclude": ["node_modules", "dist", "tests"] } diff --git a/bin/task-master.js b/bin/task-master.js index 634dc145..c3fc279f 100755 --- a/bin/task-master.js +++ b/bin/task-master.js @@ -24,4 +24,4 @@ import { runCLI } from '../scripts/modules/commands.js'; // Simply run the CLI directly -runCLI(); \ No newline at end of file +runCLI(); diff --git a/package-lock.json b/package-lock.json index 99913321..eefd1998 100644 --- a/package-lock.json +++ b/package-lock.json @@ -53,6 +53,8 @@ "jsonrepair": "^3.13.0", "jsonwebtoken": "^9.0.2", "lru-cache": "^10.2.0", + "marked": "^15.0.12", + "marked-terminal": "^7.3.0", "ollama-ai-provider": "^1.2.0", "openai": "^4.89.0", "ora": "^8.2.0", @@ -70,6 +72,7 @@ "@changesets/changelog-github": "^0.5.1", "@changesets/cli": "^2.28.1", "@types/jest": "^29.5.14", + "@types/marked-terminal": "^6.1.1", "concurrently": "^9.2.1", "cross-env": "^10.0.0", "dotenv-mono": "^1.5.1", @@ -10101,6 +10104,13 @@ "@babel/types": "^7.28.2" } }, + "node_modules/@types/cardinal": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/@types/cardinal/-/cardinal-2.1.1.tgz", + "integrity": "sha512-/xCVwg8lWvahHsV2wXZt4i64H1sdL+sN1Uoq7fAc8/FA6uYHjuIveDwPwvGUYp4VZiv85dVl6J/Bum3NDAOm8g==", + "dev": true, + "license": "MIT" + }, "node_modules/@types/cors": { "version": "2.8.19", "resolved": "https://registry.npmjs.org/@types/cors/-/cors-2.8.19.tgz", @@ -10261,6 +10271,32 @@ "dev": true, "license": "MIT" }, + "node_modules/@types/marked-terminal": { + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/@types/marked-terminal/-/marked-terminal-6.1.1.tgz", + "integrity": "sha512-DfoUqkmFDCED7eBY9vFUhJ9fW8oZcMAK5EwRDQ9drjTbpQa+DnBTQQCwWhTFVf4WsZ6yYcJTI8D91wxTWXRZZQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/cardinal": "^2.1", + "@types/node": "*", + "chalk": "^5.3.0", + "marked": ">=6.0.0 <12" + } + }, + "node_modules/@types/marked-terminal/node_modules/marked": { + "version": "11.2.0", + "resolved": "https://registry.npmjs.org/marked/-/marked-11.2.0.tgz", + "integrity": "sha512-HR0m3bvu0jAPYiIvLUUQtdg1g6D247//lvcekpHO1WMvbwDlwSkZAX9Lw4F4YHE1T0HaaNve0tuAWuV1UJ6vtw==", + "dev": true, + "license": "MIT", + "bin": { + "marked": "bin/marked.js" + }, + "engines": { + "node": ">= 18" + } + }, "node_modules/@types/mdast": { "version": "4.0.4", "resolved": "https://registry.npmjs.org/@types/mdast/-/mdast-4.0.4.tgz", @@ -12860,7 +12896,6 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/char-regex/-/char-regex-1.0.2.tgz", "integrity": "sha512-kWWXztvZ5SBQV+eRgKFeh8q5sLuZY2+8WUIzlxWVTg+oGwY14qylx1KbKzHd8P6ZYkAg0xyIDU9JMHhyJMZ1jw==", - "dev": true, "license": "MIT", "engines": { "node": ">=10" @@ -14895,6 +14930,12 @@ "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", "license": "MIT" }, + "node_modules/emojilib": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/emojilib/-/emojilib-2.4.0.tgz", + "integrity": "sha512-5U0rVMU5Y2n2+ykNLQqMoqklN9ICBT/KsvC1Gz6vqHbz2AXXGkG+Pm5rMWk/8Vjrr/mY9985Hi8DYzn1F09Nyw==", + "license": "MIT" + }, "node_modules/encodeurl": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-2.0.0.tgz", @@ -15064,7 +15105,6 @@ "version": "1.1.0", "resolved": "https://registry.npmjs.org/environment/-/environment-1.1.0.tgz", "integrity": "sha512-xUtoPkMggbz0MPyPiIWr1Kp4aeWJjDZ6SMvURhimjdZgsRuDplF5/s9hcgGhyXMhs+6vpnuoiZ2kFiu3FMnS8Q==", - "dev": true, "license": "MIT", "engines": { "node": ">=18" @@ -22303,7 +22343,6 @@ "resolved": "https://registry.npmjs.org/marked/-/marked-15.0.12.tgz", "integrity": "sha512-8dD6FusOQSrpv9Z1rdNMdlSgQOIP880DHqnohobOmYLElGEqAL/JvxvuxZO16r4HtjTlfPRDC1hbvxC9dPN2nA==", "license": "MIT", - "optional": true, "bin": { "marked": "bin/marked.js" }, @@ -22311,6 +22350,54 @@ "node": ">= 18" } }, + "node_modules/marked-terminal": { + "version": "7.3.0", + "resolved": "https://registry.npmjs.org/marked-terminal/-/marked-terminal-7.3.0.tgz", + "integrity": "sha512-t4rBvPsHc57uE/2nJOLmMbZCQ4tgAccAED3ngXQqW6g+TxA488JzJ+FK3lQkzBQOI1mRV/r/Kq+1ZlJ4D0owQw==", + "license": "MIT", + "dependencies": { + "ansi-escapes": "^7.0.0", + "ansi-regex": "^6.1.0", + "chalk": "^5.4.1", + "cli-highlight": "^2.1.11", + "cli-table3": "^0.6.5", + "node-emoji": "^2.2.0", + "supports-hyperlinks": "^3.1.0" + }, + "engines": { + "node": ">=16.0.0" + }, + "peerDependencies": { + "marked": ">=1 <16" + } + }, + "node_modules/marked-terminal/node_modules/ansi-escapes": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-7.1.0.tgz", + "integrity": "sha512-YdhtCd19sKRKfAAUsrcC1wzm4JuzJoiX4pOJqIoW2qmKj5WzG/dL8uUJ0361zaXtHqK7gEhOwtAtz7t3Yq3X5g==", + "license": "MIT", + "dependencies": { + "environment": "^1.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/marked-terminal/node_modules/ansi-regex": { + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.2.2.tgz", + "integrity": "sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg==", + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, "node_modules/math-intrinsics": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", @@ -24134,6 +24221,33 @@ "node": ">=10.5.0" } }, + "node_modules/node-emoji": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/node-emoji/-/node-emoji-2.2.0.tgz", + "integrity": "sha512-Z3lTE9pLaJF47NyMhd4ww1yFTAP8YhYI8SleJiHzM46Fgpm5cnNzSl9XfzFNqbaz+VlJrIj3fXQ4DeN1Rjm6cw==", + "license": "MIT", + "dependencies": { + "@sindresorhus/is": "^4.6.0", + "char-regex": "^1.0.2", + "emojilib": "^2.4.0", + "skin-tone": "^2.0.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/node-emoji/node_modules/@sindresorhus/is": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-4.6.0.tgz", + "integrity": "sha512-t09vSN3MdfsyCHoFcTRCH/iUtG7OJ0CsjzB8cjAmKc/va/kIgeDI/TxsigdncE/4be734m0cvIYwNaV4i2XqAw==", + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sindresorhus/is?sponsor=1" + } + }, "node_modules/node-fetch": { "version": "2.7.0", "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz", @@ -27643,6 +27757,18 @@ "dev": true, "license": "MIT" }, + "node_modules/skin-tone": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/skin-tone/-/skin-tone-2.0.0.tgz", + "integrity": "sha512-kUMbT1oBJCpgrnKoSr0o6wPtvRWT9W9UKvGLwfJYO2WuahZRHOpEyL1ckyMGgMWh0UdpmaoFqKKD29WTomNEGA==", + "license": "MIT", + "dependencies": { + "unicode-emoji-modifier-base": "^1.0.0" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/slash": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", @@ -28446,6 +28572,34 @@ "url": "https://github.com/chalk/supports-color?sponsor=1" } }, + "node_modules/supports-hyperlinks": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/supports-hyperlinks/-/supports-hyperlinks-3.2.0.tgz", + "integrity": "sha512-zFObLMyZeEwzAoKCyu1B91U79K2t7ApXuQfo8OuxwXLDgcKxuwM+YvcbIhm6QWqz7mHUH1TVytR1PwVVjEuMig==", + "license": "MIT", + "dependencies": { + "has-flag": "^4.0.0", + "supports-color": "^7.0.0" + }, + "engines": { + "node": ">=14.18" + }, + "funding": { + "url": "https://github.com/chalk/supports-hyperlinks?sponsor=1" + } + }, + "node_modules/supports-hyperlinks/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "license": "MIT", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/supports-preserve-symlinks-flag": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", @@ -29435,6 +29589,15 @@ "integrity": "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==", "license": "MIT" }, + "node_modules/unicode-emoji-modifier-base": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unicode-emoji-modifier-base/-/unicode-emoji-modifier-base-1.0.0.tgz", + "integrity": "sha512-yLSH4py7oFH3oG/9K+XWrz1pSi3dfUrWEnInbxMfArOfc1+33BlGPQtLsOYwvdMy11AwUBetYuaRxSPqgkq+8g==", + "license": "MIT", + "engines": { + "node": ">=4" + } + }, "node_modules/unicorn-magic": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/unicorn-magic/-/unicorn-magic-0.3.0.tgz", diff --git a/package.json b/package.json index 42e760aa..0029c5c2 100644 --- a/package.json +++ b/package.json @@ -59,7 +59,6 @@ "license": "MIT WITH Commons-Clause", "dependencies": { "@ai-sdk/amazon-bedrock": "^2.2.9", - "@tm/cli": "*", "@ai-sdk/anthropic": "^1.2.10", "@ai-sdk/azure": "^1.3.17", "@ai-sdk/google": "^1.2.13", @@ -74,6 +73,7 @@ "@inquirer/search": "^3.0.15", "@openrouter/ai-sdk-provider": "^0.4.5", "@streamparser/json": "^0.0.22", + "@tm/cli": "*", "ai": "^4.3.10", "ajv": "^8.17.1", "ajv-formats": "^3.0.1", @@ -97,6 +97,8 @@ "jsonrepair": "^3.13.0", "jsonwebtoken": "^9.0.2", "lru-cache": "^10.2.0", + "marked": "^15.0.12", + "marked-terminal": "^7.3.0", "ollama-ai-provider": "^1.2.0", "openai": "^4.89.0", "ora": "^8.2.0", @@ -131,6 +133,7 @@ "@changesets/changelog-github": "^0.5.1", "@changesets/cli": "^2.28.1", "@types/jest": "^29.5.14", + "@types/marked-terminal": "^6.1.1", "concurrently": "^9.2.1", "cross-env": "^10.0.0", "dotenv-mono": "^1.5.1", diff --git a/tsup.config.ts b/tsup.config.ts index efb9ca48..eb007fc6 100644 --- a/tsup.config.ts +++ b/tsup.config.ts @@ -30,27 +30,67 @@ export default defineConfig( publicDir: 'public', // Override the base config's external to bundle our workspace packages noExternal: [/^@tm\//], - external: [/^@supabase\//], // Keep Supabase external to avoid dynamic require issues + external: [ + /^@supabase\//, // Keep Supabase external to avoid dynamic require issues + 'marked', + 'marked-terminal' + ], env: getBuildTimeEnvs(), esbuildOptions(options) { // Set up path aliases for workspace packages options.alias = { '@tm/core': path.resolve(__dirname, 'packages/tm-core/src/index.ts'), - '@tm/core/auth': path.resolve(__dirname, 'packages/tm-core/src/auth/index.ts'), - '@tm/core/storage': path.resolve(__dirname, 'packages/tm-core/src/storage/index.ts'), - '@tm/core/config': path.resolve(__dirname, 'packages/tm-core/src/config/index.ts'), - '@tm/core/providers': path.resolve(__dirname, 'packages/tm-core/src/providers/index.ts'), - '@tm/core/services': path.resolve(__dirname, 'packages/tm-core/src/services/index.ts'), - '@tm/core/errors': path.resolve(__dirname, 'packages/tm-core/src/errors/index.ts'), - '@tm/core/logger': path.resolve(__dirname, 'packages/tm-core/src/logger/index.ts'), - '@tm/core/types': path.resolve(__dirname, 'packages/tm-core/src/types/index.ts'), - '@tm/core/interfaces': path.resolve(__dirname, 'packages/tm-core/src/interfaces/index.ts'), - '@tm/core/utils': path.resolve(__dirname, 'packages/tm-core/src/utils/index.ts'), + '@tm/core/auth': path.resolve( + __dirname, + 'packages/tm-core/src/auth/index.ts' + ), + '@tm/core/storage': path.resolve( + __dirname, + 'packages/tm-core/src/storage/index.ts' + ), + '@tm/core/config': path.resolve( + __dirname, + 'packages/tm-core/src/config/index.ts' + ), + '@tm/core/providers': path.resolve( + __dirname, + 'packages/tm-core/src/providers/index.ts' + ), + '@tm/core/services': path.resolve( + __dirname, + 'packages/tm-core/src/services/index.ts' + ), + '@tm/core/errors': path.resolve( + __dirname, + 'packages/tm-core/src/errors/index.ts' + ), + '@tm/core/logger': path.resolve( + __dirname, + 'packages/tm-core/src/logger/index.ts' + ), + '@tm/core/types': path.resolve( + __dirname, + 'packages/tm-core/src/types/index.ts' + ), + '@tm/core/interfaces': path.resolve( + __dirname, + 'packages/tm-core/src/interfaces/index.ts' + ), + '@tm/core/utils': path.resolve( + __dirname, + 'packages/tm-core/src/utils/index.ts' + ), '@tm/cli': path.resolve(__dirname, 'apps/cli/src/index.ts'), - '@tm/cli/commands': path.resolve(__dirname, 'apps/cli/src/commands/index.ts'), + '@tm/cli/commands': path.resolve( + __dirname, + 'apps/cli/src/commands/index.ts' + ), '@tm/cli/utils': path.resolve(__dirname, 'apps/cli/src/utils/index.ts'), '@tm/cli/ui': path.resolve(__dirname, 'apps/cli/src/ui/index.ts'), - '@tm/build-config': path.resolve(__dirname, 'packages/build-config/src/tsup.base.ts'), + '@tm/build-config': path.resolve( + __dirname, + 'packages/build-config/src/tsup.base.ts' + ) }; } }) diff --git a/turbo.json b/turbo.json index 54bb815c..50523359 100644 --- a/turbo.json +++ b/turbo.json @@ -41,4 +41,4 @@ } }, "globalDependencies": ["turbo.json", "tsconfig.json", ".env*"] -} \ No newline at end of file +}