ethan-skill 1.5.4 → 1.5.6

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/dist/cli/index.js CHANGED
@@ -910,7 +910,7 @@ program
910
910
  const workflowCmd = program.command('workflow').description('有状态工作流执行:一键推进各阶段任务');
911
911
  workflowCmd
912
912
  .command('start [pipelineId]')
913
- .description('启动工作流会话(默认 dev-workflow),输出第一步提示词')
913
+ .description('启动工作流会话,输出第一步提示词(无参数时显示 Pipeline 选择菜单)')
914
914
  .option('-c, --context <context>', '初始任务上下文', '')
915
915
  .option('-n, --name <name>', '具名会话(存至 .ethan/sessions/<name>.json,可并行多个工作流)')
916
916
  .action(async (pipelineId, options) => {
@@ -928,7 +928,39 @@ workflowCmd
928
928
  console.log(' 使用 ethan workflow reset 重置后再启动新工作流\n');
929
929
  return;
930
930
  }
931
- const id = pipelineId ?? 'dev-workflow';
931
+ let id = pipelineId;
932
+ // 无参数时,显示交互式 Pipeline 选择菜单
933
+ if (!id) {
934
+ const customPipelines = loadCustomPipelines(process.cwd());
935
+ const allPipelines = [
936
+ ...PIPELINES,
937
+ ...customPipelines.map((p) => ({ id: p.id, name: p.name, description: p.description, skillIds: p.skillIds })),
938
+ ];
939
+ const readline = await Promise.resolve().then(() => __importStar(require('readline')));
940
+ const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
941
+ const ask = (q) => new Promise((resolve) => rl.question(q, (a) => resolve(a.trim())));
942
+ console.log('\n🔄 可用工作流 Pipeline\n');
943
+ console.log('─'.repeat(60));
944
+ allPipelines.forEach((p, i) => {
945
+ console.log(` ${i + 1}. ${p.name} [${p.id}]`);
946
+ console.log(` ${p.description}`);
947
+ console.log(` 步骤: ${p.skillIds.join(' → ')}`);
948
+ console.log('');
949
+ });
950
+ const choice = await ask(`选择 Pipeline(输入序号 1-${allPipelines.length},或直接输入 ID):\n> `);
951
+ rl.close();
952
+ if (!choice) {
953
+ console.error('\n❌ 未选择 Pipeline\n');
954
+ process.exit(1);
955
+ }
956
+ const num = parseInt(choice, 10);
957
+ if (!isNaN(num) && num >= 1 && num <= allPipelines.length) {
958
+ id = allPipelines[num - 1].id;
959
+ }
960
+ else {
961
+ id = choice;
962
+ }
963
+ }
932
964
  let resolved = resolvePipeline(id);
933
965
  // 尝试从自定义 YAML pipeline 加载
934
966
  if (!resolved) {
@@ -990,15 +1022,56 @@ workflowCmd
990
1022
  if (copyToClipboard(prompt)) {
991
1023
  console.log('\n✅ 提示词已复制到剪贴板!粘贴到你的 AI 编辑器中执行。');
992
1024
  }
993
- console.log(`\n💡 完成本步后,运行:ethan workflow done "你的本步摘要"${session.name ? ` --name ${session.name}` : ''}\n`);
1025
+ console.log(`\n💡 完成本步后,运行:ethan workflow done${session.name ? ` --name ${session.name}` : ''}\n`);
994
1026
  // 记录使用统计
995
1027
  const stats = readStats();
996
1028
  stats[firstSkill.id] = (stats[firstSkill.id] || 0) + 1;
997
1029
  writeStats(stats);
998
1030
  });
1031
+ workflowCmd
1032
+ .command('use [name]')
1033
+ .description('设置当前工作目录的活跃会话(后续命令无需 --name);不传 name 则显示当前激活会话')
1034
+ .action(async (name) => {
1035
+ const { getCurrentSessionName, setCurrentSessionName, clearCurrentSessionName, loadSession } = await Promise.resolve().then(() => __importStar(require('../workflow/state')));
1036
+ if (!name) {
1037
+ const current = getCurrentSessionName(process.cwd());
1038
+ if (!current) {
1039
+ console.log('\n📌 当前无激活会话(使用默认 workflow.json)');
1040
+ console.log(' 运行 ethan workflow use <name> 激活一个具名会话\n');
1041
+ }
1042
+ else {
1043
+ const session = loadSession(process.cwd(), current);
1044
+ console.log(`\n📌 当前激活会话:${current}`);
1045
+ if (session) {
1046
+ const { calcProgress } = await Promise.resolve().then(() => __importStar(require('../workflow/state')));
1047
+ console.log(` Pipeline: ${session.pipelineName}`);
1048
+ console.log(` 进度: ${calcProgress(session)}%`);
1049
+ }
1050
+ console.log('\n 运行 ethan workflow use (不带参数)可查看,ethan workflow use default 可切回默认\n');
1051
+ }
1052
+ return;
1053
+ }
1054
+ if (name === 'default' || name === '-') {
1055
+ clearCurrentSessionName(process.cwd());
1056
+ console.log('\n✅ 已切换回默认会话(workflow.json)\n');
1057
+ return;
1058
+ }
1059
+ const session = loadSession(process.cwd(), name);
1060
+ if (!session) {
1061
+ console.error(`\n❌ 未找到具名会话:${name}`);
1062
+ console.error(' 使用 ethan workflow list 查看所有会话\n');
1063
+ process.exit(1);
1064
+ }
1065
+ setCurrentSessionName(process.cwd(), name);
1066
+ const { calcProgress } = await Promise.resolve().then(() => __importStar(require('../workflow/state')));
1067
+ console.log(`\n✅ 已激活会话:${name}`);
1068
+ console.log(` Pipeline: ${session.pipelineName}`);
1069
+ console.log(` 进度: ${calcProgress(session)}%`);
1070
+ console.log('\n 后续 workflow done/status/reset 将自动使用此会话(无需 --name)\n');
1071
+ });
999
1072
  workflowCmd
