@nick848/sf-cli 1.0.12 → 1.0.14

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
@@ -5,6 +5,55 @@ All notable changes to this project will be documented in this file.
5
5
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
6
6
  and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
7
 
8
+ ## v1.0.13 (2026-03-22)
9
+
10
+ **修复 DeepSeek API Key 验证**
11
+
12
+ - 🐛 修复 DeepSeek API Key 验证失败问题
13
+ - 🔧 DeepSeek 适配器现在使用正确的 API 端点 `https://api.deepseek.com/v1`
14
+ - 🔧 验证和调用都使用 DeepSeek 专用端点,而非 OpenAI 端点
15
+
16
+ **问题原因**
17
+
18
+ DeepSeek 使用 OpenAI 兼容接口,但 API 端点不同:
19
+ - OpenAI: `https://api.openai.com/v1`
20
+ - DeepSeek: `https://api.deepseek.com/v1`
21
+
22
+ 之前验证时使用了 OpenAI 端点导致验证失败。
23
+
24
+ ## v1.0.12 (2026-03-22)
25
+
26
+ **交互优化 - API Key 配置引导**
27
+
28
+ - ✨ 启动时检查 API Key 配置状态,未配置时显示引导信息
29
+ - ✨ 自然语言处理功能实现 - 可直接与 AI 对话
30
+ - 🔧 简化权限逻辑:
31
+ - `/model` 等基础命令始终可用
32
+ - `/new` 需要先配置 API Key
33
+ - 自然语言输入始终可用(内部检查 API Key)
34
+
35
+ **引导流程**
36
+
37
+ ```
38
+ 启动 CLI
39
+
40
+ 检查 API Key
41
+ ↓ 未配置
42
+ ━━━━━━━━━━━━━━━━━━━
43
+ ⚠️ 未配置 API Key
44
+
45
+ 请先配置模型以启用 AI 功能:
46
+ /model - 交互式选择模型并配置 API Key
47
+ /model list - 查看可用模型列表
48
+
49
+ 支持: GLM-5, GPT-4o, Claude
50
+ ━━━━━━━━━━━━━━━━━━━
51
+ ↓ 配置完成
52
+ ✓ 已配置模型: GLM-5
53
+ 💡 使用 /new <需求描述> 启动新工作流
54
+ 或直接输入自然语言与 AI 交互
55
+ ```
56
+
8
57
  ## v1.0.11 (2026-03-22)
9
58
 
10
59
  **重大更新 - 规格确认后自动执行开发流程**
package/dist/cli/index.js CHANGED
@@ -1018,6 +1018,8 @@ function createAdapter(provider) {
1018
1018
  }
