atomix-cli 1.1.0 → 1.2.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/dist/tui.mjs CHANGED
@@ -27296,8 +27296,14 @@ var require_adapter = __commonJS({
27296
27296
  "../atomix-core/dist/util/adapter.js"(exports2) {
27297
27297
  "use strict";
27298
27298
  Object.defineProperty(exports2, "__esModule", { value: true });
27299
- exports2.TEMPERATURE_ONE_MODELS = void 0;
27299
+ exports2.TEMPERATURE_MAX = exports2.TEMPERATURE_MIN = exports2.DEFAULT_ANTHROPIC_TEMPERATURE = exports2.TEMPERATURE_ONE_MODELS = void 0;
27300
27300
  exports2.resolveAdapter = resolveAdapter;
27301
+ exports2.openaiTemperatureCapability = openaiTemperatureCapability;
27302
+ exports2.modelForcesTemperatureOne = modelForcesTemperatureOne3;
27303
+ exports2.modelRejectsTemperature = modelRejectsTemperature3;
27304
+ exports2.modelTemperatureGatedByThinking = modelTemperatureGatedByThinking3;
27305
+ exports2.isValidTemperature = isValidTemperature3;
27306
+ exports2.assertTemperature = assertTemperature;
27301
27307
  exports2.useMaxCompletionTokens = useMaxCompletionTokens;
27302
27308
  exports2.modelForcesThinking = modelForcesThinking;
27303
27309
  exports2.forcedThinkingEffort = forcedThinkingEffort;
@@ -27346,6 +27352,60 @@ var require_adapter = __commonJS({
27346
27352
  "kimi-k2.5",
27347
27353
  "moonshotai/kimi-k2.5"
27348
27354
  ];
27355
+ var OPENAI_TEMPERATURE_NORMAL_PREFIXES = ["gpt-5-chat", "gpt-5.1-chat", "gpt-5.2-chat"];
27356
+ var OPENAI_TEMPERATURE_REJECT_EXACT = ["gpt-5"];
27357
+ var OPENAI_TEMPERATURE_REJECT_PREFIXES = [
27358
+ "o1",
27359
+ "o3",
27360
+ "o4",
27361
+ "gpt-5-mini",
27362
+ "gpt-5-nano",
27363
+ "gpt-5-20",
27364
+ // 初代及其日期快照(gpt-5-2025-08-07)
27365
+ "gpt-5-pro",
27366
+ "gpt-5.1-pro",
27367
+ "gpt-5.2-pro",
27368
+ "gpt-5-codex",
27369
+ "gpt-5.1-codex",
27370
+ "gpt-5.2-codex"
27371
+ ];
27372
+ var OPENAI_TEMPERATURE_GATED_PREFIXES = ["gpt-5.1", "gpt-5.2"];
27373
+ function bareModelName(modelName) {
27374
+ const lower = modelName.toLowerCase();
27375
+ return lower.split("/").pop() ?? lower;
27376
+ }
27377
+ function openaiTemperatureCapability(modelName) {
27378
+ const bare = bareModelName(modelName);
27379
+ if (OPENAI_TEMPERATURE_NORMAL_PREFIXES.some((p) => bare.startsWith(p)))
27380
+ return "normal";
27381
+ if (OPENAI_TEMPERATURE_REJECT_EXACT.includes(bare) || OPENAI_TEMPERATURE_REJECT_PREFIXES.some((p) => bare.startsWith(p)))
27382
+ return "reject";
27383
+ if (OPENAI_TEMPERATURE_GATED_PREFIXES.some((p) => bare.startsWith(p)))
27384
+ return "gated";
27385
+ if (bare.startsWith("gpt-5"))
27386
+ return "reject";
27387
+ return null;
27388
+ }
27389
+ function modelForcesTemperatureOne3(modelName) {
27390
+ return exports2.TEMPERATURE_ONE_MODELS.includes(modelName);
27391
+ }
27392
+ function modelRejectsTemperature3(modelName) {
27393
+ return openaiTemperatureCapability(modelName) === "reject";
27394
+ }
27395
+ function modelTemperatureGatedByThinking3(modelName) {
27396
+ return openaiTemperatureCapability(modelName) === "gated";
27397
+ }
27398
+ function isValidTemperature3(t) {
27399
+ return typeof t === "number" && Number.isFinite(t) && t >= exports2.TEMPERATURE_MIN && t <= exports2.TEMPERATURE_MAX;
27400
+ }
27401
+ exports2.DEFAULT_ANTHROPIC_TEMPERATURE = 0.7;
27402
+ exports2.TEMPERATURE_MIN = 0;
27403
+ exports2.TEMPERATURE_MAX = 2;
27404
+ function assertTemperature(t) {
27405
+ if (!isValidTemperature3(t)) {
27406
+ throw new Error(`temperature \u987B\u4E3A ${exports2.TEMPERATURE_MIN}\u2013${exports2.TEMPERATURE_MAX} \u7684\u6570\u5B57,\u6536\u5230 ${JSON.stringify(t)}`);
27407
+ }
27408
+ }
27349
27409
  var MAX_COMPLETION_TOKENS_PREFIXES = [
27350
27410
  "o1",
27351
27411
  "o3",
@@ -27539,7 +27599,8 @@ var require_apiUtil = __commonJS({
27539
27599
  model: modelName,
27540
27600
  messages: [{ role: "user", content: 'Please respond with exactly "YES" (in capital letters) to confirm this connection is working.' }],
27541
27601
  ...(0, adapter_1.useMaxCompletionTokens)(modelName) ? { max_completion_tokens: 200 } : { max_tokens: 200 },
27542
- temperature: adapter_1.TEMPERATURE_ONE_MODELS.includes(modelName) ? 1 : 0,
27602
+ // 不发 temperature:与正式请求(adapt/openai.ts)一致,交给服务端默认。之前固定发 0.0,
27603
+ // gpt-5 / o 系列等只接受默认值 1 的模型直接 400("does not support 0.0 with this model"),把可用模型挡在添加阶段
27543
27604
  stream: false
27544
27605
  }),
27545
27606
  extractContent: (response) => response.choices?.[0]?.message?.content || "",
@@ -44624,7 +44685,8 @@ var require_model = __commonJS({
44624
44685
  apiKey: config.apiKey,
44625
44686
  maxTokens: config.maxTokens || fallback.maxTokens,
44626
44687
  contextLength: config.contextLength || fallback.contextLength,
44627
- adapt: config.adapt ?? (0, adapter_1.resolveAdapter)(config.provider, config.modelName)
44688
+ adapt: config.adapt ?? (0, adapter_1.resolveAdapter)(config.provider, config.modelName),
44689
+ ...config.temperature !== void 0 ? { temperature: config.temperature } : {}
44628
44690
  };
44629
44691
  }
44630
44692
  }
@@ -44675,10 +44737,12 @@ var require_ModelManager = __commonJS({
44675
44737
  exports2.getModelManager = exports2.ModelManager = void 0;
44676
44738
  var fs14 = __importStar(__require("fs"));
44677
44739
  var path15 = __importStar(__require("path"));
44740
+ var adapter_1 = require_adapter();
44678
44741
  var apiUtil_1 = require_apiUtil();
44679
44742
  var savePath_1 = require_savePath();
44680
44743
  var model_1 = require_model();
44681
44744
  var log_1 = require_log();
44745
+ var EngineContext_1 = require_EngineContext();
44682
44746
  var ModelManager = class {
44683
44747
  constructor(initialConfig) {
44684
44748
  this.configPath = (0, savePath_1.getModelConfigFilePath)();
@@ -44706,6 +44770,8 @@ var require_ModelManager = __commonJS({
44706
44770
  * @param skipValidation 是否跳过API校验,默认为false
44707
44771
  */
44708
44772
  async addNewModel(config, skipValidation = false) {
44773
+ if (config.temperature !== void 0)
44774
+ this.assertProfileTemperature(config.modelName, config.temperature);
44709
44775
  const profile = (0, model_1.convertToModelProfile)(config);
44710
44776
  const existingModelIndex = this.config.modelProfiles.findIndex((p) => p.name === profile.name);
44711
44777
  if (!skipValidation) {
@@ -44734,7 +44800,7 @@ ${testResult.curlCommand}` : testResult.message;
44734
44800
  }
44735
44801
  }
44736
44802
  if (existingModelIndex !== -1) {
44737
- this.config.modelProfiles[existingModelIndex] = profile;
44803
+ this.config.modelProfiles[existingModelIndex] = { ...this.config.modelProfiles[existingModelIndex], ...profile };
44738
44804
  } else {
44739
44805
  this.config.modelProfiles.push(profile);
44740
44806
  if (this.config.modelProfiles.length === 1) {
@@ -44833,16 +44899,36 @@ ${testResult.curlCommand}` : testResult.message;
44833
44899
  };
44834
44900
  }
44835
44901
  /**
44836
- * 获取指定类型的模型配置
44902
+ * 解析指针槽位实际指向的模型标识(harness-model-v1 §2):
44903
+ * 当前会话(EngineStore.coreConfig.modelOverrides)有覆盖则用覆盖,否则用 model.conf 指针。
44904
+ * ALS 之外(无 EngineStore)读不到覆盖 = base。
44905
+ */
44906
+ resolvePointer(pointer) {
44907
+ const override = (0, EngineContext_1.getEngineStore)()?.coreConfig?.modelOverrides?.[pointer];
44908
+ if (typeof override === "string" && override)
44909
+ return { id: override, overridden: true };
44910
+ return { id: this.config.modelPointers?.[pointer] || null, overridden: false };
44911
+ }
44912
+ /**
44913
+ * 获取指定类型的模型配置(会话覆盖优先)。
44914
+ * 覆盖指向的 profile 已不存在(会话中被删)时返回 null,由调用方报错——不静默回落 base。
44837
44915
  */
44838
44916
  getModel(pointer) {
44839
- const pointerId = this.config.modelPointers?.[pointer];
44840
- if (!pointerId) {
44917
+ const { id } = this.resolvePointer(pointer);
44918
+ if (!id) {
44841
44919
  return null;
44842
44920
  }
44843
- const profile = (0, model_1.findModelProfile)(pointerId, this.config.modelProfiles);
44921
+ const profile = (0, model_1.findModelProfile)(id, this.config.modelProfiles);
44844
44922
  return profile || null;
44845
44923
  }
44924
+ /** 已配置的模型标识列表(同步;harness 解析是同步纯函数,不能等异步 getModelData)。 */
44925
+ getModelNames() {
44926
+ return this.config.modelProfiles.map((p) => p.name);
44927
+ }
44928
+ /** model.conf 的指针值(base,不含会话覆盖;同步)。 */
44929
+ getModelPointers() {
44930
+ return { main: this.config.modelPointers?.main ?? "", quick: this.config.modelPointers?.quick ?? "" };
44931
+ }
44846
44932
  /**
44847
44933
  * 获取指定类型的模型名称
44848
44934
  */
@@ -44850,6 +44936,89 @@ ${testResult.curlCommand}` : testResult.message;
44850
44936
  const profile = this.getModel(pointer);
44851
44937
  return profile ? profile.modelName : null;
44852
44938
  }
44939
+ // ===================== 温度 / profile 字段编辑(model-temperature-v1) =====================
44940
+ /** 去 apiKey 的只读视图;adapt 补齐(缺省按 provider/modelName 推断),cli 展示"协议默认"时不必再算 */
44941
+ getModelProfiles() {
44942
+ return this.config.modelProfiles.map((p) => {
44943
+ const { apiKey: _k, ...rest2 } = p;
44944
+ return { ...rest2, adapt: p.adapt ?? (0, adapter_1.resolveAdapter)(p.provider, p.modelName) };
44945
+ });
44946
+ }
44947
+ /**
44948
+ * 改单个 profile 的字段,不重跑连通性测试。`'temperature' in patch && patch.temperature === undefined` = 清除。
44949
+ * 硬约束模型(TEMPERATURE_ONE_MODELS)拒绝设温度:覆盖只会换来 4xx。
44950
+ */
44951
+ async updateModelProfile(name, patch) {
44952
+ const idx = this.config.modelProfiles.findIndex((p) => p.name === name);
44953
+ if (idx === -1)
44954
+ throw new Error(`\u6A21\u578B\u4E0D\u5B58\u5728: ${name}`);
44955
+ const next = { ...this.config.modelProfiles[idx] };
44956
+ if ("temperature" in patch) {
44957
+ if (patch.temperature === void 0)
44958
+ delete next.temperature;
44959
+ else {
44960
+ this.assertProfileTemperature(next.modelName, patch.temperature);
44961
+ next.temperature = patch.temperature;
44962
+ }
44963
+ }
44964
+ for (const k of ["maxTokens", "contextLength"]) {
44965
+ if (k in patch) {
44966
+ const v = patch[k];
44967
+ if (!Number.isInteger(v) || v <= 0)
44968
+ throw new Error(`${k} \u987B\u4E3A\u6B63\u6574\u6570,\u6536\u5230 ${JSON.stringify(v)}`);
44969
+ next[k] = v;
44970
+ }
44971
+ }
44972
+ if ("vision" in patch) {
44973
+ if (patch.vision === void 0)
44974
+ delete next.vision;
44975
+ else if (typeof patch.vision !== "boolean")
44976
+ throw new Error(`vision \u987B\u4E3A\u5E03\u5C14\u503C`);
44977
+ else
44978
+ next.vision = patch.vision;
44979
+ }
44980
+ this.config.modelProfiles[idx] = next;
44981
+ await this.saveConfig();
44982
+ const { apiKey: _k, ...rest2 } = next;
44983
+ return { ...rest2, adapt: next.adapt ?? (0, adapter_1.resolveAdapter)(next.provider, next.modelName) };
44984
+ }
44985
+ /** 范围校验 + 模型侧约束拒绝;addNewModel / updateModelProfile 共用。gpt-5 系列允许配置(thinking 关时生效),这里不挡 */
44986
+ assertProfileTemperature(modelName, t) {
44987
+ (0, adapter_1.assertTemperature)(t);
44988
+ if ((0, adapter_1.modelForcesTemperatureOne)(modelName))
44989
+ throw new Error(`\u6A21\u578B ${modelName} \u53EA\u63A5\u53D7\u9ED8\u8BA4\u6E29\u5EA6 1,\u4E0D\u80FD\u8BBE\u7F6E temperature`);
44990
+ if ((0, adapter_1.modelRejectsTemperature)(modelName))
44991
+ throw new Error(`\u6A21\u578B ${modelName} \u4E0D\u652F\u6301 temperature \u53C2\u6570(\u63A8\u7406\u6A21\u578B),\u4E0D\u80FD\u8BBE\u7F6E`);
44992
+ }
44993
+ /**
44994
+ * 请求时的温度解析(model-temperature-v1 §1.1),高者胜:
44995
+ * 1 模型侧约束:kimi 恒 1;o 系列永不发;gpt-5 系列 thinking 开(发 reasoning_effort)时不发;anthropic 协议开 thinking 不发;
44996
+ * 2 会话级覆盖(harness,经 EngineStore);3 profile.temperature;4 协议默认(anthropic 0.7,openai 不发)。
44997
+ * 返回 undefined = 请求体不带该字段。
44998
+ */
44999
+ resolveTemperature(pointer, profile, opts) {
45000
+ if ((0, adapter_1.modelForcesTemperatureOne)(profile.modelName))
45001
+ return 1;
45002
+ if ((0, adapter_1.modelRejectsTemperature)(profile.modelName))
45003
+ return void 0;
45004
+ if (opts.enableThinking && (0, adapter_1.modelTemperatureGatedByThinking)(profile.modelName))
45005
+ return void 0;
45006
+ if (opts.adapter === "anthropic" && opts.enableThinking)
45007
+ return void 0;
45008
+ const over2 = (0, EngineContext_1.getEngineStore)()?.coreConfig?.temperatureOverrides?.[pointer];
45009
+ if (over2 !== void 0 && !(0, adapter_1.isValidTemperature)(over2))
45010
+ (0, log_1.logWarn)(`temperatureOverrides.${pointer} \u975E\u6CD5(${JSON.stringify(over2)}),\u5FFD\u7565,\u6539\u7528 profile / \u9ED8\u8BA4`);
45011
+ if (profile.temperature !== void 0 && !(0, adapter_1.isValidTemperature)(profile.temperature))
45012
+ (0, log_1.logWarn)(`\u6A21\u578B ${profile.name} \u7684 temperature \u975E\u6CD5(${JSON.stringify(profile.temperature)}),\u5FFD\u7565,\u6539\u7528\u534F\u8BAE\u9ED8\u8BA4`);
45013
+ let t = (0, adapter_1.isValidTemperature)(over2) ? over2 : (0, adapter_1.isValidTemperature)(profile.temperature) ? profile.temperature : void 0;
45014
+ if (t === void 0)
45015
+ return opts.adapter === "anthropic" ? adapter_1.DEFAULT_ANTHROPIC_TEMPERATURE : void 0;
45016
+ if (opts.adapter === "anthropic" && t > 1) {
45017
+ (0, log_1.logWarn)(`temperature ${t} \u8D85\u51FA anthropic \u534F\u8BAE\u4E0A\u9650,\u6309 1 \u53D1\u9001(${profile.name})`);
45018
+ t = 1;
45019
+ }
45020
+ return t;
45021
+ }
44853
45022
  /**
44854
45023
  * 获取当前模型数据
44855
45024
  * @param showModelProfiles 是否包含详细的模型配置信息,默认为false
@@ -74973,13 +75142,15 @@ var require_cacheLLM = __commonJS({
74973
75142
  /**
74974
75143
  * 生成缓存键 - 基于消息内容生成简单hash
74975
75144
  */
74976
- generateKey(messages, systemPrompt, modelName, enableThinking = false) {
75145
+ generateKey(messages, systemPrompt, modelName, enableThinking = false, temperature) {
74977
75146
  const normalizedSystemPrompt = Array.isArray(systemPrompt) && systemPrompt.length > 0 && typeof systemPrompt[0] === "object" && "type" in systemPrompt[0] ? systemPrompt.map((item) => item.text) : systemPrompt;
74978
75147
  const content = JSON.stringify({
74979
75148
  messages: messages.map((msg) => msg.message.content),
74980
75149
  systemPrompt: normalizedSystemPrompt,
74981
75150
  modelName,
74982
- enableThinking
75151
+ enableThinking,
75152
+ temperature: temperature ?? null
75153
+ // 不同温度不共享缓存(model-temperature-v1)
74983
75154
  });
74984
75155
  return crypto_1.default.createHash("md5").update(content).digest("hex");
74985
75156
  }
@@ -75009,8 +75180,8 @@ var require_cacheLLM = __commonJS({
75009
75180
  /**
75010
75181
  * 获取缓存
75011
75182
  */
75012
- get(messages, systemPrompt, modelName, enableThinking = false) {
75013
- const key = this.generateKey(messages, systemPrompt, modelName, enableThinking);
75183
+ get(messages, systemPrompt, modelName, enableThinking = false, temperature) {
75184
+ const key = this.generateKey(messages, systemPrompt, modelName, enableThinking, temperature);
75014
75185
  const entries = this.readCacheFile();
75015
75186
  const entry = entries.find((e) => e.key === key);
75016
75187
  return entry ? entry.response : null;
@@ -75018,8 +75189,8 @@ var require_cacheLLM = __commonJS({
75018
75189
  /**
75019
75190
  * 设置缓存
75020
75191
  */
75021
- set(messages, systemPrompt, modelName, response, enableThinking = false) {
75022
- const key = this.generateKey(messages, systemPrompt, modelName, enableThinking);
75192
+ set(messages, systemPrompt, modelName, response, enableThinking = false, temperature) {
75193
+ const key = this.generateKey(messages, systemPrompt, modelName, enableThinking, temperature);
75023
75194
  let entries = this.readCacheFile();
75024
75195
  entries = entries.filter((e) => e.key !== key);
75025
75196
  entries.unshift({
@@ -75068,8 +75239,8 @@ var require_cache = __commonJS({
75068
75239
  var log_1 = require_log();
75069
75240
  var CACHE_STREAM_CHUNK_SIZE = 20;
75070
75241
  var CACHE_STREAM_DELAY = 100;
75071
- async function tryGetCachedResponse(messages, systemPromptContent, modelName, shouldStream, enableThinking, emitChunkEvents, signal) {
75072
- const cachedResponse = cacheLLM_1.llmCache.get(messages, systemPromptContent, modelName, enableThinking);
75242
+ async function tryGetCachedResponse(messages, systemPromptContent, modelName, shouldStream, enableThinking, emitChunkEvents, signal, temperature) {
75243
+ const cachedResponse = cacheLLM_1.llmCache.get(messages, systemPromptContent, modelName, enableThinking, temperature);
75073
75244
  if (!cachedResponse) {
75074
75245
  return null;
75075
75246
  }
@@ -75142,8 +75313,8 @@ var require_cache = __commonJS({
75142
75313
  function calcSimulatedDelay(contentLength, maxDelay) {
75143
75314
  return Math.min(Math.ceil(contentLength / CACHE_STREAM_CHUNK_SIZE) * CACHE_STREAM_DELAY, maxDelay);
75144
75315
  }
75145
- function setCachedResponse(messages, systemPromptContent, modelName, response, enableThinking = false) {
75146
- cacheLLM_1.llmCache.set(messages, systemPromptContent, modelName, response, enableThinking);
75316
+ function setCachedResponse(messages, systemPromptContent, modelName, response, enableThinking = false, temperature) {
75317
+ cacheLLM_1.llmCache.set(messages, systemPromptContent, modelName, response, enableThinking, temperature);
75147
75318
  }
75148
75319
  function getCacheSize() {
75149
75320
  return cacheLLM_1.llmCache.size();
@@ -88410,7 +88581,7 @@ var require_openai2 = __commonJS({
88410
88581
  }
88411
88582
  };
88412
88583
  }
88413
- async function queryOpenAI(messages, systemPromptContent, tools, signal, modelProfile, enableThinking, emitChunkEvents) {
88584
+ async function queryOpenAI(messages, systemPromptContent, tools, signal, modelProfile, enableThinking, temperature, emitChunkEvents) {
88414
88585
  const start = Date.now();
88415
88586
  let baseURL = modelProfile.baseURL || "https://api.openai.com/v1";
88416
88587
  const providerEndpoints = (0, providerEndpoint_1.getProviderEndpoints)(modelProfile.provider, baseURL);
@@ -88435,6 +88606,7 @@ var require_openai2 = __commonJS({
88435
88606
  stream: true,
88436
88607
  ...openaiTools && { tools: openaiTools },
88437
88608
  ...(0, adapter_1.useMaxCompletionTokens)(modelProfile.modelName) ? { max_completion_tokens: modelProfile.maxTokens || 8e3 } : { max_tokens: modelProfile.maxTokens || 8e3 },
88609
+ ...temperature !== void 0 && { temperature },
88438
88610
  // thinking 参数按 provider profile 统一构造(openai/openrouter/qwen/compat 等)
88439
88611
  ...(0, providerProfile_1.buildThinkingParams)(modelProfile, enableThinking)
88440
88612
  };
@@ -99644,7 +99816,7 @@ var require_anthropic = __commonJS({
99644
99816
  usage: usage2
99645
99817
  };
99646
99818
  }
99647
- async function queryAnthropic(messages, systemPromptContent, tools, signal, modelProfile, enableThinking, emitChunkEvents) {
99819
+ async function queryAnthropic(messages, systemPromptContent, tools, signal, modelProfile, enableThinking, temperature, emitChunkEvents) {
99648
99820
  const start = Date.now();
99649
99821
  const rawBaseURL = modelProfile.baseURL || "https://api.anthropic.com";
99650
99822
  const providerEndpoints = (0, providerEndpoint_1.getProviderEndpoints)(modelProfile.provider, rawBaseURL);
@@ -99665,7 +99837,7 @@ var require_anthropic = __commonJS({
99665
99837
  messages: anthropicMessages,
99666
99838
  system: systemPromptContent,
99667
99839
  max_tokens: modelProfile.maxTokens,
99668
- temperature: util_1.MAIN_QUERY_TEMPERATURE,
99840
+ ...temperature !== void 0 && { temperature },
99669
99841
  stream: true,
99670
99842
  ...anthropicTools && { tools: anthropicTools }
99671
99843
  };
@@ -99746,7 +99918,8 @@ var require_queryLLM = __commonJS({
99746
99918
  async function queryLLM(messages, systemPromptContent, signal, tools, modelPointer = "main", disableChunkEvents = false, suppressErrorEvent = false) {
99747
99919
  const modelProfile = (0, ModelManager_1.getModelManager)().getModel(modelPointer);
99748
99920
  if (!modelProfile) {
99749
- throw new Error(`\u89E3\u6790\u6A21\u578B\u5931\u8D25: ${modelPointer}`);
99921
+ const { id, overridden } = (0, ModelManager_1.getModelManager)().resolvePointer(modelPointer);
99922
+ throw new Error(id ? `\u89E3\u6790\u6A21\u578B\u5931\u8D25: ${modelPointer} \u2192 ${id} \u4E0D\u5728\u6A21\u578B\u914D\u7F6E\u4E2D${overridden ? "(\u4F1A\u8BDD\u7EA7\u8986\u76D6,\u6765\u81EA harness)" : ""}` : `\u89E3\u6790\u6A21\u578B\u5931\u8D25: ${modelPointer}`);
99750
99923
  }
99751
99924
  try {
99752
99925
  const coreConfig = (0, ConfManager_1.getConfManager)().getCoreConfig();
@@ -99754,30 +99927,31 @@ var require_queryLLM = __commonJS({
99754
99927
  const shouldStream = coreConfig?.stream !== false;
99755
99928
  const enableThinking = modelPointer !== "quick" && coreConfig?.thinking === true;
99756
99929
  const emitChunkEvents = !disableChunkEvents && shouldStream !== false;
99930
+ const adapt = modelProfile.adapt || (0, adapter_1.resolveAdapter)(modelProfile.provider, modelProfile.modelName);
99931
+ const temperature = (0, ModelManager_1.getModelManager)().resolveTemperature(modelPointer, modelProfile, { adapter: adapt, enableThinking });
99757
99932
  if (shouldUseCache) {
99758
- const cachedResponse = await (0, cache_1.tryGetCachedResponse)(messages, systemPromptContent, modelProfile.modelName, shouldStream, enableThinking, emitChunkEvents, signal);
99933
+ const cachedResponse = await (0, cache_1.tryGetCachedResponse)(messages, systemPromptContent, modelProfile.modelName, shouldStream, enableThinking, emitChunkEvents, signal, temperature);
99759
99934
  if (cachedResponse) {
99760
99935
  (0, logLLM_1.logLLMRequest)({ cached: true, model: modelProfile.modelName, messages });
99761
99936
  (0, logLLM_1.logLLMResponse)(cachedResponse);
99762
99937
  return cachedResponse;
99763
99938
  }
99764
99939
  }
99765
- const adapt = modelProfile.adapt || (0, adapter_1.resolveAdapter)(modelProfile.provider, modelProfile.modelName);
99766
99940
  let result2;
99767
99941
  switch (adapt) {
99768
99942
  case "anthropic":
99769
- result2 = await (0, anthropic_1.queryAnthropic)(messages, systemPromptContent, tools, signal, modelProfile, enableThinking, emitChunkEvents);
99943
+ result2 = await (0, anthropic_1.queryAnthropic)(messages, systemPromptContent, tools, signal, modelProfile, enableThinking, temperature, emitChunkEvents);
99770
99944
  break;
99771
99945
  case "openai":
99772
99946
  default:
99773
- result2 = await (0, openai_1.queryOpenAI)(messages, systemPromptContent, tools, signal, modelProfile, enableThinking, emitChunkEvents);
99947
+ result2 = await (0, openai_1.queryOpenAI)(messages, systemPromptContent, tools, signal, modelProfile, enableThinking, temperature, emitChunkEvents);
99774
99948
  break;
99775
99949
  }
99776
99950
  (0, logLLM_1.logLLMResponse)(result2);
99777
99951
  if (shouldUseCache && !signal.aborted) {
99778
99952
  const hasContent = result2.message.content.some((block) => block.type === "text" && block.text.trim().length > 0 || block.type === "tool_use");
99779
99953
  if (hasContent) {
99780
- (0, cache_1.setCachedResponse)(messages, systemPromptContent, modelProfile.modelName, result2, enableThinking);
99954
+ (0, cache_1.setCachedResponse)(messages, systemPromptContent, modelProfile.modelName, result2, enableThinking, temperature);
99781
99955
  (0, log_1.logDebug)(`LLM\u54CD\u5E94\u5DF2\u7F13\u5B58\uFF0C\u5F53\u524D\u7F13\u5B58\u6761\u76EE\u6570: ${(0, cache_1.getCacheSize)()}`);
99782
99956
  }
99783
99957
  }
@@ -136655,6 +136829,12 @@ var require_SemaEngine = __commonJS({
136655
136829
  cfg.memoryFiles = partial2.memoryFiles ?? null;
136656
136830
  if ("personaFile" in partial2)
136657
136831
  cfg.personaFile = partial2.personaFile ?? null;
136832
+ if ("modelOverrides" in partial2)
136833
+ cfg.modelOverrides = partial2.modelOverrides ?? null;
136834
+ if ("temperatureOverrides" in partial2)
136835
+ cfg.temperatureOverrides = partial2.temperatureOverrides ?? null;
136836
+ if ("thinking" in partial2)
136837
+ cfg.thinking = partial2.thinking === true;
136658
136838
  }
136659
136839
  /**
136660
136840
  * 当前 session 的 coreConfig 只读快照(= initialConfig,含运行时 mutation 结果)。
@@ -137513,7 +137693,7 @@ var require_AtomixCore = __commonJS({
137513
137693
  exports2.AtomixCore = void 0;
137514
137694
  var SemaKernel_1 = require_SemaKernel();
137515
137695
  var ConfManager_1 = require_ConfManager();
137516
- var AtomixCore3 = class {
137696
+ var AtomixCore4 = class {
137517
137697
  constructor(config) {
137518
137698
  this.setWorkingDir = (newDir) => this.session.setWorkingDir(newDir);
137519
137699
  this.clearWorkingDir = () => this.session.clearWorkingDir();
@@ -137539,6 +137719,10 @@ var require_AtomixCore = __commonJS({
137539
137719
  this.switchModel = (ModelName) => this.kernel.models.switchCurrentModel(ModelName);
137540
137720
  this.applyTaskModel = (config2) => this.kernel.models.applyTaskModelConfig(config2);
137541
137721
  this.getModelData = () => this.kernel.models.getModelData();
137722
+ this.getModelNames = () => this.kernel.models.getModelNames();
137723
+ this.getModelPointers = () => this.kernel.models.getModelPointers();
137724
+ this.getModelProfiles = () => this.kernel.models.getModelProfiles();
137725
+ this.updateModel = (name, patch) => this.kernel.models.updateModelProfile(name, patch);
137542
137726
  this.updateCoreConfByKey = (key, value) => {
137543
137727
  if (key === "customRules") {
137544
137728
  this.session.updateAssemblyConfig({ customRules: value ?? "" });
@@ -137587,7 +137771,7 @@ var require_AtomixCore = __commonJS({
137587
137771
  return this.session.workbenchService;
137588
137772
  }
137589
137773
  };
137590
- exports2.AtomixCore = AtomixCore3;
137774
+ exports2.AtomixCore = AtomixCore4;
137591
137775
  }
137592
137776
  });
137593
137777
 
@@ -144162,7 +144346,7 @@ var require_dist4 = __commonJS({
144162
144346
  "../atomix-core/dist/index.js"(exports2) {
144163
144347
  "use strict";
144164
144348
  Object.defineProperty(exports2, "__esModule", { value: true });
144165
- exports2.fetchModels = exports2.testApiConnection = exports2.inferVision = exports2.modelHasVision = exports2.ImageLoadError = exports2.preprocessImage = exports2.imageBlockToPlaceholder = exports2.loadImagesAsBlocks = exports2.loadImageAsBlock = exports2.HOOK_EVENTS = exports2.executeHooks = exports2.HookManager = exports2.projectPathToDirName = exports2.getHistoryFilePath = exports2.getProjectHistoryDir = exports2.getHistoryDir = exports2.setModelConfigPathOverride = exports2.setLogLevel = exports2.getModelManager = exports2.SemaSession = exports2.SemaKernel = exports2.getAgentOwnedFilePaths = exports2.renderContextReminder = exports2.readContextSections = exports2.normalizeMemoryFiles = exports2.resolveContextFiles = exports2.isReadOnlyBashCommand = exports2.DEFAULT_PERMISSION_MODE = exports2.PERMISSION_MODES = exports2.assemblePromptSections = exports2.PROMPT_SECTION_CATALOG = exports2.AtomixCore = void 0;
144349
+ exports2.fetchModels = exports2.testApiConnection = exports2.inferVision = exports2.modelHasVision = exports2.ImageLoadError = exports2.preprocessImage = exports2.imageBlockToPlaceholder = exports2.loadImagesAsBlocks = exports2.loadImageAsBlock = exports2.HOOK_EVENTS = exports2.executeHooks = exports2.HookManager = exports2.projectPathToDirName = exports2.getHistoryFilePath = exports2.getProjectHistoryDir = exports2.getHistoryDir = exports2.setModelConfigPathOverride = exports2.setLogLevel = exports2.TEMPERATURE_MAX = exports2.TEMPERATURE_MIN = exports2.DEFAULT_ANTHROPIC_TEMPERATURE = exports2.isValidTemperature = exports2.openaiTemperatureCapability = exports2.modelTemperatureGatedByThinking = exports2.modelRejectsTemperature = exports2.modelForcesTemperatureOne = exports2.getModelManager = exports2.SemaSession = exports2.SemaKernel = exports2.getAgentOwnedFilePaths = exports2.renderContextReminder = exports2.readContextSections = exports2.normalizeMemoryFiles = exports2.resolveContextFiles = exports2.isReadOnlyBashCommand = exports2.DEFAULT_PERMISSION_MODE = exports2.PERMISSION_MODES = exports2.assemblePromptSections = exports2.PROMPT_SECTION_CATALOG = exports2.AtomixCore = void 0;
144166
144350
  var AtomixCore_1 = require_AtomixCore();
144167
144351
  Object.defineProperty(exports2, "AtomixCore", { enumerable: true, get: function() {
144168
144352
  return AtomixCore_1.AtomixCore;
@@ -144213,6 +144397,31 @@ var require_dist4 = __commonJS({
144213
144397
  Object.defineProperty(exports2, "getModelManager", { enumerable: true, get: function() {
144214
144398
  return ModelManager_1.getModelManager;
144215
144399
  } });
144400
+ var adapter_1 = require_adapter();
144401
+ Object.defineProperty(exports2, "modelForcesTemperatureOne", { enumerable: true, get: function() {
144402
+ return adapter_1.modelForcesTemperatureOne;
144403
+ } });
144404
+ Object.defineProperty(exports2, "modelRejectsTemperature", { enumerable: true, get: function() {
144405
+ return adapter_1.modelRejectsTemperature;
144406
+ } });
144407
+ Object.defineProperty(exports2, "modelTemperatureGatedByThinking", { enumerable: true, get: function() {
144408
+ return adapter_1.modelTemperatureGatedByThinking;
144409
+ } });
144410
+ Object.defineProperty(exports2, "openaiTemperatureCapability", { enumerable: true, get: function() {
144411
+ return adapter_1.openaiTemperatureCapability;
144412
+ } });
144413
+ Object.defineProperty(exports2, "isValidTemperature", { enumerable: true, get: function() {
144414
+ return adapter_1.isValidTemperature;
144415
+ } });
144416
+ Object.defineProperty(exports2, "DEFAULT_ANTHROPIC_TEMPERATURE", { enumerable: true, get: function() {
144417
+ return adapter_1.DEFAULT_ANTHROPIC_TEMPERATURE;
144418
+ } });
144419
+ Object.defineProperty(exports2, "TEMPERATURE_MIN", { enumerable: true, get: function() {
144420
+ return adapter_1.TEMPERATURE_MIN;
144421
+ } });
144422
+ Object.defineProperty(exports2, "TEMPERATURE_MAX", { enumerable: true, get: function() {
144423
+ return adapter_1.TEMPERATURE_MAX;
144424
+ } });
144216
144425
  var log_1 = require_log();
144217
144426
  Object.defineProperty(exports2, "setLogLevel", { enumerable: true, get: function() {
144218
144427
  return log_1.setLogLevel;
@@ -151707,641 +151916,50 @@ var require_dist5 = __commonJS({
151707
151916
  }
151708
151917
  });
151709
151918
 
151710
- // src/agents.ts
151711
- var agents_exports = {};
151712
- __export(agents_exports, {
151713
- agentsCommand: () => agentsCommand,
151714
- applyDisabledAgents: () => applyDisabledAgents,
151715
- disableAgent: () => disableAgent,
151716
- enableAgent: () => enableAgent,
151717
- readDisabledAgents: () => readDisabledAgents
151718
- });
151919
+ // src/memoryPaths.ts
151719
151920
  import * as fs2 from "fs";
151720
151921
  import * as path2 from "path";
151721
- function disabledFile() {
151722
- return path2.join(getAtomixRoot(), "disabled-agents.json");
151723
- }
151724
- function readDisabledAgents() {
151725
- try {
151726
- const parsed = JSON.parse(fs2.readFileSync(disabledFile(), "utf8"));
151727
- if (Array.isArray(parsed.disabled)) return new Set(parsed.disabled);
151728
- } catch {
151729
- }
151730
- return /* @__PURE__ */ new Set();
151731
- }
151732
- function writeDisabledAgents(disabled) {
151733
- fs2.mkdirSync(getAtomixRoot(), { recursive: true });
151734
- fs2.writeFileSync(disabledFile(), JSON.stringify({ disabled: [...disabled].sort() }, null, 2) + "\n");
151735
- }
151736
- function disableAgent(name) {
151737
- const s = readDisabledAgents();
151738
- s.add(name);
151739
- writeDisabledAgents(s);
151740
- }
151741
- function enableAgent(name) {
151742
- const s = readDisabledAgents();
151743
- if (!s.delete(name)) return false;
151744
- writeDisabledAgents(s);
151745
- return true;
151746
- }
151747
- async function applyDisabledAgents(core) {
151748
- await core.reloadAgents(/* @__PURE__ */ new Set());
151749
- const allNames = core.getAgentsInfo().map((a) => a.name);
151750
- recordAgentUniverse(core, allNames);
151751
- const disabled = /* @__PURE__ */ new Set([...readDisabledAgents(), ...harnessDisabledAgents(core, allNames)]);
151752
- await core.reloadAgents(disabled);
151753
- }
151754
- async function agentsCommand(core, args) {
151755
- const [sub, ...rest2] = args;
151756
- const name = rest2.join(" ").trim();
151757
- switch (sub) {
151758
- case void 0:
151759
- case "list": {
151760
- const infos = [...core.getAgentsInfo()].sort(
151761
- (a, b) => a.locate.localeCompare(b.locate) || a.name.localeCompare(b.name)
151762
- );
151763
- const disabledSet = readDisabledAgents();
151764
- const lines = infos.filter((a) => !disabledSet.has(a.name)).map((a) => {
151765
- const desc = a.description ? ` \u2014 ${a.description.length > 60 ? a.description.slice(0, 60) + "\u2026" : a.description}` : "";
151766
- return `\u25CF ${a.name} [${a.locate}]${desc}`;
151767
- });
151768
- for (const n of [...disabledSet].sort()) lines.push(`\u25CB ${n} \uFF08\u5DF2\u7981\u7528\uFF09`);
151769
- if (!lines.length) lines.push("\uFF08\u65E0\u53EF\u7528\u4EBA\u8BBE\uFF09");
151770
- lines.push(`\u25CF \u542F\u7528\u4E2D \u25CB \u5DF2\u7981\u7528${disabledSet.size === 0 ? "\uFF08\u5F53\u524D\u65E0\u7981\u7528\u9879\uFF09" : ""} \xB7 \u7528\u6CD5\uFF1A/agents list | enable <\u540D\u79F0> | disable <\u540D\u79F0>`);
151771
- return lines.join("\n ");
151772
- }
151773
- case "disable": {
151774
- if (!name) return "\u7528\u6CD5\uFF1A/agents disable <\u540D\u79F0>";
151775
- disableAgent(name);
151776
- await applyDisabledAgents(core);
151777
- return `\u5DF2\u7981\u7528\u4EBA\u8BBE\uFF1A${name}`;
151778
- }
151779
- case "enable": {
151780
- if (!name) return "\u7528\u6CD5\uFF1A/agents enable <\u540D\u79F0>";
151781
- if (!enableAgent(name)) return `${name} \u672A\u88AB\u7981\u7528`;
151782
- await applyDisabledAgents(core);
151783
- return `\u5DF2\u542F\u7528\u4EBA\u8BBE\uFF1A${name}`;
151784
- }
151785
- default:
151786
- return `\u672A\u77E5\u5B50\u547D\u4EE4\uFF1A${sub}\uFF08\u7528\u6CD5\uFF1A/agents list | enable <\u540D\u79F0> | disable <\u540D\u79F0>\uFF09`;
151787
- }
151788
- }
151789
- var init_agents = __esm({
151790
- "src/agents.ts"() {
151791
- "use strict";
151792
- init_paths();
151793
- init_harness();
151794
- }
151795
- });
151796
-
151797
- // src/harness.ts
151798
- import * as fs3 from "fs";
151799
- import * as path3 from "path";
151800
- function runtimeOf(core) {
151801
- return runtimes.get(core) ?? null;
151802
- }
151803
- function requireRuntime(core) {
151804
- const rt = runtimeOf(core);
151805
- if (!rt) throw new Error("harness \u672A\u521D\u59CB\u5316(initHarness \u672A\u8C03\u7528)");
151806
- return rt;
151807
- }
151808
- function overrideOf(activeValue, baseValue) {
151809
- if (baseValue === void 0 || activeValue === void 0) return null;
151810
- const baseOn = baseValue !== null;
151811
- const activeOn = activeValue !== null;
151812
- return activeOn === baseOn ? null : activeOn ? "on" : "off";
151813
- }
151814
- function personaOverrideOf(activeValue, baseValue) {
151815
- const basic = overrideOf(activeValue, baseValue);
151816
- if (basic !== null) return basic;
151817
- if (activeValue && baseValue && activeValue !== baseValue) return "swap";
151818
- return null;
151819
- }
151820
- function harnessMemoryOverride(core) {
151821
- const rt = runtimeOf(core);
151822
- return rt ? overrideOf(rt.activeMemoryFiles, rt.baseline.memoryFiles) : null;
151823
- }
151824
- function harnessPersonaOverride(core) {
151825
- const rt = runtimeOf(core);
151826
- return rt ? personaOverrideOf(rt.activePersonaFile, rt.baseline.personaFile) : null;
151827
- }
151828
- function getActivePersonaFile(core) {
151829
- return runtimeOf(core)?.activePersonaFile;
151830
- }
151831
- function getActiveHarnessName(core) {
151832
- return runtimeOf(core)?.active?.name ?? BASE_HARNESS;
151833
- }
151834
- function isHarnessOverridden(core) {
151835
- return runtimeOf(core)?.overridden ?? false;
151836
- }
151837
- function recordSkillUniverse(core, names) {
151838
- const rt = runtimeOf(core);
151839
- if (rt) rt.fullSkillNames = names.slice();
151840
- }
151841
- function recordAgentUniverse(core, names) {
151842
- const rt = runtimeOf(core);
151843
- if (rt) rt.fullAgentNames = names.slice();
151844
- }
151845
- function computeDisabledFrom(spec, allNames) {
151846
- if (!spec) return /* @__PURE__ */ new Set();
151847
- return spec.mode === "whitelist" ? new Set(allNames.filter((n) => !spec.enable.includes(n))) : new Set(spec.disable);
151848
- }
151849
- function harnessDisabledSkills(core, allNames) {
151850
- return computeDisabledFrom(runtimeOf(core)?.active?.skillsSpec ?? null, allNames);
151851
- }
151852
- function harnessDisabledAgents(core, allNames) {
151853
- return computeDisabledFrom(runtimeOf(core)?.active?.agentsSpec ?? null, allNames);
151854
- }
151855
- function libraryDir() {
151856
- return path3.join(getAtomixRoot(), "harness");
151857
- }
151858
- function statePath(cwd2) {
151859
- return path3.join(cwd2, ".atomix", "harness-state.json");
151860
- }
151861
- function readState(cwd2) {
151862
- try {
151863
- const parsed = JSON.parse(fs3.readFileSync(statePath(cwd2), "utf8"));
151864
- return typeof parsed.active === "string" && parsed.active ? parsed.active : BASE_HARNESS;
151865
- } catch {
151866
- return BASE_HARNESS;
151867
- }
151868
- }
151869
- function writeState(cwd2, name) {
151870
- const p = statePath(cwd2);
151871
- if (name === BASE_HARNESS) {
151872
- try {
151873
- fs3.unlinkSync(p);
151874
- } catch {
151875
- }
151876
- return;
151877
- }
151878
- fs3.mkdirSync(path3.dirname(p), { recursive: true });
151879
- fs3.writeFileSync(p, JSON.stringify({ active: name }, null, 2) + "\n");
151880
- }
151881
- function listHarnesses() {
151882
- let names = [];
151883
- try {
151884
- names = fs3.readdirSync(libraryDir(), { withFileTypes: true }).filter((e) => e.isDirectory() && fs3.existsSync(path3.join(libraryDir(), e.name, "harness.yaml"))).map((e) => e.name).sort();
151885
- } catch {
151886
- }
151887
- return [BASE_HARNESS, ...names.filter((n) => n !== BASE_HARNESS)];
151888
- }
151889
- function asStrArr(v) {
151890
- return Array.isArray(v) ? v.filter((x) => typeof x === "string") : [];
151891
- }
151892
- function asMode(v) {
151893
- return v === "whitelist" ? "whitelist" : "blacklist";
151894
- }
151895
- function normalizePromptGroup(raw) {
151896
- const warnings = [];
151897
- if (!raw || typeof raw !== "object") return { overrides: null, warnings };
151898
- const g = raw;
151899
- const meta = new Map(import_atomix_core2.PROMPT_SECTION_CATALOG.map((m) => [m.name, m]));
151900
- const replace2 = {};
151901
- if (g.replace && typeof g.replace === "object") {
151902
- for (const [name, text] of Object.entries(g.replace)) {
151903
- const m = meta.get(name);
151904
- if (!m) {
151905
- warnings.push(`prompt.replace \u672A\u77E5\u6BB5\u540D ${name}(\u53EF\u7528:${[...meta.keys()].join(" / ")})`);
151906
- continue;
151907
- }
151908
- if (m.locked) {
151909
- warnings.push(`prompt.replace \u5FFD\u7565 ${name}:\u5B89\u5168\u6761\u6B3E\u6BB5\u4EE3\u7801\u7EA7\u9501\u5B9A`);
151910
- continue;
151911
- }
151912
- if (m.dynamic) {
151913
- warnings.push(`prompt.replace \u5FFD\u7565 ${name}:\u52A8\u6001\u6BB5(\u6BCF\u8F6E\u91CD\u7B97)\u53EA\u53EF disable`);
151914
- continue;
151915
- }
151916
- if (typeof text !== "string") {
151917
- warnings.push(`prompt.replace.${name} \u975E\u5B57\u7B26\u4E32,\u5FFD\u7565`);
151918
- continue;
151919
- }
151920
- replace2[name] = text;
151921
- }
151922
- }
151923
- const disable = [];
151924
- for (const name of asStrArr(g.disable)) {
151925
- const m = meta.get(name);
151926
- if (!m) {
151927
- warnings.push(`prompt.disable \u672A\u77E5\u6BB5\u540D ${name}`);
151928
- continue;
151929
- }
151930
- if (m.locked) {
151931
- warnings.push(`prompt.disable \u5FFD\u7565 ${name}:\u5B89\u5168\u6761\u6B3E\u6BB5\u4EE3\u7801\u7EA7\u9501\u5B9A`);
151932
- continue;
151933
- }
151934
- disable.push(name);
151935
- }
151936
- const insert = [];
151937
- if (Array.isArray(g.insert)) {
151938
- for (const item of g.insert) {
151939
- if (!item || typeof item !== "object") continue;
151940
- const it = item;
151941
- const name = typeof it.name === "string" ? it.name : "";
151942
- const text = typeof it.text === "string" ? it.text : "";
151943
- if (!name || !text.trim()) {
151944
- warnings.push("prompt.insert \u5FFD\u7565\u7F3A name/text \u7684\u6761\u76EE");
151945
- continue;
151946
- }
151947
- if (meta.has(name)) {
151948
- warnings.push(`prompt.insert \u5FFD\u7565 ${name}:\u4E0E\u5185\u7F6E\u6BB5\u91CD\u540D(\u6539\u5185\u7F6E\u6BB5\u7528 replace)`);
151949
- continue;
151950
- }
151951
- const order = typeof it.order === "number" && Number.isFinite(it.order) ? it.order : 999;
151952
- insert.push({ name, order, text });
151953
- }
151954
- }
151955
- const overrides = {};
151956
- if (Object.keys(replace2).length) overrides.replace = replace2;
151957
- if (disable.length) overrides.disable = disable;
151958
- if (insert.length) overrides.insert = insert;
151959
- return { overrides: Object.keys(overrides).length ? overrides : null, warnings };
151960
- }
151961
- function assertSafeHarnessName(name) {
151962
- if (!name || name === "." || name === ".." || name.includes("/") || name.includes("\\") || path3.basename(name) !== name) {
151963
- throw new Error(`\u975E\u6CD5 harness \u540D\u79F0:${JSON.stringify(name)}`);
151964
- }
151965
- }
151966
- function assertInsideDir(dir, target, what) {
151967
- const rel = path3.relative(dir, target);
151968
- if (rel === ".." || rel.startsWith(`..${path3.sep}`) || path3.isAbsolute(rel)) {
151969
- throw new Error(`${what}\u5FC5\u987B\u4F4D\u4E8E harness \u76EE\u5F55\u5185:${target}`);
151970
- }
151971
- }
151972
- function loadHarnessDoc(name) {
151973
- assertSafeHarnessName(name);
151974
- const dir = path3.join(libraryDir(), name);
151975
- const yamlPath = path3.join(dir, "harness.yaml");
151976
- const raw = import_yaml.default.parse(fs3.readFileSync(yamlPath, "utf8"));
151977
- if (!raw || typeof raw !== "object") throw new Error(`harness.yaml \u4E3A\u7A7A\u6216\u975E\u5BF9\u8C61:${yamlPath}`);
151978
- const t = raw.tools ?? {};
151979
- const sk = raw.skills ?? {};
151980
- const ag = raw.agents ?? {};
151981
- let rulesText = "";
151982
- const rulesFile = typeof raw.rules === "string" ? raw.rules : "rules.md";
151983
- const rulesPath = path3.resolve(dir, rulesFile);
151984
- assertInsideDir(path3.resolve(dir), rulesPath, "rules \u6587\u4EF6");
151985
- let rulesReal = null;
151986
- try {
151987
- rulesReal = fs3.realpathSync(rulesPath);
151988
- } catch {
151989
- }
151990
- if (rulesReal !== null) {
151991
- assertInsideDir(fs3.realpathSync(dir), rulesReal, "rules \u6587\u4EF6(symlink \u89E3\u6790\u540E)");
151992
- rulesText = fs3.readFileSync(rulesReal, "utf8").trim();
151993
- }
151994
- let soulPath = null;
151995
- let soulReal = null;
151996
- try {
151997
- soulReal = fs3.realpathSync(path3.resolve(dir, "SOUL.md"));
151998
- } catch (e) {
151999
- if (e.code !== "ENOENT") throw e;
152000
- }
152001
- if (soulReal !== null) {
152002
- assertInsideDir(fs3.realpathSync(dir), soulReal, "SOUL \u6587\u4EF6(symlink \u89E3\u6790\u540E)");
152003
- const soulStat = fs3.statSync(soulReal);
152004
- if (!soulStat.isFile()) throw new Error(`SOUL.md \u4E0D\u662F\u666E\u901A\u6587\u4EF6:${soulReal}`);
152005
- if (soulStat.nlink > 1) throw new Error(`SOUL.md \u662F\u591A\u786C\u94FE\u63A5\u6587\u4EF6,\u62D2\u7EDD\u52A0\u8F7D:${soulReal}`);
152006
- soulPath = soulReal;
152007
- }
152008
- const promptGroup = normalizePromptGroup(raw.prompt);
152009
- const toggleWarnings = [];
152010
- const parseToggle = (v, key) => {
152011
- if (v === void 0 || v === null) return null;
152012
- if (v === "off" || v === false) return "off";
152013
- if (v === "on" || v === true) return "on";
152014
- toggleWarnings.push(`${key} \u53EA\u8BA4 on/off,\u5FFD\u7565\u975E\u6CD5\u503C ${JSON.stringify(v)}`);
152015
- return null;
152016
- };
152017
- const memory = parseToggle(raw.memory, "memory");
152018
- const persona = parseToggle(raw.persona, "persona");
152019
- return {
152020
- name: typeof raw.name === "string" && raw.name ? raw.name : name,
152021
- description: typeof raw.description === "string" ? raw.description : void 0,
152022
- version: typeof raw.version === "string" ? raw.version : void 0,
152023
- rulesText,
152024
- tools: {
152025
- mode: asMode(t.mode),
152026
- useTools: Array.isArray(t.useTools) ? asStrArr(t.useTools) : null,
152027
- disable: asStrArr(t.disable),
152028
- enable: asStrArr(t.enable),
152029
- defer: asStrArr(t.defer),
152030
- pin: asStrArr(t.pin)
152031
- },
152032
- skills: { mode: asMode(sk.mode), disable: asStrArr(sk.disable), enable: asStrArr(sk.enable) },
152033
- agents: { mode: asMode(ag.mode), disable: asStrArr(ag.disable), enable: asStrArr(ag.enable) },
152034
- prompt: promptGroup.overrides,
152035
- promptWarnings: promptGroup.warnings,
152036
- memory,
152037
- persona,
152038
- soulPath,
152039
- toggleWarnings,
152040
- dir
152041
- };
152042
- }
152043
- function resolveBase(ctx) {
152044
- return {
152045
- name: BASE_HARNESS,
152046
- useTools: ctx.baseline.useTools,
152047
- deferBuiltinTools: ctx.baseline.deferBuiltinTools ?? [],
152048
- pinnedTools: [],
152049
- customRules: "",
152050
- promptOverrides: null,
152051
- memoryFiles: ctx.baseline.memoryFiles,
152052
- personaFile: ctx.baseline.personaFile,
152053
- warnings: [],
152054
- skillsSpec: null,
152055
- agentsSpec: null,
152056
- skillsDisabled: /* @__PURE__ */ new Set(),
152057
- agentsDisabled: /* @__PURE__ */ new Set()
152058
- };
152059
- }
152060
- function resolveHarness(doc, ctx) {
152061
- if (!doc) return resolveBase(ctx);
152062
- let useTools;
152063
- if (doc.tools.mode === "whitelist") {
152064
- useTools = doc.tools.enable.slice();
152065
- } else {
152066
- useTools = doc.tools.useTools ?? ctx.baseline.useTools;
152067
- if (doc.tools.disable.length) {
152068
- const src = useTools ?? ctx.allToolNames;
152069
- const drop2 = new Set(doc.tools.disable);
152070
- useTools = src.filter((n) => !drop2.has(n));
152071
- }
152072
- }
152073
- const warnings = [...doc.promptWarnings, ...doc.toggleWarnings];
152074
- const resolveToggle = (toggle, base, potential, emptyWarning) => {
152075
- if (base === void 0) return void 0;
152076
- if (toggle === "off") return null;
152077
- if (toggle === "on") {
152078
- const p = potential === void 0 ? base : potential;
152079
- if (p === null) {
152080
- warnings.push(emptyWarning);
152081
- return null;
152082
- }
152083
- return p;
152084
- }
152085
- return base;
152086
- };
152087
- const memoryFiles = resolveToggle(
152088
- doc.memory,
152089
- ctx.baseline.memoryFiles,
152090
- ctx.baseline.potentialMemoryFiles,
152091
- "memory: on \u65E0\u8D27\u53EF\u5F00:config.json \u5DF2\u628A global/project \u90FD\u663E\u5F0F\u5173\u6B7B"
152092
- );
152093
- let personaFile;
152094
- if (ctx.baseline.personaFile === void 0) {
152095
- personaFile = void 0;
152096
- } else if (doc.persona === "off") {
152097
- personaFile = null;
152098
- } else if (doc.soulPath) {
152099
- personaFile = doc.soulPath;
152100
- } else {
152101
- if (doc.persona === "on") warnings.push("persona: on \u65E0\u6548:\u672C harness \u672A\u5E26\u4E13\u5C5E SOUL.md(\u4E25\u683C\u9694\u79BB,\u4E0D\u501F base \u4EBA\u8BBE;\u653E\u4E00\u4EFD SOUL.md \u8FDB harness \u76EE\u5F55\u5373\u751F\u6548)");
152102
- personaFile = null;
152103
- }
152104
- return {
152105
- name: doc.name,
152106
- useTools,
152107
- deferBuiltinTools: doc.tools.defer.length ? doc.tools.defer : ctx.baseline.deferBuiltinTools ?? [],
152108
- pinnedTools: doc.tools.pin,
152109
- customRules: doc.rulesText,
152110
- promptOverrides: doc.prompt,
152111
- memoryFiles,
152112
- personaFile,
152113
- warnings,
152114
- skillsSpec: doc.skills,
152115
- agentsSpec: doc.agents,
152116
- skillsDisabled: computeDisabledFrom(doc.skills, ctx.allSkillNames),
152117
- agentsDisabled: computeDisabledFrom(doc.agents, ctx.allAgentNames)
152118
- };
152119
- }
152120
- function buildContext(core) {
152121
- const rt = requireRuntime(core);
152122
- return {
152123
- baseline: rt.baseline,
152124
- // 工具:getToolInfos 恒返回内置全集(禁用项带 status),可直读;
152125
- // skill:core 按 session 读取时过滤,includeDisabled 直接取供给全集;
152126
- // agent:注册表是已过滤视图,优先用 applyDisabledAgents 回写的全集缓存,
152127
- // 缓存为空只在启动初始化时(此刻尚未过滤,直读即全集)
152128
- allToolNames: core.getToolInfos().map((t) => t.name),
152129
- allSkillNames: rt.fullSkillNames ?? core.getSkillsInfo({ includeDisabled: true }).map((s) => s.name),
152130
- allAgentNames: rt.fullAgentNames ?? core.getAgentsInfo().map((a) => a.name)
152131
- };
152132
- }
152133
- function applyAssembly(core, rt, r) {
152134
- core.updateAssemblyConfig({
152135
- useTools: r.useTools,
152136
- deferBuiltinTools: r.deferBuiltinTools,
152137
- pinnedTools: r.pinnedTools,
152138
- customRules: r.customRules,
152139
- promptOverrides: r.promptOverrides,
152140
- // null = 回默认组装(base 清场)
152141
- // 基线未知(宿主没给快照)时不下发该键:传 undefined 会被 core 当 null 落,把供给层开着的注入误关
152142
- ...r.memoryFiles !== void 0 ? { memoryFiles: r.memoryFiles } : {},
152143
- ...r.personaFile !== void 0 ? { personaFile: r.personaFile } : {}
152144
- });
152145
- rt.activeMemoryFiles = r.memoryFiles;
152146
- rt.activePersonaFile = r.personaFile;
152147
- rt.active = r.name === BASE_HARNESS ? null : r;
152148
- }
152149
- function initHarness(core, cwd2, base, opts = {}) {
152150
- const rt = {
152151
- baseline: {
152152
- useTools: base.useTools ? [...base.useTools] : null,
152153
- deferBuiltinTools: base.deferBuiltinTools?.slice(),
152154
- memoryFiles: base.memoryFiles,
152155
- personaFile: base.personaFile,
152156
- potentialMemoryFiles: base.potentialMemoryFiles
152157
- },
152158
- activeMemoryFiles: base.memoryFiles,
152159
- activePersonaFile: base.personaFile,
152160
- projectDir: cwd2,
152161
- active: null,
152162
- overridden: opts.harness !== void 0,
152163
- fullSkillNames: null,
152164
- fullAgentNames: null
152165
- };
152166
- runtimes.set(core, rt);
152167
- const name = opts.harness ?? readState(cwd2);
152168
- const source = rt.overridden ? "\u4F1A\u8BDD\u7EA7\u6307\u5B9A" : "\u6765\u81EA .atomix/harness-state.json";
152169
- if (name === BASE_HARNESS) return null;
152170
- try {
152171
- const doc = loadHarnessDoc(name);
152172
- const r = resolveHarness(doc, buildContext(core));
152173
- applyAssembly(core, rt, r);
152174
- return r.warnings.length ? `harness "${r.name}"(${source})\u5DF2\u52A0\u8F7D:
152175
- \u26A0 ${r.warnings.join("\n \u26A0 ")}` : null;
152176
- } catch (e) {
152177
- if (rt.overridden) throw new Error(`harness "${name}" \u52A0\u8F7D\u5931\u8D25:${e instanceof Error ? e.message : e}`);
152178
- return `harness "${name}"(${source})\u52A0\u8F7D\u5931\u8D25,\u5DF2\u56DE\u843D base:${e instanceof Error ? e.message : e}`;
152179
- }
152180
- }
152181
- async function switchTo(core, name) {
152182
- const rt = requireRuntime(core);
152183
- const ctx = buildContext(core);
152184
- const r = name === BASE_HARNESS ? resolveBase(ctx) : resolveHarness(loadHarnessDoc(name), ctx);
152185
- const wasOn = (v) => v !== null && v !== void 0;
152186
- const memWasOn = wasOn(rt.activeMemoryFiles);
152187
- const personaWas = rt.activePersonaFile;
152188
- applyAssembly(core, rt, r);
152189
- const memNowOn = wasOn(rt.activeMemoryFiles);
152190
- const personaNow = rt.activePersonaFile;
152191
- writeState(rt.projectDir, name);
152192
- rt.overridden = false;
152193
- const { applyDisabledSkills: applyDisabledSkills2 } = await Promise.resolve().then(() => (init_skills(), skills_exports));
152194
- const { applyDisabledAgents: applyDisabledAgents2 } = await Promise.resolve().then(() => (init_agents(), agents_exports));
152195
- applyDisabledSkills2(core);
152196
- await applyDisabledAgents2(core);
152197
- const warn = r.warnings.length ? "\n \u26A0 " + r.warnings.join("\n \u26A0 ") : "";
152198
- const hints = [];
152199
- if (memWasOn !== memNowOn) hints.push(memNowOn ? "\u8BB0\u5FC6\u6CE8\u5165\u5DF2\u5F00;\u9700 /compact\u3001/clear \u6216\u65B0\u4F1A\u8BDD\u540E\u91CD\u65B0\u6CE8\u5165" : "\u8BB0\u5FC6\u6CE8\u5165\u5DF2\u5173;\u5386\u53F2\u91CC\u5DF2\u6CE8\u5165\u7684\u8BB0\u5FC6\u9700 /compact \u6216 /clear \u624D\u64A4\u51FA");
152200
- const pWasOn = wasOn(personaWas);
152201
- const pNowOn = wasOn(personaNow);
152202
- if (pWasOn !== pNowOn) hints.push(pNowOn ? "\u4EBA\u8BBE\u6CE8\u5165\u5DF2\u5F00;\u9700 /compact\u3001/clear \u6216\u65B0\u4F1A\u8BDD\u540E\u91CD\u65B0\u6CE8\u5165" : "\u4EBA\u8BBE\u6CE8\u5165\u5DF2\u5173;\u5386\u53F2\u91CC\u5DF2\u6CE8\u5165\u7684\u4EBA\u8BBE\u9700 /compact \u6216 /clear \u624D\u64A4\u51FA");
152203
- else if (pWasOn && pNowOn && personaWas !== personaNow) hints.push("\u4EBA\u8BBE\u6765\u6E90\u5DF2\u5207\u6362;\u5386\u53F2\u91CC\u5DF2\u6CE8\u5165\u7684\u4EBA\u8BBE\u9700 /compact \u6216 /clear \u624D\u66F4\u65B0");
152204
- const hintText = hints.map((h) => `
152205
- ${h}`).join("");
152206
- return (name === BASE_HARNESS ? "\u5DF2\u56DE\u5230 base(\u9ED8\u8BA4\u88C5\u914D)" : `\u5DF2\u5207\u6362 harness:${r.name}(\u4EC5\u5F53\u524D\u9879\u76EE\u751F\u6548)`) + hintText + warn;
152207
- }
152208
- function summarize(r, ctx) {
152209
- const lines = [];
152210
- const base = resolveBase(ctx);
152211
- const baseSet2 = new Set(base.useTools ?? ctx.allToolNames);
152212
- const curSet = new Set(r.useTools ?? ctx.allToolNames);
152213
- const removed = [...baseSet2].filter((n) => !curSet.has(n));
152214
- const added = [...curSet].filter((n) => !baseSet2.has(n));
152215
- lines.push(`\u5DE5\u5177 ${r.useTools ? `${curSet.size} \u4E2A` : "\u5168\u90E8"}${removed.length ? `(\u76F8\u5BF9 base \u5C11:${removed.join(", ")})` : ""}${added.length ? `(\u76F8\u5BF9 base \u591A:${added.join(", ")})` : ""}`);
152216
- if (r.deferBuiltinTools.length) lines.push(`defer ${r.deferBuiltinTools.join(", ")}`);
152217
- if (r.pinnedTools.length) lines.push(`pin ${r.pinnedTools.join(", ")}`);
152218
- const skillsDisabled = computeDisabledFrom(r.skillsSpec, ctx.allSkillNames);
152219
- const agentsDisabled = computeDisabledFrom(r.agentsSpec, ctx.allAgentNames);
152220
- lines.push(`skill ${skillsDisabled.size ? `\u7981\u7528 ${[...skillsDisabled].join(", ")}` : "\u5168\u90E8\u53EF\u89C1"}`);
152221
- lines.push(`agent ${agentsDisabled.size ? `\u7981\u7528 ${[...agentsDisabled].join(", ")}` : "\u5168\u90E8\u53EF\u89C1"}`);
152222
- lines.push(`\u89C4\u5219\u6BB5 ${r.customRules ? `${r.customRules.split("\n").length} \u884C` : "\u65E0"}`);
152223
- const p = r.promptOverrides;
152224
- const promptDesc = p ? [
152225
- p.replace && Object.keys(p.replace).length ? `\u66FF\u6362 ${Object.keys(p.replace).join(", ")}` : "",
152226
- p.disable?.length ? `\u7981\u7528 ${p.disable.join(", ")}` : "",
152227
- p.insert?.length ? `\u63D2\u5165 ${p.insert.map((i) => i.name).join(", ")}` : ""
152228
- ].filter(Boolean).join(";") : "\u9ED8\u8BA4";
152229
- lines.push(`\u63D0\u793A\u6BB5 ${promptDesc}`);
152230
- const mo = overrideOf(r.memoryFiles, ctx.baseline.memoryFiles);
152231
- if (mo === "off") lines.push("\u8BB0\u5FC6 \u5173(harness memory: off;base \u5F00\u7740,\u5207\u8D70\u5373\u6062\u590D)");
152232
- else if (mo === "on") lines.push("\u8BB0\u5FC6 \u5F00(harness memory: on;base \u5173\u7740,\u5207\u8D70\u5373\u5173)");
152233
- const po = personaOverrideOf(r.personaFile, ctx.baseline.personaFile);
152234
- if (po === "off") lines.push("\u4EBA\u8BBE \u5173(\u672C harness \u65E0\u4EBA\u8BBE;base \u5F00\u7740,\u5207\u8D70\u5373\u6062\u590D)");
152235
- else if (po === "swap") lines.push("\u4EBA\u8BBE \u4E13\u5C5E(harness SOUL.md;\u5207\u8D70\u5373\u56DE base)");
152236
- else if (po === "on") lines.push("\u4EBA\u8BBE \u4E13\u5C5E(harness SOUL.md;base \u5173\u7740,\u5207\u8D70\u5373\u5173)");
152237
- if (r.warnings.length) lines.push(...r.warnings.map((w) => `\u26A0 ${w}`));
152238
- return lines.join("\n ");
152239
- }
152240
- async function harnessCommand(core, args) {
152241
- const [sub, ...rest2] = args;
152242
- const arg = rest2.join(" ").trim() || void 0;
152243
- const names = listHarnesses();
152244
- switch (sub) {
152245
- case void 0:
152246
- case "list": {
152247
- const cur = getActiveHarnessName(core);
152248
- const rt = runtimeOf(core);
152249
- const lines = names.map((n) => `${n === cur ? "\u25CF" : "\u25CB"} ${n}${n === BASE_HARNESS ? "(\u9ED8\u8BA4\u88C5\u914D)" : ""}`);
152250
- if (sub === void 0 && rt?.active) {
152251
- const ctx = buildContext(core);
152252
- const where = rt.overridden ? "\u4F1A\u8BDD\u7EA7\u6307\u5B9A,\u672A\u5199\u5165\u9879\u76EE\u6001" : `\u9879\u76EE\u7EA7,${path3.join(".atomix", "harness-state.json")}`;
152253
- lines.unshift(`\u5F53\u524D:${cur}(${where})`, " " + summarize(rt.active, ctx), "");
152254
- } else if (sub === void 0) {
152255
- lines.unshift(rt?.overridden ? "\u5F53\u524D:base(\u4F1A\u8BDD\u7EA7\u6307\u5B9A\u9ED8\u8BA4\u88C5\u914D)" : "\u5F53\u524D:base(\u9ED8\u8BA4\u88C5\u914D,\u672A\u9009\u62E9 harness)", "");
152256
- }
152257
- lines.push("", "\u7528\u6CD5:/harness list | use <\u540D\u79F0> | show <\u540D\u79F0> | diff <\u540D\u79F0> | reset");
152258
- lines.push(`\u5E93\u76EE\u5F55:${libraryDir()}(\u6BCF\u4E2A harness \u4E00\u4E2A\u5B50\u76EE\u5F55,\u542B harness.yaml + rules.md)`);
152259
- return lines.join("\n");
152260
- }
152261
- case "use": {
152262
- if (!arg) return "\u7528\u6CD5:/harness use <\u540D\u79F0>";
152263
- if (!names.includes(arg)) return `\u672A\u627E\u5230 harness:${arg}(\u53EF\u7528:${names.join(" / ")})`;
152264
- try {
152265
- return await switchTo(core, arg);
152266
- } catch (e) {
152267
- return `\u5207\u6362\u5931\u8D25:${e instanceof Error ? e.message : e}`;
152268
- }
152269
- }
152270
- case "reset":
152271
- return await switchTo(core, BASE_HARNESS);
152272
- case "show":
152273
- case "diff": {
152274
- if (!arg) return `\u7528\u6CD5:/harness ${sub} <\u540D\u79F0>`;
152275
- if (arg === BASE_HARNESS) return "base = \u9ED8\u8BA4\u88C5\u914D\u57FA\u7EBF,\u65E0\u53D6\u820D\u9879";
152276
- try {
152277
- const ctx = buildContext(core);
152278
- const r = resolveHarness(loadHarnessDoc(arg), ctx);
152279
- return `${r.name}${arg === getActiveHarnessName(core) ? "(\u5F53\u524D)" : ""}
152280
- ${summarize(r, ctx)}`;
152281
- } catch (e) {
152282
- return `\u8BFB\u53D6\u5931\u8D25:${e instanceof Error ? e.message : e}`;
152283
- }
152284
- }
152285
- default:
152286
- return `\u672A\u77E5\u5B50\u547D\u4EE4:${sub}(\u53EF\u7528:list / use / show / diff / reset)`;
152287
- }
152288
- }
152289
- var import_yaml, import_atomix_core2, BASE_HARNESS, runtimes;
152290
- var init_harness = __esm({
152291
- "src/harness.ts"() {
152292
- "use strict";
152293
- import_yaml = __toESM(require_dist5());
152294
- import_atomix_core2 = __toESM(require_dist4());
152295
- init_paths();
152296
- BASE_HARNESS = "base";
152297
- runtimes = /* @__PURE__ */ new WeakMap();
152298
- }
152299
- });
152300
-
152301
- // src/memoryPaths.ts
152302
- import * as fs4 from "fs";
152303
- import * as path4 from "path";
152304
151922
  function getMemoryPaths(cwd2) {
152305
151923
  const root2 = realpathOrSelf(getAtomixRoot());
152306
- const slug = (0, import_atomix_core3.projectPathToDirName)(cwd2);
152307
- const projectDir = path4.join(root2, "projects", slug);
151924
+ const slug = (0, import_atomix_core2.projectPathToDirName)(cwd2);
151925
+ const projectDir = path2.join(root2, "projects", slug);
152308
151926
  return {
152309
151927
  root: root2,
152310
151928
  slug,
152311
- soul: path4.join(root2, "SOUL.md"),
152312
- globalMemory: path4.join(root2, "MEMORY.md"),
151929
+ soul: path2.join(root2, "SOUL.md"),
151930
+ globalMemory: path2.join(root2, "MEMORY.md"),
152313
151931
  projectDir,
152314
- projectMemory: path4.join(projectDir, "MEMORY.md")
151932
+ projectMemory: path2.join(projectDir, "MEMORY.md")
152315
151933
  };
152316
151934
  }
152317
151935
  function realpathOrSelf(p) {
152318
151936
  try {
152319
- return fs4.realpathSync(p);
151937
+ return fs2.realpathSync(p);
152320
151938
  } catch {
152321
151939
  return p;
152322
151940
  }
152323
151941
  }
152324
- var import_atomix_core3;
151942
+ var import_atomix_core2;
152325
151943
  var init_memoryPaths = __esm({
152326
151944
  "src/memoryPaths.ts"() {
152327
151945
  "use strict";
152328
- import_atomix_core3 = __toESM(require_dist4());
151946
+ import_atomix_core2 = __toESM(require_dist4());
152329
151947
  init_paths();
152330
151948
  }
152331
151949
  });
152332
151950
 
152333
151951
  // src/appConfig.ts
152334
- import * as fs5 from "fs";
152335
- import * as path5 from "path";
151952
+ import * as fs3 from "fs";
151953
+ import * as path3 from "path";
152336
151954
  function configPath() {
152337
- return path5.join(getAtomixRoot(), "config.json");
151955
+ return path3.join(getAtomixRoot(), "config.json");
152338
151956
  }
152339
151957
  function configFilePath() {
152340
151958
  return configPath();
152341
151959
  }
152342
151960
  function readConfig() {
152343
151961
  try {
152344
- return JSON.parse(fs5.readFileSync(configPath(), "utf8"));
151962
+ return JSON.parse(fs3.readFileSync(configPath(), "utf8"));
152345
151963
  } catch {
152346
151964
  return {};
152347
151965
  }
@@ -152349,7 +151967,7 @@ function readConfig() {
152349
151967
  function readConfigForWrite() {
152350
151968
  let text;
152351
151969
  try {
152352
- text = fs5.readFileSync(configPath(), "utf8");
151970
+ text = fs3.readFileSync(configPath(), "utf8");
152353
151971
  } catch (e) {
152354
151972
  if (e.code === "ENOENT") return {};
152355
151973
  throw e;
@@ -152362,8 +151980,8 @@ function readConfigForWrite() {
152362
151980
  }
152363
151981
  function writeConfig(patch) {
152364
151982
  const next = { ...readConfigForWrite(), ...patch };
152365
- fs5.mkdirSync(getAtomixRoot(), { recursive: true });
152366
- fs5.writeFileSync(configPath(), JSON.stringify(next, null, 2) + "\n");
151983
+ fs3.mkdirSync(getAtomixRoot(), { recursive: true });
151984
+ fs3.writeFileSync(configPath(), JSON.stringify(next, null, 2) + "\n");
152367
151985
  }
152368
151986
  function applyConfiguredTheme() {
152369
151987
  const name = readConfig().theme;
@@ -152387,7 +152005,7 @@ function buildContextFilesConfig(cwd2, cfg) {
152387
152005
  if (s.memoryGlobal) memoryFiles.push({ path: p.globalMemory, label: "user-level" });
152388
152006
  if (s.memoryProject) {
152389
152007
  try {
152390
- fs5.mkdirSync(p.projectDir, { recursive: true });
152008
+ fs3.mkdirSync(p.projectDir, { recursive: true });
152391
152009
  } catch {
152392
152010
  }
152393
152011
  memoryFiles.push({ path: p.projectMemory, label: "project-level" });
@@ -152403,7 +152021,7 @@ function buildPotentialContextFiles(cwd2, cfg) {
152403
152021
  if (cfg.memory?.global !== false) memoryFiles.push({ path: p.globalMemory, label: "user-level" });
152404
152022
  if (cfg.memory?.project !== false) {
152405
152023
  try {
152406
- fs5.mkdirSync(p.projectDir, { recursive: true });
152024
+ fs3.mkdirSync(p.projectDir, { recursive: true });
152407
152025
  } catch {
152408
152026
  }
152409
152027
  memoryFiles.push({ path: p.projectMemory, label: "project-level" });
@@ -152437,39 +152055,39 @@ var init_appConfig = __esm({
152437
152055
  });
152438
152056
 
152439
152057
  // src/marketplace.ts
152440
- import * as fs6 from "fs";
152058
+ import * as fs4 from "fs";
152441
152059
  import * as os4 from "os";
152442
- import * as path6 from "path";
152060
+ import * as path4 from "path";
152443
152061
  import { randomUUID } from "crypto";
152444
152062
  import { execFile } from "child_process";
152445
152063
  import { promisify } from "util";
152446
152064
  function ownConfigPath() {
152447
- return path6.join(getAtomixRoot(), "marketplace.json");
152065
+ return path4.join(getAtomixRoot(), "marketplace.json");
152448
152066
  }
152449
152067
  function clonesDir() {
152450
- return path6.join(getAtomixRoot(), "marketplace");
152068
+ return path4.join(getAtomixRoot(), "marketplace");
152451
152069
  }
152452
- function statePath2() {
152453
- return path6.join(getAtomixRoot(), "marketplace-state.json");
152070
+ function statePath() {
152071
+ return path4.join(getAtomixRoot(), "marketplace-state.json");
152454
152072
  }
152455
152073
  function initMarketplaceProject(cwd2) {
152456
- activeProjectDir = path6.resolve(cwd2);
152074
+ activeProjectDir = path4.resolve(cwd2);
152457
152075
  if (_instance) _instance.reload();
152458
152076
  }
152459
152077
  function projectStatePath() {
152460
- return activeProjectDir ? path6.join(activeProjectDir, ".atomix", "marketplace-state.json") : null;
152078
+ return activeProjectDir ? path4.join(activeProjectDir, ".atomix", "marketplace-state.json") : null;
152461
152079
  }
152462
152080
  function resolveTilde(p) {
152463
- return p.startsWith("~/") ? path6.join(os4.homedir(), p.slice(2)) : path6.resolve(p);
152081
+ return p.startsWith("~/") ? path4.join(os4.homedir(), p.slice(2)) : path4.resolve(p);
152464
152082
  }
152465
152083
  async function cloneOrPull(url, branch, localPath) {
152466
- if (fs6.existsSync(path6.join(localPath, ".git"))) {
152084
+ if (fs4.existsSync(path4.join(localPath, ".git"))) {
152467
152085
  await execFileP("git", ["-C", localPath, "fetch", "origin"], { timeout: 12e4 });
152468
152086
  await execFileP("git", ["-C", localPath, "checkout", branch], { timeout: 3e4 });
152469
152087
  await execFileP("git", ["-C", localPath, "pull", "origin", branch], { timeout: 12e4 });
152470
152088
  } else {
152471
- if (fs6.existsSync(localPath)) fs6.rmSync(localPath, { recursive: true, force: true });
152472
- fs6.mkdirSync(path6.dirname(localPath), { recursive: true });
152089
+ if (fs4.existsSync(localPath)) fs4.rmSync(localPath, { recursive: true, force: true });
152090
+ fs4.mkdirSync(path4.dirname(localPath), { recursive: true });
152473
152091
  await execFileP("git", ["clone", "--depth", "1", "--branch", branch, url, localPath], { timeout: 3e5 });
152474
152092
  }
152475
152093
  }
@@ -152501,7 +152119,7 @@ function refreshCommandsExtraDirs() {
152501
152119
  for (const [, d] of sessionRegistry) d.commands.splice(0, d.commands.length, ...fresh);
152502
152120
  }
152503
152121
  function syncMarketplaceMcp() {
152504
- const mcpPath = path6.join(getAtomixRoot(), "mcp.json");
152122
+ const mcpPath = path4.join(getAtomixRoot(), "mcp.json");
152505
152123
  const file = readJson(mcpPath) ?? { mcpServers: {} };
152506
152124
  if (!file.mcpServers || typeof file.mcpServers !== "object") file.mcpServers = {};
152507
152125
  const before2 = JSON.stringify(file.mcpServers);
@@ -152526,13 +152144,13 @@ function syncMarketplaceMcp() {
152526
152144
  }
152527
152145
  const removed = [...localCopies.keys()].filter((k) => !synced.includes(k));
152528
152146
  if (JSON.stringify(file.mcpServers) !== before2) {
152529
- fs6.mkdirSync(getAtomixRoot(), { recursive: true });
152530
- fs6.writeFileSync(mcpPath, JSON.stringify(file, null, 2) + "\n");
152147
+ fs4.mkdirSync(getAtomixRoot(), { recursive: true });
152148
+ fs4.writeFileSync(mcpPath, JSON.stringify(file, null, 2) + "\n");
152531
152149
  }
152532
152150
  return { synced, removed, entries };
152533
152151
  }
152534
152152
  function getEffectiveMcpEntries() {
152535
- const mcpPath = path6.join(getAtomixRoot(), "mcp.json");
152153
+ const mcpPath = path4.join(getAtomixRoot(), "mcp.json");
152536
152154
  const file = readJson(mcpPath);
152537
152155
  const local = file?.mcpServers ?? {};
152538
152156
  return getMarketplace().getMCPServerDefs("effective").map((def) => ({
@@ -152542,17 +152160,17 @@ function getEffectiveMcpEntries() {
152542
152160
  }
152543
152161
  function readJson(p) {
152544
152162
  try {
152545
- return JSON.parse(fs6.readFileSync(p, "utf8"));
152163
+ return JSON.parse(fs4.readFileSync(p, "utf8"));
152546
152164
  } catch {
152547
152165
  return null;
152548
152166
  }
152549
152167
  }
152550
152168
  function listDirs(p) {
152551
152169
  try {
152552
- return fs6.readdirSync(p).filter((e) => {
152170
+ return fs4.readdirSync(p).filter((e) => {
152553
152171
  if (e.startsWith(".")) return false;
152554
152172
  try {
152555
- return fs6.statSync(path6.join(p, e)).isDirectory();
152173
+ return fs4.statSync(path4.join(p, e)).isDirectory();
152556
152174
  } catch {
152557
152175
  return false;
152558
152176
  }
@@ -152562,9 +152180,9 @@ function listDirs(p) {
152562
152180
  }
152563
152181
  }
152564
152182
  function readPluginMCPConfig(pluginDir) {
152565
- const dotMcp = readJson(path6.join(pluginDir, ".mcp.json"));
152183
+ const dotMcp = readJson(path4.join(pluginDir, ".mcp.json"));
152566
152184
  if (dotMcp) return parseDotMcpJson(dotMcp, pluginDir);
152567
- const mcpFile = readJson(path6.join(pluginDir, "mcp", "mcp.json"));
152185
+ const mcpFile = readJson(path4.join(pluginDir, "mcp", "mcp.json"));
152568
152186
  return Array.isArray(mcpFile?.servers) ? mcpFile.servers : [];
152569
152187
  }
152570
152188
  function parseDotMcpJson(data, pluginDir) {
@@ -152596,20 +152214,20 @@ function parseDotMcpJson(data, pluginDir) {
152596
152214
  }
152597
152215
  function countPluginContents(dir) {
152598
152216
  let skillCount = 0;
152599
- const skillsDir = path6.join(dir, "skills");
152217
+ const skillsDir = path4.join(dir, "skills");
152600
152218
  for (const entry of listDirs(skillsDir)) {
152601
- if (["SKILL.md", "skill.md", "Skill.md"].some((n) => fs6.existsSync(path6.join(skillsDir, entry, n)))) skillCount++;
152219
+ if (["SKILL.md", "skill.md", "Skill.md"].some((n) => fs4.existsSync(path4.join(skillsDir, entry, n)))) skillCount++;
152602
152220
  }
152603
152221
  let commandCount = 0;
152604
152222
  try {
152605
- commandCount = fs6.readdirSync(path6.join(dir, "commands")).filter((e) => e.endsWith(".md") && !e.startsWith(".")).length;
152223
+ commandCount = fs4.readdirSync(path4.join(dir, "commands")).filter((e) => e.endsWith(".md") && !e.startsWith(".")).length;
152606
152224
  } catch {
152607
152225
  }
152608
152226
  return {
152609
152227
  skillCount,
152610
152228
  commandCount,
152611
152229
  mcpServerCount: readPluginMCPConfig(dir).length,
152612
- hasHooks: fs6.existsSync(path6.join(dir, "hooks", "hooks.json"))
152230
+ hasHooks: fs4.existsSync(path4.join(dir, "hooks", "hooks.json"))
152613
152231
  };
152614
152232
  }
152615
152233
  var execFileP, MKT_PREFIX, activeProjectDir, Marketplace, _instance, sessionRegistry;
@@ -152633,7 +152251,7 @@ var init_marketplace = __esm({
152633
152251
  reload() {
152634
152252
  this.own = readJson(ownConfigPath()) ?? { sources: [] };
152635
152253
  if (!Array.isArray(this.own.sources)) this.own = { sources: [] };
152636
- this.state = readJson(statePath2()) ?? {};
152254
+ this.state = readJson(statePath()) ?? {};
152637
152255
  const pp = projectStatePath();
152638
152256
  this.projectState = (pp ? readJson(pp) : null) ?? {};
152639
152257
  this.external = [];
@@ -152661,7 +152279,7 @@ var init_marketplace = __esm({
152661
152279
  type: data.type,
152662
152280
  url: data.url,
152663
152281
  branch: data.branch ?? "main",
152664
- localPath: data.type === "git" ? path6.join(clonesDir(), id) : resolveTilde(data.localPath ?? ""),
152282
+ localPath: data.type === "git" ? path4.join(clonesDir(), id) : resolveTilde(data.localPath ?? ""),
152665
152283
  priority: maxPriority + 1,
152666
152284
  enabled: true,
152667
152285
  lastSynced: null
@@ -152695,7 +152313,7 @@ var init_marketplace = __esm({
152695
152313
  this.saveState();
152696
152314
  if (source.type === "git") {
152697
152315
  try {
152698
- fs6.rmSync(path6.join(clonesDir(), source.id), { recursive: true, force: true });
152316
+ fs4.rmSync(path4.join(clonesDir(), source.id), { recursive: true, force: true });
152699
152317
  } catch {
152700
152318
  }
152701
152319
  }
@@ -152764,26 +152382,26 @@ var init_marketplace = __esm({
152764
152382
  /** 插件配置目录优先级:.atomix-plugin > .semaclaw-plugin > .claude-plugin */
152765
152383
  resolvePluginJson(dir) {
152766
152384
  for (const conf of [".atomix-plugin", ".semaclaw-plugin", ".claude-plugin"]) {
152767
- const p = path6.join(dir, conf, "plugin.json");
152768
- if (fs6.existsSync(p)) return p;
152385
+ const p = path4.join(dir, conf, "plugin.json");
152386
+ if (fs4.existsSync(p)) return p;
152769
152387
  }
152770
152388
  return null;
152771
152389
  }
152772
152390
  /** 三种布局:源根即插件 / 平铺插件子目录 / 分组目录再下一层 */
152773
152391
  findPlugins(localPath) {
152774
- if (!fs6.existsSync(localPath)) return [];
152392
+ if (!fs4.existsSync(localPath)) return [];
152775
152393
  const rootJson = this.resolvePluginJson(localPath);
152776
152394
  if (rootJson) return [{ dir: localPath, pluginJsonPath: rootJson }];
152777
152395
  const results = [];
152778
152396
  for (const entry of listDirs(localPath)) {
152779
- const entryPath = path6.join(localPath, entry);
152397
+ const entryPath = path4.join(localPath, entry);
152780
152398
  const pluginJson = this.resolvePluginJson(entryPath);
152781
152399
  if (pluginJson) {
152782
152400
  results.push({ dir: entryPath, pluginJsonPath: pluginJson });
152783
152401
  continue;
152784
152402
  }
152785
152403
  for (const sub of listDirs(entryPath)) {
152786
- const subPath = path6.join(entryPath, sub);
152404
+ const subPath = path4.join(entryPath, sub);
152787
152405
  const subJson = this.resolvePluginJson(subPath);
152788
152406
  if (subJson) results.push({ dir: subPath, pluginJsonPath: subJson });
152789
152407
  }
@@ -152792,7 +152410,7 @@ var init_marketplace = __esm({
152792
152410
  }
152793
152411
  pluginName(def) {
152794
152412
  const meta = readJson(def.pluginJsonPath) ?? {};
152795
- return meta.name || path6.basename(def.dir);
152413
+ return meta.name || path4.basename(def.dir);
152796
152414
  }
152797
152415
  /** 启用的源,按 priority 降序(高优先级源后处理 = 覆盖生效) */
152798
152416
  enabledSourcesByDescPriority() {
@@ -152813,8 +152431,8 @@ var init_marketplace = __esm({
152813
152431
  getSkillExtraDirs() {
152814
152432
  const result2 = [];
152815
152433
  for (const { def } of this.enabledPluginDirs()) {
152816
- const dir = path6.join(def.dir, "skills");
152817
- if (fs6.existsSync(dir)) result2.push({ dir, locate: "managed" });
152434
+ const dir = path4.join(def.dir, "skills");
152435
+ if (fs4.existsSync(dir)) result2.push({ dir, locate: "managed" });
152818
152436
  }
152819
152437
  return result2;
152820
152438
  }
@@ -152822,8 +152440,8 @@ var init_marketplace = __esm({
152822
152440
  getCommandDirs() {
152823
152441
  const result2 = [];
152824
152442
  for (const { def } of this.enabledPluginDirs()) {
152825
- const dir = path6.join(def.dir, "commands");
152826
- if (fs6.existsSync(dir)) result2.push(dir);
152443
+ const dir = path4.join(def.dir, "commands");
152444
+ if (fs4.existsSync(dir)) result2.push(dir);
152827
152445
  }
152828
152446
  return result2;
152829
152447
  }
@@ -152832,8 +152450,8 @@ var init_marketplace = __esm({
152832
152450
  const result2 = [];
152833
152451
  for (const { def } of this.enabledPluginDirs()) {
152834
152452
  for (const dirName of ["subagents", "agents"]) {
152835
- const dir = path6.join(def.dir, dirName);
152836
- if (fs6.existsSync(dir)) result2.push(dir);
152453
+ const dir = path4.join(def.dir, dirName);
152454
+ if (fs4.existsSync(dir)) result2.push(dir);
152837
152455
  }
152838
152456
  }
152839
152457
  return result2;
@@ -152842,8 +152460,8 @@ var init_marketplace = __esm({
152842
152460
  getHookEntries() {
152843
152461
  const result2 = [];
152844
152462
  for (const { def } of this.enabledPluginDirs()) {
152845
- const file = path6.join(def.dir, "hooks", "hooks.json");
152846
- if (fs6.existsSync(file)) result2.push({ file, pluginDir: def.dir });
152463
+ const file = path4.join(def.dir, "hooks", "hooks.json");
152464
+ if (fs4.existsSync(file)) result2.push({ file, pluginDir: def.dir });
152847
152465
  }
152848
152466
  return result2;
152849
152467
  }
@@ -152868,7 +152486,7 @@ var init_marketplace = __esm({
152868
152486
  for (const source of this.getSources()) {
152869
152487
  for (const def of this.findPlugins(source.localPath)) {
152870
152488
  const meta = readJson(def.pluginJsonPath) ?? {};
152871
- const name = meta.name || path6.basename(def.dir);
152489
+ const name = meta.name || path4.basename(def.dir);
152872
152490
  result2.push({
152873
152491
  name,
152874
152492
  description: meta.description ?? "",
@@ -152889,18 +152507,18 @@ var init_marketplace = __esm({
152889
152507
  }
152890
152508
  // ===== 持久化 =====
152891
152509
  saveOwn() {
152892
- fs6.mkdirSync(getAtomixRoot(), { recursive: true });
152893
- fs6.writeFileSync(ownConfigPath(), JSON.stringify(this.own, null, 2) + "\n");
152510
+ fs4.mkdirSync(getAtomixRoot(), { recursive: true });
152511
+ fs4.writeFileSync(ownConfigPath(), JSON.stringify(this.own, null, 2) + "\n");
152894
152512
  }
152895
152513
  saveState() {
152896
- fs6.mkdirSync(getAtomixRoot(), { recursive: true });
152897
- fs6.writeFileSync(statePath2(), JSON.stringify(this.state, null, 2) + "\n");
152514
+ fs4.mkdirSync(getAtomixRoot(), { recursive: true });
152515
+ fs4.writeFileSync(statePath(), JSON.stringify(this.state, null, 2) + "\n");
152898
152516
  }
152899
152517
  saveProjectState() {
152900
152518
  const pp = projectStatePath();
152901
152519
  if (!pp) throw new Error("\u9879\u76EE\u7EA7 override \u9700\u8981\u5148 initMarketplaceProject(cwd)");
152902
- fs6.mkdirSync(path6.dirname(pp), { recursive: true });
152903
- fs6.writeFileSync(pp, JSON.stringify(this.projectState, null, 2) + "\n");
152520
+ fs4.mkdirSync(path4.dirname(pp), { recursive: true });
152521
+ fs4.writeFileSync(pp, JSON.stringify(this.projectState, null, 2) + "\n");
152904
152522
  }
152905
152523
  };
152906
152524
  _instance = null;
@@ -152919,23 +152537,23 @@ __export(skills_exports, {
152919
152537
  refreshSkillsExtraDirs: () => refreshSkillsExtraDirs,
152920
152538
  skillsCommand: () => skillsCommand
152921
152539
  });
152922
- import * as fs7 from "fs";
152540
+ import * as fs5 from "fs";
152923
152541
  import * as os5 from "os";
152924
- import * as path7 from "path";
152925
- function disabledFile2() {
152926
- return path7.join(getAtomixRoot(), "disabled-skills.json");
152542
+ import * as path5 from "path";
152543
+ function disabledFile() {
152544
+ return path5.join(getAtomixRoot(), "disabled-skills.json");
152927
152545
  }
152928
152546
  function readDisabledSkills() {
152929
152547
  try {
152930
- const parsed = JSON.parse(fs7.readFileSync(disabledFile2(), "utf8"));
152548
+ const parsed = JSON.parse(fs5.readFileSync(disabledFile(), "utf8"));
152931
152549
  if (Array.isArray(parsed.disabled)) return new Set(parsed.disabled);
152932
152550
  } catch {
152933
152551
  }
152934
152552
  return /* @__PURE__ */ new Set();
152935
152553
  }
152936
152554
  function writeDisabledSkills(disabled) {
152937
- fs7.mkdirSync(getAtomixRoot(), { recursive: true });
152938
- fs7.writeFileSync(disabledFile2(), JSON.stringify({ disabled: [...disabled].sort() }, null, 2) + "\n");
152555
+ fs5.mkdirSync(getAtomixRoot(), { recursive: true });
152556
+ fs5.writeFileSync(disabledFile(), JSON.stringify({ disabled: [...disabled].sort() }, null, 2) + "\n");
152939
152557
  }
152940
152558
  function disableSkill(name) {
152941
152559
  const s = readDisabledSkills();
@@ -152949,23 +152567,23 @@ function enableSkill(name) {
152949
152567
  return true;
152950
152568
  }
152951
152569
  function resolveTilde2(p) {
152952
- return p.startsWith("~/") ? path7.join(os5.homedir(), p.slice(2)) : path7.resolve(p);
152570
+ return p.startsWith("~/") ? path5.join(os5.homedir(), p.slice(2)) : path5.resolve(p);
152953
152571
  }
152954
152572
  function computeSkillsExtraDirs() {
152955
152573
  const eco = readConfig().ecosystem ?? {};
152956
152574
  const dirs = [];
152957
- const claudeSkills = path7.join(os5.homedir(), ".claude", "skills");
152958
- if ((eco.inheritClaudeSkills ?? true) && fs7.existsSync(claudeSkills)) {
152575
+ const claudeSkills = path5.join(os5.homedir(), ".claude", "skills");
152576
+ if ((eco.inheritClaudeSkills ?? true) && fs5.existsSync(claudeSkills)) {
152959
152577
  dirs.push({ dir: claudeSkills, locate: "user" });
152960
152578
  }
152961
- const semaclawHome = process.env.SEMACLAW_CONFIG_HOME ? path7.resolve(process.env.SEMACLAW_CONFIG_HOME) : path7.join(os5.homedir(), ".semaclaw");
152962
- const managedSkills = path7.join(semaclawHome, "managed", "skills");
152963
- if ((eco.inheritSemaclawManagedSkills ?? true) && fs7.existsSync(managedSkills)) {
152579
+ const semaclawHome = process.env.SEMACLAW_CONFIG_HOME ? path5.resolve(process.env.SEMACLAW_CONFIG_HOME) : path5.join(os5.homedir(), ".semaclaw");
152580
+ const managedSkills = path5.join(semaclawHome, "managed", "skills");
152581
+ if ((eco.inheritSemaclawManagedSkills ?? true) && fs5.existsSync(managedSkills)) {
152964
152582
  dirs.push({ dir: managedSkills, locate: "managed" });
152965
152583
  }
152966
152584
  for (const d of eco.sharedSkillDirs ?? []) {
152967
152585
  const resolved = resolveTilde2(d);
152968
- if (fs7.existsSync(resolved)) dirs.push({ dir: resolved, locate: "managed" });
152586
+ if (fs5.existsSync(resolved)) dirs.push({ dir: resolved, locate: "managed" });
152969
152587
  }
152970
152588
  dirs.push(...getMarketplace().getSkillExtraDirs());
152971
152589
  return dirs;
@@ -152986,13 +152604,13 @@ function applyDisabledSkills(core) {
152986
152604
  }
152987
152605
  function sourceLabel(s) {
152988
152606
  const p = s.filePath ?? "";
152989
- if (p.includes(`${path7.sep}.claude${path7.sep}`)) return "claude";
152990
- if (p.includes(`${path7.sep}.semaclaw${path7.sep}`)) return "semaclaw";
152991
- if (p.includes(`${path7.sep}marketplace${path7.sep}`)) return "marketplace";
152607
+ if (p.includes(`${path5.sep}.claude${path5.sep}`)) return "claude";
152608
+ if (p.includes(`${path5.sep}.semaclaw${path5.sep}`)) return "semaclaw";
152609
+ if (p.includes(`${path5.sep}marketplace${path5.sep}`)) return "marketplace";
152992
152610
  return LOCATE_LABEL[s.locate] ?? s.locate;
152993
152611
  }
152994
152612
  function semaclawConfigHome() {
152995
- return process.env.SEMACLAW_CONFIG_HOME ? path7.resolve(process.env.SEMACLAW_CONFIG_HOME) : path7.join(os5.homedir(), ".semaclaw");
152613
+ return process.env.SEMACLAW_CONFIG_HOME ? path5.resolve(process.env.SEMACLAW_CONFIG_HOME) : path5.join(os5.homedir(), ".semaclaw");
152996
152614
  }
152997
152615
  async function skillsCommand(core, args) {
152998
152616
  const [sub, ...rest2] = args;
@@ -153029,7 +152647,7 @@ async function skillsCommand(core, args) {
153029
152647
  const semaclawDisabled = (() => {
153030
152648
  try {
153031
152649
  const parsed = JSON.parse(
153032
- fs7.readFileSync(path7.join(semaclawConfigHome(), "disabled-skills.json"), "utf8")
152650
+ fs5.readFileSync(path5.join(semaclawConfigHome(), "disabled-skills.json"), "utf8")
153033
152651
  );
153034
152652
  return Array.isArray(parsed.disabled) ? parsed.disabled : [];
153035
152653
  } catch {
@@ -153067,6 +152685,905 @@ var init_skills = __esm({
153067
152685
  }
153068
152686
  });
153069
152687
 
152688
+ // src/agents.ts
152689
+ var agents_exports = {};
152690
+ __export(agents_exports, {
152691
+ agentsCommand: () => agentsCommand,
152692
+ applyDisabledAgents: () => applyDisabledAgents,
152693
+ disableAgent: () => disableAgent,
152694
+ enableAgent: () => enableAgent,
152695
+ readDisabledAgents: () => readDisabledAgents
152696
+ });
152697
+ import * as fs6 from "fs";
152698
+ import * as path6 from "path";
152699
+ function disabledFile2() {
152700
+ return path6.join(getAtomixRoot(), "disabled-agents.json");
152701
+ }
152702
+ function readDisabledAgents() {
152703
+ try {
152704
+ const parsed = JSON.parse(fs6.readFileSync(disabledFile2(), "utf8"));
152705
+ if (Array.isArray(parsed.disabled)) return new Set(parsed.disabled);
152706
+ } catch {
152707
+ }
152708
+ return /* @__PURE__ */ new Set();
152709
+ }
152710
+ function writeDisabledAgents(disabled) {
152711
+ fs6.mkdirSync(getAtomixRoot(), { recursive: true });
152712
+ fs6.writeFileSync(disabledFile2(), JSON.stringify({ disabled: [...disabled].sort() }, null, 2) + "\n");
152713
+ }
152714
+ function disableAgent(name) {
152715
+ const s = readDisabledAgents();
152716
+ s.add(name);
152717
+ writeDisabledAgents(s);
152718
+ }
152719
+ function enableAgent(name) {
152720
+ const s = readDisabledAgents();
152721
+ if (!s.delete(name)) return false;
152722
+ writeDisabledAgents(s);
152723
+ return true;
152724
+ }
152725
+ async function applyDisabledAgents(core) {
152726
+ await core.reloadAgents(/* @__PURE__ */ new Set());
152727
+ const allNames = core.getAgentsInfo().map((a) => a.name);
152728
+ recordAgentUniverse(core, allNames);
152729
+ const disabled = /* @__PURE__ */ new Set([...readDisabledAgents(), ...harnessDisabledAgents(core, allNames)]);
152730
+ await core.reloadAgents(disabled);
152731
+ }
152732
+ async function agentsCommand(core, args) {
152733
+ const [sub, ...rest2] = args;
152734
+ const name = rest2.join(" ").trim();
152735
+ switch (sub) {
152736
+ case void 0:
152737
+ case "list": {
152738
+ const infos = [...core.getAgentsInfo()].sort(
152739
+ (a, b) => a.locate.localeCompare(b.locate) || a.name.localeCompare(b.name)
152740
+ );
152741
+ const disabledSet = readDisabledAgents();
152742
+ const lines = infos.filter((a) => !disabledSet.has(a.name)).map((a) => {
152743
+ const desc = a.description ? ` \u2014 ${a.description.length > 60 ? a.description.slice(0, 60) + "\u2026" : a.description}` : "";
152744
+ return `\u25CF ${a.name} [${a.locate}]${desc}`;
152745
+ });
152746
+ for (const n of [...disabledSet].sort()) lines.push(`\u25CB ${n} \uFF08\u5DF2\u7981\u7528\uFF09`);
152747
+ if (!lines.length) lines.push("\uFF08\u65E0\u53EF\u7528\u4EBA\u8BBE\uFF09");
152748
+ lines.push(`\u25CF \u542F\u7528\u4E2D \u25CB \u5DF2\u7981\u7528${disabledSet.size === 0 ? "\uFF08\u5F53\u524D\u65E0\u7981\u7528\u9879\uFF09" : ""} \xB7 \u7528\u6CD5\uFF1A/agents list | enable <\u540D\u79F0> | disable <\u540D\u79F0>`);
152749
+ return lines.join("\n ");
152750
+ }
152751
+ case "disable": {
152752
+ if (!name) return "\u7528\u6CD5\uFF1A/agents disable <\u540D\u79F0>";
152753
+ disableAgent(name);
152754
+ await applyDisabledAgents(core);
152755
+ return `\u5DF2\u7981\u7528\u4EBA\u8BBE\uFF1A${name}`;
152756
+ }
152757
+ case "enable": {
152758
+ if (!name) return "\u7528\u6CD5\uFF1A/agents enable <\u540D\u79F0>";
152759
+ if (!enableAgent(name)) return `${name} \u672A\u88AB\u7981\u7528`;
152760
+ await applyDisabledAgents(core);
152761
+ return `\u5DF2\u542F\u7528\u4EBA\u8BBE\uFF1A${name}`;
152762
+ }
152763
+ default:
152764
+ return `\u672A\u77E5\u5B50\u547D\u4EE4\uFF1A${sub}\uFF08\u7528\u6CD5\uFF1A/agents list | enable <\u540D\u79F0> | disable <\u540D\u79F0>\uFF09`;
152765
+ }
152766
+ }
152767
+ var init_agents = __esm({
152768
+ "src/agents.ts"() {
152769
+ "use strict";
152770
+ init_paths();
152771
+ init_harness();
152772
+ }
152773
+ });
152774
+
152775
+ // src/harness.ts
152776
+ import * as fs7 from "fs";
152777
+ import * as path7 from "path";
152778
+ function runtimeOf(core) {
152779
+ return runtimes.get(core) ?? null;
152780
+ }
152781
+ function requireRuntime(core) {
152782
+ const rt = runtimeOf(core);
152783
+ if (!rt) throw new Error("harness \u672A\u521D\u59CB\u5316(initHarness \u672A\u8C03\u7528)");
152784
+ return rt;
152785
+ }
152786
+ function overrideOf(activeValue, baseValue) {
152787
+ if (baseValue === void 0 || activeValue === void 0) return null;
152788
+ const baseOn = baseValue !== null;
152789
+ const activeOn = activeValue !== null;
152790
+ return activeOn === baseOn ? null : activeOn ? "on" : "off";
152791
+ }
152792
+ function personaOverrideOf(activeValue, baseValue) {
152793
+ const basic = overrideOf(activeValue, baseValue);
152794
+ if (basic !== null) return basic;
152795
+ if (activeValue && baseValue && activeValue !== baseValue) return "swap";
152796
+ return null;
152797
+ }
152798
+ function harnessMemoryOverride(core) {
152799
+ const rt = runtimeOf(core);
152800
+ return rt ? overrideOf(rt.activeMemoryFiles, rt.baseline.memoryFiles) : null;
152801
+ }
152802
+ function harnessPersonaOverride(core) {
152803
+ const rt = runtimeOf(core);
152804
+ return rt ? personaOverrideOf(rt.activePersonaFile, rt.baseline.personaFile) : null;
152805
+ }
152806
+ function getActivePersonaFile(core) {
152807
+ return runtimeOf(core)?.activePersonaFile;
152808
+ }
152809
+ function getActiveHarnessName(core) {
152810
+ return runtimeOf(core)?.active?.name ?? BASE_HARNESS;
152811
+ }
152812
+ function getActiveHarnessDir(core) {
152813
+ return runtimeOf(core)?.active?.dirName ?? BASE_HARNESS;
152814
+ }
152815
+ function isHarnessActive(core) {
152816
+ return !!runtimeOf(core)?.active;
152817
+ }
152818
+ function harnessThinking(core) {
152819
+ return runtimeOf(core)?.active?.thinkingDeclared ?? null;
152820
+ }
152821
+ function appliedThinking(core) {
152822
+ return runtimeOf(core)?.activeThinking;
152823
+ }
152824
+ function thinkingStatusLine(core, current) {
152825
+ const on = (v) => v ? "on" : "off";
152826
+ const declared = harnessThinking(core);
152827
+ if (declared === null) return on(current);
152828
+ const dir = getActiveHarnessDir(core);
152829
+ return declared === current ? `${on(current)}(harness ${dir},\u4EC5 main;quick \u6052\u5173)` : `${on(current)}(\u4F1A\u8BDD\u4E34\u65F6\u5207\u6362;harness ${dir} \u58F0\u660E ${on(declared)},/harness use ${dir} \u91CD\u65B0\u5E94\u7528\u5373\u6062\u590D)`;
152830
+ }
152831
+ function harnessTemperatureOverride(core) {
152832
+ return runtimeOf(core)?.active?.temperatureOverrides ?? null;
152833
+ }
152834
+ function effectiveTemperatures(core) {
152835
+ const models = effectiveModels(core);
152836
+ const profiles = core.getModelProfiles();
152837
+ const over2 = harnessTemperatureOverride(core);
152838
+ const one = (slot) => {
152839
+ const prof = profiles.find((p) => p.name === models[slot]);
152840
+ const mn = prof?.modelName;
152841
+ if (mn && (0, import_atomix_core4.modelForcesTemperatureOne)(mn)) return { value: 1, from: "fixed" };
152842
+ if (mn && (0, import_atomix_core4.modelRejectsTemperature)(mn)) return { value: null, from: "unsupported" };
152843
+ const anthropic = prof?.adapt === "anthropic";
152844
+ const gatedByThinking = anthropic || (mn ? (0, import_atomix_core4.modelTemperatureGatedByThinking)(mn) : false);
152845
+ const notes = [];
152846
+ let from = "default";
152847
+ let raw;
152848
+ const o = over2?.[slot];
152849
+ if (o !== void 0) {
152850
+ if ((0, import_atomix_core4.isValidTemperature)(o)) {
152851
+ raw = o;
152852
+ from = "harness";
152853
+ } else notes.push(`harness \u503C ${JSON.stringify(o)} \u975E\u6CD5(\u987B 0\u20132),\u5DF2\u5FFD\u7565`);
152854
+ }
152855
+ if (raw === void 0 && prof?.temperature !== void 0) {
152856
+ if ((0, import_atomix_core4.isValidTemperature)(prof.temperature)) {
152857
+ raw = prof.temperature;
152858
+ from = "profile";
152859
+ } else notes.push(`profile \u503C ${JSON.stringify(prof.temperature)} \u975E\u6CD5(\u987B 0\u20132),\u5DF2\u5FFD\u7565`);
152860
+ }
152861
+ if (raw === void 0) {
152862
+ return { value: anthropic ? import_atomix_core4.DEFAULT_ANTHROPIC_TEMPERATURE : null, from: "default", ...gatedByThinking ? { gatedByThinking } : {}, ...notes.length ? { notes } : {} };
152863
+ }
152864
+ let value = raw;
152865
+ if (anthropic && value > 1) {
152866
+ value = 1;
152867
+ notes.push(`\u58F0\u660E ${raw} \u8D85 anthropic \u534F\u8BAE\u4E0A\u9650,\u5B9E\u9645\u6309 1 \u53D1`);
152868
+ }
152869
+ return { value, from, configured: raw, ...gatedByThinking ? { gatedByThinking } : {}, ...notes.length ? { notes } : {} };
152870
+ };
152871
+ return { main: one("main"), quick: one("quick") };
152872
+ }
152873
+ function formatTemperature(e, thinkingOn) {
152874
+ if (e.from === "fixed") return "1(\u6A21\u578B\u56FA\u5B9A)";
152875
+ if (e.from === "unsupported") return "\u4E0D\u652F\u6301";
152876
+ const notes = e.notes?.length ? ";" + e.notes.join(";") : "";
152877
+ const hint = e.gatedByThinking && thinkingOn === void 0 ? ";thinking \u5F00\u65F6\u4E0D\u53D1" : "";
152878
+ if (e.from === "default") {
152879
+ if (thinkingOn && e.gatedByThinking) return `\u4E0D\u53D1(thinking \u5F00;${e.value === null ? "\u5173\u65F6\u4E3A\u670D\u52A1\u7AEF\u9ED8\u8BA4" : `\u5173\u65F6\u4E3A\u9ED8\u8BA4 ${e.value}`}${notes})`;
152880
+ return `\u9ED8\u8BA4(${e.value === null ? "\u670D\u52A1\u7AEF" : e.value}${notes}${hint})`;
152881
+ }
152882
+ const cfg = `${e.configured ?? e.value}(${e.from})`;
152883
+ if (thinkingOn && e.gatedByThinking) return `\u4E0D\u53D1(thinking \u5F00;\u914D\u7F6E ${cfg}${notes})`;
152884
+ return `${e.value}(${e.from}${notes}${hint})`;
152885
+ }
152886
+ function temperatureStatusLine(core, thinkingOn) {
152887
+ const t = effectiveTemperatures(core);
152888
+ return `main=${formatTemperature(t.main, thinkingOn)} quick=${formatTemperature(t.quick, false)}`;
152889
+ }
152890
+ function harnessModelOverride(core) {
152891
+ return runtimeOf(core)?.active?.modelOverrides ?? null;
152892
+ }
152893
+ function harnessModelFallback(core) {
152894
+ return runtimeOf(core)?.active?.modelFallback ?? null;
152895
+ }
152896
+ function harnessModelDeclared(core) {
152897
+ return runtimeOf(core)?.active?.modelDeclared ?? null;
152898
+ }
152899
+ function effectiveModels(core) {
152900
+ const base = core.getModelPointers();
152901
+ const over2 = harnessModelOverride(core);
152902
+ const fb = harnessModelFallback(core);
152903
+ const pick2 = (slot) => over2?.[slot] ? [over2[slot], "harness"] : [base[slot], fb?.[slot] ? "fallback" : "base"];
152904
+ const [main, mainFrom] = pick2("main");
152905
+ const [quick, quickFrom] = pick2("quick");
152906
+ return { main, quick, mainFrom, quickFrom, ...fb ? { fallback: fb } : {} };
152907
+ }
152908
+ function modelStatusLine(core) {
152909
+ const m = effectiveModels(core);
152910
+ if (m.mainFrom === "base" && m.quickFrom === "base") return `main=${m.main || "-"} quick=${m.quick || "-"}`;
152911
+ const part = (slot) => {
152912
+ const v = m[slot] || "-";
152913
+ const from = slot === "main" ? m.mainFrom : m.quickFrom;
152914
+ if (from === "fallback") return `${slot}=${v} (base;harness \u58F0\u660E ${m.fallback?.[slot]} \u4E0D\u5B58\u5728,\u5DF2\u56DE\u843D)`;
152915
+ return `${slot}=${v} (${from})`;
152916
+ };
152917
+ return `${m.fallback ? "\u26A0 " : ""}${part("main")} ${part("quick")}`;
152918
+ }
152919
+ function isHarnessOverridden(core) {
152920
+ return runtimeOf(core)?.overridden ?? false;
152921
+ }
152922
+ function recordSkillUniverse(core, names) {
152923
+ const rt = runtimeOf(core);
152924
+ if (rt) rt.fullSkillNames = names.slice();
152925
+ }
152926
+ function recordAgentUniverse(core, names) {
152927
+ const rt = runtimeOf(core);
152928
+ if (rt) rt.fullAgentNames = names.slice();
152929
+ }
152930
+ function computeDisabledFrom(spec, allNames) {
152931
+ if (!spec) return /* @__PURE__ */ new Set();
152932
+ return spec.mode === "whitelist" ? new Set(allNames.filter((n) => !spec.enable.includes(n))) : new Set(spec.disable);
152933
+ }
152934
+ function harnessDisabledSkills(core, allNames) {
152935
+ return computeDisabledFrom(runtimeOf(core)?.active?.skillsSpec ?? null, allNames);
152936
+ }
152937
+ function harnessDisabledAgents(core, allNames) {
152938
+ return computeDisabledFrom(runtimeOf(core)?.active?.agentsSpec ?? null, allNames);
152939
+ }
152940
+ function libraryDir() {
152941
+ return path7.join(getAtomixRoot(), "harness");
152942
+ }
152943
+ function statePath2(cwd2) {
152944
+ return path7.join(cwd2, ".atomix", "harness-state.json");
152945
+ }
152946
+ function readState(cwd2) {
152947
+ try {
152948
+ const parsed = JSON.parse(fs7.readFileSync(statePath2(cwd2), "utf8"));
152949
+ return typeof parsed.active === "string" && parsed.active ? parsed.active : BASE_HARNESS;
152950
+ } catch {
152951
+ return BASE_HARNESS;
152952
+ }
152953
+ }
152954
+ function writeState(cwd2, name) {
152955
+ const p = statePath2(cwd2);
152956
+ if (name === BASE_HARNESS) {
152957
+ try {
152958
+ fs7.unlinkSync(p);
152959
+ } catch {
152960
+ }
152961
+ return;
152962
+ }
152963
+ fs7.mkdirSync(path7.dirname(p), { recursive: true });
152964
+ fs7.writeFileSync(p, JSON.stringify({ active: name }, null, 2) + "\n");
152965
+ }
152966
+ function listHarnesses() {
152967
+ let names = [];
152968
+ try {
152969
+ names = fs7.readdirSync(libraryDir(), { withFileTypes: true }).filter((e) => e.isDirectory() && fs7.existsSync(path7.join(libraryDir(), e.name, "harness.yaml"))).map((e) => e.name).sort();
152970
+ } catch {
152971
+ }
152972
+ return [BASE_HARNESS, ...names.filter((n) => n !== BASE_HARNESS)];
152973
+ }
152974
+ function asStrArr(v) {
152975
+ return Array.isArray(v) ? v.filter((x) => typeof x === "string") : [];
152976
+ }
152977
+ function asMode(v) {
152978
+ return v === "whitelist" ? "whitelist" : "blacklist";
152979
+ }
152980
+ function normalizePromptGroup(raw) {
152981
+ const warnings = [];
152982
+ if (!raw || typeof raw !== "object") return { overrides: null, warnings };
152983
+ const g = raw;
152984
+ const meta = new Map(import_atomix_core3.PROMPT_SECTION_CATALOG.map((m) => [m.name, m]));
152985
+ const replace2 = {};
152986
+ if (g.replace && typeof g.replace === "object") {
152987
+ for (const [name, text] of Object.entries(g.replace)) {
152988
+ const m = meta.get(name);
152989
+ if (!m) {
152990
+ warnings.push(`prompt.replace \u672A\u77E5\u6BB5\u540D ${name}(\u53EF\u7528:${[...meta.keys()].join(" / ")})`);
152991
+ continue;
152992
+ }
152993
+ if (m.locked) {
152994
+ warnings.push(`prompt.replace \u5FFD\u7565 ${name}:\u5B89\u5168\u6761\u6B3E\u6BB5\u4EE3\u7801\u7EA7\u9501\u5B9A`);
152995
+ continue;
152996
+ }
152997
+ if (m.dynamic) {
152998
+ warnings.push(`prompt.replace \u5FFD\u7565 ${name}:\u52A8\u6001\u6BB5(\u6BCF\u8F6E\u91CD\u7B97)\u53EA\u53EF disable`);
152999
+ continue;
153000
+ }
153001
+ if (typeof text !== "string") {
153002
+ warnings.push(`prompt.replace.${name} \u975E\u5B57\u7B26\u4E32,\u5FFD\u7565`);
153003
+ continue;
153004
+ }
153005
+ replace2[name] = text;
153006
+ }
153007
+ }
153008
+ const disable = [];
153009
+ for (const name of asStrArr(g.disable)) {
153010
+ const m = meta.get(name);
153011
+ if (!m) {
153012
+ warnings.push(`prompt.disable \u672A\u77E5\u6BB5\u540D ${name}`);
153013
+ continue;
153014
+ }
153015
+ if (m.locked) {
153016
+ warnings.push(`prompt.disable \u5FFD\u7565 ${name}:\u5B89\u5168\u6761\u6B3E\u6BB5\u4EE3\u7801\u7EA7\u9501\u5B9A`);
153017
+ continue;
153018
+ }
153019
+ disable.push(name);
153020
+ }
153021
+ const insert = [];
153022
+ if (Array.isArray(g.insert)) {
153023
+ for (const item of g.insert) {
153024
+ if (!item || typeof item !== "object") continue;
153025
+ const it = item;
153026
+ const name = typeof it.name === "string" ? it.name : "";
153027
+ const text = typeof it.text === "string" ? it.text : "";
153028
+ if (!name || !text.trim()) {
153029
+ warnings.push("prompt.insert \u5FFD\u7565\u7F3A name/text \u7684\u6761\u76EE");
153030
+ continue;
153031
+ }
153032
+ if (meta.has(name)) {
153033
+ warnings.push(`prompt.insert \u5FFD\u7565 ${name}:\u4E0E\u5185\u7F6E\u6BB5\u91CD\u540D(\u6539\u5185\u7F6E\u6BB5\u7528 replace)`);
153034
+ continue;
153035
+ }
153036
+ const order = typeof it.order === "number" && Number.isFinite(it.order) ? it.order : 999;
153037
+ insert.push({ name, order, text });
153038
+ }
153039
+ }
153040
+ const overrides = {};
153041
+ if (Object.keys(replace2).length) overrides.replace = replace2;
153042
+ if (disable.length) overrides.disable = disable;
153043
+ if (insert.length) overrides.insert = insert;
153044
+ return { overrides: Object.keys(overrides).length ? overrides : null, warnings };
153045
+ }
153046
+ function assertSafeHarnessName(name) {
153047
+ if (!name || name === "." || name === ".." || name.includes("/") || name.includes("\\") || path7.basename(name) !== name) {
153048
+ throw new Error(`\u975E\u6CD5 harness \u540D\u79F0:${JSON.stringify(name)}`);
153049
+ }
153050
+ }
153051
+ function assertInsideDir(dir, target, what) {
153052
+ const rel = path7.relative(dir, target);
153053
+ if (rel === ".." || rel.startsWith(`..${path7.sep}`) || path7.isAbsolute(rel)) {
153054
+ throw new Error(`${what}\u5FC5\u987B\u4F4D\u4E8E harness \u76EE\u5F55\u5185:${target}`);
153055
+ }
153056
+ }
153057
+ function loadHarnessDoc(name) {
153058
+ assertSafeHarnessName(name);
153059
+ const dir = path7.join(libraryDir(), name);
153060
+ const yamlPath = path7.join(dir, "harness.yaml");
153061
+ const raw = import_yaml.default.parse(fs7.readFileSync(yamlPath, "utf8"));
153062
+ if (!raw || typeof raw !== "object") throw new Error(`harness.yaml \u4E3A\u7A7A\u6216\u975E\u5BF9\u8C61:${yamlPath}`);
153063
+ const t = raw.tools ?? {};
153064
+ const sk = raw.skills ?? {};
153065
+ const ag = raw.agents ?? {};
153066
+ let rulesText = "";
153067
+ const rulesFile = typeof raw.rules === "string" ? raw.rules : "rules.md";
153068
+ const rulesPath = path7.resolve(dir, rulesFile);
153069
+ assertInsideDir(path7.resolve(dir), rulesPath, "rules \u6587\u4EF6");
153070
+ let rulesReal = null;
153071
+ try {
153072
+ rulesReal = fs7.realpathSync(rulesPath);
153073
+ } catch {
153074
+ }
153075
+ if (rulesReal !== null) {
153076
+ assertInsideDir(fs7.realpathSync(dir), rulesReal, "rules \u6587\u4EF6(symlink \u89E3\u6790\u540E)");
153077
+ rulesText = fs7.readFileSync(rulesReal, "utf8").trim();
153078
+ }
153079
+ let soulPath = null;
153080
+ let soulReal = null;
153081
+ try {
153082
+ soulReal = fs7.realpathSync(path7.resolve(dir, "SOUL.md"));
153083
+ } catch (e) {
153084
+ if (e.code !== "ENOENT") throw e;
153085
+ }
153086
+ if (soulReal !== null) {
153087
+ assertInsideDir(fs7.realpathSync(dir), soulReal, "SOUL \u6587\u4EF6(symlink \u89E3\u6790\u540E)");
153088
+ const soulStat = fs7.statSync(soulReal);
153089
+ if (!soulStat.isFile()) throw new Error(`SOUL.md \u4E0D\u662F\u666E\u901A\u6587\u4EF6:${soulReal}`);
153090
+ if (soulStat.nlink > 1) throw new Error(`SOUL.md \u662F\u591A\u786C\u94FE\u63A5\u6587\u4EF6,\u62D2\u7EDD\u52A0\u8F7D:${soulReal}`);
153091
+ soulPath = soulReal;
153092
+ }
153093
+ const promptGroup = normalizePromptGroup(raw.prompt);
153094
+ const toggleWarnings = [];
153095
+ const parseToggle = (v, key) => {
153096
+ if (v === void 0 || v === null) return null;
153097
+ if (v === "off" || v === false) return "off";
153098
+ if (v === "on" || v === true) return "on";
153099
+ toggleWarnings.push(`${key} \u53EA\u8BA4 on/off,\u5FFD\u7565\u975E\u6CD5\u503C ${JSON.stringify(v)}`);
153100
+ return null;
153101
+ };
153102
+ const memory = parseToggle(raw.memory, "memory");
153103
+ const persona = parseToggle(raw.persona, "persona");
153104
+ const parseModel = (v) => {
153105
+ if (v === void 0 || v === null) return null;
153106
+ if (typeof v === "string") {
153107
+ const id = v.trim();
153108
+ if (id) return { main: id, quick: id };
153109
+ toggleWarnings.push("model \u4E3A\u7A7A\u5B57\u7B26\u4E32,\u5FFD\u7565(\u89C6\u4E3A\u672A\u58F0\u660E,\u8DDF\u968F base)");
153110
+ return null;
153111
+ }
153112
+ if (typeof v === "object" && !Array.isArray(v)) {
153113
+ const o = v;
153114
+ const out = {};
153115
+ for (const slot of MODEL_SLOTS) {
153116
+ const x = o[slot];
153117
+ if (x === void 0 || x === null) continue;
153118
+ if (typeof x === "string" && x.trim()) out[slot] = x.trim();
153119
+ else toggleWarnings.push(`model.${slot} \u987B\u4E3A\u6A21\u578B\u6807\u8BC6\u5B57\u7B26\u4E32(modelName[provider]),\u5FFD\u7565\u975E\u6CD5\u503C ${JSON.stringify(x)}`);
153120
+ }
153121
+ for (const k of Object.keys(o)) if (!MODEL_SLOTS.includes(k)) toggleWarnings.push(`model \u672A\u77E5\u69FD\u4F4D ${k}(\u53EA\u8BA4 main / quick),\u5FFD\u7565`);
153122
+ if (!out.main && !out.quick) {
153123
+ toggleWarnings.push("model \u672A\u58F0\u660E\u4EFB\u4F55\u6709\u6548\u69FD\u4F4D,\u89C6\u4E3A\u672A\u58F0\u660E(\u8DDF\u968F base)");
153124
+ return null;
153125
+ }
153126
+ return out;
153127
+ }
153128
+ toggleWarnings.push(`model \u53EA\u8BA4\u5B57\u7B26\u4E32\u6216 { main, quick },\u5FFD\u7565\u975E\u6CD5\u503C ${JSON.stringify(v)}`);
153129
+ return null;
153130
+ };
153131
+ const model = parseModel(raw.model);
153132
+ const thinkingToggle = parseToggle(raw.thinking, "thinking");
153133
+ const thinking = thinkingToggle === null ? null : thinkingToggle === "on";
153134
+ const parseTemperature = (v) => {
153135
+ if (v === void 0 || v === null) return null;
153136
+ const num = (x, label) => {
153137
+ if ((0, import_atomix_core4.isValidTemperature)(x)) return x;
153138
+ toggleWarnings.push(`${label} \u987B\u4E3A 0\u20132 \u7684\u6570\u5B57,\u5FFD\u7565\u975E\u6CD5\u503C ${JSON.stringify(x)}`);
153139
+ return void 0;
153140
+ };
153141
+ if (typeof v === "number") {
153142
+ const t2 = num(v, "temperature");
153143
+ return t2 === void 0 ? null : { main: t2 };
153144
+ }
153145
+ if (typeof v === "object" && !Array.isArray(v)) {
153146
+ const o = v;
153147
+ const out = {};
153148
+ for (const slot of MODEL_SLOTS) {
153149
+ const x = o[slot];
153150
+ if (x === void 0 || x === null) continue;
153151
+ const t2 = num(x, `temperature.${slot}`);
153152
+ if (t2 !== void 0) out[slot] = t2;
153153
+ }
153154
+ for (const k of Object.keys(o)) if (!MODEL_SLOTS.includes(k)) toggleWarnings.push(`temperature \u672A\u77E5\u69FD\u4F4D ${k}(\u53EA\u8BA4 main / quick),\u5FFD\u7565`);
153155
+ if (out.main === void 0 && out.quick === void 0) {
153156
+ toggleWarnings.push("temperature \u672A\u58F0\u660E\u4EFB\u4F55\u6709\u6548\u69FD\u4F4D,\u89C6\u4E3A\u672A\u58F0\u660E");
153157
+ return null;
153158
+ }
153159
+ return out;
153160
+ }
153161
+ toggleWarnings.push(`temperature \u53EA\u8BA4\u6570\u5B57\u6216 { main, quick },\u5FFD\u7565\u975E\u6CD5\u503C ${JSON.stringify(v)}`);
153162
+ return null;
153163
+ };
153164
+ const temperature = parseTemperature(raw.temperature);
153165
+ return {
153166
+ name: typeof raw.name === "string" && raw.name ? raw.name : name,
153167
+ description: typeof raw.description === "string" ? raw.description : void 0,
153168
+ version: typeof raw.version === "string" ? raw.version : void 0,
153169
+ rulesText,
153170
+ tools: {
153171
+ mode: asMode(t.mode),
153172
+ useTools: Array.isArray(t.useTools) ? asStrArr(t.useTools) : null,
153173
+ disable: asStrArr(t.disable),
153174
+ enable: asStrArr(t.enable),
153175
+ defer: asStrArr(t.defer),
153176
+ pin: asStrArr(t.pin)
153177
+ },
153178
+ skills: { mode: asMode(sk.mode), disable: asStrArr(sk.disable), enable: asStrArr(sk.enable) },
153179
+ agents: { mode: asMode(ag.mode), disable: asStrArr(ag.disable), enable: asStrArr(ag.enable) },
153180
+ prompt: promptGroup.overrides,
153181
+ promptWarnings: promptGroup.warnings,
153182
+ memory,
153183
+ persona,
153184
+ soulPath,
153185
+ model,
153186
+ thinking,
153187
+ temperature,
153188
+ toggleWarnings,
153189
+ dir
153190
+ };
153191
+ }
153192
+ function resolveBase(ctx) {
153193
+ return {
153194
+ name: BASE_HARNESS,
153195
+ useTools: ctx.baseline.useTools,
153196
+ deferBuiltinTools: ctx.baseline.deferBuiltinTools ?? [],
153197
+ pinnedTools: [],
153198
+ customRules: "",
153199
+ promptOverrides: null,
153200
+ memoryFiles: ctx.baseline.memoryFiles,
153201
+ personaFile: ctx.baseline.personaFile,
153202
+ warnings: [],
153203
+ dirName: BASE_HARNESS,
153204
+ modelOverrides: null,
153205
+ modelDeclared: null,
153206
+ modelFallback: null,
153207
+ thinkingDeclared: null,
153208
+ temperatureOverrides: null,
153209
+ temperatureDeclared: null,
153210
+ thinking: ctx.baseline.thinking,
153211
+ skillsSpec: null,
153212
+ agentsSpec: null,
153213
+ skillsDisabled: /* @__PURE__ */ new Set(),
153214
+ agentsDisabled: /* @__PURE__ */ new Set()
153215
+ };
153216
+ }
153217
+ function resolveHarness(doc, ctx) {
153218
+ if (!doc) return resolveBase(ctx);
153219
+ let useTools;
153220
+ if (doc.tools.mode === "whitelist") {
153221
+ useTools = doc.tools.enable.slice();
153222
+ } else {
153223
+ useTools = doc.tools.useTools ?? ctx.baseline.useTools;
153224
+ if (doc.tools.disable.length) {
153225
+ const src = useTools ?? ctx.allToolNames;
153226
+ const drop2 = new Set(doc.tools.disable);
153227
+ useTools = src.filter((n) => !drop2.has(n));
153228
+ }
153229
+ }
153230
+ const warnings = [...doc.promptWarnings, ...doc.toggleWarnings];
153231
+ const resolveToggle = (toggle, base, potential, emptyWarning) => {
153232
+ if (base === void 0) return void 0;
153233
+ if (toggle === "off") return null;
153234
+ if (toggle === "on") {
153235
+ const p = potential === void 0 ? base : potential;
153236
+ if (p === null) {
153237
+ warnings.push(emptyWarning);
153238
+ return null;
153239
+ }
153240
+ return p;
153241
+ }
153242
+ return base;
153243
+ };
153244
+ const memoryFiles = resolveToggle(
153245
+ doc.memory,
153246
+ ctx.baseline.memoryFiles,
153247
+ ctx.baseline.potentialMemoryFiles,
153248
+ "memory: on \u65E0\u8D27\u53EF\u5F00:config.json \u5DF2\u628A global/project \u90FD\u663E\u5F0F\u5173\u6B7B"
153249
+ );
153250
+ let personaFile;
153251
+ if (ctx.baseline.personaFile === void 0) {
153252
+ personaFile = void 0;
153253
+ } else if (doc.persona === "off") {
153254
+ personaFile = null;
153255
+ } else if (doc.soulPath) {
153256
+ personaFile = doc.soulPath;
153257
+ } else {
153258
+ if (doc.persona === "on") warnings.push("persona: on \u65E0\u6548:\u672C harness \u672A\u5E26\u4E13\u5C5E SOUL.md(\u4E25\u683C\u9694\u79BB,\u4E0D\u501F base \u4EBA\u8BBE;\u653E\u4E00\u4EFD SOUL.md \u8FDB harness \u76EE\u5F55\u5373\u751F\u6548)");
153259
+ personaFile = null;
153260
+ }
153261
+ const dirName = path7.basename(doc.dir);
153262
+ const modelOverrides = {};
153263
+ const modelFallback = {};
153264
+ if (doc.model) {
153265
+ for (const slot of MODEL_SLOTS) {
153266
+ const want = doc.model[slot];
153267
+ if (!want) continue;
153268
+ if (ctx.modelNames.includes(want)) modelOverrides[slot] = want;
153269
+ else {
153270
+ modelFallback[slot] = want;
153271
+ warnings.push(`\u6A21\u578B\u56DE\u843D:harness.yaml \u58F0\u660E ${slot}=${want},model.conf \u4E2D\u4E0D\u5B58\u5728,\u5F53\u524D ${slot} \u4F7F\u7528 base \u7684 ${ctx.baseModels[slot] || "-"}(/model add \u6DFB\u52A0\u540E /harness use ${dirName} \u91CD\u65B0\u5E94\u7528)`);
153272
+ }
153273
+ }
153274
+ }
153275
+ const temperatureOverrides = {};
153276
+ if (doc.temperature) {
153277
+ for (const slot of MODEL_SLOTS) {
153278
+ const t = doc.temperature[slot];
153279
+ if (t === void 0) continue;
153280
+ const effModel = modelOverrides[slot] ?? ctx.baseModels[slot];
153281
+ const mn = ctx.modelProfiles?.find((p) => p.name === effModel)?.modelName;
153282
+ if (mn && (0, import_atomix_core4.modelForcesTemperatureOne)(mn)) {
153283
+ warnings.push(`\u6E29\u5EA6\u5FFD\u7565:harness.yaml \u58F0\u660E ${slot} temperature=${t},\u4F46\u6A21\u578B ${effModel} \u53EA\u63A5\u53D7\u9ED8\u8BA4\u6E29\u5EA6 1`);
153284
+ continue;
153285
+ }
153286
+ if (mn && (0, import_atomix_core4.modelRejectsTemperature)(mn)) {
153287
+ warnings.push(`\u6E29\u5EA6\u5FFD\u7565:harness.yaml \u58F0\u660E ${slot} temperature=${t},\u4F46\u6A21\u578B ${effModel} \u4E0D\u652F\u6301 temperature \u53C2\u6570`);
153288
+ continue;
153289
+ }
153290
+ temperatureOverrides[slot] = t;
153291
+ }
153292
+ }
153293
+ return {
153294
+ name: doc.name,
153295
+ dirName,
153296
+ temperatureOverrides: Object.keys(temperatureOverrides).length ? temperatureOverrides : null,
153297
+ temperatureDeclared: doc.temperature,
153298
+ modelOverrides: Object.keys(modelOverrides).length ? modelOverrides : null,
153299
+ modelDeclared: doc.model,
153300
+ modelFallback: Object.keys(modelFallback).length ? modelFallback : null,
153301
+ // thinking:声明即下发;未声明跟随基线(基线未知则不下发该键,与 memoryFiles 同规则)
153302
+ thinkingDeclared: doc.thinking,
153303
+ thinking: doc.thinking ?? ctx.baseline.thinking,
153304
+ useTools,
153305
+ deferBuiltinTools: doc.tools.defer.length ? doc.tools.defer : ctx.baseline.deferBuiltinTools ?? [],
153306
+ pinnedTools: doc.tools.pin,
153307
+ customRules: doc.rulesText,
153308
+ promptOverrides: doc.prompt,
153309
+ memoryFiles,
153310
+ personaFile,
153311
+ warnings,
153312
+ skillsSpec: doc.skills,
153313
+ agentsSpec: doc.agents,
153314
+ skillsDisabled: computeDisabledFrom(doc.skills, ctx.allSkillNames),
153315
+ agentsDisabled: computeDisabledFrom(doc.agents, ctx.allAgentNames)
153316
+ };
153317
+ }
153318
+ function buildContext(core) {
153319
+ const rt = requireRuntime(core);
153320
+ return {
153321
+ baseline: rt.baseline,
153322
+ // 工具:getToolInfos 恒返回内置全集(禁用项带 status),可直读;
153323
+ // skill:core 按 session 读取时过滤,includeDisabled 直接取供给全集;
153324
+ // agent:注册表是已过滤视图,优先用 applyDisabledAgents 回写的全集缓存,
153325
+ // 缓存为空只在启动初始化时(此刻尚未过滤,直读即全集)
153326
+ allToolNames: core.getToolInfos().map((t) => t.name),
153327
+ allSkillNames: rt.fullSkillNames ?? core.getSkillsInfo({ includeDisabled: true }).map((s) => s.name),
153328
+ allAgentNames: rt.fullAgentNames ?? core.getAgentsInfo().map((a) => a.name),
153329
+ modelNames: core.getModelNames(),
153330
+ baseModels: core.getModelPointers(),
153331
+ modelProfiles: core.getModelProfiles()
153332
+ };
153333
+ }
153334
+ function applyAssembly(core, rt, r, opts = {}) {
153335
+ core.updateAssemblyConfig({
153336
+ useTools: r.useTools,
153337
+ deferBuiltinTools: r.deferBuiltinTools,
153338
+ pinnedTools: r.pinnedTools,
153339
+ customRules: r.customRules,
153340
+ promptOverrides: r.promptOverrides,
153341
+ // null = 回默认组装(base 清场)
153342
+ // 基线未知(宿主没给快照)时不下发该键:传 undefined 会被 core 当 null 落,把供给层开着的注入误关
153343
+ ...r.memoryFiles !== void 0 ? { memoryFiles: r.memoryFiles } : {},
153344
+ ...r.personaFile !== void 0 ? { personaFile: r.personaFile } : {},
153345
+ modelOverrides: r.modelOverrides,
153346
+ // null = 回 model.conf 指针(base 清场)
153347
+ temperatureOverrides: r.temperatureOverrides,
153348
+ // null = 回 profile / 协议默认(base 清场)
153349
+ ...!opts.preserveThinking && r.thinking !== void 0 ? { thinking: r.thinking } : {}
153350
+ // 声明 ?? 基线;只在 use/reset/启动 下发,不做热切换
153351
+ });
153352
+ rt.activeMemoryFiles = r.memoryFiles;
153353
+ rt.activePersonaFile = r.personaFile;
153354
+ if (!opts.preserveThinking) rt.activeThinking = r.thinking;
153355
+ rt.active = r.dirName === BASE_HARNESS ? null : r;
153356
+ }
153357
+ function initHarness(core, cwd2, base, opts = {}) {
153358
+ const rt = {
153359
+ baseline: {
153360
+ useTools: base.useTools ? [...base.useTools] : null,
153361
+ deferBuiltinTools: base.deferBuiltinTools?.slice(),
153362
+ memoryFiles: base.memoryFiles,
153363
+ personaFile: base.personaFile,
153364
+ potentialMemoryFiles: base.potentialMemoryFiles,
153365
+ thinking: base.thinking
153366
+ },
153367
+ activeMemoryFiles: base.memoryFiles,
153368
+ activePersonaFile: base.personaFile,
153369
+ activeThinking: base.thinking,
153370
+ projectDir: cwd2,
153371
+ active: null,
153372
+ overridden: opts.harness !== void 0,
153373
+ fullSkillNames: null,
153374
+ fullAgentNames: null
153375
+ };
153376
+ runtimes.set(core, rt);
153377
+ const name = opts.harness ?? readState(cwd2);
153378
+ const source = rt.overridden ? "\u4F1A\u8BDD\u7EA7\u6307\u5B9A" : "\u6765\u81EA .atomix/harness-state.json";
153379
+ if (name === BASE_HARNESS) return null;
153380
+ try {
153381
+ const doc = loadHarnessDoc(name);
153382
+ const r = resolveHarness(doc, buildContext(core));
153383
+ applyAssembly(core, rt, r);
153384
+ return r.warnings.length ? `harness "${r.name}"(${source})\u5DF2\u52A0\u8F7D:
153385
+ \u26A0 ${r.warnings.join("\n \u26A0 ")}` : null;
153386
+ } catch (e) {
153387
+ if (rt.overridden) throw new Error(`harness "${name}" \u52A0\u8F7D\u5931\u8D25:${e instanceof Error ? e.message : e}`);
153388
+ return `harness "${name}"(${source})\u52A0\u8F7D\u5931\u8D25,\u5DF2\u56DE\u843D base:${e instanceof Error ? e.message : e}`;
153389
+ }
153390
+ }
153391
+ async function switchTo(core, name) {
153392
+ const rt = requireRuntime(core);
153393
+ const ctx = buildContext(core);
153394
+ const r = name === BASE_HARNESS ? resolveBase(ctx) : resolveHarness(loadHarnessDoc(name), ctx);
153395
+ const wasOn = (v) => v !== null && v !== void 0;
153396
+ const memWasOn = wasOn(rt.activeMemoryFiles);
153397
+ const personaWas = rt.activePersonaFile;
153398
+ applyAssembly(core, rt, r);
153399
+ const memNowOn = wasOn(rt.activeMemoryFiles);
153400
+ const personaNow = rt.activePersonaFile;
153401
+ writeState(rt.projectDir, name);
153402
+ rt.overridden = false;
153403
+ const { applyDisabledSkills: applyDisabledSkills2 } = await Promise.resolve().then(() => (init_skills(), skills_exports));
153404
+ const { applyDisabledAgents: applyDisabledAgents2 } = await Promise.resolve().then(() => (init_agents(), agents_exports));
153405
+ applyDisabledSkills2(core);
153406
+ await applyDisabledAgents2(core);
153407
+ const warn = r.warnings.length ? "\n \u26A0 " + r.warnings.join("\n \u26A0 ") : "";
153408
+ const hints = [];
153409
+ if (memWasOn !== memNowOn) hints.push(memNowOn ? "\u8BB0\u5FC6\u6CE8\u5165\u5DF2\u5F00;\u9700 /compact\u3001/clear \u6216\u65B0\u4F1A\u8BDD\u540E\u91CD\u65B0\u6CE8\u5165" : "\u8BB0\u5FC6\u6CE8\u5165\u5DF2\u5173;\u5386\u53F2\u91CC\u5DF2\u6CE8\u5165\u7684\u8BB0\u5FC6\u9700 /compact \u6216 /clear \u624D\u64A4\u51FA");
153410
+ const pWasOn = wasOn(personaWas);
153411
+ const pNowOn = wasOn(personaNow);
153412
+ if (pWasOn !== pNowOn) hints.push(pNowOn ? "\u4EBA\u8BBE\u6CE8\u5165\u5DF2\u5F00;\u9700 /compact\u3001/clear \u6216\u65B0\u4F1A\u8BDD\u540E\u91CD\u65B0\u6CE8\u5165" : "\u4EBA\u8BBE\u6CE8\u5165\u5DF2\u5173;\u5386\u53F2\u91CC\u5DF2\u6CE8\u5165\u7684\u4EBA\u8BBE\u9700 /compact \u6216 /clear \u624D\u64A4\u51FA");
153413
+ else if (pWasOn && pNowOn && personaWas !== personaNow) hints.push("\u4EBA\u8BBE\u6765\u6E90\u5DF2\u5207\u6362;\u5386\u53F2\u91CC\u5DF2\u6CE8\u5165\u7684\u4EBA\u8BBE\u9700 /compact \u6216 /clear \u624D\u66F4\u65B0");
153414
+ const hintText = hints.map((h) => `
153415
+ ${h}`).join("");
153416
+ return (name === BASE_HARNESS ? "\u5DF2\u56DE\u5230 base(\u9ED8\u8BA4\u88C5\u914D)" : `\u5DF2\u5207\u6362 harness:${r.name}(\u4EC5\u5F53\u524D\u9879\u76EE\u751F\u6548)`) + hintText + warn;
153417
+ }
153418
+ function reapply(core, rt) {
153419
+ const r = resolveHarness(loadHarnessDoc(rt.active.dirName), buildContext(core));
153420
+ applyAssembly(core, rt, r, { preserveThinking: true });
153421
+ return r;
153422
+ }
153423
+ function setActiveHarnessModel(core, slot, name) {
153424
+ const rt = requireRuntime(core);
153425
+ if (!rt.active) throw new Error("\u5F53\u524D\u4E3A base,\u6A21\u578B\u6307\u9488\u76F4\u63A5\u7531 model.conf \u7BA1\u7406");
153426
+ if (!core.getModelNames().includes(name)) throw new Error(`\u6A21\u578B\u4E0D\u5B58\u5728: ${name}(/model list \u67E5\u770B,/model add \u6DFB\u52A0)`);
153427
+ const dirName = rt.active.dirName;
153428
+ const declared = { ...rt.active.modelDeclared ?? {} };
153429
+ declared[slot] = name;
153430
+ const value = declared.main && declared.quick && declared.main === declared.quick ? declared.main : declared;
153431
+ const yamlPath = path7.join(libraryDir(), dirName, "harness.yaml");
153432
+ const ydoc = import_yaml.default.parseDocument(fs7.readFileSync(yamlPath, "utf8"));
153433
+ ydoc.set("model", typeof value === "string" ? value : ydoc.createNode(value));
153434
+ fs7.writeFileSync(yamlPath, ydoc.toString());
153435
+ const r = reapply(core, rt);
153436
+ const warn = r.warnings.length ? "\n \u26A0 " + r.warnings.join("\n \u26A0 ") : "";
153437
+ return `harness ${dirName} \u7684 ${slot} \u2192 ${name}(\u5DF2\u5199\u5165 harness.yaml,base \u672A\u53D8)` + warn;
153438
+ }
153439
+ function setActiveHarnessTemperature(core, slot, value) {
153440
+ const rt = requireRuntime(core);
153441
+ if (!rt.active) throw new Error("\u5F53\u524D\u4E3A base,\u6E29\u5EA6\u76F4\u63A5\u7531 model.conf \u7684 profile \u7BA1\u7406(/model temp <\u6A21\u578B\u540D> <\u503C|default>)");
153442
+ if (value !== null) {
153443
+ if (!(0, import_atomix_core4.isValidTemperature)(value)) throw new Error(`temperature \u987B\u4E3A 0\u20132 \u7684\u6570\u5B57,\u6536\u5230 ${JSON.stringify(value)}`);
153444
+ const effModel = effectiveModels(core)[slot];
153445
+ const mn = core.getModelProfiles().find((p) => p.name === effModel)?.modelName;
153446
+ if (mn && (0, import_atomix_core4.modelForcesTemperatureOne)(mn)) throw new Error(`\u6A21\u578B ${effModel} \u53EA\u63A5\u53D7\u9ED8\u8BA4\u6E29\u5EA6 1,\u4E0D\u80FD\u8BBE\u7F6E temperature`);
153447
+ if (mn && (0, import_atomix_core4.modelRejectsTemperature)(mn)) throw new Error(`\u6A21\u578B ${effModel} \u4E0D\u652F\u6301 temperature \u53C2\u6570(\u63A8\u7406\u6A21\u578B),\u4E0D\u80FD\u8BBE\u7F6E`);
153448
+ }
153449
+ const dirName = rt.active.dirName;
153450
+ const declared = { ...rt.active.temperatureDeclared ?? {} };
153451
+ if (value === null) delete declared[slot];
153452
+ else declared[slot] = value;
153453
+ const yamlPath = path7.join(libraryDir(), dirName, "harness.yaml");
153454
+ const ydoc = import_yaml.default.parseDocument(fs7.readFileSync(yamlPath, "utf8"));
153455
+ if (declared.main === void 0 && declared.quick === void 0) ydoc.delete("temperature");
153456
+ else if (declared.quick === void 0) ydoc.set("temperature", declared.main);
153457
+ else ydoc.set("temperature", ydoc.createNode(declared));
153458
+ fs7.writeFileSync(yamlPath, ydoc.toString());
153459
+ const r = reapply(core, rt);
153460
+ const warn = r.warnings.length ? "\n \u26A0 " + r.warnings.join("\n \u26A0 ") : "";
153461
+ return `harness ${dirName} \u7684 ${slot} temperature \u2192 ${value === null ? "\u9ED8\u8BA4(\u5DF2\u6E05\u9664\u58F0\u660E)" : value}(\u5DF2\u5199\u5165 harness.yaml,model.conf \u672A\u53D8)` + warn;
153462
+ }
153463
+ function harnessesReferencingModel(name) {
153464
+ const out = [];
153465
+ for (const n of listHarnesses()) {
153466
+ if (n === BASE_HARNESS) continue;
153467
+ try {
153468
+ const m = loadHarnessDoc(n).model;
153469
+ if (m && (m.main === name || m.quick === name)) out.push(n);
153470
+ } catch {
153471
+ }
153472
+ }
153473
+ return out;
153474
+ }
153475
+ function summarize(r, ctx) {
153476
+ const lines = [];
153477
+ const base = resolveBase(ctx);
153478
+ const baseSet2 = new Set(base.useTools ?? ctx.allToolNames);
153479
+ const curSet = new Set(r.useTools ?? ctx.allToolNames);
153480
+ const removed = [...baseSet2].filter((n) => !curSet.has(n));
153481
+ const added = [...curSet].filter((n) => !baseSet2.has(n));
153482
+ lines.push(`\u5DE5\u5177 ${r.useTools ? `${curSet.size} \u4E2A` : "\u5168\u90E8"}${removed.length ? `(\u76F8\u5BF9 base \u5C11:${removed.join(", ")})` : ""}${added.length ? `(\u76F8\u5BF9 base \u591A:${added.join(", ")})` : ""}`);
153483
+ if (r.deferBuiltinTools.length) lines.push(`defer ${r.deferBuiltinTools.join(", ")}`);
153484
+ if (r.pinnedTools.length) lines.push(`pin ${r.pinnedTools.join(", ")}`);
153485
+ const skillsDisabled = computeDisabledFrom(r.skillsSpec, ctx.allSkillNames);
153486
+ const agentsDisabled = computeDisabledFrom(r.agentsSpec, ctx.allAgentNames);
153487
+ lines.push(`skill ${skillsDisabled.size ? `\u7981\u7528 ${[...skillsDisabled].join(", ")}` : "\u5168\u90E8\u53EF\u89C1"}`);
153488
+ lines.push(`agent ${agentsDisabled.size ? `\u7981\u7528 ${[...agentsDisabled].join(", ")}` : "\u5168\u90E8\u53EF\u89C1"}`);
153489
+ lines.push(`\u89C4\u5219\u6BB5 ${r.customRules ? `${r.customRules.split("\n").length} \u884C` : "\u65E0"}`);
153490
+ const p = r.promptOverrides;
153491
+ const promptDesc = p ? [
153492
+ p.replace && Object.keys(p.replace).length ? `\u66FF\u6362 ${Object.keys(p.replace).join(", ")}` : "",
153493
+ p.disable?.length ? `\u7981\u7528 ${p.disable.join(", ")}` : "",
153494
+ p.insert?.length ? `\u63D2\u5165 ${p.insert.map((i) => i.name).join(", ")}` : ""
153495
+ ].filter(Boolean).join(";") : "\u9ED8\u8BA4";
153496
+ lines.push(`\u63D0\u793A\u6BB5 ${promptDesc}`);
153497
+ const mo = overrideOf(r.memoryFiles, ctx.baseline.memoryFiles);
153498
+ if (mo === "off") lines.push("\u8BB0\u5FC6 \u5173(harness memory: off;base \u5F00\u7740,\u5207\u8D70\u5373\u6062\u590D)");
153499
+ else if (mo === "on") lines.push("\u8BB0\u5FC6 \u5F00(harness memory: on;base \u5173\u7740,\u5207\u8D70\u5373\u5173)");
153500
+ const po = personaOverrideOf(r.personaFile, ctx.baseline.personaFile);
153501
+ if (po === "off") lines.push("\u4EBA\u8BBE \u5173(\u672C harness \u65E0\u4EBA\u8BBE;base \u5F00\u7740,\u5207\u8D70\u5373\u6062\u590D)");
153502
+ else if (po === "swap") lines.push("\u4EBA\u8BBE \u4E13\u5C5E(harness SOUL.md;\u5207\u8D70\u5373\u56DE base)");
153503
+ else if (po === "on") lines.push("\u4EBA\u8BBE \u4E13\u5C5E(harness SOUL.md;base \u5173\u7740,\u5207\u8D70\u5373\u5173)");
153504
+ if (r.modelDeclared) {
153505
+ const parts = MODEL_SLOTS.map((slot) => {
153506
+ const d = r.modelDeclared[slot];
153507
+ if (!d) return `${slot}=${ctx.baseModels[slot] || "-"}(base)`;
153508
+ return r.modelFallback?.[slot] ? `${slot}=${ctx.baseModels[slot] || "-"}(base;\u58F0\u660E ${d} \u4E0D\u5B58\u5728,\u5DF2\u56DE\u843D)` : `${slot}=${d}`;
153509
+ });
153510
+ lines.push(`${r.modelFallback ? "\u26A0 " : ""}\u6A21\u578B ${parts.join(" ")}`);
153511
+ }
153512
+ if (r.thinkingDeclared !== null) lines.push(`\u601D\u8003 ${r.thinkingDeclared ? "\u5F00" : "\u5173"}(harness thinking: ${r.thinkingDeclared ? "on" : "off"};\u4EC5 main,quick \u6052\u5173;\u5207\u8D70\u5373\u56DE base)`);
153513
+ if (r.temperatureDeclared) {
153514
+ const parts = MODEL_SLOTS.map((slot) => {
153515
+ const d = r.temperatureDeclared[slot];
153516
+ if (d === void 0) return `${slot}=\u8DDF\u968F(profile / \u534F\u8BAE\u9ED8\u8BA4)`;
153517
+ return r.temperatureOverrides?.[slot] === void 0 ? `${slot}=${d}(\u5DF2\u5FFD\u7565,\u89C1\u544A\u8B66)` : `${slot}=${d}`;
153518
+ });
153519
+ lines.push(`\u6E29\u5EA6 ${parts.join(" ")}(harness \u58F0\u660E;\u5207\u8D70\u5373\u56DE profile / \u9ED8\u8BA4)`);
153520
+ }
153521
+ if (r.warnings.length) lines.push(...r.warnings.map((w) => `\u26A0 ${w}`));
153522
+ return lines.join("\n ");
153523
+ }
153524
+ async function harnessCommand(core, args) {
153525
+ const [sub, ...rest2] = args;
153526
+ const arg = rest2.join(" ").trim() || void 0;
153527
+ const names = listHarnesses();
153528
+ switch (sub) {
153529
+ case void 0:
153530
+ case "list": {
153531
+ const cur = getActiveHarnessDir(core);
153532
+ const rt = runtimeOf(core);
153533
+ const lines = names.map((n) => `${n === cur ? "\u25CF" : "\u25CB"} ${n}${n === BASE_HARNESS ? "(\u9ED8\u8BA4\u88C5\u914D)" : ""}`);
153534
+ if (sub === void 0 && rt?.active) {
153535
+ const ctx = buildContext(core);
153536
+ const where = rt.overridden ? "\u4F1A\u8BDD\u7EA7\u6307\u5B9A,\u672A\u5199\u5165\u9879\u76EE\u6001" : `\u9879\u76EE\u7EA7,${path7.join(".atomix", "harness-state.json")}`;
153537
+ lines.unshift(`\u5F53\u524D:${cur}(${where})`, " " + summarize(rt.active, ctx), "");
153538
+ } else if (sub === void 0) {
153539
+ lines.unshift(rt?.overridden ? "\u5F53\u524D:base(\u4F1A\u8BDD\u7EA7\u6307\u5B9A\u9ED8\u8BA4\u88C5\u914D)" : "\u5F53\u524D:base(\u9ED8\u8BA4\u88C5\u914D,\u672A\u9009\u62E9 harness)", "");
153540
+ }
153541
+ lines.push("", "\u7528\u6CD5:/harness list | use <\u540D\u79F0> | show <\u540D\u79F0> | diff <\u540D\u79F0> | reset");
153542
+ lines.push(`\u5E93\u76EE\u5F55:${libraryDir()}(\u6BCF\u4E2A harness \u4E00\u4E2A\u5B50\u76EE\u5F55,\u542B harness.yaml + rules.md)`);
153543
+ return lines.join("\n");
153544
+ }
153545
+ case "use": {
153546
+ if (!arg) return "\u7528\u6CD5:/harness use <\u540D\u79F0>";
153547
+ if (!names.includes(arg)) return `\u672A\u627E\u5230 harness:${arg}(\u53EF\u7528:${names.join(" / ")})`;
153548
+ try {
153549
+ return await switchTo(core, arg);
153550
+ } catch (e) {
153551
+ return `\u5207\u6362\u5931\u8D25:${e instanceof Error ? e.message : e}`;
153552
+ }
153553
+ }
153554
+ case "reset":
153555
+ return await switchTo(core, BASE_HARNESS);
153556
+ case "show":
153557
+ case "diff": {
153558
+ if (!arg) return `\u7528\u6CD5:/harness ${sub} <\u540D\u79F0>`;
153559
+ if (arg === BASE_HARNESS) return "base = \u9ED8\u8BA4\u88C5\u914D\u57FA\u7EBF,\u65E0\u53D6\u820D\u9879";
153560
+ try {
153561
+ const ctx = buildContext(core);
153562
+ const r = resolveHarness(loadHarnessDoc(arg), ctx);
153563
+ return `${r.name}${arg === getActiveHarnessDir(core) ? "(\u5F53\u524D)" : ""}
153564
+ ${summarize(r, ctx)}`;
153565
+ } catch (e) {
153566
+ return `\u8BFB\u53D6\u5931\u8D25:${e instanceof Error ? e.message : e}`;
153567
+ }
153568
+ }
153569
+ default:
153570
+ return `\u672A\u77E5\u5B50\u547D\u4EE4:${sub}(\u53EF\u7528:list / use / show / diff / reset)`;
153571
+ }
153572
+ }
153573
+ var import_yaml, import_atomix_core3, import_atomix_core4, MODEL_SLOTS, BASE_HARNESS, runtimes;
153574
+ var init_harness = __esm({
153575
+ "src/harness.ts"() {
153576
+ "use strict";
153577
+ import_yaml = __toESM(require_dist5());
153578
+ import_atomix_core3 = __toESM(require_dist4());
153579
+ import_atomix_core4 = __toESM(require_dist4());
153580
+ init_paths();
153581
+ MODEL_SLOTS = ["main", "quick"];
153582
+ BASE_HARNESS = "base";
153583
+ runtimes = /* @__PURE__ */ new WeakMap();
153584
+ }
153585
+ });
153586
+
153070
153587
  // node_modules/react/cjs/react-jsx-runtime.production.min.js
153071
153588
  var require_react_jsx_runtime_production_min = __commonJS({
153072
153589
  "node_modules/react/cjs/react-jsx-runtime.production.min.js"(exports2) {
@@ -159656,6 +160173,9 @@ function filterSemaDebugConsole() {
159656
160173
  };
159657
160174
  }
159658
160175
 
160176
+ // src/modelWizard.ts
160177
+ var import_atomix_core5 = __toESM(require_dist4());
160178
+
159659
160179
  // src/ui.ts
159660
160180
  init_theme();
159661
160181
  var wrap3 = (code) => (s) => `\x1B[${code}m${s}\x1B[0m`;
@@ -159832,6 +160352,7 @@ function makeCancellableAsk(rl) {
159832
160352
  }
159833
160353
 
159834
160354
  // src/modelWizard.ts
160355
+ init_harness();
159835
160356
  function modelId(modelName, provider) {
159836
160357
  return `${modelName}[${provider}]`;
159837
160358
  }
@@ -159853,6 +160374,15 @@ async function askPositiveInt(ask, label, def) {
159853
160374
  console.log(red(" \u8BF7\u8F93\u5165\u6B63\u6574\u6570\uFF0C\u6216\u56DE\u8F66\u7528\u9ED8\u8BA4"));
159854
160375
  }
159855
160376
  }
160377
+ async function askOptionalTemperature(ask, defHint) {
160378
+ for (; ; ) {
160379
+ const raw = (await ask(` temperature [${gray("0\u20132,\u56DE\u8F66\u7528" + defHint)}${gray("]")}: `)).trim();
160380
+ if (!raw) return void 0;
160381
+ const n = Number(raw);
160382
+ if ((0, import_atomix_core5.isValidTemperature)(n)) return n;
160383
+ console.log(red(" \u8BF7\u8F93\u5165 0\u20132 \u7684\u6570\u5B57\uFF0C\u6216\u56DE\u8F66\u7528\u9ED8\u8BA4"));
160384
+ }
160385
+ }
159856
160386
  async function askSelect(ask, label, items, defaultIdx = 0) {
159857
160387
  items.forEach((it, i) => console.log(` ${cyan(String(i + 1))}. ${it}`));
159858
160388
  for (; ; ) {
@@ -159941,9 +160471,16 @@ async function runAddWizard(core, ask) {
159941
160471
  if (limits) console.log(gray(` \u5DF2\u6309\u6A21\u578B\u81EA\u52A8\u8BC6\u522B\u9650\u989D\uFF1AmaxTokens=${defMax} contextLength=${defCtx}`));
159942
160472
  const maxTokens = await askPositiveInt(ask, "maxTokens", defMax);
159943
160473
  const contextLength = await askPositiveInt(ask, "contextLength", defCtx);
160474
+ let temperature;
160475
+ if ((0, import_atomix_core5.modelForcesTemperatureOne)(modelName)) console.log(gray(" \u8BE5\u6A21\u578B\u53EA\u63A5\u53D7\u9ED8\u8BA4\u6E29\u5EA6 1\uFF0C\u8DF3\u8FC7 temperature"));
160476
+ else if ((0, import_atomix_core5.modelRejectsTemperature)(modelName)) console.log(gray(" \u8BE5\u6A21\u578B\u4E0D\u652F\u6301 temperature \u53C2\u6570\uFF0C\u8DF3\u8FC7"));
160477
+ else {
160478
+ if ((0, import_atomix_core5.modelTemperatureGatedByThinking)(modelName)) console.log(gray(" \u8BE5\u6A21\u578B\u4EC5 thinking \u5173\u95ED\u65F6\u4F7F\u7528 temperature\uFF0C\u5F00\u542F\u65F6\u4E0D\u53D1\u9001"));
160479
+ temperature = await askOptionalTemperature(ask, adapt === "anthropic" ? `\u9ED8\u8BA4 ${import_atomix_core5.DEFAULT_ANTHROPIC_TEMPERATURE}` : "\u670D\u52A1\u7AEF\u9ED8\u8BA4");
160480
+ }
159944
160481
  console.log(gray(" \u9A8C\u8BC1\u8FDE\u901A\u6027\u5E76\u4FDD\u5B58\u2026"));
159945
160482
  try {
159946
- await core.addModel({ provider, modelName, baseURL, apiKey, maxTokens, contextLength, adapt });
160483
+ await core.addModel({ provider, modelName, baseURL, apiKey, maxTokens, contextLength, adapt, ...temperature !== void 0 ? { temperature } : {} });
159947
160484
  } catch (e) {
159948
160485
  console.log(red(` \u6DFB\u52A0\u5931\u8D25\uFF1A${e instanceof Error ? e.message : String(e)}`));
159949
160486
  return false;
@@ -159970,13 +160507,33 @@ async function printModelList(core) {
159970
160507
  console.log(gray(" \uFF08\u65E0\u5DF2\u914D\u7F6E\u6A21\u578B\uFF0C`/model add` \u6DFB\u52A0\uFF09"));
159971
160508
  return;
159972
160509
  }
160510
+ const eff = effectiveModels(core);
160511
+ const profiles = new Map(core.getModelProfiles().map((p) => [p.name, p]));
160512
+ const tempOf = (name) => {
160513
+ const p = profiles.get(name);
160514
+ if (!p) return "";
160515
+ if ((0, import_atomix_core5.modelForcesTemperatureOne)(p.modelName)) return "temp=\u56FA\u5B9A1";
160516
+ if ((0, import_atomix_core5.modelRejectsTemperature)(p.modelName)) return "temp=\u4E0D\u652F\u6301";
160517
+ return p.temperature !== void 0 ? `temp=${p.temperature}` : "temp=\u9ED8\u8BA4";
160518
+ };
159973
160519
  for (const name of data.modelList) {
159974
- const marks = [
159975
- name === data.taskConfig?.main ? green("main") : "",
159976
- name === data.taskConfig?.quick ? cyan("quick") : ""
159977
- ].filter(Boolean).join(" ");
159978
- console.log(` ${marks ? "\u25CF " : " "}${name}${marks ? gray(" \u2190 ") + marks : ""}`);
160520
+ const marks = [];
160521
+ if (name === eff.main) marks.push(green(eff.mainFrom === "harness" ? "main(harness)" : "main"));
160522
+ else if (name === data.taskConfig?.main && eff.mainFrom === "harness") marks.push(gray("main(base)"));
160523
+ if (name === eff.quick) marks.push(cyan(eff.quickFrom === "harness" ? "quick(harness)" : "quick"));
160524
+ else if (name === data.taskConfig?.quick && eff.quickFrom === "harness") marks.push(gray("quick(base)"));
160525
+ const m = marks.join(" ");
160526
+ console.log(` ${m ? "\u25CF " : " "}${name}${gray(" " + tempOf(name))}${m ? gray(" \u2190 ") + m : ""}`);
159979
160527
  }
160528
+ console.log(gray(` temperature: ${temperatureStatusLine(core)}`));
160529
+ if (eff.fallback) {
160530
+ for (const slot of ["main", "quick"]) {
160531
+ if (eff.fallback[slot]) console.log(yellow(` \u26A0 harness \u58F0\u660E ${slot}=${eff.fallback[slot]} \u4E0D\u5B58\u5728,${slot} \u5DF2\u56DE\u843D base \u7684 ${eff[slot] || "-"}`));
160532
+ }
160533
+ }
160534
+ }
160535
+ function inHarness(core) {
160536
+ return isHarnessActive(core);
159980
160537
  }
159981
160538
  async function modelCommand(core, args, ask) {
159982
160539
  const [sub, ...rest2] = args;
@@ -159986,33 +160543,83 @@ async function modelCommand(core, args, ask) {
159986
160543
  case void 0:
159987
160544
  case "list":
159988
160545
  await printModelList(core);
159989
- if (!sub) console.log(gray(" \u7528\u6CD5\uFF1A/model list | add | use <\u540D\u79F0> | quick <\u540D\u79F0> | del <\u540D\u79F0>"));
160546
+ if (!sub) console.log(gray(" \u7528\u6CD5\uFF1A/model list | add | use <\u540D\u79F0> | quick <\u540D\u79F0> | temp [<\u540D\u79F0>] <\u503C|default> | del <\u540D\u79F0>"));
159990
160547
  break;
159991
160548
  case "add":
159992
160549
  await addModelWizard(core, ask);
159993
160550
  break;
159994
160551
  case "use": {
159995
160552
  if (!name) return console.log(red(" \u7528\u6CD5\uFF1A/model use <\u540D\u79F0>"));
160553
+ if (inHarness(core)) {
160554
+ console.log(green(` \u2713 ${setActiveHarnessModel(core, "main", name)}`));
160555
+ break;
160556
+ }
159996
160557
  const r = await core.switchModel(name);
159997
160558
  console.log(green(` \u2713 \u4E3B\u6A21\u578B \u2192 ${r.taskConfig.main}`));
159998
160559
  break;
159999
160560
  }
160000
160561
  case "quick": {
160001
160562
  if (!name) return console.log(red(" \u7528\u6CD5\uFF1A/model quick <\u540D\u79F0>"));
160563
+ if (inHarness(core)) {
160564
+ console.log(green(` \u2713 ${setActiveHarnessModel(core, "quick", name)}`));
160565
+ break;
160566
+ }
160002
160567
  const cur = await core.getModelData();
160003
160568
  const r = await core.applyTaskModel({ main: cur.taskConfig.main, quick: name });
160004
160569
  console.log(green(` \u2713 \u5FEB\u901F\u6A21\u578B \u2192 ${r.taskConfig.quick}`));
160005
160570
  break;
160006
160571
  }
160572
+ case "temp": {
160573
+ if (!rest2.length) {
160574
+ console.log(gray(` temperature: ${temperatureStatusLine(core)}`));
160575
+ console.log(gray(" \u7528\u6CD5\uFF1A/model temp <\u503C|default> | temp <\u6A21\u578B\u540D> <\u503C|default>"));
160576
+ break;
160577
+ }
160578
+ const parseVal = (s) => {
160579
+ if (s === "default") return null;
160580
+ const n = Number(s);
160581
+ if (!s || !(0, import_atomix_core5.isValidTemperature)(n)) throw new Error(`temperature \u987B\u4E3A 0\u20132 \u7684\u6570\u5B57\u6216 default\uFF0C\u6536\u5230 ${JSON.stringify(s)}`);
160582
+ return n;
160583
+ };
160584
+ const fmt = (v2) => v2 === null ? "\u9ED8\u8BA4" : String(v2);
160585
+ if (rest2.length >= 2) {
160586
+ const target = rest2.slice(0, -1).join(" ");
160587
+ const v2 = parseVal(rest2[rest2.length - 1]);
160588
+ await core.updateModel(target, { temperature: v2 ?? void 0 });
160589
+ console.log(green(` \u2713 ${target} \u7684 temperature \u2192 ${fmt(v2)}\uFF08model.conf\uFF09`));
160590
+ const eff = effectiveModels(core);
160591
+ const over2 = harnessTemperatureOverride(core);
160592
+ for (const slot of ["main", "quick"]) {
160593
+ if (eff[slot] === target && over2?.[slot] !== void 0) console.log(yellow(` \u26A0 \u5F53\u524D harness ${getActiveHarnessDir(core)} \u5BF9 ${slot} \u58F0\u660E\u4E86 temperature=${over2[slot]}\uFF0C\u4F18\u5148\u4E8E profile\uFF1B\u6539 harness \u7528 /model temp <\u503C>`));
160594
+ }
160595
+ break;
160596
+ }
160597
+ const v = parseVal(rest2[0]);
160598
+ if (inHarness(core)) {
160599
+ console.log(green(` \u2713 ${setActiveHarnessTemperature(core, "main", v)}`));
160600
+ break;
160601
+ }
160602
+ const main = effectiveModels(core).main;
160603
+ if (!main) return console.log(red(" \u5C1A\u672A\u914D\u7F6E\u4E3B\u6A21\u578B\uFF08/model add\uFF09"));
160604
+ await core.updateModel(main, { temperature: v ?? void 0 });
160605
+ console.log(green(` \u2713 ${main} \u7684 temperature \u2192 ${fmt(v)}\uFF08model.conf\uFF09`));
160606
+ break;
160607
+ }
160007
160608
  case "del": {
160008
160609
  if (!name) return console.log(red(" \u7528\u6CD5\uFF1A/model del <\u540D\u79F0>"));
160610
+ const decl = harnessModelDeclared(core);
160611
+ if (decl && (decl.main === name || decl.quick === name)) {
160612
+ return console.log(red(` \u6A21\u578B\u6B63\u5728\u88AB\u5F53\u524D harness ${getActiveHarnessDir(core)} \u58F0\u660E\u4F7F\u7528,\u65E0\u6CD5\u5220\u9664(\u5148\u6539\u5176 harness.yaml \u7684 model \u5B57\u6BB5)`));
160613
+ }
160009
160614
  await core.delModel(name);
160010
160615
  console.log(green(` \u2713 \u5DF2\u5220\u9664\uFF1A${name}`));
160616
+ const refs = harnessesReferencingModel(name);
160617
+ if (refs.length) console.log(yellow(` \u26A0 \u4EE5\u4E0B harness \u4ECD\u58F0\u660E\u8BE5\u6A21\u578B,\u4E0B\u6B21\u52A0\u8F7D\u4F1A\u56DE\u843D base:${refs.join(" / ")}(\u8BF7\u6539\u5176 harness.yaml \u7684 model \u5B57\u6BB5)`));
160011
160618
  break;
160012
160619
  }
160013
160620
  default:
160014
160621
  console.log(bold(` \u672A\u77E5\u5B50\u547D\u4EE4\uFF1A${sub}`));
160015
- console.log(gray(" \u7528\u6CD5\uFF1A/model list | add | use <\u540D\u79F0> | quick <\u540D\u79F0> | del <\u540D\u79F0>"));
160622
+ console.log(gray(" \u7528\u6CD5\uFF1A/model list | add | use <\u540D\u79F0> | quick <\u540D\u79F0> | temp [<\u540D\u79F0>] <\u503C|default> | del <\u540D\u79F0>"));
160016
160623
  }
160017
160624
  } catch (e) {
160018
160625
  console.log(red(` \u6A21\u578B\u64CD\u4F5C\u5931\u8D25\uFF1A${e instanceof Error ? e.message : String(e)}`));
@@ -160020,7 +160627,7 @@ async function modelCommand(core, args, ask) {
160020
160627
  }
160021
160628
 
160022
160629
  // src/session.ts
160023
- var import_atomix_core5 = __toESM(require_dist4());
160630
+ var import_atomix_core7 = __toESM(require_dist4());
160024
160631
 
160025
160632
  // src/sessionTypes.ts
160026
160633
  var SESSION_HANDLE_BRAND = /* @__PURE__ */ Symbol.for("atomix-cli.sessionHandle");
@@ -160342,12 +160949,12 @@ async function marketplaceCommand(core, args) {
160342
160949
  }
160343
160950
 
160344
160951
  // src/hooksLoader.ts
160345
- var import_atomix_core4 = __toESM(require_dist4());
160952
+ var import_atomix_core6 = __toESM(require_dist4());
160346
160953
  init_paths();
160347
160954
  init_marketplace();
160348
160955
  import * as fs9 from "fs";
160349
160956
  import * as path9 from "path";
160350
- var VALID_EVENTS = new Set(import_atomix_core4.HOOK_EVENTS);
160957
+ var VALID_EVENTS = new Set(import_atomix_core6.HOOK_EVENTS);
160351
160958
  function readHookFile(p) {
160352
160959
  if (!fs9.existsSync(p)) return null;
160353
160960
  try {
@@ -160441,7 +161048,7 @@ function prepareProcess(cwd2) {
160441
161048
  }
160442
161049
  function createSessionCore(opts) {
160443
161050
  const interactive = opts.interactive ?? false;
160444
- const permissionMode = opts.permissionMode ?? (interactive ? import_atomix_core5.DEFAULT_PERMISSION_MODE : "free-style");
161051
+ const permissionMode = opts.permissionMode ?? (interactive ? import_atomix_core7.DEFAULT_PERMISSION_MODE : "free-style");
160445
161052
  const notes = [];
160446
161053
  const prepNote = prepareProcess(opts.cwd);
160447
161054
  if (prepNote) notes.push(prepNote);
@@ -160449,7 +161056,7 @@ function createSessionCore(opts) {
160449
161056
  const contextFiles = buildContextFilesConfig(opts.cwd, appConfig);
160450
161057
  const hookCfg = opts.hooks ?? interactive ? loadHooks(opts.cwd) : {};
160451
161058
  const dirs = { skills: buildSkillsExtraDirs(), agents: buildAgentsExtraDirs(), commands: buildCommandsExtraDirs() };
160452
- const core = new import_atomix_core5.AtomixCore({
161059
+ const core = new import_atomix_core7.AtomixCore({
160453
161060
  workingDir: opts.cwd,
160454
161061
  logLevel: opts.logLevel ?? atomixLogLevel(),
160455
161062
  stream: opts.stream ?? interactive,
@@ -160473,7 +161080,9 @@ function createSessionCore(opts) {
160473
161080
  deferBuiltinTools: ATOMIX_DEFER_TOOLS,
160474
161081
  memoryFiles: contextFiles.memoryFiles,
160475
161082
  personaFile: contextFiles.personaFile,
160476
- potentialMemoryFiles: potential.memoryFiles
161083
+ potentialMemoryFiles: potential.memoryFiles,
161084
+ thinking: false
161085
+ // cli 构造 core 时 thinking 关;harness 未声明即回到这里
160477
161086
  };
160478
161087
  return { [SESSION_HANDLE_BRAND]: true, core, cwd: opts.cwd, interactive, permissionMode, appConfig, contextFiles, baseline, notes };
160479
161088
  }
@@ -160562,6 +161171,16 @@ var SessionImpl = class {
160562
161171
  get harness() {
160563
161172
  return getActiveHarnessName(this.core);
160564
161173
  }
161174
+ get model() {
161175
+ const m = effectiveModels(this.core);
161176
+ const t = effectiveTemperatures(this.core);
161177
+ const temperature = {};
161178
+ for (const slot of ["main", "quick"]) {
161179
+ const e = t[slot];
161180
+ if ((e.from === "harness" || e.from === "profile") && e.value !== null) temperature[slot] = e.value;
161181
+ }
161182
+ return { main: m.main, quick: m.quick, ...m.fallback ? { fallback: m.fallback } : {}, ...Object.keys(temperature).length ? { temperature } : {} };
161183
+ }
160565
161184
  on(event, listener) {
160566
161185
  this.core.on(event, listener);
160567
161186
  }
@@ -160647,7 +161266,7 @@ var SessionImpl = class {
160647
161266
  };
160648
161267
 
160649
161268
  // src/resume.ts
160650
- var import_atomix_core6 = __toESM(require_dist4());
161269
+ var import_atomix_core8 = __toESM(require_dist4());
160651
161270
  import * as fs10 from "fs";
160652
161271
  import * as path10 from "path";
160653
161272
  function extractText(content) {
@@ -160666,7 +161285,7 @@ function readMessages(file) {
160666
161285
  }
160667
161286
  }
160668
161287
  function listSessions(cwd2) {
160669
- const dir = (0, import_atomix_core6.getProjectHistoryDir)(cwd2);
161288
+ const dir = (0, import_atomix_core8.getProjectHistoryDir)(cwd2);
160670
161289
  if (!fs10.existsSync(dir)) return [];
160671
161290
  const entries = [];
160672
161291
  for (const f of fs10.readdirSync(dir)) {
@@ -160805,16 +161424,19 @@ function setGlyphMode(mode) {
160805
161424
  return true;
160806
161425
  }
160807
161426
 
161427
+ // src/tui/index.tsx
161428
+ init_harness();
161429
+
160808
161430
  // src/permissionMode.ts
160809
- var import_atomix_core7 = __toESM(require_dist4());
161431
+ var import_atomix_core9 = __toESM(require_dist4());
160810
161432
  var META = {
160811
161433
  "step-by-step": { label: "step by step", hint: "\u6BCF\u4E2A\u654F\u611F\u64CD\u4F5C\u9010\u9879\u786E\u8BA4", tone: "muted" },
160812
161434
  "action-check": { label: "action check", hint: "\u53EA\u8BFB\u64CD\u4F5C\u514D\u786E\u8BA4\uFF0C\u5176\u4F59\u9010\u9879\u786E\u8BA4", tone: "accent" },
160813
161435
  "free-style": { label: "free style", hint: "\u5168\u90E8\u514D\u786E\u8BA4\uFF08\u5B89\u5168\u6821\u9A8C\u4ECD\u751F\u6548\uFF09", tone: "warning" }
160814
161436
  };
160815
- var PERMISSION_MODE_ORDER = import_atomix_core7.PERMISSION_MODES;
161437
+ var PERMISSION_MODE_ORDER = import_atomix_core9.PERMISSION_MODES;
160816
161438
  function permissionModeMeta(mode) {
160817
- return META[mode] ?? META[import_atomix_core7.DEFAULT_PERMISSION_MODE];
161439
+ return META[mode] ?? META[import_atomix_core9.DEFAULT_PERMISSION_MODE];
160818
161440
  }
160819
161441
  function nextPermissionMode(mode) {
160820
161442
  const i = PERMISSION_MODE_ORDER.indexOf(mode);
@@ -161075,7 +161697,7 @@ var Bridge = class {
161075
161697
  interactions: [],
161076
161698
  sessionId: "",
161077
161699
  thinkingEnabled: false,
161078
- permissionMode: import_atomix_core7.DEFAULT_PERMISSION_MODE,
161700
+ permissionMode: import_atomix_core9.DEFAULT_PERMISSION_MODE,
161079
161701
  modelName: "",
161080
161702
  redrawNonce: 0,
161081
161703
  staticEpoch: 0,
@@ -161134,6 +161756,10 @@ var Bridge = class {
161134
161756
  this.set({ thinkingEnabled: enabled });
161135
161757
  this.core.updateThinking(enabled);
161136
161758
  }
161759
+ /** 只同步 UI 镜像,不碰 core(harness 应用时 core 已由 applyAssembly 下发)。 */
161760
+ syncThinking(enabled) {
161761
+ this.set({ thinkingEnabled: enabled });
161762
+ }
161137
161763
  setModelName(name) {
161138
161764
  this.set({ modelName: name });
161139
161765
  }
@@ -162237,7 +162863,7 @@ function PromptCard({
162237
162863
  }
162238
162864
 
162239
162865
  // src/tui/images.ts
162240
- var import_atomix_core8 = __toESM(require_dist4());
162866
+ var import_atomix_core10 = __toESM(require_dist4());
162241
162867
  import { execFile as execFile2 } from "child_process";
162242
162868
  import * as fs13 from "fs";
162243
162869
  import * as os8 from "os";
@@ -162354,7 +162980,7 @@ async function buildUserInput(text, cwd2) {
162354
162980
  if (sources.length === 0) return { input: text, display: text };
162355
162981
  const blocks = [
162356
162982
  { type: "text", text: rewritten },
162357
- ...await Promise.all(sources.map((src) => (0, import_atomix_core8.loadImageAsBlock)(src)))
162983
+ ...await Promise.all(sources.map((src) => (0, import_atomix_core10.loadImageAsBlock)(src)))
162358
162984
  ];
162359
162985
  for (const placeholder of usedPlaceholders) {
162360
162986
  const file = pastedImages.get(placeholder);
@@ -162679,8 +163305,7 @@ function App2({ bridge, cwd: cwd2, initialHistory, appConfig }) {
162679
163305
  return;
162680
163306
  case "/model": {
162681
163307
  await modelCommand(bridge.core, rest2, bridge.ask);
162682
- const md = await bridge.core.getModelData().catch(() => null);
162683
- if (md) bridge.setModelName(md.taskConfig.main);
163308
+ bridge.setModelName(effectiveModels(bridge.core).main);
162684
163309
  return;
162685
163310
  }
162686
163311
  case "/resume": {
@@ -162719,9 +163344,16 @@ function App2({ bridge, cwd: cwd2, initialHistory, appConfig }) {
162719
163344
  case "/agents":
162720
163345
  bridge.notice(await agentsCommand(bridge.core, rest2));
162721
163346
  return;
162722
- case "/harness":
162723
- bridge.notice(await harnessCommand(bridge.core, rest2));
163347
+ case "/harness": {
163348
+ const out = await harnessCommand(bridge.core, rest2);
163349
+ bridge.notice(out, out.includes("\u26A0") ? "warn" : "info");
163350
+ bridge.setModelName(effectiveModels(bridge.core).main);
163351
+ if (rest2[0] === "use" || rest2[0] === "reset") {
163352
+ const t = appliedThinking(bridge.core);
163353
+ if (t !== void 0) bridge.syncThinking(t);
163354
+ }
162724
163355
  return;
163356
+ }
162725
163357
  case "/memory":
162726
163358
  bridge.notice(await memoryCommand(cwd2, appConfig, rest2, { harnessMemory: harnessMemoryOverride(bridge.core), harnessPersona: harnessPersonaOverride(bridge.core), personaPath: getActivePersonaFile(bridge.core) }));
162727
163359
  return;
@@ -162733,18 +163365,21 @@ function App2({ bridge, cwd: cwd2, initialHistory, appConfig }) {
162733
163365
  setSlashCommands(await loadSlashCommands(bridge.core));
162734
163366
  return;
162735
163367
  case "/status": {
162736
- const md = await bridge.core.getModelData().catch(() => null);
163368
+ const modelLine = modelStatusLine(bridge.core);
162737
163369
  bridge.notice(
162738
163370
  [
162739
163371
  `session ${s.sessionId}`,
162740
163372
  `cwd ${cwd2}`,
162741
163373
  `harness ${getActiveHarnessName(bridge.core)}${isHarnessOverridden(bridge.core) ? "\uFF08\u4F1A\u8BDD\u7EA7\u6307\u5B9A\uFF09" : ""}`,
162742
163374
  `memory ${memoryStatusLine(appConfig, { harnessMemory: harnessMemoryOverride(bridge.core), harnessPersona: harnessPersonaOverride(bridge.core) })}`,
162743
- `model main=${md?.taskConfig.main ?? "-"} quick=${md?.taskConfig.quick ?? "-"}`,
163375
+ `model ${modelLine}`,
163376
+ `temp ${temperatureStatusLine(bridge.core, s.thinkingEnabled)}`,
162744
163377
  `context ${s.usage ? `${s.usage.useTokens} / ${s.usage.maxTokens} tokens` : "-"}`,
162745
- `thinking ${s.thinkingEnabled ? "on" : "off"}`,
163378
+ `thinking ${thinkingStatusLine(bridge.core, s.thinkingEnabled)}`,
162746
163379
  `perms ${permissionModeMeta(s.permissionMode).label}\uFF08${s.permissionMode}\uFF0CShift+Tab \u5207\u6362\uFF09`
162747
- ].join("\n ")
163380
+ ].join("\n "),
163381
+ modelLine.startsWith("\u26A0") ? "warn" : "info"
163382
+ // 模型回落时整条黄色
162748
163383
  );
162749
163384
  return;
162750
163385
  }
@@ -162943,8 +163578,7 @@ async function startTui(cwd2, options2 = {}) {
162943
163578
  }
162944
163579
  }
162945
163580
  const bridge = new Bridge(core);
162946
- const md = await core.getModelData();
162947
- bridge.setModelName(md.taskConfig.main);
163581
+ bridge.setModelName(effectiveModels(core).main);
162948
163582
  const accent = paint("accent");
162949
163583
  const muted = paint("muted");
162950
163584
  bridge.notice(
@@ -162952,7 +163586,7 @@ async function startTui(cwd2, options2 = {}) {
162952
163586
  accent("\u256D\u2500 ") + bold("\u25C6 atomix") + muted(` v${VERSION2}`),
162953
163587
  accent("\u2502 ") + muted(`cwd ${cwd2}`),
162954
163588
  accent("\u2502 ") + muted(`root ${getAtomixRoot()}`),
162955
- accent("\u2502 ") + muted(`model ${md.taskConfig.main}`),
163589
+ accent("\u2502 ") + muted(`model ${effectiveModels(core).main}`),
162956
163590
  accent("\u2570\u2500 ") + muted("/help \u67E5\u770B\u547D\u4EE4")
162957
163591
  ].join("\n")
162958
163592
  );
@@ -162964,6 +163598,7 @@ async function startTui(cwd2, options2 = {}) {
162964
163598
  bridge.setPermissionMode(handle.permissionMode, { silent: true });
162965
163599
  bridge.setSessionId(session.ready.sessionId);
162966
163600
  bridge.setUsage(session.ready.usage);
163601
+ bridge.syncThinking(appliedThinking(core) ?? false);
162967
163602
  const initialHistory = [...session.ready.projectInputHistory ?? []];
162968
163603
  for (const n of session.notes) bridge.notice(n, n.startsWith("harness") ? "warn" : "info");
162969
163604
  if (resumeSessionId) {