1000
1073
  .command('done [summary]')
1001
- .description('完成当前步骤,传入本步摘要,自动推进到下一步')
1074
+ .description('完成当前步骤,自动推进到下一步(摘要可选)')
1002
1075
  .option('-n, --name <name>', '具名会话名称')
1003
1076
  .action(async (summary, options) => {
1004
1077
  const { loadSession, markStepDone, buildStepPrompt, getCurrentStep, getCurrentStepIndex, calcProgress, } = await Promise.resolve().then(() => __importStar(require('../workflow/state')));
@@ -1017,21 +1090,8 @@ workflowCmd
1017
1090
  console.error('\n❌ 未找到当前步骤,工作流状态异常。\n');
1018
1091
  process.exit(1);
1019
1092
  }
1020
- // 获取摘要(命令行参数 or 交互输入)
1021
- let stepSummary = summary?.trim() ?? '';
1022
- if (!stepSummary) {
1023
- const readline = await Promise.resolve().then(() => __importStar(require('readline')));
1024
- const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
1025
- const ask = (q) => new Promise((resolve) => rl.question(q, (a) => resolve(a.trim())));
1026
- const currentIdx = getCurrentStepIndex(session);
1027
- console.log(`\n✅ 完成第 ${currentIdx + 1} 步:${currentStep.skillId}`);
1028
- stepSummary = await ask('请输入本步执行摘要(将作为下一步的上下文):\n> ');
1029
- rl.close();
1030
- if (!stepSummary) {
1031
- console.error('\n❌ 摘要不能为空\n');
1032
- process.exit(1);
1033
- }
1034
- }
1093
+ // 获取摘要(命令行参数,可选)
1094
+ const stepSummary = summary?.trim() ?? '';
1035
1095
  const nextStep = markStepDone(session, stepSummary, process.cwd());
1036
1096
  const progress = calcProgress(session);
1037
1097
  // 自动归档到 Skill Memory(T16)
@@ -1064,7 +1124,7 @@ workflowCmd
1064
1124
  if (copyToClipboard(prompt)) {
1065
1125
  console.log('\n✅ 下一步提示词已复制到剪贴板!');
1066
1126
  }
1067
- console.log(`\n💡 完成本步后,运行:ethan workflow done "你的本步摘要"${session.name ? ` --name ${session.name}` : ''}\n`);
1127
+ console.log(`\n💡 完成本步后,运行:ethan workflow done${session.name ? ` --name ${session.name}` : ''}\n`);
1068
1128
  // 记录使用统计
1069
1129
  const stats = readStats();
1070
1130
  stats[nextSkill.id] = (stats[nextSkill.id] || 0) + 1;
@@ -1121,7 +1181,7 @@ workflowCmd
1121
1181
  }
1122
1182
  else {
1123
1183
  console.log(`\n💡 当前任务背景:${session.initialContext}`);
1124
- console.log(` 完成当前步骤后运行:ethan workflow done "你的摘要"${session.name ? ` --name ${session.name}` : ''}\n`);
1184
+ console.log(` 完成当前步骤后运行:ethan workflow done${session.name ? ` --name ${session.name}` : ''}\n`);
1125
1185
  }
1126
1186
  });
1127
1187
  workflowCmd
@@ -1152,47 +1212,44 @@ workflowCmd
1152
1212
  });
1153
1213
  workflowCmd
1154
1214
  .command('list')
