more refactor
This commit is contained in:
parent
a66eb24009
commit
f04a950c9e
@ -7,7 +7,7 @@
|
||||
|
||||
import { describe, it, expect } from 'vitest';
|
||||
import { buildPrBody } from '../github/pr.js';
|
||||
import type { GitHubIssue } from '../github/issue.js';
|
||||
import type { GitHubIssue } from '../github/types.js';
|
||||
|
||||
describe('buildPrBody', () => {
|
||||
it('should build body with issue and report', () => {
|
||||
|
||||
@ -6,7 +6,7 @@ import { describe, it, expect, beforeEach, afterEach } from 'vitest';
|
||||
import { mkdirSync, writeFileSync, existsSync, rmSync } from 'node:fs';
|
||||
import { join } from 'node:path';
|
||||
import { TaskWatcher } from '../task/watcher.js';
|
||||
import type { TaskInfo } from '../task/runner.js';
|
||||
import type { TaskInfo } from '../task/types.js';
|
||||
|
||||
describe('TaskWatcher', () => {
|
||||
const testDir = `/tmp/takt-watcher-test-${Date.now()}`;
|
||||
|
||||
@ -45,11 +45,8 @@ import { DEFAULT_WORKFLOW_NAME } from './constants.js';
|
||||
import { checkForUpdates } from './utils/updateNotifier.js';
|
||||
import { getErrorMessage } from './utils/error.js';
|
||||
import { resolveIssueTask, isIssueReference } from './github/issue.js';
|
||||
import {
|
||||
selectAndExecuteTask,
|
||||
type SelectAndExecuteOptions,
|
||||
} from './commands/execution/selectAndExecute.js';
|
||||
import type { TaskExecutionOptions } from './commands/execution/taskExecution.js';
|
||||
import { selectAndExecuteTask } from './commands/execution/selectAndExecute.js';
|
||||
import type { TaskExecutionOptions, SelectAndExecuteOptions } from './commands/execution/types.js';
|
||||
import type { ProviderType } from './providers/index.js';
|
||||
|
||||
const require = createRequire(import.meta.url);
|
||||
|
||||
@ -2,13 +2,22 @@
|
||||
* Task/workflow execution commands.
|
||||
*/
|
||||
|
||||
export { executeWorkflow, type WorkflowExecutionResult, type WorkflowExecutionOptions } from './workflowExecution.js';
|
||||
export { executeTask, runAllTasks, executeAndCompleteTask, resolveTaskExecution, type TaskExecutionOptions } from './taskExecution.js';
|
||||
// Types
|
||||
export type {
|
||||
WorkflowExecutionResult,
|
||||
WorkflowExecutionOptions,
|
||||
TaskExecutionOptions,
|
||||
ExecuteTaskOptions,
|
||||
PipelineExecutionOptions,
|
||||
WorktreeConfirmationResult,
|
||||
SelectAndExecuteOptions,
|
||||
} from './types.js';
|
||||
|
||||
export { executeWorkflow } from './workflowExecution.js';
|
||||
export { executeTask, runAllTasks, executeAndCompleteTask, resolveTaskExecution } from './taskExecution.js';
|
||||
export {
|
||||
selectAndExecuteTask,
|
||||
confirmAndCreateWorktree,
|
||||
type SelectAndExecuteOptions,
|
||||
type WorktreeConfirmationResult,
|
||||
} from './selectAndExecute.js';
|
||||
export { executePipeline, type PipelineExecutionOptions } from './pipelineExecution.js';
|
||||
export { executePipeline } from './pipelineExecution.js';
|
||||
export { withAgentSession } from './session.js';
|
||||
|
||||
@ -10,10 +10,12 @@
|
||||
*/
|
||||
|
||||
import { execFileSync } from 'node:child_process';
|
||||
import { fetchIssue, formatIssueAsTask, checkGhCli, type GitHubIssue } from '../../github/issue.js';
|
||||
import { fetchIssue, formatIssueAsTask, checkGhCli } from '../../github/issue.js';
|
||||
import type { GitHubIssue } from '../../github/types.js';
|
||||
import { createPullRequest, pushBranch, buildPrBody } from '../../github/pr.js';
|
||||
import { stageAndCommit } from '../../task/git.js';
|
||||
import { executeTask, type TaskExecutionOptions } from './taskExecution.js';
|
||||
import { executeTask } from './taskExecution.js';
|
||||
import type { TaskExecutionOptions, PipelineExecutionOptions } from './types.js';
|
||||
import { loadGlobalConfig } from '../../config/global/globalConfig.js';
|
||||
import { info, error, success, status, blankLine } from '../../utils/ui.js';
|
||||
import { createLogger } from '../../utils/debug.js';
|
||||
@ -25,31 +27,11 @@ import {
|
||||
EXIT_GIT_OPERATION_FAILED,
|
||||
EXIT_PR_CREATION_FAILED,
|
||||
} from '../../exitCodes.js';
|
||||
import type { ProviderType } from '../../providers/index.js';
|
||||
|
||||
export type { PipelineExecutionOptions };
|
||||
|
||||
const log = createLogger('pipeline');
|
||||
|
||||
export interface PipelineExecutionOptions {
|
||||
/** GitHub issue number */
|
||||
issueNumber?: number;
|
||||
/** Task content (alternative to issue) */
|
||||
task?: string;
|
||||
/** Workflow name or path to workflow file */
|
||||
workflow: string;
|
||||
/** Branch name (auto-generated if omitted) */
|
||||
branch?: string;
|
||||
/** Whether to create a PR after successful execution */
|
||||
autoPr: boolean;
|
||||
/** Repository in owner/repo format */
|
||||
repo?: string;
|
||||
/** Skip branch creation, commit, and push (workflow-only execution) */
|
||||
skipGit?: boolean;
|
||||
/** Working directory */
|
||||
cwd: string;
|
||||
provider?: ProviderType;
|
||||
model?: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* Expand template variables in a string.
|
||||
* Supported: {title}, {issue}, {issue_body}, {report}
|
||||
|
||||
@ -17,23 +17,12 @@ import { info, error, success } from '../../utils/ui.js';
|
||||
import { createLogger } from '../../utils/debug.js';
|
||||
import { createPullRequest, buildPrBody } from '../../github/pr.js';
|
||||
import { executeTask } from './taskExecution.js';
|
||||
import type { TaskExecutionOptions } from './taskExecution.js';
|
||||
import type { TaskExecutionOptions, WorktreeConfirmationResult, SelectAndExecuteOptions } from './types.js';
|
||||
|
||||
export type { WorktreeConfirmationResult, SelectAndExecuteOptions };
|
||||
|
||||
const log = createLogger('selectAndExecute');
|
||||
|
||||
export interface WorktreeConfirmationResult {
|
||||
execCwd: string;
|
||||
isWorktree: boolean;
|
||||
branch?: string;
|
||||
}
|
||||
|
||||
export interface SelectAndExecuteOptions {
|
||||
autoPr?: boolean;
|
||||
repo?: string;
|
||||
workflow?: string;
|
||||
createWorktree?: boolean | undefined;
|
||||
}
|
||||
|
||||
/**
|
||||
* Select a workflow interactively.
|
||||
* Returns the selected workflow name, or null if cancelled.
|
||||
|
||||
@ -19,28 +19,12 @@ import { createLogger } from '../../utils/debug.js';
|
||||
import { getErrorMessage } from '../../utils/error.js';
|
||||
import { executeWorkflow } from './workflowExecution.js';
|
||||
import { DEFAULT_WORKFLOW_NAME } from '../../constants.js';
|
||||
import type { ProviderType } from '../../providers/index.js';
|
||||
import type { TaskExecutionOptions, ExecuteTaskOptions } from './types.js';
|
||||
|
||||
export type { TaskExecutionOptions, ExecuteTaskOptions };
|
||||
|
||||
const log = createLogger('task');
|
||||
|
||||
export interface TaskExecutionOptions {
|
||||
provider?: ProviderType;
|
||||
model?: string;
|
||||
}
|
||||
|
||||
export interface ExecuteTaskOptions {
|
||||
/** Task content */
|
||||
task: string;
|
||||
/** Working directory (may be a clone path) */
|
||||
cwd: string;
|
||||
/** Workflow name or path (auto-detected by isWorkflowPath) */
|
||||
workflowIdentifier: string;
|
||||
/** Project root (where .takt/ lives) */
|
||||
projectCwd: string;
|
||||
/** Agent provider/model overrides */
|
||||
agentOverrides?: TaskExecutionOptions;
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute a single task with workflow.
|
||||
*/
|
||||
|
||||
76
src/commands/execution/types.ts
Normal file
76
src/commands/execution/types.ts
Normal file
@ -0,0 +1,76 @@
|
||||
/**
|
||||
* Execution module type definitions
|
||||
*/
|
||||
|
||||
import type { Language } from '../../models/types.js';
|
||||
import type { ProviderType } from '../../providers/index.js';
|
||||
|
||||
/** Result of workflow execution */
|
||||
export interface WorkflowExecutionResult {
|
||||
success: boolean;
|
||||
reason?: string;
|
||||
}
|
||||
|
||||
/** Options for workflow execution */
|
||||
export interface WorkflowExecutionOptions {
|
||||
/** Header prefix for display */
|
||||
headerPrefix?: string;
|
||||
/** Project root directory (where .takt/ lives). */
|
||||
projectCwd: string;
|
||||
/** Language for instruction metadata */
|
||||
language?: Language;
|
||||
provider?: ProviderType;
|
||||
model?: string;
|
||||
}
|
||||
|
||||
export interface TaskExecutionOptions {
|
||||
provider?: ProviderType;
|
||||
model?: string;
|
||||
}
|
||||
|
||||
export interface ExecuteTaskOptions {
|
||||
/** Task content */
|
||||
task: string;
|
||||
/** Working directory (may be a clone path) */
|
||||
cwd: string;
|
||||
/** Workflow name or path (auto-detected by isWorkflowPath) */
|
||||
workflowIdentifier: string;
|
||||
/** Project root (where .takt/ lives) */
|
||||
projectCwd: string;
|
||||
/** Agent provider/model overrides */
|
||||
agentOverrides?: TaskExecutionOptions;
|
||||
}
|
||||
|
||||
export interface PipelineExecutionOptions {
|
||||
/** GitHub issue number */
|
||||
issueNumber?: number;
|
||||
/** Task content (alternative to issue) */
|
||||
task?: string;
|
||||
/** Workflow name or path to workflow file */
|
||||
workflow: string;
|
||||
/** Branch name (auto-generated if omitted) */
|
||||
branch?: string;
|
||||
/** Whether to create a PR after successful execution */
|
||||
autoPr: boolean;
|
||||
/** Repository in owner/repo format */
|
||||
repo?: string;
|
||||
/** Skip branch creation, commit, and push (workflow-only execution) */
|
||||
skipGit?: boolean;
|
||||
/** Working directory */
|
||||
cwd: string;
|
||||
provider?: ProviderType;
|
||||
model?: string;
|
||||
}
|
||||
|
||||
export interface WorktreeConfirmationResult {
|
||||
execCwd: string;
|
||||
isWorktree: boolean;
|
||||
branch?: string;
|
||||
}
|
||||
|
||||
export interface SelectAndExecuteOptions {
|
||||
autoPr?: boolean;
|
||||
repo?: string;
|
||||
workflow?: string;
|
||||
createWorktree?: boolean | undefined;
|
||||
}
|
||||
@ -4,9 +4,12 @@
|
||||
|
||||
import { readFileSync } from 'node:fs';
|
||||
import { WorkflowEngine } from '../../workflow/engine/WorkflowEngine.js';
|
||||
import type { WorkflowConfig, Language } from '../../models/types.js';
|
||||
import type { WorkflowConfig } from '../../models/types.js';
|
||||
import type { IterationLimitRequest } from '../../workflow/types.js';
|
||||
import type { ProviderType } from '../../providers/index.js';
|
||||
import type { WorkflowExecutionResult, WorkflowExecutionOptions } from './types.js';
|
||||
|
||||
export type { WorkflowExecutionResult, WorkflowExecutionOptions };
|
||||
|
||||
import {
|
||||
loadAgentSessions,
|
||||
updateAgentSession,
|
||||
@ -62,24 +65,6 @@ function formatElapsedTime(startTime: string, endTime: string): string {
|
||||
return `${minutes}m ${seconds}s`;
|
||||
}
|
||||
|
||||
/** Result of workflow execution */
|
||||
export interface WorkflowExecutionResult {
|
||||
success: boolean;
|
||||
reason?: string;
|
||||
}
|
||||
|
||||
/** Options for workflow execution */
|
||||
export interface WorkflowExecutionOptions {
|
||||
/** Header prefix for display */
|
||||
headerPrefix?: string;
|
||||
/** Project root directory (where .takt/ lives). */
|
||||
projectCwd: string;
|
||||
/** Language for instruction metadata */
|
||||
language?: Language;
|
||||
provider?: ProviderType;
|
||||
model?: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute a workflow and handle all events
|
||||
*/
|
||||
|
||||
@ -13,7 +13,7 @@ import {
|
||||
import { selectOption, confirm } from '../../prompt/index.js';
|
||||
import { info } from '../../utils/ui.js';
|
||||
import { createLogger } from '../../utils/debug.js';
|
||||
import type { TaskExecutionOptions } from '../execution/taskExecution.js';
|
||||
import type { TaskExecutionOptions } from '../execution/types.js';
|
||||
import {
|
||||
type ListAction,
|
||||
showFullDiff,
|
||||
|
||||
@ -22,7 +22,8 @@ import { selectOption, promptInput } from '../../prompt/index.js';
|
||||
import { info, success, error as logError, warn, header, blankLine } from '../../utils/ui.js';
|
||||
import { createLogger } from '../../utils/debug.js';
|
||||
import { getErrorMessage } from '../../utils/error.js';
|
||||
import { executeTask, type TaskExecutionOptions } from '../execution/taskExecution.js';
|
||||
import { executeTask } from '../execution/taskExecution.js';
|
||||
import type { TaskExecutionOptions } from '../execution/types.js';
|
||||
import { listWorkflows } from '../../config/loaders/workflowLoader.js';
|
||||
import { getCurrentWorkflow } from '../../config/paths.js';
|
||||
import { DEFAULT_WORKFLOW_NAME } from '../../constants.js';
|
||||
|
||||
@ -17,7 +17,7 @@ import {
|
||||
} from '../../utils/ui.js';
|
||||
import { executeAndCompleteTask } from '../execution/taskExecution.js';
|
||||
import { DEFAULT_WORKFLOW_NAME } from '../../constants.js';
|
||||
import type { TaskExecutionOptions } from '../execution/taskExecution.js';
|
||||
import type { TaskExecutionOptions } from '../execution/types.js';
|
||||
|
||||
/**
|
||||
* Watch for tasks and execute them as they appear.
|
||||
|
||||
@ -8,31 +8,9 @@ import { existsSync, readFileSync, writeFileSync, mkdirSync } from 'node:fs';
|
||||
import { join, resolve } from 'node:path';
|
||||
import { parse, stringify } from 'yaml';
|
||||
import { copyProjectResourcesToDir } from '../../resources/index.js';
|
||||
import type { PermissionMode, ProjectPermissionMode, ProjectLocalConfig } from '../types.js';
|
||||
|
||||
/** Permission mode for the project
|
||||
* - default: Uses Agent SDK's acceptEdits mode (auto-accepts file edits, minimal prompts)
|
||||
* - sacrifice-my-pc: Auto-approves all permission requests (bypassPermissions)
|
||||
*
|
||||
* Note: 'confirm' mode is planned but not yet implemented
|
||||
*/
|
||||
export type PermissionMode = 'default' | 'sacrifice-my-pc';
|
||||
|
||||
/** @deprecated Use PermissionMode instead */
|
||||
export type ProjectPermissionMode = PermissionMode;
|
||||
|
||||
/** Project configuration stored in .takt/config.yaml */
|
||||
export interface ProjectLocalConfig {
|
||||
/** Current workflow name */
|
||||
workflow?: string;
|
||||
/** Provider selection for agent runtime */
|
||||
provider?: 'claude' | 'codex';
|
||||
/** Permission mode setting */
|
||||
permissionMode?: PermissionMode;
|
||||
/** Verbose output mode */
|
||||
verbose?: boolean;
|
||||
/** Custom settings */
|
||||
[key: string]: unknown;
|
||||
}
|
||||
export type { PermissionMode, ProjectPermissionMode, ProjectLocalConfig };
|
||||
|
||||
/** Default project configuration */
|
||||
const DEFAULT_PROJECT_CONFIG: ProjectLocalConfig = {
|
||||
|
||||
@ -84,13 +84,9 @@ export function addToInputHistory(projectDir: string, input: string): void {
|
||||
|
||||
// ============ Agent Sessions ============
|
||||
|
||||
/** Agent session data for persistence */
|
||||
export interface AgentSessionData {
|
||||
agentSessions: Record<string, string>;
|
||||
updatedAt: string;
|
||||
/** Provider that created these sessions (claude, codex, etc.) */
|
||||
provider?: string;
|
||||
}
|
||||
import type { AgentSessionData } from '../types.js';
|
||||
|
||||
export type { AgentSessionData };
|
||||
|
||||
/** Get path for storing agent sessions */
|
||||
export function getAgentSessionsPath(projectDir: string): string {
|
||||
|
||||
36
src/config/types.ts
Normal file
36
src/config/types.ts
Normal file
@ -0,0 +1,36 @@
|
||||
/**
|
||||
* Config module type definitions
|
||||
*/
|
||||
|
||||
/** Permission mode for the project
|
||||
* - default: Uses Agent SDK's acceptEdits mode (auto-accepts file edits, minimal prompts)
|
||||
* - sacrifice-my-pc: Auto-approves all permission requests (bypassPermissions)
|
||||
*
|
||||
* Note: 'confirm' mode is planned but not yet implemented
|
||||
*/
|
||||
export type PermissionMode = 'default' | 'sacrifice-my-pc';
|
||||
|
||||
/** @deprecated Use PermissionMode instead */
|
||||
export type ProjectPermissionMode = PermissionMode;
|
||||
|
||||
/** Project configuration stored in .takt/config.yaml */
|
||||
export interface ProjectLocalConfig {
|
||||
/** Current workflow name */
|
||||
workflow?: string;
|
||||
/** Provider selection for agent runtime */
|
||||
provider?: 'claude' | 'codex';
|
||||
/** Permission mode setting */
|
||||
permissionMode?: PermissionMode;
|
||||
/** Verbose output mode */
|
||||
verbose?: boolean;
|
||||
/** Custom settings */
|
||||
[key: string]: unknown;
|
||||
}
|
||||
|
||||
/** Agent session data for persistence */
|
||||
export interface AgentSessionData {
|
||||
agentSessions: Record<string, string>;
|
||||
updatedAt: string;
|
||||
/** Provider that created these sessions (claude, codex, etc.) */
|
||||
provider?: string;
|
||||
}
|
||||
@ -7,25 +7,15 @@
|
||||
|
||||
import { execFileSync } from 'node:child_process';
|
||||
import { createLogger } from '../utils/debug.js';
|
||||
import type { GitHubIssue, GhCliStatus } from './types.js';
|
||||
|
||||
export type { GitHubIssue, GhCliStatus };
|
||||
|
||||
const log = createLogger('github');
|
||||
|
||||
/** Regex to match `#N` patterns (issue numbers) */
|
||||
const ISSUE_NUMBER_REGEX = /^#(\d+)$/;
|
||||
|
||||
export interface GitHubIssue {
|
||||
number: number;
|
||||
title: string;
|
||||
body: string;
|
||||
labels: string[];
|
||||
comments: Array<{ author: string; body: string }>;
|
||||
}
|
||||
|
||||
export interface GhCliStatus {
|
||||
available: boolean;
|
||||
error?: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if `gh` CLI is available and authenticated.
|
||||
*/
|
||||
|
||||
@ -7,31 +7,13 @@
|
||||
import { execFileSync } from 'node:child_process';
|
||||
import { createLogger } from '../utils/debug.js';
|
||||
import { getErrorMessage } from '../utils/error.js';
|
||||
import { checkGhCli, type GitHubIssue } from './issue.js';
|
||||
import { checkGhCli } from './issue.js';
|
||||
import type { GitHubIssue, CreatePrOptions, CreatePrResult } from './types.js';
|
||||
|
||||
export type { CreatePrOptions, CreatePrResult };
|
||||
|
||||
const log = createLogger('github-pr');
|
||||
|
||||
export interface CreatePrOptions {
|
||||
/** Branch to create PR from */
|
||||
branch: string;
|
||||
/** PR title */
|
||||
title: string;
|
||||
/** PR body (markdown) */
|
||||
body: string;
|
||||
/** Base branch (default: repo default branch) */
|
||||
base?: string;
|
||||
/** Repository in owner/repo format (optional, uses current repo if omitted) */
|
||||
repo?: string;
|
||||
}
|
||||
|
||||
export interface CreatePrResult {
|
||||
success: boolean;
|
||||
/** PR URL on success */
|
||||
url?: string;
|
||||
/** Error message on failure */
|
||||
error?: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* Push a branch to origin.
|
||||
* Throws on failure.
|
||||
|
||||
37
src/github/types.ts
Normal file
37
src/github/types.ts
Normal file
@ -0,0 +1,37 @@
|
||||
/**
|
||||
* GitHub module type definitions
|
||||
*/
|
||||
|
||||
export interface GitHubIssue {
|
||||
number: number;
|
||||
title: string;
|
||||
body: string;
|
||||
labels: string[];
|
||||
comments: Array<{ author: string; body: string }>;
|
||||
}
|
||||
|
||||
export interface GhCliStatus {
|
||||
available: boolean;
|
||||
error?: string;
|
||||
}
|
||||
|
||||
export interface CreatePrOptions {
|
||||
/** Branch to create PR from */
|
||||
branch: string;
|
||||
/** PR title */
|
||||
title: string;
|
||||
/** PR body (markdown) */
|
||||
body: string;
|
||||
/** Base branch (default: repo default branch) */
|
||||
base?: string;
|
||||
/** Repository in owner/repo format (optional, uses current repo if omitted) */
|
||||
repo?: string;
|
||||
}
|
||||
|
||||
export interface CreatePrResult {
|
||||
success: boolean;
|
||||
/** PR URL on success */
|
||||
url?: string;
|
||||
/** Error message on failure */
|
||||
error?: string;
|
||||
}
|
||||
@ -6,20 +6,12 @@
|
||||
*/
|
||||
|
||||
import { randomUUID } from 'node:crypto';
|
||||
import type { StreamCallback, StreamEvent } from '../claude/process.js';
|
||||
import type { StreamEvent } from '../claude/process.js';
|
||||
import type { AgentResponse } from '../models/types.js';
|
||||
import { getScenarioQueue } from './scenario.js';
|
||||
import type { MockCallOptions } from './types.js';
|
||||
|
||||
/** Options for mock calls */
|
||||
export interface MockCallOptions {
|
||||
cwd: string;
|
||||
sessionId?: string;
|
||||
onStream?: StreamCallback;
|
||||
/** Fixed response content (optional, defaults to generic mock response) */
|
||||
mockResponse?: string;
|
||||
/** Fixed status to return (optional, defaults to 'done') */
|
||||
mockStatus?: 'done' | 'blocked' | 'approved' | 'rejected' | 'improve';
|
||||
}
|
||||
export type { MockCallOptions };
|
||||
|
||||
/**
|
||||
* Generate a mock session ID
|
||||
|
||||
@ -7,16 +7,9 @@
|
||||
*/
|
||||
|
||||
import { readFileSync, existsSync } from 'node:fs';
|
||||
import type { ScenarioEntry } from './types.js';
|
||||
|
||||
/** A single entry in a mock scenario */
|
||||
export interface ScenarioEntry {
|
||||
/** Agent name to match (optional — if omitted, consumed by call order) */
|
||||
agent?: string;
|
||||
/** Response status */
|
||||
status: 'done' | 'blocked' | 'approved' | 'rejected' | 'improve';
|
||||
/** Response content body */
|
||||
content: string;
|
||||
}
|
||||
export type { ScenarioEntry };
|
||||
|
||||
/**
|
||||
* Queue that dispenses scenario entries.
|
||||
|
||||
26
src/mock/types.ts
Normal file
26
src/mock/types.ts
Normal file
@ -0,0 +1,26 @@
|
||||
/**
|
||||
* Mock module type definitions
|
||||
*/
|
||||
|
||||
import type { StreamCallback } from '../claude/process.js';
|
||||
|
||||
/** Options for mock calls */
|
||||
export interface MockCallOptions {
|
||||
cwd: string;
|
||||
sessionId?: string;
|
||||
onStream?: StreamCallback;
|
||||
/** Fixed response content (optional, defaults to generic mock response) */
|
||||
mockResponse?: string;
|
||||
/** Fixed status to return (optional, defaults to 'done') */
|
||||
mockStatus?: 'done' | 'blocked' | 'approved' | 'rejected' | 'improve';
|
||||
}
|
||||
|
||||
/** A single entry in a mock scenario */
|
||||
export interface ScenarioEntry {
|
||||
/** Agent name to match (optional — if omitted, consumed by call order) */
|
||||
agent?: string;
|
||||
/** Response status */
|
||||
status: 'done' | 'blocked' | 'approved' | 'rejected' | 'improve';
|
||||
/** Response content body */
|
||||
content: string;
|
||||
}
|
||||
@ -2,7 +2,8 @@
|
||||
* Mock provider implementation
|
||||
*/
|
||||
|
||||
import { callMock, callMockCustom, type MockCallOptions } from '../mock/client.js';
|
||||
import { callMock, callMockCustom } from '../mock/client.js';
|
||||
import type { MockCallOptions } from '../mock/types.js';
|
||||
import type { AgentResponse } from '../models/types.js';
|
||||
import type { Provider, ProviderCallOptions } from './types.js';
|
||||
|
||||
|
||||
@ -9,23 +9,12 @@
|
||||
import { execFileSync } from 'node:child_process';
|
||||
import { createLogger } from '../utils/debug.js';
|
||||
|
||||
import type { BranchInfo, BranchListItem } from './types.js';
|
||||
|
||||
export type { BranchInfo, BranchListItem };
|
||||
|
||||
const log = createLogger('branchList');
|
||||
|
||||
/** Branch info from `git branch --list` */
|
||||
export interface BranchInfo {
|
||||
branch: string;
|
||||
commit: string;
|
||||
}
|
||||
|
||||
/** Branch with list metadata */
|
||||
export interface BranchListItem {
|
||||
info: BranchInfo;
|
||||
filesChanged: number;
|
||||
taskSlug: string;
|
||||
/** Original task instruction extracted from first commit message */
|
||||
originalInstruction: string;
|
||||
}
|
||||
|
||||
const TAKT_BRANCH_PREFIX = 'takt/';
|
||||
|
||||
/**
|
||||
|
||||
@ -13,27 +13,12 @@ import { execFileSync } from 'node:child_process';
|
||||
import { createLogger } from '../utils/debug.js';
|
||||
import { slugify } from '../utils/slug.js';
|
||||
import { loadGlobalConfig } from '../config/global/globalConfig.js';
|
||||
import type { WorktreeOptions, WorktreeResult } from './types.js';
|
||||
|
||||
export type { WorktreeOptions, WorktreeResult };
|
||||
|
||||
const log = createLogger('clone');
|
||||
|
||||
export interface WorktreeOptions {
|
||||
/** worktree setting: true = auto path, string = custom path */
|
||||
worktree: boolean | string;
|
||||
/** Branch name (optional, auto-generated if omitted) */
|
||||
branch?: string;
|
||||
/** Task slug for auto-generated paths/branches */
|
||||
taskSlug: string;
|
||||
/** GitHub Issue number (optional, for formatting branch/path) */
|
||||
issueNumber?: number;
|
||||
}
|
||||
|
||||
export interface WorktreeResult {
|
||||
/** Absolute path to the clone */
|
||||
path: string;
|
||||
/** Branch name used */
|
||||
branch: string;
|
||||
}
|
||||
|
||||
const CLONE_META_DIR = 'clone-meta';
|
||||
|
||||
/**
|
||||
@ -112,11 +97,41 @@ export class CloneManager {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolve the main repository path (handles git worktree case).
|
||||
* If projectDir is a worktree, returns the main repo path.
|
||||
* Otherwise, returns projectDir as-is.
|
||||
*/
|
||||
private static resolveMainRepo(projectDir: string): string {
|
||||
const gitPath = path.join(projectDir, '.git');
|
||||
|
||||
try {
|
||||
const stats = fs.statSync(gitPath);
|
||||
if (stats.isFile()) {
|
||||
const content = fs.readFileSync(gitPath, 'utf-8');
|
||||
const match = content.match(/^gitdir:\s*(.+)$/m);
|
||||
if (match && match[1]) {
|
||||
const worktreePath = match[1].trim();
|
||||
const gitDir = path.resolve(worktreePath, '..', '..');
|
||||
const mainRepoPath = path.dirname(gitDir);
|
||||
log.info('Detected worktree, using main repo', { worktree: projectDir, mainRepo: mainRepoPath });
|
||||
return mainRepoPath;
|
||||
}
|
||||
}
|
||||
} catch (err) {
|
||||
log.debug('Failed to resolve main repo, using projectDir as-is', { error: String(err) });
|
||||
}
|
||||
|
||||
return projectDir;
|
||||
}
|
||||
|
||||
/** Clone a repository and remove origin to isolate from the main repo */
|
||||
private static cloneAndIsolate(projectDir: string, clonePath: string): void {
|
||||
const referenceRepo = CloneManager.resolveMainRepo(projectDir);
|
||||
|
||||
fs.mkdirSync(path.dirname(clonePath), { recursive: true });
|
||||
|
||||
execFileSync('git', ['clone', '--reference', projectDir, '--dissociate', projectDir, clonePath], {
|
||||
execFileSync('git', ['clone', '--reference', referenceRepo, '--dissociate', projectDir, clonePath], {
|
||||
cwd: projectDir,
|
||||
stdio: 'pipe',
|
||||
});
|
||||
|
||||
@ -2,17 +2,24 @@
|
||||
* Task execution module
|
||||
*/
|
||||
|
||||
// Types
|
||||
export type {
|
||||
TaskInfo,
|
||||
TaskResult,
|
||||
WorktreeOptions,
|
||||
WorktreeResult,
|
||||
BranchInfo,
|
||||
BranchListItem,
|
||||
SummarizeOptions,
|
||||
} from './types.js';
|
||||
|
||||
// Classes
|
||||
export { CloneManager } from './clone.js';
|
||||
export { AutoCommitter } from './autoCommit.js';
|
||||
export { TaskSummarizer } from './summarize.js';
|
||||
export { BranchManager } from './branchList.js';
|
||||
|
||||
export {
|
||||
TaskRunner,
|
||||
type TaskInfo,
|
||||
type TaskResult,
|
||||
} from './runner.js';
|
||||
export { TaskRunner } from './runner.js';
|
||||
|
||||
export { showTaskList } from './display.js';
|
||||
|
||||
@ -25,8 +32,6 @@ export {
|
||||
saveCloneMeta,
|
||||
removeCloneMeta,
|
||||
cleanupOrphanedClone,
|
||||
type WorktreeOptions,
|
||||
type WorktreeResult,
|
||||
} from './clone.js';
|
||||
export {
|
||||
detectDefaultBranch,
|
||||
@ -36,9 +41,7 @@ export {
|
||||
extractTaskSlug,
|
||||
getOriginalInstruction,
|
||||
buildListItems,
|
||||
type BranchInfo,
|
||||
type BranchListItem,
|
||||
} from './branchList.js';
|
||||
export { autoCommitAndPush, type AutoCommitResult } from './autoCommit.js';
|
||||
export { summarizeTaskName, type SummarizeOptions } from './summarize.js';
|
||||
export { summarizeTaskName } from './summarize.js';
|
||||
export { TaskWatcher, type TaskWatcherOptions } from './watcher.js';
|
||||
|
||||
@ -16,27 +16,9 @@
|
||||
import * as fs from 'node:fs';
|
||||
import * as path from 'node:path';
|
||||
import { parseTaskFiles, parseTaskFile, type ParsedTask } from './parser.js';
|
||||
import type { TaskFileData } from './schema.js';
|
||||
import type { TaskInfo, TaskResult } from './types.js';
|
||||
|
||||
/** タスク情報 */
|
||||
export interface TaskInfo {
|
||||
filePath: string;
|
||||
name: string;
|
||||
content: string;
|
||||
createdAt: string;
|
||||
/** Structured data from YAML files (null for .md files) */
|
||||
data: TaskFileData | null;
|
||||
}
|
||||
|
||||
/** タスク実行結果 */
|
||||
export interface TaskResult {
|
||||
task: TaskInfo;
|
||||
success: boolean;
|
||||
response: string;
|
||||
executionLog: string[];
|
||||
startedAt: string;
|
||||
completedAt: string;
|
||||
}
|
||||
export type { TaskInfo, TaskResult };
|
||||
|
||||
/**
|
||||
* タスク実行管理クラス
|
||||
|
||||
@ -8,6 +8,9 @@ import * as wanakana from 'wanakana';
|
||||
import { loadGlobalConfig } from '../config/global/globalConfig.js';
|
||||
import { getProvider, type ProviderType } from '../providers/index.js';
|
||||
import { createLogger } from '../utils/debug.js';
|
||||
import type { SummarizeOptions } from './types.js';
|
||||
|
||||
export type { SummarizeOptions };
|
||||
|
||||
const log = createLogger('summarize');
|
||||
|
||||
@ -25,15 +28,6 @@ Fix the login bug → fix-login-bug
|
||||
worktreeを作るときブランチ名をAIで生成 → ai-branch-naming
|
||||
レビュー画面に元の指示を表示する → show-original-instruction`;
|
||||
|
||||
export interface SummarizeOptions {
|
||||
/** Working directory for Claude execution */
|
||||
cwd: string;
|
||||
/** Model to use (optional, defaults to config or haiku) */
|
||||
model?: string;
|
||||
/** Use LLM for summarization (default: true). If false, uses romanization. */
|
||||
useLLM?: boolean;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sanitize a string for use as git branch name and directory name.
|
||||
* Allows only: a-z, 0-9, hyphen.
|
||||
|
||||
67
src/task/types.ts
Normal file
67
src/task/types.ts
Normal file
@ -0,0 +1,67 @@
|
||||
/**
|
||||
* Task module type definitions
|
||||
*/
|
||||
|
||||
import type { TaskFileData } from './schema.js';
|
||||
|
||||
/** タスク情報 */
|
||||
export interface TaskInfo {
|
||||
filePath: string;
|
||||
name: string;
|
||||
content: string;
|
||||
createdAt: string;
|
||||
/** Structured data from YAML files (null for .md files) */
|
||||
data: TaskFileData | null;
|
||||
}
|
||||
|
||||
/** タスク実行結果 */
|
||||
export interface TaskResult {
|
||||
task: TaskInfo;
|
||||
success: boolean;
|
||||
response: string;
|
||||
executionLog: string[];
|
||||
startedAt: string;
|
||||
completedAt: string;
|
||||
}
|
||||
|
||||
export interface WorktreeOptions {
|
||||
/** worktree setting: true = auto path, string = custom path */
|
||||
worktree: boolean | string;
|
||||
/** Branch name (optional, auto-generated if omitted) */
|
||||
branch?: string;
|
||||
/** Task slug for auto-generated paths/branches */
|
||||
taskSlug: string;
|
||||
/** GitHub Issue number (optional, for formatting branch/path) */
|
||||
issueNumber?: number;
|
||||
}
|
||||
|
||||
export interface WorktreeResult {
|
||||
/** Absolute path to the clone */
|
||||
path: string;
|
||||
/** Branch name used */
|
||||
branch: string;
|
||||
}
|
||||
|
||||
/** Branch info from `git branch --list` */
|
||||
export interface BranchInfo {
|
||||
branch: string;
|
||||
commit: string;
|
||||
}
|
||||
|
||||
/** Branch with list metadata */
|
||||
export interface BranchListItem {
|
||||
info: BranchInfo;
|
||||
filesChanged: number;
|
||||
taskSlug: string;
|
||||
/** Original task instruction extracted from first commit message */
|
||||
originalInstruction: string;
|
||||
}
|
||||
|
||||
export interface SummarizeOptions {
|
||||
/** Working directory for Claude execution */
|
||||
cwd: string;
|
||||
/** Model to use (optional, defaults to config or haiku) */
|
||||
model?: string;
|
||||
/** Use LLM for summarization (default: true). If false, uses romanization. */
|
||||
useLLM?: boolean;
|
||||
}
|
||||
@ -6,7 +6,8 @@
|
||||
*/
|
||||
|
||||
import { createLogger } from '../utils/debug.js';
|
||||
import { TaskRunner, type TaskInfo } from './runner.js';
|
||||
import { TaskRunner } from './runner.js';
|
||||
import type { TaskInfo } from './types.js';
|
||||
|
||||
const log = createLogger('watcher');
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user