atomix-cli 1.0.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
@@ -27277,13 +27277,33 @@ var require_stack_utils = __commonJS({
27277
27277
  }
27278
27278
  });
27279
27279
 
27280
+ // src/paths.ts
27281
+ import * as os3 from "os";
27282
+ import * as path from "path";
27283
+ function getAtomixRoot() {
27284
+ const custom = process.env.ATOMIX_ROOT;
27285
+ if (custom) return path.resolve(custom);
27286
+ return path.join(os3.homedir(), ".atomix");
27287
+ }
27288
+ var init_paths = __esm({
27289
+ "src/paths.ts"() {
27290
+ "use strict";
27291
+ }
27292
+ });
27293
+
27280
27294
  // ../atomix-core/dist/util/adapter.js
27281
27295
  var require_adapter = __commonJS({
27282
27296
  "../atomix-core/dist/util/adapter.js"(exports2) {
27283
27297
  "use strict";
27284
27298
  Object.defineProperty(exports2, "__esModule", { value: true });
27285
- exports2.TEMPERATURE_ONE_MODELS = void 0;
27299
+ exports2.TEMPERATURE_MAX = exports2.TEMPERATURE_MIN = exports2.DEFAULT_ANTHROPIC_TEMPERATURE = exports2.TEMPERATURE_ONE_MODELS = void 0;
27286
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;
27287
27307
  exports2.useMaxCompletionTokens = useMaxCompletionTokens;
27288
27308
  exports2.modelForcesThinking = modelForcesThinking;
27289
27309
  exports2.forcedThinkingEffort = forcedThinkingEffort;
@@ -27332,6 +27352,60 @@ var require_adapter = __commonJS({
27332
27352
  "kimi-k2.5",
27333
27353
  "moonshotai/kimi-k2.5"
27334
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
+ }
27335
27409
  var MAX_COMPLETION_TOKENS_PREFIXES = [
27336
27410
  "o1",
27337
27411
  "o3",
@@ -27525,7 +27599,8 @@ var require_apiUtil = __commonJS({
27525
27599
  model: modelName,
27526
27600
  messages: [{ role: "user", content: 'Please respond with exactly "YES" (in capital letters) to confirm this connection is working.' }],
27527
27601
  ...(0, adapter_1.useMaxCompletionTokens)(modelName) ? { max_completion_tokens: 200 } : { max_tokens: 200 },
27528
- 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"),把可用模型挡在添加阶段
27529
27604
  stream: false
27530
27605
  }),
27531
27606
  extractContent: (response) => response.choices?.[0]?.message?.content || "",
@@ -34969,7 +35044,7 @@ var require_combineLatest = __commonJS({
34969
35044
  maybeSchedule(scheduler, function() {
34970
35045
  var length = observables.length;
34971
35046
  var values2 = new Array(length);
34972
- var active2 = length;
35047
+ var active = length;
34973
35048
  var remainingFirstValues = length;
34974
35049
  var _loop_1 = function(i2) {
34975
35050
  maybeSchedule(scheduler, function() {
@@ -34985,7 +35060,7 @@ var require_combineLatest = __commonJS({
34985
35060
  subscriber.next(valueTransform(values2.slice()));
34986
35061
  }
34987
35062
  }, function() {
34988
- if (!--active2) {
35063
+ if (!--active) {
34989
35064
  subscriber.complete();
34990
35065
  }
34991
35066
  }));
@@ -35019,20 +35094,20 @@ var require_mergeInternals = __commonJS({
35019
35094
  var OperatorSubscriber_1 = require_OperatorSubscriber();
35020
35095
  function mergeInternals(source, subscriber, project, concurrent, onBeforeNext, expand, innerSubScheduler, additionalFinalizer) {
35021
35096
  var buffer = [];
35022
- var active2 = 0;
35097
+ var active = 0;
35023
35098
  var index = 0;
35024
35099
  var isComplete = false;
35025
35100
  var checkComplete = function() {
35026
- if (isComplete && !buffer.length && !active2) {
35101
+ if (isComplete && !buffer.length && !active) {
35027
35102
  subscriber.complete();
35028
35103
  }
35029
35104
  };
35030
35105
  var outerNext = function(value) {
35031
- return active2 < concurrent ? doInnerSub(value) : buffer.push(value);
35106
+ return active < concurrent ? doInnerSub(value) : buffer.push(value);
35032
35107
  };
35033
35108
  var doInnerSub = function(value) {
35034
35109
  expand && subscriber.next(value);
35035
- active2++;
35110
+ active++;
35036
35111
  var innerComplete = false;
35037
35112
  innerFrom_1.innerFrom(project(value, index++)).subscribe(OperatorSubscriber_1.createOperatorSubscriber(subscriber, function(innerValue) {
35038
35113
  onBeforeNext === null || onBeforeNext === void 0 ? void 0 : onBeforeNext(innerValue);
@@ -35046,7 +35121,7 @@ var require_mergeInternals = __commonJS({
35046
35121
  }, void 0, function() {
35047
35122
  if (innerComplete) {
35048
35123
  try {
35049
- active2--;
35124
+ active--;
35050
35125
  var _loop_1 = function() {
35051
35126
  var bufferedValue = buffer.shift();
35052
35127
  if (innerSubScheduler) {
@@ -35057,7 +35132,7 @@ var require_mergeInternals = __commonJS({
35057
35132
  doInnerSub(bufferedValue);
35058
35133
  }
35059
35134
  };
35060
- while (buffer.length && active2 < concurrent) {
35135
+ while (buffer.length && active < concurrent) {
35061
35136
  _loop_1();
35062
35137
  }
35063
35138
  checkComplete();
@@ -42241,7 +42316,7 @@ var require_shell = __commonJS({
42241
42316
  var os9 = __importStar(__require("os"));
42242
42317
  var crypto3 = __importStar(__require("crypto"));
42243
42318
  var log_1 = require_log();
42244
- var TEMPFILE_PREFIX = os9.tmpdir() + `sema-`;
42319
+ var TEMPFILE_PREFIX = (0, path_1.join)(os9.tmpdir(), "sema-");
42245
42320
  var DEFAULT_TIMEOUT = 30 * 60 * 1e3;
42246
42321
  var SIGTERM_CODE = 143;
42247
42322
  var FILE_SUFFIXES = {
@@ -44610,7 +44685,8 @@ var require_model = __commonJS({
44610
44685
  apiKey: config.apiKey,
44611
44686
  maxTokens: config.maxTokens || fallback.maxTokens,
44612
44687
  contextLength: config.contextLength || fallback.contextLength,
44613
- 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 } : {}
44614
44690
  };
44615
44691
  }
44616
44692
  }
@@ -44661,10 +44737,12 @@ var require_ModelManager = __commonJS({
44661
44737
  exports2.getModelManager = exports2.ModelManager = void 0;
44662
44738
  var fs14 = __importStar(__require("fs"));
44663
44739
  var path15 = __importStar(__require("path"));
44740
+ var adapter_1 = require_adapter();
44664
44741
  var apiUtil_1 = require_apiUtil();
44665
44742
  var savePath_1 = require_savePath();
44666
44743
  var model_1 = require_model();
44667
44744
  var log_1 = require_log();
44745
+ var EngineContext_1 = require_EngineContext();
44668
44746
  var ModelManager = class {
44669
44747
  constructor(initialConfig) {
44670
44748
  this.configPath = (0, savePath_1.getModelConfigFilePath)();
@@ -44692,6 +44770,8 @@ var require_ModelManager = __commonJS({
44692
44770
  * @param skipValidation 是否跳过API校验,默认为false
44693
44771
  */
44694
44772
  async addNewModel(config, skipValidation = false) {
44773
+ if (config.temperature !== void 0)
44774
+ this.assertProfileTemperature(config.modelName, config.temperature);
44695
44775
  const profile = (0, model_1.convertToModelProfile)(config);
44696
44776
  const existingModelIndex = this.config.modelProfiles.findIndex((p) => p.name === profile.name);
44697
44777
  if (!skipValidation) {
@@ -44720,7 +44800,7 @@ ${testResult.curlCommand}` : testResult.message;
44720
44800
  }
44721
44801
  }
44722
44802
  if (existingModelIndex !== -1) {
44723
- this.config.modelProfiles[existingModelIndex] = profile;
44803
+ this.config.modelProfiles[existingModelIndex] = { ...this.config.modelProfiles[existingModelIndex], ...profile };
44724
44804
  } else {
44725
44805
  this.config.modelProfiles.push(profile);
44726
44806
  if (this.config.modelProfiles.length === 1) {
@@ -44819,16 +44899,36 @@ ${testResult.curlCommand}` : testResult.message;
44819
44899
  };
44820
44900
  }
44821
44901
  /**
44822
- * 获取指定类型的模型配置
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。
44823
44915
  */
44824
44916
  getModel(pointer) {
44825
- const pointerId = this.config.modelPointers?.[pointer];
44826
- if (!pointerId) {
44917
+ const { id } = this.resolvePointer(pointer);
44918
+ if (!id) {
44827
44919
  return null;
44828
44920
  }
44829
- const profile = (0, model_1.findModelProfile)(pointerId, this.config.modelProfiles);
44921
+ const profile = (0, model_1.findModelProfile)(id, this.config.modelProfiles);
44830
44922
  return profile || null;
44831
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
+ }
44832
44932
  /**
44833
44933
  * 获取指定类型的模型名称
44834
44934
  */
@@ -44836,6 +44936,89 @@ ${testResult.curlCommand}` : testResult.message;
44836
44936
  const profile = this.getModel(pointer);
44837
44937
  return profile ? profile.modelName : null;
44838
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
+ }
44839
45022
  /**
44840
45023
  * 获取当前模型数据
44841
45024
  * @param showModelProfiles 是否包含详细的模型配置信息,默认为false
@@ -51127,9 +51310,9 @@ var require_agentsManager = __commonJS({
51127
51310
  }
51128
51311
  const userNext = /* @__PURE__ */ new Map();
51129
51312
  await this.loadAgentsFromDir(userNext, this.userAgentsDir, "user");
51130
- const projectDir2 = opts?.projectAgentsDir !== void 0 ? path15.resolve(opts.projectAgentsDir) : this.resolveProjectAgentsDir();
51313
+ const projectDir = opts?.projectAgentsDir !== void 0 ? path15.resolve(opts.projectAgentsDir) : this.resolveProjectAgentsDir();
51131
51314
  const projectNext = /* @__PURE__ */ new Map();
51132
- await this.loadAgentsFromDir(projectNext, projectDir2, "project");
51315
+ await this.loadAgentsFromDir(projectNext, projectDir, "project");
51133
51316
  for (const name of userNext.keys()) {
51134
51317
  if (managedNext.has(name) || builtinNext.has(name))
51135
51318
  (0, log_1.logWarn)(`Agent [${name}] \u88AB user \u7EA7\u914D\u7F6E\u8986\u76D6`);
@@ -51142,11 +51325,11 @@ var require_agentsManager = __commonJS({
51142
51325
  this.builtinLayer = builtinNext;
51143
51326
  this.managedLayers.set(key, managedNext);
51144
51327
  this.userLayer = userNext;
51145
- this.projectLayers.set(projectDir2, projectNext);
51328
+ this.projectLayers.set(projectDir, projectNext);
51146
51329
  this.lastInitKey = key;
51147
- this.lastInitProjectKey = projectDir2;
51330
+ this.lastInitProjectKey = projectDir;
51148
51331
  this.invalidateCache();
51149
- const agentNames = Array.from(this.mergedFor(key, projectDir2).keys()).join(", ");
51332
+ const agentNames = Array.from(this.mergedFor(key, projectDir).keys()).join(", ");
51150
51333
  (0, log_1.logInfo)(`\u52A0\u8F7D Agents \u914D\u7F6E: ${agentNames}`);
51151
51334
  }
51152
51335
  /** 按 managed 键 + project 键合并四层(带缓存);spread 顺序即覆盖顺序 */
@@ -51385,20 +51568,20 @@ var require_agentsManager = __commonJS({
51385
51568
  if (this.currentMerged(view).has(agentConf.name)) {
51386
51569
  (0, log_1.logWarn)(`Agent [${agentConf.name}] \u88AB\u8986\u76D6`);
51387
51570
  }
51388
- const projectDir2 = view?.projectAgentsDir !== void 0 ? path15.resolve(view.projectAgentsDir) : this.resolveProjectAgentsDir();
51571
+ const projectDir = view?.projectAgentsDir !== void 0 ? path15.resolve(view.projectAgentsDir) : this.resolveProjectAgentsDir();
51389
51572
  if (agentConf.locate === "user") {
51390
51573
  this.userLayer.set(agentConf.name, { ...agentConf });
51391
51574
  } else {
51392
- let layer = this.projectLayers.get(projectDir2);
51575
+ let layer = this.projectLayers.get(projectDir);
51393
51576
  if (!layer) {
51394
51577
  layer = /* @__PURE__ */ new Map();
51395
- this.projectLayers.set(projectDir2, layer);
51578
+ this.projectLayers.set(projectDir, layer);
51396
51579
  }
51397
51580
  layer.set(agentConf.name, { ...agentConf });
51398
51581
  }
51399
51582
  this.invalidateCache();
51400
51583
  (0, log_1.logInfo)(`\u6DFB\u52A0 Agent \u914D\u7F6E: ${agentConf.name}`);
51401
- const saved = await this.saveAgentToFile(agentConf, projectDir2);
51584
+ const saved = await this.saveAgentToFile(agentConf, projectDir);
51402
51585
  if (!saved) {
51403
51586
  (0, log_1.logWarn)(`Agent \u914D\u7F6E\u5DF2\u6DFB\u52A0\u5230\u5185\u5B58\uFF0C\u4F46\u4FDD\u5B58\u5230\u6587\u4EF6\u5931\u8D25: ${agentConf.name}`);
51404
51587
  }
@@ -51870,9 +52053,15 @@ var require_Bash = __commonJS({
51870
52053
  "--eof",
51871
52054
  "-a",
51872
52055
  "--arg-file"
51873
- ])
51874
- };
51875
- var STATEMENT_KEYWORDS = /* @__PURE__ */ new Set([
52056
+ ]),
52057
+ // zsh precommand modifier(macOS 默认 $SHELL 是 zsh,PersistentShell 直接用它):
52058
+ // `repeat N cmd`、`noglob cmd`、`nocorrect cmd`、`- cmd`(argv[0] 加 `-`)都会执行后面的命令
52059
+ repeat: W([], [], 1),
52060
+ noglob: W([], []),
52061
+ nocorrect: W([], []),
52062
+ "-": W([], [])
52063
+ };
52064
+ var CMD_KEYWORDS = /* @__PURE__ */ new Set([
51876
52065
  "!",
51877
52066
  "{",
51878
52067
  "}",
@@ -51885,13 +52074,9 @@ var require_Bash = __commonJS({
51885
52074
  "until",
51886
52075
  "do",
51887
52076
  "done",
51888
- "case",
51889
52077
  "esac",
51890
- "in",
51891
- "for",
51892
- "select",
51893
- "function",
51894
- "coproc"
52078
+ "always",
52079
+ "end"
51895
52080
  ]);
51896
52081
  var REDIRECT_OPS = /* @__PURE__ */ new Set([">", ">>", "<", ">&", "<&", "<<<", ">|"]);
51897
52082
  var LIST_SEPARATORS = /* @__PURE__ */ new Set(["&&", "||", ";", ";;", "|", "|&", "&"]);
@@ -51901,6 +52086,8 @@ var require_Bash = __commonJS({
51901
52086
  var isClobberPipe = (entries, k) => isOp(entries[k], "|") && isOp(entries[k - 1], ">");
51902
52087
  function analyzeCommandSegments(command) {
51903
52088
  const out = [];
52089
+ let state = "cmd";
52090
+ let caseDepth = 0;
51904
52091
  for (const line of command.split(/\r\n|\n|\r/)) {
51905
52092
  if (!line.trim())
51906
52093
  continue;
@@ -51911,32 +52098,226 @@ var require_Bash = __commonJS({
51911
52098
  out.push({ error: `command could not be parsed: ${line}` });
51912
52099
  continue;
51913
52100
  }
51914
- const segments = [];
52101
+ if (state !== "patterns")
52102
+ state = "cmd";
52103
+ let pending = null;
52104
+ let parenList = false;
52105
+ let patternWord = false;
51915
52106
  let cur = [];
51916
- for (let k = 0; k < entries.length; k++) {
52107
+ let failed = false;
52108
+ const flush = () => {
52109
+ if (cur.length) {
52110
+ const r = unwrapEntries(cur, line);
52111
+ if (r !== null)
52112
+ out.push(r);
52113
+ }
52114
+ cur = [];
52115
+ };
52116
+ const fail = (msg) => {
52117
+ out.push({ error: msg });
52118
+ failed = true;
52119
+ };
52120
+ for (let k = 0; k < entries.length && !failed; k++) {
51917
52121
  const e = entries[k];
51918
- let boundary;
51919
- if (typeof e === "string")
51920
- boundary = STATEMENT_KEYWORDS.has(e);
51921
- else if ("op" in e)
51922
- boundary = e.op === "(" || e.op === ")" || LIST_SEPARATORS.has(e.op) && !isAmpRedirect(entries, k) && !isClobberPipe(entries, k);
51923
- else
51924
- boundary = false;
51925
- if (boundary) {
51926
- if (cur.length)
51927
- segments.push(cur);
51928
- cur = [];
52122
+ if (typeof e === "object" && "comment" in e)
52123
+ break;
52124
+ const kw = typeof e === "string" ? e : null;
52125
+ const isWord = kw !== null || isOp(e, "glob");
52126
+ if (isWord) {
52127
+ switch (state) {
52128
+ case "cmd":
52129
+ if (kw !== null && CMD_KEYWORDS.has(kw)) {
52130
+ flush();
52131
+ if (kw === "esac")
52132
+ caseDepth = Math.max(0, caseDepth - 1);
52133
+ continue;
52134
+ }
52135
+ if (kw === "for" || kw === "select" || kw === "foreach") {
52136
+ flush();
52137
+ pending = "for";
52138
+ state = "name";
52139
+ continue;
52140
+ }
52141
+ if (kw === "case") {
52142
+ flush();
52143
+ pending = "case";
52144
+ state = "name";
52145
+ continue;
52146
+ }
52147
+ if (kw === "function") {
52148
+ flush();
52149
+ pending = "function";
52150
+ state = "name";
52151
+ continue;
52152
+ }
52153
+ if (kw === "coproc") {
52154
+ flush();
52155
+ if (typeof entries[k + 1] === "string" && (entries[k + 2] === "{" || isOp(entries[k + 2], "(")))
52156
+ k++;
52157
+ continue;
52158
+ }
52159
+ if (kw === "[[") {
52160
+ flush();
52161
+ state = "cond";
52162
+ continue;
52163
+ }
52164
+ cur.push(e);
52165
+ if (kw !== null && (ENV_ASSIGN_RE.test(kw) || kw.startsWith("-") || /^\d+$/.test(kw) && isRedirectOp(entries[k + 1])))
52166
+ continue;
52167
+ if (kw !== null && WRAPPERS[kw]) {
52168
+ const words2 = [kw];
52169
+ for (let j = k + 1; j < entries.length; j++) {
52170
+ const w = entries[j];
52171
+ if (typeof w === "string")
52172
+ words2.push(w);
52173
+ else if (isOp(w, "glob"))
52174
+ words2.push(w.pattern);
52175
+ else
52176
+ break;
52177
+ }
52178
+ const r = consumeWrapper(words2, 0);
52179
+ if ("error" in r) {
52180
+ fail(r.error);
52181
+ continue;
52182
+ }
52183
+ const n = Math.min(r.next, words2.length);
52184
+ for (let m = 1; m < n; m++)
52185
+ cur.push(entries[k + m]);
52186
+ k += n - 1;
52187
+ if (r.query)
52188
+ state = "args";
52189
+ continue;
52190
+ }
52191
+ state = "args";
52192
+ continue;
52193
+ case "args":
52194
+ if (kw === "}") {
52195
+ flush();
52196
+ state = "cmd";
52197
+ continue;
52198
+ }
52199
+ cur.push(e);
52200
+ continue;
52201
+ case "name":
52202
+ state = pending === "function" ? "cmd" : "afterName";
52203
+ continue;
52204
+ case "afterName":
52205
+ if (kw === "in") {
52206
+ if (pending === "case") {
52207
+ caseDepth++;
52208
+ state = "patterns";
52209
+ patternWord = false;
52210
+ } else
52211
+ state = "wordList";
52212
+ continue;
52213
+ }
52214
+ if (kw === "do" && pending === "for") {
52215
+ state = "cmd";
52216
+ continue;
52217
+ }
52218
+ state = "cmd";
52219
+ k--;
52220
+ continue;
52221
+ case "wordList":
52222
+ continue;
52223
+ // 字面量列表,不是命令
52224
+ case "patterns":
52225
+ if (kw === "esac") {
52226
+ caseDepth = Math.max(0, caseDepth - 1);
52227
+ state = "cmd";
52228
+ continue;
52229
+ }
52230
+ if (patternWord) {
52231
+ fail(`case pattern cannot be analyzed statically in: ${line}`);
52232
+ continue;
52233
+ }
52234
+ patternWord = true;
52235
+ continue;
52236
+ case "cond":
52237
+ if (kw === "]]")
52238
+ state = "cmd";
52239
+ continue;
52240
+ }
52241
+ }
52242
+ const op = e.op;
52243
+ if (state === "cond") {
52244
+ if (LIST_SEPARATORS.has(op) && op !== "&&" && op !== "||")
52245
+ state = "cmd";
51929
52246
  continue;
51930
52247
  }
52248
+ if ((state === "name" || state === "afterName") && !(state === "afterName" && op === "(")) {
52249
+ state = "cmd";
52250
+ k--;
52251
+ continue;
52252
+ }
52253
+ if (REDIRECT_OPS.has(op) || isAmpRedirect(entries, k)) {
52254
+ const skip = state === "wordList" || state === "patterns";
52255
+ const take2 = (idx) => {
52256
+ if (!skip)
52257
+ cur.push(entries[idx]);
52258
+ };
52259
+ take2(k);
52260
+ if (op === "&")
52261
+ take2(++k);
52262
+ while (k + 1 < entries.length && (isRedirectOp(entries[k + 1]) || isClobberPipe(entries, k + 1)))
52263
+ take2(++k);
52264
+ if (k + 1 < entries.length && typeof entries[k + 1] === "string")
52265
+ take2(++k);
52266
+ continue;
52267
+ }
52268
+ if (op === "(") {
52269
+ if (state === "afterName") {
52270
+ state = "wordList";
52271
+ parenList = true;
52272
+ continue;
52273
+ }
52274
+ if (state === "patterns") {
52275
+ patternWord = false;
52276
+ continue;
52277
+ }
52278
+ flush();
52279
+ state = "cmd";
52280
+ continue;
52281
+ }
52282
+ if (op === ")") {
52283
+ if (state === "wordList" && parenList) {
52284
+ parenList = false;
52285
+ state = "cmd";
52286
+ continue;
52287
+ }
52288
+ if (state === "patterns") {
52289
+ state = "cmd";
52290
+ continue;
52291
+ }
52292
+ flush();
52293
+ state = "cmd";
52294
+ continue;
52295
+ }
52296
+ if (op === "|" && state === "patterns") {
52297
+ patternWord = false;
52298
+ continue;
52299
+ }
52300
+ if (LIST_SEPARATORS.has(op) && !isClobberPipe(entries, k)) {
52301
+ flush();
52302
+ if (op === ";;" && caseDepth > 0) {
52303
+ state = "patterns";
52304
+ patternWord = false;
52305
+ } else
52306
+ state = "cmd";
52307
+ parenList = false;
52308
+ continue;
52309
+ }
52310
+ if (state === "wordList" || state === "patterns")
52311
+ continue;
51931
52312
  cur.push(e);
51932
52313
  }
51933
- if (cur.length)
51934
- segments.push(cur);
51935
- for (const seg of segments) {
51936
- const r = unwrapEntries(seg, line);
51937
- if (r !== null)
51938
- out.push(r);
52314
+ if (failed)
52315
+ continue;
52316
+ if (state === "cond") {
52317
+ fail(`unterminated [[ in: ${line}`);
52318
+ continue;
51939
52319
  }
52320
+ flush();
51940
52321
  }
51941
52322
  return out;
51942
52323
  }
@@ -51977,53 +52358,62 @@ var require_Bash = __commonJS({
51977
52358
  i++;
51978
52359
  continue;
51979
52360
  }
51980
- const spec = WRAPPERS[t];
51981
- if (!spec)
52361
+ if (!WRAPPERS[t])
51982
52362
  break;
51983
- if (t === "command") {
51984
- const rest2 = tokens.slice(i + 1);
51985
- const optEnd = rest2.findIndex((x) => !x.startsWith("-") || x === "--");
51986
- const opts = optEnd < 0 ? rest2 : rest2.slice(0, optEnd);
51987
- if (opts.some((o) => /^-[pvV]*[vV][pvV]*$/.test(o)))
51988
- return { baseCmd: "command", args: rest2 };
51989
- }
51990
- i++;
51991
- while (i < tokens.length && tokens[i].startsWith("-")) {
51992
- const opt = tokens[i];
51993
- if (opt === "--") {
51994
- i++;
51995
- break;
51996
- }
51997
- const eq2 = opt.startsWith("--") ? opt.indexOf("=") : -1;
51998
- const name = eq2 > 0 ? opt.slice(0, eq2) : opt;
51999
- if (eq2 > 0 && (spec.flags.has(name) || spec.valueFlags.has(name))) {
52000
- i++;
52001
- continue;
52002
- }
52003
- if (spec.flags.has(opt)) {
52004
- i++;
52005
- continue;
52006
- }
52007
- if (spec.valueFlags.has(opt)) {
52008
- i += 2;
52009
- continue;
52010
- }
52011
- if (/^-[A-Za-z]/.test(opt) && opt.length > 2 && spec.valueFlags.has(opt.slice(0, 2))) {
52012
- i++;
52013
- continue;
52014
- }
52015
- if (t === "nice" && /^-\d+$/.test(opt)) {
52016
- i++;
52017
- continue;
52018
- }
52019
- return { error: `option '${opt}' of wrapper '${t}' cannot be analyzed statically` };
52020
- }
52021
- i += spec.positional ?? 0;
52363
+ const r = consumeWrapper(tokens, i);
52364
+ if ("error" in r)
52365
+ return r;
52366
+ if (r.query)
52367
+ return { baseCmd: "command", args: tokens.slice(i + 1) };
52368
+ i = r.next;
52022
52369
  }
52023
52370
  if (i >= tokens.length)
52024
52371
  return { baseCmd: tokens[tokens.length - 1], args: [] };
52025
52372
  return { baseCmd: tokens[i], args: tokens.slice(i + 1) };
52026
52373
  }
52374
+ function consumeWrapper(tokens, i) {
52375
+ const t = tokens[i];
52376
+ const spec = WRAPPERS[t];
52377
+ if (t === "command") {
52378
+ const rest2 = tokens.slice(i + 1);
52379
+ const optEnd = rest2.findIndex((x) => !x.startsWith("-") || x === "--");
52380
+ const opts = optEnd < 0 ? rest2 : rest2.slice(0, optEnd);
52381
+ if (opts.some((o) => /^-[pvV]*[vV][pvV]*$/.test(o)))
52382
+ return { next: tokens.length, query: true };
52383
+ }
52384
+ i++;
52385
+ while (i < tokens.length && tokens[i].startsWith("-")) {
52386
+ const opt = tokens[i];
52387
+ if (opt === "--") {
52388
+ i++;
52389
+ break;
52390
+ }
52391
+ const eq2 = opt.startsWith("--") ? opt.indexOf("=") : -1;
52392
+ const name = eq2 > 0 ? opt.slice(0, eq2) : opt;
52393
+ if (eq2 > 0 && (spec.flags.has(name) || spec.valueFlags.has(name))) {
52394
+ i++;
52395
+ continue;
52396
+ }
52397
+ if (spec.flags.has(opt)) {
52398
+ i++;
52399
+ continue;
52400
+ }
52401
+ if (spec.valueFlags.has(opt)) {
52402
+ i += 2;
52403
+ continue;
52404
+ }
52405
+ if (/^-[A-Za-z]/.test(opt) && opt.length > 2 && spec.valueFlags.has(opt.slice(0, 2))) {
52406
+ i++;
52407
+ continue;
52408
+ }
52409
+ if (t === "nice" && /^-\d+$/.test(opt)) {
52410
+ i++;
52411
+ continue;
52412
+ }
52413
+ return { error: `option '${opt}' of wrapper '${t}' cannot be analyzed statically` };
52414
+ }
52415
+ return { next: i + (spec.positional ?? 0) };
52416
+ }
52027
52417
  function resolveCdTarget(args) {
52028
52418
  const positional = [];
52029
52419
  let optionsDone = false;
@@ -64769,7 +65159,7 @@ var init_iteratee = __esm({
64769
65159
  });
64770
65160
 
64771
65161
  // ../atomix-core/node_modules/lodash-es/join.js
64772
- function join(array, separator) {
65162
+ function join2(array, separator) {
64773
65163
  return array == null ? "" : nativeJoin.call(array, separator);
64774
65164
  }
64775
65165
  var arrayProto2, nativeJoin, join_default;
@@ -64777,7 +65167,7 @@ var init_join = __esm({
64777
65167
  "../atomix-core/node_modules/lodash-es/join.js"() {
64778
65168
  arrayProto2 = Array.prototype;
64779
65169
  nativeJoin = arrayProto2.join;
64780
- join_default = join;
65170
+ join_default = join2;
64781
65171
  }
64782
65172
  });
64783
65173
 
@@ -74274,15 +74664,30 @@ var require_skillRegistry = __commonJS({
74274
74664
  "../atomix-core/dist/services/skill/skillRegistry.js"(exports2) {
74275
74665
  "use strict";
74276
74666
  Object.defineProperty(exports2, "__esModule", { value: true });
74667
+ exports2.skillRegistryKey = skillRegistryKey;
74277
74668
  exports2.initializeSkillRegistry = initializeSkillRegistry;
74278
74669
  exports2.getSkillRegistry = getSkillRegistry;
74279
74670
  exports2.findSkill = findSkill;
74280
74671
  exports2.getSkillsInfo = getSkillsInfo;
74281
74672
  exports2.getSkillsSummary = getSkillsSummary;
74673
+ exports2.invalidateSkillCache = invalidateSkillCache;
74282
74674
  exports2.clearSkillRegistry = clearSkillRegistry;
74283
74675
  var skillLoader_1 = require_skillLoader();
74284
74676
  var log_1 = require_log();
74285
- var globalRegistry = null;
74677
+ var EngineContext_1 = require_EngineContext();
74678
+ var registries = /* @__PURE__ */ new Map();
74679
+ var lastKey = null;
74680
+ function skillRegistryKey(workingDir, extraDirs) {
74681
+ return workingDir + "\0" + (extraDirs ?? []).map((e) => `${e.locate}:${e.dir}`).join("\0");
74682
+ }
74683
+ function viewFromContext() {
74684
+ const store = (0, EngineContext_1.getEngineStore)();
74685
+ const cfg = store?.coreConfig;
74686
+ if (!store || !cfg)
74687
+ return null;
74688
+ const workingDir = cfg.agentDataDir || cfg.workingDir || store.agentDataDir || store.workingDir || process.cwd();
74689
+ return { workingDir, extraDirs: cfg.skillsExtraDirs, disabledNames: cfg.skillsDisabledNames };
74690
+ }
74286
74691
  function initializeSkillRegistry(workingDir, extraDirs) {
74287
74692
  const registry = /* @__PURE__ */ new Map();
74288
74693
  const skills = (0, skillLoader_1.loadAllSkills)(workingDir, extraDirs);
@@ -74294,21 +74699,44 @@ var require_skillRegistry = __commonJS({
74294
74699
  }
74295
74700
  registry.set(name, skill);
74296
74701
  }
74297
- globalRegistry = registry;
74702
+ const key = skillRegistryKey(workingDir, extraDirs);
74703
+ registries.set(key, registry);
74704
+ lastKey = key;
74298
74705
  return registry;
74299
74706
  }
74300
- function getSkillRegistry() {
74301
- if (!globalRegistry) {
74707
+ function resolve9(view) {
74708
+ const v = view ?? viewFromContext();
74709
+ if (v) {
74710
+ const key = skillRegistryKey(v.workingDir, v.extraDirs);
74711
+ let registry = registries.get(key);
74712
+ if (!registry) {
74713
+ registry = initializeSkillRegistry(v.workingDir, v.extraDirs);
74714
+ }
74715
+ return { registry, disabled: new Set(v.disabledNames ?? []) };
74716
+ }
74717
+ if (!lastKey) {
74302
74718
  throw new Error("Skill registry not initialized. Call initializeSkillRegistry() first.");
74303
74719
  }
74304
- return globalRegistry;
74305
- }
74306
- function findSkill(name) {
74307
- const registry = getSkillRegistry();
74720
+ return { registry: registries.get(lastKey), disabled: /* @__PURE__ */ new Set() };
74721
+ }
74722
+ function getSkillRegistry(view) {
74723
+ const { registry, disabled } = resolve9(view);
74724
+ if (disabled.size === 0)
74725
+ return registry;
74726
+ const filtered = /* @__PURE__ */ new Map();
74727
+ for (const [name, skill] of registry)
74728
+ if (!disabled.has(name))
74729
+ filtered.set(name, skill);
74730
+ return filtered;
74731
+ }
74732
+ function findSkill(name, view) {
74733
+ const { registry, disabled } = resolve9(view);
74734
+ if (disabled.has(name))
74735
+ return void 0;
74308
74736
  return registry.get(name);
74309
74737
  }
74310
- function getSkillsInfo() {
74311
- const registry = getSkillRegistry();
74738
+ function getSkillsInfo(view, opts) {
74739
+ const registry = opts?.includeDisabled ? resolve9(view).registry : getSkillRegistry(view);
74312
74740
  const skillsInfo = [];
74313
74741
  for (const [name, skill] of registry.entries()) {
74314
74742
  skillsInfo.push({
@@ -74320,8 +74748,8 @@ var require_skillRegistry = __commonJS({
74320
74748
  }
74321
74749
  return skillsInfo;
74322
74750
  }
74323
- function getSkillsSummary() {
74324
- const registry = getSkillRegistry();
74751
+ function getSkillsSummary(view) {
74752
+ const registry = getSkillRegistry(view);
74325
74753
  if (registry.size === 0) {
74326
74754
  return "";
74327
74755
  }
@@ -74335,10 +74763,14 @@ var require_skillRegistry = __commonJS({
74335
74763
  lines.push("When a task requires specific domain knowledge or workflow, use the Skill tool to activate the relevant skill.");
74336
74764
  return lines.join("\n");
74337
74765
  }
74338
- function clearSkillRegistry() {
74339
- globalRegistry = null;
74766
+ function invalidateSkillCache() {
74340
74767
  skillLoader_1.loadAllSkills.cache.clear?.();
74341
74768
  }
74769
+ function clearSkillRegistry() {
74770
+ registries.clear();
74771
+ lastKey = null;
74772
+ invalidateSkillCache();
74773
+ }
74342
74774
  }
74343
74775
  });
74344
74776
 
@@ -74710,13 +75142,15 @@ var require_cacheLLM = __commonJS({
74710
75142
  /**
74711
75143
  * 生成缓存键 - 基于消息内容生成简单hash
74712
75144
  */
74713
- generateKey(messages, systemPrompt, modelName, enableThinking = false) {
75145
+ generateKey(messages, systemPrompt, modelName, enableThinking = false, temperature) {
74714
75146
  const normalizedSystemPrompt = Array.isArray(systemPrompt) && systemPrompt.length > 0 && typeof systemPrompt[0] === "object" && "type" in systemPrompt[0] ? systemPrompt.map((item) => item.text) : systemPrompt;
74715
75147
  const content = JSON.stringify({
74716
75148
  messages: messages.map((msg) => msg.message.content),
74717
75149
  systemPrompt: normalizedSystemPrompt,
74718
75150
  modelName,
74719
- enableThinking
75151
+ enableThinking,
75152
+ temperature: temperature ?? null
75153
+ // 不同温度不共享缓存(model-temperature-v1)
74720
75154
  });
74721
75155
  return crypto_1.default.createHash("md5").update(content).digest("hex");
74722
75156
  }
@@ -74746,8 +75180,8 @@ var require_cacheLLM = __commonJS({
74746
75180
  /**
74747
75181
  * 获取缓存
74748
75182
  */
74749
- get(messages, systemPrompt, modelName, enableThinking = false) {
74750
- 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);
74751
75185
  const entries = this.readCacheFile();
74752
75186
  const entry = entries.find((e) => e.key === key);
74753
75187
  return entry ? entry.response : null;
@@ -74755,8 +75189,8 @@ var require_cacheLLM = __commonJS({
74755
75189
  /**
74756
75190
  * 设置缓存
74757
75191
  */
74758
- set(messages, systemPrompt, modelName, response, enableThinking = false) {
74759
- 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);
74760
75194
  let entries = this.readCacheFile();
74761
75195
  entries = entries.filter((e) => e.key !== key);
74762
75196
  entries.unshift({
@@ -74805,8 +75239,8 @@ var require_cache = __commonJS({
74805
75239
  var log_1 = require_log();
74806
75240
  var CACHE_STREAM_CHUNK_SIZE = 20;
74807
75241
  var CACHE_STREAM_DELAY = 100;
74808
- async function tryGetCachedResponse(messages, systemPromptContent, modelName, shouldStream, enableThinking, emitChunkEvents, signal) {
74809
- 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);
74810
75244
  if (!cachedResponse) {
74811
75245
  return null;
74812
75246
  }
@@ -74879,8 +75313,8 @@ var require_cache = __commonJS({
74879
75313
  function calcSimulatedDelay(contentLength, maxDelay) {
74880
75314
  return Math.min(Math.ceil(contentLength / CACHE_STREAM_CHUNK_SIZE) * CACHE_STREAM_DELAY, maxDelay);
74881
75315
  }
74882
- function setCachedResponse(messages, systemPromptContent, modelName, response, enableThinking = false) {
74883
- 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);
74884
75318
  }
74885
75319
  function getCacheSize() {
74886
75320
  return cacheLLM_1.llmCache.size();
@@ -88147,7 +88581,7 @@ var require_openai2 = __commonJS({
88147
88581
  }
88148
88582
  };
88149
88583
  }
88150
- async function queryOpenAI(messages, systemPromptContent, tools, signal, modelProfile, enableThinking, emitChunkEvents) {
88584
+ async function queryOpenAI(messages, systemPromptContent, tools, signal, modelProfile, enableThinking, temperature, emitChunkEvents) {
88151
88585
  const start = Date.now();
88152
88586
  let baseURL = modelProfile.baseURL || "https://api.openai.com/v1";
88153
88587
  const providerEndpoints = (0, providerEndpoint_1.getProviderEndpoints)(modelProfile.provider, baseURL);
@@ -88172,6 +88606,7 @@ var require_openai2 = __commonJS({
88172
88606
  stream: true,
88173
88607
  ...openaiTools && { tools: openaiTools },
88174
88608
  ...(0, adapter_1.useMaxCompletionTokens)(modelProfile.modelName) ? { max_completion_tokens: modelProfile.maxTokens || 8e3 } : { max_tokens: modelProfile.maxTokens || 8e3 },
88609
+ ...temperature !== void 0 && { temperature },
88175
88610
  // thinking 参数按 provider profile 统一构造(openai/openrouter/qwen/compat 等)
88176
88611
  ...(0, providerProfile_1.buildThinkingParams)(modelProfile, enableThinking)
88177
88612
  };
@@ -99381,7 +99816,7 @@ var require_anthropic = __commonJS({
99381
99816
  usage: usage2
99382
99817
  };
99383
99818
  }
99384
- async function queryAnthropic(messages, systemPromptContent, tools, signal, modelProfile, enableThinking, emitChunkEvents) {
99819
+ async function queryAnthropic(messages, systemPromptContent, tools, signal, modelProfile, enableThinking, temperature, emitChunkEvents) {
99385
99820
  const start = Date.now();
99386
99821
  const rawBaseURL = modelProfile.baseURL || "https://api.anthropic.com";
99387
99822
  const providerEndpoints = (0, providerEndpoint_1.getProviderEndpoints)(modelProfile.provider, rawBaseURL);
@@ -99402,7 +99837,7 @@ var require_anthropic = __commonJS({
99402
99837
  messages: anthropicMessages,
99403
99838
  system: systemPromptContent,
99404
99839
  max_tokens: modelProfile.maxTokens,
99405
- temperature: util_1.MAIN_QUERY_TEMPERATURE,
99840
+ ...temperature !== void 0 && { temperature },
99406
99841
  stream: true,
99407
99842
  ...anthropicTools && { tools: anthropicTools }
99408
99843
  };
@@ -99483,7 +99918,8 @@ var require_queryLLM = __commonJS({
99483
99918
  async function queryLLM(messages, systemPromptContent, signal, tools, modelPointer = "main", disableChunkEvents = false, suppressErrorEvent = false) {
99484
99919
  const modelProfile = (0, ModelManager_1.getModelManager)().getModel(modelPointer);
99485
99920
  if (!modelProfile) {
99486
- 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}`);
99487
99923
  }
99488
99924
  try {
99489
99925
  const coreConfig = (0, ConfManager_1.getConfManager)().getCoreConfig();
@@ -99491,30 +99927,31 @@ var require_queryLLM = __commonJS({
99491
99927
  const shouldStream = coreConfig?.stream !== false;
99492
99928
  const enableThinking = modelPointer !== "quick" && coreConfig?.thinking === true;
99493
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 });
99494
99932
  if (shouldUseCache) {
99495
- 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);
99496
99934
  if (cachedResponse) {
99497
99935
  (0, logLLM_1.logLLMRequest)({ cached: true, model: modelProfile.modelName, messages });
99498
99936
  (0, logLLM_1.logLLMResponse)(cachedResponse);
99499
99937
  return cachedResponse;
99500
99938
  }
99501
99939
  }
99502
- const adapt = modelProfile.adapt || (0, adapter_1.resolveAdapter)(modelProfile.provider, modelProfile.modelName);
99503
99940
  let result2;
99504
99941
  switch (adapt) {
99505
99942
  case "anthropic":
99506
- 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);
99507
99944
  break;
99508
99945
  case "openai":
99509
99946
  default:
99510
- 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);
99511
99948
  break;
99512
99949
  }
99513
99950
  (0, logLLM_1.logLLMResponse)(result2);
99514
99951
  if (shouldUseCache && !signal.aborted) {
99515
99952
  const hasContent = result2.message.content.some((block) => block.type === "text" && block.text.trim().length > 0 || block.type === "tool_use");
99516
99953
  if (hasContent) {
99517
- (0, cache_1.setCachedResponse)(messages, systemPromptContent, modelProfile.modelName, result2, enableThinking);
99954
+ (0, cache_1.setCachedResponse)(messages, systemPromptContent, modelProfile.modelName, result2, enableThinking, temperature);
99518
99955
  (0, log_1.logDebug)(`LLM\u54CD\u5E94\u5DF2\u7F13\u5B58\uFF0C\u5F53\u524D\u7F13\u5B58\u6761\u76EE\u6570: ${(0, cache_1.getCacheSize)()}`);
99519
99956
  }
99520
99957
  }
@@ -135411,7 +135848,7 @@ var require_session = __commonJS({
135411
135848
  exports2.parseSessionIdFromHistoryPath = parseSessionIdFromHistoryPath;
135412
135849
  exports2.generateSessionId = generateSessionId;
135413
135850
  exports2.initializeSessionId = initializeSessionId;
135414
- exports2.validateSessionId = validateSessionId;
135851
+ exports2.validateSessionId = validateSessionId2;
135415
135852
  exports2.generateHistoryPath = generateHistoryPath;
135416
135853
  var crypto3 = __importStar(__require("crypto"));
135417
135854
  var path15 = __importStar(__require("path"));
@@ -135446,7 +135883,7 @@ var require_session = __commonJS({
135446
135883
  }
135447
135884
  return generateSessionId();
135448
135885
  }
135449
- function validateSessionId(sessionId) {
135886
+ function validateSessionId2(sessionId) {
135450
135887
  const shortIdRegex = /^[0-9a-f]{8}$/i;
135451
135888
  return shortIdRegex.test(sessionId);
135452
135889
  }
@@ -136392,6 +136829,12 @@ var require_SemaEngine = __commonJS({
136392
136829
  cfg.memoryFiles = partial2.memoryFiles ?? null;
136393
136830
  if ("personaFile" in partial2)
136394
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;
136395
136838
  }
136396
136839
  /**
136397
136840
  * 当前 session 的 coreConfig 只读快照(= initialConfig,含运行时 mutation 结果)。
@@ -136429,7 +136872,7 @@ var require_SemaEngine = __commonJS({
136429
136872
  */
136430
136873
  async initializePlugins(workingDir, extraDirs) {
136431
136874
  try {
136432
- (0, skillRegistry_1.clearSkillRegistry)();
136875
+ (0, skillRegistry_1.invalidateSkillCache)();
136433
136876
  (0, skillRegistry_1.initializeSkillRegistry)(workingDir || process.cwd(), extraDirs);
136434
136877
  (0, log_1.logDebug)("Skill registry initialized successfully");
136435
136878
  } catch (error) {
@@ -136609,6 +137052,11 @@ var require_SemaSession = __commonJS({
136609
137052
  this.engine = new SemaEngine_1.SemaEngine(instanceId, resolvedConfig, this.instanceMCPManager, kernel);
136610
137053
  if (resolvedConfig.skipMCPInit) {
136611
137054
  this.configPromise = (0, ConfManager_1.getConfManager)().registerProjectConfig(resolvedConfig);
137055
+ } else if (resolvedConfig.multiSession) {
137056
+ (0, log_1.setLogLevel)(resolvedConfig.logLevel || "info");
137057
+ this.configPromise = (0, ConfManager_1.getConfManager)().registerProjectConfig(resolvedConfig).then(async () => {
137058
+ await this.instanceMCPManager.init();
137059
+ });
136612
137060
  } else {
136613
137061
  this.configPromise = (0, ConfManager_1.getConfManager)().setCoreConfig(resolvedConfig);
136614
137062
  this.configPromise = this.configPromise.then(async () => {
@@ -136675,26 +137123,34 @@ var require_SemaSession = __commonJS({
136675
137123
  return this.engine.coreConfig;
136676
137124
  }
136677
137125
  // ==================== Skill 热重载(session 触发)====================
137126
+ /** 本 session 的 skill 视图(同 agentsView:显式上下文,ALS 外可读)。 */
137127
+ skillsView() {
137128
+ const config = this.engine["initialConfig"];
137129
+ return {
137130
+ workingDir: config.agentDataDir || config.workingDir || (0, cwd_1.getCwd)(),
137131
+ extraDirs: config.skillsExtraDirs,
137132
+ disabledNames: config.skillsDisabledNames ?? []
137133
+ };
137134
+ }
136678
137135
  /**
136679
137136
  * 热重载 Skill 注册表(不重建 session/历史)。
136680
137137
  *
136681
- * Stage A wrinkle:方法依赖本 session 的 workingDir / skillsExtraDirs,但内部
136682
- * clearSkillRegistry + initializeSkillRegistry mutate 的是【全局】registry,会影响所有
136683
- * session。这是 D6「project 层 vs 全局 registry」矛盾的具象,Stage A 保持现状行为
136684
- * (全局重扫),Stage D 做 global/project 分层 + mtime 缓存时彻底解决。
137138
+ * 注册表按供给键(workingDir + skillsExtraDirs)隔离,只重建本 session 键;屏蔽名单写入
137139
+ * initialConfig.skillsDisabledNames 由读取端过滤(session-api-v1 §3.1,语义同 reloadAgents)。
136685
137140
  *
136686
- * @param disabledNames 需要从注册表中移除的 skill 名称集合。
137141
+ * @param disabledNames 按名屏蔽的 skill 集合;undefined = 只重扫,屏蔽名单不变。
136687
137142
  */
136688
137143
  reloadSkills(disabledNames) {
136689
137144
  const config = this.engine["initialConfig"];
136690
- const workingDir = config.agentDataDir || config.workingDir || (0, cwd_1.getCwd)();
136691
- (0, skillRegistry_1.clearSkillRegistry)();
136692
- const registry = (0, skillRegistry_1.initializeSkillRegistry)(workingDir, config.skillsExtraDirs);
136693
- if (disabledNames?.size) {
136694
- for (const name of disabledNames) {
136695
- registry.delete(name);
136696
- }
136697
- }
137145
+ if (disabledNames !== void 0)
137146
+ config.skillsDisabledNames = [...disabledNames];
137147
+ const view = this.skillsView();
137148
+ (0, skillRegistry_1.invalidateSkillCache)();
137149
+ (0, skillRegistry_1.initializeSkillRegistry)(view.workingDir, view.extraDirs);
137150
+ }
137151
+ /** 本 session 视角的 skills 列表;includeDisabled 取供给全集(harness whitelist 求补用)。 */
137152
+ getSkillsInfo(opts) {
137153
+ return (0, skillRegistry_1.getSkillsInfo)(this.skillsView(), opts);
136698
137154
  }
136699
137155
  // ==================== Agents(session 视角,显式上下文)====================
136700
137156
  /**
@@ -137237,7 +137693,7 @@ var require_AtomixCore = __commonJS({
137237
137693
  exports2.AtomixCore = void 0;
137238
137694
  var SemaKernel_1 = require_SemaKernel();
137239
137695
  var ConfManager_1 = require_ConfManager();
137240
- var AtomixCore3 = class {
137696
+ var AtomixCore4 = class {
137241
137697
  constructor(config) {
137242
137698
  this.setWorkingDir = (newDir) => this.session.setWorkingDir(newDir);
137243
137699
  this.clearWorkingDir = () => this.session.clearWorkingDir();
@@ -137263,6 +137719,10 @@ var require_AtomixCore = __commonJS({
137263
137719
  this.switchModel = (ModelName) => this.kernel.models.switchCurrentModel(ModelName);
137264
137720
  this.applyTaskModel = (config2) => this.kernel.models.applyTaskModelConfig(config2);
137265
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);
137266
137726
  this.updateCoreConfByKey = (key, value) => {
137267
137727
  if (key === "customRules") {
137268
137728
  this.session.updateAssemblyConfig({ customRules: value ?? "" });
@@ -137287,7 +137747,7 @@ var require_AtomixCore = __commonJS({
137287
137747
  this.getMCPServerConfigs = () => this.session.getMCPServerConfigs();
137288
137748
  this.connectMCPServer = (name) => this.session.connectMCPServer(name);
137289
137749
  this.updateMCPUseTools = (name, toolNames) => this.session.updateMCPUseTools(name, toolNames);
137290
- this.getSkillsInfo = () => this.kernel.skills.getInfo();
137750
+ this.getSkillsInfo = (opts) => this.session.getSkillsInfo(opts);
137291
137751
  this.getAgentsInfo = () => this.session.getAgentsInfo();
137292
137752
  this.addAgentConf = (agentConf) => this.session.addAgentConf(agentConf);
137293
137753
  this.getCustomCommands = () => this.session.getCustomCommands();
@@ -137311,7 +137771,7 @@ var require_AtomixCore = __commonJS({
137311
137771
  return this.session.workbenchService;
137312
137772
  }
137313
137773
  };
137314
- exports2.AtomixCore = AtomixCore3;
137774
+ exports2.AtomixCore = AtomixCore4;
137315
137775
  }
137316
137776
  });
137317
137777
 
@@ -143886,7 +144346,7 @@ var require_dist4 = __commonJS({
143886
144346
  "../atomix-core/dist/index.js"(exports2) {
143887
144347
  "use strict";
143888
144348
  Object.defineProperty(exports2, "__esModule", { value: true });
143889
- 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;
143890
144350
  var AtomixCore_1 = require_AtomixCore();
143891
144351
  Object.defineProperty(exports2, "AtomixCore", { enumerable: true, get: function() {
143892
144352
  return AtomixCore_1.AtomixCore;
@@ -143937,6 +144397,31 @@ var require_dist4 = __commonJS({
143937
144397
  Object.defineProperty(exports2, "getModelManager", { enumerable: true, get: function() {
143938
144398
  return ModelManager_1.getModelManager;
143939
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
+ } });
143940
144425
  var log_1 = require_log();
143941
144426
  Object.defineProperty(exports2, "setLogLevel", { enumerable: true, get: function() {
143942
144427
  return log_1.setLogLevel;
@@ -144002,20 +144487,6 @@ var require_dist4 = __commonJS({
144002
144487
  }
144003
144488
  });
144004
144489
 
144005
- // src/paths.ts
144006
- import * as os3 from "os";
144007
- import * as path from "path";
144008
- function getAtomixRoot() {
144009
- const custom = process.env.ATOMIX_ROOT;
144010
- if (custom) return path.resolve(custom);
144011
- return path.join(os3.homedir(), ".atomix");
144012
- }
144013
- var init_paths = __esm({
144014
- "src/paths.ts"() {
144015
- "use strict";
144016
- }
144017
- });
144018
-
144019
144490
  // src/theme.ts
144020
144491
  function getThemeName() {
144021
144492
  return activeThemeName;
@@ -151445,616 +151916,50 @@ var require_dist5 = __commonJS({
151445
151916
  }
151446
151917
  });
151447
151918
 
151448
- // src/agents.ts
151449
- var agents_exports = {};
151450
- __export(agents_exports, {
151451
- agentsCommand: () => agentsCommand,
151452
- applyDisabledAgents: () => applyDisabledAgents,
151453
- disableAgent: () => disableAgent,
151454
- enableAgent: () => enableAgent,
151455
- readDisabledAgents: () => readDisabledAgents
151456
- });
151919
+ // src/memoryPaths.ts
151457
151920
  import * as fs2 from "fs";
151458
151921
  import * as path2 from "path";
151459
- function disabledFile() {
151460
- return path2.join(getAtomixRoot(), "disabled-agents.json");
151461
- }
151462
- function readDisabledAgents() {
151463
- try {
151464
- const parsed = JSON.parse(fs2.readFileSync(disabledFile(), "utf8"));
151465
- if (Array.isArray(parsed.disabled)) return new Set(parsed.disabled);
151466
- } catch {
151467
- }
151468
- return /* @__PURE__ */ new Set();
151469
- }
151470
- function writeDisabledAgents(disabled) {
151471
- fs2.mkdirSync(getAtomixRoot(), { recursive: true });
151472
- fs2.writeFileSync(disabledFile(), JSON.stringify({ disabled: [...disabled].sort() }, null, 2) + "\n");
151473
- }
151474
- function disableAgent(name) {
151475
- const s = readDisabledAgents();
151476
- s.add(name);
151477
- writeDisabledAgents(s);
151478
- }
151479
- function enableAgent(name) {
151480
- const s = readDisabledAgents();
151481
- if (!s.delete(name)) return false;
151482
- writeDisabledAgents(s);
151483
- return true;
151484
- }
151485
- async function applyDisabledAgents(core) {
151486
- await core.reloadAgents(/* @__PURE__ */ new Set());
151487
- const allNames = core.getAgentsInfo().map((a) => a.name);
151488
- recordAgentUniverse(allNames);
151489
- const disabled = /* @__PURE__ */ new Set([...readDisabledAgents(), ...harnessDisabledAgents(allNames)]);
151490
- await core.reloadAgents(disabled);
151491
- }
151492
- async function agentsCommand(core, args) {
151493
- const [sub, ...rest2] = args;
151494
- const name = rest2.join(" ").trim();
151495
- switch (sub) {
151496
- case void 0:
151497
- case "list": {
151498
- const infos = [...core.getAgentsInfo()].sort(
151499
- (a, b) => a.locate.localeCompare(b.locate) || a.name.localeCompare(b.name)
151500
- );
151501
- const disabledSet = readDisabledAgents();
151502
- const lines = infos.filter((a) => !disabledSet.has(a.name)).map((a) => {
151503
- const desc = a.description ? ` \u2014 ${a.description.length > 60 ? a.description.slice(0, 60) + "\u2026" : a.description}` : "";
151504
- return `\u25CF ${a.name} [${a.locate}]${desc}`;
151505
- });
151506
- for (const n of [...disabledSet].sort()) lines.push(`\u25CB ${n} \uFF08\u5DF2\u7981\u7528\uFF09`);
151507
- if (!lines.length) lines.push("\uFF08\u65E0\u53EF\u7528\u4EBA\u8BBE\uFF09");
151508
- 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>`);
151509
- return lines.join("\n ");
151510
- }
151511
- case "disable": {
151512
- if (!name) return "\u7528\u6CD5\uFF1A/agents disable <\u540D\u79F0>";
151513
- disableAgent(name);
151514
- await applyDisabledAgents(core);
151515
- return `\u5DF2\u7981\u7528\u4EBA\u8BBE\uFF1A${name}`;
151516
- }
151517
- case "enable": {
151518
- if (!name) return "\u7528\u6CD5\uFF1A/agents enable <\u540D\u79F0>";
151519
- if (!enableAgent(name)) return `${name} \u672A\u88AB\u7981\u7528`;
151520
- await applyDisabledAgents(core);
151521
- return `\u5DF2\u542F\u7528\u4EBA\u8BBE\uFF1A${name}`;
151522
- }
151523
- default:
151524
- return `\u672A\u77E5\u5B50\u547D\u4EE4\uFF1A${sub}\uFF08\u7528\u6CD5\uFF1A/agents list | enable <\u540D\u79F0> | disable <\u540D\u79F0>\uFF09`;
151525
- }
151526
- }
151527
- var init_agents = __esm({
151528
- "src/agents.ts"() {
151529
- "use strict";
151530
- init_paths();
151531
- init_harness();
151532
- }
151533
- });
151534
-
151535
- // src/harness.ts
151536
- import * as fs3 from "fs";
151537
- import * as path3 from "path";
151538
- function overrideOf(activeValue, baseValue) {
151539
- if (baseValue === void 0 || activeValue === void 0) return null;
151540
- const baseOn = baseValue !== null;
151541
- const activeOn = activeValue !== null;
151542
- return activeOn === baseOn ? null : activeOn ? "on" : "off";
151543
- }
151544
- function personaOverrideOf(activeValue, baseValue) {
151545
- const basic = overrideOf(activeValue, baseValue);
151546
- if (basic !== null) return basic;
151547
- if (activeValue && baseValue && activeValue !== baseValue) return "swap";
151548
- return null;
151549
- }
151550
- function harnessMemoryOverride() {
151551
- return overrideOf(activeMemoryFiles, baseline.memoryFiles);
151552
- }
151553
- function harnessPersonaOverride() {
151554
- return personaOverrideOf(activePersonaFile, baseline.personaFile);
151555
- }
151556
- function getActivePersonaFile() {
151557
- return activePersonaFile;
151558
- }
151559
- function getActiveHarnessName() {
151560
- return active?.name ?? BASE_HARNESS;
151561
- }
151562
- function recordSkillUniverse(names) {
151563
- fullSkillNames = names.slice();
151564
- }
151565
- function recordAgentUniverse(names) {
151566
- fullAgentNames = names.slice();
151567
- }
151568
- function computeDisabledFrom(spec, allNames) {
151569
- if (!spec) return /* @__PURE__ */ new Set();
151570
- return spec.mode === "whitelist" ? new Set(allNames.filter((n) => !spec.enable.includes(n))) : new Set(spec.disable);
151571
- }
151572
- function harnessDisabledSkills(allNames) {
151573
- return computeDisabledFrom(active?.skillsSpec ?? null, allNames);
151574
- }
151575
- function harnessDisabledAgents(allNames) {
151576
- return computeDisabledFrom(active?.agentsSpec ?? null, allNames);
151577
- }
151578
- function libraryDir() {
151579
- return path3.join(getAtomixRoot(), "harness");
151580
- }
151581
- function statePath(cwd2) {
151582
- return path3.join(cwd2, ".atomix", "harness-state.json");
151583
- }
151584
- function readState(cwd2) {
151585
- try {
151586
- const parsed = JSON.parse(fs3.readFileSync(statePath(cwd2), "utf8"));
151587
- return typeof parsed.active === "string" && parsed.active ? parsed.active : BASE_HARNESS;
151588
- } catch {
151589
- return BASE_HARNESS;
151590
- }
151591
- }
151592
- function writeState(cwd2, name) {
151593
- const p = statePath(cwd2);
151594
- if (name === BASE_HARNESS) {
151595
- try {
151596
- fs3.unlinkSync(p);
151597
- } catch {
151598
- }
151599
- return;
151600
- }
151601
- fs3.mkdirSync(path3.dirname(p), { recursive: true });
151602
- fs3.writeFileSync(p, JSON.stringify({ active: name }, null, 2) + "\n");
151603
- }
151604
- function listHarnesses() {
151605
- let names = [];
151606
- try {
151607
- names = fs3.readdirSync(libraryDir(), { withFileTypes: true }).filter((e) => e.isDirectory() && fs3.existsSync(path3.join(libraryDir(), e.name, "harness.yaml"))).map((e) => e.name).sort();
151608
- } catch {
151609
- }
151610
- return [BASE_HARNESS, ...names.filter((n) => n !== BASE_HARNESS)];
151611
- }
151612
- function asStrArr(v) {
151613
- return Array.isArray(v) ? v.filter((x) => typeof x === "string") : [];
151614
- }
151615
- function asMode(v) {
151616
- return v === "whitelist" ? "whitelist" : "blacklist";
151617
- }
151618
- function normalizePromptGroup(raw) {
151619
- const warnings = [];
151620
- if (!raw || typeof raw !== "object") return { overrides: null, warnings };
151621
- const g = raw;
151622
- const meta = new Map(import_atomix_core2.PROMPT_SECTION_CATALOG.map((m) => [m.name, m]));
151623
- const replace2 = {};
151624
- if (g.replace && typeof g.replace === "object") {
151625
- for (const [name, text] of Object.entries(g.replace)) {
151626
- const m = meta.get(name);
151627
- if (!m) {
151628
- warnings.push(`prompt.replace \u672A\u77E5\u6BB5\u540D ${name}(\u53EF\u7528:${[...meta.keys()].join(" / ")})`);
151629
- continue;
151630
- }
151631
- if (m.locked) {
151632
- warnings.push(`prompt.replace \u5FFD\u7565 ${name}:\u5B89\u5168\u6761\u6B3E\u6BB5\u4EE3\u7801\u7EA7\u9501\u5B9A`);
151633
- continue;
151634
- }
151635
- if (m.dynamic) {
151636
- warnings.push(`prompt.replace \u5FFD\u7565 ${name}:\u52A8\u6001\u6BB5(\u6BCF\u8F6E\u91CD\u7B97)\u53EA\u53EF disable`);
151637
- continue;
151638
- }
151639
- if (typeof text !== "string") {
151640
- warnings.push(`prompt.replace.${name} \u975E\u5B57\u7B26\u4E32,\u5FFD\u7565`);
151641
- continue;
151642
- }
151643
- replace2[name] = text;
151644
- }
151645
- }
151646
- const disable = [];
151647
- for (const name of asStrArr(g.disable)) {
151648
- const m = meta.get(name);
151649
- if (!m) {
151650
- warnings.push(`prompt.disable \u672A\u77E5\u6BB5\u540D ${name}`);
151651
- continue;
151652
- }
151653
- if (m.locked) {
151654
- warnings.push(`prompt.disable \u5FFD\u7565 ${name}:\u5B89\u5168\u6761\u6B3E\u6BB5\u4EE3\u7801\u7EA7\u9501\u5B9A`);
151655
- continue;
151656
- }
151657
- disable.push(name);
151658
- }
151659
- const insert = [];
151660
- if (Array.isArray(g.insert)) {
151661
- for (const item of g.insert) {
151662
- if (!item || typeof item !== "object") continue;
151663
- const it = item;
151664
- const name = typeof it.name === "string" ? it.name : "";
151665
- const text = typeof it.text === "string" ? it.text : "";
151666
- if (!name || !text.trim()) {
151667
- warnings.push("prompt.insert \u5FFD\u7565\u7F3A name/text \u7684\u6761\u76EE");
151668
- continue;
151669
- }
151670
- if (meta.has(name)) {
151671
- warnings.push(`prompt.insert \u5FFD\u7565 ${name}:\u4E0E\u5185\u7F6E\u6BB5\u91CD\u540D(\u6539\u5185\u7F6E\u6BB5\u7528 replace)`);
151672
- continue;
151673
- }
151674
- const order = typeof it.order === "number" && Number.isFinite(it.order) ? it.order : 999;
151675
- insert.push({ name, order, text });
151676
- }
151677
- }
151678
- const overrides = {};
151679
- if (Object.keys(replace2).length) overrides.replace = replace2;
151680
- if (disable.length) overrides.disable = disable;
151681
- if (insert.length) overrides.insert = insert;
151682
- return { overrides: Object.keys(overrides).length ? overrides : null, warnings };
151683
- }
151684
- function assertSafeHarnessName(name) {
151685
- if (!name || name === "." || name === ".." || name.includes("/") || name.includes("\\") || path3.basename(name) !== name) {
151686
- throw new Error(`\u975E\u6CD5 harness \u540D\u79F0:${JSON.stringify(name)}`);
151687
- }
151688
- }
151689
- function assertInsideDir(dir, target, what) {
151690
- const rel = path3.relative(dir, target);
151691
- if (rel === ".." || rel.startsWith(`..${path3.sep}`) || path3.isAbsolute(rel)) {
151692
- throw new Error(`${what}\u5FC5\u987B\u4F4D\u4E8E harness \u76EE\u5F55\u5185:${target}`);
151693
- }
151694
- }
151695
- function loadHarnessDoc(name) {
151696
- assertSafeHarnessName(name);
151697
- const dir = path3.join(libraryDir(), name);
151698
- const yamlPath = path3.join(dir, "harness.yaml");
151699
- const raw = import_yaml.default.parse(fs3.readFileSync(yamlPath, "utf8"));
151700
- if (!raw || typeof raw !== "object") throw new Error(`harness.yaml \u4E3A\u7A7A\u6216\u975E\u5BF9\u8C61:${yamlPath}`);
151701
- const t = raw.tools ?? {};
151702
- const sk = raw.skills ?? {};
151703
- const ag = raw.agents ?? {};
151704
- let rulesText = "";
151705
- const rulesFile = typeof raw.rules === "string" ? raw.rules : "rules.md";
151706
- const rulesPath = path3.resolve(dir, rulesFile);
151707
- assertInsideDir(path3.resolve(dir), rulesPath, "rules \u6587\u4EF6");
151708
- let rulesReal = null;
151709
- try {
151710
- rulesReal = fs3.realpathSync(rulesPath);
151711
- } catch {
151712
- }
151713
- if (rulesReal !== null) {
151714
- assertInsideDir(fs3.realpathSync(dir), rulesReal, "rules \u6587\u4EF6(symlink \u89E3\u6790\u540E)");
151715
- rulesText = fs3.readFileSync(rulesReal, "utf8").trim();
151716
- }
151717
- let soulPath = null;
151718
- let soulReal = null;
151719
- try {
151720
- soulReal = fs3.realpathSync(path3.resolve(dir, "SOUL.md"));
151721
- } catch (e) {
151722
- if (e.code !== "ENOENT") throw e;
151723
- }
151724
- if (soulReal !== null) {
151725
- assertInsideDir(fs3.realpathSync(dir), soulReal, "SOUL \u6587\u4EF6(symlink \u89E3\u6790\u540E)");
151726
- const soulStat = fs3.statSync(soulReal);
151727
- if (!soulStat.isFile()) throw new Error(`SOUL.md \u4E0D\u662F\u666E\u901A\u6587\u4EF6:${soulReal}`);
151728
- if (soulStat.nlink > 1) throw new Error(`SOUL.md \u662F\u591A\u786C\u94FE\u63A5\u6587\u4EF6,\u62D2\u7EDD\u52A0\u8F7D:${soulReal}`);
151729
- soulPath = soulReal;
151730
- }
151731
- const promptGroup = normalizePromptGroup(raw.prompt);
151732
- const toggleWarnings = [];
151733
- const parseToggle = (v, key) => {
151734
- if (v === void 0 || v === null) return null;
151735
- if (v === "off" || v === false) return "off";
151736
- if (v === "on" || v === true) return "on";
151737
- toggleWarnings.push(`${key} \u53EA\u8BA4 on/off,\u5FFD\u7565\u975E\u6CD5\u503C ${JSON.stringify(v)}`);
151738
- return null;
151739
- };
151740
- const memory = parseToggle(raw.memory, "memory");
151741
- const persona = parseToggle(raw.persona, "persona");
151742
- return {
151743
- name: typeof raw.name === "string" && raw.name ? raw.name : name,
151744
- description: typeof raw.description === "string" ? raw.description : void 0,
151745
- version: typeof raw.version === "string" ? raw.version : void 0,
151746
- rulesText,
151747
- tools: {
151748
- mode: asMode(t.mode),
151749
- useTools: Array.isArray(t.useTools) ? asStrArr(t.useTools) : null,
151750
- disable: asStrArr(t.disable),
151751
- enable: asStrArr(t.enable),
151752
- defer: asStrArr(t.defer),
151753
- pin: asStrArr(t.pin)
151754
- },
151755
- skills: { mode: asMode(sk.mode), disable: asStrArr(sk.disable), enable: asStrArr(sk.enable) },
151756
- agents: { mode: asMode(ag.mode), disable: asStrArr(ag.disable), enable: asStrArr(ag.enable) },
151757
- prompt: promptGroup.overrides,
151758
- promptWarnings: promptGroup.warnings,
151759
- memory,
151760
- persona,
151761
- soulPath,
151762
- toggleWarnings,
151763
- dir
151764
- };
151765
- }
151766
- function resolveBase(ctx) {
151767
- return {
151768
- name: BASE_HARNESS,
151769
- useTools: ctx.baseline.useTools,
151770
- deferBuiltinTools: ctx.baseline.deferBuiltinTools ?? [],
151771
- pinnedTools: [],
151772
- customRules: "",
151773
- promptOverrides: null,
151774
- memoryFiles: ctx.baseline.memoryFiles,
151775
- personaFile: ctx.baseline.personaFile,
151776
- warnings: [],
151777
- skillsSpec: null,
151778
- agentsSpec: null,
151779
- skillsDisabled: /* @__PURE__ */ new Set(),
151780
- agentsDisabled: /* @__PURE__ */ new Set()
151781
- };
151782
- }
151783
- function resolveHarness(doc, ctx) {
151784
- if (!doc) return resolveBase(ctx);
151785
- let useTools;
151786
- if (doc.tools.mode === "whitelist") {
151787
- useTools = doc.tools.enable.slice();
151788
- } else {
151789
- useTools = doc.tools.useTools ?? ctx.baseline.useTools;
151790
- if (doc.tools.disable.length) {
151791
- const src = useTools ?? ctx.allToolNames;
151792
- const drop2 = new Set(doc.tools.disable);
151793
- useTools = src.filter((n) => !drop2.has(n));
151794
- }
151795
- }
151796
- const warnings = [...doc.promptWarnings, ...doc.toggleWarnings];
151797
- const resolveToggle = (toggle, base, potential, emptyWarning) => {
151798
- if (base === void 0) return void 0;
151799
- if (toggle === "off") return null;
151800
- if (toggle === "on") {
151801
- const p = potential === void 0 ? base : potential;
151802
- if (p === null) {
151803
- warnings.push(emptyWarning);
151804
- return null;
151805
- }
151806
- return p;
151807
- }
151808
- return base;
151809
- };
151810
- const memoryFiles = resolveToggle(
151811
- doc.memory,
151812
- ctx.baseline.memoryFiles,
151813
- ctx.baseline.potentialMemoryFiles,
151814
- "memory: on \u65E0\u8D27\u53EF\u5F00:config.json \u5DF2\u628A global/project \u90FD\u663E\u5F0F\u5173\u6B7B"
151815
- );
151816
- let personaFile;
151817
- if (ctx.baseline.personaFile === void 0) {
151818
- personaFile = void 0;
151819
- } else if (doc.persona === "off") {
151820
- personaFile = null;
151821
- } else if (doc.soulPath) {
151822
- personaFile = doc.soulPath;
151823
- } else {
151824
- 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)");
151825
- personaFile = null;
151826
- }
151827
- return {
151828
- name: doc.name,
151829
- useTools,
151830
- deferBuiltinTools: doc.tools.defer.length ? doc.tools.defer : ctx.baseline.deferBuiltinTools ?? [],
151831
- pinnedTools: doc.tools.pin,
151832
- customRules: doc.rulesText,
151833
- promptOverrides: doc.prompt,
151834
- memoryFiles,
151835
- personaFile,
151836
- warnings,
151837
- skillsSpec: doc.skills,
151838
- agentsSpec: doc.agents,
151839
- skillsDisabled: computeDisabledFrom(doc.skills, ctx.allSkillNames),
151840
- agentsDisabled: computeDisabledFrom(doc.agents, ctx.allAgentNames)
151841
- };
151842
- }
151843
- function buildContext(core) {
151844
- return {
151845
- baseline,
151846
- // 工具:getToolInfos 恒返回内置全集(禁用项带 status),可直读;
151847
- // skill/agent:注册表是已过滤视图,优先用 applyDisabled* 回写的全集缓存,
151848
- // 缓存为空只在启动初始化时(此刻注册表尚未过滤,直读即全集)
151849
- allToolNames: core.getToolInfos().map((t) => t.name),
151850
- allSkillNames: fullSkillNames ?? core.getSkillsInfo().map((s) => s.name),
151851
- allAgentNames: fullAgentNames ?? core.getAgentsInfo().map((a) => a.name)
151852
- };
151853
- }
151854
- function applyAssembly(core, r) {
151855
- core.updateAssemblyConfig({
151856
- useTools: r.useTools,
151857
- deferBuiltinTools: r.deferBuiltinTools,
151858
- pinnedTools: r.pinnedTools,
151859
- customRules: r.customRules,
151860
- promptOverrides: r.promptOverrides,
151861
- // null = 回默认组装(base 清场)
151862
- // 基线未知(宿主没给快照)时不下发该键:传 undefined 会被 core 当 null 落,把供给层开着的注入误关
151863
- ...r.memoryFiles !== void 0 ? { memoryFiles: r.memoryFiles } : {},
151864
- ...r.personaFile !== void 0 ? { personaFile: r.personaFile } : {}
151865
- });
151866
- activeMemoryFiles = r.memoryFiles;
151867
- activePersonaFile = r.personaFile;
151868
- active = r.name === BASE_HARNESS ? null : r;
151869
- }
151870
- function initHarness(core, cwd2, base) {
151871
- baseline = {
151872
- useTools: base.useTools ? [...base.useTools] : null,
151873
- deferBuiltinTools: base.deferBuiltinTools?.slice(),
151874
- memoryFiles: base.memoryFiles,
151875
- personaFile: base.personaFile,
151876
- potentialMemoryFiles: base.potentialMemoryFiles
151877
- };
151878
- activeMemoryFiles = base.memoryFiles;
151879
- activePersonaFile = base.personaFile;
151880
- projectDir = cwd2;
151881
- const name = readState(cwd2);
151882
- if (name === BASE_HARNESS) return null;
151883
- try {
151884
- const doc = loadHarnessDoc(name);
151885
- const r = resolveHarness(doc, buildContext(core));
151886
- applyAssembly(core, r);
151887
- return r.warnings.length ? `harness "${r.name}"(\u6765\u81EA .atomix/harness-state.json)\u5DF2\u52A0\u8F7D:
151888
- \u26A0 ${r.warnings.join("\n \u26A0 ")}` : null;
151889
- } catch (e) {
151890
- return `harness "${name}"(\u6765\u81EA .atomix/harness-state.json)\u52A0\u8F7D\u5931\u8D25,\u5DF2\u56DE\u843D base:${e instanceof Error ? e.message : e}`;
151891
- }
151892
- }
151893
- async function switchTo(core, name) {
151894
- if (!projectDir) throw new Error("harness \u672A\u521D\u59CB\u5316(initHarness \u672A\u8C03\u7528)");
151895
- const ctx = buildContext(core);
151896
- const r = name === BASE_HARNESS ? resolveBase(ctx) : resolveHarness(loadHarnessDoc(name), ctx);
151897
- const wasOn = (v) => v !== null && v !== void 0;
151898
- const memWasOn = wasOn(activeMemoryFiles);
151899
- const personaWas = activePersonaFile;
151900
- applyAssembly(core, r);
151901
- const memNowOn = wasOn(activeMemoryFiles);
151902
- const personaNow = activePersonaFile;
151903
- writeState(projectDir, name);
151904
- const { applyDisabledSkills: applyDisabledSkills2 } = await Promise.resolve().then(() => (init_skills(), skills_exports));
151905
- const { applyDisabledAgents: applyDisabledAgents2 } = await Promise.resolve().then(() => (init_agents(), agents_exports));
151906
- applyDisabledSkills2(core);
151907
- await applyDisabledAgents2(core);
151908
- const warn = r.warnings.length ? "\n \u26A0 " + r.warnings.join("\n \u26A0 ") : "";
151909
- const hints = [];
151910
- 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");
151911
- const pWasOn = wasOn(personaWas);
151912
- const pNowOn = wasOn(personaNow);
151913
- 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");
151914
- 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");
151915
- const hintText = hints.map((h) => `
151916
- ${h}`).join("");
151917
- 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;
151918
- }
151919
- function summarize(r, ctx) {
151920
- const lines = [];
151921
- const base = resolveBase(ctx);
151922
- const baseSet2 = new Set(base.useTools ?? ctx.allToolNames);
151923
- const curSet = new Set(r.useTools ?? ctx.allToolNames);
151924
- const removed = [...baseSet2].filter((n) => !curSet.has(n));
151925
- const added = [...curSet].filter((n) => !baseSet2.has(n));
151926
- 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(", ")})` : ""}`);
151927
- if (r.deferBuiltinTools.length) lines.push(`defer ${r.deferBuiltinTools.join(", ")}`);
151928
- if (r.pinnedTools.length) lines.push(`pin ${r.pinnedTools.join(", ")}`);
151929
- const skillsDisabled = computeDisabledFrom(r.skillsSpec, ctx.allSkillNames);
151930
- const agentsDisabled = computeDisabledFrom(r.agentsSpec, ctx.allAgentNames);
151931
- lines.push(`skill ${skillsDisabled.size ? `\u7981\u7528 ${[...skillsDisabled].join(", ")}` : "\u5168\u90E8\u53EF\u89C1"}`);
151932
- lines.push(`agent ${agentsDisabled.size ? `\u7981\u7528 ${[...agentsDisabled].join(", ")}` : "\u5168\u90E8\u53EF\u89C1"}`);
151933
- lines.push(`\u89C4\u5219\u6BB5 ${r.customRules ? `${r.customRules.split("\n").length} \u884C` : "\u65E0"}`);
151934
- const p = r.promptOverrides;
151935
- const promptDesc = p ? [
151936
- p.replace && Object.keys(p.replace).length ? `\u66FF\u6362 ${Object.keys(p.replace).join(", ")}` : "",
151937
- p.disable?.length ? `\u7981\u7528 ${p.disable.join(", ")}` : "",
151938
- p.insert?.length ? `\u63D2\u5165 ${p.insert.map((i) => i.name).join(", ")}` : ""
151939
- ].filter(Boolean).join(";") : "\u9ED8\u8BA4";
151940
- lines.push(`\u63D0\u793A\u6BB5 ${promptDesc}`);
151941
- const mo = overrideOf(r.memoryFiles, ctx.baseline.memoryFiles);
151942
- if (mo === "off") lines.push("\u8BB0\u5FC6 \u5173(harness memory: off;base \u5F00\u7740,\u5207\u8D70\u5373\u6062\u590D)");
151943
- else if (mo === "on") lines.push("\u8BB0\u5FC6 \u5F00(harness memory: on;base \u5173\u7740,\u5207\u8D70\u5373\u5173)");
151944
- const po = personaOverrideOf(r.personaFile, ctx.baseline.personaFile);
151945
- if (po === "off") lines.push("\u4EBA\u8BBE \u5173(\u672C harness \u65E0\u4EBA\u8BBE;base \u5F00\u7740,\u5207\u8D70\u5373\u6062\u590D)");
151946
- else if (po === "swap") lines.push("\u4EBA\u8BBE \u4E13\u5C5E(harness SOUL.md;\u5207\u8D70\u5373\u56DE base)");
151947
- else if (po === "on") lines.push("\u4EBA\u8BBE \u4E13\u5C5E(harness SOUL.md;base \u5173\u7740,\u5207\u8D70\u5373\u5173)");
151948
- if (r.warnings.length) lines.push(...r.warnings.map((w) => `\u26A0 ${w}`));
151949
- return lines.join("\n ");
151950
- }
151951
- async function harnessCommand(core, args) {
151952
- const [sub, ...rest2] = args;
151953
- const arg = rest2.join(" ").trim() || void 0;
151954
- const names = listHarnesses();
151955
- switch (sub) {
151956
- case void 0:
151957
- case "list": {
151958
- const cur = getActiveHarnessName();
151959
- const lines = names.map((n) => `${n === cur ? "\u25CF" : "\u25CB"} ${n}${n === BASE_HARNESS ? "(\u9ED8\u8BA4\u88C5\u914D)" : ""}`);
151960
- if (sub === void 0 && active) {
151961
- const ctx = buildContext(core);
151962
- lines.unshift(`\u5F53\u524D:${cur}(\u9879\u76EE\u7EA7,${path3.join(".atomix", "harness-state.json")})`, " " + summarize(active, ctx), "");
151963
- } else if (sub === void 0) {
151964
- lines.unshift(`\u5F53\u524D:base(\u9ED8\u8BA4\u88C5\u914D,\u672A\u9009\u62E9 harness)`, "");
151965
- }
151966
- lines.push("", "\u7528\u6CD5:/harness list | use <\u540D\u79F0> | show <\u540D\u79F0> | diff <\u540D\u79F0> | reset");
151967
- lines.push(`\u5E93\u76EE\u5F55:${libraryDir()}(\u6BCF\u4E2A harness \u4E00\u4E2A\u5B50\u76EE\u5F55,\u542B harness.yaml + rules.md)`);
151968
- return lines.join("\n");
151969
- }
151970
- case "use": {
151971
- if (!arg) return "\u7528\u6CD5:/harness use <\u540D\u79F0>";
151972
- if (!names.includes(arg)) return `\u672A\u627E\u5230 harness:${arg}(\u53EF\u7528:${names.join(" / ")})`;
151973
- try {
151974
- return await switchTo(core, arg);
151975
- } catch (e) {
151976
- return `\u5207\u6362\u5931\u8D25:${e instanceof Error ? e.message : e}`;
151977
- }
151978
- }
151979
- case "reset":
151980
- return await switchTo(core, BASE_HARNESS);
151981
- case "show":
151982
- case "diff": {
151983
- if (!arg) return `\u7528\u6CD5:/harness ${sub} <\u540D\u79F0>`;
151984
- if (arg === BASE_HARNESS) return "base = \u9ED8\u8BA4\u88C5\u914D\u57FA\u7EBF,\u65E0\u53D6\u820D\u9879";
151985
- try {
151986
- const ctx = buildContext(core);
151987
- const r = resolveHarness(loadHarnessDoc(arg), ctx);
151988
- return `${r.name}${arg === getActiveHarnessName() ? "(\u5F53\u524D)" : ""}
151989
- ${summarize(r, ctx)}`;
151990
- } catch (e) {
151991
- return `\u8BFB\u53D6\u5931\u8D25:${e instanceof Error ? e.message : e}`;
151992
- }
151993
- }
151994
- default:
151995
- return `\u672A\u77E5\u5B50\u547D\u4EE4:${sub}(\u53EF\u7528:list / use / show / diff / reset)`;
151996
- }
151997
- }
151998
- var import_yaml, import_atomix_core2, BASE_HARNESS, baseline, activeMemoryFiles, activePersonaFile, projectDir, active, fullSkillNames, fullAgentNames;
151999
- var init_harness = __esm({
152000
- "src/harness.ts"() {
152001
- "use strict";
152002
- import_yaml = __toESM(require_dist5());
152003
- import_atomix_core2 = __toESM(require_dist4());
152004
- init_paths();
152005
- BASE_HARNESS = "base";
152006
- baseline = { useTools: null };
152007
- projectDir = null;
152008
- active = null;
152009
- fullSkillNames = null;
152010
- fullAgentNames = null;
152011
- }
152012
- });
152013
-
152014
- // src/memoryPaths.ts
152015
- import * as fs4 from "fs";
152016
- import * as path4 from "path";
152017
151922
  function getMemoryPaths(cwd2) {
152018
151923
  const root2 = realpathOrSelf(getAtomixRoot());
152019
- const slug = (0, import_atomix_core3.projectPathToDirName)(cwd2);
152020
- const projectDir2 = path4.join(root2, "projects", slug);
151924
+ const slug = (0, import_atomix_core2.projectPathToDirName)(cwd2);
151925
+ const projectDir = path2.join(root2, "projects", slug);
152021
151926
  return {
152022
151927
  root: root2,
152023
151928
  slug,
152024
- soul: path4.join(root2, "SOUL.md"),
152025
- globalMemory: path4.join(root2, "MEMORY.md"),
152026
- projectDir: projectDir2,
152027
- projectMemory: path4.join(projectDir2, "MEMORY.md")
151929
+ soul: path2.join(root2, "SOUL.md"),
151930
+ globalMemory: path2.join(root2, "MEMORY.md"),
151931
+ projectDir,
151932
+ projectMemory: path2.join(projectDir, "MEMORY.md")
152028
151933
  };
152029
151934
  }
152030
151935
  function realpathOrSelf(p) {
152031
151936
  try {
152032
- return fs4.realpathSync(p);
151937
+ return fs2.realpathSync(p);
152033
151938
  } catch {
152034
151939
  return p;
152035
151940
  }
152036
151941
  }
152037
- var import_atomix_core3;
151942
+ var import_atomix_core2;
152038
151943
  var init_memoryPaths = __esm({
152039
151944
  "src/memoryPaths.ts"() {
152040
151945
  "use strict";
152041
- import_atomix_core3 = __toESM(require_dist4());
151946
+ import_atomix_core2 = __toESM(require_dist4());
152042
151947
  init_paths();
152043
151948
  }
152044
151949
  });
152045
151950
 
152046
151951
  // src/appConfig.ts
152047
- import * as fs5 from "fs";
152048
- import * as path5 from "path";
151952
+ import * as fs3 from "fs";
151953
+ import * as path3 from "path";
152049
151954
  function configPath() {
152050
- return path5.join(getAtomixRoot(), "config.json");
151955
+ return path3.join(getAtomixRoot(), "config.json");
152051
151956
  }
152052
151957
  function configFilePath() {
152053
151958
  return configPath();
152054
151959
  }
152055
151960
  function readConfig() {
152056
151961
  try {
152057
- return JSON.parse(fs5.readFileSync(configPath(), "utf8"));
151962
+ return JSON.parse(fs3.readFileSync(configPath(), "utf8"));
152058
151963
  } catch {
152059
151964
  return {};
152060
151965
  }
@@ -152062,7 +151967,7 @@ function readConfig() {
152062
151967
  function readConfigForWrite() {
152063
151968
  let text;
152064
151969
  try {
152065
- text = fs5.readFileSync(configPath(), "utf8");
151970
+ text = fs3.readFileSync(configPath(), "utf8");
152066
151971
  } catch (e) {
152067
151972
  if (e.code === "ENOENT") return {};
152068
151973
  throw e;
@@ -152075,8 +151980,8 @@ function readConfigForWrite() {
152075
151980
  }
152076
151981
  function writeConfig(patch) {
152077
151982
  const next = { ...readConfigForWrite(), ...patch };
152078
- fs5.mkdirSync(getAtomixRoot(), { recursive: true });
152079
- 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");
152080
151985
  }
152081
151986
  function applyConfiguredTheme() {
152082
151987
  const name = readConfig().theme;
@@ -152100,7 +152005,7 @@ function buildContextFilesConfig(cwd2, cfg) {
152100
152005
  if (s.memoryGlobal) memoryFiles.push({ path: p.globalMemory, label: "user-level" });
152101
152006
  if (s.memoryProject) {
152102
152007
  try {
152103
- fs5.mkdirSync(p.projectDir, { recursive: true });
152008
+ fs3.mkdirSync(p.projectDir, { recursive: true });
152104
152009
  } catch {
152105
152010
  }
152106
152011
  memoryFiles.push({ path: p.projectMemory, label: "project-level" });
@@ -152116,7 +152021,7 @@ function buildPotentialContextFiles(cwd2, cfg) {
152116
152021
  if (cfg.memory?.global !== false) memoryFiles.push({ path: p.globalMemory, label: "user-level" });
152117
152022
  if (cfg.memory?.project !== false) {
152118
152023
  try {
152119
- fs5.mkdirSync(p.projectDir, { recursive: true });
152024
+ fs3.mkdirSync(p.projectDir, { recursive: true });
152120
152025
  } catch {
152121
152026
  }
152122
152027
  memoryFiles.push({ path: p.projectMemory, label: "project-level" });
@@ -152150,39 +152055,39 @@ var init_appConfig = __esm({
152150
152055
  });
152151
152056
 
152152
152057
  // src/marketplace.ts
152153
- import * as fs6 from "fs";
152058
+ import * as fs4 from "fs";
152154
152059
  import * as os4 from "os";
152155
- import * as path6 from "path";
152060
+ import * as path4 from "path";
152156
152061
  import { randomUUID } from "crypto";
152157
152062
  import { execFile } from "child_process";
152158
152063
  import { promisify } from "util";
152159
152064
  function ownConfigPath() {
152160
- return path6.join(getAtomixRoot(), "marketplace.json");
152065
+ return path4.join(getAtomixRoot(), "marketplace.json");
152161
152066
  }
152162
152067
  function clonesDir() {
152163
- return path6.join(getAtomixRoot(), "marketplace");
152068
+ return path4.join(getAtomixRoot(), "marketplace");
152164
152069
  }
152165
- function statePath2() {
152166
- return path6.join(getAtomixRoot(), "marketplace-state.json");
152070
+ function statePath() {
152071
+ return path4.join(getAtomixRoot(), "marketplace-state.json");
152167
152072
  }
152168
152073
  function initMarketplaceProject(cwd2) {
152169
- activeProjectDir = path6.resolve(cwd2);
152074
+ activeProjectDir = path4.resolve(cwd2);
152170
152075
  if (_instance) _instance.reload();
152171
152076
  }
152172
152077
  function projectStatePath() {
152173
- return activeProjectDir ? path6.join(activeProjectDir, ".atomix", "marketplace-state.json") : null;
152078
+ return activeProjectDir ? path4.join(activeProjectDir, ".atomix", "marketplace-state.json") : null;
152174
152079
  }
152175
152080
  function resolveTilde(p) {
152176
- 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);
152177
152082
  }
152178
152083
  async function cloneOrPull(url, branch, localPath) {
152179
- if (fs6.existsSync(path6.join(localPath, ".git"))) {
152084
+ if (fs4.existsSync(path4.join(localPath, ".git"))) {
152180
152085
  await execFileP("git", ["-C", localPath, "fetch", "origin"], { timeout: 12e4 });
152181
152086
  await execFileP("git", ["-C", localPath, "checkout", branch], { timeout: 3e4 });
152182
152087
  await execFileP("git", ["-C", localPath, "pull", "origin", branch], { timeout: 12e4 });
152183
152088
  } else {
152184
- if (fs6.existsSync(localPath)) fs6.rmSync(localPath, { recursive: true, force: true });
152185
- 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 });
152186
152091
  await execFileP("git", ["clone", "--depth", "1", "--branch", branch, url, localPath], { timeout: 3e5 });
152187
152092
  }
152188
152093
  }
@@ -152190,22 +152095,31 @@ function getMarketplace() {
152190
152095
  if (!_instance) _instance = new Marketplace();
152191
152096
  return _instance;
152192
152097
  }
152098
+ function registerSessionDirs(core, dirs) {
152099
+ sessionRegistry.set(core, dirs);
152100
+ }
152101
+ function unregisterSessionDirs(core) {
152102
+ sessionRegistry.delete(core);
152103
+ }
152104
+ function listSessionDirs() {
152105
+ return [...sessionRegistry.entries()];
152106
+ }
152193
152107
  function buildAgentsExtraDirs() {
152194
- activeAgentsDirs = getMarketplace().getSubagentDirs();
152195
- return activeAgentsDirs;
152108
+ return getMarketplace().getSubagentDirs();
152196
152109
  }
152197
152110
  function refreshAgentsExtraDirs() {
152198
- if (activeAgentsDirs) activeAgentsDirs.splice(0, activeAgentsDirs.length, ...getMarketplace().getSubagentDirs());
152111
+ const fresh = getMarketplace().getSubagentDirs();
152112
+ for (const [, d] of sessionRegistry) d.agents.splice(0, d.agents.length, ...fresh);
152199
152113
  }
152200
152114
  function buildCommandsExtraDirs() {
152201
- activeCommandDirs = getMarketplace().getCommandDirs();
152202
- return activeCommandDirs;
152115
+ return getMarketplace().getCommandDirs();
152203
152116
  }
152204
152117
  function refreshCommandsExtraDirs() {
152205
- if (activeCommandDirs) activeCommandDirs.splice(0, activeCommandDirs.length, ...getMarketplace().getCommandDirs());
152118
+ const fresh = getMarketplace().getCommandDirs();
152119
+ for (const [, d] of sessionRegistry) d.commands.splice(0, d.commands.length, ...fresh);
152206
152120
  }
152207
152121
  function syncMarketplaceMcp() {
152208
- const mcpPath = path6.join(getAtomixRoot(), "mcp.json");
152122
+ const mcpPath = path4.join(getAtomixRoot(), "mcp.json");
152209
152123
  const file = readJson(mcpPath) ?? { mcpServers: {} };
152210
152124
  if (!file.mcpServers || typeof file.mcpServers !== "object") file.mcpServers = {};
152211
152125
  const before2 = JSON.stringify(file.mcpServers);
@@ -152230,13 +152144,13 @@ function syncMarketplaceMcp() {
152230
152144
  }
152231
152145
  const removed = [...localCopies.keys()].filter((k) => !synced.includes(k));
152232
152146
  if (JSON.stringify(file.mcpServers) !== before2) {
152233
- fs6.mkdirSync(getAtomixRoot(), { recursive: true });
152234
- 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");
152235
152149
  }
152236
152150
  return { synced, removed, entries };
152237
152151
  }
152238
152152
  function getEffectiveMcpEntries() {
152239
- const mcpPath = path6.join(getAtomixRoot(), "mcp.json");
152153
+ const mcpPath = path4.join(getAtomixRoot(), "mcp.json");
152240
152154
  const file = readJson(mcpPath);
152241
152155
  const local = file?.mcpServers ?? {};
152242
152156
  return getMarketplace().getMCPServerDefs("effective").map((def) => ({
@@ -152246,17 +152160,17 @@ function getEffectiveMcpEntries() {
152246
152160
  }
152247
152161
  function readJson(p) {
152248
152162
  try {
152249
- return JSON.parse(fs6.readFileSync(p, "utf8"));
152163
+ return JSON.parse(fs4.readFileSync(p, "utf8"));
152250
152164
  } catch {
152251
152165
  return null;
152252
152166
  }
152253
152167
  }
152254
152168
  function listDirs(p) {
152255
152169
  try {
152256
- return fs6.readdirSync(p).filter((e) => {
152170
+ return fs4.readdirSync(p).filter((e) => {
152257
152171
  if (e.startsWith(".")) return false;
152258
152172
  try {
152259
- return fs6.statSync(path6.join(p, e)).isDirectory();
152173
+ return fs4.statSync(path4.join(p, e)).isDirectory();
152260
152174
  } catch {
152261
152175
  return false;
152262
152176
  }
@@ -152266,9 +152180,9 @@ function listDirs(p) {
152266
152180
  }
152267
152181
  }
152268
152182
  function readPluginMCPConfig(pluginDir) {
152269
- const dotMcp = readJson(path6.join(pluginDir, ".mcp.json"));
152183
+ const dotMcp = readJson(path4.join(pluginDir, ".mcp.json"));
152270
152184
  if (dotMcp) return parseDotMcpJson(dotMcp, pluginDir);
152271
- const mcpFile = readJson(path6.join(pluginDir, "mcp", "mcp.json"));
152185
+ const mcpFile = readJson(path4.join(pluginDir, "mcp", "mcp.json"));
152272
152186
  return Array.isArray(mcpFile?.servers) ? mcpFile.servers : [];
152273
152187
  }
152274
152188
  function parseDotMcpJson(data, pluginDir) {
@@ -152300,23 +152214,23 @@ function parseDotMcpJson(data, pluginDir) {
152300
152214
  }
152301
152215
  function countPluginContents(dir) {
152302
152216
  let skillCount = 0;
152303
- const skillsDir = path6.join(dir, "skills");
152217
+ const skillsDir = path4.join(dir, "skills");
152304
152218
  for (const entry of listDirs(skillsDir)) {
152305
- 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++;
152306
152220
  }
152307
152221
  let commandCount = 0;
152308
152222
  try {
152309
- 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;
152310
152224
  } catch {
152311
152225
  }
152312
152226
  return {
152313
152227
  skillCount,
152314
152228
  commandCount,
152315
152229
  mcpServerCount: readPluginMCPConfig(dir).length,
152316
- hasHooks: fs6.existsSync(path6.join(dir, "hooks", "hooks.json"))
152230
+ hasHooks: fs4.existsSync(path4.join(dir, "hooks", "hooks.json"))
152317
152231
  };
152318
152232
  }
152319
- var execFileP, MKT_PREFIX, activeProjectDir, Marketplace, _instance, activeAgentsDirs, activeCommandDirs;
152233
+ var execFileP, MKT_PREFIX, activeProjectDir, Marketplace, _instance, sessionRegistry;
152320
152234
  var init_marketplace = __esm({
152321
152235
  "src/marketplace.ts"() {
152322
152236
  "use strict";
@@ -152337,7 +152251,7 @@ var init_marketplace = __esm({
152337
152251
  reload() {
152338
152252
  this.own = readJson(ownConfigPath()) ?? { sources: [] };
152339
152253
  if (!Array.isArray(this.own.sources)) this.own = { sources: [] };
152340
- this.state = readJson(statePath2()) ?? {};
152254
+ this.state = readJson(statePath()) ?? {};
152341
152255
  const pp = projectStatePath();
152342
152256
  this.projectState = (pp ? readJson(pp) : null) ?? {};
152343
152257
  this.external = [];
@@ -152365,7 +152279,7 @@ var init_marketplace = __esm({
152365
152279
  type: data.type,
152366
152280
  url: data.url,
152367
152281
  branch: data.branch ?? "main",
152368
- localPath: data.type === "git" ? path6.join(clonesDir(), id) : resolveTilde(data.localPath ?? ""),
152282
+ localPath: data.type === "git" ? path4.join(clonesDir(), id) : resolveTilde(data.localPath ?? ""),
152369
152283
  priority: maxPriority + 1,
152370
152284
  enabled: true,
152371
152285
  lastSynced: null
@@ -152399,7 +152313,7 @@ var init_marketplace = __esm({
152399
152313
  this.saveState();
152400
152314
  if (source.type === "git") {
152401
152315
  try {
152402
- fs6.rmSync(path6.join(clonesDir(), source.id), { recursive: true, force: true });
152316
+ fs4.rmSync(path4.join(clonesDir(), source.id), { recursive: true, force: true });
152403
152317
  } catch {
152404
152318
  }
152405
152319
  }
@@ -152468,26 +152382,26 @@ var init_marketplace = __esm({
152468
152382
  /** 插件配置目录优先级:.atomix-plugin > .semaclaw-plugin > .claude-plugin */
152469
152383
  resolvePluginJson(dir) {
152470
152384
  for (const conf of [".atomix-plugin", ".semaclaw-plugin", ".claude-plugin"]) {
152471
- const p = path6.join(dir, conf, "plugin.json");
152472
- if (fs6.existsSync(p)) return p;
152385
+ const p = path4.join(dir, conf, "plugin.json");
152386
+ if (fs4.existsSync(p)) return p;
152473
152387
  }
152474
152388
  return null;
152475
152389
  }
152476
152390
  /** 三种布局:源根即插件 / 平铺插件子目录 / 分组目录再下一层 */
152477
152391
  findPlugins(localPath) {
152478
- if (!fs6.existsSync(localPath)) return [];
152392
+ if (!fs4.existsSync(localPath)) return [];
152479
152393
  const rootJson = this.resolvePluginJson(localPath);
152480
152394
  if (rootJson) return [{ dir: localPath, pluginJsonPath: rootJson }];
152481
152395
  const results = [];
152482
152396
  for (const entry of listDirs(localPath)) {
152483
- const entryPath = path6.join(localPath, entry);
152397
+ const entryPath = path4.join(localPath, entry);
152484
152398
  const pluginJson = this.resolvePluginJson(entryPath);
152485
152399
  if (pluginJson) {
152486
152400
  results.push({ dir: entryPath, pluginJsonPath: pluginJson });
152487
152401
  continue;
152488
152402
  }
152489
152403
  for (const sub of listDirs(entryPath)) {
152490
- const subPath = path6.join(entryPath, sub);
152404
+ const subPath = path4.join(entryPath, sub);
152491
152405
  const subJson = this.resolvePluginJson(subPath);
152492
152406
  if (subJson) results.push({ dir: subPath, pluginJsonPath: subJson });
152493
152407
  }
@@ -152496,7 +152410,7 @@ var init_marketplace = __esm({
152496
152410
  }
152497
152411
  pluginName(def) {
152498
152412
  const meta = readJson(def.pluginJsonPath) ?? {};
152499
- return meta.name || path6.basename(def.dir);
152413
+ return meta.name || path4.basename(def.dir);
152500
152414
  }
152501
152415
  /** 启用的源,按 priority 降序(高优先级源后处理 = 覆盖生效) */
152502
152416
  enabledSourcesByDescPriority() {
@@ -152517,8 +152431,8 @@ var init_marketplace = __esm({
152517
152431
  getSkillExtraDirs() {
152518
152432
  const result2 = [];
152519
152433
  for (const { def } of this.enabledPluginDirs()) {
152520
- const dir = path6.join(def.dir, "skills");
152521
- 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" });
152522
152436
  }
152523
152437
  return result2;
152524
152438
  }
@@ -152526,8 +152440,8 @@ var init_marketplace = __esm({
152526
152440
  getCommandDirs() {
152527
152441
  const result2 = [];
152528
152442
  for (const { def } of this.enabledPluginDirs()) {
152529
- const dir = path6.join(def.dir, "commands");
152530
- if (fs6.existsSync(dir)) result2.push(dir);
152443
+ const dir = path4.join(def.dir, "commands");
152444
+ if (fs4.existsSync(dir)) result2.push(dir);
152531
152445
  }
152532
152446
  return result2;
152533
152447
  }
@@ -152536,8 +152450,8 @@ var init_marketplace = __esm({
152536
152450
  const result2 = [];
152537
152451
  for (const { def } of this.enabledPluginDirs()) {
152538
152452
  for (const dirName of ["subagents", "agents"]) {
152539
- const dir = path6.join(def.dir, dirName);
152540
- if (fs6.existsSync(dir)) result2.push(dir);
152453
+ const dir = path4.join(def.dir, dirName);
152454
+ if (fs4.existsSync(dir)) result2.push(dir);
152541
152455
  }
152542
152456
  }
152543
152457
  return result2;
@@ -152546,8 +152460,8 @@ var init_marketplace = __esm({
152546
152460
  getHookEntries() {
152547
152461
  const result2 = [];
152548
152462
  for (const { def } of this.enabledPluginDirs()) {
152549
- const file = path6.join(def.dir, "hooks", "hooks.json");
152550
- 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 });
152551
152465
  }
152552
152466
  return result2;
152553
152467
  }
@@ -152572,7 +152486,7 @@ var init_marketplace = __esm({
152572
152486
  for (const source of this.getSources()) {
152573
152487
  for (const def of this.findPlugins(source.localPath)) {
152574
152488
  const meta = readJson(def.pluginJsonPath) ?? {};
152575
- const name = meta.name || path6.basename(def.dir);
152489
+ const name = meta.name || path4.basename(def.dir);
152576
152490
  result2.push({
152577
152491
  name,
152578
152492
  description: meta.description ?? "",
@@ -152593,23 +152507,22 @@ var init_marketplace = __esm({
152593
152507
  }
152594
152508
  // ===== 持久化 =====
152595
152509
  saveOwn() {
152596
- fs6.mkdirSync(getAtomixRoot(), { recursive: true });
152597
- 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");
152598
152512
  }
152599
152513
  saveState() {
152600
- fs6.mkdirSync(getAtomixRoot(), { recursive: true });
152601
- 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");
152602
152516
  }
152603
152517
  saveProjectState() {
152604
152518
  const pp = projectStatePath();
152605
152519
  if (!pp) throw new Error("\u9879\u76EE\u7EA7 override \u9700\u8981\u5148 initMarketplaceProject(cwd)");
152606
- fs6.mkdirSync(path6.dirname(pp), { recursive: true });
152607
- 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");
152608
152522
  }
152609
152523
  };
152610
152524
  _instance = null;
152611
- activeAgentsDirs = null;
152612
- activeCommandDirs = null;
152525
+ sessionRegistry = /* @__PURE__ */ new Map();
152613
152526
  }
152614
152527
  });
152615
152528
 
@@ -152624,23 +152537,23 @@ __export(skills_exports, {
152624
152537
  refreshSkillsExtraDirs: () => refreshSkillsExtraDirs,
152625
152538
  skillsCommand: () => skillsCommand
152626
152539
  });
152627
- import * as fs7 from "fs";
152540
+ import * as fs5 from "fs";
152628
152541
  import * as os5 from "os";
152629
- import * as path7 from "path";
152630
- function disabledFile2() {
152631
- return path7.join(getAtomixRoot(), "disabled-skills.json");
152542
+ import * as path5 from "path";
152543
+ function disabledFile() {
152544
+ return path5.join(getAtomixRoot(), "disabled-skills.json");
152632
152545
  }
152633
152546
  function readDisabledSkills() {
152634
152547
  try {
152635
- const parsed = JSON.parse(fs7.readFileSync(disabledFile2(), "utf8"));
152548
+ const parsed = JSON.parse(fs5.readFileSync(disabledFile(), "utf8"));
152636
152549
  if (Array.isArray(parsed.disabled)) return new Set(parsed.disabled);
152637
152550
  } catch {
152638
152551
  }
152639
152552
  return /* @__PURE__ */ new Set();
152640
152553
  }
152641
152554
  function writeDisabledSkills(disabled) {
152642
- fs7.mkdirSync(getAtomixRoot(), { recursive: true });
152643
- 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");
152644
152557
  }
152645
152558
  function disableSkill(name) {
152646
152559
  const s = readDisabledSkills();
@@ -152654,50 +152567,50 @@ function enableSkill(name) {
152654
152567
  return true;
152655
152568
  }
152656
152569
  function resolveTilde2(p) {
152657
- 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);
152658
152571
  }
152659
152572
  function computeSkillsExtraDirs() {
152660
152573
  const eco = readConfig().ecosystem ?? {};
152661
152574
  const dirs = [];
152662
- const claudeSkills = path7.join(os5.homedir(), ".claude", "skills");
152663
- if ((eco.inheritClaudeSkills ?? true) && fs7.existsSync(claudeSkills)) {
152575
+ const claudeSkills = path5.join(os5.homedir(), ".claude", "skills");
152576
+ if ((eco.inheritClaudeSkills ?? true) && fs5.existsSync(claudeSkills)) {
152664
152577
  dirs.push({ dir: claudeSkills, locate: "user" });
152665
152578
  }
152666
- const semaclawHome = process.env.SEMACLAW_CONFIG_HOME ? path7.resolve(process.env.SEMACLAW_CONFIG_HOME) : path7.join(os5.homedir(), ".semaclaw");
152667
- const managedSkills = path7.join(semaclawHome, "managed", "skills");
152668
- 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)) {
152669
152582
  dirs.push({ dir: managedSkills, locate: "managed" });
152670
152583
  }
152671
152584
  for (const d of eco.sharedSkillDirs ?? []) {
152672
152585
  const resolved = resolveTilde2(d);
152673
- if (fs7.existsSync(resolved)) dirs.push({ dir: resolved, locate: "managed" });
152586
+ if (fs5.existsSync(resolved)) dirs.push({ dir: resolved, locate: "managed" });
152674
152587
  }
152675
152588
  dirs.push(...getMarketplace().getSkillExtraDirs());
152676
152589
  return dirs;
152677
152590
  }
152678
152591
  function buildSkillsExtraDirs() {
152679
- activeExtraDirs = computeSkillsExtraDirs();
152680
- return activeExtraDirs;
152592
+ return computeSkillsExtraDirs();
152681
152593
  }
152682
152594
  function refreshSkillsExtraDirs() {
152683
- if (activeExtraDirs) activeExtraDirs.splice(0, activeExtraDirs.length, ...computeSkillsExtraDirs());
152595
+ const fresh = computeSkillsExtraDirs();
152596
+ for (const [, d] of listSessionDirs()) d.skills.splice(0, d.skills.length, ...fresh);
152684
152597
  }
152685
152598
  function applyDisabledSkills(core) {
152686
152599
  core.reloadSkills();
152687
- const allNames = core.getSkillsInfo().map((s) => s.name);
152688
- recordSkillUniverse(allNames);
152689
- const disabled = /* @__PURE__ */ new Set([...readDisabledSkills(), ...harnessDisabledSkills(allNames)]);
152600
+ const allNames = core.getSkillsInfo({ includeDisabled: true }).map((s) => s.name);
152601
+ recordSkillUniverse(core, allNames);
152602
+ const disabled = /* @__PURE__ */ new Set([...readDisabledSkills(), ...harnessDisabledSkills(core, allNames)]);
152690
152603
  core.reloadSkills(disabled);
152691
152604
  }
152692
152605
  function sourceLabel(s) {
152693
152606
  const p = s.filePath ?? "";
152694
- if (p.includes(`${path7.sep}.claude${path7.sep}`)) return "claude";
152695
- if (p.includes(`${path7.sep}.semaclaw${path7.sep}`)) return "semaclaw";
152696
- 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";
152697
152610
  return LOCATE_LABEL[s.locate] ?? s.locate;
152698
152611
  }
152699
152612
  function semaclawConfigHome() {
152700
- 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");
152701
152614
  }
152702
152615
  async function skillsCommand(core, args) {
152703
152616
  const [sub, ...rest2] = args;
@@ -152734,7 +152647,7 @@ async function skillsCommand(core, args) {
152734
152647
  const semaclawDisabled = (() => {
152735
152648
  try {
152736
152649
  const parsed = JSON.parse(
152737
- fs7.readFileSync(path7.join(semaclawConfigHome(), "disabled-skills.json"), "utf8")
152650
+ fs5.readFileSync(path5.join(semaclawConfigHome(), "disabled-skills.json"), "utf8")
152738
152651
  );
152739
152652
  return Array.isArray(parsed.disabled) ? parsed.disabled : [];
152740
152653
  } catch {
@@ -152755,7 +152668,7 @@ async function skillsCommand(core, args) {
152755
152668
  return `\u672A\u77E5\u5B50\u547D\u4EE4\uFF1A${sub}\uFF08\u7528\u6CD5\uFF1A/skills list | enable <\u540D\u79F0> | disable <\u540D\u79F0> | import-disabled\uFF09`;
152756
152669
  }
152757
152670
  }
152758
- var activeExtraDirs, LOCATE_LABEL;
152671
+ var LOCATE_LABEL;
152759
152672
  var init_skills = __esm({
152760
152673
  "src/skills.ts"() {
152761
152674
  "use strict";
@@ -152763,7 +152676,6 @@ var init_skills = __esm({
152763
152676
  init_harness();
152764
152677
  init_appConfig();
152765
152678
  init_marketplace();
152766
- activeExtraDirs = null;
152767
152679
  LOCATE_LABEL = {
152768
152680
  user: "user",
152769
152681
  project: "project",
@@ -152773,6 +152685,905 @@ var init_skills = __esm({
152773
152685
  }
152774
152686
  });
152775
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
+
152776
153587
  // node_modules/react/cjs/react-jsx-runtime.production.min.js
152777
153588
  var require_react_jsx_runtime_production_min = __commonJS({
152778
153589
  "node_modules/react/cjs/react-jsx-runtime.production.min.js"(exports2) {
@@ -159339,26 +160150,6 @@ var import_react20 = __toESM(require_react(), 1);
159339
160150
  // node_modules/ink/build/hooks/use-focus-manager.js
159340
160151
  var import_react21 = __toESM(require_react(), 1);
159341
160152
 
159342
- // src/tui/index.tsx
159343
- var import_atomix_core8 = __toESM(require_dist4());
159344
-
159345
- // src/tools.ts
159346
- var ATOMIX_TOOLS = [
159347
- "Bash",
159348
- "Glob",
159349
- "Grep",
159350
- "Read",
159351
- "Write",
159352
- "Edit",
159353
- "TodoWrite",
159354
- "Skill",
159355
- "AgentTeam",
159356
- "NotebookEdit",
159357
- "AskUser",
159358
- "ToolSearch"
159359
- ];
159360
- var ATOMIX_DEFER_TOOLS = ["NotebookEdit"];
159361
-
159362
160153
  // src/tui/index.tsx
159363
160154
  init_paths();
159364
160155
 
@@ -159382,6 +160173,9 @@ function filterSemaDebugConsole() {
159382
160173
  };
159383
160174
  }
159384
160175
 
160176
+ // src/modelWizard.ts
160177
+ var import_atomix_core5 = __toESM(require_dist4());
160178
+
159385
160179
  // src/ui.ts
159386
160180
  init_theme();
159387
160181
  var wrap3 = (code) => (s) => `\x1B[${code}m${s}\x1B[0m`;
@@ -159558,6 +160352,7 @@ function makeCancellableAsk(rl) {
159558
160352
  }
159559
160353
 
159560
160354
  // src/modelWizard.ts
160355
+ init_harness();
159561
160356
  function modelId(modelName, provider) {
159562
160357
  return `${modelName}[${provider}]`;
159563
160358
  }
@@ -159579,6 +160374,15 @@ async function askPositiveInt(ask, label, def) {
159579
160374
  console.log(red(" \u8BF7\u8F93\u5165\u6B63\u6574\u6570\uFF0C\u6216\u56DE\u8F66\u7528\u9ED8\u8BA4"));
159580
160375
  }
159581
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
+ }
159582
160386
  async function askSelect(ask, label, items, defaultIdx = 0) {
159583
160387
  items.forEach((it, i) => console.log(` ${cyan(String(i + 1))}. ${it}`));
159584
160388
  for (; ; ) {
@@ -159667,9 +160471,16 @@ async function runAddWizard(core, ask) {
159667
160471
  if (limits) console.log(gray(` \u5DF2\u6309\u6A21\u578B\u81EA\u52A8\u8BC6\u522B\u9650\u989D\uFF1AmaxTokens=${defMax} contextLength=${defCtx}`));
159668
160472
  const maxTokens = await askPositiveInt(ask, "maxTokens", defMax);
159669
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
+ }
159670
160481
  console.log(gray(" \u9A8C\u8BC1\u8FDE\u901A\u6027\u5E76\u4FDD\u5B58\u2026"));
159671
160482
  try {
159672
- 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 } : {} });
159673
160484
  } catch (e) {
159674
160485
  console.log(red(` \u6DFB\u52A0\u5931\u8D25\uFF1A${e instanceof Error ? e.message : String(e)}`));
159675
160486
  return false;
@@ -159696,13 +160507,33 @@ async function printModelList(core) {
159696
160507
  console.log(gray(" \uFF08\u65E0\u5DF2\u914D\u7F6E\u6A21\u578B\uFF0C`/model add` \u6DFB\u52A0\uFF09"));
159697
160508
  return;
159698
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
+ };
159699
160519
  for (const name of data.modelList) {
159700
- const marks = [
159701
- name === data.taskConfig?.main ? green("main") : "",
159702
- name === data.taskConfig?.quick ? cyan("quick") : ""
159703
- ].filter(Boolean).join(" ");
159704
- 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 : ""}`);
159705
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);
159706
160537
  }
159707
160538
  async function modelCommand(core, args, ask) {
159708
160539
  const [sub, ...rest2] = args;
@@ -159712,40 +160543,113 @@ async function modelCommand(core, args, ask) {
159712
160543
  case void 0:
159713
160544
  case "list":
159714
160545
  await printModelList(core);
159715
- 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>"));
159716
160547
  break;
159717
160548
  case "add":
159718
160549
  await addModelWizard(core, ask);
159719
160550
  break;
159720
160551
  case "use": {
159721
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
+ }
159722
160557
  const r = await core.switchModel(name);
159723
160558
  console.log(green(` \u2713 \u4E3B\u6A21\u578B \u2192 ${r.taskConfig.main}`));
159724
160559
  break;
159725
160560
  }
159726
160561
  case "quick": {
159727
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
+ }
159728
160567
  const cur = await core.getModelData();
159729
160568
  const r = await core.applyTaskModel({ main: cur.taskConfig.main, quick: name });
159730
160569
  console.log(green(` \u2713 \u5FEB\u901F\u6A21\u578B \u2192 ${r.taskConfig.quick}`));
159731
160570
  break;
159732
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
+ }
159733
160608
  case "del": {
159734
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
+ }
159735
160614
  await core.delModel(name);
159736
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)`));
159737
160618
  break;
159738
160619
  }
159739
160620
  default:
159740
160621
  console.log(bold(` \u672A\u77E5\u5B50\u547D\u4EE4\uFF1A${sub}`));
159741
- 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>"));
159742
160623
  }
159743
160624
  } catch (e) {
159744
160625
  console.log(red(` \u6A21\u578B\u64CD\u4F5C\u5931\u8D25\uFF1A${e instanceof Error ? e.message : String(e)}`));
159745
160626
  }
159746
160627
  }
159747
160628
 
159748
- // src/tui/index.tsx
160629
+ // src/session.ts
160630
+ var import_atomix_core7 = __toESM(require_dist4());
160631
+
160632
+ // src/sessionTypes.ts
160633
+ var SESSION_HANDLE_BRAND = /* @__PURE__ */ Symbol.for("atomix-cli.sessionHandle");
160634
+
160635
+ // src/tools.ts
160636
+ var ATOMIX_TOOLS = [
160637
+ "Bash",
160638
+ "Glob",
160639
+ "Grep",
160640
+ "Read",
160641
+ "Write",
160642
+ "Edit",
160643
+ "TodoWrite",
160644
+ "Skill",
160645
+ "AgentTeam",
160646
+ "NotebookEdit",
160647
+ "AskUser",
160648
+ "ToolSearch"
160649
+ ];
160650
+ var ATOMIX_DEFER_TOOLS = ["NotebookEdit"];
160651
+
160652
+ // src/session.ts
159749
160653
  init_skills();
159750
160654
  init_agents();
159751
160655
  init_harness();
@@ -159820,7 +160724,7 @@ async function mcpCommand(core, args) {
159820
160724
  return lines.join("\n ");
159821
160725
  }
159822
160726
 
159823
- // src/tui/index.tsx
160727
+ // src/session.ts
159824
160728
  init_marketplace();
159825
160729
 
159826
160730
  // src/marketplaceCommand.ts
@@ -159878,6 +160782,19 @@ async function applyMcpHotUpdates(core) {
159878
160782
  }
159879
160783
  return notes;
159880
160784
  }
160785
+ async function refreshRegisteredSessions(invoker) {
160786
+ refreshSkillsExtraDirs();
160787
+ refreshAgentsExtraDirs();
160788
+ refreshCommandsExtraDirs();
160789
+ const cores = new Set(listSessionDirs().map(([c]) => c));
160790
+ if (invoker) cores.add(invoker);
160791
+ for (const c of cores) {
160792
+ applyDisabledSkills(c);
160793
+ await applyDisabledAgents(c).catch(() => {
160794
+ });
160795
+ c.reloadCustomCommands();
160796
+ }
160797
+ }
159881
160798
  async function applyChanges(core, opts) {
159882
160799
  const notes = [];
159883
160800
  const { synced, removed } = syncMarketplaceMcp();
@@ -159885,13 +160802,7 @@ async function applyChanges(core, opts) {
159885
160802
  if (synced.length || removed.length) notes.push(`MCP \u5168\u5C40\u540C\u6B65\uFF1A+${synced.length} \u2212${removed.length}\uFF08\u4E0B\u6B21\u542F\u52A8\u8FDE\u63A5\uFF09`);
159886
160803
  return notes;
159887
160804
  }
159888
- refreshSkillsExtraDirs();
159889
- applyDisabledSkills(core);
159890
- refreshAgentsExtraDirs();
159891
- await applyDisabledAgents(core).catch(() => {
159892
- });
159893
- refreshCommandsExtraDirs();
159894
- core.reloadCustomCommands();
160805
+ await refreshRegisteredSessions(core);
159895
160806
  notes.push(...await applyMcpHotUpdates(core));
159896
160807
  const hooksNow = getMarketplace().getHookEntries().map((h) => h.file).sort();
159897
160808
  const hooksBefore = [...opts?.hooksBefore ?? hooksNow].sort();
@@ -160038,12 +160949,12 @@ async function marketplaceCommand(core, args) {
160038
160949
  }
160039
160950
 
160040
160951
  // src/hooksLoader.ts
160041
- var import_atomix_core4 = __toESM(require_dist4());
160952
+ var import_atomix_core6 = __toESM(require_dist4());
160042
160953
  init_paths();
160043
160954
  init_marketplace();
160044
160955
  import * as fs9 from "fs";
160045
160956
  import * as path9 from "path";
160046
- var VALID_EVENTS = new Set(import_atomix_core4.HOOK_EVENTS);
160957
+ var VALID_EVENTS = new Set(import_atomix_core6.HOOK_EVENTS);
160047
160958
  function readHookFile(p) {
160048
160959
  if (!fs9.existsSync(p)) return null;
160049
160960
  try {
@@ -160104,8 +161015,258 @@ function loadHooks(cwd2) {
160104
161015
  };
160105
161016
  }
160106
161017
 
161018
+ // src/session.ts
161019
+ init_appConfig();
161020
+ function internalHandle(handle) {
161021
+ if (!handle || handle[SESSION_HANDLE_BRAND] !== true) {
161022
+ throw new Error("\u975E\u6CD5\u4F1A\u8BDD\u53E5\u67C4:\u5FC5\u987B\u6765\u81EA createSessionCore()");
161023
+ }
161024
+ return handle;
161025
+ }
161026
+ var MAIN = "main";
161027
+ var DEFAULT_SYSTEM_PROMPT = "You are Atomix, a CLI coding agent bound to the current working directory.";
161028
+ var DEFAULT_SEND_TIMEOUT_MS = 10 * 60 * 1e3;
161029
+ var SESSION_ID_PATTERN = /^[A-Za-z0-9._-]{1,128}$/;
161030
+ function validateSessionId(id) {
161031
+ if (!SESSION_ID_PATTERN.test(id) || id === "." || id === "..") {
161032
+ throw new Error(`\u975E\u6CD5 session id:${JSON.stringify(id)}(\u53EA\u5141\u8BB8 1\u2013128 \u4E2A\u5B57\u6BCD\u3001\u6570\u5B57\u3001\u70B9\u3001\u4E0B\u5212\u7EBF\u3001\u8FDE\u5B57\u7B26)`);
161033
+ }
161034
+ }
161035
+ var preparedCwd = null;
161036
+ function prepareProcess(cwd2) {
161037
+ if (preparedCwd === null) {
161038
+ initMarketplaceProject(cwd2);
161039
+ syncInheritedMcp();
161040
+ syncMarketplaceMcp();
161041
+ preparedCwd = cwd2;
161042
+ return null;
161043
+ }
161044
+ if (preparedCwd !== cwd2) {
161045
+ return `marketplace \u9879\u76EE\u7EA7 override \u4ECD\u7ED1\u5B9A\u9996\u4E2A\u4F1A\u8BDD\u76EE\u5F55 ${preparedCwd}(\u672C\u8FDB\u7A0B\u5185\u591A\u4F1A\u8BDD\u5171\u7528\u4E00\u4E2A\u9879\u76EE\u57DF)`;
161046
+ }
161047
+ return null;
161048
+ }
161049
+ function createSessionCore(opts) {
161050
+ const interactive = opts.interactive ?? false;
161051
+ const permissionMode = opts.permissionMode ?? (interactive ? import_atomix_core7.DEFAULT_PERMISSION_MODE : "free-style");
161052
+ const notes = [];
161053
+ const prepNote = prepareProcess(opts.cwd);
161054
+ if (prepNote) notes.push(prepNote);
161055
+ const appConfig = readConfig();
161056
+ const contextFiles = buildContextFilesConfig(opts.cwd, appConfig);
161057
+ const hookCfg = opts.hooks ?? interactive ? loadHooks(opts.cwd) : {};
161058
+ const dirs = { skills: buildSkillsExtraDirs(), agents: buildAgentsExtraDirs(), commands: buildCommandsExtraDirs() };
161059
+ const core = new import_atomix_core7.AtomixCore({
161060
+ workingDir: opts.cwd,
161061
+ logLevel: opts.logLevel ?? atomixLogLevel(),
161062
+ stream: opts.stream ?? interactive,
161063
+ useTools: ATOMIX_TOOLS,
161064
+ deferBuiltinTools: ATOMIX_DEFER_TOOLS,
161065
+ skillsExtraDirs: dirs.skills,
161066
+ agentsExtraDirs: dirs.agents,
161067
+ commandsExtraDirs: dirs.commands,
161068
+ ...hookCfg,
161069
+ ...contextFiles,
161070
+ permissionMode,
161071
+ // 交互模式下文件编辑必须过权限卡;无人值守靠 permissionMode(free-style 全放行,其余由自动应答器 fail-closed)
161072
+ skipFileEditPermission: false,
161073
+ multiSession: opts.multiSession ?? false,
161074
+ systemPrompt: opts.systemPrompt ?? DEFAULT_SYSTEM_PROMPT
161075
+ });
161076
+ registerSessionDirs(core, dirs);
161077
+ const potential = buildPotentialContextFiles(opts.cwd, appConfig);
161078
+ const baseline = {
161079
+ useTools: ATOMIX_TOOLS,
161080
+ deferBuiltinTools: ATOMIX_DEFER_TOOLS,
161081
+ memoryFiles: contextFiles.memoryFiles,
161082
+ personaFile: contextFiles.personaFile,
161083
+ potentialMemoryFiles: potential.memoryFiles,
161084
+ thinking: false
161085
+ // cli 构造 core 时 thinking 关;harness 未声明即回到这里
161086
+ };
161087
+ return { [SESSION_HANDLE_BRAND]: true, core, cwd: opts.cwd, interactive, permissionMode, appConfig, contextFiles, baseline, notes };
161088
+ }
161089
+ async function discardSessionCore(handle) {
161090
+ const h = internalHandle(handle);
161091
+ unregisterSessionDirs(h.core);
161092
+ await h.core.dispose().catch(() => {
161093
+ });
161094
+ }
161095
+ async function startSession(handle, opts = {}) {
161096
+ const h = internalHandle(handle);
161097
+ const { core, cwd: cwd2 } = h;
161098
+ if (opts.sessionId !== void 0) validateSessionId(opts.sessionId);
161099
+ const notes = [...h.notes];
161100
+ const warn = initHarness(core, cwd2, h.baseline, opts.harness !== void 0 ? { harness: opts.harness } : {});
161101
+ if (warn) notes.push(warn);
161102
+ let ready;
161103
+ const onReady = (d) => {
161104
+ ready = d;
161105
+ };
161106
+ core.once("session:ready", onReady);
161107
+ try {
161108
+ await core.createSession(opts.sessionId);
161109
+ } finally {
161110
+ core.off("session:ready", onReady);
161111
+ }
161112
+ if (!ready) throw new Error("createSession \u5DF2\u8FD4\u56DE\u4F46\u672A\u6536\u5230 session:ready");
161113
+ applyDisabledSkills(core);
161114
+ await applyDisabledAgents(core).catch((e) => {
161115
+ notes.push(`subagent \u542F\u505C\u540D\u5355\u5E94\u7528\u5931\u8D25(harness agent \u53D6\u820D\u53EF\u80FD\u672A\u751F\u6548):${e instanceof Error ? e.message : String(e)}`);
161116
+ });
161117
+ const mcpNotes = await applyMcpHotUpdates(core).catch(() => []);
161118
+ notes.push(...mcpNotes.map((n) => `${n}\uFF08\u9879\u76EE\u7EA7 override\uFF09`));
161119
+ const responder = h.interactive ? null : attachHeadlessResponder(core);
161120
+ return new SessionImpl(h, ready, notes, responder);
161121
+ }
161122
+ function attachHeadlessResponder(core) {
161123
+ const blocked = [];
161124
+ const onPermission = (d) => {
161125
+ blocked.push({ kind: "permission", name: d.toolName, title: d.title, agentId: d.agentId });
161126
+ setImmediate(() => core.respondToToolPermission({ toolName: d.toolName, selected: "refuse", agentId: d.agentId }));
161127
+ };
161128
+ const onQuestion = (d) => {
161129
+ blocked.push({ kind: "question", name: "AskUserQuestion", title: d.questions.map((q) => q.question).join(" / "), agentId: d.agentId });
161130
+ setImmediate(() => core.respondToAskQuestion({ agentId: d.agentId, answers: {} }));
161131
+ };
161132
+ const onForm = (d) => {
161133
+ blocked.push({ kind: "form", name: "FormUI", title: d.title, agentId: d.agentId });
161134
+ setImmediate(() => core.respondToForm({ agentId: d.agentId, values: {}, submitted: false }));
161135
+ };
161136
+ core.on("tool:permission:request", onPermission);
161137
+ core.on("ask:question:request", onQuestion);
161138
+ core.on("form:request", onForm);
161139
+ return {
161140
+ blocked,
161141
+ detach() {
161142
+ core.off("tool:permission:request", onPermission);
161143
+ core.off("ask:question:request", onQuestion);
161144
+ core.off("form:request", onForm);
161145
+ }
161146
+ };
161147
+ }
161148
+ var DISPOSED_ERROR = "session \u5DF2\u91CA\u653E";
161149
+ var SessionImpl = class {
161150
+ constructor(handle, ready, notes, responder) {
161151
+ this.responder = responder;
161152
+ this.core = handle.core;
161153
+ this.cwd = handle.cwd;
161154
+ this.permissionMode = handle.permissionMode;
161155
+ this.ready = ready;
161156
+ this.notes = notes;
161157
+ }
161158
+ responder;
161159
+ core;
161160
+ cwd;
161161
+ permissionMode;
161162
+ ready;
161163
+ notes;
161164
+ queue = Promise.resolve();
161165
+ disposed = false;
161166
+ /** 进行中一轮的强制收尾(dispose 用):以给定错误结束 send 并中断 core */
161167
+ abortCurrent = null;
161168
+ get sessionId() {
161169
+ return this.core.getCurrentSessionId() ?? this.ready.sessionId;
161170
+ }
161171
+ get harness() {
161172
+ return getActiveHarnessName(this.core);
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
+ }
161184
+ on(event, listener) {
161185
+ this.core.on(event, listener);
161186
+ }
161187
+ off(event, listener) {
161188
+ this.core.off(event, listener);
161189
+ }
161190
+ send(input, opts = {}) {
161191
+ if (this.disposed) return Promise.reject(new Error(DISPOSED_ERROR));
161192
+ const run = this.queue.then(() => this.sendNow(input, opts));
161193
+ this.queue = run.catch(() => void 0);
161194
+ return run;
161195
+ }
161196
+ sendNow(input, opts) {
161197
+ if (this.disposed) return Promise.reject(new Error(DISPOSED_ERROR));
161198
+ const core = this.core;
161199
+ const timeoutMs = opts.timeoutMs ?? DEFAULT_SEND_TIMEOUT_MS;
161200
+ const blockedStart = this.responder?.blocked.length ?? 0;
161201
+ return new Promise((resolve9) => {
161202
+ const texts = [];
161203
+ let usage2;
161204
+ let sawProcessing = false;
161205
+ let done = false;
161206
+ const onMessage = (d) => {
161207
+ if (d.agentId === MAIN && d.content.trim()) texts.push(d.content);
161208
+ };
161209
+ const onState = (d) => {
161210
+ if (d.state === "processing") sawProcessing = true;
161211
+ else if (d.state === "idle" && sawProcessing) finish();
161212
+ };
161213
+ const onError = (d) => {
161214
+ finish({ type: d.type, message: d.error?.message ?? d.error?.code ?? "" });
161215
+ };
161216
+ const onUsage = (d) => {
161217
+ if (d.agentId === void 0 || d.agentId === MAIN) usage2 = d.usage;
161218
+ };
161219
+ const interruptWith = (error) => {
161220
+ if (done) return;
161221
+ finish(error);
161222
+ core.interruptSession();
161223
+ };
161224
+ const onAbort = () => interruptWith({ type: "aborted", message: "\u8C03\u7528\u65B9\u4E2D\u6B62" });
161225
+ const timer = setTimeout(() => interruptWith({ type: "timeout", message: `\u8D85\u65F6\uFF08${timeoutMs / 1e3}s\uFF09` }), timeoutMs);
161226
+ const finish = (error) => {
161227
+ if (done) return;
161228
+ done = true;
161229
+ clearTimeout(timer);
161230
+ this.abortCurrent = null;
161231
+ core.off("message:complete", onMessage);
161232
+ core.off("state:update", onState);
161233
+ core.off("session:error", onError);
161234
+ core.off("conversation:usage", onUsage);
161235
+ opts.signal?.removeEventListener("abort", onAbort);
161236
+ resolve9({
161237
+ text: texts[texts.length - 1] ?? "",
161238
+ texts,
161239
+ blocked: this.responder ? this.responder.blocked.slice(blockedStart) : [],
161240
+ usage: usage2,
161241
+ ...error ? { error } : {}
161242
+ });
161243
+ };
161244
+ this.abortCurrent = interruptWith;
161245
+ core.on("message:complete", onMessage);
161246
+ core.on("state:update", onState);
161247
+ core.on("session:error", onError);
161248
+ core.on("conversation:usage", onUsage);
161249
+ if (opts.signal) {
161250
+ if (opts.signal.aborted) return onAbort();
161251
+ opts.signal.addEventListener("abort", onAbort, { once: true });
161252
+ }
161253
+ core.processUserInput(input);
161254
+ });
161255
+ }
161256
+ async dispose() {
161257
+ if (this.disposed) return;
161258
+ this.disposed = true;
161259
+ this.abortCurrent?.({ type: "disposed", message: DISPOSED_ERROR });
161260
+ await this.queue.catch(() => void 0);
161261
+ this.responder?.detach();
161262
+ unregisterSessionDirs(this.core);
161263
+ await this.core.dispose().catch(() => {
161264
+ });
161265
+ }
161266
+ };
161267
+
160107
161268
  // src/resume.ts
160108
- var import_atomix_core5 = __toESM(require_dist4());
161269
+ var import_atomix_core8 = __toESM(require_dist4());
160109
161270
  import * as fs10 from "fs";
160110
161271
  import * as path10 from "path";
160111
161272
  function extractText(content) {
@@ -160124,7 +161285,7 @@ function readMessages(file) {
160124
161285
  }
160125
161286
  }
160126
161287
  function listSessions(cwd2) {
160127
- const dir = (0, import_atomix_core5.getProjectHistoryDir)(cwd2);
161288
+ const dir = (0, import_atomix_core8.getProjectHistoryDir)(cwd2);
160128
161289
  if (!fs10.existsSync(dir)) return [];
160129
161290
  const entries = [];
160130
161291
  for (const f of fs10.readdirSync(dir)) {
@@ -160263,16 +161424,19 @@ function setGlyphMode(mode) {
160263
161424
  return true;
160264
161425
  }
160265
161426
 
161427
+ // src/tui/index.tsx
161428
+ init_harness();
161429
+
160266
161430
  // src/permissionMode.ts
160267
- var import_atomix_core6 = __toESM(require_dist4());
161431
+ var import_atomix_core9 = __toESM(require_dist4());
160268
161432
  var META = {
160269
161433
  "step-by-step": { label: "step by step", hint: "\u6BCF\u4E2A\u654F\u611F\u64CD\u4F5C\u9010\u9879\u786E\u8BA4", tone: "muted" },
160270
161434
  "action-check": { label: "action check", hint: "\u53EA\u8BFB\u64CD\u4F5C\u514D\u786E\u8BA4\uFF0C\u5176\u4F59\u9010\u9879\u786E\u8BA4", tone: "accent" },
160271
161435
  "free-style": { label: "free style", hint: "\u5168\u90E8\u514D\u786E\u8BA4\uFF08\u5B89\u5168\u6821\u9A8C\u4ECD\u751F\u6548\uFF09", tone: "warning" }
160272
161436
  };
160273
- var PERMISSION_MODE_ORDER = import_atomix_core6.PERMISSION_MODES;
161437
+ var PERMISSION_MODE_ORDER = import_atomix_core9.PERMISSION_MODES;
160274
161438
  function permissionModeMeta(mode) {
160275
- return META[mode] ?? META[import_atomix_core6.DEFAULT_PERMISSION_MODE];
161439
+ return META[mode] ?? META[import_atomix_core9.DEFAULT_PERMISSION_MODE];
160276
161440
  }
160277
161441
  function nextPermissionMode(mode) {
160278
161442
  const i = PERMISSION_MODE_ORDER.indexOf(mode);
@@ -160490,7 +161654,7 @@ function windowAroundCursor(chars, cursor, budget, newlineGlyph) {
160490
161654
  }
160491
161655
 
160492
161656
  // src/tui/bridge.ts
160493
- var MAIN = "main";
161657
+ var MAIN2 = "main";
160494
161658
  function estimateItemRows(item, columns) {
160495
161659
  const text = item.kind === "thinking" ? "" : item.kind === "tool" ? `${item.title} ${item.summary ?? ""}` : item.kind === "shell" ? `${item.cmd}
160496
161660
  ${item.body}
@@ -160533,7 +161697,7 @@ var Bridge = class {
160533
161697
  interactions: [],
160534
161698
  sessionId: "",
160535
161699
  thinkingEnabled: false,
160536
- permissionMode: import_atomix_core6.DEFAULT_PERMISSION_MODE,
161700
+ permissionMode: import_atomix_core9.DEFAULT_PERMISSION_MODE,
160537
161701
  modelName: "",
160538
161702
  redrawNonce: 0,
160539
161703
  staticEpoch: 0,
@@ -160592,6 +161756,10 @@ var Bridge = class {
160592
161756
  this.set({ thinkingEnabled: enabled });
160593
161757
  this.core.updateThinking(enabled);
160594
161758
  }
161759
+ /** 只同步 UI 镜像,不碰 core(harness 应用时 core 已由 applyAssembly 下发)。 */
161760
+ syncThinking(enabled) {
161761
+ this.set({ thinkingEnabled: enabled });
161762
+ }
160595
161763
  setModelName(name) {
160596
161764
  this.set({ modelName: name });
160597
161765
  }
@@ -160710,7 +161878,7 @@ var Bridge = class {
160710
161878
  this.set({ streamText: content ?? "" });
160711
161879
  });
160712
161880
  core.on("message:complete", (d) => {
160713
- if (d.agentId !== MAIN) return;
161881
+ if (d.agentId !== MAIN2) return;
160714
161882
  const items = [...this.state.items];
160715
161883
  if (d.reasoning) items.push({ kind: "thinking", chars: d.reasoning.length });
160716
161884
  if (d.content.trim()) items.push({ kind: "assistant", text: d.content });
@@ -160759,7 +161927,7 @@ var Bridge = class {
160759
161927
  core.on("todos:update", (todos) => {
160760
161928
  this.set({ todos: todos ?? [] });
160761
161929
  });
160762
- const isMainEvent = (agentId) => !agentId || agentId === MAIN;
161930
+ const isMainEvent = (agentId) => !agentId || agentId === MAIN2;
160763
161931
  core.on("conversation:usage", (d) => {
160764
161932
  if (isMainEvent(d.agentId)) this.set({ usage: d.usage });
160765
161933
  });
@@ -160790,7 +161958,7 @@ var Bridge = class {
160790
161958
  });
160791
161959
  });
160792
161960
  core.on("session:interrupted", (d) => {
160793
- if (d.agentId === MAIN) this.notice("\u23F9 \u5DF2\u4E2D\u65AD", "warn");
161961
+ if (d.agentId === MAIN2) this.notice("\u23F9 \u5DF2\u4E2D\u65AD", "warn");
160794
161962
  });
160795
161963
  core.on("session:error", (d) => {
160796
161964
  this.notice(`\u4F1A\u8BDD\u9519\u8BEF [${d.type}] ${d.error?.message ?? d.error?.code ?? ""}`, "error");
@@ -161484,9 +162652,9 @@ function SelectList({ options: options2, multi = false, color = theme.accent, on
161484
162652
  winStart > 0 ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(Text, { dimColor: true, children: ` \u2026 \u4E0A\u65B9\u8FD8\u6709 ${winStart} \u9879` }) : null,
161485
162653
  visible.map((o, vi) => {
161486
162654
  const i = winStart + vi;
161487
- const active2 = i === index;
161488
- const mark = multi ? checked.has(i) ? G.radioOn : G.radioOff : active2 ? G.pointer : " ";
161489
- return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(Text, { color: active2 ? color : void 0, dimColor: !active2, children: [
162655
+ const active = i === index;
162656
+ const mark = multi ? checked.has(i) ? G.radioOn : G.radioOff : active ? G.pointer : " ";
162657
+ return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(Text, { color: active ? color : void 0, dimColor: !active, children: [
161490
162658
  ` ${mark} ${i + 1}. ${o.label}`,
161491
162659
  o.hint ? ` ${o.hint}` : ""
161492
162660
  ] }, i);
@@ -161695,7 +162863,7 @@ function PromptCard({
161695
162863
  }
161696
162864
 
161697
162865
  // src/tui/images.ts
161698
- var import_atomix_core7 = __toESM(require_dist4());
162866
+ var import_atomix_core10 = __toESM(require_dist4());
161699
162867
  import { execFile as execFile2 } from "child_process";
161700
162868
  import * as fs13 from "fs";
161701
162869
  import * as os8 from "os";
@@ -161812,7 +162980,7 @@ async function buildUserInput(text, cwd2) {
161812
162980
  if (sources.length === 0) return { input: text, display: text };
161813
162981
  const blocks = [
161814
162982
  { type: "text", text: rewritten },
161815
- ...await Promise.all(sources.map((src) => (0, import_atomix_core7.loadImageAsBlock)(src)))
162983
+ ...await Promise.all(sources.map((src) => (0, import_atomix_core10.loadImageAsBlock)(src)))
161816
162984
  ];
161817
162985
  for (const placeholder of usedPlaceholders) {
161818
162986
  const file = pastedImages.get(placeholder);
@@ -162042,7 +163210,7 @@ function App2({ bridge, cwd: cwd2, initialHistory, appConfig }) {
162042
163210
  }, [bridge]);
162043
163211
  const submittingRef = (0, import_react25.useRef)(false);
162044
163212
  const [submitting, setSubmitting] = (0, import_react25.useState)(false);
162045
- const active2 = s.interactions[0];
163213
+ const active = s.interactions[0];
162046
163214
  const shellKillRef = (0, import_react25.useRef)(null);
162047
163215
  const [shellCmd, setShellCmd] = (0, import_react25.useState)(null);
162048
163216
  use_input_default((input, key) => {
@@ -162137,8 +163305,7 @@ function App2({ bridge, cwd: cwd2, initialHistory, appConfig }) {
162137
163305
  return;
162138
163306
  case "/model": {
162139
163307
  await modelCommand(bridge.core, rest2, bridge.ask);
162140
- const md = await bridge.core.getModelData().catch(() => null);
162141
- if (md) bridge.setModelName(md.taskConfig.main);
163308
+ bridge.setModelName(effectiveModels(bridge.core).main);
162142
163309
  return;
162143
163310
  }
162144
163311
  case "/resume": {
@@ -162177,11 +163344,18 @@ function App2({ bridge, cwd: cwd2, initialHistory, appConfig }) {
162177
163344
  case "/agents":
162178
163345
  bridge.notice(await agentsCommand(bridge.core, rest2));
162179
163346
  return;
162180
- case "/harness":
162181
- 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
+ }
162182
163355
  return;
163356
+ }
162183
163357
  case "/memory":
162184
- bridge.notice(await memoryCommand(cwd2, appConfig, rest2, { harnessMemory: harnessMemoryOverride(), harnessPersona: harnessPersonaOverride(), personaPath: getActivePersonaFile() }));
163358
+ bridge.notice(await memoryCommand(cwd2, appConfig, rest2, { harnessMemory: harnessMemoryOverride(bridge.core), harnessPersona: harnessPersonaOverride(bridge.core), personaPath: getActivePersonaFile(bridge.core) }));
162185
163359
  return;
162186
163360
  case "/mcp":
162187
163361
  bridge.notice(await mcpCommand(bridge.core, rest2));
@@ -162191,18 +163365,21 @@ function App2({ bridge, cwd: cwd2, initialHistory, appConfig }) {
162191
163365
  setSlashCommands(await loadSlashCommands(bridge.core));
162192
163366
  return;
162193
163367
  case "/status": {
162194
- const md = await bridge.core.getModelData().catch(() => null);
163368
+ const modelLine = modelStatusLine(bridge.core);
162195
163369
  bridge.notice(
162196
163370
  [
162197
163371
  `session ${s.sessionId}`,
162198
163372
  `cwd ${cwd2}`,
162199
- `harness ${getActiveHarnessName()}`,
162200
- `memory ${memoryStatusLine(appConfig, { harnessMemory: harnessMemoryOverride(), harnessPersona: harnessPersonaOverride() })}`,
162201
- `model main=${md?.taskConfig.main ?? "-"} quick=${md?.taskConfig.quick ?? "-"}`,
163373
+ `harness ${getActiveHarnessName(bridge.core)}${isHarnessOverridden(bridge.core) ? "\uFF08\u4F1A\u8BDD\u7EA7\u6307\u5B9A\uFF09" : ""}`,
163374
+ `memory ${memoryStatusLine(appConfig, { harnessMemory: harnessMemoryOverride(bridge.core), harnessPersona: harnessPersonaOverride(bridge.core) })}`,
163375
+ `model ${modelLine}`,
163376
+ `temp ${temperatureStatusLine(bridge.core, s.thinkingEnabled)}`,
162202
163377
  `context ${s.usage ? `${s.usage.useTokens} / ${s.usage.maxTokens} tokens` : "-"}`,
162203
- `thinking ${s.thinkingEnabled ? "on" : "off"}`,
163378
+ `thinking ${thinkingStatusLine(bridge.core, s.thinkingEnabled)}`,
162204
163379
  `perms ${permissionModeMeta(s.permissionMode).label}\uFF08${s.permissionMode}\uFF0CShift+Tab \u5207\u6362\uFF09`
162205
- ].join("\n ")
163380
+ ].join("\n "),
163381
+ modelLine.startsWith("\u26A0") ? "warn" : "info"
163382
+ // 模型回落时整条黄色
162206
163383
  );
162207
163384
  return;
162208
163385
  }
@@ -162324,11 +163501,11 @@ function App2({ bridge, cwd: cwd2, initialHistory, appConfig }) {
162324
163501
  /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(Box_default, { flexDirection: "column", width: previewWidth, children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(Text, { children: streamPreview.text }) })
162325
163502
  ] })
162326
163503
  ] }) : null,
162327
- active2?.kind === "permission" ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(PermissionCard, { data: active2.data, respond: active2.respond }) : null,
162328
- active2?.kind === "question" ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(QuestionCard, { data: active2.data, respond: active2.respond }) : null,
162329
- active2?.kind === "form" ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(FormCard, { data: active2.data, respond: active2.respond }) : null,
162330
- active2?.kind === "prompt" ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(PromptCard, { question: active2.question, respond: active2.respond, cancel: active2.cancel }) : null,
162331
- active2?.kind === "select" ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(SelectCard, { question: active2.question, options: active2.options, respond: active2.respond }) : null,
163504
+ active?.kind === "permission" ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(PermissionCard, { data: active.data, respond: active.respond }) : null,
163505
+ active?.kind === "question" ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(QuestionCard, { data: active.data, respond: active.respond }) : null,
163506
+ active?.kind === "form" ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(FormCard, { data: active.data, respond: active.respond }) : null,
163507
+ active?.kind === "prompt" ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(PromptCard, { question: active.question, respond: active.respond, cancel: active.cancel }) : null,
163508
+ active?.kind === "select" ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(SelectCard, { question: active.question, options: active.options, respond: active.respond }) : null,
162332
163509
  showTodos ? /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(Box_default, { flexDirection: "column", marginTop: 1, children: [
162333
163510
  s.todos.slice(0, 6).map((t, i) => {
162334
163511
  const mark = t.status === "completed" ? G.todoDone : t.status === "in_progress" ? G.todoDoing : G.todoPending;
@@ -162349,9 +163526,9 @@ function App2({ bridge, cwd: cwd2, initialHistory, appConfig }) {
162349
163526
  }
162350
163527
  ),
162351
163528
  redrawPulse ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(Text, { children: " " }) : null,
162352
- s.processing && !active2 ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(ProcessingLine, {}) : null,
162353
- shellCmd && !active2 ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(ShellRunningLine, { cmd: shellCmd }) : null,
162354
- !s.processing && !active2 && !submitting ? /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(Box_default, { flexDirection: "column", children: [
163529
+ s.processing && !active ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(ProcessingLine, {}) : null,
163530
+ shellCmd && !active ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(ShellRunningLine, { cmd: shellCmd }) : null,
163531
+ !s.processing && !active && !submitting ? /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(Box_default, { flexDirection: "column", children: [
162355
163532
  /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(Box_default, { borderStyle: G.border, borderColor: theme.muted, paddingX: 1, children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(Box_default, { flexGrow: 1, children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
162356
163533
  LineInput,
162357
163534
  {
@@ -162375,32 +163552,15 @@ function App2({ bridge, cwd: cwd2, initialHistory, appConfig }) {
162375
163552
  // src/tui/index.tsx
162376
163553
  var import_jsx_runtime7 = __toESM(require_jsx_runtime());
162377
163554
  var VERSION2 = "0.1.0";
162378
- async function startTui(cwd2, resumeSessionId) {
163555
+ async function startTui(cwd2, options2 = {}) {
163556
+ const { resumeSessionId } = options2;
162379
163557
  applyConfiguredTheme();
162380
163558
  if (!process.env.ATOMIX_GLYPHS) {
162381
163559
  const mode = configuredGlyphMode();
162382
163560
  if (mode) setGlyphMode(mode);
162383
163561
  }
162384
- initMarketplaceProject(cwd2);
162385
- syncInheritedMcp();
162386
- syncMarketplaceMcp();
162387
- const hookCfg = loadHooks(cwd2);
162388
- const appConfig = readConfig();
162389
- const contextFiles = buildContextFilesConfig(cwd2, appConfig);
162390
- const core = new import_atomix_core8.AtomixCore({
162391
- workingDir: cwd2,
162392
- logLevel: atomixLogLevel(),
162393
- stream: true,
162394
- useTools: ATOMIX_TOOLS,
162395
- deferBuiltinTools: ATOMIX_DEFER_TOOLS,
162396
- skillsExtraDirs: buildSkillsExtraDirs(),
162397
- agentsExtraDirs: buildAgentsExtraDirs(),
162398
- commandsExtraDirs: buildCommandsExtraDirs(),
162399
- ...hookCfg,
162400
- ...contextFiles,
162401
- skipFileEditPermission: false,
162402
- systemPrompt: "You are Atomix, a CLI coding agent bound to the current working directory."
162403
- });
163562
+ const handle = createSessionCore({ cwd: cwd2, interactive: true, permissionMode: options2.permissionMode });
163563
+ const { core, appConfig } = handle;
162404
163564
  {
162405
163565
  const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
162406
163566
  const { ask, dispose } = makeCancellableAsk(rl);
@@ -162413,14 +163573,12 @@ async function startTui(cwd2, resumeSessionId) {
162413
163573
  }
162414
163574
  if (!ok) {
162415
163575
  console.log(gray("\u672A\u5B8C\u6210\u6A21\u578B\u914D\u7F6E\uFF0C\u9000\u51FA\u3002"));
162416
- await core.dispose().catch(() => {
162417
- });
163576
+ await discardSessionCore(handle);
162418
163577
  process.exit(1);
162419
163578
  }
162420
163579
  }
162421
163580
  const bridge = new Bridge(core);
162422
- const md = await core.getModelData();
162423
- bridge.setModelName(md.taskConfig.main);
163581
+ bridge.setModelName(effectiveModels(core).main);
162424
163582
  const accent = paint("accent");
162425
163583
  const muted = paint("muted");
162426
163584
  bridge.notice(
@@ -162428,41 +163586,21 @@ async function startTui(cwd2, resumeSessionId) {
162428
163586
  accent("\u256D\u2500 ") + bold("\u25C6 atomix") + muted(` v${VERSION2}`),
162429
163587
  accent("\u2502 ") + muted(`cwd ${cwd2}`),
162430
163588
  accent("\u2502 ") + muted(`root ${getAtomixRoot()}`),
162431
- accent("\u2502 ") + muted(`model ${md.taskConfig.main}`),
163589
+ accent("\u2502 ") + muted(`model ${effectiveModels(core).main}`),
162432
163590
  accent("\u2570\u2500 ") + muted("/help \u67E5\u770B\u547D\u4EE4")
162433
163591
  ].join("\n")
162434
163592
  );
162435
- let initialHistory = [];
162436
- await new Promise((resolve9, reject2) => {
162437
- core.once("session:ready", (d) => {
162438
- bridge.setSessionId(d.sessionId);
162439
- bridge.setUsage(d.usage);
162440
- initialHistory = [...d.projectInputHistory ?? []];
162441
- resolve9();
162442
- });
162443
- core.createSession(resumeSessionId).catch(reject2);
162444
- }).catch(async (e) => {
163593
+ const session = await startSession(handle, { sessionId: resumeSessionId, harness: options2.harness }).catch(async (e) => {
162445
163594
  console.error(`\u4F1A\u8BDD\u521D\u59CB\u5316\u5931\u8D25\uFF1A${e instanceof Error ? e.message : String(e)}`);
162446
- await core.dispose().catch(() => {
162447
- });
163595
+ await discardSessionCore(handle);
162448
163596
  process.exit(1);
162449
163597
  });
162450
- {
162451
- const potential = buildPotentialContextFiles(cwd2, appConfig);
162452
- const warn = initHarness(core, cwd2, {
162453
- useTools: ATOMIX_TOOLS,
162454
- deferBuiltinTools: ATOMIX_DEFER_TOOLS,
162455
- memoryFiles: contextFiles.memoryFiles,
162456
- personaFile: contextFiles.personaFile,
162457
- potentialMemoryFiles: potential.memoryFiles
162458
- });
162459
- if (warn) console.error(warn);
162460
- }
162461
- applyDisabledSkills(core);
162462
- await applyDisabledAgents(core).catch(() => {
162463
- });
162464
- const mcpNotes = await applyMcpHotUpdates(core).catch(() => []);
162465
- for (const n of mcpNotes) bridge.notice(`${n}\uFF08\u9879\u76EE\u7EA7 override\uFF09`);
163598
+ bridge.setPermissionMode(handle.permissionMode, { silent: true });
163599
+ bridge.setSessionId(session.ready.sessionId);
163600
+ bridge.setUsage(session.ready.usage);
163601
+ bridge.syncThinking(appliedThinking(core) ?? false);
163602
+ const initialHistory = [...session.ready.projectInputHistory ?? []];
163603
+ for (const n of session.notes) bridge.notice(n, n.startsWith("harness") ? "warn" : "info");
162466
163604
  if (resumeSessionId) {
162467
163605
  bridge.seedReplay(loadReplay(cwd2, resumeSessionId));
162468
163606
  }