1155
- .description('列出所有可用的工作流 Pipeline 及进行中的具名会话')
1156
- .option('--sessions', '只列出所有具名会话(不列 Pipeline)')
1157
- .action(async (options) => {
1158
- const { PIPELINES } = await Promise.resolve().then(() => __importStar(require('../skills/pipeline')));
1159
- const { loadSession, calcProgress, listNamedSessions } = await Promise.resolve().then(() => __importStar(require('../workflow/state')));
1160
- // ── 列出具名会话 ─────────────────────────────────────────────────────────
1215
+ .description('列出所有进行中的会话(具名 + 默认)')
1216
+ .action(async () => {
1217
+ const { loadSession, calcProgress, listNamedSessions, getCurrentSessionName } = await Promise.resolve().then(() => __importStar(require('../workflow/state')));
1218
+ const currentActiveName = getCurrentSessionName(process.cwd());
1219
+ const defaultSession = loadSession(process.cwd(), undefined);
1161
1220
  const namedSessions = listNamedSessions(process.cwd());
1162
- if (namedSessions.length > 0 || options.sessions) {
1163
- console.log('\n📂 具名会话\n');
1164
- console.log('─'.repeat(60));
1165
- if (namedSessions.length === 0) {
1166
- console.log(' 暂无具名会话。使用 ethan workflow start --name <name> 创建。');
1167
- }
1168
- else {
1169
- for (const s of namedSessions) {
1170
- const pct = calcProgress(s);
1171
- const statusLabel = s.completed ? '🎉 已完成' : `${pct}% 进行中`;
1172
- console.log(`\n 📌 ${s.name || s.id} [${statusLabel}]`);
1173
- console.log(` Pipeline: ${s.pipelineName}`);
1174
- console.log(` 背景: ${s.initialContext.slice(0, 60)}${s.initialContext.length > 60 ? '…' : ''}`);
1175
- console.log(` 更新: ${s.updatedAt.slice(0, 19).replace('T', ' ')}`);
1176
- }
1221
+ console.log('\n📂 工作流会话\n');
1222
+ console.log(''.repeat(60));
1223
+ // 默认会话
1224
+ if (defaultSession) {
1225
+ const pct = calcProgress(defaultSession);
1226
+ const statusLabel = defaultSession.completed ? '🎉 已完成' : `${pct}% 进行中`;
1227
+ const activeTag = !currentActiveName ? ' ◀ 当前激活' : '';
1228
+ console.log(`\n 📋 默认会话${activeTag} [${statusLabel}]`);
1229
+ console.log(` Pipeline: ${defaultSession.pipelineName}`);
1230
+ console.log(` 背景: ${defaultSession.initialContext.slice(0, 60)}${defaultSession.initialContext.length > 60 ? '' : ''}`);
1231
+ console.log(` 更新: ${defaultSession.updatedAt.slice(0, 19).replace('T', ' ')}`);
1232
+ }
1233
+ // 具名会话
1234
+ if (namedSessions.length > 0) {
1235
+ for (const s of namedSessions) {
1236
+ const pct = calcProgress(s);
1237
+ const statusLabel = s.completed ? '🎉 已完成' : `${pct}% 进行中`;
1238
+ const isActive = s.name === currentActiveName;
1239
+ const activeTag = isActive ? ' ◀ 当前激活' : '';
1240
+ console.log(`\n 📌 ${s.name || s.id}${activeTag} [${statusLabel}]`);
1241
+ console.log(` Pipeline: ${s.pipelineName}`);
1242
+ console.log(` 背景: ${s.initialContext.slice(0, 60)}${s.initialContext.length > 60 ? '…' : ''}`);
1243
+ console.log(` 更新: ${s.updatedAt.slice(0, 19).replace('T', ' ')}`);
1177
1244
  }
1178
- console.log('\n' + '─'.repeat(60));
1179
- if (options.sessions)
1180
- return;
1181
1245
  }
1182
- const current = loadSession(process.cwd());
1183
- console.log('\n🔄 可用工作流\n');
1184
- console.log('─'.repeat(60));
1185
- for (const p of PIPELINES) {
1186
- const isCurrent = current?.pipelineId === p.id && !current.completed;
1187
- const tag = isCurrent ? ` ◀ 进行中(${calcProgress(current)}%)` : '';
1188
- console.log(`\n ${p.id}${tag}`);
1189
- console.log(` 名称:${p.name}`);
1190
- console.log(` 描述:${p.description}`);
1191
- console.log(` 步骤:${p.skillIds.join(' → ')}`);
1246
+ if (!defaultSession && namedSessions.length === 0) {
1247
+ console.log(' 暂无工作流会话。');
1192
1248
  }
1193
1249
  console.log('\n' + '─'.repeat(60));
1194
- console.log('\n启动工作流:ethan workflow start <pipeline-id> -c "任务描述"');
1195
- console.log('具名会话: ethan workflow start <pipeline-id> --name <name> -c "任务描述"\n');
1250
+ console.log('\n💡 启动工作流:ethan workflow start');
1251
+ console.log(' 激活会话: ethan workflow use <session-name>');
1252
+ console.log(' 查看 Pipeline:ethan pipeline list\n');
1196
1253
  });
1197
1254
  workflowCmd
1198
1255
  .command('report')