agent-handoff 0.2.0 → 0.3.0

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/CHANGELOG.md CHANGED
@@ -2,6 +2,19 @@
2
2
 
3
3
  All notable changes to this project will be documented in this file.
4
4
 
5
+ ## [0.3.0] - 2026-03-02
6
+
7
+ ### Added
8
+ - TRAE 自动化能力(可选):视觉识别、自动输入、任务等待(Nut.js 路线)
9
+ - 自动化操作日志:会话级 JSONL 落盘(`workspace/operations/`)
10
+ - 自动化诊断落盘:失败时输出 diagnostics JSON(`workspace/diagnostics/`)
11
+ - 自动化降级:失败时输出可继续手工执行的辅助模式提示,并可复制 prompt 到剪贴板
12
+ - `agent-handoff report` 命令:从 operations JSONL 生成 json/markdown/html 报告
13
+ - 新事件类型:`automation.session`(events.jsonl,支持 data 字段承载统计信息)
14
+
15
+ ### Changed
16
+ - `TraeAdapter.execute()` 支持恢复重试与失败降级输出
17
+
5
18
  ## [0.2.0] - 2026-03-02
6
19
 
7
20
  ### Added
@@ -9,7 +22,7 @@ All notable changes to this project will be documented in this file.
9
22
  - `agent-handoff advance` 命令 - 推进 workspace 状态
10
23
  - `agent-handoff config` 命令 - 查看和管理配置
11
24
  - `--copy` 选项 - 自动复制 prompt 到剪贴板(跨平台支持)
12
- - `--skip-event` 选项 - 跳过事件日志写入
25
+ - `--no-event` 选项 - 跳过事件日志写入
13
26
  - 产物校验模块 - 检查 output.md 必要区块
14
27
  - 剪贴板模块 - 跨平台剪贴板操作
15
28
  - 事件写入模块 - events.jsonl 追加式日志
package/README.md CHANGED
@@ -65,11 +65,45 @@ agent-handoff status [workspace] [--json]
65
65
  输出下一步执行指令和 prompt。
66
66
 
67
67
  ```bash
68
- agent-handoff next [workspace]
68
+ agent-handoff next [workspace] [--copy] [--no-event]
69
69
  ```
70
70
 
71
71
  参数:
72
72
  - `[workspace]` - workspace 路径(默认当前目录)
73
+ - `--copy, -c` - 复制 prompt 到剪贴板
74
+ - `--no-event` - 不写入 events.jsonl
75
+
76
+ ### validate
77
+
78
+ 校验 workflow 与产物结构。
79
+
80
+ ```bash
81
+ agent-handoff validate [workspace]
82
+ ```
83
+
84
+ ### advance
85
+
86
+ 手动推进 workflow 状态,并可写入事件。
87
+
88
+ ```bash
89
+ agent-handoff advance [workspace]
90
+ ```
91
+
92
+ ### config
93
+
94
+ 查看或生成配置文件。
95
+
96
+ ```bash
97
+ agent-handoff config [workspace]
98
+ ```
99
+
100
+ ### report
101
+
102
+ 读取 workspace 下的自动化操作日志并生成报告(json/markdown/html)。
103
+
104
+ ```bash
105
+ agent-handoff report [workspace] [--format markdown|json|html] [--session <id>] [--screenshots] [--output <path>]
106
+ ```
73
107
 
74
108
  ## Workspace 结构
75
109
 
package/dist/index.js CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  // src/index.ts
4
4
  import { createRequire } from "module";
5
- import { Command as Command7 } from "commander";
5
+ import { Command as Command8 } from "commander";
6
6
 
7
7
  // src/cli/commands/init.ts
8
8
  import { Command } from "commander";
