add /refresh-builtin
This commit is contained in:
parent
4671af954a
commit
7270b29044
@ -30,6 +30,7 @@ import {
|
|||||||
switchWorkflow,
|
switchWorkflow,
|
||||||
switchConfig,
|
switchConfig,
|
||||||
addTask,
|
addTask,
|
||||||
|
refreshBuiltin,
|
||||||
} from './commands/index.js';
|
} from './commands/index.js';
|
||||||
import { listWorkflows } from './config/workflowLoader.js';
|
import { listWorkflows } from './config/workflowLoader.js';
|
||||||
import { selectOptionWithDefault } from './prompt/index.js';
|
import { selectOptionWithDefault } from './prompt/index.js';
|
||||||
@ -109,9 +110,13 @@ program
|
|||||||
await addTask(cwd, args);
|
await addTask(cwd, args);
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
case 'refresh-builtin':
|
||||||
|
await refreshBuiltin();
|
||||||
|
return;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
error(`Unknown command: /${command}`);
|
error(`Unknown command: /${command}`);
|
||||||
info('Available: /run-tasks, /add-task, /switch, /clear, /help, /config');
|
info('Available: /run-tasks, /add-task, /switch, /clear, /refresh-builtin, /help, /config');
|
||||||
process.exit(1);
|
process.exit(1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -18,6 +18,7 @@ Usage:
|
|||||||
takt /add-task Add a new task (interactive, YAML format)
|
takt /add-task Add a new task (interactive, YAML format)
|
||||||
takt /switch Switch workflow interactively
|
takt /switch Switch workflow interactively
|
||||||
takt /clear Clear agent conversation sessions (reset to initial state)
|
takt /clear Clear agent conversation sessions (reset to initial state)
|
||||||
|
takt /refresh-builtin Overwrite builtin agents/workflows with latest version
|
||||||
takt /help Show this help
|
takt /help Show this help
|
||||||
|
|
||||||
Examples:
|
Examples:
|
||||||
@ -25,6 +26,7 @@ Examples:
|
|||||||
takt /add-task "認証機能を追加する" # Quick add task
|
takt /add-task "認証機能を追加する" # Quick add task
|
||||||
takt /add-task # Interactive task creation
|
takt /add-task # Interactive task creation
|
||||||
takt /clear # Clear sessions, start fresh
|
takt /clear # Clear sessions, start fresh
|
||||||
|
takt /refresh-builtin # Update builtin resources
|
||||||
takt /switch
|
takt /switch
|
||||||
takt /run-tasks
|
takt /run-tasks
|
||||||
|
|
||||||
|
|||||||
@ -5,6 +5,7 @@
|
|||||||
export { executeWorkflow, type WorkflowExecutionResult, type WorkflowExecutionOptions } from './workflowExecution.js';
|
export { executeWorkflow, type WorkflowExecutionResult, type WorkflowExecutionOptions } from './workflowExecution.js';
|
||||||
export { executeTask, runAllTasks } from './taskExecution.js';
|
export { executeTask, runAllTasks } from './taskExecution.js';
|
||||||
export { addTask } from './addTask.js';
|
export { addTask } from './addTask.js';
|
||||||
|
export { refreshBuiltin } from './refreshBuiltin.js';
|
||||||
export { showHelp } from './help.js';
|
export { showHelp } from './help.js';
|
||||||
export { withAgentSession } from './session.js';
|
export { withAgentSession } from './session.js';
|
||||||
export { switchWorkflow } from './workflow.js';
|
export { switchWorkflow } from './workflow.js';
|
||||||
|
|||||||
43
src/commands/refreshBuiltin.ts
Normal file
43
src/commands/refreshBuiltin.ts
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
/**
|
||||||
|
* /refresh-builtin command implementation
|
||||||
|
*
|
||||||
|
* Overwrites builtin workflow and agent files in ~/.takt/ with the latest
|
||||||
|
* embedded resources. Does NOT touch config.yaml or user-added files.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { getGlobalConfigDir } from '../config/paths.js';
|
||||||
|
import { getLanguage } from '../config/globalConfig.js';
|
||||||
|
import { forceRefreshLanguageResources } from '../resources/index.js';
|
||||||
|
import { header, success, info, error } from '../utils/ui.js';
|
||||||
|
import { createLogger } from '../utils/debug.js';
|
||||||
|
|
||||||
|
const log = createLogger('refresh-builtin');
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Refresh builtin agents and workflows to latest version.
|
||||||
|
*/
|
||||||
|
export async function refreshBuiltin(): Promise<void> {
|
||||||
|
const globalDir = getGlobalConfigDir();
|
||||||
|
const lang = getLanguage();
|
||||||
|
|
||||||
|
header('Refresh Builtin Resources');
|
||||||
|
info(`Language: ${lang}`);
|
||||||
|
info(`Target: ${globalDir}`);
|
||||||
|
|
||||||
|
try {
|
||||||
|
const overwritten = forceRefreshLanguageResources(globalDir, lang);
|
||||||
|
|
||||||
|
log.info('Builtin resources refreshed', { count: overwritten.length, lang });
|
||||||
|
|
||||||
|
console.log();
|
||||||
|
success(`${overwritten.length} files refreshed.`);
|
||||||
|
|
||||||
|
for (const filePath of overwritten) {
|
||||||
|
info(` ✓ ${filePath}`);
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
const message = err instanceof Error ? err.message : String(err);
|
||||||
|
log.error('Failed to refresh builtin resources', { error: message });
|
||||||
|
error(`Failed to refresh: ${message}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -55,7 +55,7 @@ export function copyGlobalResourcesToDir(targetDir: string): void {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// Skip language directories (they are handled by copyLanguageResourcesToDir)
|
// Skip language directories (they are handled by copyLanguageResourcesToDir)
|
||||||
copyDirRecursive(resourcesDir, targetDir, ['en', 'ja']);
|
copyDirRecursive(resourcesDir, targetDir, { skipDirs: ['en', 'ja'] });
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -106,24 +106,62 @@ export function copyLanguageResourcesToDir(targetDir: string, lang: Language): v
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Force-refresh language-specific resources (agents and workflows) to ~/.takt.
|
||||||
|
* Overwrites existing builtin files. Does NOT touch config.yaml.
|
||||||
|
*/
|
||||||
|
export function forceRefreshLanguageResources(targetDir: string, lang: Language): string[] {
|
||||||
|
const langDir = getLanguageResourcesDir(lang);
|
||||||
|
if (!existsSync(langDir)) {
|
||||||
|
throw new Error(`Language resources not found: ${langDir}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
const copiedFiles: string[] = [];
|
||||||
|
const forceOptions = { overwrite: true, copiedFiles };
|
||||||
|
|
||||||
|
// Overwrite agents directory
|
||||||
|
const langAgentsDir = join(langDir, 'agents');
|
||||||
|
const targetAgentsDir = join(targetDir, 'agents');
|
||||||
|
if (existsSync(langAgentsDir)) {
|
||||||
|
copyDirRecursive(langAgentsDir, targetAgentsDir, forceOptions);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Overwrite workflows directory
|
||||||
|
const langWorkflowsDir = join(langDir, 'workflows');
|
||||||
|
const targetWorkflowsDir = join(targetDir, 'workflows');
|
||||||
|
if (existsSync(langWorkflowsDir)) {
|
||||||
|
copyDirRecursive(langWorkflowsDir, targetWorkflowsDir, forceOptions);
|
||||||
|
}
|
||||||
|
|
||||||
|
return copiedFiles;
|
||||||
|
}
|
||||||
|
|
||||||
/** Files to skip during resource copy (OS-generated files) */
|
/** Files to skip during resource copy (OS-generated files) */
|
||||||
const SKIP_FILES = ['.DS_Store', 'Thumbs.db'];
|
const SKIP_FILES = ['.DS_Store', 'Thumbs.db'];
|
||||||
|
|
||||||
|
interface CopyOptions {
|
||||||
|
/** Directory names to skip at the top level */
|
||||||
|
skipDirs?: string[];
|
||||||
|
/** Overwrite existing files (default: false) */
|
||||||
|
overwrite?: boolean;
|
||||||
|
/** Collect copied file paths into this array */
|
||||||
|
copiedFiles?: string[];
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Recursively copy directory contents.
|
* Recursively copy directory contents.
|
||||||
* Skips files that already exist in target.
|
* @param overwrite - If false (default), skips files that already exist in target.
|
||||||
* @param skipDirs - Directory names to skip at top level
|
* If true, overwrites existing files.
|
||||||
*/
|
*/
|
||||||
function copyDirRecursive(srcDir: string, destDir: string, skipDirs: string[] = []): void {
|
function copyDirRecursive(srcDir: string, destDir: string, options: CopyOptions = {}): void {
|
||||||
|
const { skipDirs = [], overwrite = false, copiedFiles } = options;
|
||||||
|
|
||||||
if (!existsSync(destDir)) {
|
if (!existsSync(destDir)) {
|
||||||
mkdirSync(destDir, { recursive: true });
|
mkdirSync(destDir, { recursive: true });
|
||||||
}
|
}
|
||||||
|
|
||||||
for (const entry of readdirSync(srcDir)) {
|
for (const entry of readdirSync(srcDir)) {
|
||||||
// Skip OS-generated files
|
|
||||||
if (SKIP_FILES.includes(entry)) continue;
|
if (SKIP_FILES.includes(entry)) continue;
|
||||||
|
|
||||||
// Skip specified directories
|
|
||||||
if (skipDirs.includes(entry)) continue;
|
if (skipDirs.includes(entry)) continue;
|
||||||
|
|
||||||
const srcPath = join(srcDir, entry);
|
const srcPath = join(srcDir, entry);
|
||||||
@ -131,11 +169,11 @@ function copyDirRecursive(srcDir: string, destDir: string, skipDirs: string[] =
|
|||||||
const stat = statSync(srcPath);
|
const stat = statSync(srcPath);
|
||||||
|
|
||||||
if (stat.isDirectory()) {
|
if (stat.isDirectory()) {
|
||||||
copyDirRecursive(srcPath, destPath);
|
copyDirRecursive(srcPath, destPath, { overwrite, copiedFiles });
|
||||||
} else if (!existsSync(destPath)) {
|
} else if (overwrite || !existsSync(destPath)) {
|
||||||
// Only copy if file doesn't exist
|
|
||||||
const content = readFileSync(srcPath);
|
const content = readFileSync(srcPath);
|
||||||
writeFileSync(destPath, content);
|
writeFileSync(destPath, content);
|
||||||
|
copiedFiles?.push(destPath);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user