1019
1019
  function createDeepSeekAdapter() {
1020
1020
  const adapter = new OpenAIAdapter();
1021
+ let initialized = false;
1022
+ let config = null;
1021
1023
  return {
1022
1024
  get name() {
1023
1025
  return "DeepSeek";
@@ -1028,14 +1030,41 @@ function createDeepSeekAdapter() {
1028
1030
  get models() {
1029
1031
  return adapter.models;
1030
1032
  },
1031
- initialize: (config) => adapter.initialize(config),
1032
- sendMessage: (messages, options) => adapter.sendMessage(messages, options),
1033
- streamMessage: (messages, options) => adapter.streamMessage(messages, options),
1034
- countTokens: (text) => adapter.countTokens(text),
1035
- validateApiKey: (apiKey) => adapter.validateApiKey(apiKey),
1036
- isInitialized: () => adapter.isInitialized()
1033
+ async initialize(modelConfig) {
1034
+ config = {
1035
+ ...modelConfig,
1036
+ apiEndpoint: DEEPSEEK_API_ENDPOINT
1037
+ };
1038
+ await adapter.initialize(config);
1039
+ initialized = true;
1040
+ },
1041
+ async sendMessage(messages, options) {
1042
+ return adapter.sendMessage(messages, options);
1043
+ },
1044
+ async *streamMessage(messages, options) {
1045
+ yield* adapter.streamMessage(messages, options);
1046
+ },
1047
+ countTokens(text) {
1048
+ return adapter.countTokens(text);
1049
+ },
1050
+ async validateApiKey(apiKey) {
1051
+ try {
1052
+ const response = await fetch(`${DEEPSEEK_API_ENDPOINT}/models`, {
1053
+ headers: {
1054
+ "Authorization": `Bearer ${apiKey}`
1055
+ }
1056
+ });
1057
+ return response.ok;
1058
+ } catch {
1059
+ return false;
1060
+ }
1061
+ },
1062
+ isInitialized() {
1063
+ return initialized;
1064
+ }
1037
1065
  };
1038
1066
  }
1067
+ var DEEPSEEK_API_ENDPOINT;
1039
1068
  var init_adapters = __esm({
1040
1069
  "src/services/adapters/index.ts"() {
1041
1070
  init_cjs_shims();
@@ -1046,6 +1075,7 @@ var init_adapters = __esm({
1046
1075
  init_glm();
1047
1076
  init_openai();
1048
1077
  init_claude();
1078
+ DEEPSEEK_API_ENDPOINT = "https://api.deepseek.com/v1";
1049
1079
  }
1050
1080
  });
1051
1081
  var ModelService;
@@ -6936,7 +6966,7 @@ async function executeShell(command, ctx) {
6936
6966
  init_cjs_shims();
6937
6967
  init_new();
6938
6968
  async function handleNaturalLanguage(input, ctx) {
6939
- input.trim().toLowerCase();
6969
+ const trimmedInput = input.trim();
6940
6970
  const session = getActiveSession();
6941
6971
  if (session) {
6942
6972
  const result = await handleWorkflowInput(input, ctx);
@@ -6947,81 +6977,163 @@ async function handleNaturalLanguage(input, ctx) {
6947
6977
  };
6948
6978
  }
6949
6979
  }
6950
- ctx.contextManager.addMessage({
6951
- role: "user",
6952
- content: input
6953
- });
6954
- return {
6955
- output: chalk9__default.default.cyan("\u6B63\u5728\u601D\u8003...") + chalk9__default.default.yellow("\n\n\u81EA\u7136\u8BED\u8A00\u5904\u7406\u529F\u80FD\u5F00\u53D1\u4E2D...") + chalk9__default.default.gray(`
6956
- \u8F93\u5165: ${input}`),
6957
- contextUsed: input.length
6958
- };
6980
+ const apiKey = ctx.configManager.get("apiKey");
6981
+ if (!apiKey) {
6982
+ return {
6983
+ output: chalk9__default.default.yellow("\u26A0\uFE0F \u672A\u914D\u7F6E API Key\uFF0C\u65E0\u6CD5\u4F7F\u7528 AI \u529F\u80FD") + chalk9__default.default.gray("\n\n\u8BF7\u5148\u6267\u884C /model \u914D\u7F6E\u6A21\u578B") + chalk9__default.default.gray("\n\u652F\u6301: GLM-5, GPT-4o, Claude"),
6984
+ contextUsed: 0
6985
+ };
6986
+ }
6987
+ try {
6988
+ const response = await ctx.modelService.sendMessage(
6989
+ [
6990
+ {
6991
+ role: "system",
6992
+ content: buildSystemPrompt(ctx)
6993
+ },
6994
+ {
6995
+ role: "user",
6996
+ content: trimmedInput
6997
+ }
6998
+ ],
6999
+ {
7000
+ temperature: 0.7,
7001
+ maxTokens: 2e3
7002
+ }
7003
+ );
7004
+ ctx.contextManager.addMessage({
7005
+ role: "user",
7006
+ content: trimmedInput
7007
+ });
7008
+ ctx.contextManager.addMessage({
7009
+ role: "assistant",
7010
+ content: response.content
7011
+ });
7012
+ return {
7013
+ output: response.content,
7014
+ contextUsed: response.usage?.totalTokens || 0
7015
+ };
7016
+ } catch (error) {
7017
+ const errorMessage = error.message;
7018
+ if (errorMessage.includes("\u672A\u914D\u7F6E") || errorMessage.includes("\u672A\u521D\u59CB\u5316")) {
7019
+ return {
7020
+ output: chalk9__default.default.yellow("\u26A0\uFE0F \u6A21\u578B\u672A\u6B63\u786E\u914D\u7F6E") + chalk9__default.default.gray("\n\n\u8BF7\u6267\u884C /model \u91CD\u65B0\u914D\u7F6E"),
7021
+ contextUsed: 0
7022
+ };
7023
+ }
7024
+ if (errorMessage.includes("timeout") || errorMessage.includes("\u8D85\u65F6")) {
7025
+ return {
7026
+ output: chalk9__default.default.red("\u2717 \u8BF7\u6C42\u8D85\u65F6\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5"),
7027
+ contextUsed: 0
7028
+ };
7029
+ }
7030
+ return {
7031
+ output: chalk9__default.default.red(`\u2717 \u5904\u7406\u5931\u8D25: ${errorMessage}`),
7032
+ contextUsed: 0
7033
+ };
7034
+ }
7035
+ }
7036
+ function buildSystemPrompt(ctx) {
7037
+ const parts = [
7038
+ "\u4F60\u662F sf-cli \u7684 AI \u52A9\u624B\uFF0C\u4E00\u4E2A\u4E13\u4E1A\u7684\u8F6F\u4EF6\u5F00\u53D1\u52A9\u624B\u3002",
7039
+ "",
7040
+ "\u4F60\u53EF\u4EE5\u5E2E\u52A9\u7528\u6237\uFF1A",
7041
+ "1. \u7406\u89E3\u548C\u5206\u6790\u9700\u6C42",
7042
+ "2. \u63D0\u4F9B\u4EE3\u7801\u5EFA\u8BAE\u548C\u5B9E\u73B0\u65B9\u6848",
7043
+ "3. \u56DE\u7B54\u6280\u672F\u95EE\u9898",
7044
+ "4. \u8F85\u52A9\u8FDB\u884C\u4EE3\u7801\u5BA1\u67E5",
7045
+ "",
7046
+ "\u5F53\u524D\u9879\u76EE\u4FE1\u606F\uFF1A",
7047
+ `- \u5DE5\u4F5C\u76EE\u5F55: ${ctx.options.workingDirectory}`,
7048
+ `- \u6A21\u578B: ${ctx.modelService.getCurrentModel() || "\u672A\u6307\u5B9A"}`
7049
+ ];
7050
+ return parts.join("\n");
6959
7051
  }
6960
7052
 
6961
7053
  // src/cli/executor.ts
6962
7054
  init_new();
6963
- var BASIC_COMMANDS = [
7055
+ var ALWAYS_ALLOWED = [
6964
7056
  "help",
6965
7057
  "h",
6966
7058
  "?",
6967
- "init",
6968
- "i",
6969
7059
  "model",
6970
7060
  "m",
6971
- "new",
6972
- "n",
6973
7061
  "exit",
6974
7062
  "e",
6975
7063
  "q",
6976
7064
  "quit",
6977
7065
  "clear",
6978
7066
  "c",
6979
- "update",
6980
- "u",
6981
7067
  "version",
6982
7068
  "v"
6983
7069
  ];
7070
+ var REQUIRES_API_KEY = [
7071
+ "new",
7072
+ "n",
7073
+ "init",
7074
+ "i",
7075
+ "update",
7076
+ "u"
7077
+ ];
6984
7078
  var CommandExecutor = class {
6985
7079
  async execute(parseResult, ctx) {
6986
7080
  if (!parseResult.success || !parseResult.command) {
6987
7081
  return { output: chalk9__default.default.red(`\u9519\u8BEF: ${parseResult.error}`) };
6988
7082
  }
6989
7083
  const { command } = parseResult;
7084
+ const hasApiKey = !!ctx.configManager.get("apiKey");
6990
7085
  const hasActiveWorkflow = getActiveSession() !== null;
6991
- if (!hasActiveWorkflow) {
6992
- if (command.type === "slash" /* SLASH */) {
6993
- const cmd = command.command?.toLowerCase() || "";
6994
- if (!BASIC_COMMANDS.includes(cmd)) {
7086
+ if (command.type === "slash" /* SLASH */) {
7087
+ const cmd = command.command?.toLowerCase() || "";
7088
+ if (ALWAYS_ALLOWED.includes(cmd)) {
7089
+ return this.executeSlashCommand(command, ctx);
7090
+ }
7091
+ if (REQUIRES_API_KEY.includes(cmd)) {
7092
+ if (!hasApiKey) {
6995
7093
  return {
6996
- output: chalk9__default.default.yellow("\u5F53\u524D\u6CA1\u6709\u6D3B\u8DC3\u7684\u5DE5\u4F5C\u6D41") + chalk9__default.default.gray("\n\u8BF7\u5148\u4F7F\u7528 ") + chalk9__default.default.cyan("/new <\u9700\u6C42\u63CF\u8FF0>") + chalk9__default.default.gray(" \u542F\u52A8\u65B0\u5DE5\u4F5C\u6D41")
7094
+ output: chalk9__default.default.yellow("\u26A0\uFE0F \u8BF7\u5148\u914D\u7F6E API Key") + chalk9__default.default.gray("\n\n\u6267\u884C /model \u9009\u62E9\u6A21\u578B\u5E76\u914D\u7F6E API Key")
6997
7095
  };
6998
7096
  }
6999
- } else if (command.type === "dollar" /* DOLLAR */) {
7097
+ return this.executeSlashCommand(command, ctx);
7098
+ }
7099
+ if (!hasActiveWorkflow) {
7100
+ return {
7101
+ output: chalk9__default.default.yellow("\u5F53\u524D\u6CA1\u6709\u6D3B\u8DC3\u7684\u5DE5\u4F5C\u6D41") + chalk9__default.default.gray("\n\u8BF7\u5148\u4F7F\u7528 ") + chalk9__default.default.cyan("/new <\u9700\u6C42\u63CF\u8FF0>") + chalk9__default.default.gray(" \u542F\u52A8\u65B0\u5DE5\u4F5C\u6D41")
7102
+ };
7103
+ }
7104
+ return this.executeSlashCommand(command, ctx);
7105
+ }
7106
+ if (command.type === "dollar" /* DOLLAR */) {
7107
+ if (!hasActiveWorkflow) {
7000
7108
  return {
7001
7109
  output: chalk9__default.default.yellow("\u5F53\u524D\u6CA1\u6709\u6D3B\u8DC3\u7684\u5DE5\u4F5C\u6D41\uFF0C\u65E0\u6CD5\u8C03\u7528 Agent") + chalk9__default.default.gray("\n\u8BF7\u5148\u4F7F\u7528 ") + chalk9__default.default.cyan("/new <\u9700\u6C42\u63CF\u8FF0>") + chalk9__default.default.gray(" \u542F\u52A8\u65B0\u5DE5\u4F5C\u6D41")
7002
7110
  };
7003
- } else if (command.type === "shell" /* SHELL */) {
7111
+ }
7112
+ if (!hasApiKey) {
7113
+ return {
7114
+ output: chalk9__default.default.yellow("\u26A0\uFE0F \u8BF7\u5148\u914D\u7F6E API Key") + chalk9__default.default.gray("\n\n\u6267\u884C /model \u914D\u7F6E\u6A21\u578B")
7115
+ };
7116
+ }
7117
+ return this.executeAgent(command, ctx);
7118
+ }
7119
+ if (command.type === "shell" /* SHELL */) {
7120
+ if (!hasActiveWorkflow) {
7004
7121
  return {
7005
7122
  output: chalk9__default.default.yellow("\u5F53\u524D\u6CA1\u6709\u6D3B\u8DC3\u7684\u5DE5\u4F5C\u6D41\uFF0C\u65E0\u6CD5\u6267\u884C Shell \u547D\u4EE4") + chalk9__default.default.gray("\n\u8BF7\u5148\u4F7F\u7528 ") + chalk9__default.default.cyan("/new <\u9700\u6C42\u63CF\u8FF0>") + chalk9__default.default.gray(" \u542F\u52A8\u65B0\u5DE5\u4F5C\u6D41")
7006
7123
  };
7007
7124
  }
7125
+ return this.executeShell(command, ctx);
7008
7126
  }
7009
- switch (command.type) {
7010
- case "slash" /* SLASH */:
7011
- return this.executeSlashCommand(command, ctx);
7012
- case "at" /* AT */:
7013
- return this.executeFileReference(command, ctx);
7014
- case "dollar" /* DOLLAR */:
7015
- return this.executeAgent(command, ctx);
7016
- case "shell" /* SHELL */:
7017
- return this.executeShell(command, ctx);
7018
- case "natural" /* NATURAL */:
7019
- return this.executeNaturalLanguage(command, ctx);
7020
- case "yolo" /* YOLO */:
7021
- return this.executeYolo(ctx);
7022
- default:
7023
- return { output: chalk9__default.default.red("\u672A\u77E5\u7684\u547D\u4EE4\u7C7B\u578B") };
7127
+ if (command.type === "at" /* AT */) {
7128
+ return this.executeFileReference(command, ctx);
7129
+ }
7130
+ if (command.type === "natural" /* NATURAL */) {
7131
+ return this.executeNaturalLanguage(command, ctx);
7132
+ }
7133
+ if (command.type === "yolo" /* YOLO */) {
7134
+ return this.executeYolo(ctx);
7024
7135
  }
7136
+ return { output: chalk9__default.default.red("\u672A\u77E5\u7684\u547D\u4EE4\u7C7B\u578B") };
7025
7137
  }
7026
7138
  async executeSlashCommand(command, ctx) {
7027
7139
  const result = await runSlashCommand(
@@ -7670,6 +7782,7 @@ async function startInteractiveMode(options) {
7670
7782
  contextLimit: 512 * 1024
7671
7783
  };
7672
7784
  const currentModel = modelService.getCurrentModel() || "GLM-5";
7785
+ const hasApiKey = !!configManager.get("apiKey");
7673
7786
  const activeSession2 = getActiveSession();
7674
7787
  displayStatus({
7675
7788
  directory: options.workingDirectory,
@@ -7678,14 +7791,34 @@ async function startInteractiveMode(options) {
7678
7791
  services: [],
7679
7792
  workflowStep: activeSession2?.phase
7680
7793
  });
7681
- if (activeSession2) {
7682
- console.log(chalk9__default.default.cyan(`
7794
+ if (!hasApiKey) {
7795
+ console.log("");
7796
+ console.log(chalk9__default.default.yellow.bold("\u26A0\uFE0F \u672A\u914D\u7F6E API Key"));
7797
+ console.log("");
7798
+ console.log(chalk9__default.default.gray("\u8BF7\u5148\u914D\u7F6E\u6A21\u578B\u4EE5\u542F\u7528 AI \u529F\u80FD:"));
7799
+ console.log("");
7800
+ console.log(chalk9__default.default.cyan(" /model ") + chalk9__default.default.gray("- \u4EA4\u4E92\u5F0F\u9009\u62E9\u6A21\u578B\u5E76\u914D\u7F6E API Key"));
7801
+ console.log(chalk9__default.default.cyan(" /model list ") + chalk9__default.default.gray("- \u67E5\u770B\u53EF\u7528\u6A21\u578B\u5217\u8868"));
7802
+ console.log(chalk9__default.default.cyan(" /model set <model-id> ") + chalk9__default.default.gray("- \u76F4\u63A5\u8BBE\u7F6E\u6A21\u578B"));
7803
+ console.log("");
7804
+ console.log(chalk9__default.default.gray("\u652F\u6301\u7684\u6A21\u578B:"));
7805
+ console.log(chalk9__default.default.gray(" \u2022 GLM-5 (\u667A\u8C31AI) - \u63A8\u8350"));
7806
+ console.log(chalk9__default.default.gray(" \u2022 GPT-4o (OpenAI)"));
7807
+ console.log(chalk9__default.default.gray(" \u2022 Claude (Anthropic)"));
7808
+ console.log("");
7809
+ console.log(chalk9__default.default.gray("\u2500".repeat(50)));
7810
+ } else {
7811
+ if (activeSession2) {
7812
+ console.log(chalk9__default.default.cyan(`
7683
7813
  \u{1F4CB} \u6D3B\u8DC3\u5DE5\u4F5C\u6D41: ${activeSession2.requirement.slice(0, 40)}...`));
7684
- console.log(chalk9__default.default.gray(` \u9636\u6BB5: ${activeSession2.phase}`));
7685
- console.log(chalk9__default.default.gray(` \u8F93\u5165\u4EFB\u610F\u5185\u5BB9\u7EE7\u7EED
7814
+ console.log(chalk9__default.default.gray(` \u9636\u6BB5: ${activeSession2.phase}`));
7815
+ console.log(chalk9__default.default.gray(` \u8F93\u5165\u4EFB\u610F\u5185\u5BB9\u7EE7\u7EED
7686
7816
  `));
7687
- } else {
7688
- console.log(chalk9__default.default.gray("\n\u{1F4A1} \u4F7F\u7528 /new <\u9700\u6C42\u63CF\u8FF0> \u542F\u52A8\u65B0\u5DE5\u4F5C\u6D41\n"));
7817
+ } else {
7818
+ console.log(chalk9__default.default.green("\n\u2713 \u5DF2\u914D\u7F6E\u6A21\u578B: ") + chalk9__default.default.white(currentModel));
7819
+ console.log(chalk9__default.default.gray("\n\u{1F4A1} \u4F7F\u7528 /new <\u9700\u6C42\u63CF\u8FF0> \u542F\u52A8\u65B0\u5DE5\u4F5C\u6D41"));
7820
+ console.log(chalk9__default.default.gray(" \u6216\u76F4\u63A5\u8F93\u5165\u81EA\u7136\u8BED\u8A00\u4E0E AI \u4EA4\u4E92\n"));
7821
+ }
7689
7822
  }
7690
7823
  const saveHistory = async () => {
7691
7824
  try {