@@ -377,14 +377,15 @@ async function copyToClipboard(text) {
377
377
  import fs4 from "fs/promises";
378
378
  import path4 from "path";
379
379
  async function writeEvent(options) {
380
- const { workspacePath, step, type, summary, workItemId, links } = options;
380
+ const { workspacePath, step, type, summary, workItemId, links, data } = options;
381
381
  const event = {
382
382
  ts: (/* @__PURE__ */ new Date()).toISOString(),
383
383
  step,
384
384
  type,
385
385
  summary,
386
386
  ...workItemId && { workItemId },
387
- ...links && links.length > 0 && { links }
387
+ ...links && links.length > 0 && { links },
388
+ ...data && { data }
388
389
  };
389
390
  try {
390
391
  const eventsPath = path4.join(workspacePath, "events.jsonl");
@@ -571,7 +572,7 @@ async function validateArtifactFile(filePath) {
571
572
  try {
572
573
  const content = await fs5.readFile(filePath, "utf-8");
573
574
  return validateArtifact(content);
574
- } catch (error) {
575
+ } catch {
575
576
  return {
576
577
  valid: false,
577
578
  errors: [
@@ -799,7 +800,8 @@ function getDefaultSummary(eventType, stepId) {
799
800
  "accept.passed": "\u9A8C\u6536\u901A\u8FC7",
800
801
  "accept.failed": "\u9A8C\u6536\u5931\u8D25",
801
802
  "issue.raised": "\u53D1\u73B0\u95EE\u9898",
802
- "handoff.sent": "\u5DF2\u4EA4\u63A5\u7ED9\u4E0B\u4E00\u6B65"
803
+ "handoff.sent": "\u5DF2\u4EA4\u63A5\u7ED9\u4E0B\u4E00\u6B65",
804
+ "automation.session": "\u81EA\u52A8\u5316\u4F1A\u8BDD\u5DF2\u8BB0\u5F55"
803
805
  };
804
806
  return summaries[eventType] || `\u4E8B\u4EF6: ${eventType}`;
805
807
  }
@@ -818,6 +820,14 @@ var DEFAULT_CONFIG = {
818
820
  logStepStarted: true,
819
821
  logStepDone: true
820
822
  },
823
+ automation: {
824
+ enabled: false,
825
+ provider: "nutjs",
826
+ screenshot: false,
827
+ timeout: 3e4,
828
+ retries: 3,
829
+ confidence: 0.8
830
+ },
821
831
  clipboard: {
822
832
  autoCopy: false
823
833
  },
@@ -989,7 +999,7 @@ var configCommand = new Command6("config").description("\u67E5\u770B\u6216\u7BA1
989
999
  } else if (action === "init") {
990
1000
  await initConfig(options);
991
1001
  } else if (action === "list") {
992
- await listConfig(options);
1002
+ await listConfig();
993
1003
  } else {
994
1004
  console.error(`Unknown action: ${action}`);
995
1005
  console.log("Available actions: show, init, list");
@@ -1023,7 +1033,7 @@ async function initConfig(options) {
1023
1033
  console.log("Default configuration:");
1024
1034
  console.log(JSON.stringify(DEFAULT_CONFIG, null, 2));
1025
1035
  }
1026
- async function listConfig(options) {
1036
+ async function listConfig() {
1027
1037
  console.log("Configuration options:");
1028
1038
  console.log("");
1029
1039
  console.log(" defaultWorkspace - \u9ED8\u8BA4 workspace \u8DEF\u5F84");
@@ -1044,10 +1054,201 @@ async function listConfig(options) {
1044
1054
  console.log(` ~/.agenthandoffrc (global)`);
1045
1055
  }
1046
1056
 
1057
+ // src/cli/commands/report.ts
1058
+ import { Command as Command7 } from "commander";
1059
+ import fs9 from "fs/promises";
1060
+ import path10 from "path";
1061
+
1062
+ // src/adapters/trae/operation-reporter.ts
1063
+ import fs8 from "fs/promises";
1064
+ var OperationReporter = class {
1065
+ session;
1066
+ constructor(session) {
1067
+ this.session = session;
1068
+ }
1069
+ generate(options) {
1070
+ switch (options.format) {
1071
+ case "json":
1072
+ return this.generateJson();
1073
+ case "markdown":
1074
+ return this.generateMarkdown(options.includeScreenshots);
1075
+ case "html":
1076
+ return this.generateHtml(options.includeScreenshots);
1077
+ default:
1078
+ return this.generateMarkdown(options.includeScreenshots);
1079
+ }
1080
+ }
1081
+ generateJson() {
1082
+ return JSON.stringify(this.session, null, 2);
1083
+ }
1084
+ generateMarkdown(includeScreenshots) {
1085
+ const lines = [
1086
+ "# Automation Session Report",
1087
+ "",
1088
+ `**Session ID:** ${this.session.id}`,
1089
+ `**Started At:** ${this.session.startedAt}`,
1090
+ `**Workspace:** ${this.session.workspacePath}`,
1091
+ `**Step ID:** ${this.session.stepId}`,
1092
+ ...this.session.status ? [`**Status:** ${this.session.status}`] : [],
1093
+ ...this.session.error ? [`**Error:** ${this.session.error}`] : [],
1094
+ "",
1095
+ `## Operations (${this.session.operations.length})`,
1096
+ ""
1097
+ ];
1098
+ this.session.operations.forEach((op, index) => {
1099
+ lines.push(`### ${index + 1}. ${op.type}`);
1100
+ if (op.target) {
1101
+ lines.push(`- **Target:** ${op.target}`);
1102
+ }
1103
+ if (op.value) {
1104
+ lines.push(
1105
+ `- **Value:** ${op.value.substring(0, 100)}${op.value.length > 100 ? "..." : ""}`
1106
+ );
1107
+ }
1108
+ lines.push(`- **Timestamp:** ${new Date(op.timestamp).toISOString()}`);
1109
+ lines.push("");
1110
+ });
1111
+ if (includeScreenshots && this.session.screenshots.length > 0) {
1112
+ lines.push(`## Screenshots (${this.session.screenshots.length})`);
1113
+ lines.push("");
1114
+ this.session.screenshots.forEach((screenshot, index) => {
1115
+ lines.push(`### Screenshot ${index + 1}`);
1116
+ lines.push(`![Screenshot ${index + 1}](${screenshot})`);
1117
+ lines.push("");
1118
+ });
1119
+ }
1120
+ return lines.join("\n");
1121
+ }
1122
+ generateHtml(includeScreenshots) {
1123
+ const operationsHtml = this.session.operations.map(
1124
+ (op, index) => `
1125
+ <div class="operation">
1126
+ <h3>${index + 1}. ${op.type}</h3>
1127
+ ${op.target ? `<p><strong>Target:</strong> ${op.target}</p>` : ""}
1128
+ ${op.value ? `<p><strong>Value:</strong> ${op.value.substring(0, 100)}${op.value.length > 100 ? "..." : ""}</p>` : ""}
1129
+ <p><strong>Timestamp:</strong> ${new Date(op.timestamp).toISOString()}</p>
1130
+ </div>
1131
+ `
1132
+ ).join("");
1133
+ const screenshotsHtml = includeScreenshots && this.session.screenshots.length > 0 ? `
1134
+ <h2>Screenshots (${this.session.screenshots.length})</h2>
1135
+ ${this.session.screenshots.map(
1136
+ (s, i) => `
1137
+ <div class="screenshot">
1138
+ <h3>Screenshot ${i + 1}</h3>
1139
+ <img src="${s}" alt="Screenshot ${i + 1}" />
1140
+ </div>
1141
+ `
1142
+ ).join("")}
1143
+ ` : "";
1144
+ const statusLine = this.session.status ? `<p><strong>Status:</strong> ${this.session.status}</p>` : "";
1145
+ const errorLine = this.session.error ? `<p><strong>Error:</strong> ${this.session.error}</p>` : "";
1146
+ return `
1147
+ <!DOCTYPE html>
1148
+ <html lang="zh-CN">
1149
+ <head>
1150
+ <meta charset="UTF-8">
1151
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
1152
+ <title>Automation Session Report</title>
1153
+ <style>
1154
+ body {
1155
+ font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
1156
+ max-width: 800px;
1157
+ margin: 0 auto;
1158
+ padding: 20px;
1159
+ background: #f5f5f5;
1160
+ }
1161
+ .header {
1162
+ background: white;
1163
+ padding: 20px;
1164
+ border-radius: 8px;
1165
+ margin-bottom: 20px;
1166
+ }
1167
+ .operation {
1168
+ background: white;
1169
+ padding: 15px;
1170
+ border-radius: 8px;
1171
+ margin-bottom: 10px;
1172
+ }
1173
+ .screenshot img {
1174
+ max-width: 100%;
1175
+ border-radius: 8px;
1176
+ }
1177
+ h1 { color: #333; }
1178
+ h2 { color: #555; border-bottom: 1px solid #eee; padding-bottom: 10px; }
1179
+ h3 { color: #666; margin: 0 0 10px 0; }
1180
+ p { margin: 5px 0; color: #666; }
1181
+ </style>
1182
+ </head>
1183
+ <body>
1184
+ <div class="header">
1185
+ <h1>Automation Session Report</h1>
1186
+ <p><strong>Session ID:</strong> ${this.session.id}</p>
1187
+ <p><strong>Started At:</strong> ${this.session.startedAt}</p>
1188
+ <p><strong>Workspace:</strong> ${this.session.workspacePath}</p>
1189
+ <p><strong>Step ID:</strong> ${this.session.stepId}</p>
1190
+ ${statusLine}
1191
+ ${errorLine}
1192
+ </div>
1193
+
1194
+ <h2>Operations (${this.session.operations.length})</h2>
1195
+ ${operationsHtml}
1196
+
1197
+ ${screenshotsHtml}
1198
+ </body>
1199
+ </html>
1200
+ `.trim();
1201
+ }
1202
+ async saveToFile(outputPath, options) {
1203
+ const content = this.generate(options);
1204
+ await fs8.writeFile(outputPath, content, "utf-8");
1205
+ return outputPath;
1206
+ }
1207
+ };
1208
+
1209
+ // src/cli/commands/report.ts
1210
+ var reportCommand = new Command7("report").description("\u751F\u6210\u81EA\u52A8\u5316\u64CD\u4F5C\u62A5\u544A").argument("[workspace]", "workspace \u8DEF\u5F84", ".").option("-f, --format <format>", "\u62A5\u544A\u683C\u5F0F: json, markdown, html", "markdown").option("-s, --session <id>", "\u6307\u5B9A session ID").option("--screenshots", "\u5305\u542B\u622A\u56FE", false).option("-o, --output <path>", "\u8F93\u51FA\u8DEF\u5F84").action(
1211
+ async (workspace, options) => {
1212
+ const workspacePath = path10.resolve(workspace);
1213
+ const logDir = path10.join(workspacePath, "operations");
1214
+ try {
1215
+ let sessionFile;
1216
+ if (options.session) {
1217
+ sessionFile = path10.join(logDir, `operations-${options.session}.jsonl`);
1218
+ } else {
1219
+ const files = await fs9.readdir(logDir);
1220
+ const jsonlFiles = files.filter((f) => f.endsWith(".jsonl")).sort().reverse();
1221
+ if (jsonlFiles.length === 0) {
1222
+ console.error("Error: no operation logs found");
1223
+ process.exit(1);
1224
+ }
1225
+ sessionFile = path10.join(logDir, jsonlFiles[0]);
1226
+ }
1227
+ const content = await fs9.readFile(sessionFile, "utf-8");
1228
+ const lines = content.split("\n").filter((l) => l.trim());
1229
+ const session = JSON.parse(lines[lines.length - 1]);
1230
+ const reporter = new OperationReporter(session);
1231
+ const report = reporter.generate({
1232
+ format: options.format,
1233
+ includeScreenshots: options.screenshots
1234
+ });
1235
+ if (options.output) {
1236
+ await fs9.writeFile(path10.resolve(options.output), report, "utf-8");
1237
+ console.log(`\u2705 Report saved to: ${options.output}`);
1238
+ } else {
1239
+ console.log(report);
1240
+ }
1241
+ } catch (error) {
1242
+ console.error(`Error: ${error}`);
1243
+ process.exit(1);
1244
+ }
1245
+ }
1246
+ );
1247
+
1047
1248
  // src/index.ts
1048
1249
  var require2 = createRequire(import.meta.url);
1049
1250
  var { version } = require2("../package.json");
1050
- var program = new Command7();
1251
+ var program = new Command8();
1051
1252
  program.name("agent-handoff").description("\u8F7B\u91CF\u7EA7\u591A Agent \u534F\u4F5C\u63A5\u529B\u5DE5\u5177").version(version);
1052
1253
  program.addCommand(initCommand);
1053
1254
  program.addCommand(statusCommand);
@@ -1055,5 +1256,6 @@ program.addCommand(nextCommand);
1055
1256
  program.addCommand(validateCommand);
1056
1257
  program.addCommand(advanceCommand);
1057
1258
  program.addCommand(configCommand);
1259
+ program.addCommand(reportCommand);
1058
1260
  program.parse();
1059
1261
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts","../src/cli/commands/init.ts","../src/cli/commands/status.ts","../src/core/workspace.ts","../src/core/workflow-parser.ts","../src/core/state-machine.ts","../src/cli/commands/next.ts","../src/core/prompt-generator.ts","../src/core/clipboard.ts","../src/core/events-writer.ts","../src/cli/commands/validate.ts","../src/core/artifact-validator.ts","../src/cli/commands/advance.ts","../src/cli/commands/config.ts","../src/core/config.ts"],"sourcesContent":["#!/usr/bin/env node\nimport { createRequire } from 'module';\nimport { Command } from 'commander';\nimport { initCommand } from './cli/commands/init.js';\nimport { statusCommand } from './cli/commands/status.js';\nimport { nextCommand } from './cli/commands/next.js';\nimport { validateCommand } from './cli/commands/validate.js';\nimport { advanceCommand } from './cli/commands/advance.js';\nimport { configCommand } from './cli/commands/config.js';\n\nconst require = createRequire(import.meta.url);\nconst { version } = require('../package.json');\n\nconst program = new Command();\n\nprogram\n .name('agent-handoff')\n .description('轻量级多 Agent 协作接力工具')\n .version(version);\n\nprogram.addCommand(initCommand);\nprogram.addCommand(statusCommand);\nprogram.addCommand(nextCommand);\nprogram.addCommand(validateCommand);\nprogram.addCommand(advanceCommand);\nprogram.addCommand(configCommand);\n\nprogram.parse();\n","import { Command } from 'commander';\nimport fs from 'fs/promises';\nimport path from 'path';\n\nexport const initCommand = new Command('init')\n .description('创建新的 workspace')\n .argument('<name>', 'workspace 名称')\n .option('-p, --path <path>', '父目录路径', process.cwd())\n .action(async (name: string, options: { path: string }) => {\n const workspacePath = path.resolve(options.path, name);\n\n try {\n await fs.access(workspacePath);\n console.error(`Error: workspace \"${name}\" already exists at ${workspacePath}`);\n process.exit(1);\n } catch {\n // 目录不存在,继续创建\n }\n\n try {\n await fs.mkdir(workspacePath, { recursive: true });\n await fs.mkdir(path.join(workspacePath, 'steps'), { recursive: true });\n\n const workflowTemplate = `name: ${name}\nsteps:\n - id: clarify\n executor: trae\n input: brief.md\n output: steps/01-clarify/output.md\n acceptance:\n - 澄清需求范围与非目标\n - 产出结构化需求文档\n`;\n\n const stateTemplate = JSON.stringify({\n currentIndex: 0,\n status: 'running',\n updatedAt: new Date().toISOString(),\n }, null, 2);\n\n const briefTemplate = `# brief:需求描述\n\n## 背景\n(请描述项目背景)\n\n## 目标\n(请描述本轮目标)\n\n## 非目标\n(请描述本轮不做的事情)\n\n## 验收标准\n(请描述验收标准)\n`;\n\n await fs.writeFile(path.join(workspacePath, 'workflow.yaml'), workflowTemplate);\n await fs.writeFile(path.join(workspacePath, 'state.json'), stateTemplate);\n await fs.writeFile(path.join(workspacePath, 'brief.md'), briefTemplate);\n\n console.log(`✅ Created workspace \"${name}\" at ${workspacePath}`);\n console.log(`\nNext steps:\n 1. Edit brief.md to describe your requirements\n 2. Run \"agent-handoff status ${name}\" to check workspace status\n 3. Run \"agent-handoff next ${name}\" to get the first step prompt\n`);\n } catch (error) {\n console.error(`Error creating workspace: ${error}`);\n process.exit(1);\n }\n });\n","import { Command } from 'commander';\nimport path from 'path';\nimport { loadWorkspace } from '../../core/workspace.js';\nimport { computeState } from '../../core/state-machine.js';\n\nexport const statusCommand = new Command('status')\n .description('显示 workspace 状态')\n .argument('[workspace]', 'workspace 路径', '.')\n .option('-j, --json', 'JSON 格式输出')\n .action(async (workspace: string, options: { json: boolean }) => {\n const workspacePath = path.resolve(workspace);\n\n try {\n const info = await loadWorkspace(workspacePath);\n\n if (!info.exists) {\n console.error(`Error: workspace not found: ${workspacePath}`);\n process.exit(1);\n }\n\n if (!info.hasWorkflow) {\n console.error(`Error: workflow.yaml not found in ${workspacePath}`);\n process.exit(1);\n }\n\n if (!info.workflow) {\n console.error(`Error: failed to parse workflow.yaml`);\n process.exit(1);\n }\n\n const stateResult = computeState(info.workflow, info.stepOutputs);\n\n if (options.json) {\n const jsonOutput = {\n name: info.workflow.name,\n path: workspacePath,\n status: stateResult.status,\n currentIndex: stateResult.currentIndex,\n totalSteps: info.workflow.steps.length,\n completedSteps: stateResult.completedSteps.length,\n steps: info.workflow.steps.map((step, index) => ({\n index,\n id: step.id,\n executor: step.executor,\n workItemId: step.workItemId,\n completed: info.stepOutputs.get(step.id) ?? false,\n })),\n };\n console.log(JSON.stringify(jsonOutput, null, 2));\n } else {\n console.log(`Workspace: ${info.workflow.name}`);\n console.log(`Status: ${stateResult.status}`);\n console.log('');\n console.log('Steps:');\n\n info.workflow.steps.forEach((step, index) => {\n const completed = info.stepOutputs.get(step.id) ?? false;\n const statusIcon = completed ? '✅' : '⬜';\n const stepNum = String(index + 1).padStart(2, '0');\n let line = ` ${statusIcon} ${stepNum}-${step.id} (${step.executor})`;\n if (step.workItemId) {\n line += ` [${step.workItemId}]`;\n }\n console.log(line);\n });\n\n console.log('');\n if (stateResult.status === 'done') {\n console.log('Current: completed');\n } else {\n const currentStep = info.workflow.steps[stateResult.currentIndex];\n console.log(`Current: step ${stateResult.currentIndex + 1} (${currentStep?.id})`);\n }\n }\n } catch (error) {\n console.error(`Error: ${error}`);\n process.exit(1);\n }\n });\n","import fs from 'fs/promises';\nimport path from 'path';\nimport { Workflow } from './models/workflow.js';\nimport { State } from './models/state.js';\nimport { parseWorkflow } from './workflow-parser.js';\n\nexport interface WorkspaceInfo {\n path: string;\n exists: boolean;\n hasWorkflow: boolean;\n hasState: boolean;\n workflow?: Workflow;\n state?: State;\n stepOutputs: Map<string, boolean>;\n}\n\nexport async function loadWorkspace(workspacePath: string): Promise<WorkspaceInfo> {\n const absolutePath = path.resolve(workspacePath);\n const workflowPath = path.join(absolutePath, 'workflow.yaml');\n const statePath = path.join(absolutePath, 'state.json');\n\n let exists = false;\n let hasWorkflow = false;\n let hasState = false;\n let workflow: Workflow | undefined;\n let state: State | undefined;\n let stepOutputs = new Map<string, boolean>();\n\n try {\n await fs.access(absolutePath);\n exists = true;\n } catch {\n return {\n path: absolutePath,\n exists: false,\n hasWorkflow: false,\n hasState: false,\n stepOutputs,\n };\n }\n\n try {\n await fs.access(workflowPath);\n hasWorkflow = true;\n workflow = await parseWorkflow(workflowPath);\n } catch {\n hasWorkflow = false;\n }\n\n try {\n const stateContent = await fs.readFile(statePath, 'utf-8');\n hasState = true;\n state = JSON.parse(stateContent) as State;\n } catch {\n hasState = false;\n }\n\n if (workflow) {\n stepOutputs = await detectStepOutputs(absolutePath, workflow);\n }\n\n return {\n path: absolutePath,\n exists,\n hasWorkflow,\n hasState,\n workflow,\n state,\n stepOutputs,\n };\n}\n\nexport async function detectStepOutputs(\n workspacePath: string,\n workflow: Workflow\n): Promise<Map<string, boolean>> {\n const outputs = new Map<string, boolean>();\n\n for (const step of workflow.steps) {\n const outputPath = path.join(workspacePath, step.output);\n try {\n const content = await fs.readFile(outputPath, 'utf-8');\n outputs.set(step.id, content.trim().length > 0);\n } catch {\n outputs.set(step.id, false);\n }\n }\n\n return outputs;\n}\n\nexport async function fileExists(filePath: string): Promise<boolean> {\n try {\n await fs.access(filePath);\n return true;\n } catch {\n return false;\n }\n}\n\nexport async function fileNotEmpty(filePath: string): Promise<boolean> {\n try {\n const content = await fs.readFile(filePath, 'utf-8');\n return content.trim().length > 0;\n } catch {\n return false;\n }\n}\n","import fs from 'fs/promises';\nimport YAML from 'yaml';\nimport { Workflow, Step, Executor } from './models/workflow';\n\nexport async function parseWorkflow(filePath: string): Promise<Workflow> {\n const content = await fs.readFile(filePath, 'utf-8');\n const parsed = YAML.parse(content);\n \n if (!parsed || typeof parsed !== 'object') {\n throw new Error(`Invalid workflow.yaml: ${filePath}`);\n }\n \n if (!parsed.name || typeof parsed.name !== 'string') {\n throw new Error('workflow.yaml missing required field: name');\n }\n \n if (!Array.isArray(parsed.steps) || parsed.steps.length === 0) {\n throw new Error('workflow.yaml missing required field: steps (non-empty array)');\n }\n \n const steps: Step[] = parsed.steps.map((step: Record<string, unknown>, index: number) => {\n if (!step.id || typeof step.id !== 'string') {\n throw new Error(`Step ${index} missing required field: id`);\n }\n if (!step.executor || typeof step.executor !== 'string') {\n throw new Error(`Step ${index} missing required field: executor`);\n }\n if (!step.input || typeof step.input !== 'string') {\n throw new Error(`Step ${index} missing required field: input`);\n }\n if (!step.output || typeof step.output !== 'string') {\n throw new Error(`Step ${index} missing required field: output`);\n }\n \n return {\n id: step.id,\n executor: step.executor as Executor,\n input: step.input,\n output: step.output,\n workItemId: step.workItemId as string | undefined,\n acceptance: step.acceptance as string[] | undefined,\n };\n });\n \n return {\n name: parsed.name,\n steps,\n };\n}\n\nexport function validateWorkflow(workflow: Workflow): string[] {\n const errors: string[] = [];\n \n if (!workflow.name || workflow.name.trim() === '') {\n errors.push('workflow.name is required');\n }\n \n if (!workflow.steps || workflow.steps.length === 0) {\n errors.push('workflow.steps is required and must be non-empty');\n return errors;\n }\n \n workflow.steps.forEach((step, index) => {\n if (!step.id || step.id.trim() === '') {\n errors.push(`steps[${index}].id is required`);\n }\n if (!step.executor) {\n errors.push(`steps[${index}].executor is required`);\n }\n if (!step.input || step.input.trim() === '') {\n errors.push(`steps[${index}].input is required`);\n }\n if (!step.output || step.output.trim() === '') {\n errors.push(`steps[${index}].output is required`);\n }\n if (!step.output.startsWith('steps/')) {\n errors.push(`steps[${index}].output should start with 'steps/'`);\n }\n });\n \n return errors;\n}\n","import { Workflow } from './models/workflow';\nimport { State, WorkflowStatus } from './models/state';\n\nexport interface StateMachineResult {\n currentIndex: number;\n status: WorkflowStatus;\n nextStepIndex: number | null;\n completedSteps: number[];\n pendingSteps: number[];\n}\n\nexport function computeState(\n workflow: Workflow,\n stepOutputs: Map<string, boolean>\n): StateMachineResult {\n if (!workflow.steps || workflow.steps.length === 0) {\n return {\n currentIndex: 0,\n status: 'done',\n nextStepIndex: null,\n completedSteps: [],\n pendingSteps: [],\n };\n }\n\n const completedSteps: number[] = [];\n const pendingSteps: number[] = [];\n let currentIndex = 0;\n let status: WorkflowStatus = 'running';\n\n for (let i = 0; i < workflow.steps.length; i++) {\n const step = workflow.steps[i];\n const outputExists = stepOutputs.get(step.id) ?? false;\n\n if (outputExists) {\n completedSteps.push(i);\n } else {\n pendingSteps.push(i);\n }\n }\n\n const firstPendingIndex = pendingSteps[0];\n\n if (firstPendingIndex === undefined) {\n currentIndex = workflow.steps.length;\n status = 'done';\n } else {\n currentIndex = firstPendingIndex;\n status = 'running';\n }\n\n return {\n currentIndex,\n status,\n nextStepIndex: status === 'done' ? null : currentIndex,\n completedSteps,\n pendingSteps,\n };\n}\n\nexport function advanceState(\n state: State,\n workflow: Workflow,\n stepOutputs: Map<string, boolean>\n): State {\n const result = computeState(workflow, stepOutputs);\n\n return {\n ...state,\n currentIndex: result.currentIndex,\n status: result.status,\n updatedAt: new Date().toISOString(),\n };\n}\n\nexport function isWorkflowComplete(\n workflow: Workflow,\n stepOutputs: Map<string, boolean>\n): boolean {\n if (!workflow.steps || workflow.steps.length === 0) {\n return true;\n }\n\n return workflow.steps.every((step) => stepOutputs.get(step.id) === true);\n}\n\nexport function getCurrentStep(\n workflow: Workflow,\n stepOutputs: Map<string, boolean>\n): { index: number; step: typeof workflow.steps[0] } | null {\n const result = computeState(workflow, stepOutputs);\n\n if (result.status === 'done' || result.nextStepIndex === null) {\n return null;\n }\n\n return {\n index: result.nextStepIndex,\n step: workflow.steps[result.nextStepIndex],\n };\n}\n","import { Command } from 'commander';\nimport path from 'path';\nimport { loadWorkspace } from '../../core/workspace.js';\nimport { computeState, getCurrentStep } from '../../core/state-machine.js';\nimport { generatePrompt } from '../../core/prompt-generator.js';\nimport { copyToClipboard, isClipboardSupported } from '../../core/clipboard.js';\nimport { writeEvent } from '../../core/events-writer.js';\n\nexport const nextCommand = new Command('next')\n .description('输出下一步执行指令和 prompt')\n .argument('[workspace]', 'workspace 路径', '.')\n .option('-c, --copy', '复制 prompt 到剪贴板')\n .option('--no-event', '不写入事件日志')\n .action(async (workspace: string, options: { copy: boolean; event: boolean }) => {\n const workspacePath = path.resolve(workspace);\n\n try {\n const info = await loadWorkspace(workspacePath);\n\n if (!info.exists) {\n console.error(`Error: workspace not found: ${workspacePath}`);\n process.exit(1);\n }\n\n if (!info.hasWorkflow) {\n console.error(`Error: workflow.yaml not found in ${workspacePath}`);\n process.exit(1);\n }\n\n if (!info.workflow) {\n console.error(`Error: failed to parse workflow.yaml`);\n process.exit(1);\n }\n\n const stateResult = computeState(info.workflow, info.stepOutputs);\n\n if (stateResult.status === 'done') {\n console.log(`Workflow \"${info.workflow.name}\" 已完成所有步骤。`);\n console.log('无下一步操作。');\n return;\n }\n\n const currentStep = getCurrentStep(info.workflow, info.stepOutputs);\n\n if (!currentStep) {\n console.log(`Workflow \"${info.workflow.name}\" 已完成所有步骤。`);\n console.log('无下一步操作。');\n return;\n }\n\n const { step, index } = currentStep;\n\n console.log(`Step: ${step.id}`);\n console.log(`Executor: ${step.executor}`);\n if (step.workItemId) {\n console.log(`Work Item: ${step.workItemId}`);\n }\n console.log('');\n console.log('Input:');\n console.log(` - ${step.input}`);\n console.log('');\n console.log('Output:');\n console.log(` - ${step.output}`);\n console.log('');\n console.log('Prompt:');\n console.log('────────────────────────────────────────');\n\n const prompt = generatePrompt({\n workflow: info.workflow,\n step,\n stepIndex: index,\n workspacePath: info.path,\n });\n\n console.log(prompt);\n console.log('────────────────────────────────────────');\n console.log('');\n\n if (options.event) {\n await writeEvent({\n workspacePath,\n step: { index: index + 1, id: step.id },\n type: 'step.started',\n summary: `开始执行步骤: ${step.id}`,\n workItemId: step.workItemId,\n links: [step.input],\n });\n }\n\n if (options.copy) {\n if (!isClipboardSupported()) {\n console.log('⚠️ 剪贴板功能在当前环境不可用');\n console.log('请手动复制上面的 Prompt');\n } else {\n const result = await copyToClipboard(prompt);\n if (result.success) {\n console.log('✅ Prompt 已复制到剪贴板');\n } else {\n console.log(`❌ 复制失败: ${result.error}`);\n console.log('请手动复制上面的 Prompt');\n }\n }\n } else {\n console.log('提示:将上述 Prompt 复制到 TRAE 新 Task 中执行');\n console.log(' 使用 --copy 选项可自动复制到剪贴板');\n }\n } catch (error) {\n console.error(`Error: ${error}`);\n process.exit(1);\n }\n });\n","import { Workflow, Step } from './models/workflow.js';\n\nexport interface PromptContext {\n workflow: Workflow;\n step: Step;\n stepIndex: number;\n workspacePath: string;\n}\n\nexport function generatePrompt(context: PromptContext): string {\n const { workflow, step, stepIndex } = context;\n const totalSteps = workflow.steps.length;\n const stepNum = stepIndex + 1;\n\n let prompt = `# 任务:${step.id}\n\n## 上下文\n- Workflow: ${workflow.name}\n- Step: ${stepNum} / ${totalSteps}\n- Executor: ${step.executor}`;\n\n if (step.workItemId) {\n prompt += `\\n- Work Item: ${step.workItemId}`;\n }\n\n prompt += `\n\n## 输入产物\n请阅读以下输入产物:\n- ${step.input}\n\n## 输出产物\n请将结果写入:\n- ${step.output}`;\n\n if (step.acceptance && step.acceptance.length > 0) {\n prompt += `\n\n## 验收标准`;\n for (const criteria of step.acceptance) {\n prompt += `\\n- ${criteria}`;\n }\n }\n\n prompt += `\n\n## 输出要求\n完成后请在 output.md 中包含以下区块:\n- 产物更新\n- 关键决策\n- 风险与待确认\n- 下一步交接\n\n---\nAgentHandoff Step Prompt`;\n\n return prompt;\n}\n","import clipboard from 'clipboardy';\n\nexport interface ClipboardResult {\n success: boolean;\n error?: string;\n}\n\nlet clipboardSupported: boolean | null = null;\n\nexport function isClipboardSupported(): boolean {\n if (clipboardSupported !== null) {\n return clipboardSupported;\n }\n\n try {\n clipboardSupported = true;\n return true;\n } catch {\n clipboardSupported = false;\n return false;\n }\n}\n\nexport async function copyToClipboard(text: string): Promise<ClipboardResult> {\n try {\n await clipboard.write(text);\n return { success: true };\n } catch (error) {\n const errorMessage = error instanceof Error ? error.message : String(error);\n return {\n success: false,\n error: errorMessage,\n };\n }\n}\n\nexport async function readFromClipboard(): Promise<string> {\n try {\n return await clipboard.read();\n } catch {\n return '';\n }\n}\n","import fs from 'fs/promises';\nimport path from 'path';\nimport { Event, EventType, EventStep } from './models/event.js';\n\nexport interface WriteEventOptions {\n workspacePath: string;\n step: EventStep;\n type: EventType;\n summary: string;\n workItemId?: string;\n links?: string[];\n}\n\nexport interface EventsWriterResult {\n success: boolean;\n event: Event;\n error?: string;\n}\n\nexport async function writeEvent(options: WriteEventOptions): Promise<EventsWriterResult> {\n const { workspacePath, step, type, summary, workItemId, links } = options;\n\n const event: Event = {\n ts: new Date().toISOString(),\n step,\n type,\n summary,\n ...(workItemId && { workItemId }),\n ...(links && links.length > 0 && { links }),\n };\n\n try {\n const eventsPath = path.join(workspacePath, 'events.jsonl');\n const line = JSON.stringify(event) + '\\n';\n await fs.appendFile(eventsPath, line, 'utf-8');\n\n return {\n success: true,\n event,\n };\n } catch (error) {\n const errorMessage = error instanceof Error ? error.message : String(error);\n return {\n success: false,\n event,\n error: errorMessage,\n };\n }\n}\n\nexport async function readEvents(workspacePath: string): Promise<Event[]> {\n const eventsPath = path.join(workspacePath, 'events.jsonl');\n\n try {\n const content = await fs.readFile(eventsPath, 'utf-8');\n const lines = content.split('\\n').filter((line) => line.trim());\n\n const events: Event[] = [];\n for (const line of lines) {\n try {\n const event = JSON.parse(line) as Event;\n events.push(event);\n } catch {\n // Skip invalid lines\n }\n }\n\n return events;\n } catch {\n return [];\n }\n}\n\nexport async function getLatestEvent(workspacePath: string): Promise<Event | null> {\n const events = await readEvents(workspacePath);\n if (events.length === 0) {\n return null;\n }\n return events[events.length - 1];\n}\n\nexport async function getEventsByStep(workspacePath: string, stepId: string): Promise<Event[]> {\n const events = await readEvents(workspacePath);\n return events.filter((event) => event.step.id === stepId);\n}\n\nexport async function getEventsByType(workspacePath: string, type: EventType): Promise<Event[]> {\n const events = await readEvents(workspacePath);\n return events.filter((event) => event.type === type);\n}\n\nexport async function getEventsByWorkItem(\n workspacePath: string,\n workItemId: string\n): Promise<Event[]> {\n const events = await readEvents(workspacePath);\n return events.filter((event) => event.workItemId === workItemId);\n}\n","import { Command } from 'commander';\nimport path from 'path';\nimport { loadWorkspace } from '../../core/workspace.js';\nimport { validateWorkspaceArtifacts } from '../../core/artifact-validator.js';\n\nexport const validateCommand = new Command('validate')\n .description('校验 workspace 产物结构')\n .argument('[workspace]', 'workspace 路径', '.')\n .option('--strict', '严格模式(将警告视为错误)')\n .option('-j, --json', 'JSON 格式输出')\n .action(async (workspace: string, options: { strict: boolean; json: boolean }) => {\n const workspacePath = path.resolve(workspace);\n\n try {\n const info = await loadWorkspace(workspacePath);\n\n if (!info.exists) {\n console.error(`Error: workspace not found: ${workspacePath}`);\n process.exit(1);\n }\n\n if (!info.hasWorkflow) {\n console.error(`Error: workflow.yaml not found in ${workspacePath}`);\n process.exit(1);\n }\n\n if (!info.workflow) {\n console.error(`Error: failed to parse workflow.yaml`);\n process.exit(1);\n }\n\n const result = await validateWorkspaceArtifacts(workspacePath);\n\n if (options.json) {\n const jsonOutput = {\n valid: options.strict ? result.valid && result.warningCount === 0 : result.valid,\n workspace: workspacePath,\n totalSteps: result.totalSteps,\n validSteps: result.validSteps,\n errorCount: result.errorCount,\n warningCount: result.warningCount,\n steps: Array.from(result.stepResults.entries()).map(([stepId, stepResult]) => ({\n stepId,\n valid: options.strict ? stepResult.valid && stepResult.warnings.length === 0 : stepResult.valid,\n errors: stepResult.errors,\n warnings: stepResult.warnings,\n })),\n };\n console.log(JSON.stringify(jsonOutput, null, 2));\n } else {\n console.log(`Workspace: ${info.workflow.name}`);\n console.log('');\n\n for (const step of info.workflow.steps) {\n const stepResult = result.stepResults.get(step.id);\n if (!stepResult) continue;\n\n const icon = stepResult.valid ? '✅' : '❌';\n console.log(`${icon} ${step.output} - ${stepResult.valid ? 'Valid' : 'Invalid'}`);\n\n if (!stepResult.valid) {\n for (const error of stepResult.errors) {\n console.log(` - ${error.message}`);\n }\n }\n\n if (stepResult.warnings.length > 0) {\n for (const warning of stepResult.warnings) {\n console.log(` ⚠️ ${warning.message}`);\n }\n }\n }\n\n console.log('');\n\n const hasErrors = result.errorCount > 0;\n const hasWarnings = result.warningCount > 0;\n const strictFail = options.strict && hasWarnings;\n\n if (!hasErrors && !strictFail) {\n console.log('All artifacts validated successfully.');\n if (hasWarnings) {\n console.log(`⚠️ ${result.warningCount} warning(s) found.`);\n }\n } else {\n const totalErrors = result.errorCount + (strictFail ? result.warningCount : 0);\n console.log(`Validation failed with ${totalErrors} error(s).`);\n }\n\n if (hasErrors || strictFail) {\n process.exit(1);\n }\n }\n } catch (error) {\n console.error(`Error: ${error}`);\n process.exit(1);\n }\n });\n","import fs from 'fs/promises';\nimport path from 'path';\nimport { loadWorkspace } from './workspace.js';\n\nexport interface ValidationResult {\n valid: boolean;\n errors: ValidationError[];\n warnings: ValidationWarning[];\n}\n\nexport interface ValidationError {\n type: 'missing_section' | 'empty_section' | 'invalid_format';\n section: string;\n message: string;\n}\n\nexport interface ValidationWarning {\n type: 'short_content' | 'missing_detail';\n section: string;\n message: string;\n}\n\nexport const REQUIRED_SECTIONS = [\n '产物更新',\n '关键决策',\n '风险与待确认',\n '下一步交接',\n] as const;\n\nexport type RequiredSection = (typeof REQUIRED_SECTIONS)[number];\n\nexport interface WorkspaceValidationResult {\n valid: boolean;\n stepResults: Map<string, ValidationResult>;\n totalSteps: number;\n validSteps: number;\n errorCount: number;\n warningCount: number;\n}\n\nconst MIN_CONTENT_LENGTH = 10;\n\nexport function validateArtifact(content: string): ValidationResult {\n const errors: ValidationError[] = [];\n const warnings: ValidationWarning[] = [];\n\n for (const section of REQUIRED_SECTIONS) {\n const sectionResult = findSection(content, section);\n\n if (!sectionResult.found) {\n errors.push({\n type: 'missing_section',\n section,\n message: `缺少必要区块: ${section}`,\n });\n } else if (!sectionResult.hasContent) {\n errors.push({\n type: 'empty_section',\n section,\n message: `区块内容为空: ${section}`,\n });\n } else if (sectionResult.contentLength < MIN_CONTENT_LENGTH) {\n warnings.push({\n type: 'short_content',\n section,\n message: `区块内容过短 (${sectionResult.contentLength} 字符): ${section}`,\n });\n }\n }\n\n return {\n valid: errors.length === 0,\n errors,\n warnings,\n };\n}\n\ninterface SectionResult {\n found: boolean;\n hasContent: boolean;\n contentLength: number;\n}\n\nfunction findSection(content: string, sectionName: string): SectionResult {\n const patterns = [\n new RegExp(`^##\\\\s+${escapeRegex(sectionName)}[^\\\\n]*$`, 'm'),\n new RegExp(`^###\\\\s+${escapeRegex(sectionName)}[^\\\\n]*$`, 'm'),\n ];\n\n let matchIndex = -1;\n let matchLength = 0;\n\n for (const pattern of patterns) {\n const match = content.match(pattern);\n if (match && match.index !== undefined) {\n matchIndex = match.index;\n matchLength = match[0].length;\n break;\n }\n }\n\n if (matchIndex === -1) {\n return { found: false, hasContent: false, contentLength: 0 };\n }\n\n const contentStart = matchIndex + matchLength;\n const remainingContent = content.slice(contentStart);\n\n const nextSectionMatch = remainingContent.match(/^#{1,3}\\s+/m);\n const sectionContent = nextSectionMatch\n ? remainingContent.slice(0, nextSectionMatch.index)\n : remainingContent;\n\n const trimmedContent = sectionContent.trim();\n\n return {\n found: true,\n hasContent: trimmedContent.length > 0,\n contentLength: trimmedContent.length,\n };\n}\n\nfunction escapeRegex(str: string): string {\n return str.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&');\n}\n\nexport async function validateArtifactFile(\n filePath: string\n): Promise<ValidationResult> {\n try {\n const content = await fs.readFile(filePath, 'utf-8');\n return validateArtifact(content);\n } catch (error) {\n return {\n valid: false,\n errors: [\n {\n type: 'invalid_format',\n section: '',\n message: `无法读取文件: ${filePath}`,\n },\n ],\n warnings: [],\n };\n }\n}\n\nexport async function validateWorkspaceArtifacts(\n workspacePath: string\n): Promise<WorkspaceValidationResult> {\n const workspace = await loadWorkspace(workspacePath);\n const stepResults = new Map<string, ValidationResult>();\n let validSteps = 0;\n let errorCount = 0;\n let warningCount = 0;\n\n if (!workspace.workflow) {\n return {\n valid: false,\n stepResults,\n totalSteps: 0,\n validSteps: 0,\n errorCount: 1,\n warningCount: 0,\n };\n }\n\n for (const step of workspace.workflow.steps) {\n const outputPath = path.join(workspace.path, step.output);\n const result = await validateArtifactFile(outputPath);\n stepResults.set(step.id, result);\n\n if (result.valid) {\n validSteps++;\n }\n errorCount += result.errors.length;\n warningCount += result.warnings.length;\n }\n\n return {\n valid: errorCount === 0,\n stepResults,\n totalSteps: workspace.workflow.steps.length,\n validSteps,\n errorCount,\n warningCount,\n };\n}\n","import { Command } from 'commander';\nimport path from 'path';\nimport fs from 'fs/promises';\nimport { loadWorkspace } from '../../core/workspace.js';\nimport { computeState, getCurrentStep } from '../../core/state-machine.js';\nimport { writeEvent } from '../../core/events-writer.js';\nimport { EventType } from '../../core/models/event.js';\n\nexport const advanceCommand = new Command('advance')\n .description('推进 workspace 状态')\n .argument('[workspace]', 'workspace 路径', '.')\n .option('-e, --event <type>', '事件类型', 'step.done')\n .option('-s, --summary <text>', '事件摘要')\n .option('--no-state', '不更新 state.json')\n .option('--skip-event', '不写入事件日志')\n .action(\n async (\n workspace: string,\n options: { event: string; summary?: string; state: boolean; skipEvent: boolean }\n ) => {\n const workspacePath = path.resolve(workspace);\n\n try {\n const info = await loadWorkspace(workspacePath);\n\n if (!info.exists) {\n console.error(`Error: workspace not found: ${workspacePath}`);\n process.exit(1);\n }\n\n if (!info.hasWorkflow) {\n console.error(`Error: workflow.yaml not found in ${workspacePath}`);\n process.exit(1);\n }\n\n if (!info.workflow) {\n console.error(`Error: failed to parse workflow.yaml`);\n process.exit(1);\n }\n\n const stateResult = computeState(info.workflow, info.stepOutputs);\n\n console.log(`Workspace: ${info.workflow.name}`);\n\n if (stateResult.status === 'done') {\n console.log('Status: done');\n console.log('');\n console.log('⚠️ Workflow already completed. No steps to advance.');\n return;\n }\n\n const currentStep = getCurrentStep(info.workflow, info.stepOutputs);\n\n if (!currentStep) {\n console.log('Status: done');\n console.log('');\n console.log('⚠️ Workflow already completed. No steps to advance.');\n return;\n }\n\n const { step, index } = currentStep;\n\n console.log(`Current step: ${step.id} (index: ${index})`);\n console.log('');\n\n const eventType = options.event as EventType;\n const eventSummary = options.summary || getDefaultSummary(eventType, step.id);\n\n if (!options.skipEvent) {\n const result = await writeEvent({\n workspacePath,\n step: { index: index + 1, id: step.id },\n type: eventType,\n summary: eventSummary,\n workItemId: step.workItemId,\n links: [step.output],\n });\n\n if (result.success) {\n console.log(`✅ Event written: ${eventType}`);\n console.log(` Summary: ${eventSummary}`);\n if (step.workItemId) {\n console.log(` Work Item: ${step.workItemId}`);\n }\n if (step.output) {\n console.log(` Links: ${step.output}`);\n }\n } else {\n console.log(`❌ Failed to write event: ${result.error}`);\n }\n }\n\n if (options.state) {\n const statePath = path.join(workspacePath, 'state.json');\n const newIndex = index + 1;\n const isDone = newIndex >= info.workflow.steps.length;\n\n const newState = {\n currentIndex: newIndex,\n status: isDone ? 'done' : 'running',\n updatedAt: new Date().toISOString(),\n };\n\n await fs.writeFile(statePath, JSON.stringify(newState, null, 2));\n console.log('');\n console.log(`✅ State updated: ${statePath}`);\n console.log(` Current index: ${newState.currentIndex}`);\n console.log(` Status: ${newState.status}`);\n\n if (isDone) {\n console.log('');\n console.log('🎉 Workflow completed!');\n } else {\n const nextStep = info.workflow.steps[newIndex];\n console.log(` Next step: ${nextStep.id}`);\n }\n }\n } catch (error) {\n console.error(`Error: ${error}`);\n process.exit(1);\n }\n }\n );\n\nfunction getDefaultSummary(eventType: EventType, stepId: string): string {\n const summaries: Record<EventType, string> = {\n 'step.started': `开始执行步骤: ${stepId}`,\n 'step.done': `步骤完成: ${stepId}`,\n 'artifact.updated': '产物已更新',\n 'workflow.updated': '工作流已更新',\n 'verify.passed': '验证通过',\n 'verify.failed': '验证失败',\n 'accept.passed': '验收通过',\n 'accept.failed': '验收失败',\n 'issue.raised': '发现问题',\n 'handoff.sent': '已交接给下一步',\n };\n return summaries[eventType] || `事件: ${eventType}`;\n}\n","import { Command } from 'commander';\nimport path from 'path';\nimport os from 'os';\nimport {\n loadConfig,\n findConfigFile,\n initConfigFile,\n DEFAULT_CONFIG,\n} from '../../core/config.js';\n\nexport const configCommand = new Command('config')\n .description('查看或管理配置')\n .argument('[action]', '操作: show, init', 'show')\n .option('-g, --global', '操作全局配置')\n .option('--verbose', '显示详细信息')\n .action(async (action: string, options: { global: boolean; verbose: boolean }) => {\n try {\n if (action === 'show') {\n await showConfig(options);\n } else if (action === 'init') {\n await initConfig(options);\n } else if (action === 'list') {\n await listConfig(options);\n } else {\n console.error(`Unknown action: ${action}`);\n console.log('Available actions: show, init, list');\n process.exit(1);\n }\n } catch (error) {\n console.error(`Error: ${error}`);\n process.exit(1);\n }\n });\n\nasync function showConfig(options: { global: boolean; verbose: boolean }): Promise<void> {\n const targetPath = options.global ? os.homedir() : process.cwd();\n const config = await loadConfig(targetPath);\n\n if (options.verbose) {\n const configFile = await findConfigFile(targetPath);\n if (configFile) {\n console.log(`Config file: ${configFile}`);\n console.log('');\n } else {\n console.log('No config file found, using defaults');\n console.log('');\n }\n }\n\n console.log(JSON.stringify(config, null, 2));\n}\n\nasync function initConfig(options: { global: boolean; verbose: boolean }): Promise<void> {\n const targetPath = options.global ? os.homedir() : process.cwd();\n const configPath = await initConfigFile(targetPath, options.global);\n\n console.log(`✅ Created config file: ${configPath}`);\n console.log('');\n console.log('Default configuration:');\n console.log(JSON.stringify(DEFAULT_CONFIG, null, 2));\n}\n\nasync function listConfig(options: { global: boolean; verbose: boolean }): Promise<void> {\n console.log('Configuration options:');\n console.log('');\n console.log(' defaultWorkspace - 默认 workspace 路径');\n console.log(' events.enabled - 是否启用事件日志 (default: true)');\n console.log(' events.logStepStarted - 是否记录 step.started (default: true)');\n console.log(' events.logStepDone - 是否记录 step.done (default: true)');\n console.log(' clipboard.autoCopy - 是否自动复制 prompt (default: false)');\n console.log(' prompt.templatePath - 自定义 prompt 模板路径');\n console.log(' prompt.language - prompt 语言 (default: zh)');\n console.log(' validation.strict - 严格校验模式 (default: false)');\n console.log(' validation.warnOnShortContent - 内容过短时警告 (default: true)');\n console.log('');\n console.log('Config file locations (in order of priority):');\n console.log(' .agenthandoffrc');\n console.log(' .agenthandoffrc.json');\n console.log(' .agenthandoffrc.yaml');\n console.log(' package.json#agenthandoff');\n console.log(` ~/.agenthandoffrc (global)`);\n}\n","import fs from 'fs/promises';\nimport path from 'path';\nimport os from 'os';\n\nexport interface AgentHandoffConfig {\n defaultWorkspace?: string;\n events?: {\n enabled: boolean;\n logStepStarted: boolean;\n logStepDone: boolean;\n };\n clipboard?: {\n autoCopy: boolean;\n };\n prompt?: {\n templatePath?: string;\n language: 'zh' | 'en';\n };\n validation?: {\n strict: boolean;\n warnOnShortContent: boolean;\n };\n}\n\nexport const DEFAULT_CONFIG: AgentHandoffConfig = {\n events: {\n enabled: true,\n logStepStarted: true,\n logStepDone: true,\n },\n clipboard: {\n autoCopy: false,\n },\n prompt: {\n language: 'zh',\n },\n validation: {\n strict: false,\n warnOnShortContent: true,\n },\n};\n\nconst CONFIG_FILES = [\n '.agenthandoffrc',\n '.agenthandoffrc.json',\n '.agenthandoffrc.yaml',\n '.agenthandoffrc.yml',\n];\n\nconst configCache = new Map<string, AgentHandoffConfig>();\n\nexport async function findConfigFile(startPath: string): Promise<string | null> {\n let currentPath = path.resolve(startPath);\n const homePath = os.homedir();\n\n while (true) {\n for (const configFile of CONFIG_FILES) {\n const filePath = path.join(currentPath, configFile);\n try {\n await fs.access(filePath);\n return filePath;\n } catch {\n // File doesn't exist, continue\n }\n }\n\n const packageJsonPath = path.join(currentPath, 'package.json');\n try {\n const content = await fs.readFile(packageJsonPath, 'utf-8');\n const pkg = JSON.parse(content);\n if (pkg.agenthandoff) {\n return packageJsonPath;\n }\n } catch {\n // File doesn't exist or invalid, continue\n }\n\n if (currentPath === homePath || currentPath === path.dirname(currentPath)) {\n break;\n }\n currentPath = path.dirname(currentPath);\n }\n\n return null;\n}\n\nexport async function loadConfigFile(filePath: string): Promise<Partial<AgentHandoffConfig>> {\n try {\n const content = await fs.readFile(filePath, 'utf-8');\n const ext = path.extname(filePath);\n\n if (ext === '.yaml' || ext === '.yml') {\n return parseYaml(content);\n }\n\n if (filePath.endsWith('package.json')) {\n const pkg = JSON.parse(content);\n return pkg.agenthandoff || {};\n }\n\n return JSON.parse(content);\n } catch {\n return {};\n }\n}\n\nfunction parseYaml(content: string): Record<string, unknown> {\n const result: Record<string, unknown> = {};\n const lines = content.split('\\n');\n let currentObj: Record<string, unknown> = result;\n const stack: Array<{ obj: Record<string, unknown> }> = [];\n\n for (const line of lines) {\n if (!line.trim() || line.trim().startsWith('#')) {\n continue;\n }\n\n const indent = line.search(/\\S/);\n const trimmed = line.trim();\n\n if (trimmed.includes(':')) {\n const colonIndex = trimmed.indexOf(':');\n const key = trimmed.slice(0, colonIndex).trim();\n const value = trimmed.slice(colonIndex + 1).trim();\n\n if (value === '') {\n if (stack.length > 0) {\n const expectedIndent = stack.length * 2;\n if (indent < expectedIndent) {\n while (stack.length > 0 && indent < stack.length * 2) {\n stack.pop();\n }\n if (stack.length > 0) {\n currentObj = stack[stack.length - 1].obj as Record<string, unknown>;\n } else {\n currentObj = result;\n }\n }\n }\n\n const newObj: Record<string, unknown> = {};\n currentObj[key] = newObj;\n stack.push({ obj: currentObj });\n currentObj = newObj;\n } else {\n let parsedValue: unknown = value;\n if (value === 'true') parsedValue = true;\n else if (value === 'false') parsedValue = false;\n else if (value === 'null') parsedValue = null;\n else if (/^\\d+$/.test(value)) parsedValue = parseInt(value, 10);\n else if (/^\\d+\\.\\d+$/.test(value)) parsedValue = parseFloat(value);\n else if (value.startsWith('\"') && value.endsWith('\"')) {\n parsedValue = value.slice(1, -1);\n } else if (value.startsWith(\"'\") && value.endsWith(\"'\")) {\n parsedValue = value.slice(1, -1);\n }\n\n currentObj[key] = parsedValue;\n }\n }\n }\n\n return result;\n}\n\nexport function mergeConfig(\n base: AgentHandoffConfig,\n override: Partial<AgentHandoffConfig>\n): AgentHandoffConfig {\n const result: AgentHandoffConfig = JSON.parse(JSON.stringify(base));\n\n for (const key of Object.keys(override) as Array<keyof AgentHandoffConfig>) {\n const overrideValue = override[key];\n if (overrideValue === undefined) continue;\n\n if (\n typeof overrideValue === 'object' &&\n overrideValue !== null &&\n !Array.isArray(overrideValue)\n ) {\n const baseValue = result[key];\n if (\n typeof baseValue === 'object' &&\n baseValue !== null &&\n !Array.isArray(baseValue)\n ) {\n // Deep merge for nested objects\n (result as Record<string, unknown>)[key] = mergeConfig(\n baseValue as AgentHandoffConfig,\n overrideValue as Partial<AgentHandoffConfig>\n );\n } else {\n (result as Record<string, unknown>)[key] = overrideValue;\n }\n } else {\n (result as Record<string, unknown>)[key] = overrideValue;\n }\n }\n\n return result;\n}\n\nexport async function loadConfig(workspacePath?: string): Promise<AgentHandoffConfig> {\n const startPath = workspacePath ? path.resolve(workspacePath) : process.cwd();\n const cacheKey = startPath;\n\n if (configCache.has(cacheKey)) {\n return configCache.get(cacheKey)!;\n }\n\n let config = JSON.parse(JSON.stringify(DEFAULT_CONFIG)) as AgentHandoffConfig;\n\n const globalConfigPath = path.join(os.homedir(), '.agenthandoffrc');\n try {\n await fs.access(globalConfigPath);\n const globalConfig = await loadConfigFile(globalConfigPath);\n config = mergeConfig(config, globalConfig);\n } catch {\n // Global config doesn't exist\n }\n\n const localConfigFile = await findConfigFile(startPath);\n if (localConfigFile) {\n const localConfig = await loadConfigFile(localConfigFile);\n config = mergeConfig(config, localConfig);\n }\n\n configCache.set(cacheKey, config);\n return config;\n}\n\nexport function clearConfigCache(): void {\n configCache.clear();\n}\n\nexport async function initConfigFile(targetPath: string, global = false): Promise<string> {\n const configPath = global\n ? path.join(os.homedir(), '.agenthandoffrc')\n : path.join(targetPath, '.agenthandoffrc');\n\n const content = JSON.stringify(DEFAULT_CONFIG, null, 2);\n await fs.writeFile(configPath, content, 'utf-8');\n\n return configPath;\n}\n"],"mappings":"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","names":["Command","Command","path","fs","path","fs","path","fs","Command","path","Command","path","fs","path","Command","path","Command","path","fs","path","fs","path","Command","path","Command","path","fs","Command","path","fs","Command","os","fs","path","path","fs","Command","os","require","Command"]}
1
+ {"version":3,"sources":["../src/index.ts","../src/cli/commands/init.ts","../src/cli/commands/status.ts","../src/core/workspace.ts","../src/core/workflow-parser.ts","../src/core/state-machine.ts","../src/cli/commands/next.ts","../src/core/prompt-generator.ts","../src/core/clipboard.ts","../src/core/events-writer.ts","../src/cli/commands/validate.ts","../src/core/artifact-validator.ts","../src/cli/commands/advance.ts","../src/cli/commands/config.ts","../src/core/config.ts","../src/cli/commands/report.ts","../src/adapters/trae/operation-reporter.ts"],"sourcesContent":["#!/usr/bin/env node\nimport { createRequire } from 'module';\nimport { Command } from 'commander';\nimport { initCommand } from './cli/commands/init.js';\nimport { statusCommand } from './cli/commands/status.js';\nimport { nextCommand } from './cli/commands/next.js';\nimport { validateCommand } from './cli/commands/validate.js';\nimport { advanceCommand } from './cli/commands/advance.js';\nimport { configCommand } from './cli/commands/config.js';\nimport { reportCommand } from './cli/commands/report.js';\n\nconst require = createRequire(import.meta.url);\nconst { version } = require('../package.json');\n\nconst program = new Command();\n\nprogram\n .name('agent-handoff')\n .description('轻量级多 Agent 协作接力工具')\n .version(version);\n\nprogram.addCommand(initCommand);\nprogram.addCommand(statusCommand);\nprogram.addCommand(nextCommand);\nprogram.addCommand(validateCommand);\nprogram.addCommand(advanceCommand);\nprogram.addCommand(configCommand);\nprogram.addCommand(reportCommand);\n\nprogram.parse();\n","import { Command } from 'commander';\nimport fs from 'fs/promises';\nimport path from 'path';\n\nexport const initCommand = new Command('init')\n .description('创建新的 workspace')\n .argument('<name>', 'workspace 名称')\n .option('-p, --path <path>', '父目录路径', process.cwd())\n .action(async (name: string, options: { path: string }) => {\n const workspacePath = path.resolve(options.path, name);\n\n try {\n await fs.access(workspacePath);\n console.error(`Error: workspace \"${name}\" already exists at ${workspacePath}`);\n process.exit(1);\n } catch {\n // 目录不存在,继续创建\n }\n\n try {\n await fs.mkdir(workspacePath, { recursive: true });\n await fs.mkdir(path.join(workspacePath, 'steps'), { recursive: true });\n\n const workflowTemplate = `name: ${name}\nsteps:\n - id: clarify\n executor: trae\n input: brief.md\n output: steps/01-clarify/output.md\n acceptance:\n - 澄清需求范围与非目标\n - 产出结构化需求文档\n`;\n\n const stateTemplate = JSON.stringify({\n currentIndex: 0,\n status: 'running',\n updatedAt: new Date().toISOString(),\n }, null, 2);\n\n const briefTemplate = `# brief:需求描述\n\n## 背景\n(请描述项目背景)\n\n## 目标\n(请描述本轮目标)\n\n## 非目标\n(请描述本轮不做的事情)\n\n## 验收标准\n(请描述验收标准)\n`;\n\n await fs.writeFile(path.join(workspacePath, 'workflow.yaml'), workflowTemplate);\n await fs.writeFile(path.join(workspacePath, 'state.json'), stateTemplate);\n await fs.writeFile(path.join(workspacePath, 'brief.md'), briefTemplate);\n\n console.log(`✅ Created workspace \"${name}\" at ${workspacePath}`);\n console.log(`\nNext steps:\n 1. Edit brief.md to describe your requirements\n 2. Run \"agent-handoff status ${name}\" to check workspace status\n 3. Run \"agent-handoff next ${name}\" to get the first step prompt\n`);\n } catch (error) {\n console.error(`Error creating workspace: ${error}`);\n process.exit(1);\n }\n });\n","import { Command } from 'commander';\nimport path from 'path';\nimport { loadWorkspace } from '../../core/workspace.js';\nimport { computeState } from '../../core/state-machine.js';\n\nexport const statusCommand = new Command('status')\n .description('显示 workspace 状态')\n .argument('[workspace]', 'workspace 路径', '.')\n .option('-j, --json', 'JSON 格式输出')\n .action(async (workspace: string, options: { json: boolean }) => {\n const workspacePath = path.resolve(workspace);\n\n try {\n const info = await loadWorkspace(workspacePath);\n\n if (!info.exists) {\n console.error(`Error: workspace not found: ${workspacePath}`);\n process.exit(1);\n }\n\n if (!info.hasWorkflow) {\n console.error(`Error: workflow.yaml not found in ${workspacePath}`);\n process.exit(1);\n }\n\n if (!info.workflow) {\n console.error(`Error: failed to parse workflow.yaml`);\n process.exit(1);\n }\n\n const stateResult = computeState(info.workflow, info.stepOutputs);\n\n if (options.json) {\n const jsonOutput = {\n name: info.workflow.name,\n path: workspacePath,\n status: stateResult.status,\n currentIndex: stateResult.currentIndex,\n totalSteps: info.workflow.steps.length,\n completedSteps: stateResult.completedSteps.length,\n steps: info.workflow.steps.map((step, index) => ({\n index,\n id: step.id,\n executor: step.executor,\n workItemId: step.workItemId,\n completed: info.stepOutputs.get(step.id) ?? false,\n })),\n };\n console.log(JSON.stringify(jsonOutput, null, 2));\n } else {\n console.log(`Workspace: ${info.workflow.name}`);\n console.log(`Status: ${stateResult.status}`);\n console.log('');\n console.log('Steps:');\n\n info.workflow.steps.forEach((step, index) => {\n const completed = info.stepOutputs.get(step.id) ?? false;\n const statusIcon = completed ? '✅' : '⬜';\n const stepNum = String(index + 1).padStart(2, '0');\n let line = ` ${statusIcon} ${stepNum}-${step.id} (${step.executor})`;\n if (step.workItemId) {\n line += ` [${step.workItemId}]`;\n }\n console.log(line);\n });\n\n console.log('');\n if (stateResult.status === 'done') {\n console.log('Current: completed');\n } else {\n const currentStep = info.workflow.steps[stateResult.currentIndex];\n console.log(`Current: step ${stateResult.currentIndex + 1} (${currentStep?.id})`);\n }\n }\n } catch (error) {\n console.error(`Error: ${error}`);\n process.exit(1);\n }\n });\n","import fs from 'fs/promises';\nimport path from 'path';\nimport { Workflow } from './models/workflow.js';\nimport { State } from './models/state.js';\nimport { parseWorkflow } from './workflow-parser.js';\n\nexport interface WorkspaceInfo {\n path: string;\n exists: boolean;\n hasWorkflow: boolean;\n hasState: boolean;\n workflow?: Workflow;\n state?: State;\n stepOutputs: Map<string, boolean>;\n}\n\nexport async function loadWorkspace(workspacePath: string): Promise<WorkspaceInfo> {\n const absolutePath = path.resolve(workspacePath);\n const workflowPath = path.join(absolutePath, 'workflow.yaml');\n const statePath = path.join(absolutePath, 'state.json');\n\n let exists = false;\n let hasWorkflow = false;\n let hasState = false;\n let workflow: Workflow | undefined;\n let state: State | undefined;\n let stepOutputs = new Map<string, boolean>();\n\n try {\n await fs.access(absolutePath);\n exists = true;\n } catch {\n return {\n path: absolutePath,\n exists: false,\n hasWorkflow: false,\n hasState: false,\n stepOutputs,\n };\n }\n\n try {\n await fs.access(workflowPath);\n hasWorkflow = true;\n workflow = await parseWorkflow(workflowPath);\n } catch {\n hasWorkflow = false;\n }\n\n try {\n const stateContent = await fs.readFile(statePath, 'utf-8');\n hasState = true;\n state = JSON.parse(stateContent) as State;\n } catch {\n hasState = false;\n }\n\n if (workflow) {\n stepOutputs = await detectStepOutputs(absolutePath, workflow);\n }\n\n return {\n path: absolutePath,\n exists,\n hasWorkflow,\n hasState,\n workflow,\n state,\n stepOutputs,\n };\n}\n\nexport async function detectStepOutputs(\n workspacePath: string,\n workflow: Workflow\n): Promise<Map<string, boolean>> {\n const outputs = new Map<string, boolean>();\n\n for (const step of workflow.steps) {\n const outputPath = path.join(workspacePath, step.output);\n try {\n const content = await fs.readFile(outputPath, 'utf-8');\n outputs.set(step.id, content.trim().length > 0);\n } catch {\n outputs.set(step.id, false);\n }\n }\n\n return outputs;\n}\n\nexport async function fileExists(filePath: string): Promise<boolean> {\n try {\n await fs.access(filePath);\n return true;\n } catch {\n return false;\n }\n}\n\nexport async function fileNotEmpty(filePath: string): Promise<boolean> {\n try {\n const content = await fs.readFile(filePath, 'utf-8');\n return content.trim().length > 0;\n } catch {\n return false;\n }\n}\n","import fs from 'fs/promises';\nimport YAML from 'yaml';\nimport { Workflow, Step, Executor } from './models/workflow';\n\nexport async function parseWorkflow(filePath: string): Promise<Workflow> {\n const content = await fs.readFile(filePath, 'utf-8');\n const parsed = YAML.parse(content);\n \n if (!parsed || typeof parsed !== 'object') {\n throw new Error(`Invalid workflow.yaml: ${filePath}`);\n }\n \n if (!parsed.name || typeof parsed.name !== 'string') {\n throw new Error('workflow.yaml missing required field: name');\n }\n \n if (!Array.isArray(parsed.steps) || parsed.steps.length === 0) {\n throw new Error('workflow.yaml missing required field: steps (non-empty array)');\n }\n \n const steps: Step[] = parsed.steps.map((step: Record<string, unknown>, index: number) => {\n if (!step.id || typeof step.id !== 'string') {\n throw new Error(`Step ${index} missing required field: id`);\n }\n if (!step.executor || typeof step.executor !== 'string') {\n throw new Error(`Step ${index} missing required field: executor`);\n }\n if (!step.input || typeof step.input !== 'string') {\n throw new Error(`Step ${index} missing required field: input`);\n }\n if (!step.output || typeof step.output !== 'string') {\n throw new Error(`Step ${index} missing required field: output`);\n }\n \n return {\n id: step.id,\n executor: step.executor as Executor,\n input: step.input,\n output: step.output,\n workItemId: step.workItemId as string | undefined,\n acceptance: step.acceptance as string[] | undefined,\n };\n });\n \n return {\n name: parsed.name,\n steps,\n };\n}\n\nexport function validateWorkflow(workflow: Workflow): string[] {\n const errors: string[] = [];\n \n if (!workflow.name || workflow.name.trim() === '') {\n errors.push('workflow.name is required');\n }\n \n if (!workflow.steps || workflow.steps.length === 0) {\n errors.push('workflow.steps is required and must be non-empty');\n return errors;\n }\n \n workflow.steps.forEach((step, index) => {\n if (!step.id || step.id.trim() === '') {\n errors.push(`steps[${index}].id is required`);\n }\n if (!step.executor) {\n errors.push(`steps[${index}].executor is required`);\n }\n if (!step.input || step.input.trim() === '') {\n errors.push(`steps[${index}].input is required`);\n }\n if (!step.output || step.output.trim() === '') {\n errors.push(`steps[${index}].output is required`);\n }\n if (!step.output.startsWith('steps/')) {\n errors.push(`steps[${index}].output should start with 'steps/'`);\n }\n });\n \n return errors;\n}\n","import { Workflow } from './models/workflow';\nimport { State, WorkflowStatus } from './models/state';\n\nexport interface StateMachineResult {\n currentIndex: number;\n status: WorkflowStatus;\n nextStepIndex: number | null;\n completedSteps: number[];\n pendingSteps: number[];\n}\n\nexport function computeState(\n workflow: Workflow,\n stepOutputs: Map<string, boolean>\n): StateMachineResult {\n if (!workflow.steps || workflow.steps.length === 0) {\n return {\n currentIndex: 0,\n status: 'done',\n nextStepIndex: null,\n completedSteps: [],\n pendingSteps: [],\n };\n }\n\n const completedSteps: number[] = [];\n const pendingSteps: number[] = [];\n let currentIndex = 0;\n let status: WorkflowStatus = 'running';\n\n for (let i = 0; i < workflow.steps.length; i++) {\n const step = workflow.steps[i];\n const outputExists = stepOutputs.get(step.id) ?? false;\n\n if (outputExists) {\n completedSteps.push(i);\n } else {\n pendingSteps.push(i);\n }\n }\n\n const firstPendingIndex = pendingSteps[0];\n\n if (firstPendingIndex === undefined) {\n currentIndex = workflow.steps.length;\n status = 'done';\n } else {\n currentIndex = firstPendingIndex;\n status = 'running';\n }\n\n return {\n currentIndex,\n status,\n nextStepIndex: status === 'done' ? null : currentIndex,\n completedSteps,\n pendingSteps,\n };\n}\n\nexport function advanceState(\n state: State,\n workflow: Workflow,\n stepOutputs: Map<string, boolean>\n): State {\n const result = computeState(workflow, stepOutputs);\n\n return {\n ...state,\n currentIndex: result.currentIndex,\n status: result.status,\n updatedAt: new Date().toISOString(),\n };\n}\n\nexport function isWorkflowComplete(\n workflow: Workflow,\n stepOutputs: Map<string, boolean>\n): boolean {\n if (!workflow.steps || workflow.steps.length === 0) {\n return true;\n }\n\n return workflow.steps.every((step) => stepOutputs.get(step.id) === true);\n}\n\nexport function getCurrentStep(\n workflow: Workflow,\n stepOutputs: Map<string, boolean>\n): { index: number; step: typeof workflow.steps[0] } | null {\n const result = computeState(workflow, stepOutputs);\n\n if (result.status === 'done' || result.nextStepIndex === null) {\n return null;\n }\n\n return {\n index: result.nextStepIndex,\n step: workflow.steps[result.nextStepIndex],\n };\n}\n","import { Command } from 'commander';\nimport path from 'path';\nimport { loadWorkspace } from '../../core/workspace.js';\nimport { computeState, getCurrentStep } from '../../core/state-machine.js';\nimport { generatePrompt } from '../../core/prompt-generator.js';\nimport { copyToClipboard, isClipboardSupported } from '../../core/clipboard.js';\nimport { writeEvent } from '../../core/events-writer.js';\n\nexport const nextCommand = new Command('next')\n .description('输出下一步执行指令和 prompt')\n .argument('[workspace]', 'workspace 路径', '.')\n .option('-c, --copy', '复制 prompt 到剪贴板')\n .option('--no-event', '不写入事件日志')\n .action(async (workspace: string, options: { copy: boolean; event: boolean }) => {\n const workspacePath = path.resolve(workspace);\n\n try {\n const info = await loadWorkspace(workspacePath);\n\n if (!info.exists) {\n console.error(`Error: workspace not found: ${workspacePath}`);\n process.exit(1);\n }\n\n if (!info.hasWorkflow) {\n console.error(`Error: workflow.yaml not found in ${workspacePath}`);\n process.exit(1);\n }\n\n if (!info.workflow) {\n console.error(`Error: failed to parse workflow.yaml`);\n process.exit(1);\n }\n\n const stateResult = computeState(info.workflow, info.stepOutputs);\n\n if (stateResult.status === 'done') {\n console.log(`Workflow \"${info.workflow.name}\" 已完成所有步骤。`);\n console.log('无下一步操作。');\n return;\n }\n\n const currentStep = getCurrentStep(info.workflow, info.stepOutputs);\n\n if (!currentStep) {\n console.log(`Workflow \"${info.workflow.name}\" 已完成所有步骤。`);\n console.log('无下一步操作。');\n return;\n }\n\n const { step, index } = currentStep;\n\n console.log(`Step: ${step.id}`);\n console.log(`Executor: ${step.executor}`);\n if (step.workItemId) {\n console.log(`Work Item: ${step.workItemId}`);\n }\n console.log('');\n console.log('Input:');\n console.log(` - ${step.input}`);\n console.log('');\n console.log('Output:');\n console.log(` - ${step.output}`);\n console.log('');\n console.log('Prompt:');\n console.log('────────────────────────────────────────');\n\n const prompt = generatePrompt({\n workflow: info.workflow,\n step,\n stepIndex: index,\n workspacePath: info.path,\n });\n\n console.log(prompt);\n console.log('────────────────────────────────────────');\n console.log('');\n\n if (options.event) {\n await writeEvent({\n workspacePath,\n step: { index: index + 1, id: step.id },\n type: 'step.started',\n summary: `开始执行步骤: ${step.id}`,\n workItemId: step.workItemId,\n links: [step.input],\n });\n }\n\n if (options.copy) {\n if (!isClipboardSupported()) {\n console.log('⚠️ 剪贴板功能在当前环境不可用');\n console.log('请手动复制上面的 Prompt');\n } else {\n const result = await copyToClipboard(prompt);\n if (result.success) {\n console.log('✅ Prompt 已复制到剪贴板');\n } else {\n console.log(`❌ 复制失败: ${result.error}`);\n console.log('请手动复制上面的 Prompt');\n }\n }\n } else {\n console.log('提示:将上述 Prompt 复制到 TRAE 新 Task 中执行');\n console.log(' 使用 --copy 选项可自动复制到剪贴板');\n }\n } catch (error) {\n console.error(`Error: ${error}`);\n process.exit(1);\n }\n });\n","import { Workflow, Step } from './models/workflow.js';\n\nexport interface PromptContext {\n workflow: Workflow;\n step: Step;\n stepIndex: number;\n workspacePath: string;\n}\n\nexport function generatePrompt(context: PromptContext): string {\n const { workflow, step, stepIndex } = context;\n const totalSteps = workflow.steps.length;\n const stepNum = stepIndex + 1;\n\n let prompt = `# 任务:${step.id}\n\n## 上下文\n- Workflow: ${workflow.name}\n- Step: ${stepNum} / ${totalSteps}\n- Executor: ${step.executor}`;\n\n if (step.workItemId) {\n prompt += `\\n- Work Item: ${step.workItemId}`;\n }\n\n prompt += `\n\n## 输入产物\n请阅读以下输入产物:\n- ${step.input}\n\n## 输出产物\n请将结果写入:\n- ${step.output}`;\n\n if (step.acceptance && step.acceptance.length > 0) {\n prompt += `\n\n## 验收标准`;\n for (const criteria of step.acceptance) {\n prompt += `\\n- ${criteria}`;\n }\n }\n\n prompt += `\n\n## 输出要求\n完成后请在 output.md 中包含以下区块:\n- 产物更新\n- 关键决策\n- 风险与待确认\n- 下一步交接\n\n---\nAgentHandoff Step Prompt`;\n\n return prompt;\n}\n","import clipboard from 'clipboardy';\n\nexport interface ClipboardResult {\n success: boolean;\n error?: string;\n}\n\nlet clipboardSupported: boolean | null = null;\n\nexport function isClipboardSupported(): boolean {\n if (clipboardSupported !== null) {\n return clipboardSupported;\n }\n\n try {\n clipboardSupported = true;\n return true;\n } catch {\n clipboardSupported = false;\n return false;\n }\n}\n\nexport async function copyToClipboard(text: string): Promise<ClipboardResult> {\n try {\n await clipboard.write(text);\n return { success: true };\n } catch (error) {\n const errorMessage = error instanceof Error ? error.message : String(error);\n return {\n success: false,\n error: errorMessage,\n };\n }\n}\n\nexport async function readFromClipboard(): Promise<string> {\n try {\n return await clipboard.read();\n } catch {\n return '';\n }\n}\n","import fs from 'fs/promises';\nimport path from 'path';\nimport { Event, EventType, EventStep } from './models/event.js';\n\nexport interface WriteEventOptions {\n workspacePath: string;\n step: EventStep;\n type: EventType;\n summary: string;\n workItemId?: string;\n links?: string[];\n data?: Record<string, unknown>;\n}\n\nexport interface EventsWriterResult {\n success: boolean;\n event: Event;\n error?: string;\n}\n\nexport async function writeEvent(options: WriteEventOptions): Promise<EventsWriterResult> {\n const { workspacePath, step, type, summary, workItemId, links, data } = options;\n\n const event: Event = {\n ts: new Date().toISOString(),\n step,\n type,\n summary,\n ...(workItemId && { workItemId }),\n ...(links && links.length > 0 && { links }),\n ...(data && { data }),\n };\n\n try {\n const eventsPath = path.join(workspacePath, 'events.jsonl');\n const line = JSON.stringify(event) + '\\n';\n await fs.appendFile(eventsPath, line, 'utf-8');\n\n return {\n success: true,\n event,\n };\n } catch (error) {\n const errorMessage = error instanceof Error ? error.message : String(error);\n return {\n success: false,\n event,\n error: errorMessage,\n };\n }\n}\n\nexport async function readEvents(workspacePath: string): Promise<Event[]> {\n const eventsPath = path.join(workspacePath, 'events.jsonl');\n\n try {\n const content = await fs.readFile(eventsPath, 'utf-8');\n const lines = content.split('\\n').filter((line) => line.trim());\n\n const events: Event[] = [];\n for (const line of lines) {\n try {\n const event = JSON.parse(line) as Event;\n events.push(event);\n } catch {\n // Skip invalid lines\n }\n }\n\n return events;\n } catch {\n return [];\n }\n}\n\nexport async function getLatestEvent(workspacePath: string): Promise<Event | null> {\n const events = await readEvents(workspacePath);\n if (events.length === 0) {\n return null;\n }\n return events[events.length - 1];\n}\n\nexport async function getEventsByStep(workspacePath: string, stepId: string): Promise<Event[]> {\n const events = await readEvents(workspacePath);\n return events.filter((event) => event.step.id === stepId);\n}\n\nexport async function getEventsByType(workspacePath: string, type: EventType): Promise<Event[]> {\n const events = await readEvents(workspacePath);\n return events.filter((event) => event.type === type);\n}\n\nexport async function getEventsByWorkItem(\n workspacePath: string,\n workItemId: string\n): Promise<Event[]> {\n const events = await readEvents(workspacePath);\n return events.filter((event) => event.workItemId === workItemId);\n}\n","import { Command } from 'commander';\nimport path from 'path';\nimport { loadWorkspace } from '../../core/workspace.js';\nimport { validateWorkspaceArtifacts } from '../../core/artifact-validator.js';\n\nexport const validateCommand = new Command('validate')\n .description('校验 workspace 产物结构')\n .argument('[workspace]', 'workspace 路径', '.')\n .option('--strict', '严格模式(将警告视为错误)')\n .option('-j, --json', 'JSON 格式输出')\n .action(async (workspace: string, options: { strict: boolean; json: boolean }) => {\n const workspacePath = path.resolve(workspace);\n\n try {\n const info = await loadWorkspace(workspacePath);\n\n if (!info.exists) {\n console.error(`Error: workspace not found: ${workspacePath}`);\n process.exit(1);\n }\n\n if (!info.hasWorkflow) {\n console.error(`Error: workflow.yaml not found in ${workspacePath}`);\n process.exit(1);\n }\n\n if (!info.workflow) {\n console.error(`Error: failed to parse workflow.yaml`);\n process.exit(1);\n }\n\n const result = await validateWorkspaceArtifacts(workspacePath);\n\n if (options.json) {\n const jsonOutput = {\n valid: options.strict ? result.valid && result.warningCount === 0 : result.valid,\n workspace: workspacePath,\n totalSteps: result.totalSteps,\n validSteps: result.validSteps,\n errorCount: result.errorCount,\n warningCount: result.warningCount,\n steps: Array.from(result.stepResults.entries()).map(([stepId, stepResult]) => ({\n stepId,\n valid: options.strict ? stepResult.valid && stepResult.warnings.length === 0 : stepResult.valid,\n errors: stepResult.errors,\n warnings: stepResult.warnings,\n })),\n };\n console.log(JSON.stringify(jsonOutput, null, 2));\n } else {\n console.log(`Workspace: ${info.workflow.name}`);\n console.log('');\n\n for (const step of info.workflow.steps) {\n const stepResult = result.stepResults.get(step.id);\n if (!stepResult) continue;\n\n const icon = stepResult.valid ? '✅' : '❌';\n console.log(`${icon} ${step.output} - ${stepResult.valid ? 'Valid' : 'Invalid'}`);\n\n if (!stepResult.valid) {\n for (const error of stepResult.errors) {\n console.log(` - ${error.message}`);\n }\n }\n\n if (stepResult.warnings.length > 0) {\n for (const warning of stepResult.warnings) {\n console.log(` ⚠️ ${warning.message}`);\n }\n }\n }\n\n console.log('');\n\n const hasErrors = result.errorCount > 0;\n const hasWarnings = result.warningCount > 0;\n const strictFail = options.strict && hasWarnings;\n\n if (!hasErrors && !strictFail) {\n console.log('All artifacts validated successfully.');\n if (hasWarnings) {\n console.log(`⚠️ ${result.warningCount} warning(s) found.`);\n }\n } else {\n const totalErrors = result.errorCount + (strictFail ? result.warningCount : 0);\n console.log(`Validation failed with ${totalErrors} error(s).`);\n }\n\n if (hasErrors || strictFail) {\n process.exit(1);\n }\n }\n } catch (error) {\n console.error(`Error: ${error}`);\n process.exit(1);\n }\n });\n","import fs from 'fs/promises';\nimport path from 'path';\nimport { loadWorkspace } from './workspace.js';\n\nexport interface ValidationResult {\n valid: boolean;\n errors: ValidationError[];\n warnings: ValidationWarning[];\n}\n\nexport interface ValidationError {\n type: 'missing_section' | 'empty_section' | 'invalid_format';\n section: string;\n message: string;\n}\n\nexport interface ValidationWarning {\n type: 'short_content' | 'missing_detail';\n section: string;\n message: string;\n}\n\nexport const REQUIRED_SECTIONS = [\n '产物更新',\n '关键决策',\n '风险与待确认',\n '下一步交接',\n] as const;\n\nexport type RequiredSection = (typeof REQUIRED_SECTIONS)[number];\n\nexport interface WorkspaceValidationResult {\n valid: boolean;\n stepResults: Map<string, ValidationResult>;\n totalSteps: number;\n validSteps: number;\n errorCount: number;\n warningCount: number;\n}\n\nconst MIN_CONTENT_LENGTH = 10;\n\nexport function validateArtifact(content: string): ValidationResult {\n const errors: ValidationError[] = [];\n const warnings: ValidationWarning[] = [];\n\n for (const section of REQUIRED_SECTIONS) {\n const sectionResult = findSection(content, section);\n\n if (!sectionResult.found) {\n errors.push({\n type: 'missing_section',\n section,\n message: `缺少必要区块: ${section}`,\n });\n } else if (!sectionResult.hasContent) {\n errors.push({\n type: 'empty_section',\n section,\n message: `区块内容为空: ${section}`,\n });\n } else if (sectionResult.contentLength < MIN_CONTENT_LENGTH) {\n warnings.push({\n type: 'short_content',\n section,\n message: `区块内容过短 (${sectionResult.contentLength} 字符): ${section}`,\n });\n }\n }\n\n return {\n valid: errors.length === 0,\n errors,\n warnings,\n };\n}\n\ninterface SectionResult {\n found: boolean;\n hasContent: boolean;\n contentLength: number;\n}\n\nfunction findSection(content: string, sectionName: string): SectionResult {\n const patterns = [\n new RegExp(`^##\\\\s+${escapeRegex(sectionName)}[^\\\\n]*$`, 'm'),\n new RegExp(`^###\\\\s+${escapeRegex(sectionName)}[^\\\\n]*$`, 'm'),\n ];\n\n let matchIndex = -1;\n let matchLength = 0;\n\n for (const pattern of patterns) {\n const match = content.match(pattern);\n if (match && match.index !== undefined) {\n matchIndex = match.index;\n matchLength = match[0].length;\n break;\n }\n }\n\n if (matchIndex === -1) {\n return { found: false, hasContent: false, contentLength: 0 };\n }\n\n const contentStart = matchIndex + matchLength;\n const remainingContent = content.slice(contentStart);\n\n const nextSectionMatch = remainingContent.match(/^#{1,3}\\s+/m);\n const sectionContent = nextSectionMatch\n ? remainingContent.slice(0, nextSectionMatch.index)\n : remainingContent;\n\n const trimmedContent = sectionContent.trim();\n\n return {\n found: true,\n hasContent: trimmedContent.length > 0,\n contentLength: trimmedContent.length,\n };\n}\n\nfunction escapeRegex(str: string): string {\n return str.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&');\n}\n\nexport async function validateArtifactFile(\n filePath: string\n): Promise<ValidationResult> {\n try {\n const content = await fs.readFile(filePath, 'utf-8');\n return validateArtifact(content);\n } catch {\n return {\n valid: false,\n errors: [\n {\n type: 'invalid_format',\n section: '',\n message: `无法读取文件: ${filePath}`,\n },\n ],\n warnings: [],\n };\n }\n}\n\nexport async function validateWorkspaceArtifacts(\n workspacePath: string\n): Promise<WorkspaceValidationResult> {\n const workspace = await loadWorkspace(workspacePath);\n const stepResults = new Map<string, ValidationResult>();\n let validSteps = 0;\n let errorCount = 0;\n let warningCount = 0;\n\n if (!workspace.workflow) {\n return {\n valid: false,\n stepResults,\n totalSteps: 0,\n validSteps: 0,\n errorCount: 1,\n warningCount: 0,\n };\n }\n\n for (const step of workspace.workflow.steps) {\n const outputPath = path.join(workspace.path, step.output);\n const result = await validateArtifactFile(outputPath);\n stepResults.set(step.id, result);\n\n if (result.valid) {\n validSteps++;\n }\n errorCount += result.errors.length;\n warningCount += result.warnings.length;\n }\n\n return {\n valid: errorCount === 0,\n stepResults,\n totalSteps: workspace.workflow.steps.length,\n validSteps,\n errorCount,\n warningCount,\n };\n}\n","import { Command } from 'commander';\nimport path from 'path';\nimport fs from 'fs/promises';\nimport { loadWorkspace } from '../../core/workspace.js';\nimport { computeState, getCurrentStep } from '../../core/state-machine.js';\nimport { writeEvent } from '../../core/events-writer.js';\nimport { EventType } from '../../core/models/event.js';\n\nexport const advanceCommand = new Command('advance')\n .description('推进 workspace 状态')\n .argument('[workspace]', 'workspace 路径', '.')\n .option('-e, --event <type>', '事件类型', 'step.done')\n .option('-s, --summary <text>', '事件摘要')\n .option('--no-state', '不更新 state.json')\n .option('--skip-event', '不写入事件日志')\n .action(\n async (\n workspace: string,\n options: { event: string; summary?: string; state: boolean; skipEvent: boolean }\n ) => {\n const workspacePath = path.resolve(workspace);\n\n try {\n const info = await loadWorkspace(workspacePath);\n\n if (!info.exists) {\n console.error(`Error: workspace not found: ${workspacePath}`);\n process.exit(1);\n }\n\n if (!info.hasWorkflow) {\n console.error(`Error: workflow.yaml not found in ${workspacePath}`);\n process.exit(1);\n }\n\n if (!info.workflow) {\n console.error(`Error: failed to parse workflow.yaml`);\n process.exit(1);\n }\n\n const stateResult = computeState(info.workflow, info.stepOutputs);\n\n console.log(`Workspace: ${info.workflow.name}`);\n\n if (stateResult.status === 'done') {\n console.log('Status: done');\n console.log('');\n console.log('⚠️ Workflow already completed. No steps to advance.');\n return;\n }\n\n const currentStep = getCurrentStep(info.workflow, info.stepOutputs);\n\n if (!currentStep) {\n console.log('Status: done');\n console.log('');\n console.log('⚠️ Workflow already completed. No steps to advance.');\n return;\n }\n\n const { step, index } = currentStep;\n\n console.log(`Current step: ${step.id} (index: ${index})`);\n console.log('');\n\n const eventType = options.event as EventType;\n const eventSummary = options.summary || getDefaultSummary(eventType, step.id);\n\n if (!options.skipEvent) {\n const result = await writeEvent({\n workspacePath,\n step: { index: index + 1, id: step.id },\n type: eventType,\n summary: eventSummary,\n workItemId: step.workItemId,\n links: [step.output],\n });\n\n if (result.success) {\n console.log(`✅ Event written: ${eventType}`);\n console.log(` Summary: ${eventSummary}`);\n if (step.workItemId) {\n console.log(` Work Item: ${step.workItemId}`);\n }\n if (step.output) {\n console.log(` Links: ${step.output}`);\n }\n } else {\n console.log(`❌ Failed to write event: ${result.error}`);\n }\n }\n\n if (options.state) {\n const statePath = path.join(workspacePath, 'state.json');\n const newIndex = index + 1;\n const isDone = newIndex >= info.workflow.steps.length;\n\n const newState = {\n currentIndex: newIndex,\n status: isDone ? 'done' : 'running',\n updatedAt: new Date().toISOString(),\n };\n\n await fs.writeFile(statePath, JSON.stringify(newState, null, 2));\n console.log('');\n console.log(`✅ State updated: ${statePath}`);\n console.log(` Current index: ${newState.currentIndex}`);\n console.log(` Status: ${newState.status}`);\n\n if (isDone) {\n console.log('');\n console.log('🎉 Workflow completed!');\n } else {\n const nextStep = info.workflow.steps[newIndex];\n console.log(` Next step: ${nextStep.id}`);\n }\n }\n } catch (error) {\n console.error(`Error: ${error}`);\n process.exit(1);\n }\n }\n );\n\nfunction getDefaultSummary(eventType: EventType, stepId: string): string {\n const summaries: Record<EventType, string> = {\n 'step.started': `开始执行步骤: ${stepId}`,\n 'step.done': `步骤完成: ${stepId}`,\n 'artifact.updated': '产物已更新',\n 'workflow.updated': '工作流已更新',\n 'verify.passed': '验证通过',\n 'verify.failed': '验证失败',\n 'accept.passed': '验收通过',\n 'accept.failed': '验收失败',\n 'issue.raised': '发现问题',\n 'handoff.sent': '已交接给下一步',\n 'automation.session': '自动化会话已记录',\n };\n return summaries[eventType] || `事件: ${eventType}`;\n}\n","import { Command } from 'commander';\nimport os from 'os';\nimport {\n loadConfig,\n findConfigFile,\n initConfigFile,\n DEFAULT_CONFIG,\n} from '../../core/config.js';\n\nexport const configCommand = new Command('config')\n .description('查看或管理配置')\n .argument('[action]', '操作: show, init', 'show')\n .option('-g, --global', '操作全局配置')\n .option('--verbose', '显示详细信息')\n .action(async (action: string, options: { global: boolean; verbose: boolean }) => {\n try {\n if (action === 'show') {\n await showConfig(options);\n } else if (action === 'init') {\n await initConfig(options);\n } else if (action === 'list') {\n await listConfig();\n } else {\n console.error(`Unknown action: ${action}`);\n console.log('Available actions: show, init, list');\n process.exit(1);\n }\n } catch (error) {\n console.error(`Error: ${error}`);\n process.exit(1);\n }\n });\n\nasync function showConfig(options: { global: boolean; verbose: boolean }): Promise<void> {\n const targetPath = options.global ? os.homedir() : process.cwd();\n const config = await loadConfig(targetPath);\n\n if (options.verbose) {\n const configFile = await findConfigFile(targetPath);\n if (configFile) {\n console.log(`Config file: ${configFile}`);\n console.log('');\n } else {\n console.log('No config file found, using defaults');\n console.log('');\n }\n }\n\n console.log(JSON.stringify(config, null, 2));\n}\n\nasync function initConfig(options: { global: boolean; verbose: boolean }): Promise<void> {\n const targetPath = options.global ? os.homedir() : process.cwd();\n const configPath = await initConfigFile(targetPath, options.global);\n\n console.log(`✅ Created config file: ${configPath}`);\n console.log('');\n console.log('Default configuration:');\n console.log(JSON.stringify(DEFAULT_CONFIG, null, 2));\n}\n\nasync function listConfig(): Promise<void> {\n console.log('Configuration options:');\n console.log('');\n console.log(' defaultWorkspace - 默认 workspace 路径');\n console.log(' events.enabled - 是否启用事件日志 (default: true)');\n console.log(' events.logStepStarted - 是否记录 step.started (default: true)');\n console.log(' events.logStepDone - 是否记录 step.done (default: true)');\n console.log(' clipboard.autoCopy - 是否自动复制 prompt (default: false)');\n console.log(' prompt.templatePath - 自定义 prompt 模板路径');\n console.log(' prompt.language - prompt 语言 (default: zh)');\n console.log(' validation.strict - 严格校验模式 (default: false)');\n console.log(' validation.warnOnShortContent - 内容过短时警告 (default: true)');\n console.log('');\n console.log('Config file locations (in order of priority):');\n console.log(' .agenthandoffrc');\n console.log(' .agenthandoffrc.json');\n console.log(' .agenthandoffrc.yaml');\n console.log(' package.json#agenthandoff');\n console.log(` ~/.agenthandoffrc (global)`);\n}\n","import fs from 'fs/promises';\nimport path from 'path';\nimport os from 'os';\n\nexport interface AgentHandoffConfig {\n defaultWorkspace?: string;\n events?: {\n enabled: boolean;\n logStepStarted: boolean;\n logStepDone: boolean;\n };\n automation?: {\n enabled: boolean;\n provider: 'nutjs';\n screenshot: boolean;\n timeout: number;\n retries: number;\n confidence?: number;\n };\n clipboard?: {\n autoCopy: boolean;\n };\n prompt?: {\n templatePath?: string;\n language: 'zh' | 'en';\n };\n validation?: {\n strict: boolean;\n warnOnShortContent: boolean;\n };\n}\n\nexport const DEFAULT_CONFIG: AgentHandoffConfig = {\n events: {\n enabled: true,\n logStepStarted: true,\n logStepDone: true,\n },\n automation: {\n enabled: false,\n provider: 'nutjs',\n screenshot: false,\n timeout: 30000,\n retries: 3,\n confidence: 0.8,\n },\n clipboard: {\n autoCopy: false,\n },\n prompt: {\n language: 'zh',\n },\n validation: {\n strict: false,\n warnOnShortContent: true,\n },\n};\n\nconst CONFIG_FILES = [\n '.agenthandoffrc',\n '.agenthandoffrc.json',\n '.agenthandoffrc.yaml',\n '.agenthandoffrc.yml',\n];\n\nconst configCache = new Map<string, AgentHandoffConfig>();\n\nexport async function findConfigFile(startPath: string): Promise<string | null> {\n let currentPath = path.resolve(startPath);\n const homePath = os.homedir();\n\n while (true) {\n for (const configFile of CONFIG_FILES) {\n const filePath = path.join(currentPath, configFile);\n try {\n await fs.access(filePath);\n return filePath;\n } catch {\n // File doesn't exist, continue\n }\n }\n\n const packageJsonPath = path.join(currentPath, 'package.json');\n try {\n const content = await fs.readFile(packageJsonPath, 'utf-8');\n const pkg = JSON.parse(content);\n if (pkg.agenthandoff) {\n return packageJsonPath;\n }\n } catch {\n // File doesn't exist or invalid, continue\n }\n\n if (currentPath === homePath || currentPath === path.dirname(currentPath)) {\n break;\n }\n currentPath = path.dirname(currentPath);\n }\n\n return null;\n}\n\nexport async function loadConfigFile(filePath: string): Promise<Partial<AgentHandoffConfig>> {\n try {\n const content = await fs.readFile(filePath, 'utf-8');\n const ext = path.extname(filePath);\n\n if (ext === '.yaml' || ext === '.yml') {\n return parseYaml(content);\n }\n\n if (filePath.endsWith('package.json')) {\n const pkg = JSON.parse(content);\n return pkg.agenthandoff || {};\n }\n\n return JSON.parse(content);\n } catch {\n return {};\n }\n}\n\nfunction parseYaml(content: string): Record<string, unknown> {\n const result: Record<string, unknown> = {};\n const lines = content.split('\\n');\n let currentObj: Record<string, unknown> = result;\n const stack: Array<{ obj: Record<string, unknown> }> = [];\n\n for (const line of lines) {\n if (!line.trim() || line.trim().startsWith('#')) {\n continue;\n }\n\n const indent = line.search(/\\S/);\n const trimmed = line.trim();\n\n if (trimmed.includes(':')) {\n const colonIndex = trimmed.indexOf(':');\n const key = trimmed.slice(0, colonIndex).trim();\n const value = trimmed.slice(colonIndex + 1).trim();\n\n if (value === '') {\n if (stack.length > 0) {\n const expectedIndent = stack.length * 2;\n if (indent < expectedIndent) {\n while (stack.length > 0 && indent < stack.length * 2) {\n stack.pop();\n }\n if (stack.length > 0) {\n currentObj = stack[stack.length - 1].obj as Record<string, unknown>;\n } else {\n currentObj = result;\n }\n }\n }\n\n const newObj: Record<string, unknown> = {};\n currentObj[key] = newObj;\n stack.push({ obj: currentObj });\n currentObj = newObj;\n } else {\n let parsedValue: unknown = value;\n if (value === 'true') parsedValue = true;\n else if (value === 'false') parsedValue = false;\n else if (value === 'null') parsedValue = null;\n else if (/^\\d+$/.test(value)) parsedValue = parseInt(value, 10);\n else if (/^\\d+\\.\\d+$/.test(value)) parsedValue = parseFloat(value);\n else if (value.startsWith('\"') && value.endsWith('\"')) {\n parsedValue = value.slice(1, -1);\n } else if (value.startsWith(\"'\") && value.endsWith(\"'\")) {\n parsedValue = value.slice(1, -1);\n }\n\n currentObj[key] = parsedValue;\n }\n }\n }\n\n return result;\n}\n\nexport function mergeConfig(\n base: AgentHandoffConfig,\n override: Partial<AgentHandoffConfig>\n): AgentHandoffConfig {\n const result: AgentHandoffConfig = JSON.parse(JSON.stringify(base));\n\n for (const key of Object.keys(override) as Array<keyof AgentHandoffConfig>) {\n const overrideValue = override[key];\n if (overrideValue === undefined) continue;\n\n if (\n typeof overrideValue === 'object' &&\n overrideValue !== null &&\n !Array.isArray(overrideValue)\n ) {\n const baseValue = result[key];\n if (\n typeof baseValue === 'object' &&\n baseValue !== null &&\n !Array.isArray(baseValue)\n ) {\n // Deep merge for nested objects\n (result as Record<string, unknown>)[key] = mergeConfig(\n baseValue as AgentHandoffConfig,\n overrideValue as Partial<AgentHandoffConfig>\n );\n } else {\n (result as Record<string, unknown>)[key] = overrideValue;\n }\n } else {\n (result as Record<string, unknown>)[key] = overrideValue;\n }\n }\n\n return result;\n}\n\nexport async function loadConfig(workspacePath?: string): Promise<AgentHandoffConfig> {\n const startPath = workspacePath ? path.resolve(workspacePath) : process.cwd();\n const cacheKey = startPath;\n\n if (configCache.has(cacheKey)) {\n return configCache.get(cacheKey)!;\n }\n\n let config = JSON.parse(JSON.stringify(DEFAULT_CONFIG)) as AgentHandoffConfig;\n\n const globalConfigPath = path.join(os.homedir(), '.agenthandoffrc');\n try {\n await fs.access(globalConfigPath);\n const globalConfig = await loadConfigFile(globalConfigPath);\n config = mergeConfig(config, globalConfig);\n } catch {\n // Global config doesn't exist\n }\n\n const localConfigFile = await findConfigFile(startPath);\n if (localConfigFile) {\n const localConfig = await loadConfigFile(localConfigFile);\n config = mergeConfig(config, localConfig);\n }\n\n configCache.set(cacheKey, config);\n return config;\n}\n\nexport function clearConfigCache(): void {\n configCache.clear();\n}\n\nexport async function initConfigFile(targetPath: string, global = false): Promise<string> {\n const configPath = global\n ? path.join(os.homedir(), '.agenthandoffrc')\n : path.join(targetPath, '.agenthandoffrc');\n\n const content = JSON.stringify(DEFAULT_CONFIG, null, 2);\n await fs.writeFile(configPath, content, 'utf-8');\n\n return configPath;\n}\n","import { Command } from 'commander';\nimport fs from 'fs/promises';\nimport path from 'path';\nimport { OperationReporter } from '../../adapters/trae/operation-reporter.js';\n\ntype ReportFormat = 'json' | 'markdown' | 'html';\n\nexport const reportCommand = new Command('report')\n .description('生成自动化操作报告')\n .argument('[workspace]', 'workspace 路径', '.')\n .option('-f, --format <format>', '报告格式: json, markdown, html', 'markdown')\n .option('-s, --session <id>', '指定 session ID')\n .option('--screenshots', '包含截图', false)\n .option('-o, --output <path>', '输出路径')\n .action(\n async (\n workspace: string,\n options: { format: ReportFormat; session?: string; screenshots: boolean; output?: string }\n ) => {\n const workspacePath = path.resolve(workspace);\n const logDir = path.join(workspacePath, 'operations');\n\n try {\n let sessionFile: string;\n if (options.session) {\n sessionFile = path.join(logDir, `operations-${options.session}.jsonl`);\n } else {\n const files = await fs.readdir(logDir);\n const jsonlFiles = files\n .filter((f) => f.endsWith('.jsonl'))\n .sort()\n .reverse();\n if (jsonlFiles.length === 0) {\n console.error('Error: no operation logs found');\n process.exit(1);\n }\n sessionFile = path.join(logDir, jsonlFiles[0]);\n }\n\n const content = await fs.readFile(sessionFile, 'utf-8');\n const lines = content.split('\\n').filter((l) => l.trim());\n const session = JSON.parse(lines[lines.length - 1]);\n\n const reporter = new OperationReporter(session);\n const report = reporter.generate({\n format: options.format,\n includeScreenshots: options.screenshots,\n });\n\n if (options.output) {\n await fs.writeFile(path.resolve(options.output), report, 'utf-8');\n console.log(`✅ Report saved to: ${options.output}`);\n } else {\n console.log(report);\n }\n } catch (error) {\n console.error(`Error: ${error}`);\n process.exit(1);\n }\n }\n );\n\n","import fs from 'fs/promises';\nimport { TraeSession } from './types';\n\nexport interface ReportOptions {\n format: 'json' | 'markdown' | 'html';\n includeScreenshots: boolean;\n}\n\nexport class OperationReporter {\n private session: TraeSession;\n\n constructor(session: TraeSession) {\n this.session = session;\n }\n\n generate(options: ReportOptions): string {\n switch (options.format) {\n case 'json':\n return this.generateJson();\n case 'markdown':\n return this.generateMarkdown(options.includeScreenshots);\n case 'html':\n return this.generateHtml(options.includeScreenshots);\n default:\n return this.generateMarkdown(options.includeScreenshots);\n }\n }\n\n private generateJson(): string {\n return JSON.stringify(this.session, null, 2);\n }\n\n private generateMarkdown(includeScreenshots: boolean): string {\n const lines: string[] = [\n '# Automation Session Report',\n '',\n `**Session ID:** ${this.session.id}`,\n `**Started At:** ${this.session.startedAt}`,\n `**Workspace:** ${this.session.workspacePath}`,\n `**Step ID:** ${this.session.stepId}`,\n ...(this.session.status ? [`**Status:** ${this.session.status}`] : []),\n ...(this.session.error ? [`**Error:** ${this.session.error}`] : []),\n '',\n `## Operations (${this.session.operations.length})`,\n '',\n ];\n\n this.session.operations.forEach((op, index) => {\n lines.push(`### ${index + 1}. ${op.type}`);\n if (op.target) {\n lines.push(`- **Target:** ${op.target}`);\n }\n if (op.value) {\n lines.push(\n `- **Value:** ${op.value.substring(0, 100)}${op.value.length > 100 ? '...' : ''}`\n );\n }\n lines.push(`- **Timestamp:** ${new Date(op.timestamp).toISOString()}`);\n lines.push('');\n });\n\n if (includeScreenshots && this.session.screenshots.length > 0) {\n lines.push(`## Screenshots (${this.session.screenshots.length})`);\n lines.push('');\n this.session.screenshots.forEach((screenshot, index) => {\n lines.push(`### Screenshot ${index + 1}`);\n lines.push(`![Screenshot ${index + 1}](${screenshot})`);\n lines.push('');\n });\n }\n\n return lines.join('\\n');\n }\n\n private generateHtml(includeScreenshots: boolean): string {\n const operationsHtml = this.session.operations\n .map(\n (op, index) => `\n <div class=\"operation\">\n <h3>${index + 1}. ${op.type}</h3>\n ${op.target ? `<p><strong>Target:</strong> ${op.target}</p>` : ''}\n ${\n op.value\n ? `<p><strong>Value:</strong> ${op.value.substring(0, 100)}${\n op.value.length > 100 ? '...' : ''\n }</p>`\n : ''\n }\n <p><strong>Timestamp:</strong> ${new Date(op.timestamp).toISOString()}</p>\n </div>\n `\n )\n .join('');\n\n const screenshotsHtml =\n includeScreenshots && this.session.screenshots.length > 0\n ? `\n <h2>Screenshots (${this.session.screenshots.length})</h2>\n ${this.session.screenshots\n .map(\n (s, i) => `\n <div class=\"screenshot\">\n <h3>Screenshot ${i + 1}</h3>\n <img src=\"${s}\" alt=\"Screenshot ${i + 1}\" />\n </div>\n `\n )\n .join('')}\n `\n : '';\n\n const statusLine = this.session.status\n ? `<p><strong>Status:</strong> ${this.session.status}</p>`\n : '';\n const errorLine = this.session.error ? `<p><strong>Error:</strong> ${this.session.error}</p>` : '';\n\n return `\n<!DOCTYPE html>\n<html lang=\"zh-CN\">\n<head>\n <meta charset=\"UTF-8\">\n <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n <title>Automation Session Report</title>\n <style>\n body {\n font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;\n max-width: 800px;\n margin: 0 auto;\n padding: 20px;\n background: #f5f5f5;\n }\n .header {\n background: white;\n padding: 20px;\n border-radius: 8px;\n margin-bottom: 20px;\n }\n .operation {\n background: white;\n padding: 15px;\n border-radius: 8px;\n margin-bottom: 10px;\n }\n .screenshot img {\n max-width: 100%;\n border-radius: 8px;\n }\n h1 { color: #333; }\n h2 { color: #555; border-bottom: 1px solid #eee; padding-bottom: 10px; }\n h3 { color: #666; margin: 0 0 10px 0; }\n p { margin: 5px 0; color: #666; }\n </style>\n</head>\n<body>\n <div class=\"header\">\n <h1>Automation Session Report</h1>\n <p><strong>Session ID:</strong> ${this.session.id}</p>\n <p><strong>Started At:</strong> ${this.session.startedAt}</p>\n <p><strong>Workspace:</strong> ${this.session.workspacePath}</p>\n <p><strong>Step ID:</strong> ${this.session.stepId}</p>\n ${statusLine}\n ${errorLine}\n </div>\n\n <h2>Operations (${this.session.operations.length})</h2>\n ${operationsHtml}\n\n ${screenshotsHtml}\n</body>\n</html>\n `.trim();\n }\n\n async saveToFile(outputPath: string, options: ReportOptions): Promise<string> {\n const content = this.generate(options);\n await fs.writeFile(outputPath, content, 'utf-8');\n return outputPath;\n }\n}\n\n"],"mappings":"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","names":["Command","Command","path","fs","path","fs","path","fs","Command","path","Command","path","fs","path","Command","path","Command","path","fs","path","fs","path","Command","path","Command","path","fs","Command","path","fs","Command","os","fs","path","path","fs","Command","os","Command","fs","path","fs","Command","path","fs","require","Command"]}
package/package.json CHANGED
@@ -1,13 +1,13 @@
1
1
  {
2
2
  "name": "agent-handoff",
3
- "version": "0.2.0",
3
+ "version": "0.3.0",
4
4
  "description": "轻量级多 Agent 协作接力工具",
5
5
  "type": "module",
6
6
  "author": "helinjiang",
7
7
  "license": "MIT",
8
8
  "repository": {
9
9
  "type": "git",
10
- "url": "https://github.com/helinjiang/agent-handoff.git"
10
+ "url": "git+https://github.com/helinjiang/agent-handoff.git"
11
11
  },
12
12
  "keywords": [
13
13
  "agent",
@@ -17,7 +17,7 @@
17
17
  "collaboration"
18
18
  ],
19
19
  "bin": {
20
- "agent-handoff": "./dist/index.js"
20
+ "agent-handoff": "dist/index.js"
21
21
  },
22
22
  "files": [
23
23
  "dist",
@@ -38,9 +38,12 @@
38
38
  "yaml": "^2.4.0"
39
39
  },
40
40
  "devDependencies": {
41
+ "@eslint/js": "^9.30.0",
41
42
  "@types/node": "^20.0.0",
43
+ "eslint": "^9.30.0",
42
44
  "tsup": "^8.0.0",
43
45
  "typescript": "^5.3.0",
46
+ "typescript-eslint": "^8.35.0",
44
47
  "vitest": "^1.0.0"
45
48
  },
46
49
  "engines": {