@atlasharness/atlascode 0.1.65 → 0.1.67

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.
Files changed (2) hide show
  1. package/dist/cli.js +1934 -1727
  2. package/package.json +1 -1
package/dist/cli.js CHANGED
@@ -19862,7 +19862,7 @@ var init_openai = __esm(() => {
19862
19862
  });
19863
19863
 
19864
19864
  // src/modelprovider/constants.ts
19865
- var API_IMAGE_MAX_BASE64_SIZE, IMAGE_TARGET_RAW_SIZE, PDF_TARGET_RAW_SIZE, API_PDF_MAX_PAGES = 100, LLM_TIMEOUT_DEFAULT_MS = 600000, LLM_TIMEOUT_CAP_MS = 1800000, SUMMARIZE_CONNECTOR_TEXT_BETA_HEADER, AFK_MODE_BETA_HEADER;
19865
+ var API_IMAGE_MAX_BASE64_SIZE, IMAGE_TARGET_RAW_SIZE, PDF_TARGET_RAW_SIZE, API_PDF_MAX_PAGES = 100, LLM_TIMEOUT_DEFAULT_MS = 900000, LLM_TIMEOUT_CAP_MS = 1800000, LLM_TIMEOUT_UNIT_WARN_THRESHOLD_MS = 60000, SUMMARIZE_CONNECTOR_TEXT_BETA_HEADER, AFK_MODE_BETA_HEADER;
19866
19866
  var init_constants2 = __esm(() => {
19867
19867
  init_shared();
19868
19868
  API_IMAGE_MAX_BASE64_SIZE = 5 * 1024 * 1024;
@@ -26616,13 +26616,29 @@ function getDefaultEffortForModel(model) {
26616
26616
  }
26617
26617
  return "medium";
26618
26618
  }
26619
+ function setEffortByModelSource(next) {
26620
+ effortByModelSource = next;
26621
+ }
26622
+ function lookupEffortByModel(model) {
26623
+ const map = effortByModelSource?.();
26624
+ if (!map)
26625
+ return;
26626
+ const wanted = model.toLowerCase();
26627
+ for (const [key, level] of Object.entries(map)) {
26628
+ if (key.toLowerCase() === wanted)
26629
+ return level;
26630
+ }
26631
+ return;
26632
+ }
26619
26633
  function resolveAppliedEffort(model, appStateEffortValue) {
26620
26634
  const envOverride = getEffortEnvOverride();
26621
26635
  if (envOverride === null) {
26622
26636
  return;
26623
26637
  }
26624
- return envOverride ?? appStateEffortValue ?? getDefaultEffortForModel(model);
26638
+ const perModelMemory = lookupEffortByModel(model);
26639
+ return envOverride ?? perModelMemory ?? appStateEffortValue ?? getDefaultEffortForModel(model);
26625
26640
  }
26641
+ var effortByModelSource = null;
26626
26642
  var init_effort = __esm(() => {
26627
26643
  init_shared();
26628
26644
  });
@@ -26808,7 +26824,7 @@ async function buildOpenAIParams(args, role = "small", entry, opts) {
26808
26824
  const maxTokens = entry ? args.options?.maxOutputTokensOverride ?? entry.maxTokens : args.options?.maxOutputTokensOverride ?? 8192;
26809
26825
  const temperature = args.options?.temperatureOverride;
26810
26826
  const effortValue = args.options?.effortValue;
26811
- const resolvedEffort = effortValue !== undefined ? resolveAppliedEffort(model, effortValue) : args.thinkingConfig && args.thinkingConfig.type === "enabled" ? mapBudgetToEffort(args.thinkingConfig.budgetTokens) : getDefaultEffortForModel(model);
26827
+ const resolvedEffort = effortValue !== undefined ? resolveAppliedEffort(model, effortValue) : args.thinkingConfig && args.thinkingConfig.type === "enabled" ? mapBudgetToEffort(args.thinkingConfig.budgetTokens) : resolveAppliedEffort(model, undefined);
26812
26828
  const reasoningEffort = resolvedEffort !== undefined ? convertEffortValueToLevel(resolvedEffort) : undefined;
26813
26829
  return {
26814
26830
  model,
@@ -26895,11 +26911,20 @@ function shouldRetryModelError(err, signal) {
26895
26911
  return false;
26896
26912
  return isRetryableError(err);
26897
26913
  }
26914
+ function llmTimeoutUnitHint(ms) {
26915
+ if (!(Number.isFinite(ms) && ms > 0 && ms < LLM_TIMEOUT_UNIT_WARN_THRESHOLD_MS))
26916
+ return;
26917
+ return `⚠ llmTimeoutMs/ATLAS_LLM_TIMEOUT 单位是毫秒,当前 ${ms}ms ≈ ${(ms / 1000).toFixed(1)}s;若按秒填写请 ×1000(如 ${ms}s 应填 ${ms * 1000})`;
26918
+ }
26898
26919
  function llmTimeoutRemediationHint(error, currentTimeoutMs) {
26899
26920
  if (!isClientRequestTimeout(error))
26900
26921
  return null;
26901
- const head = typeof currentTimeoutMs === "number" && currentTimeoutMs > 0 ? `当前超时 ${Math.round(currentTimeoutMs / 1000)}s` : "慢模型长生成可能超过缺省超时";
26902
- return `LLM 请求超时(${head})。可调大:env ATLAS_LLM_TIMEOUT=<毫秒> 或 settings.json llmTimeoutMs 键(上限 ${Math.round(LLM_TIMEOUT_CAP_MS / 60000)}min)。`;
26922
+ const head = typeof currentTimeoutMs === "number" && currentTimeoutMs > 0 ? `当前超时 ${Math.round(currentTimeoutMs / 1000)}s(${currentTimeoutMs}ms)` : "慢模型长生成可能超过缺省超时";
26923
+ const unitNote = "单位=毫秒";
26924
+ const capNote = `上限 ${Math.round(LLM_TIMEOUT_CAP_MS / 60000)}min(${LLM_TIMEOUT_CAP_MS}ms)`;
26925
+ const misconfigNote = llmTimeoutUnitHint(typeof currentTimeoutMs === "number" && currentTimeoutMs > 0 ? currentTimeoutMs : 0);
26926
+ const misconfig = misconfigNote ? ` ${misconfigNote}` : "";
26927
+ return `LLM 请求超时(${head},${unitNote})。可调大:env ATLAS_LLM_TIMEOUT(${unitNote})或 settings.json llmTimeoutMs 键(${capNote})。${misconfig}`.trimEnd();
26903
26928
  }
26904
26929
  function describeEndpointFailure(baseURL) {
26905
26930
  if (!baseURL)
@@ -27848,7 +27873,14 @@ var init_queryWithRoleFallback = __esm(() => {
27848
27873
 
27849
27874
  // src/modelprovider/index.ts
27850
27875
  function getModelProvider() {
27851
- return _provider ??= new OpenAIProvider(3, LLM_TIMEOUT_DEFAULT_MS, () => resolveLlmTimeoutMs(process.env.ATLAS_LLM_TIMEOUT, llmTimeoutSettingsSource?.()));
27876
+ _provider ??= new OpenAIProvider(3, LLM_TIMEOUT_DEFAULT_MS, () => resolveLlmTimeoutMs(process.env.ATLAS_LLM_TIMEOUT, llmTimeoutSettingsSource?.()));
27877
+ if (!_llmTimeoutUnitHintWarned) {
27878
+ _llmTimeoutUnitHintWarned = true;
27879
+ const hint = llmTimeoutUnitHint(resolveLlmTimeoutMs(process.env.ATLAS_LLM_TIMEOUT, llmTimeoutSettingsSource?.()));
27880
+ if (hint)
27881
+ logForDebugging(hint, { level: "warn" });
27882
+ }
27883
+ return _provider;
27852
27884
  }
27853
27885
  function setLlmTimeoutSettingsSource(next) {
27854
27886
  llmTimeoutSettingsSource = next;
@@ -27886,12 +27918,13 @@ function lazyProxy(resolve) {
27886
27918
  }
27887
27919
  });
27888
27920
  }
27889
- var _provider, llmTimeoutSettingsSource = null, modelProvider;
27921
+ var _provider, _llmTimeoutUnitHintWarned = false, llmTimeoutSettingsSource = null, modelProvider;
27890
27922
  var init_modelprovider2 = __esm(() => {
27891
27923
  init_modelprovider();
27892
27924
  init_constants2();
27893
27925
  init_shared();
27894
27926
  init_roles7();
27927
+ init_modelprovider();
27895
27928
  init_constants2();
27896
27929
  init_modelprovider();
27897
27930
  init_types2();
@@ -27999,296 +28032,673 @@ var init_turnRecovery = __esm(() => {
27999
28032
  init_modelprovider2();
28000
28033
  });
28001
28034
 
28002
- // src/engine/goal/goalState.ts
28003
- function armGoal(condition) {
28004
- const trimmed = condition.trim();
28005
- if (trimmed === "") {
28006
- return { ok: false, reason: "Goal condition cannot be empty." };
28007
- }
28008
- if (trimmed.length > MAX_GOAL_CONDITION_CHARS) {
28009
- return {
28010
- ok: false,
28011
- reason: `Goal condition exceeds ${MAX_GOAL_CONDITION_CHARS} characters (got ${trimmed.length}).`
28012
- };
28035
+ // src/engine/session/types.ts
28036
+ function sortLogs(logs) {
28037
+ return logs.sort((a, b) => {
28038
+ const modifiedDiff = b.modified.getTime() - a.modified.getTime();
28039
+ if (modifiedDiff !== 0) {
28040
+ return modifiedDiff;
28041
+ }
28042
+ return b.created.getTime() - a.created.getTime();
28043
+ });
28044
+ }
28045
+
28046
+ // src/engine/session/env.ts
28047
+ import { randomUUID as randomUUID2 } from "crypto";
28048
+ import { homedir as homedir2 } from "os";
28049
+ import { join as join2 } from "path";
28050
+ function setSessionEnv(partial) {
28051
+ _env = { ..._env, ...partial };
28052
+ }
28053
+ function getSessionEnv() {
28054
+ return _env;
28055
+ }
28056
+ function resetSessionEnv() {
28057
+ _env = defaultEnv;
28058
+ }
28059
+ var _sessionId, _originalCwd, _cleanupHandlers, defaultEnv, _env;
28060
+ var init_env = __esm(() => {
28061
+ init_shared();
28062
+ _sessionId = randomUUID2();
28063
+ _originalCwd = process.cwd();
28064
+ _cleanupHandlers = [];
28065
+ defaultEnv = {
28066
+ getSessionId: () => _sessionId,
28067
+ switchSession: (id) => {
28068
+ if (id)
28069
+ _sessionId = id;
28070
+ },
28071
+ getOriginalCwd: () => _originalCwd,
28072
+ getCwd: () => process.cwd(),
28073
+ getProjectsDir: () => join2((process.env.ATLAS_CONFIG_DIR ?? join2(homedir2(), getConfigDirName())).normalize("NFC"), "projects"),
28074
+ registerCleanup: (handler) => {
28075
+ _cleanupHandlers.push(handler);
28076
+ }
28077
+ };
28078
+ _env = defaultEnv;
28079
+ });
28080
+
28081
+ // src/engine/session/paths.ts
28082
+ import { execFile } from "child_process";
28083
+ import { existsSync as existsSync3, readFileSync as readFileSync3, realpathSync as realpathSync3 } from "fs";
28084
+ import { dirname as dirname2, join as join3 } from "path";
28085
+ function getProjectsDir() {
28086
+ return getSessionEnv().getProjectsDir();
28087
+ }
28088
+ function getTranscriptPath() {
28089
+ const projectDir = getProjectDir(getSessionEnv().getOriginalCwd());
28090
+ return join3(projectDir, `${getSessionEnv().getSessionId()}.jsonl`);
28091
+ }
28092
+ function getTranscriptPathForSession(sessionId) {
28093
+ if (sessionId === getSessionEnv().getSessionId()) {
28094
+ return getTranscriptPath();
28013
28095
  }
28014
- goalState = { armed: true, condition: trimmed, paused: false, pausedReason: undefined };
28015
- return { ok: true };
28096
+ const projectDir = getProjectDir(getSessionEnv().getOriginalCwd());
28097
+ return join3(projectDir, `${sessionId}.jsonl`);
28016
28098
  }
28017
- function clearGoal() {
28018
- goalState = { armed: false, condition: undefined, paused: false, pausedReason: undefined };
28099
+ function setAgentTranscriptSubdir(agentId, subdir) {
28100
+ agentTranscriptSubdirs.set(agentId, subdir);
28019
28101
  }
28020
- function pauseGoal(reason) {
28021
- if (!goalState.armed)
28022
- return;
28023
- goalState = { ...goalState, paused: true, pausedReason: reason };
28102
+ function clearAgentTranscriptSubdir(agentId) {
28103
+ agentTranscriptSubdirs.delete(agentId);
28024
28104
  }
28025
- function resumeGoal() {
28026
- if (!goalState.paused)
28027
- return;
28028
- goalState = { ...goalState, paused: false, pausedReason: undefined };
28105
+ function getAgentTranscriptPath(agentId) {
28106
+ const projectDir = getProjectDir(getSessionEnv().getOriginalCwd());
28107
+ const sessionId = getSessionEnv().getSessionId();
28108
+ const subdir = agentTranscriptSubdirs.get(agentId);
28109
+ const base = subdir ? join3(projectDir, sessionId, "subagents", subdir) : join3(projectDir, sessionId, "subagents");
28110
+ return join3(base, `agent-${agentId}.jsonl`);
28029
28111
  }
28030
- function isGoalPaused() {
28031
- return goalState.armed && goalState.paused;
28112
+ function getUserType() {
28113
+ return "atlas";
28032
28114
  }
28033
- function getGoalPausedReason() {
28034
- return goalState.armed && goalState.paused ? goalState.pausedReason : undefined;
28115
+ function getEntrypoint() {
28116
+ return process.env.ATLAS_ENTRYPOINT ?? "cli";
28035
28117
  }
28036
- function goalPausedNotification(reason) {
28037
- return `Goal paused: ${reason}
28038
- The goal will resume when the condition recovers.`;
28118
+ function getGitBranch() {
28119
+ return new Promise((resolve) => {
28120
+ execFile("git", ["rev-parse", "--abbrev-ref", "HEAD"], (err, stdout) => {
28121
+ if (err) {
28122
+ resolve(undefined);
28123
+ return;
28124
+ }
28125
+ const branch = stdout.trim();
28126
+ resolve(branch && branch !== "HEAD" ? branch : undefined);
28127
+ });
28128
+ });
28039
28129
  }
28040
- function isGoalArmed() {
28041
- return goalState.armed;
28130
+ function getVersion2() {
28131
+ return VERSION3;
28042
28132
  }
28043
- function getGoalCondition() {
28044
- return goalState.armed ? goalState.condition : undefined;
28133
+ var _projectDirCache, getProjectDir = (projectDir) => {
28134
+ const cached = _projectDirCache.get(projectDir);
28135
+ if (cached !== undefined)
28136
+ return cached;
28137
+ const normalized = process.platform === "win32" ? projectDir.toLowerCase() : projectDir;
28138
+ const resolved = join3(getSessionEnv().getProjectsDir(), sanitizePath(normalized));
28139
+ _projectDirCache.set(projectDir, resolved);
28140
+ return resolved;
28141
+ }, MAX_TRANSCRIPT_READ_BYTES, agentTranscriptSubdirs, VERSION3;
28142
+ var init_paths = __esm(() => {
28143
+ init_shared();
28144
+ init_env();
28145
+ _projectDirCache = new Map;
28146
+ MAX_TRANSCRIPT_READ_BYTES = 50 * 1024 * 1024;
28147
+ agentTranscriptSubdirs = new Map;
28148
+ VERSION3 = (() => {
28149
+ try {
28150
+ let d = dirname2(realpathSync3(process.argv[1] ?? ""));
28151
+ for (;; ) {
28152
+ const pkgPath = join3(d, "package.json");
28153
+ if (existsSync3(pkgPath)) {
28154
+ const v = JSON.parse(readFileSync3(pkgPath, "utf8")).version;
28155
+ if (typeof v === "string" && v)
28156
+ return v;
28157
+ }
28158
+ const parent = dirname2(d);
28159
+ if (parent === d)
28160
+ break;
28161
+ d = parent;
28162
+ }
28163
+ } catch {}
28164
+ return "0.0.0";
28165
+ })();
28166
+ });
28167
+
28168
+ // src/engine/session/json.ts
28169
+ function parseJSONLBun(data) {
28170
+ const parse = bunJSONLParse;
28171
+ const len = data.length;
28172
+ const result = parse(data);
28173
+ if (!result.error || result.done || result.read >= len) {
28174
+ return result.values;
28175
+ }
28176
+ let values = result.values;
28177
+ let offset = result.read;
28178
+ while (offset < len) {
28179
+ const newlineIndex = typeof data === "string" ? data.indexOf(`
28180
+ `, offset) : data.indexOf(10, offset);
28181
+ if (newlineIndex === -1)
28182
+ break;
28183
+ offset = newlineIndex + 1;
28184
+ const next = parse(data, offset);
28185
+ if (next.values.length > 0) {
28186
+ values = values.concat(next.values);
28187
+ }
28188
+ if (!next.error || next.done || next.read >= len)
28189
+ break;
28190
+ offset = next.read;
28191
+ }
28192
+ return values;
28045
28193
  }
28046
- function getGoalStateForPersistence() {
28047
- return {
28048
- armed: goalState.armed,
28049
- condition: goalState.condition ?? ""
28050
- };
28194
+ function parseJSONLBuffer(buf) {
28195
+ const bufLen = buf.length;
28196
+ let start = 0;
28197
+ if (buf[0] === 239 && buf[1] === 187 && buf[2] === 191) {
28198
+ start = 3;
28199
+ }
28200
+ const results = [];
28201
+ while (start < bufLen) {
28202
+ let end = buf.indexOf(10, start);
28203
+ if (end === -1)
28204
+ end = bufLen;
28205
+ const line = buf.toString("utf8", start, end).trim();
28206
+ start = end + 1;
28207
+ if (!line)
28208
+ continue;
28209
+ try {
28210
+ results.push(JSON.parse(line));
28211
+ } catch {}
28212
+ }
28213
+ return results;
28051
28214
  }
28052
- function restoreGoalState(snapshot) {
28053
- if (snapshot && snapshot.armed && snapshot.condition.trim() !== "") {
28054
- goalState = { armed: true, condition: snapshot.condition.trim(), paused: false, pausedReason: undefined };
28215
+ function parseJSONLString(data) {
28216
+ const stripped = data.startsWith("\uFEFF") ? data.slice(1) : data;
28217
+ const len = stripped.length;
28218
+ let start = 0;
28219
+ const results = [];
28220
+ while (start < len) {
28221
+ let end = stripped.indexOf(`
28222
+ `, start);
28223
+ if (end === -1)
28224
+ end = len;
28225
+ const line = stripped.substring(start, end).trim();
28226
+ start = end + 1;
28227
+ if (!line)
28228
+ continue;
28229
+ try {
28230
+ results.push(JSON.parse(line));
28231
+ } catch {}
28232
+ }
28233
+ return results;
28234
+ }
28235
+ function parseJSONL(data) {
28236
+ if (bunJSONLParse) {
28237
+ return parseJSONLBun(data);
28238
+ }
28239
+ if (typeof data === "string") {
28240
+ return parseJSONLString(data);
28241
+ }
28242
+ return parseJSONLBuffer(data);
28243
+ }
28244
+ function jsonStringify(data, space) {
28245
+ return JSON.stringify(data, undefined, space);
28246
+ }
28247
+ var bunJSONLParse, jsonParse = (text, reviver) => {
28248
+ return typeof reviver === "undefined" ? JSON.parse(text) : JSON.parse(text, reviver);
28249
+ };
28250
+ var init_json = __esm(() => {
28251
+ bunJSONLParse = (() => {
28252
+ if (typeof Bun === "undefined")
28253
+ return false;
28254
+ const b = Bun;
28255
+ const jsonl = b.JSONL;
28256
+ if (!jsonl?.parseChunk)
28257
+ return false;
28258
+ return jsonl.parseChunk;
28259
+ })();
28260
+ });
28261
+
28262
+ // src/engine/session/scanner.ts
28263
+ import { open as fsOpen } from "fs/promises";
28264
+ function compactBoundaryMarker() {
28265
+ return _compactBoundaryMarker ??= Buffer.from('"compact_boundary"');
28266
+ }
28267
+ function parseBoundaryLine(line) {
28268
+ try {
28269
+ const parsed = JSON.parse(line);
28270
+ if (parsed.type !== "system" || parsed.subtype !== "compact_boundary") {
28271
+ return null;
28272
+ }
28273
+ return {
28274
+ hasPreservedSegment: Boolean(parsed.compactMetadata?.preservedSegment)
28275
+ };
28276
+ } catch {
28277
+ return null;
28278
+ }
28279
+ }
28280
+ function sinkWrite(s, src, start, end) {
28281
+ const n = end - start;
28282
+ if (n <= 0)
28283
+ return;
28284
+ if (s.len + n > s.buf.length) {
28285
+ const grown = Buffer.allocUnsafe(Math.min(Math.max(s.buf.length * 2, s.len + n), s.cap));
28286
+ s.buf.copy(grown, 0, 0, s.len);
28287
+ s.buf = grown;
28288
+ }
28289
+ src.copy(s.buf, s.len, start, end);
28290
+ s.len += n;
28291
+ }
28292
+ function hasPrefix(src, prefix, at, end) {
28293
+ return end - at >= prefix.length && src.compare(prefix, 0, prefix.length, at, at + prefix.length) === 0;
28294
+ }
28295
+ function processStraddle(s, chunk, bytesRead) {
28296
+ s.straddleSnapCarryLen = 0;
28297
+ s.straddleSnapTailEnd = 0;
28298
+ if (s.carryLen === 0)
28299
+ return 0;
28300
+ const cb = s.carryBuf;
28301
+ const firstNl = chunk.indexOf(LF);
28302
+ if (firstNl === -1 || firstNl >= bytesRead)
28303
+ return 0;
28304
+ const tailEnd = firstNl + 1;
28305
+ if (hasPrefix(cb, ATTR_SNAP_PREFIX, 0, s.carryLen)) {
28306
+ s.straddleSnapCarryLen = s.carryLen;
28307
+ s.straddleSnapTailEnd = tailEnd;
28308
+ s.lastSnapSrc = null;
28309
+ } else if (s.carryLen < ATTR_SNAP_PREFIX.length) {
28310
+ return 0;
28055
28311
  } else {
28056
- goalState = { armed: false, condition: undefined, paused: false, pausedReason: undefined };
28312
+ if (hasPrefix(cb, SYSTEM_PREFIX, 0, s.carryLen)) {
28313
+ const hit = parseBoundaryLine(cb.toString("utf-8", 0, s.carryLen) + chunk.toString("utf-8", 0, firstNl));
28314
+ if (hit?.hasPreservedSegment) {
28315
+ s.hasPreservedSegment = true;
28316
+ } else if (hit) {
28317
+ s.out.len = 0;
28318
+ s.boundaryStartOffset = s.bufFileOff;
28319
+ s.hasPreservedSegment = false;
28320
+ s.lastSnapSrc = null;
28321
+ }
28322
+ }
28323
+ sinkWrite(s.out, cb, 0, s.carryLen);
28324
+ sinkWrite(s.out, chunk, 0, tailEnd);
28057
28325
  }
28326
+ s.bufFileOff += s.carryLen + tailEnd;
28327
+ s.carryLen = 0;
28328
+ return tailEnd;
28058
28329
  }
28059
- function resetGoalStateForTesting() {
28060
- goalState = { armed: false, condition: undefined, paused: false, pausedReason: undefined };
28330
+ function scanChunkLines(s, buf, boundaryMarker) {
28331
+ let boundaryAt = buf.indexOf(boundaryMarker);
28332
+ let runStart = 0;
28333
+ let lineStart = 0;
28334
+ let lastSnapStart = -1;
28335
+ let lastSnapEnd = -1;
28336
+ let nl = buf.indexOf(LF);
28337
+ while (nl !== -1) {
28338
+ const lineEnd = nl + 1;
28339
+ if (boundaryAt !== -1 && boundaryAt < lineStart) {
28340
+ boundaryAt = buf.indexOf(boundaryMarker, lineStart);
28341
+ }
28342
+ if (hasPrefix(buf, ATTR_SNAP_PREFIX, lineStart, lineEnd)) {
28343
+ sinkWrite(s.out, buf, runStart, lineStart);
28344
+ lastSnapStart = lineStart;
28345
+ lastSnapEnd = lineEnd;
28346
+ runStart = lineEnd;
28347
+ } else if (boundaryAt >= lineStart && boundaryAt < Math.min(lineStart + BOUNDARY_SEARCH_BOUND, lineEnd)) {
28348
+ const hit = parseBoundaryLine(buf.toString("utf-8", lineStart, nl));
28349
+ if (hit?.hasPreservedSegment) {
28350
+ s.hasPreservedSegment = true;
28351
+ } else if (hit) {
28352
+ s.out.len = 0;
28353
+ s.boundaryStartOffset = s.bufFileOff + lineStart;
28354
+ s.hasPreservedSegment = false;
28355
+ s.lastSnapSrc = null;
28356
+ lastSnapStart = -1;
28357
+ s.straddleSnapCarryLen = 0;
28358
+ runStart = lineStart;
28359
+ }
28360
+ boundaryAt = buf.indexOf(boundaryMarker, boundaryAt + boundaryMarker.length);
28361
+ }
28362
+ lineStart = lineEnd;
28363
+ nl = buf.indexOf(LF, lineStart);
28364
+ }
28365
+ sinkWrite(s.out, buf, runStart, lineStart);
28366
+ return { lastSnapStart, lastSnapEnd, trailStart: lineStart };
28061
28367
  }
28062
- function classifyGoalError(err) {
28063
- const msg = (err instanceof Error ? err.message : String(err ?? "")).toLowerCase();
28064
- if (/\b401\b/.test(msg) || /\b403\b/.test(msg) || msg.includes("unauthorized") || msg.includes("forbidden")) {
28065
- return "unrecoverable";
28368
+ function captureSnap(s, buf, chunk, lastSnapStart, lastSnapEnd) {
28369
+ if (lastSnapStart !== -1) {
28370
+ s.lastSnapLen = lastSnapEnd - lastSnapStart;
28371
+ if (s.lastSnapBuf === undefined || s.lastSnapLen > s.lastSnapBuf.length) {
28372
+ s.lastSnapBuf = Buffer.allocUnsafe(s.lastSnapLen);
28373
+ }
28374
+ buf.copy(s.lastSnapBuf, 0, lastSnapStart, lastSnapEnd);
28375
+ s.lastSnapSrc = s.lastSnapBuf;
28376
+ } else if (s.straddleSnapCarryLen > 0) {
28377
+ s.lastSnapLen = s.straddleSnapCarryLen + s.straddleSnapTailEnd;
28378
+ if (s.lastSnapBuf === undefined || s.lastSnapLen > s.lastSnapBuf.length) {
28379
+ s.lastSnapBuf = Buffer.allocUnsafe(s.lastSnapLen);
28380
+ }
28381
+ s.carryBuf.copy(s.lastSnapBuf, 0, 0, s.straddleSnapCarryLen);
28382
+ chunk.copy(s.lastSnapBuf, s.straddleSnapCarryLen, 0, s.straddleSnapTailEnd);
28383
+ s.lastSnapSrc = s.lastSnapBuf;
28066
28384
  }
28067
- if (msg.includes("context length exceeded") || msg.includes("prompt too long") || msg.includes("context window")) {
28068
- return "unrecoverable";
28385
+ }
28386
+ function captureCarry(s, buf, trailStart) {
28387
+ s.carryLen = buf.length - trailStart;
28388
+ if (s.carryLen > 0) {
28389
+ if (s.carryBuf === undefined || s.carryLen > s.carryBuf.length) {
28390
+ s.carryBuf = Buffer.allocUnsafe(s.carryLen);
28391
+ }
28392
+ buf.copy(s.carryBuf, 0, trailStart, buf.length);
28069
28393
  }
28070
- return "recoverable";
28071
28394
  }
28072
- function goalUnrecoverableNotification(reason) {
28073
- return `Goal cleared (unrecoverable): ${reason}
28074
- The goal can no longer be pursued. Set a new goal if needed.`;
28395
+ function finalizeOutput(s) {
28396
+ if (s.carryLen > 0) {
28397
+ const cb = s.carryBuf;
28398
+ if (hasPrefix(cb, ATTR_SNAP_PREFIX, 0, s.carryLen)) {
28399
+ s.lastSnapSrc = cb;
28400
+ s.lastSnapLen = s.carryLen;
28401
+ } else {
28402
+ sinkWrite(s.out, cb, 0, s.carryLen);
28403
+ }
28404
+ }
28405
+ if (s.lastSnapSrc) {
28406
+ if (s.out.len > 0 && s.out.buf[s.out.len - 1] !== LF) {
28407
+ sinkWrite(s.out, LF_BYTE, 0, 1);
28408
+ }
28409
+ sinkWrite(s.out, s.lastSnapSrc, 0, s.lastSnapLen);
28410
+ }
28075
28411
  }
28076
- function extractConversationEvidence(messages, maxMessages = 12) {
28077
- const recent = messages.slice(-maxMessages);
28078
- const lines = [];
28079
- for (const m of recent) {
28080
- if (m.type === "user" || m.type === "assistant") {
28081
- const content = m.message?.content;
28082
- if (typeof content === "string") {
28083
- lines.push(`[${m.type}] ${content}`);
28084
- } else if (Array.isArray(content)) {
28085
- const text = content.filter((b) => typeof b === "object" && b !== null && b.type === "text").map((b) => b.text ?? "").join(" ");
28086
- if (text)
28087
- lines.push(`[${m.type}] ${text}`);
28412
+ async function readTranscriptForLoad(filePath, fileSize) {
28413
+ const boundaryMarker = compactBoundaryMarker();
28414
+ const CHUNK_SIZE = TRANSCRIPT_READ_CHUNK_SIZE;
28415
+ const s = {
28416
+ out: {
28417
+ buf: Buffer.allocUnsafe(Math.min(fileSize, 8 * 1024 * 1024)),
28418
+ len: 0,
28419
+ cap: fileSize + 1
28420
+ },
28421
+ boundaryStartOffset: 0,
28422
+ hasPreservedSegment: false,
28423
+ lastSnapSrc: null,
28424
+ lastSnapLen: 0,
28425
+ lastSnapBuf: undefined,
28426
+ bufFileOff: 0,
28427
+ carryLen: 0,
28428
+ carryBuf: undefined,
28429
+ straddleSnapCarryLen: 0,
28430
+ straddleSnapTailEnd: 0
28431
+ };
28432
+ const chunk = Buffer.allocUnsafe(CHUNK_SIZE);
28433
+ const fd = await fsOpen(filePath, "r");
28434
+ try {
28435
+ let filePos = 0;
28436
+ while (filePos < fileSize) {
28437
+ const { bytesRead } = await fd.read(chunk, 0, Math.min(CHUNK_SIZE, fileSize - filePos), filePos);
28438
+ if (bytesRead === 0)
28439
+ break;
28440
+ filePos += bytesRead;
28441
+ const chunkOff = processStraddle(s, chunk, bytesRead);
28442
+ let buf;
28443
+ if (s.carryLen > 0) {
28444
+ const bufLen = s.carryLen + (bytesRead - chunkOff);
28445
+ buf = Buffer.allocUnsafe(bufLen);
28446
+ s.carryBuf.copy(buf, 0, 0, s.carryLen);
28447
+ chunk.copy(buf, s.carryLen, chunkOff, bytesRead);
28448
+ } else {
28449
+ buf = chunk.subarray(chunkOff, bytesRead);
28088
28450
  }
28451
+ const r = scanChunkLines(s, buf, boundaryMarker);
28452
+ captureSnap(s, buf, chunk, r.lastSnapStart, r.lastSnapEnd);
28453
+ captureCarry(s, buf, r.trailStart);
28454
+ s.bufFileOff += r.trailStart;
28089
28455
  }
28456
+ finalizeOutput(s);
28457
+ } finally {
28458
+ await fd.close();
28090
28459
  }
28091
- return lines.join(`
28092
- `) || "(no conversation evidence)";
28460
+ return {
28461
+ boundaryStartOffset: s.boundaryStartOffset,
28462
+ postBoundaryBuf: s.out.buf.subarray(0, s.out.len),
28463
+ hasPreservedSegment: s.hasPreservedSegment
28464
+ };
28093
28465
  }
28094
- async function evaluateGoal(params) {
28095
- const evidence = extractConversationEvidence(params.messages);
28096
- const userPrompt = `Goal condition:
28097
- ${params.condition}
28466
+ var TRANSCRIPT_READ_CHUNK_SIZE, SKIP_PRECOMPACT_THRESHOLD, _compactBoundaryMarker, ATTR_SNAP_PREFIX, SYSTEM_PREFIX, LF = 10, LF_BYTE, BOUNDARY_SEARCH_BOUND = 256;
28467
+ var init_scanner = __esm(() => {
28468
+ TRANSCRIPT_READ_CHUNK_SIZE = 1024 * 1024;
28469
+ SKIP_PRECOMPACT_THRESHOLD = 5 * 1024 * 1024;
28470
+ ATTR_SNAP_PREFIX = Buffer.from('{"type":"attribution-snapshot"');
28471
+ SYSTEM_PREFIX = Buffer.from('{"type":"system"');
28472
+ LF_BYTE = Buffer.from([LF]);
28473
+ });
28098
28474
 
28099
- Conversation evidence:
28100
- ${evidence}
28475
+ // src/engine/session/predicates.ts
28476
+ function isTranscriptMessage(entry) {
28477
+ return entry.type === "user" || entry.type === "assistant" || entry.type === "attachment" || entry.type === "system";
28478
+ }
28479
+ function isChainParticipant(m) {
28480
+ return m.type !== "progress";
28481
+ }
28482
+ function isLegacyProgressEntry(entry) {
28483
+ return typeof entry === "object" && entry !== null && "type" in entry && entry.type === "progress" && "uuid" in entry && typeof entry.uuid === "string";
28484
+ }
28485
+ function isEphemeralToolProgress(dataType) {
28486
+ return typeof dataType === "string" && EPHEMERAL_PROGRESS_TYPES.has(dataType);
28487
+ }
28488
+ function isCompactBoundaryMessage(message) {
28489
+ return message?.type === "system" && message.subtype === "compact_boundary";
28490
+ }
28491
+ var EPHEMERAL_PROGRESS_TYPES;
28492
+ var init_predicates = __esm(() => {
28493
+ EPHEMERAL_PROGRESS_TYPES = new Set([
28494
+ "bash_progress",
28495
+ "powershell_progress",
28496
+ "mcp_progress"
28497
+ ]);
28498
+ });
28101
28499
 
28102
- Has the goal condition been met?`;
28103
- const resp = await params.modelProvider.chat({
28104
- role: "small",
28105
- messages: [
28106
- { type: "user", message: { role: "user", content: userPrompt } }
28107
- ],
28108
- systemPrompt: { type: "system", content: EVALUATOR_SYSTEM_PROMPT },
28109
- signal: params.signal
28110
- });
28111
- const content = resp.message?.content;
28112
- const blocks = Array.isArray(content) ? content : [content];
28113
- const text = blocks.map((b) => {
28114
- if (typeof b === "string")
28115
- return b;
28116
- if (typeof b === "object" && b !== null && b.type === "text") {
28117
- return b.text ?? "";
28500
+ // src/bootstrap/state.ts
28501
+ import { existsSync as existsSync4 } from "fs";
28502
+ import { randomUUID as randomUUID3 } from "crypto";
28503
+ import { homedir as homedir3 } from "os";
28504
+ import { dirname as dirname3, join as join4 } from "path";
28505
+ function getOriginalCwd() {
28506
+ return _originalCwd2;
28507
+ }
28508
+ function setOriginalCwd(v) {
28509
+ _originalCwd2 = v;
28510
+ }
28511
+ function getCwdState() {
28512
+ return _cwdState;
28513
+ }
28514
+ function setCwdState(v) {
28515
+ _cwdState = v;
28516
+ }
28517
+ function getProjectRoot() {
28518
+ let dir = process.cwd();
28519
+ for (;; ) {
28520
+ if (existsSync4(join4(dir, ".git"))) {
28521
+ return dir;
28118
28522
  }
28119
- return "";
28120
- }).join(`
28121
- `);
28122
- const firstLine = text.trim().split(`
28123
- `)[0]?.toUpperCase() ?? "";
28124
- const reasonLine = text.trim().split(`
28125
- `).slice(1).join(`
28126
- `).trim() || "No reason provided.";
28127
- if (firstLine.includes("MET") && !firstLine.includes("UNMET")) {
28128
- return { met: true, reason: reasonLine };
28523
+ const parent = dirname3(dir);
28524
+ if (parent === dir) {
28525
+ return process.cwd();
28526
+ }
28527
+ dir = parent;
28129
28528
  }
28130
- return { met: false, reason: reasonLine };
28131
28529
  }
28132
- function goalContinuationReminder(condition) {
28133
- const text = `The goal condition has not been met yet. Continue working toward the goal.
28134
-
28135
- Goal condition: ${condition}
28136
-
28137
- Do not stop until the goal condition is met. If the goal is truly unachievable, explain why and what was attempted.`;
28530
+ function setProjectRoot(_v) {}
28531
+ function getSessionId() {
28532
+ return _sessionId2;
28533
+ }
28534
+ function switchSession(id, _projectDir) {
28535
+ if (id)
28536
+ _sessionId2 = id;
28537
+ }
28538
+ function getIsInteractive() {
28539
+ return !_isNonInteractiveSession;
28540
+ }
28541
+ function getIsNonInteractiveSession() {
28542
+ return _isNonInteractiveSession;
28543
+ }
28544
+ function setIsInteractive(v) {
28545
+ _isNonInteractiveSession = !v;
28546
+ }
28547
+ function setClientType(t) {
28548
+ _clientType = t;
28549
+ }
28550
+ function getClientType() {
28551
+ return _clientType;
28552
+ }
28553
+ function setQuestionPreviewFormat(f) {
28554
+ _questionPreviewFormat = f;
28555
+ }
28556
+ function getQuestionPreviewFormat() {
28557
+ return _questionPreviewFormat;
28558
+ }
28559
+ function setSessionBypassPermissionsMode(v) {
28560
+ _sessionBypassPermissionsMode = v;
28561
+ }
28562
+ function isSessionPersistenceDisabled() {
28563
+ return _sessionPersistenceDisabled;
28564
+ }
28565
+ function setSessionPersistenceDisabled(v) {
28566
+ _sessionPersistenceDisabled = v;
28567
+ }
28568
+ function setFlagSettingsPath(p) {
28569
+ _flagSettingsPath = p;
28570
+ }
28571
+ function setAllowedSettingSources(sources) {
28572
+ _allowedSettingSources = sources;
28573
+ }
28574
+ function freshCostState() {
28138
28575
  return {
28139
- type: "user",
28140
- message: { role: "user", content: text },
28141
- uuid: `goal-reminder-${Date.now()}`,
28142
- timestamp: new Date().toISOString()
28576
+ totalAPIDuration: 0,
28577
+ totalAPIDurationWithoutRetries: 0,
28578
+ totalToolDuration: 0,
28579
+ totalLinesAdded: 0,
28580
+ totalLinesRemoved: 0,
28581
+ modelUsage: {}
28143
28582
  };
28144
28583
  }
28145
- function goalMetNotification(condition) {
28146
- return `✓ Goal met: ${condition}
28147
- The goal has been auto-cleared.`;
28584
+ function addToTotalLinesChanged(added, removed) {
28585
+ _costState.totalLinesAdded += added;
28586
+ _costState.totalLinesRemoved += removed;
28148
28587
  }
28149
- function goalClearedNotification() {
28150
- return "Goal cleared.";
28588
+ function getModelUsage() {
28589
+ return _costState.modelUsage;
28151
28590
  }
28152
- function goalHookGateNotification() {
28153
- return "Goal cleared: hooks are disabled (disableAllHooks). Goals require hooks to continue.";
28591
+ function getTotalAPIDuration() {
28592
+ return _costState.totalAPIDuration;
28154
28593
  }
28155
- var MAX_GOAL_CONDITION_CHARS = 500, DEFAULT_MAX_GOAL_TURNS = 10, goalState, EVALUATOR_SYSTEM_PROMPT = `You are a goal-condition evaluator. You are given a goal condition and the recent conversation. Determine whether the goal condition has been MET based solely on the conversation evidence — do not run commands, do not read files, do not make assumptions beyond what is shown.
28156
-
28157
- Respond on the first line with exactly "MET" or "UNMET". On the following line, give a one-sentence reason citing the conversation evidence.`;
28158
- var init_goalState = __esm(() => {
28159
- goalState = { armed: false, condition: undefined, paused: false, pausedReason: undefined };
28160
- });
28161
-
28162
- // src/engine/config/settingsCache.ts
28163
- function getSessionSettingsCache() {
28164
- return sessionSettingsCache;
28594
+ function getTotalAPIDurationWithoutRetries() {
28595
+ return _costState.totalAPIDurationWithoutRetries;
28165
28596
  }
28166
- function setSessionSettingsCache(value) {
28167
- sessionSettingsCache = value;
28597
+ function getTotalToolDuration() {
28598
+ return _costState.totalToolDuration;
28168
28599
  }
28169
- function getCachedSettingsForSource(source) {
28170
- return perSourceCache.has(source) ? perSourceCache.get(source) : undefined;
28600
+ function getTotalDuration() {
28601
+ return _costState.totalAPIDuration + _costState.totalToolDuration;
28171
28602
  }
28172
- function setCachedSettingsForSource(source, value) {
28173
- perSourceCache.set(source, value);
28603
+ function getTotalLinesAdded() {
28604
+ return _costState.totalLinesAdded;
28174
28605
  }
28175
- function getCachedParsedFile(path) {
28176
- return parseFileCache.get(path);
28606
+ function getTotalLinesRemoved() {
28607
+ return _costState.totalLinesRemoved;
28177
28608
  }
28178
- function setCachedParsedFile(path, value) {
28179
- parseFileCache.set(path, value);
28609
+ function getTotalInputTokens() {
28610
+ return Object.values(_costState.modelUsage).reduce((sum, u) => sum + u.inputTokens, 0);
28180
28611
  }
28181
- function resetSettingsCache() {
28182
- sessionSettingsCache = null;
28183
- perSourceCache.clear();
28184
- parseFileCache.clear();
28612
+ function getTotalOutputTokens() {
28613
+ return Object.values(_costState.modelUsage).reduce((sum, u) => sum + u.outputTokens, 0);
28185
28614
  }
28186
- function getPluginSettingsBase() {
28187
- return pluginSettingsBase;
28615
+ function getTotalCacheReadInputTokens() {
28616
+ return Object.values(_costState.modelUsage).reduce((sum, u) => sum + u.cacheReadInputTokens, 0);
28188
28617
  }
28189
- function setPluginSettingsBase(settings) {
28190
- pluginSettingsBase = settings;
28618
+ function getTotalCacheCreationInputTokens() {
28619
+ return Object.values(_costState.modelUsage).reduce((sum, u) => sum + u.cacheCreationInputTokens, 0);
28191
28620
  }
28192
- function clearPluginSettingsBase() {
28193
- pluginSettingsBase = undefined;
28621
+ function getTotalWebSearchRequests() {
28622
+ return Object.values(_costState.modelUsage).reduce((sum, u) => sum + u.webSearchRequests, 0);
28194
28623
  }
28195
- var sessionSettingsCache = null, perSourceCache, parseFileCache, pluginSettingsBase;
28196
- var init_settingsCache = __esm(() => {
28197
- perSourceCache = new Map;
28198
- parseFileCache = new Map;
28199
- });
28200
-
28201
- // node_modules/zod/index.js
28202
- var init_zod = __esm(() => {
28203
- init_external();
28204
- init_external();
28205
- });
28206
-
28207
- // src/engine/config/configRoot.ts
28208
- import { homedir as homedir2 } from "os";
28209
- import { join as join2 } from "path";
28210
- function getAtlasConfigHomeDir() {
28211
- return (process.env.ATLAS_CONFIG_DIR ?? join2(homedir2(), getConfigDirName())).normalize("NFC");
28624
+ function setCostStateForRestore(data) {
28625
+ _costState = {
28626
+ totalAPIDuration: data.totalAPIDuration ?? 0,
28627
+ totalAPIDurationWithoutRetries: data.totalAPIDurationWithoutRetries ?? 0,
28628
+ totalToolDuration: data.totalToolDuration ?? 0,
28629
+ totalLinesAdded: data.totalLinesAdded ?? 0,
28630
+ totalLinesRemoved: data.totalLinesRemoved ?? 0,
28631
+ modelUsage: data.modelUsage ? { ...data.modelUsage } : {}
28632
+ };
28212
28633
  }
28213
- var init_configRoot = __esm(() => {
28214
- init_shared();
28215
- });
28216
-
28217
- // src/engine/config/constants.ts
28218
- function getEnabledSettingSources() {
28219
- const result = new Set(ALLOWED_SETTING_SOURCES);
28220
- result.add("policySettings");
28221
- result.add("flagSettings");
28222
- return Array.from(result);
28634
+ function resetCostState() {
28635
+ _costState = freshCostState();
28223
28636
  }
28224
- function isSettingSourceEnabled(source) {
28225
- const enabled = getEnabledSettingSources();
28226
- return enabled.includes(source);
28637
+ function getSessionCreatedTeams() {
28638
+ return sessionCreatedTeams;
28227
28639
  }
28228
- var SETTING_SOURCES, ALLOWED_SETTING_SOURCES;
28229
- var init_constants3 = __esm(() => {
28230
- SETTING_SOURCES = [
28231
- "userSettings",
28232
- "projectSettings",
28233
- "localSettings",
28234
- "flagSettings",
28235
- "policySettings"
28236
- ];
28237
- ALLOWED_SETTING_SOURCES = ["userSettings"];
28238
- });
28239
-
28240
- // src/engine/config/merge.ts
28241
- function isPlainObject2(v) {
28242
- return typeof v === "object" && v !== null && !Array.isArray(v);
28640
+ function defaultTranscriptDir() {
28641
+ const root = process.env.ATLAS_CONFIG_DIR ?? join4(homedir3(), getConfigDirName());
28642
+ return join4(root, "sessions");
28243
28643
  }
28244
- function mergeWith(target, source, customizer) {
28245
- for (const key of Object.keys(source)) {
28246
- const srcValue = source[key];
28247
- const objValue = target[key];
28248
- if (customizer) {
28249
- const customized = customizer(objValue, srcValue, key, target);
28250
- if (customized !== undefined) {
28251
- target[key] = customized;
28252
- continue;
28253
- }
28254
- }
28255
- if (srcValue === undefined)
28256
- continue;
28257
- if (isPlainObject2(objValue) && isPlainObject2(srcValue)) {
28258
- mergeWith(objValue, srcValue, customizer);
28259
- } else {
28260
- target[key] = srcValue;
28261
- }
28262
- }
28263
- return target;
28644
+ function getTranscriptPathForSession2(sessionId) {
28645
+ const dir = _transcriptDir ?? defaultTranscriptDir();
28646
+ return join4(dir, `${sessionId}.jsonl`);
28264
28647
  }
28265
- function uniq(arr) {
28266
- const seen = new Set;
28267
- const out = [];
28268
- for (const x of arr) {
28269
- if (!seen.has(x)) {
28270
- seen.add(x);
28271
- out.push(x);
28272
- }
28273
- }
28274
- return out;
28648
+ function setMainThreadAgentType(agentType) {
28649
+ _mainThreadAgentType = agentType;
28275
28650
  }
28276
- function settingsMergeCustomizer(objValue, srcValue) {
28277
- if (Array.isArray(objValue) && Array.isArray(srcValue)) {
28278
- return uniq([...objValue, ...srcValue]);
28279
- }
28280
- return;
28651
+ function getMainThreadAgentType() {
28652
+ return _mainThreadAgentType;
28653
+ }
28654
+ function setTrustAccepted(accepted) {
28655
+ _trustAccepted = accepted;
28281
28656
  }
28657
+ function hasTrustAccepted() {
28658
+ return _trustAccepted;
28659
+ }
28660
+ var _originalCwd2, _cwdState, _sessionId2, _isNonInteractiveSession = false, _clientType, _questionPreviewFormat, _sessionBypassPermissionsMode = false, _sessionPersistenceDisabled = false, _flagSettingsPath, _allowedSettingSources, _costState, sessionCreatedTeams, _transcriptDir, _mainThreadAgentType, _trustAccepted = true;
28661
+ var init_state = __esm(() => {
28662
+ init_shared();
28663
+ _originalCwd2 = process.cwd();
28664
+ _cwdState = process.cwd();
28665
+ _sessionId2 = randomUUID3();
28666
+ _costState = freshCostState();
28667
+ sessionCreatedTeams = new Set;
28668
+ });
28282
28669
 
28283
- // src/engine/config/managedPath.ts
28284
- import { join as join3 } from "path";
28285
- function getManagedSettingsDir() {
28286
- return "/etc/atlas";
28670
+ // src/bootstrap/cwd.ts
28671
+ import { AsyncLocalStorage } from "async_hooks";
28672
+ function runWithCwdOverride(cwd, fn) {
28673
+ return cwdOverrideStorage.run(cwd, fn);
28287
28674
  }
28288
- function getManagedSettingsDropInDir() {
28289
- return join3(getManagedSettingsDir(), "managed-settings.d");
28675
+ function pwd() {
28676
+ return cwdOverrideStorage.getStore() ?? getCwdState();
28290
28677
  }
28291
- var init_managedPath = () => {};
28678
+ function getCwd() {
28679
+ try {
28680
+ return pwd();
28681
+ } catch {
28682
+ return getOriginalCwd();
28683
+ }
28684
+ }
28685
+ var cwdOverrideStorage;
28686
+ var init_cwd = __esm(() => {
28687
+ init_state();
28688
+ cwdOverrideStorage = new AsyncLocalStorage;
28689
+ });
28690
+
28691
+ // src/bootstrap/index.ts
28692
+ var init_bootstrap = __esm(() => {
28693
+ init_state();
28694
+ init_cwd();
28695
+ });
28696
+
28697
+ // node_modules/zod/index.js
28698
+ var init_zod = __esm(() => {
28699
+ init_external();
28700
+ init_external();
28701
+ });
28292
28702
 
28293
28703
  // src/hooks/hookEvents.ts
28294
28704
  var HOOK_EVENTS;
@@ -28328,15 +28738,15 @@ var init_hookEvents = __esm(() => {
28328
28738
 
28329
28739
  // src/hooks/bootstrap-env.ts
28330
28740
  function setHooksBootstrapEnv(env) {
28331
- _env = env;
28741
+ _env2 = env;
28332
28742
  }
28333
28743
  function getHooksBootstrapEnv() {
28334
- if (!_env) {
28744
+ if (!_env2) {
28335
28745
  throw new Error("hooks bootstrap 未注入 — 组合根须先 setHooksBootstrapEnv({ getSessionId, getCwd, getTranscriptPath, getMainThreadAgentType, isNonInteractive, hasTrustAccepted })(§8.14 注入序 permissions→task→hooks)");
28336
28746
  }
28337
- return _env;
28747
+ return _env2;
28338
28748
  }
28339
- var _env = null;
28749
+ var _env2 = null;
28340
28750
 
28341
28751
  // src/hooks/config-provider.ts
28342
28752
  function setHookConfigProvider(provider) {
@@ -28878,6 +29288,131 @@ var init_types3 = __esm(() => {
28878
29288
  init_hooksSchema();
28879
29289
  });
28880
29290
 
29291
+ // src/engine/config/constants.ts
29292
+ function getEnabledSettingSources() {
29293
+ const result = new Set(ALLOWED_SETTING_SOURCES);
29294
+ result.add("policySettings");
29295
+ result.add("flagSettings");
29296
+ return Array.from(result);
29297
+ }
29298
+ function isSettingSourceEnabled(source) {
29299
+ const enabled = getEnabledSettingSources();
29300
+ return enabled.includes(source);
29301
+ }
29302
+ var SETTING_SOURCES, ALLOWED_SETTING_SOURCES;
29303
+ var init_constants3 = __esm(() => {
29304
+ SETTING_SOURCES = [
29305
+ "userSettings",
29306
+ "projectSettings",
29307
+ "localSettings",
29308
+ "flagSettings",
29309
+ "policySettings"
29310
+ ];
29311
+ ALLOWED_SETTING_SOURCES = ["userSettings"];
29312
+ });
29313
+
29314
+ // src/engine/config/settingsCache.ts
29315
+ function getSessionSettingsCache() {
29316
+ return sessionSettingsCache;
29317
+ }
29318
+ function setSessionSettingsCache(value) {
29319
+ sessionSettingsCache = value;
29320
+ }
29321
+ function getCachedSettingsForSource(source) {
29322
+ return perSourceCache.has(source) ? perSourceCache.get(source) : undefined;
29323
+ }
29324
+ function setCachedSettingsForSource(source, value) {
29325
+ perSourceCache.set(source, value);
29326
+ }
29327
+ function getCachedParsedFile(path) {
29328
+ return parseFileCache.get(path);
29329
+ }
29330
+ function setCachedParsedFile(path, value) {
29331
+ parseFileCache.set(path, value);
29332
+ }
29333
+ function resetSettingsCache() {
29334
+ sessionSettingsCache = null;
29335
+ perSourceCache.clear();
29336
+ parseFileCache.clear();
29337
+ }
29338
+ function getPluginSettingsBase() {
29339
+ return pluginSettingsBase;
29340
+ }
29341
+ function setPluginSettingsBase(settings) {
29342
+ pluginSettingsBase = settings;
29343
+ }
29344
+ function clearPluginSettingsBase() {
29345
+ pluginSettingsBase = undefined;
29346
+ }
29347
+ var sessionSettingsCache = null, perSourceCache, parseFileCache, pluginSettingsBase;
29348
+ var init_settingsCache = __esm(() => {
29349
+ perSourceCache = new Map;
29350
+ parseFileCache = new Map;
29351
+ });
29352
+
29353
+ // src/engine/config/managedPath.ts
29354
+ import { join as join5 } from "path";
29355
+ function getManagedSettingsDir() {
29356
+ return "/etc/atlas";
29357
+ }
29358
+ function getManagedSettingsDropInDir() {
29359
+ return join5(getManagedSettingsDir(), "managed-settings.d");
29360
+ }
29361
+ var init_managedPath = () => {};
29362
+
29363
+ // src/engine/config/configRoot.ts
29364
+ import { homedir as homedir4 } from "os";
29365
+ import { join as join6 } from "path";
29366
+ function getAtlasConfigHomeDir() {
29367
+ return (process.env.ATLAS_CONFIG_DIR ?? join6(homedir4(), getConfigDirName())).normalize("NFC");
29368
+ }
29369
+ var init_configRoot = __esm(() => {
29370
+ init_shared();
29371
+ });
29372
+
29373
+ // src/engine/config/merge.ts
29374
+ function isPlainObject2(v) {
29375
+ return typeof v === "object" && v !== null && !Array.isArray(v);
29376
+ }
29377
+ function mergeWith(target, source, customizer) {
29378
+ for (const key of Object.keys(source)) {
29379
+ const srcValue = source[key];
29380
+ const objValue = target[key];
29381
+ if (customizer) {
29382
+ const customized = customizer(objValue, srcValue, key, target);
29383
+ if (customized !== undefined) {
29384
+ target[key] = customized;
29385
+ continue;
29386
+ }
29387
+ }
29388
+ if (srcValue === undefined)
29389
+ continue;
29390
+ if (isPlainObject2(objValue) && isPlainObject2(srcValue)) {
29391
+ mergeWith(objValue, srcValue, customizer);
29392
+ } else {
29393
+ target[key] = srcValue;
29394
+ }
29395
+ }
29396
+ return target;
29397
+ }
29398
+ function uniq(arr) {
29399
+ const seen = new Set;
29400
+ const out = [];
29401
+ for (const x of arr) {
29402
+ if (!seen.has(x)) {
29403
+ seen.add(x);
29404
+ out.push(x);
29405
+ }
29406
+ }
29407
+ return out;
29408
+ }
29409
+ function settingsMergeCustomizer(objValue, srcValue) {
29410
+ if (Array.isArray(objValue) && Array.isArray(srcValue)) {
29411
+ return uniq([...objValue, ...srcValue]);
29412
+ }
29413
+ return;
29414
+ }
29415
+
28881
29416
  // src/permissions/PermissionRule.ts
28882
29417
  var permissionBehaviorSchema, permissionRuleValueSchema;
28883
29418
  var init_PermissionRule = __esm(() => {
@@ -28892,15 +29427,15 @@ var init_PermissionRule = __esm(() => {
28892
29427
 
28893
29428
  // src/permissions/bootstrap-env.ts
28894
29429
  function setPermissionsBootstrapEnv(env) {
28895
- _env2 = env;
29430
+ _env3 = env;
28896
29431
  }
28897
29432
  function getPermissionsBootstrapEnv() {
28898
- if (!_env2) {
29433
+ if (!_env3) {
28899
29434
  throw new Error("permissions bootstrap 未注入 — 组合根须先 setPermissionsBootstrapEnv({ getOriginalCwd, getCwd })(§8.14 注入序 permissions→task→hooks)");
28900
29435
  }
28901
- return _env2;
29436
+ return _env3;
28902
29437
  }
28903
- var _env2 = null;
29438
+ var _env3 = null;
28904
29439
 
28905
29440
  // src/permissions/settingsPaths.ts
28906
29441
  function setSettingsPathsProvider(provider) {
@@ -28913,7 +29448,7 @@ var _provider3 = null;
28913
29448
 
28914
29449
  // src/permissions/filesystem.ts
28915
29450
  import { tmpdir } from "os";
28916
- import { join as join4, posix, resolve as resolve2, sep } from "path";
29451
+ import { join as join7, posix, resolve as resolve2, sep } from "path";
28917
29452
  function expandPathLocal(path) {
28918
29453
  return expandPath(path, getPermissionsBootstrapEnv().getCwd());
28919
29454
  }
@@ -28938,9 +29473,9 @@ function isClaudeConfigFilePath(filePath) {
28938
29473
  }
28939
29474
  const configDir = getConfigDirName();
28940
29475
  const originalCwd = getPermissionsBootstrapEnv().getOriginalCwd();
28941
- const commandsDir = join4(originalCwd, configDir, "commands");
28942
- const agentsDir = join4(originalCwd, configDir, "agents");
28943
- const skillsDir = join4(originalCwd, configDir, "skills");
29476
+ const commandsDir = join7(originalCwd, configDir, "commands");
29477
+ const agentsDir = join7(originalCwd, configDir, "agents");
29478
+ const skillsDir = join7(originalCwd, configDir, "skills");
28944
29479
  return pathInWorkingPath(filePath, commandsDir) || pathInWorkingPath(filePath, agentsDir) || pathInWorkingPath(filePath, skillsDir);
28945
29480
  }
28946
29481
  function getAtlasTempDir() {
@@ -28951,12 +29486,12 @@ function getAtlasTempDir() {
28951
29486
  try {
28952
29487
  resolvedBaseTmpDir = fs.realpathSync(baseTmpDir);
28953
29488
  } catch {}
28954
- _atlasTempDir = join4(resolvedBaseTmpDir, getAtlasTempDirName()) + sep;
29489
+ _atlasTempDir = join7(resolvedBaseTmpDir, getAtlasTempDirName()) + sep;
28955
29490
  }
28956
29491
  return _atlasTempDir;
28957
29492
  }
28958
29493
  function getProjectTempDir() {
28959
- return join4(getAtlasTempDir(), sanitizePath(getPermissionsBootstrapEnv().getOriginalCwd())) + sep;
29494
+ return join7(getAtlasTempDir(), sanitizePath(getPermissionsBootstrapEnv().getOriginalCwd())) + sep;
28960
29495
  }
28961
29496
  function isDangerousFilePathToAutoEdit(path) {
28962
29497
  const absolutePath = expandPathLocal(path);
@@ -29054,7 +29589,7 @@ function isActiveWorktreeCwd(cwd) {
29054
29589
  }
29055
29590
  let active = false;
29056
29591
  try {
29057
- const content = getFsImplementation().readFileSync(join4(cwd, ".git"), { encoding: "utf8" });
29592
+ const content = getFsImplementation().readFileSync(join7(cwd, ".git"), { encoding: "utf8" });
29058
29593
  const gitdirMatch = content.match(/^gitdir:\s*(.+)$/m);
29059
29594
  if (gitdirMatch?.[1]) {
29060
29595
  const gitdir = resolve2(cwd, gitdirMatch[1].trim());
@@ -30317,8 +30852,8 @@ var init_permissionUpdateSchema = __esm(() => {
30317
30852
  });
30318
30853
 
30319
30854
  // src/permissions/pathValidation.ts
30320
- import { homedir as homedir3 } from "os";
30321
- import { dirname as dirname2, isAbsolute as isAbsolute2, resolve as resolve3 } from "path";
30855
+ import { homedir as homedir5 } from "os";
30856
+ import { dirname as dirname4, isAbsolute as isAbsolute2, resolve as resolve3 } from "path";
30322
30857
  function formatDirectoryList(directories) {
30323
30858
  const dirCount = directories.length;
30324
30859
  if (dirCount <= MAX_DIRS_TO_LIST) {
@@ -30340,7 +30875,7 @@ function getGlobBaseDirectory(path) {
30340
30875
  }
30341
30876
  function expandTilde(path) {
30342
30877
  if (path === "~" || path.startsWith("~/") || process.platform === "win32" && path.startsWith("~\\")) {
30343
- return homedir3() + path.slice(1);
30878
+ return homedir5() + path.slice(1);
30344
30879
  }
30345
30880
  return path;
30346
30881
  }
@@ -30478,11 +31013,11 @@ function isDangerousRemovalPath(resolvedPath) {
30478
31013
  if (WINDOWS_DRIVE_ROOT_REGEX.test(normalizedPath)) {
30479
31014
  return true;
30480
31015
  }
30481
- const normalizedHome = homedir3().replace(/[\\/]+/g, "/");
31016
+ const normalizedHome = homedir5().replace(/[\\/]+/g, "/");
30482
31017
  if (normalizedPath === normalizedHome) {
30483
31018
  return true;
30484
31019
  }
30485
- const parentDir = dirname2(normalizedPath);
31020
+ const parentDir = dirname4(normalizedPath);
30486
31021
  if (parentDir === "/") {
30487
31022
  return true;
30488
31023
  }
@@ -31132,9 +31667,9 @@ var init_validation = __esm(() => {
31132
31667
  });
31133
31668
 
31134
31669
  // src/engine/config/settings.ts
31135
- import { dirname as dirname3, join as join5, resolve as resolve4 } from "path";
31670
+ import { dirname as dirname5, join as join8, resolve as resolve4 } from "path";
31136
31671
  function getManagedSettingsFilePath() {
31137
- return join5(getManagedSettingsDir(), "managed-settings.json");
31672
+ return join8(getManagedSettingsDir(), "managed-settings.json");
31138
31673
  }
31139
31674
  function loadManagedFileSettings() {
31140
31675
  const errors = [];
@@ -31150,7 +31685,7 @@ function loadManagedFileSettings() {
31150
31685
  try {
31151
31686
  const entries = getFsImplementation().readdirSync(dropInDir).filter((d) => (d.isFile() || d.isSymbolicLink()) && d.name.endsWith(".json") && !d.name.startsWith(".")).map((d) => d.name).sort();
31152
31687
  for (const name of entries) {
31153
- const { settings, errors: fileErrors } = parseSettingsFile(join5(dropInDir, name));
31688
+ const { settings, errors: fileErrors } = parseSettingsFile(join8(dropInDir, name));
31154
31689
  errors.push(...fileErrors);
31155
31690
  if (settings && Object.keys(settings).length > 0) {
31156
31691
  merged = mergeWith(merged, settings, settingsMergeCustomizer);
@@ -31234,10 +31769,10 @@ function getUserSettingsFilePath() {
31234
31769
  function getSettingsFilePathForSource(source) {
31235
31770
  switch (source) {
31236
31771
  case "userSettings":
31237
- return join5(getSettingsRootPathForSource(source), getUserSettingsFilePath());
31772
+ return join8(getSettingsRootPathForSource(source), getUserSettingsFilePath());
31238
31773
  case "projectSettings":
31239
31774
  case "localSettings":
31240
- return join5(getSettingsRootPathForSource(source), getRelativeSettingsFilePathForSource(source));
31775
+ return join8(getSettingsRootPathForSource(source), getRelativeSettingsFilePathForSource(source));
31241
31776
  case "policySettings":
31242
31777
  return getManagedSettingsFilePath();
31243
31778
  case "flagSettings":
@@ -31250,9 +31785,9 @@ function getSettingsPaths2() {
31250
31785
  function getRelativeSettingsFilePathForSource(source) {
31251
31786
  switch (source) {
31252
31787
  case "projectSettings":
31253
- return join5(getConfigDirName(), "settings.json");
31788
+ return join8(getConfigDirName(), "settings.json");
31254
31789
  case "localSettings":
31255
- return join5(getConfigDirName(), "settings.local.json");
31790
+ return join8(getConfigDirName(), "settings.local.json");
31256
31791
  }
31257
31792
  }
31258
31793
  function getSettingsForSource(source) {
@@ -31285,7 +31820,7 @@ function updateSettingsForSource(source, settings) {
31285
31820
  }
31286
31821
  try {
31287
31822
  const fs = getFsImplementation();
31288
- fs.mkdirSync(dirname3(filePath));
31823
+ fs.mkdirSync(dirname5(filePath));
31289
31824
  let existingSettings = getSettingsForSourceUncached(source);
31290
31825
  if (!existingSettings) {
31291
31826
  let content = null;
@@ -31509,285 +32044,6 @@ var init_hooksConfig = __esm(() => {
31509
32044
  init_settings();
31510
32045
  });
31511
32046
 
31512
- // src/engine/pipeline/errorClassification.ts
31513
- function classifyToolError(error) {
31514
- if (error instanceof Error) {
31515
- const errnoCode = error.code;
31516
- if (typeof errnoCode === "string") {
31517
- return `Error:${errnoCode}`;
31518
- }
31519
- if (error.name && error.name !== "Error" && error.name.length > 3) {
31520
- return error.name.slice(0, 60);
31521
- }
31522
- return "Error";
31523
- }
31524
- return "UnknownError";
31525
- }
31526
-
31527
- // src/engine/pipeline/schemaValidation.ts
31528
- function typeName(v) {
31529
- if (v === null)
31530
- return "null";
31531
- if (Array.isArray(v))
31532
- return "array";
31533
- return typeof v;
31534
- }
31535
- function checkBasicType(value, type) {
31536
- switch (type) {
31537
- case "string":
31538
- return typeof value === "string" ? null : `expected string, got ${typeName(value)}`;
31539
- case "number":
31540
- if (typeof value === "number") {
31541
- return Number.isFinite(value) ? null : "expected number, got non-finite number";
31542
- }
31543
- return `expected number, got ${typeName(value)}`;
31544
- case "integer":
31545
- if (typeof value === "number") {
31546
- return Number.isInteger(value) ? null : "expected integer, got non-integer number";
31547
- }
31548
- return `expected integer, got ${typeName(value)}`;
31549
- case "boolean":
31550
- return typeof value === "boolean" ? null : `expected boolean, got ${typeName(value)}`;
31551
- case "array":
31552
- return Array.isArray(value) ? null : `expected array, got ${typeName(value)}`;
31553
- case "object":
31554
- return typeof value === "object" && value !== null && !Array.isArray(value) ? null : `expected object, got ${typeName(value)}`;
31555
- case "null":
31556
- return value === null ? null : `expected null, got ${typeName(value)}`;
31557
- default:
31558
- return null;
31559
- }
31560
- }
31561
- function validateInputBySchema(input, schema) {
31562
- if (!schema) {
31563
- return { valid: true };
31564
- }
31565
- if (input === null || typeof input !== "object" || Array.isArray(input)) {
31566
- return { valid: false, message: "expected object input" };
31567
- }
31568
- const record = input;
31569
- const errors = [];
31570
- const required = schema.required;
31571
- if (Array.isArray(required)) {
31572
- for (const rawKey of required) {
31573
- const key = String(rawKey);
31574
- if (!(key in record) || record[key] === undefined) {
31575
- errors.push(`missing required field "${key}"`);
31576
- }
31577
- }
31578
- }
31579
- const properties = schema.properties;
31580
- if (properties) {
31581
- for (const [key, value] of Object.entries(record)) {
31582
- if (value === undefined)
31583
- continue;
31584
- const propSchema = properties[key];
31585
- if (!propSchema || typeof propSchema !== "object")
31586
- continue;
31587
- const type = propSchema.type;
31588
- if (typeof type !== "string")
31589
- continue;
31590
- const err = checkBasicType(value, type);
31591
- if (err)
31592
- errors.push(`field "${key}": ${err}`);
31593
- }
31594
- }
31595
- return errors.length > 0 ? { valid: false, message: errors.join("; ") } : { valid: true };
31596
- }
31597
- function buildSchemaNotSentHint(tool, discoveredToolNames) {
31598
- if (!tool.shouldDefer)
31599
- return null;
31600
- if (discoveredToolNames.has(tool.name))
31601
- return null;
31602
- return `
31603
-
31604
- This tool's schema was not sent to the API — it was not in the discovered-tool set derived from message history. ` + `Without the schema in your prompt, typed parameters (arrays, numbers, booleans) get emitted as strings and the client-side parser rejects them. ` + `Re-issue the call with correctly-typed parameters (arrays/numbers/booleans, not their string forms).`;
31605
- }
31606
-
31607
- // src/engine/pipeline/toolExecution.ts
31608
- function mergeHookPermission(hookBehavior, gate, hookReason) {
31609
- if (hookBehavior === "defer") {
31610
- return {
31611
- allowed: false,
31612
- deferred: true,
31613
- reason: hookReason ?? "deferred by hook"
31614
- };
31615
- }
31616
- if (hookBehavior === "deny") {
31617
- return { allowed: false, reason: "blocked by hook" };
31618
- }
31619
- if (!gate.allowed)
31620
- return gate;
31621
- if (hookBehavior === "ask") {
31622
- return { allowed: false, ask: true, reason: "hook requested confirmation" };
31623
- }
31624
- return gate;
31625
- }
31626
- function findTool(tools, name) {
31627
- return tools.find((t) => t.name === name || (t.aliases?.includes(name) ?? false));
31628
- }
31629
- async function executeToolUse(tu, assistantMsg, deps) {
31630
- const tool = findTool(deps.tools, tu.name);
31631
- if (!tool) {
31632
- return {
31633
- block: {
31634
- type: "tool_result",
31635
- tool_use_id: tu.id,
31636
- content: `unknown tool: ${tu.name}`,
31637
- is_error: true
31638
- },
31639
- isError: true
31640
- };
31641
- }
31642
- const toolCallContext = deps.toolContext !== undefined ? { ...deps.toolContext, signal: deps.signal, checkPermission: deps.checkPermission } : { signal: deps.signal, checkPermission: deps.checkPermission };
31643
- const schemaResult = validateInputBySchema(tu.input, tool.inputSchema);
31644
- if (schemaResult.valid === false) {
31645
- const discovered = deps.discoveredToolNames ?? new Set(deps.tools.map((t) => t.name));
31646
- const schemaHint = buildSchemaNotSentHint(tool, discovered);
31647
- const errorContent = schemaHint ? `${schemaResult.message}${schemaHint}` : schemaResult.message;
31648
- return {
31649
- block: {
31650
- type: "tool_result",
31651
- tool_use_id: tu.id,
31652
- content: `<tool_use_error>InputValidationError: ${errorContent}</tool_use_error>`,
31653
- is_error: true
31654
- },
31655
- isError: true
31656
- };
31657
- }
31658
- const validation = await tool.validateInput?.(tu.input, toolCallContext);
31659
- if (validation && validation.result === false) {
31660
- return {
31661
- block: {
31662
- type: "tool_result",
31663
- tool_use_id: tu.id,
31664
- content: `<tool_use_error>InputValidationError: ${validation.message}</tool_use_error>`,
31665
- is_error: true
31666
- },
31667
- isError: true
31668
- };
31669
- }
31670
- const preOutcome = await deps.hooks?.preToolUse?.(tool, tu.input, tu.id);
31671
- if (preOutcome?.blockingError) {
31672
- return {
31673
- block: {
31674
- type: "tool_result",
31675
- tool_use_id: tu.id,
31676
- content: `<tool_use_error>hook blocked: ${preOutcome.blockingError}</tool_use_error>`,
31677
- is_error: true
31678
- },
31679
- isError: true
31680
- };
31681
- }
31682
- if (preOutcome?.preventContinuation) {
31683
- return {
31684
- block: {
31685
- type: "tool_result",
31686
- tool_use_id: tu.id,
31687
- content: `<tool_use_error>Execution stopped by PreToolUse hook${preOutcome.stopReason ? `: ${preOutcome.stopReason}` : ""}</tool_use_error>`,
31688
- is_error: true
31689
- },
31690
- isError: true
31691
- };
31692
- }
31693
- const effectiveInput = preOutcome?.updatedInput ?? tu.input;
31694
- const gateVerdict = deps.checkPermission ? await deps.checkPermission(tool, effectiveInput, {
31695
- toolUseId: tu.id,
31696
- assistantMessage: assistantMsg
31697
- }) : { allowed: true };
31698
- const verdict = mergeHookPermission(preOutcome?.hookBehavior, gateVerdict, preOutcome?.hookPermissionDecisionReason);
31699
- if (verdict.deferred) {
31700
- return { deferred: true, deferReason: verdict.reason, isError: false };
31701
- }
31702
- if (!verdict.allowed) {
31703
- const content = verdict.ask ? `<tool_use_error>permission confirmation required (prompt 面残留守): ${verdict.reason ?? tu.name}</tool_use_error>` : `<tool_use_error>permission denied: ${verdict.reason ?? tu.name}</tool_use_error>`;
31704
- return {
31705
- block: {
31706
- type: "tool_result",
31707
- tool_use_id: tu.id,
31708
- content,
31709
- is_error: true
31710
- },
31711
- isError: true
31712
- };
31713
- }
31714
- const callInput = verdict.updatedInput ?? effectiveInput;
31715
- let block;
31716
- let isError = false;
31717
- let toolUseResult;
31718
- try {
31719
- const res = await tool.call(callInput, toolCallContext, undefined, assistantMsg);
31720
- block = tool.mapToolResultToToolResultBlockParam(res.data, tu.id);
31721
- toolUseResult = res.data;
31722
- } catch (error) {
31723
- const errorText = `tool error [${classifyToolError(error)}]: ${String(error?.message ?? error)}`;
31724
- block = {
31725
- type: "tool_result",
31726
- tool_use_id: tu.id,
31727
- content: `<tool_use_error>${errorText}</tool_use_error>`,
31728
- is_error: true
31729
- };
31730
- isError = true;
31731
- toolUseResult = errorText;
31732
- }
31733
- const postOutcome = await deps.hooks?.postToolUse?.(tool, callInput, block, tu.id);
31734
- if (postOutcome?.updatedToolOutput !== undefined) {
31735
- block = { ...block, content: postOutcome.updatedToolOutput };
31736
- toolUseResult = postOutcome.updatedToolOutput;
31737
- }
31738
- return { block, isError, toolUseResult };
31739
- }
31740
- var init_toolExecution = () => {};
31741
-
31742
- // src/engine/pipeline/toolOrchestration.ts
31743
- function partitionToolCalls(toolUses, tools) {
31744
- return toolUses.reduce((acc, tu) => {
31745
- const tool = findTool(tools, tu.name);
31746
- let safe = false;
31747
- try {
31748
- safe = tool ? tool.isConcurrencySafe(tu.input) : false;
31749
- } catch {
31750
- safe = false;
31751
- }
31752
- if (safe && acc[acc.length - 1]?.isConcurrencySafe) {
31753
- acc[acc.length - 1].blocks.push(tu);
31754
- } else {
31755
- acc.push({ isConcurrencySafe: safe, blocks: [tu] });
31756
- }
31757
- return acc;
31758
- }, []);
31759
- }
31760
- async function runToolBatch(toolUses, assistantMsg, deps) {
31761
- const outcomes = [];
31762
- for (const batch of partitionToolCalls(toolUses, deps.tools)) {
31763
- for (const tu of batch.blocks) {
31764
- const r = await executeToolUse(tu, assistantMsg, deps);
31765
- outcomes.push({
31766
- toolUseId: tu.id,
31767
- name: tu.name,
31768
- block: r.block,
31769
- isError: r.isError,
31770
- toolUseResult: r.toolUseResult,
31771
- deferred: r.deferred,
31772
- deferReason: r.deferReason
31773
- });
31774
- if (r.deferred) {
31775
- return outcomes;
31776
- }
31777
- }
31778
- }
31779
- return outcomes;
31780
- }
31781
- var init_toolOrchestration = __esm(() => {
31782
- init_toolExecution();
31783
- });
31784
-
31785
- // src/engine/pipeline/index.ts
31786
- var init_pipeline = __esm(() => {
31787
- init_toolExecution();
31788
- init_toolOrchestration();
31789
- });
31790
-
31791
32047
  // src/engine/config/managedEnv.ts
31792
32048
  function applySafeConfigEnvironmentVariables() {
31793
32049
  for (const source of TRUSTED_SETTING_SOURCES) {
@@ -31932,667 +32188,6 @@ var init_config = __esm(() => {
31932
32188
  init_autoCompactOverrides();
31933
32189
  });
31934
32190
 
31935
- // src/engine/session/types.ts
31936
- function sortLogs(logs) {
31937
- return logs.sort((a, b) => {
31938
- const modifiedDiff = b.modified.getTime() - a.modified.getTime();
31939
- if (modifiedDiff !== 0) {
31940
- return modifiedDiff;
31941
- }
31942
- return b.created.getTime() - a.created.getTime();
31943
- });
31944
- }
31945
-
31946
- // src/engine/session/env.ts
31947
- import { randomUUID as randomUUID2 } from "crypto";
31948
- import { homedir as homedir4 } from "os";
31949
- import { join as join6 } from "path";
31950
- function setSessionEnv(partial) {
31951
- _env3 = { ..._env3, ...partial };
31952
- }
31953
- function getSessionEnv() {
31954
- return _env3;
31955
- }
31956
- function resetSessionEnv() {
31957
- _env3 = defaultEnv;
31958
- }
31959
- var _sessionId, _originalCwd, _cleanupHandlers, defaultEnv, _env3;
31960
- var init_env = __esm(() => {
31961
- init_shared();
31962
- _sessionId = randomUUID2();
31963
- _originalCwd = process.cwd();
31964
- _cleanupHandlers = [];
31965
- defaultEnv = {
31966
- getSessionId: () => _sessionId,
31967
- switchSession: (id) => {
31968
- if (id)
31969
- _sessionId = id;
31970
- },
31971
- getOriginalCwd: () => _originalCwd,
31972
- getCwd: () => process.cwd(),
31973
- getProjectsDir: () => join6((process.env.ATLAS_CONFIG_DIR ?? join6(homedir4(), getConfigDirName())).normalize("NFC"), "projects"),
31974
- registerCleanup: (handler) => {
31975
- _cleanupHandlers.push(handler);
31976
- }
31977
- };
31978
- _env3 = defaultEnv;
31979
- });
31980
-
31981
- // src/engine/session/paths.ts
31982
- import { execFile } from "child_process";
31983
- import { existsSync as existsSync3, readFileSync as readFileSync3, realpathSync as realpathSync3 } from "fs";
31984
- import { dirname as dirname4, join as join7 } from "path";
31985
- function getProjectsDir() {
31986
- return getSessionEnv().getProjectsDir();
31987
- }
31988
- function getTranscriptPath() {
31989
- const projectDir = getProjectDir(getSessionEnv().getOriginalCwd());
31990
- return join7(projectDir, `${getSessionEnv().getSessionId()}.jsonl`);
31991
- }
31992
- function getTranscriptPathForSession(sessionId) {
31993
- if (sessionId === getSessionEnv().getSessionId()) {
31994
- return getTranscriptPath();
31995
- }
31996
- const projectDir = getProjectDir(getSessionEnv().getOriginalCwd());
31997
- return join7(projectDir, `${sessionId}.jsonl`);
31998
- }
31999
- function setAgentTranscriptSubdir(agentId, subdir) {
32000
- agentTranscriptSubdirs.set(agentId, subdir);
32001
- }
32002
- function clearAgentTranscriptSubdir(agentId) {
32003
- agentTranscriptSubdirs.delete(agentId);
32004
- }
32005
- function getAgentTranscriptPath(agentId) {
32006
- const projectDir = getProjectDir(getSessionEnv().getOriginalCwd());
32007
- const sessionId = getSessionEnv().getSessionId();
32008
- const subdir = agentTranscriptSubdirs.get(agentId);
32009
- const base = subdir ? join7(projectDir, sessionId, "subagents", subdir) : join7(projectDir, sessionId, "subagents");
32010
- return join7(base, `agent-${agentId}.jsonl`);
32011
- }
32012
- function getUserType() {
32013
- return "atlas";
32014
- }
32015
- function getEntrypoint() {
32016
- return process.env.ATLAS_ENTRYPOINT ?? "cli";
32017
- }
32018
- function getGitBranch() {
32019
- return new Promise((resolve) => {
32020
- execFile("git", ["rev-parse", "--abbrev-ref", "HEAD"], (err, stdout) => {
32021
- if (err) {
32022
- resolve(undefined);
32023
- return;
32024
- }
32025
- const branch = stdout.trim();
32026
- resolve(branch && branch !== "HEAD" ? branch : undefined);
32027
- });
32028
- });
32029
- }
32030
- function getVersion2() {
32031
- return VERSION3;
32032
- }
32033
- var _projectDirCache, getProjectDir = (projectDir) => {
32034
- const cached = _projectDirCache.get(projectDir);
32035
- if (cached !== undefined)
32036
- return cached;
32037
- const resolved = join7(getSessionEnv().getProjectsDir(), sanitizePath(projectDir));
32038
- _projectDirCache.set(projectDir, resolved);
32039
- return resolved;
32040
- }, MAX_TRANSCRIPT_READ_BYTES, agentTranscriptSubdirs, VERSION3;
32041
- var init_paths = __esm(() => {
32042
- init_shared();
32043
- init_env();
32044
- _projectDirCache = new Map;
32045
- MAX_TRANSCRIPT_READ_BYTES = 50 * 1024 * 1024;
32046
- agentTranscriptSubdirs = new Map;
32047
- VERSION3 = (() => {
32048
- try {
32049
- let d = dirname4(realpathSync3(process.argv[1] ?? ""));
32050
- for (;; ) {
32051
- const pkgPath = join7(d, "package.json");
32052
- if (existsSync3(pkgPath)) {
32053
- const v = JSON.parse(readFileSync3(pkgPath, "utf8")).version;
32054
- if (typeof v === "string" && v)
32055
- return v;
32056
- }
32057
- const parent = dirname4(d);
32058
- if (parent === d)
32059
- break;
32060
- d = parent;
32061
- }
32062
- } catch {}
32063
- return "0.0.0";
32064
- })();
32065
- });
32066
-
32067
- // src/engine/session/json.ts
32068
- function parseJSONLBun(data) {
32069
- const parse = bunJSONLParse;
32070
- const len = data.length;
32071
- const result = parse(data);
32072
- if (!result.error || result.done || result.read >= len) {
32073
- return result.values;
32074
- }
32075
- let values = result.values;
32076
- let offset = result.read;
32077
- while (offset < len) {
32078
- const newlineIndex = typeof data === "string" ? data.indexOf(`
32079
- `, offset) : data.indexOf(10, offset);
32080
- if (newlineIndex === -1)
32081
- break;
32082
- offset = newlineIndex + 1;
32083
- const next = parse(data, offset);
32084
- if (next.values.length > 0) {
32085
- values = values.concat(next.values);
32086
- }
32087
- if (!next.error || next.done || next.read >= len)
32088
- break;
32089
- offset = next.read;
32090
- }
32091
- return values;
32092
- }
32093
- function parseJSONLBuffer(buf) {
32094
- const bufLen = buf.length;
32095
- let start = 0;
32096
- if (buf[0] === 239 && buf[1] === 187 && buf[2] === 191) {
32097
- start = 3;
32098
- }
32099
- const results = [];
32100
- while (start < bufLen) {
32101
- let end = buf.indexOf(10, start);
32102
- if (end === -1)
32103
- end = bufLen;
32104
- const line = buf.toString("utf8", start, end).trim();
32105
- start = end + 1;
32106
- if (!line)
32107
- continue;
32108
- try {
32109
- results.push(JSON.parse(line));
32110
- } catch {}
32111
- }
32112
- return results;
32113
- }
32114
- function parseJSONLString(data) {
32115
- const stripped = data.startsWith("\uFEFF") ? data.slice(1) : data;
32116
- const len = stripped.length;
32117
- let start = 0;
32118
- const results = [];
32119
- while (start < len) {
32120
- let end = stripped.indexOf(`
32121
- `, start);
32122
- if (end === -1)
32123
- end = len;
32124
- const line = stripped.substring(start, end).trim();
32125
- start = end + 1;
32126
- if (!line)
32127
- continue;
32128
- try {
32129
- results.push(JSON.parse(line));
32130
- } catch {}
32131
- }
32132
- return results;
32133
- }
32134
- function parseJSONL(data) {
32135
- if (bunJSONLParse) {
32136
- return parseJSONLBun(data);
32137
- }
32138
- if (typeof data === "string") {
32139
- return parseJSONLString(data);
32140
- }
32141
- return parseJSONLBuffer(data);
32142
- }
32143
- function jsonStringify2(data, space) {
32144
- return JSON.stringify(data, undefined, space);
32145
- }
32146
- var bunJSONLParse, jsonParse = (text, reviver) => {
32147
- return typeof reviver === "undefined" ? JSON.parse(text) : JSON.parse(text, reviver);
32148
- };
32149
- var init_json = __esm(() => {
32150
- bunJSONLParse = (() => {
32151
- if (typeof Bun === "undefined")
32152
- return false;
32153
- const b = Bun;
32154
- const jsonl = b.JSONL;
32155
- if (!jsonl?.parseChunk)
32156
- return false;
32157
- return jsonl.parseChunk;
32158
- })();
32159
- });
32160
-
32161
- // src/engine/session/scanner.ts
32162
- import { open as fsOpen } from "fs/promises";
32163
- function compactBoundaryMarker() {
32164
- return _compactBoundaryMarker ??= Buffer.from('"compact_boundary"');
32165
- }
32166
- function parseBoundaryLine(line) {
32167
- try {
32168
- const parsed = JSON.parse(line);
32169
- if (parsed.type !== "system" || parsed.subtype !== "compact_boundary") {
32170
- return null;
32171
- }
32172
- return {
32173
- hasPreservedSegment: Boolean(parsed.compactMetadata?.preservedSegment)
32174
- };
32175
- } catch {
32176
- return null;
32177
- }
32178
- }
32179
- function sinkWrite(s, src, start, end) {
32180
- const n = end - start;
32181
- if (n <= 0)
32182
- return;
32183
- if (s.len + n > s.buf.length) {
32184
- const grown = Buffer.allocUnsafe(Math.min(Math.max(s.buf.length * 2, s.len + n), s.cap));
32185
- s.buf.copy(grown, 0, 0, s.len);
32186
- s.buf = grown;
32187
- }
32188
- src.copy(s.buf, s.len, start, end);
32189
- s.len += n;
32190
- }
32191
- function hasPrefix(src, prefix, at, end) {
32192
- return end - at >= prefix.length && src.compare(prefix, 0, prefix.length, at, at + prefix.length) === 0;
32193
- }
32194
- function processStraddle(s, chunk, bytesRead) {
32195
- s.straddleSnapCarryLen = 0;
32196
- s.straddleSnapTailEnd = 0;
32197
- if (s.carryLen === 0)
32198
- return 0;
32199
- const cb = s.carryBuf;
32200
- const firstNl = chunk.indexOf(LF);
32201
- if (firstNl === -1 || firstNl >= bytesRead)
32202
- return 0;
32203
- const tailEnd = firstNl + 1;
32204
- if (hasPrefix(cb, ATTR_SNAP_PREFIX, 0, s.carryLen)) {
32205
- s.straddleSnapCarryLen = s.carryLen;
32206
- s.straddleSnapTailEnd = tailEnd;
32207
- s.lastSnapSrc = null;
32208
- } else if (s.carryLen < ATTR_SNAP_PREFIX.length) {
32209
- return 0;
32210
- } else {
32211
- if (hasPrefix(cb, SYSTEM_PREFIX, 0, s.carryLen)) {
32212
- const hit = parseBoundaryLine(cb.toString("utf-8", 0, s.carryLen) + chunk.toString("utf-8", 0, firstNl));
32213
- if (hit?.hasPreservedSegment) {
32214
- s.hasPreservedSegment = true;
32215
- } else if (hit) {
32216
- s.out.len = 0;
32217
- s.boundaryStartOffset = s.bufFileOff;
32218
- s.hasPreservedSegment = false;
32219
- s.lastSnapSrc = null;
32220
- }
32221
- }
32222
- sinkWrite(s.out, cb, 0, s.carryLen);
32223
- sinkWrite(s.out, chunk, 0, tailEnd);
32224
- }
32225
- s.bufFileOff += s.carryLen + tailEnd;
32226
- s.carryLen = 0;
32227
- return tailEnd;
32228
- }
32229
- function scanChunkLines(s, buf, boundaryMarker) {
32230
- let boundaryAt = buf.indexOf(boundaryMarker);
32231
- let runStart = 0;
32232
- let lineStart = 0;
32233
- let lastSnapStart = -1;
32234
- let lastSnapEnd = -1;
32235
- let nl = buf.indexOf(LF);
32236
- while (nl !== -1) {
32237
- const lineEnd = nl + 1;
32238
- if (boundaryAt !== -1 && boundaryAt < lineStart) {
32239
- boundaryAt = buf.indexOf(boundaryMarker, lineStart);
32240
- }
32241
- if (hasPrefix(buf, ATTR_SNAP_PREFIX, lineStart, lineEnd)) {
32242
- sinkWrite(s.out, buf, runStart, lineStart);
32243
- lastSnapStart = lineStart;
32244
- lastSnapEnd = lineEnd;
32245
- runStart = lineEnd;
32246
- } else if (boundaryAt >= lineStart && boundaryAt < Math.min(lineStart + BOUNDARY_SEARCH_BOUND, lineEnd)) {
32247
- const hit = parseBoundaryLine(buf.toString("utf-8", lineStart, nl));
32248
- if (hit?.hasPreservedSegment) {
32249
- s.hasPreservedSegment = true;
32250
- } else if (hit) {
32251
- s.out.len = 0;
32252
- s.boundaryStartOffset = s.bufFileOff + lineStart;
32253
- s.hasPreservedSegment = false;
32254
- s.lastSnapSrc = null;
32255
- lastSnapStart = -1;
32256
- s.straddleSnapCarryLen = 0;
32257
- runStart = lineStart;
32258
- }
32259
- boundaryAt = buf.indexOf(boundaryMarker, boundaryAt + boundaryMarker.length);
32260
- }
32261
- lineStart = lineEnd;
32262
- nl = buf.indexOf(LF, lineStart);
32263
- }
32264
- sinkWrite(s.out, buf, runStart, lineStart);
32265
- return { lastSnapStart, lastSnapEnd, trailStart: lineStart };
32266
- }
32267
- function captureSnap(s, buf, chunk, lastSnapStart, lastSnapEnd) {
32268
- if (lastSnapStart !== -1) {
32269
- s.lastSnapLen = lastSnapEnd - lastSnapStart;
32270
- if (s.lastSnapBuf === undefined || s.lastSnapLen > s.lastSnapBuf.length) {
32271
- s.lastSnapBuf = Buffer.allocUnsafe(s.lastSnapLen);
32272
- }
32273
- buf.copy(s.lastSnapBuf, 0, lastSnapStart, lastSnapEnd);
32274
- s.lastSnapSrc = s.lastSnapBuf;
32275
- } else if (s.straddleSnapCarryLen > 0) {
32276
- s.lastSnapLen = s.straddleSnapCarryLen + s.straddleSnapTailEnd;
32277
- if (s.lastSnapBuf === undefined || s.lastSnapLen > s.lastSnapBuf.length) {
32278
- s.lastSnapBuf = Buffer.allocUnsafe(s.lastSnapLen);
32279
- }
32280
- s.carryBuf.copy(s.lastSnapBuf, 0, 0, s.straddleSnapCarryLen);
32281
- chunk.copy(s.lastSnapBuf, s.straddleSnapCarryLen, 0, s.straddleSnapTailEnd);
32282
- s.lastSnapSrc = s.lastSnapBuf;
32283
- }
32284
- }
32285
- function captureCarry(s, buf, trailStart) {
32286
- s.carryLen = buf.length - trailStart;
32287
- if (s.carryLen > 0) {
32288
- if (s.carryBuf === undefined || s.carryLen > s.carryBuf.length) {
32289
- s.carryBuf = Buffer.allocUnsafe(s.carryLen);
32290
- }
32291
- buf.copy(s.carryBuf, 0, trailStart, buf.length);
32292
- }
32293
- }
32294
- function finalizeOutput(s) {
32295
- if (s.carryLen > 0) {
32296
- const cb = s.carryBuf;
32297
- if (hasPrefix(cb, ATTR_SNAP_PREFIX, 0, s.carryLen)) {
32298
- s.lastSnapSrc = cb;
32299
- s.lastSnapLen = s.carryLen;
32300
- } else {
32301
- sinkWrite(s.out, cb, 0, s.carryLen);
32302
- }
32303
- }
32304
- if (s.lastSnapSrc) {
32305
- if (s.out.len > 0 && s.out.buf[s.out.len - 1] !== LF) {
32306
- sinkWrite(s.out, LF_BYTE, 0, 1);
32307
- }
32308
- sinkWrite(s.out, s.lastSnapSrc, 0, s.lastSnapLen);
32309
- }
32310
- }
32311
- async function readTranscriptForLoad(filePath, fileSize) {
32312
- const boundaryMarker = compactBoundaryMarker();
32313
- const CHUNK_SIZE = TRANSCRIPT_READ_CHUNK_SIZE;
32314
- const s = {
32315
- out: {
32316
- buf: Buffer.allocUnsafe(Math.min(fileSize, 8 * 1024 * 1024)),
32317
- len: 0,
32318
- cap: fileSize + 1
32319
- },
32320
- boundaryStartOffset: 0,
32321
- hasPreservedSegment: false,
32322
- lastSnapSrc: null,
32323
- lastSnapLen: 0,
32324
- lastSnapBuf: undefined,
32325
- bufFileOff: 0,
32326
- carryLen: 0,
32327
- carryBuf: undefined,
32328
- straddleSnapCarryLen: 0,
32329
- straddleSnapTailEnd: 0
32330
- };
32331
- const chunk = Buffer.allocUnsafe(CHUNK_SIZE);
32332
- const fd = await fsOpen(filePath, "r");
32333
- try {
32334
- let filePos = 0;
32335
- while (filePos < fileSize) {
32336
- const { bytesRead } = await fd.read(chunk, 0, Math.min(CHUNK_SIZE, fileSize - filePos), filePos);
32337
- if (bytesRead === 0)
32338
- break;
32339
- filePos += bytesRead;
32340
- const chunkOff = processStraddle(s, chunk, bytesRead);
32341
- let buf;
32342
- if (s.carryLen > 0) {
32343
- const bufLen = s.carryLen + (bytesRead - chunkOff);
32344
- buf = Buffer.allocUnsafe(bufLen);
32345
- s.carryBuf.copy(buf, 0, 0, s.carryLen);
32346
- chunk.copy(buf, s.carryLen, chunkOff, bytesRead);
32347
- } else {
32348
- buf = chunk.subarray(chunkOff, bytesRead);
32349
- }
32350
- const r = scanChunkLines(s, buf, boundaryMarker);
32351
- captureSnap(s, buf, chunk, r.lastSnapStart, r.lastSnapEnd);
32352
- captureCarry(s, buf, r.trailStart);
32353
- s.bufFileOff += r.trailStart;
32354
- }
32355
- finalizeOutput(s);
32356
- } finally {
32357
- await fd.close();
32358
- }
32359
- return {
32360
- boundaryStartOffset: s.boundaryStartOffset,
32361
- postBoundaryBuf: s.out.buf.subarray(0, s.out.len),
32362
- hasPreservedSegment: s.hasPreservedSegment
32363
- };
32364
- }
32365
- var TRANSCRIPT_READ_CHUNK_SIZE, SKIP_PRECOMPACT_THRESHOLD, _compactBoundaryMarker, ATTR_SNAP_PREFIX, SYSTEM_PREFIX, LF = 10, LF_BYTE, BOUNDARY_SEARCH_BOUND = 256;
32366
- var init_scanner = __esm(() => {
32367
- TRANSCRIPT_READ_CHUNK_SIZE = 1024 * 1024;
32368
- SKIP_PRECOMPACT_THRESHOLD = 5 * 1024 * 1024;
32369
- ATTR_SNAP_PREFIX = Buffer.from('{"type":"attribution-snapshot"');
32370
- SYSTEM_PREFIX = Buffer.from('{"type":"system"');
32371
- LF_BYTE = Buffer.from([LF]);
32372
- });
32373
-
32374
- // src/engine/session/predicates.ts
32375
- function isTranscriptMessage(entry) {
32376
- return entry.type === "user" || entry.type === "assistant" || entry.type === "attachment" || entry.type === "system";
32377
- }
32378
- function isChainParticipant(m) {
32379
- return m.type !== "progress";
32380
- }
32381
- function isLegacyProgressEntry(entry) {
32382
- return typeof entry === "object" && entry !== null && "type" in entry && entry.type === "progress" && "uuid" in entry && typeof entry.uuid === "string";
32383
- }
32384
- function isEphemeralToolProgress(dataType) {
32385
- return typeof dataType === "string" && EPHEMERAL_PROGRESS_TYPES.has(dataType);
32386
- }
32387
- function isCompactBoundaryMessage(message) {
32388
- return message?.type === "system" && message.subtype === "compact_boundary";
32389
- }
32390
- var EPHEMERAL_PROGRESS_TYPES;
32391
- var init_predicates = __esm(() => {
32392
- EPHEMERAL_PROGRESS_TYPES = new Set([
32393
- "bash_progress",
32394
- "powershell_progress",
32395
- "mcp_progress"
32396
- ]);
32397
- });
32398
-
32399
- // src/bootstrap/state.ts
32400
- import { existsSync as existsSync4 } from "fs";
32401
- import { randomUUID as randomUUID3 } from "crypto";
32402
- import { homedir as homedir5 } from "os";
32403
- import { dirname as dirname5, join as join8 } from "path";
32404
- function getOriginalCwd() {
32405
- return _originalCwd2;
32406
- }
32407
- function setOriginalCwd(v) {
32408
- _originalCwd2 = v;
32409
- }
32410
- function getCwdState() {
32411
- return _cwdState;
32412
- }
32413
- function setCwdState(v) {
32414
- _cwdState = v;
32415
- }
32416
- function getProjectRoot() {
32417
- let dir = process.cwd();
32418
- for (;; ) {
32419
- if (existsSync4(join8(dir, ".git"))) {
32420
- return dir;
32421
- }
32422
- const parent = dirname5(dir);
32423
- if (parent === dir) {
32424
- return process.cwd();
32425
- }
32426
- dir = parent;
32427
- }
32428
- }
32429
- function setProjectRoot(_v) {}
32430
- function getSessionId() {
32431
- return _sessionId2;
32432
- }
32433
- function switchSession(id, _projectDir) {
32434
- if (id)
32435
- _sessionId2 = id;
32436
- }
32437
- function getIsInteractive() {
32438
- return !_isNonInteractiveSession;
32439
- }
32440
- function getIsNonInteractiveSession() {
32441
- return _isNonInteractiveSession;
32442
- }
32443
- function setIsInteractive(v) {
32444
- _isNonInteractiveSession = !v;
32445
- }
32446
- function setClientType(t) {
32447
- _clientType = t;
32448
- }
32449
- function getClientType() {
32450
- return _clientType;
32451
- }
32452
- function setQuestionPreviewFormat(f) {
32453
- _questionPreviewFormat = f;
32454
- }
32455
- function getQuestionPreviewFormat() {
32456
- return _questionPreviewFormat;
32457
- }
32458
- function setSessionBypassPermissionsMode(v) {
32459
- _sessionBypassPermissionsMode = v;
32460
- }
32461
- function isSessionPersistenceDisabled() {
32462
- return _sessionPersistenceDisabled;
32463
- }
32464
- function setSessionPersistenceDisabled(v) {
32465
- _sessionPersistenceDisabled = v;
32466
- }
32467
- function setFlagSettingsPath(p) {
32468
- _flagSettingsPath = p;
32469
- }
32470
- function setAllowedSettingSources(sources) {
32471
- _allowedSettingSources = sources;
32472
- }
32473
- function freshCostState() {
32474
- return {
32475
- totalAPIDuration: 0,
32476
- totalAPIDurationWithoutRetries: 0,
32477
- totalToolDuration: 0,
32478
- totalLinesAdded: 0,
32479
- totalLinesRemoved: 0,
32480
- modelUsage: {}
32481
- };
32482
- }
32483
- function addToTotalLinesChanged(added, removed) {
32484
- _costState.totalLinesAdded += added;
32485
- _costState.totalLinesRemoved += removed;
32486
- }
32487
- function getModelUsage() {
32488
- return _costState.modelUsage;
32489
- }
32490
- function getTotalAPIDuration() {
32491
- return _costState.totalAPIDuration;
32492
- }
32493
- function getTotalAPIDurationWithoutRetries() {
32494
- return _costState.totalAPIDurationWithoutRetries;
32495
- }
32496
- function getTotalToolDuration() {
32497
- return _costState.totalToolDuration;
32498
- }
32499
- function getTotalDuration() {
32500
- return _costState.totalAPIDuration + _costState.totalToolDuration;
32501
- }
32502
- function getTotalLinesAdded() {
32503
- return _costState.totalLinesAdded;
32504
- }
32505
- function getTotalLinesRemoved() {
32506
- return _costState.totalLinesRemoved;
32507
- }
32508
- function getTotalInputTokens() {
32509
- return Object.values(_costState.modelUsage).reduce((sum, u) => sum + u.inputTokens, 0);
32510
- }
32511
- function getTotalOutputTokens() {
32512
- return Object.values(_costState.modelUsage).reduce((sum, u) => sum + u.outputTokens, 0);
32513
- }
32514
- function getTotalCacheReadInputTokens() {
32515
- return Object.values(_costState.modelUsage).reduce((sum, u) => sum + u.cacheReadInputTokens, 0);
32516
- }
32517
- function getTotalCacheCreationInputTokens() {
32518
- return Object.values(_costState.modelUsage).reduce((sum, u) => sum + u.cacheCreationInputTokens, 0);
32519
- }
32520
- function getTotalWebSearchRequests() {
32521
- return Object.values(_costState.modelUsage).reduce((sum, u) => sum + u.webSearchRequests, 0);
32522
- }
32523
- function setCostStateForRestore(data) {
32524
- _costState = {
32525
- totalAPIDuration: data.totalAPIDuration ?? 0,
32526
- totalAPIDurationWithoutRetries: data.totalAPIDurationWithoutRetries ?? 0,
32527
- totalToolDuration: data.totalToolDuration ?? 0,
32528
- totalLinesAdded: data.totalLinesAdded ?? 0,
32529
- totalLinesRemoved: data.totalLinesRemoved ?? 0,
32530
- modelUsage: data.modelUsage ? { ...data.modelUsage } : {}
32531
- };
32532
- }
32533
- function resetCostState() {
32534
- _costState = freshCostState();
32535
- }
32536
- function getSessionCreatedTeams() {
32537
- return sessionCreatedTeams;
32538
- }
32539
- function defaultTranscriptDir() {
32540
- const root = process.env.ATLAS_CONFIG_DIR ?? join8(homedir5(), getConfigDirName());
32541
- return join8(root, "sessions");
32542
- }
32543
- function getTranscriptPathForSession2(sessionId) {
32544
- const dir = _transcriptDir ?? defaultTranscriptDir();
32545
- return join8(dir, `${sessionId}.jsonl`);
32546
- }
32547
- function setMainThreadAgentType(agentType) {
32548
- _mainThreadAgentType = agentType;
32549
- }
32550
- function getMainThreadAgentType() {
32551
- return _mainThreadAgentType;
32552
- }
32553
- function setTrustAccepted(accepted) {
32554
- _trustAccepted = accepted;
32555
- }
32556
- function hasTrustAccepted() {
32557
- return _trustAccepted;
32558
- }
32559
- var _originalCwd2, _cwdState, _sessionId2, _isNonInteractiveSession = false, _clientType, _questionPreviewFormat, _sessionBypassPermissionsMode = false, _sessionPersistenceDisabled = false, _flagSettingsPath, _allowedSettingSources, _costState, sessionCreatedTeams, _transcriptDir, _mainThreadAgentType, _trustAccepted = true;
32560
- var init_state = __esm(() => {
32561
- init_shared();
32562
- _originalCwd2 = process.cwd();
32563
- _cwdState = process.cwd();
32564
- _sessionId2 = randomUUID3();
32565
- _costState = freshCostState();
32566
- sessionCreatedTeams = new Set;
32567
- });
32568
-
32569
- // src/bootstrap/cwd.ts
32570
- import { AsyncLocalStorage } from "async_hooks";
32571
- function runWithCwdOverride(cwd, fn) {
32572
- return cwdOverrideStorage.run(cwd, fn);
32573
- }
32574
- function pwd() {
32575
- return cwdOverrideStorage.getStore() ?? getCwdState();
32576
- }
32577
- function getCwd() {
32578
- try {
32579
- return pwd();
32580
- } catch {
32581
- return getOriginalCwd();
32582
- }
32583
- }
32584
- var cwdOverrideStorage;
32585
- var init_cwd = __esm(() => {
32586
- init_state();
32587
- cwdOverrideStorage = new AsyncLocalStorage;
32588
- });
32589
-
32590
- // src/bootstrap/index.ts
32591
- var init_bootstrap = __esm(() => {
32592
- init_state();
32593
- init_cwd();
32594
- });
32595
-
32596
32191
  // src/engine/session/firstPrompt.ts
32597
32192
  function escapeRegExp2(str) {
32598
32193
  return str.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
@@ -33591,7 +33186,7 @@ class Project {
33591
33186
  let content = "";
33592
33187
  const resolvers = [];
33593
33188
  for (const { entry, resolve } of batch) {
33594
- const line = jsonStringify2(entry) + `
33189
+ const line = jsonStringify(entry) + `
33595
33190
  `;
33596
33191
  if (content.length + line.length >= this.MAX_CHUNK_BYTES) {
33597
33192
  await this.appendToFile(filePath, content);
@@ -33910,7 +33505,7 @@ class Project {
33910
33505
  }
33911
33506
  }
33912
33507
  function appendEntryToFile(fullPath, entry) {
33913
- const line = jsonStringify2(entry) + `
33508
+ const line = jsonStringify(entry) + `
33914
33509
  `;
33915
33510
  try {
33916
33511
  appendFileSync(fullPath, line, { mode: 384 });
@@ -35909,7 +35504,7 @@ async function writeToMailbox(recipientName, message, teamName) {
35909
35504
  read: false
35910
35505
  };
35911
35506
  messages.push(newMessage);
35912
- await writeFile(inboxPath, jsonStringify2(messages, 2), "utf-8");
35507
+ await writeFile(inboxPath, jsonStringify(messages, 2), "utf-8");
35913
35508
  logForDebugging(`[TeammateMailbox] Wrote message to ${recipientName}'s inbox from ${message.from}`);
35914
35509
  } catch (error) {
35915
35510
  logForDebugging(`Failed to write to inbox for ${recipientName}: ${error}`);
@@ -35944,7 +35539,7 @@ async function markMessageAsReadByIndex(agentName, teamName, messageIndex) {
35944
35539
  return;
35945
35540
  }
35946
35541
  messages[messageIndex] = { ...message, read: true };
35947
- await writeFile(inboxPath, jsonStringify2(messages, 2), "utf-8");
35542
+ await writeFile(inboxPath, jsonStringify(messages, 2), "utf-8");
35948
35543
  logForDebugging(`[TeammateMailbox] markMessageAsReadByIndex: marked message at index ${messageIndex} as read`);
35949
35544
  } catch (error) {
35950
35545
  const code = getErrnoCode(error);
@@ -35983,7 +35578,7 @@ async function markMessagesAsRead(agentName, teamName) {
35983
35578
  logForDebugging(`[TeammateMailbox] markMessagesAsRead: ${unreadCount} unread of ${messages.length} total`);
35984
35579
  for (const m of messages)
35985
35580
  m.read = true;
35986
- await writeFile(inboxPath, jsonStringify2(messages, 2), "utf-8");
35581
+ await writeFile(inboxPath, jsonStringify(messages, 2), "utf-8");
35987
35582
  logForDebugging(`[TeammateMailbox] markMessagesAsRead: WROTE ${unreadCount} message(s) as read to ${inboxPath}`);
35988
35583
  } catch (error) {
35989
35584
  const code = getErrnoCode(error);
@@ -36172,7 +35767,7 @@ async function sendShutdownRequestToMailbox(targetName, teamName, reason) {
36172
35767
  });
36173
35768
  await writeToMailbox(targetName, {
36174
35769
  from: senderName,
36175
- text: jsonStringify2(shutdownMessage),
35770
+ text: jsonStringify(shutdownMessage),
36176
35771
  timestamp: new Date().toISOString(),
36177
35772
  color: getTeammateColor()
36178
35773
  }, resolvedTeamName);
@@ -36278,7 +35873,7 @@ async function markMessagesAsReadByPredicate(agentName, predicate, teamName) {
36278
35873
  return;
36279
35874
  }
36280
35875
  const updatedMessages = messages.map((m) => !m.read && predicate(m) ? { ...m, read: true } : m);
36281
- await writeFile(inboxPath, jsonStringify2(updatedMessages, 2), "utf-8");
35876
+ await writeFile(inboxPath, jsonStringify(updatedMessages, 2), "utf-8");
36282
35877
  } catch (error) {
36283
35878
  const code = getErrnoCode(error);
36284
35879
  if (code === "ENOENT") {
@@ -37092,7 +36687,7 @@ function formatAgentLine(agent) {
37092
36687
  function getPrompt(agents) {
37093
36688
  const list = agents.length > 0 ? agents.map(formatAgentLine).join(`
37094
36689
  `) : "- general-purpose: General-purpose agent for researching and executing multi-step tasks.";
37095
- return "Launch a subagent to run a self-contained task in an isolated context. " + "Provide a short description (3-5 words) and a fully self-contained prompt " + "(the subagent cannot see this conversation). " + "Be cost-aware about delegating: prefer to do the work inline in this " + "conversation for a small task with a known, bounded target (a single-file " + "edit, a quick lookup, a change you can finish without broad exploration) — " + "spawning a subagent has overhead. Delegate when the task is genuinely " + "parallelizable or would otherwise flood this context with material you do " + "not need to keep (a broad multi-file search, an isolated multi-step " + "implementation, or independent work that can run alongside your own). Keep " + "each delegated brief narrow and evidence-focused: name the exact goal, the " + "files or area, and the expected deliverable rather than a broad " + '"figure this out." Because the subagent cannot see this conversation, its ' + "prompt must be fully self-contained — state every constraint, file, and " + "reporting requirement it needs. " + "Set run_in_background to true to launch a subagent that runs while you " + "continue working in this conversation; you will receive a task-notification " + "when it completes. Use this only for genuinely parallel work, not to defer " + "a result you need before you can proceed. " + `Available agent types and the tools they have access to:
36690
+ return "Launch a subagent to run a self-contained task in an isolated context. " + "Provide a short description (3-5 words) and a fully self-contained prompt " + "(the subagent cannot see this conversation). " + "Be cost-aware about delegating: prefer to do the work inline in this " + "conversation for a small task with a known, bounded target (a single-file " + "edit, a quick lookup, a change you can finish without broad exploration) — " + "spawning a subagent has overhead. Delegate when the task is genuinely " + "parallelizable or would otherwise flood this context with material you do " + "not need to keep (a broad multi-file search, an isolated multi-step " + "implementation, or independent work that can run alongside your own). Keep " + "each delegated brief narrow and evidence-focused: name the exact goal, the " + "files or area, and the expected deliverable rather than a broad " + '"figure this out." Because the subagent cannot see this conversation, its ' + "prompt must be fully self-contained — state every constraint, file, and " + "reporting requirement it needs. " + "Subagents run in the background by default; you will receive a " + "task-notification when one completes — do not poll or sleep waiting for " + "it. Set run_in_background to false only when you need the result before " + "you can proceed. Use background for genuinely parallel work, not to defer " + "a result you need immediately. " + `Available agent types and the tools they have access to:
37096
36691
  ${list}
37097
36692
  ` + `The ${AGENT_TOOL_NAME} tool runs the subagent and returns its final result ` + "when it completes; act on that result once it is returned. " + "Do not predict or assume what the subagent will find — wait for its " + "returned result and act on what it actually reports.";
37098
36693
  }
@@ -37204,8 +36799,44 @@ var init_runAgent = __esm(() => {
37204
36799
  init_localAgentTask();
37205
36800
  });
37206
36801
 
36802
+ // src/engine/tools/agent/backgroundTracker.ts
36803
+ function trackBackgroundAgent(p) {
36804
+ const handled = p.then(() => {}, () => {});
36805
+ pendingBackgroundAgents.add(handled);
36806
+ handled.finally(() => {
36807
+ pendingBackgroundAgents.delete(handled);
36808
+ });
36809
+ }
36810
+ function hasPendingBackgroundAgents() {
36811
+ return pendingBackgroundAgents.size > 0;
36812
+ }
36813
+ async function drainPendingBackgroundAgents(signal) {
36814
+ if (pendingBackgroundAgents.size === 0)
36815
+ return;
36816
+ const promises = Array.from(pendingBackgroundAgents);
36817
+ if (signal?.aborted)
36818
+ return;
36819
+ await Promise.allSettled(promises);
36820
+ }
36821
+ function resetBackgroundAgentTracker() {
36822
+ pendingBackgroundAgents.clear();
36823
+ }
36824
+ var pendingBackgroundAgents;
36825
+ var init_backgroundTracker = __esm(() => {
36826
+ pendingBackgroundAgents = new Set;
36827
+ });
36828
+
37207
36829
  // src/engine/tools/agent/AgentTool.ts
37208
36830
  import { randomUUID as randomUUID5 } from "crypto";
36831
+ function isAgentBackgroundByDefault() {
36832
+ return !isEnvTruthy(process.env.ATLAS_AGENT_DEFAULT_FOREGROUND);
36833
+ }
36834
+ function shouldRunInBackground(runInBg) {
36835
+ if (isAgentBackgroundByDefault()) {
36836
+ return runInBg !== false;
36837
+ }
36838
+ return !!runInBg;
36839
+ }
37209
36840
  function resolveAgentDefinition(subagentType, agents) {
37210
36841
  if (!subagentType)
37211
36842
  return GENERAL_PURPOSE_AGENT;
@@ -37229,6 +36860,8 @@ var init_AgentTool = __esm(() => {
37229
36860
  init_coordinator();
37230
36861
  init_task2();
37231
36862
  init_localAgentTask();
36863
+ init_shared();
36864
+ init_backgroundTracker();
37232
36865
  AGENT_TOOL_INPUT_SCHEMA = {
37233
36866
  type: "object",
37234
36867
  properties: {
@@ -37311,9 +36944,9 @@ var init_AgentTool = __esm(() => {
37311
36944
  const allowFanOut = isCoordinatorMode() && childSpawnDepth < MAX_WORKER_SPAWN_DEPTH;
37312
36945
  const resolvedTools = resolveAgentTools(agentDefinition, availableTools, allowFanOut).resolvedTools;
37313
36946
  const agentId = "agent-" + randomUUID5();
37314
- if (input.run_in_background) {
36947
+ if (shouldRunInBackground(input.run_in_background)) {
37315
36948
  const outputFile = getTaskOutputPath(agentId);
37316
- runAsyncAgentLifecycle({
36949
+ const bgPromise = runAsyncAgentLifecycle({
37317
36950
  agentDefinition,
37318
36951
  prompt: input.prompt,
37319
36952
  tools: resolvedTools,
@@ -37333,6 +36966,7 @@ var init_AgentTool = __esm(() => {
37333
36966
  error: err instanceof Error ? err.message : String(err)
37334
36967
  });
37335
36968
  });
36969
+ trackBackgroundAgent(bgPromise);
37336
36970
  return {
37337
36971
  data: {
37338
36972
  status: "async_launched",
@@ -51681,6 +51315,7 @@ var init_agent = __esm(() => {
51681
51315
  init_forkSubagent();
51682
51316
  init_agentToolUtils();
51683
51317
  init_prompt();
51318
+ init_backgroundTracker();
51684
51319
  });
51685
51320
 
51686
51321
  // src/engine/tools/bash/bashPrompt.ts
@@ -52369,7 +52004,7 @@ var init_configTool = __esm(() => {
52369
52004
  if (value === undefined) {
52370
52005
  return `Getting ${setting}`;
52371
52006
  }
52372
- return `Setting ${setting} to ${jsonStringify2(value)}`;
52007
+ return `Setting ${setting} to ${jsonStringify(value)}`;
52373
52008
  },
52374
52009
  async checkPermissions(input, _context) {
52375
52010
  const { setting, value } = input;
@@ -52378,7 +52013,7 @@ var init_configTool = __esm(() => {
52378
52013
  }
52379
52014
  return {
52380
52015
  behavior: "ask",
52381
- message: `Set ${setting} to ${jsonStringify2(value)}`
52016
+ message: `Set ${setting} to ${jsonStringify(value)}`
52382
52017
  };
52383
52018
  },
52384
52019
  async call(args, _context) {
@@ -52477,13 +52112,13 @@ var init_configTool = __esm(() => {
52477
52112
  return {
52478
52113
  tool_use_id: toolUseID,
52479
52114
  type: "tool_result",
52480
- content: `${content.setting} = ${jsonStringify2(content.value)}`
52115
+ content: `${content.setting} = ${jsonStringify(content.value)}`
52481
52116
  };
52482
52117
  }
52483
52118
  return {
52484
52119
  tool_use_id: toolUseID,
52485
52120
  type: "tool_result",
52486
- content: `Set ${content.setting} to ${jsonStringify2(content.newValue)}`
52121
+ content: `Set ${content.setting} to ${jsonStringify(content.newValue)}`
52487
52122
  };
52488
52123
  }
52489
52124
  return {
@@ -65262,7 +64897,7 @@ async function validateContentTokens(content, ext, maxTokens) {
65262
64897
  async function callInner(file_path, fullFilePath, resolvedFilePath, ext, offset, limit, pages, maxSizeBytes, maxTokens, readFileState, context) {
65263
64898
  if (ext === "ipynb") {
65264
64899
  const cells = await readNotebook(resolvedFilePath);
65265
- const cellsJson = jsonStringify2(cells);
64900
+ const cellsJson = jsonStringify(cells);
65266
64901
  const cellsJsonBytes = Buffer.byteLength(cellsJson);
65267
64902
  if (cellsJsonBytes > maxSizeBytes) {
65268
64903
  throw new Error(`Notebook content (${formatFileSize(cellsJsonBytes)}) exceeds maximum allowed size (${formatFileSize(maxSizeBytes)}). ` + `Use ${BASH_TOOL_NAME2} with jq to read specific portions:
@@ -67599,7 +67234,7 @@ var init_listMcpResourcesTool = __esm(() => {
67599
67234
  return i.server ? `List MCP resources from server "${i.server}"` : "List all MCP resources";
67600
67235
  },
67601
67236
  isResultTruncated(output) {
67602
- return isOutputLineTruncated(jsonStringify2(output));
67237
+ return isOutputLineTruncated(jsonStringify(output));
67603
67238
  },
67604
67239
  mapToolResultToToolResultBlockParam(content, toolUseID) {
67605
67240
  if (!content || content.length === 0) {
@@ -67612,7 +67247,7 @@ var init_listMcpResourcesTool = __esm(() => {
67612
67247
  return {
67613
67248
  tool_use_id: toolUseID,
67614
67249
  type: "tool_result",
67615
- content: jsonStringify2(content)
67250
+ content: jsonStringify(content)
67616
67251
  };
67617
67252
  }
67618
67253
  };
@@ -68732,7 +68367,7 @@ var init_webSearchTool = __esm(() => {
68732
68367
  `;
68733
68368
  } else {
68734
68369
  if (result.content?.length > 0) {
68735
- formattedOutput += `Links: ${jsonStringify2(result.content)}
68370
+ formattedOutput += `Links: ${jsonStringify(result.content)}
68736
68371
 
68737
68372
  `;
68738
68373
  } else {
@@ -68881,13 +68516,13 @@ var init_readMcpResourceTool = __esm(() => {
68881
68516
  return `Read resource "${i.uri}" from server "${i.server}"`;
68882
68517
  },
68883
68518
  isResultTruncated(output) {
68884
- return isOutputLineTruncated(jsonStringify2(output));
68519
+ return isOutputLineTruncated(jsonStringify(output));
68885
68520
  },
68886
68521
  mapToolResultToToolResultBlockParam(content, toolUseID) {
68887
68522
  return {
68888
68523
  tool_use_id: toolUseID,
68889
68524
  type: "tool_result",
68890
- content: jsonStringify2(content)
68525
+ content: jsonStringify(content)
68891
68526
  };
68892
68527
  }
68893
68528
  };
@@ -69210,7 +68845,7 @@ var init_notebookEditTool = __esm(() => {
69210
68845
  }
69211
68846
  }
69212
68847
  const IPYNB_INDENT = 1;
69213
- const updatedContent = jsonStringify2(notebook, IPYNB_INDENT);
68848
+ const updatedContent = jsonStringify(notebook, IPYNB_INDENT);
69214
68849
  writeTextContent(fullPath, updatedContent, encoding, lineEndings);
69215
68850
  readFileState?.set(fullPath, {
69216
68851
  content: updatedContent,
@@ -69471,7 +69106,7 @@ async function readTeamFileAsync(teamName) {
69471
69106
  async function writeTeamFileAsync(teamName, teamFile) {
69472
69107
  const teamDir = getTeamDir(teamName);
69473
69108
  await mkdir6(teamDir, { recursive: true });
69474
- await writeFile4(getTeamFilePath(teamName), jsonStringify2(teamFile, 2));
69109
+ await writeFile4(getTeamFilePath(teamName), jsonStringify(teamFile, 2));
69475
69110
  }
69476
69111
  async function destroyWorktree(worktreePath) {
69477
69112
  const gitFilePath = join24(worktreePath, ".git");
@@ -70560,7 +70195,7 @@ async function sendPermissionRequestViaMailbox(request) {
70560
70195
  });
70561
70196
  await writeToMailbox(leaderName, {
70562
70197
  from: request.workerName,
70563
- text: jsonStringify2(message),
70198
+ text: jsonStringify(message),
70564
70199
  timestamp: new Date().toISOString(),
70565
70200
  color: request.workerColor
70566
70201
  }, request.teamName);
@@ -71541,7 +71176,7 @@ async function handleShutdownRequest(targetName, reason, context) {
71541
71176
  });
71542
71177
  await writeToMailbox(targetName, {
71543
71178
  from: senderName,
71544
- text: jsonStringify2(shutdownMessage),
71179
+ text: jsonStringify(shutdownMessage),
71545
71180
  timestamp: new Date().toISOString(),
71546
71181
  color: getTeammateColor()
71547
71182
  }, teamName);
@@ -71565,7 +71200,7 @@ async function handleShutdownApproval(requestId, _context) {
71565
71200
  });
71566
71201
  await writeToMailbox(TEAM_LEAD_NAME, {
71567
71202
  from: agentName,
71568
- text: jsonStringify2(approvedMessage),
71203
+ text: jsonStringify(approvedMessage),
71569
71204
  timestamp: new Date().toISOString(),
71570
71205
  color: getTeammateColor()
71571
71206
  }, teamName);
@@ -71587,7 +71222,7 @@ async function handleShutdownRejection(requestId, reason) {
71587
71222
  });
71588
71223
  await writeToMailbox(TEAM_LEAD_NAME, {
71589
71224
  from: agentName,
71590
- text: jsonStringify2(rejectedMessage),
71225
+ text: jsonStringify(rejectedMessage),
71591
71226
  timestamp: new Date().toISOString(),
71592
71227
  color: getTeammateColor()
71593
71228
  }, teamName);
@@ -71616,7 +71251,7 @@ async function handlePlanApproval(recipientName, requestId, context) {
71616
71251
  };
71617
71252
  await writeToMailbox(recipientName, {
71618
71253
  from: TEAM_LEAD_NAME,
71619
- text: jsonStringify2(approvalResponse),
71254
+ text: jsonStringify(approvalResponse),
71620
71255
  timestamp: new Date().toISOString()
71621
71256
  }, teamName);
71622
71257
  return {
@@ -71642,7 +71277,7 @@ async function handlePlanRejection(recipientName, requestId, feedback, context)
71642
71277
  };
71643
71278
  await writeToMailbox(recipientName, {
71644
71279
  from: TEAM_LEAD_NAME,
71645
- text: jsonStringify2(rejectionResponse),
71280
+ text: jsonStringify(rejectionResponse),
71646
71281
  timestamp: new Date().toISOString()
71647
71282
  }, teamName);
71648
71283
  return {
@@ -71848,7 +71483,7 @@ var init_sendMessageTool = __esm(() => {
71848
71483
  content: [
71849
71484
  {
71850
71485
  type: "text",
71851
- text: jsonStringify2(data)
71486
+ text: jsonStringify(data)
71852
71487
  }
71853
71488
  ]
71854
71489
  };
@@ -71984,7 +71619,7 @@ var init_snipTool = __esm(() => {
71984
71619
  content: [
71985
71620
  {
71986
71621
  type: "text",
71987
- text: jsonStringify2(data)
71622
+ text: jsonStringify(data)
71988
71623
  }
71989
71624
  ]
71990
71625
  };
@@ -72189,7 +71824,7 @@ async function createTask(taskListId, taskData) {
72189
71824
  const id = String(highestId + 1);
72190
71825
  const task = { id, ...taskData };
72191
71826
  const path = getTaskPath(taskListId, id);
72192
- await writeFile5(path, jsonStringify2(task, 2));
71827
+ await writeFile5(path, jsonStringify(task, 2));
72193
71828
  notifyTasksUpdated();
72194
71829
  return id;
72195
71830
  } finally {
@@ -72226,7 +71861,7 @@ async function updateTaskUnsafe(taskListId, taskId, updates) {
72226
71861
  }
72227
71862
  const updated = { ...existing, ...updates, id: taskId };
72228
71863
  const path = getTaskPath(taskListId, taskId);
72229
- await writeFile5(path, jsonStringify2(updated, 2));
71864
+ await writeFile5(path, jsonStringify(updated, 2));
72230
71865
  notifyTasksUpdated();
72231
71866
  return updated;
72232
71867
  }
@@ -72726,7 +72361,7 @@ var init_teamCreateTool = __esm(() => {
72726
72361
  content: [
72727
72362
  {
72728
72363
  type: "text",
72729
- text: jsonStringify2(data)
72364
+ text: jsonStringify(data)
72730
72365
  }
72731
72366
  ]
72732
72367
  };
@@ -72858,7 +72493,7 @@ var init_teamDeleteTool = __esm(() => {
72858
72493
  content: [
72859
72494
  {
72860
72495
  type: "text",
72861
- text: jsonStringify2(data)
72496
+ text: jsonStringify(data)
72862
72497
  }
72863
72498
  ]
72864
72499
  };
@@ -78861,6 +78496,285 @@ var init_mcp3 = __esm(() => {
78861
78496
  init_mcpFetch();
78862
78497
  });
78863
78498
 
78499
+ // src/engine/pipeline/errorClassification.ts
78500
+ function classifyToolError(error) {
78501
+ if (error instanceof Error) {
78502
+ const errnoCode = error.code;
78503
+ if (typeof errnoCode === "string") {
78504
+ return `Error:${errnoCode}`;
78505
+ }
78506
+ if (error.name && error.name !== "Error" && error.name.length > 3) {
78507
+ return error.name.slice(0, 60);
78508
+ }
78509
+ return "Error";
78510
+ }
78511
+ return "UnknownError";
78512
+ }
78513
+
78514
+ // src/engine/pipeline/schemaValidation.ts
78515
+ function typeName(v) {
78516
+ if (v === null)
78517
+ return "null";
78518
+ if (Array.isArray(v))
78519
+ return "array";
78520
+ return typeof v;
78521
+ }
78522
+ function checkBasicType(value, type) {
78523
+ switch (type) {
78524
+ case "string":
78525
+ return typeof value === "string" ? null : `expected string, got ${typeName(value)}`;
78526
+ case "number":
78527
+ if (typeof value === "number") {
78528
+ return Number.isFinite(value) ? null : "expected number, got non-finite number";
78529
+ }
78530
+ return `expected number, got ${typeName(value)}`;
78531
+ case "integer":
78532
+ if (typeof value === "number") {
78533
+ return Number.isInteger(value) ? null : "expected integer, got non-integer number";
78534
+ }
78535
+ return `expected integer, got ${typeName(value)}`;
78536
+ case "boolean":
78537
+ return typeof value === "boolean" ? null : `expected boolean, got ${typeName(value)}`;
78538
+ case "array":
78539
+ return Array.isArray(value) ? null : `expected array, got ${typeName(value)}`;
78540
+ case "object":
78541
+ return typeof value === "object" && value !== null && !Array.isArray(value) ? null : `expected object, got ${typeName(value)}`;
78542
+ case "null":
78543
+ return value === null ? null : `expected null, got ${typeName(value)}`;
78544
+ default:
78545
+ return null;
78546
+ }
78547
+ }
78548
+ function validateInputBySchema(input, schema) {
78549
+ if (!schema) {
78550
+ return { valid: true };
78551
+ }
78552
+ if (input === null || typeof input !== "object" || Array.isArray(input)) {
78553
+ return { valid: false, message: "expected object input" };
78554
+ }
78555
+ const record = input;
78556
+ const errors = [];
78557
+ const required = schema.required;
78558
+ if (Array.isArray(required)) {
78559
+ for (const rawKey of required) {
78560
+ const key = String(rawKey);
78561
+ if (!(key in record) || record[key] === undefined) {
78562
+ errors.push(`missing required field "${key}"`);
78563
+ }
78564
+ }
78565
+ }
78566
+ const properties = schema.properties;
78567
+ if (properties) {
78568
+ for (const [key, value] of Object.entries(record)) {
78569
+ if (value === undefined)
78570
+ continue;
78571
+ const propSchema = properties[key];
78572
+ if (!propSchema || typeof propSchema !== "object")
78573
+ continue;
78574
+ const type = propSchema.type;
78575
+ if (typeof type !== "string")
78576
+ continue;
78577
+ const err = checkBasicType(value, type);
78578
+ if (err)
78579
+ errors.push(`field "${key}": ${err}`);
78580
+ }
78581
+ }
78582
+ return errors.length > 0 ? { valid: false, message: errors.join("; ") } : { valid: true };
78583
+ }
78584
+ function buildSchemaNotSentHint(tool, discoveredToolNames) {
78585
+ if (!tool.shouldDefer)
78586
+ return null;
78587
+ if (discoveredToolNames.has(tool.name))
78588
+ return null;
78589
+ return `
78590
+
78591
+ This tool's schema was not sent to the API — it was not in the discovered-tool set derived from message history. ` + `Without the schema in your prompt, typed parameters (arrays, numbers, booleans) get emitted as strings and the client-side parser rejects them. ` + `Re-issue the call with correctly-typed parameters (arrays/numbers/booleans, not their string forms).`;
78592
+ }
78593
+
78594
+ // src/engine/pipeline/toolExecution.ts
78595
+ function mergeHookPermission(hookBehavior, gate, hookReason) {
78596
+ if (hookBehavior === "defer") {
78597
+ return {
78598
+ allowed: false,
78599
+ deferred: true,
78600
+ reason: hookReason ?? "deferred by hook"
78601
+ };
78602
+ }
78603
+ if (hookBehavior === "deny") {
78604
+ return { allowed: false, reason: "blocked by hook" };
78605
+ }
78606
+ if (!gate.allowed)
78607
+ return gate;
78608
+ if (hookBehavior === "ask") {
78609
+ return { allowed: false, ask: true, reason: "hook requested confirmation" };
78610
+ }
78611
+ return gate;
78612
+ }
78613
+ function findTool(tools, name) {
78614
+ return tools.find((t) => t.name === name || (t.aliases?.includes(name) ?? false));
78615
+ }
78616
+ async function executeToolUse(tu, assistantMsg, deps) {
78617
+ const tool = findTool(deps.tools, tu.name);
78618
+ if (!tool) {
78619
+ return {
78620
+ block: {
78621
+ type: "tool_result",
78622
+ tool_use_id: tu.id,
78623
+ content: `unknown tool: ${tu.name}`,
78624
+ is_error: true
78625
+ },
78626
+ isError: true
78627
+ };
78628
+ }
78629
+ const toolCallContext = deps.toolContext !== undefined ? { ...deps.toolContext, signal: deps.signal, checkPermission: deps.checkPermission } : { signal: deps.signal, checkPermission: deps.checkPermission };
78630
+ const schemaResult = validateInputBySchema(tu.input, tool.inputSchema);
78631
+ if (schemaResult.valid === false) {
78632
+ const discovered = deps.discoveredToolNames ?? new Set(deps.tools.map((t) => t.name));
78633
+ const schemaHint = buildSchemaNotSentHint(tool, discovered);
78634
+ const errorContent = schemaHint ? `${schemaResult.message}${schemaHint}` : schemaResult.message;
78635
+ return {
78636
+ block: {
78637
+ type: "tool_result",
78638
+ tool_use_id: tu.id,
78639
+ content: `<tool_use_error>InputValidationError: ${errorContent}</tool_use_error>`,
78640
+ is_error: true
78641
+ },
78642
+ isError: true
78643
+ };
78644
+ }
78645
+ const validation = await tool.validateInput?.(tu.input, toolCallContext);
78646
+ if (validation && validation.result === false) {
78647
+ return {
78648
+ block: {
78649
+ type: "tool_result",
78650
+ tool_use_id: tu.id,
78651
+ content: `<tool_use_error>InputValidationError: ${validation.message}</tool_use_error>`,
78652
+ is_error: true
78653
+ },
78654
+ isError: true
78655
+ };
78656
+ }
78657
+ const preOutcome = await deps.hooks?.preToolUse?.(tool, tu.input, tu.id);
78658
+ if (preOutcome?.blockingError) {
78659
+ return {
78660
+ block: {
78661
+ type: "tool_result",
78662
+ tool_use_id: tu.id,
78663
+ content: `<tool_use_error>hook blocked: ${preOutcome.blockingError}</tool_use_error>`,
78664
+ is_error: true
78665
+ },
78666
+ isError: true
78667
+ };
78668
+ }
78669
+ if (preOutcome?.preventContinuation) {
78670
+ return {
78671
+ block: {
78672
+ type: "tool_result",
78673
+ tool_use_id: tu.id,
78674
+ content: `<tool_use_error>Execution stopped by PreToolUse hook${preOutcome.stopReason ? `: ${preOutcome.stopReason}` : ""}</tool_use_error>`,
78675
+ is_error: true
78676
+ },
78677
+ isError: true
78678
+ };
78679
+ }
78680
+ const effectiveInput = preOutcome?.updatedInput ?? tu.input;
78681
+ const gateVerdict = deps.checkPermission ? await deps.checkPermission(tool, effectiveInput, {
78682
+ toolUseId: tu.id,
78683
+ assistantMessage: assistantMsg
78684
+ }) : { allowed: true };
78685
+ const verdict = mergeHookPermission(preOutcome?.hookBehavior, gateVerdict, preOutcome?.hookPermissionDecisionReason);
78686
+ if (verdict.deferred) {
78687
+ return { deferred: true, deferReason: verdict.reason, isError: false };
78688
+ }
78689
+ if (!verdict.allowed) {
78690
+ const content = verdict.ask ? `<tool_use_error>permission confirmation required (prompt 面残留守): ${verdict.reason ?? tu.name}</tool_use_error>` : `<tool_use_error>permission denied: ${verdict.reason ?? tu.name}</tool_use_error>`;
78691
+ return {
78692
+ block: {
78693
+ type: "tool_result",
78694
+ tool_use_id: tu.id,
78695
+ content,
78696
+ is_error: true
78697
+ },
78698
+ isError: true
78699
+ };
78700
+ }
78701
+ const callInput = verdict.updatedInput ?? effectiveInput;
78702
+ let block;
78703
+ let isError = false;
78704
+ let toolUseResult;
78705
+ try {
78706
+ const res = await tool.call(callInput, toolCallContext, undefined, assistantMsg);
78707
+ block = tool.mapToolResultToToolResultBlockParam(res.data, tu.id);
78708
+ toolUseResult = res.data;
78709
+ } catch (error) {
78710
+ const errorText = `tool error [${classifyToolError(error)}]: ${String(error?.message ?? error)}`;
78711
+ block = {
78712
+ type: "tool_result",
78713
+ tool_use_id: tu.id,
78714
+ content: `<tool_use_error>${errorText}</tool_use_error>`,
78715
+ is_error: true
78716
+ };
78717
+ isError = true;
78718
+ toolUseResult = errorText;
78719
+ }
78720
+ const postOutcome = await deps.hooks?.postToolUse?.(tool, callInput, block, tu.id);
78721
+ if (postOutcome?.updatedToolOutput !== undefined) {
78722
+ block = { ...block, content: postOutcome.updatedToolOutput };
78723
+ toolUseResult = postOutcome.updatedToolOutput;
78724
+ }
78725
+ return { block, isError, toolUseResult };
78726
+ }
78727
+ var init_toolExecution = () => {};
78728
+
78729
+ // src/engine/pipeline/toolOrchestration.ts
78730
+ function partitionToolCalls(toolUses, tools) {
78731
+ return toolUses.reduce((acc, tu) => {
78732
+ const tool = findTool(tools, tu.name);
78733
+ let safe = false;
78734
+ try {
78735
+ safe = tool ? tool.isConcurrencySafe(tu.input) : false;
78736
+ } catch {
78737
+ safe = false;
78738
+ }
78739
+ if (safe && acc[acc.length - 1]?.isConcurrencySafe) {
78740
+ acc[acc.length - 1].blocks.push(tu);
78741
+ } else {
78742
+ acc.push({ isConcurrencySafe: safe, blocks: [tu] });
78743
+ }
78744
+ return acc;
78745
+ }, []);
78746
+ }
78747
+ async function runToolBatch(toolUses, assistantMsg, deps) {
78748
+ const outcomes = [];
78749
+ for (const batch of partitionToolCalls(toolUses, deps.tools)) {
78750
+ for (const tu of batch.blocks) {
78751
+ const r = await executeToolUse(tu, assistantMsg, deps);
78752
+ outcomes.push({
78753
+ toolUseId: tu.id,
78754
+ name: tu.name,
78755
+ block: r.block,
78756
+ isError: r.isError,
78757
+ toolUseResult: r.toolUseResult,
78758
+ deferred: r.deferred,
78759
+ deferReason: r.deferReason
78760
+ });
78761
+ if (r.deferred) {
78762
+ return outcomes;
78763
+ }
78764
+ }
78765
+ }
78766
+ return outcomes;
78767
+ }
78768
+ var init_toolOrchestration = __esm(() => {
78769
+ init_toolExecution();
78770
+ });
78771
+
78772
+ // src/engine/pipeline/index.ts
78773
+ var init_pipeline = __esm(() => {
78774
+ init_toolExecution();
78775
+ init_toolOrchestration();
78776
+ });
78777
+
78864
78778
  // src/engine/tools/toolsearch/toolSearchTool.ts
78865
78779
  function getDeferredToolsCacheKey(deferredTools) {
78866
78780
  return deferredTools.map((t) => t.name).sort().join(",");
@@ -80532,6 +80446,166 @@ var init_coordinator = __esm(() => {
80532
80446
  init_tasks4();
80533
80447
  });
80534
80448
 
80449
+ // src/engine/goal/goalState.ts
80450
+ function armGoal(condition) {
80451
+ const trimmed = condition.trim();
80452
+ if (trimmed === "") {
80453
+ return { ok: false, reason: "Goal condition cannot be empty." };
80454
+ }
80455
+ if (trimmed.length > MAX_GOAL_CONDITION_CHARS) {
80456
+ return {
80457
+ ok: false,
80458
+ reason: `Goal condition exceeds ${MAX_GOAL_CONDITION_CHARS} characters (got ${trimmed.length}).`
80459
+ };
80460
+ }
80461
+ goalState = { armed: true, condition: trimmed, paused: false, pausedReason: undefined };
80462
+ return { ok: true };
80463
+ }
80464
+ function clearGoal() {
80465
+ goalState = { armed: false, condition: undefined, paused: false, pausedReason: undefined };
80466
+ }
80467
+ function pauseGoal(reason) {
80468
+ if (!goalState.armed)
80469
+ return;
80470
+ goalState = { ...goalState, paused: true, pausedReason: reason };
80471
+ }
80472
+ function resumeGoal() {
80473
+ if (!goalState.paused)
80474
+ return;
80475
+ goalState = { ...goalState, paused: false, pausedReason: undefined };
80476
+ }
80477
+ function isGoalPaused() {
80478
+ return goalState.armed && goalState.paused;
80479
+ }
80480
+ function getGoalPausedReason() {
80481
+ return goalState.armed && goalState.paused ? goalState.pausedReason : undefined;
80482
+ }
80483
+ function goalPausedNotification(reason) {
80484
+ return `Goal paused: ${reason}
80485
+ The goal will resume when the condition recovers.`;
80486
+ }
80487
+ function isGoalArmed() {
80488
+ return goalState.armed;
80489
+ }
80490
+ function getGoalCondition() {
80491
+ return goalState.armed ? goalState.condition : undefined;
80492
+ }
80493
+ function getGoalStateForPersistence() {
80494
+ return {
80495
+ armed: goalState.armed,
80496
+ condition: goalState.condition ?? ""
80497
+ };
80498
+ }
80499
+ function restoreGoalState(snapshot) {
80500
+ if (snapshot && snapshot.armed && snapshot.condition.trim() !== "") {
80501
+ goalState = { armed: true, condition: snapshot.condition.trim(), paused: false, pausedReason: undefined };
80502
+ } else {
80503
+ goalState = { armed: false, condition: undefined, paused: false, pausedReason: undefined };
80504
+ }
80505
+ }
80506
+ function resetGoalStateForTesting() {
80507
+ goalState = { armed: false, condition: undefined, paused: false, pausedReason: undefined };
80508
+ }
80509
+ function classifyGoalError(err) {
80510
+ const msg = (err instanceof Error ? err.message : String(err ?? "")).toLowerCase();
80511
+ if (/\b401\b/.test(msg) || /\b403\b/.test(msg) || msg.includes("unauthorized") || msg.includes("forbidden")) {
80512
+ return "unrecoverable";
80513
+ }
80514
+ if (msg.includes("context length exceeded") || msg.includes("prompt too long") || msg.includes("context window")) {
80515
+ return "unrecoverable";
80516
+ }
80517
+ return "recoverable";
80518
+ }
80519
+ function goalUnrecoverableNotification(reason) {
80520
+ return `Goal cleared (unrecoverable): ${reason}
80521
+ The goal can no longer be pursued. Set a new goal if needed.`;
80522
+ }
80523
+ function extractConversationEvidence(messages, maxMessages = 12) {
80524
+ const recent = messages.slice(-maxMessages);
80525
+ const lines = [];
80526
+ for (const m of recent) {
80527
+ if (m.type === "user" || m.type === "assistant") {
80528
+ const content = m.message?.content;
80529
+ if (typeof content === "string") {
80530
+ lines.push(`[${m.type}] ${content}`);
80531
+ } else if (Array.isArray(content)) {
80532
+ const text = content.filter((b) => typeof b === "object" && b !== null && b.type === "text").map((b) => b.text ?? "").join(" ");
80533
+ if (text)
80534
+ lines.push(`[${m.type}] ${text}`);
80535
+ }
80536
+ }
80537
+ }
80538
+ return lines.join(`
80539
+ `) || "(no conversation evidence)";
80540
+ }
80541
+ async function evaluateGoal(params) {
80542
+ const evidence = extractConversationEvidence(params.messages);
80543
+ const userPrompt = `Goal condition:
80544
+ ${params.condition}
80545
+
80546
+ Conversation evidence:
80547
+ ${evidence}
80548
+
80549
+ Has the goal condition been met?`;
80550
+ const resp = await params.modelProvider.chat({
80551
+ role: "small",
80552
+ messages: [
80553
+ { type: "user", message: { role: "user", content: userPrompt } }
80554
+ ],
80555
+ systemPrompt: { type: "system", content: EVALUATOR_SYSTEM_PROMPT },
80556
+ signal: params.signal
80557
+ });
80558
+ const content = resp.message?.content;
80559
+ const blocks = Array.isArray(content) ? content : [content];
80560
+ const text = blocks.map((b) => {
80561
+ if (typeof b === "string")
80562
+ return b;
80563
+ if (typeof b === "object" && b !== null && b.type === "text") {
80564
+ return b.text ?? "";
80565
+ }
80566
+ return "";
80567
+ }).join(`
80568
+ `);
80569
+ const firstLine = text.trim().split(`
80570
+ `)[0]?.toUpperCase() ?? "";
80571
+ const reasonLine = text.trim().split(`
80572
+ `).slice(1).join(`
80573
+ `).trim() || "No reason provided.";
80574
+ if (firstLine.includes("MET") && !firstLine.includes("UNMET")) {
80575
+ return { met: true, reason: reasonLine };
80576
+ }
80577
+ return { met: false, reason: reasonLine };
80578
+ }
80579
+ function goalContinuationReminder(condition) {
80580
+ const text = `The goal condition has not been met yet. Continue working toward the goal.
80581
+
80582
+ Goal condition: ${condition}
80583
+
80584
+ Do not stop until the goal condition is met. If the goal is truly unachievable, explain why and what was attempted.`;
80585
+ return {
80586
+ type: "user",
80587
+ message: { role: "user", content: text },
80588
+ uuid: `goal-reminder-${Date.now()}`,
80589
+ timestamp: new Date().toISOString()
80590
+ };
80591
+ }
80592
+ function goalMetNotification(condition) {
80593
+ return `✓ Goal met: ${condition}
80594
+ The goal has been auto-cleared.`;
80595
+ }
80596
+ function goalClearedNotification() {
80597
+ return "Goal cleared.";
80598
+ }
80599
+ function goalHookGateNotification() {
80600
+ return "Goal cleared: hooks are disabled (disableAllHooks). Goals require hooks to continue.";
80601
+ }
80602
+ var MAX_GOAL_CONDITION_CHARS = 500, DEFAULT_MAX_GOAL_TURNS = 10, goalState, EVALUATOR_SYSTEM_PROMPT = `You are a goal-condition evaluator. You are given a goal condition and the recent conversation. Determine whether the goal condition has been MET based solely on the conversation evidence — do not run commands, do not read files, do not make assumptions beyond what is shown.
80603
+
80604
+ Respond on the first line with exactly "MET" or "UNMET". On the following line, give a one-sentence reason citing the conversation evidence.`;
80605
+ var init_goalState = __esm(() => {
80606
+ goalState = { armed: false, condition: undefined, paused: false, pausedReason: undefined };
80607
+ });
80608
+
80535
80609
  // src/engine/session/restore.ts
80536
80610
  async function processResumedConversation(result, opts) {
80537
80611
  if (!opts.forkSession) {
@@ -82158,6 +82232,9 @@ async function queryAgentLoop(deps, args) {
82158
82232
  let deferredToolUse;
82159
82233
  if (deps.transcript) {
82160
82234
  await deps.transcript.record(messages);
82235
+ if (isCompactBoundaryMessage(messages[0])) {
82236
+ deps.transcript.reAppendSessionMetadata?.();
82237
+ }
82161
82238
  }
82162
82239
  deps.emit?.({ type: "loop_start", messageCount: messages.length });
82163
82240
  while (turns < maxTurns) {
@@ -82183,6 +82260,7 @@ async function queryAgentLoop(deps, args) {
82183
82260
  });
82184
82261
  }
82185
82262
  }
82263
+ deps.transcript?.reAppendSessionMetadata?.();
82186
82264
  } else if (oc.consecutiveFailures !== undefined) {
82187
82265
  tracking = { ...tracking, consecutiveFailures: oc.consecutiveFailures };
82188
82266
  reportAutoCompactCircuitFailures(oc.consecutiveFailures);
@@ -82215,6 +82293,7 @@ async function queryAgentLoop(deps, args) {
82215
82293
  messages = recovered;
82216
82294
  if (deps.transcript) {
82217
82295
  await deps.transcript.record(messages);
82296
+ deps.transcript.reAppendSessionMetadata?.();
82218
82297
  }
82219
82298
  deps.emit?.({ type: "compacted", turn: turns, messages });
82220
82299
  continue;
@@ -82354,6 +82433,7 @@ var init_loop = __esm(() => {
82354
82433
  init_shared();
82355
82434
  init_modelprovider2();
82356
82435
  init_turnRecovery();
82436
+ init_session();
82357
82437
  init_goalState();
82358
82438
  init_hooksConfig();
82359
82439
  init_pipeline();
@@ -82504,7 +82584,7 @@ var init_ProposeGoal = __esm(() => {
82504
82584
  return {
82505
82585
  tool_use_id: toolUseID,
82506
82586
  type: "tool_result",
82507
- content: jsonStringify2(data)
82587
+ content: jsonStringify(data)
82508
82588
  };
82509
82589
  },
82510
82590
  async call(args, _context) {
@@ -82579,6 +82659,7 @@ async function createAgentLoopDeps(config = {}) {
82579
82659
  const modelProvider = getModelProvider();
82580
82660
  const role = config.role ?? "premium";
82581
82661
  const sessionModel = config.sessionModel;
82662
+ let pendingReplacement = Promise.resolve();
82582
82663
  const deps = {
82583
82664
  modelProvider,
82584
82665
  role,
@@ -82615,8 +82696,16 @@ async function createAgentLoopDeps(config = {}) {
82615
82696
  fallbackModels: config.fallbackModels,
82616
82697
  transcript: config.disablePersistence ? undefined : {
82617
82698
  record: (msgs) => recordTranscript(msgs),
82618
- recordContentReplacement: (recs) => recordContentReplacement(recs, config.agentId),
82619
- saveGoalState: (goal) => saveGoalState(goal)
82699
+ recordContentReplacement: (recs) => {
82700
+ pendingReplacement = recordContentReplacement(recs, config.agentId);
82701
+ return pendingReplacement;
82702
+ },
82703
+ saveGoalState: (goal) => saveGoalState(goal),
82704
+ reAppendSessionMetadata: () => {
82705
+ pendingReplacement.catch(() => {
82706
+ return;
82707
+ }).then(() => reAppendSessionMetadata());
82708
+ }
82620
82709
  }
82621
82710
  };
82622
82711
  return { toolPermissionContext, tools, deps, warnings };
@@ -86946,6 +87035,7 @@ async function runHeadless(inputPrompt, options) {
86946
87035
  }
86947
87036
  cronScheduler.stop();
86948
87037
  await drainToOutput();
87038
+ await drainPendingBackgroundAgents(abortController.signal);
86949
87039
  } catch (error) {
86950
87040
  cronScheduler.stop();
86951
87041
  logForDebugging2(headlessErrorLine(error), { level: "error" });
@@ -101302,6 +101392,33 @@ async function readHeadAndTail(filePath, fileSize, buf) {
101302
101392
  return { head: "", tail: "" };
101303
101393
  }
101304
101394
  }
101395
+ async function scanMidForSessionTitle(filePath, fileSize) {
101396
+ const tailOffset = Math.max(0, fileSize - LITE_READ_BUF_SIZE2);
101397
+ const scanStart = Math.max(0, tailOffset - MID_TITLE_SCAN_SIZE);
101398
+ const scanLen = tailOffset - scanStart;
101399
+ if (scanLen <= 0)
101400
+ return;
101401
+ try {
101402
+ const fh = await fsOpen2(filePath, "r");
101403
+ try {
101404
+ const buf = Buffer.allocUnsafe(scanLen);
101405
+ const result = await fh.read(buf, 0, scanLen, scanStart);
101406
+ const chunk = buf.toString("utf8", 0, result.bytesRead);
101407
+ const customIdx = chunk.lastIndexOf('"type":"custom-title"');
101408
+ const aiIdx = chunk.lastIndexOf('"type":"ai-title"');
101409
+ const useAi = customIdx < 0;
101410
+ const hitIdx = useAi ? aiIdx : customIdx;
101411
+ if (hitIdx < 0)
101412
+ return;
101413
+ const line = chunk.slice(hitIdx);
101414
+ return extractJsonStringField(line, useAi ? "aiTitle" : "customTitle");
101415
+ } finally {
101416
+ await fh.close();
101417
+ }
101418
+ } catch {
101419
+ return;
101420
+ }
101421
+ }
101305
101422
  function simpleHash2(str) {
101306
101423
  return Math.abs(djb2Hash2(str)).toString(36);
101307
101424
  }
@@ -101515,11 +101632,12 @@ async function readTranscriptForLoad2(filePath, fileSize) {
101515
101632
  hasPreservedSegment: s.hasPreservedSegment
101516
101633
  };
101517
101634
  }
101518
- var LITE_READ_BUF_SIZE2 = 65536, uuidRegex, MAX_SANITIZED_LENGTH3 = 200, TRANSCRIPT_READ_CHUNK_SIZE2, SKIP_PRECOMPACT_THRESHOLD2, _compactBoundaryMarker2, ATTR_SNAP_PREFIX2, SYSTEM_PREFIX2, LF3 = 10, LF_BYTE2, BOUNDARY_SEARCH_BOUND2 = 256;
101635
+ var LITE_READ_BUF_SIZE2 = 65536, uuidRegex, MID_TITLE_SCAN_SIZE, MAX_SANITIZED_LENGTH3 = 200, TRANSCRIPT_READ_CHUNK_SIZE2, SKIP_PRECOMPACT_THRESHOLD2, _compactBoundaryMarker2, ATTR_SNAP_PREFIX2, SYSTEM_PREFIX2, LF3 = 10, LF_BYTE2, BOUNDARY_SEARCH_BOUND2 = 256;
101519
101636
  var init_sessionStoragePortable = __esm(() => {
101520
101637
  init_envUtils2();
101521
101638
  init_getWorktreePathsPortable();
101522
101639
  uuidRegex = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
101640
+ MID_TITLE_SCAN_SIZE = 512 * 1024;
101523
101641
  TRANSCRIPT_READ_CHUNK_SIZE2 = 1024 * 1024;
101524
101642
  SKIP_PRECOMPACT_THRESHOLD2 = 5 * 1024 * 1024;
101525
101643
  ATTR_SNAP_PREFIX2 = Buffer.from('{"type":"attribution-snapshot"');
@@ -132044,6 +132162,482 @@ var init_AscendExecutor = __esm(() => {
132044
132162
  };
132045
132163
  });
132046
132164
 
132165
+ // src/tui/utils/model/aliases.ts
132166
+ function isModelAlias(modelInput) {
132167
+ return MODEL_ALIASES.includes(modelInput);
132168
+ }
132169
+ function isModelFamilyAlias(model) {
132170
+ return MODEL_FAMILY_ALIASES.includes(model);
132171
+ }
132172
+ var MODEL_ALIASES, MODEL_FAMILY_ALIASES;
132173
+ var init_aliases = __esm(() => {
132174
+ MODEL_ALIASES = [
132175
+ "premium",
132176
+ "fast",
132177
+ "small"
132178
+ ];
132179
+ MODEL_FAMILY_ALIASES = ["premium", "fast", "small"];
132180
+ });
132181
+
132182
+ // src/tui/utils/model/modelAllowlist.ts
132183
+ function rolePoolModelIds(role) {
132184
+ const ids = new Set;
132185
+ for (const ref of getRoleModels(role)) {
132186
+ const resolved = resolveModel(ref);
132187
+ if (resolved)
132188
+ ids.add(resolved.modelId.toLowerCase());
132189
+ }
132190
+ return ids;
132191
+ }
132192
+ function rolePoolContains(role, model) {
132193
+ return rolePoolModelIds(role).has(model.toLowerCase());
132194
+ }
132195
+ function isModelAllowed(model) {
132196
+ const settings = getSettings_DEPRECATED() || {};
132197
+ const { availableModels } = settings;
132198
+ if (!availableModels) {
132199
+ return true;
132200
+ }
132201
+ if (availableModels.length === 0) {
132202
+ return false;
132203
+ }
132204
+ const normalizedModel = model.trim().toLowerCase();
132205
+ const normalizedAllowlist = availableModels.map((m) => m.trim().toLowerCase());
132206
+ if (normalizedAllowlist.includes(normalizedModel)) {
132207
+ return true;
132208
+ }
132209
+ for (const entry of normalizedAllowlist) {
132210
+ if (isModelFamilyAlias(entry) && rolePoolContains(entry, normalizedModel)) {
132211
+ return true;
132212
+ }
132213
+ }
132214
+ if (isModelAlias(normalizedModel)) {
132215
+ const resolved = parseUserSpecifiedModel2(normalizedModel).toLowerCase();
132216
+ if (normalizedAllowlist.includes(resolved)) {
132217
+ return true;
132218
+ }
132219
+ }
132220
+ for (const entry of normalizedAllowlist) {
132221
+ if (isModelAlias(entry) && !isModelFamilyAlias(entry)) {
132222
+ const resolved = parseUserSpecifiedModel2(entry).toLowerCase();
132223
+ if (resolved === normalizedModel) {
132224
+ return true;
132225
+ }
132226
+ }
132227
+ }
132228
+ return false;
132229
+ }
132230
+ function localPoolRefs() {
132231
+ const refs = new Set;
132232
+ for (const role of AUTO_MODE_ROLES) {
132233
+ for (const ref of getRoleModels(role)) {
132234
+ const low = ref.toLowerCase();
132235
+ refs.add(low);
132236
+ refs.add(low.split("/").pop() ?? low);
132237
+ const resolved = resolveModel(ref);
132238
+ if (resolved)
132239
+ refs.add(resolved.modelId.toLowerCase());
132240
+ }
132241
+ }
132242
+ return refs;
132243
+ }
132244
+ function isModelInLocalModelPools(model) {
132245
+ const m = model.trim().toLowerCase();
132246
+ if (m.length === 0)
132247
+ return false;
132248
+ const refs = localPoolRefs();
132249
+ if (refs.has(m) || refs.has(m.split("/").pop() ?? m))
132250
+ return true;
132251
+ const def = getCanonicalName(getDefaultMainLoopModel()).toLowerCase();
132252
+ return m === def || m === def.split("/").pop();
132253
+ }
132254
+ var AUTO_MODE_ROLES;
132255
+ var init_modelAllowlist = __esm(() => {
132256
+ init_settings3();
132257
+ init_aliases();
132258
+ init_model();
132259
+ init_modelprovider2();
132260
+ AUTO_MODE_ROLES = ["premium", "fast", "small"];
132261
+ });
132262
+
132263
+ // src/tui/utils/model/model.ts
132264
+ function getDefaultFastModel() {
132265
+ const settings = getSettings_DEPRECATED() || {};
132266
+ const roleModel = settings.modelRoles?.fast?.model;
132267
+ if (roleModel) {
132268
+ return roleModel;
132269
+ }
132270
+ return process.env.ATLAS_FAST_MODEL || getRoleModel("fast");
132271
+ }
132272
+ function getAsrModel() {
132273
+ return process.env.ATLAS_ASR_MODEL || getSettings_DEPRECATED()?.asrModel || "funasr";
132274
+ }
132275
+ function getUserSpecifiedModelSetting() {
132276
+ let specifiedModel;
132277
+ const modelOverride = getMainLoopModelOverride();
132278
+ if (modelOverride !== undefined) {
132279
+ specifiedModel = modelOverride;
132280
+ } else {
132281
+ const settings = getSettings_DEPRECATED() || {};
132282
+ specifiedModel = process.env.ATLAS_MODEL || settings.model || undefined;
132283
+ }
132284
+ if (specifiedModel && !isModelAllowed(specifiedModel)) {
132285
+ return;
132286
+ }
132287
+ return specifiedModel;
132288
+ }
132289
+ function globalModelRejectedNotice() {
132290
+ const specified = (getSettings_DEPRECATED() || {}).model;
132291
+ if (!specified || isModelAllowed(specified))
132292
+ return;
132293
+ return `已选模型 ${specified} 不在 availableModels 池内,已回退 default`;
132294
+ }
132295
+ function getMainLoopModel() {
132296
+ const model = getUserSpecifiedModelSetting();
132297
+ const settings = getSettings_DEPRECATED() || {};
132298
+ const roleModel = settings.modelRoles?.small?.model;
132299
+ if (roleModel && getMainLoopModelOverride() === undefined) {
132300
+ return parseUserSpecifiedModel2(roleModel);
132301
+ }
132302
+ if (model !== undefined && model !== null) {
132303
+ return parseUserSpecifiedModel2(model);
132304
+ }
132305
+ return getDefaultMainLoopModel();
132306
+ }
132307
+ function getDefaultPremiumModel() {
132308
+ return getRoleModel("premium");
132309
+ }
132310
+ function getDefaultSmallModel() {
132311
+ return getRoleModel("small");
132312
+ }
132313
+ function getRuntimeMainLoopModel(params) {
132314
+ const { permissionMode, mainLoopModel, exceeds200kTokens = false } = params;
132315
+ if (permissionMode === "plan" && !exceeds200kTokens) {
132316
+ const premiumModel = getDefaultPremiumModel();
132317
+ if (premiumModel)
132318
+ return premiumModel;
132319
+ const smallModel = getDefaultSmallModel();
132320
+ if (smallModel)
132321
+ return smallModel;
132322
+ }
132323
+ return mainLoopModel;
132324
+ }
132325
+ function getDefaultMainLoopModelSetting() {
132326
+ return getDefaultSmallModel();
132327
+ }
132328
+ function getDefaultMainLoopModel() {
132329
+ return parseUserSpecifiedModel2(getDefaultMainLoopModelSetting());
132330
+ }
132331
+ function getCanonicalName(fullModelName) {
132332
+ const resolved = resolveModel(fullModelName);
132333
+ if (resolved) {
132334
+ return resolved.modelId;
132335
+ }
132336
+ return fullModelName.toLowerCase();
132337
+ }
132338
+ function renderDefaultModelSetting(setting) {
132339
+ return renderModelName(parseUserSpecifiedModel2(setting));
132340
+ }
132341
+ function renderModelSetting(setting) {
132342
+ if (isModelAlias(setting)) {
132343
+ return capitalize3(setting);
132344
+ }
132345
+ return renderModelName(setting);
132346
+ }
132347
+ function getPublicModelDisplayName(model) {
132348
+ const premium = getRoleModel("premium");
132349
+ const small = getRoleModel("small");
132350
+ const fast = getRoleModel("fast");
132351
+ switch (model) {
132352
+ case premium:
132353
+ return premium;
132354
+ case small:
132355
+ return small;
132356
+ case fast:
132357
+ return fast;
132358
+ default:
132359
+ return null;
132360
+ }
132361
+ }
132362
+ function renderModelName(model) {
132363
+ const publicName = getPublicModelDisplayName(model);
132364
+ if (publicName) {
132365
+ return publicName;
132366
+ }
132367
+ return model;
132368
+ }
132369
+ function getPublicModelName(model) {
132370
+ const publicName = getPublicModelDisplayName(model);
132371
+ if (publicName) {
132372
+ return `AtlasCode ${publicName}`;
132373
+ }
132374
+ return `AtlasCode (${model})`;
132375
+ }
132376
+ function parseUserSpecifiedModel2(modelInput) {
132377
+ const modelInputTrimmed = (typeof modelInput === "string" ? modelInput : String(modelInput || "")).trim();
132378
+ const normalizedModel = modelInputTrimmed.toLowerCase();
132379
+ if (isModelAlias(normalizedModel)) {
132380
+ switch (normalizedModel) {
132381
+ case "premium":
132382
+ return getDefaultPremiumModel();
132383
+ case "fast":
132384
+ return getDefaultFastModel();
132385
+ case "small":
132386
+ return getDefaultSmallModel();
132387
+ default:
132388
+ }
132389
+ }
132390
+ return modelInputTrimmed;
132391
+ }
132392
+ function resolveSkillModelOverride2(skillModel, _currentModel) {
132393
+ return skillModel;
132394
+ }
132395
+ function modelDisplayString(model) {
132396
+ if (model === null) {
132397
+ return `Default (${getDefaultMainLoopModel()})`;
132398
+ }
132399
+ const resolvedModel = parseUserSpecifiedModel2(model);
132400
+ return model === resolvedModel ? resolvedModel : `${model} (${resolvedModel})`;
132401
+ }
132402
+ function formatContextWindow(tokens) {
132403
+ if (tokens >= 1e6)
132404
+ return `${(tokens / 1e6).toFixed(1)}M`;
132405
+ if (tokens >= 1000)
132406
+ return `${Math.round(tokens / 1000)}K`;
132407
+ return `${tokens}`;
132408
+ }
132409
+ function getMarketingNameForModel(modelId) {
132410
+ return resolveModel(modelId)?.name;
132411
+ }
132412
+ var init_model = __esm(() => {
132413
+ init_bootstrapState();
132414
+ init_settings3();
132415
+ init_modelprovider2();
132416
+ init_modelAllowlist();
132417
+ init_aliases();
132418
+ init_stringUtils2();
132419
+ });
132420
+
132421
+ // src/tui/utils/thinking.ts
132422
+ function isUltrathinkEnabled2() {
132423
+ if (!feature("ULTRATHINK")) {
132424
+ return false;
132425
+ }
132426
+ return getFeatureValue_CACHED_MAY_BE_STALE("atlas_turtle_carbon", true);
132427
+ }
132428
+ function hasUltrathinkKeyword(text) {
132429
+ return /\bultrathink\b/i.test(text);
132430
+ }
132431
+ function findThinkingTriggerPositions(text) {
132432
+ const positions = [];
132433
+ const matches = text.matchAll(/\bultrathink\b/gi);
132434
+ for (const match of matches) {
132435
+ if (match.index !== undefined) {
132436
+ positions.push({
132437
+ word: match[0],
132438
+ start: match.index,
132439
+ end: match.index + match[0].length
132440
+ });
132441
+ }
132442
+ }
132443
+ return positions;
132444
+ }
132445
+ function getRainbowColor(charIndex, shimmer = false) {
132446
+ const colors = shimmer ? RAINBOW_SHIMMER_COLORS : RAINBOW_COLORS;
132447
+ return colors[charIndex % colors.length];
132448
+ }
132449
+ function shouldEnableThinkingByDefault() {
132450
+ if (process.env.MAX_THINKING_TOKENS) {
132451
+ return parseInt(process.env.MAX_THINKING_TOKENS, 10) > 0;
132452
+ }
132453
+ const { settings } = getSettingsWithErrors2();
132454
+ if (settings.alwaysThinkingEnabled === false) {
132455
+ return false;
132456
+ }
132457
+ return true;
132458
+ }
132459
+ var RAINBOW_COLORS, RAINBOW_SHIMMER_COLORS;
132460
+ var init_thinking = __esm(() => {
132461
+ init_shared();
132462
+ init_growthbook();
132463
+ init_model();
132464
+ init_settings3();
132465
+ RAINBOW_COLORS = [
132466
+ "rainbow_red",
132467
+ "rainbow_orange",
132468
+ "rainbow_yellow",
132469
+ "rainbow_green",
132470
+ "rainbow_blue",
132471
+ "rainbow_indigo",
132472
+ "rainbow_violet"
132473
+ ];
132474
+ RAINBOW_SHIMMER_COLORS = [
132475
+ "rainbow_red_shimmer",
132476
+ "rainbow_orange_shimmer",
132477
+ "rainbow_yellow_shimmer",
132478
+ "rainbow_green_shimmer",
132479
+ "rainbow_blue_shimmer",
132480
+ "rainbow_indigo_shimmer",
132481
+ "rainbow_violet_shimmer"
132482
+ ];
132483
+ });
132484
+
132485
+ // src/tui/utils/effort.ts
132486
+ function modelSupportsEffort2(model) {
132487
+ const m = model.toLowerCase();
132488
+ if (isEnvTruthy2(process.env.ATLAS_ALWAYS_ENABLE_EFFORT)) {
132489
+ return true;
132490
+ }
132491
+ if (m.includes("fast") || m.includes("small") || m.includes("premium")) {
132492
+ return false;
132493
+ }
132494
+ return true;
132495
+ }
132496
+ function isEffortLevel2(value) {
132497
+ return EFFORT_LEVELS2.includes(value);
132498
+ }
132499
+ function cycleEffortLevel(current, direction) {
132500
+ const levels = EFFORT_LEVELS2;
132501
+ const idx = levels.indexOf(current);
132502
+ const currentIndex = idx !== -1 ? idx : levels.indexOf("medium");
132503
+ if (direction === "right") {
132504
+ return levels[(currentIndex + 1) % levels.length];
132505
+ }
132506
+ return levels[(currentIndex - 1 + levels.length) % levels.length];
132507
+ }
132508
+ function parseEffortValue2(value) {
132509
+ if (value === undefined || value === null || value === "") {
132510
+ return;
132511
+ }
132512
+ if (typeof value === "number" && isValidNumericEffort2(value)) {
132513
+ return value;
132514
+ }
132515
+ const str = String(value).toLowerCase();
132516
+ if (isEffortLevel2(str)) {
132517
+ return str;
132518
+ }
132519
+ const numericValue = parseInt(str, 10);
132520
+ if (!isNaN(numericValue) && isValidNumericEffort2(numericValue)) {
132521
+ return numericValue;
132522
+ }
132523
+ return;
132524
+ }
132525
+ function toPersistableEffort(value) {
132526
+ if (value === "low" || value === "medium" || value === "high" || value === "xhigh") {
132527
+ return value;
132528
+ }
132529
+ return;
132530
+ }
132531
+ function getInitialEffortSetting() {
132532
+ return toPersistableEffort(getInitialSettings2().effortLevel);
132533
+ }
132534
+ function getEffortByModel() {
132535
+ const raw = getSettingsForSource2("userSettings")?.effortByModel;
132536
+ const out = {};
132537
+ if (raw && typeof raw === "object" && !Array.isArray(raw)) {
132538
+ for (const [key, value] of Object.entries(raw)) {
132539
+ if (isEffortLevel2(value))
132540
+ out[key] = value;
132541
+ }
132542
+ }
132543
+ return out;
132544
+ }
132545
+ function getPersistedEffortForModel(model) {
132546
+ if (!model)
132547
+ return;
132548
+ const wanted = model.toLowerCase();
132549
+ for (const [key, level] of Object.entries(getEffortByModel())) {
132550
+ if (key.toLowerCase() === wanted)
132551
+ return level;
132552
+ }
132553
+ return;
132554
+ }
132555
+ function withEffortForModel(model, level) {
132556
+ return { ...getEffortByModel(), [model]: level };
132557
+ }
132558
+ function getStartupEffortValue(startupModel) {
132559
+ return getPersistedEffortForModel(startupModel) ?? getInitialEffortSetting();
132560
+ }
132561
+ function getPickerDisplayEffort(focusedModel, sessionEffort, modelDefault) {
132562
+ return getPersistedEffortForModel(focusedModel) ?? (sessionEffort !== undefined ? convertEffortValueToLevel2(sessionEffort) : modelDefault);
132563
+ }
132564
+ function resolvePickerEffortPersistence(picked, modelDefault, priorPersisted, toggledInPicker) {
132565
+ const hadExplicit = priorPersisted !== undefined || toggledInPicker;
132566
+ return hadExplicit || picked !== modelDefault ? picked : undefined;
132567
+ }
132568
+ function getEffortEnvOverride2() {
132569
+ const envOverride = process.env.ATLAS_EFFORT_LEVEL;
132570
+ return envOverride?.toLowerCase() === "unset" || envOverride?.toLowerCase() === "auto" ? null : parseEffortValue2(envOverride);
132571
+ }
132572
+ function resolveAppliedEffort2(model, appStateEffortValue) {
132573
+ const envOverride = getEffortEnvOverride2();
132574
+ if (envOverride === null) {
132575
+ return;
132576
+ }
132577
+ const perModelMemory = getPersistedEffortForModel(model);
132578
+ return envOverride ?? perModelMemory ?? appStateEffortValue ?? getDefaultEffortForModel2(model);
132579
+ }
132580
+ function getDisplayedEffortLevel(model, appStateEffort) {
132581
+ const resolved = resolveAppliedEffort2(model, appStateEffort) ?? "medium";
132582
+ return convertEffortValueToLevel2(resolved);
132583
+ }
132584
+ function getEffortSuffix(model, effortValue) {
132585
+ if (effortValue === undefined)
132586
+ return "";
132587
+ const resolved = resolveAppliedEffort2(model, effortValue);
132588
+ if (resolved === undefined)
132589
+ return "";
132590
+ return ` with ${convertEffortValueToLevel2(resolved)} effort`;
132591
+ }
132592
+ function isValidNumericEffort2(value) {
132593
+ return Number.isInteger(value);
132594
+ }
132595
+ function convertEffortValueToLevel2(value) {
132596
+ if (typeof value === "string") {
132597
+ return isEffortLevel2(value) ? value : "high";
132598
+ }
132599
+ return "high";
132600
+ }
132601
+ function getEffortLevelDescription(level) {
132602
+ switch (level) {
132603
+ case "low":
132604
+ return "Quick, straightforward implementation with minimal overhead";
132605
+ case "medium":
132606
+ return "Balanced approach with standard implementation and testing";
132607
+ case "high":
132608
+ return "Comprehensive implementation with extensive testing and documentation";
132609
+ case "xhigh":
132610
+ return "Extra-high reasoning above high (supported by some models, e.g. Qwen)";
132611
+ case "max":
132612
+ return "Maximum capability with deepest reasoning (supported models only)";
132613
+ }
132614
+ }
132615
+ function getEffortValueDescription(value) {
132616
+ if (typeof value === "string") {
132617
+ return getEffortLevelDescription(value);
132618
+ }
132619
+ return "Balanced approach with standard implementation and testing";
132620
+ }
132621
+ function getDefaultEffortForModel2(model) {
132622
+ if (isUltrathinkEnabled2() && modelSupportsEffort2(model)) {
132623
+ return "medium";
132624
+ }
132625
+ return "medium";
132626
+ }
132627
+ var EFFORT_LEVELS2;
132628
+ var init_effort2 = __esm(() => {
132629
+ init_thinking();
132630
+ init_settings3();
132631
+ init_envUtils2();
132632
+ EFFORT_LEVELS2 = [
132633
+ "low",
132634
+ "medium",
132635
+ "high",
132636
+ "xhigh",
132637
+ "max"
132638
+ ];
132639
+ });
132640
+
132047
132641
  // node_modules/tree-kill/index.js
132048
132642
  var require_tree_kill = __commonJS(function(exports, module) {
132049
132643
  var childProcess = __require("child_process");
@@ -132239,256 +132833,6 @@ var init_constants8 = __esm(() => {
132239
132833
  GLOBAL_ATLAS_FOLDER_PERMISSION_PATTERN2 = `~/${getConfigDirName2()}/**`;
132240
132834
  });
132241
132835
 
132242
- // src/tui/utils/model/aliases.ts
132243
- function isModelAlias(modelInput) {
132244
- return MODEL_ALIASES.includes(modelInput);
132245
- }
132246
- function isModelFamilyAlias(model) {
132247
- return MODEL_FAMILY_ALIASES.includes(model);
132248
- }
132249
- var MODEL_ALIASES, MODEL_FAMILY_ALIASES;
132250
- var init_aliases = __esm(() => {
132251
- MODEL_ALIASES = [
132252
- "premium",
132253
- "fast",
132254
- "small"
132255
- ];
132256
- MODEL_FAMILY_ALIASES = ["premium", "fast", "small"];
132257
- });
132258
-
132259
- // src/tui/utils/model/modelAllowlist.ts
132260
- function rolePoolModelIds(role) {
132261
- const ids = new Set;
132262
- for (const ref of getRoleModels(role)) {
132263
- const resolved = resolveModel(ref);
132264
- if (resolved)
132265
- ids.add(resolved.modelId.toLowerCase());
132266
- }
132267
- return ids;
132268
- }
132269
- function rolePoolContains(role, model) {
132270
- return rolePoolModelIds(role).has(model.toLowerCase());
132271
- }
132272
- function isModelAllowed(model) {
132273
- const settings = getSettings_DEPRECATED() || {};
132274
- const { availableModels } = settings;
132275
- if (!availableModels) {
132276
- return true;
132277
- }
132278
- if (availableModels.length === 0) {
132279
- return false;
132280
- }
132281
- const normalizedModel = model.trim().toLowerCase();
132282
- const normalizedAllowlist = availableModels.map((m) => m.trim().toLowerCase());
132283
- if (normalizedAllowlist.includes(normalizedModel)) {
132284
- return true;
132285
- }
132286
- for (const entry of normalizedAllowlist) {
132287
- if (isModelFamilyAlias(entry) && rolePoolContains(entry, normalizedModel)) {
132288
- return true;
132289
- }
132290
- }
132291
- if (isModelAlias(normalizedModel)) {
132292
- const resolved = parseUserSpecifiedModel2(normalizedModel).toLowerCase();
132293
- if (normalizedAllowlist.includes(resolved)) {
132294
- return true;
132295
- }
132296
- }
132297
- for (const entry of normalizedAllowlist) {
132298
- if (isModelAlias(entry) && !isModelFamilyAlias(entry)) {
132299
- const resolved = parseUserSpecifiedModel2(entry).toLowerCase();
132300
- if (resolved === normalizedModel) {
132301
- return true;
132302
- }
132303
- }
132304
- }
132305
- return false;
132306
- }
132307
- function localPoolRefs() {
132308
- const refs = new Set;
132309
- for (const role of AUTO_MODE_ROLES) {
132310
- for (const ref of getRoleModels(role)) {
132311
- const low = ref.toLowerCase();
132312
- refs.add(low);
132313
- refs.add(low.split("/").pop() ?? low);
132314
- const resolved = resolveModel(ref);
132315
- if (resolved)
132316
- refs.add(resolved.modelId.toLowerCase());
132317
- }
132318
- }
132319
- return refs;
132320
- }
132321
- function isModelInLocalModelPools(model) {
132322
- const m = model.trim().toLowerCase();
132323
- if (m.length === 0)
132324
- return false;
132325
- const refs = localPoolRefs();
132326
- if (refs.has(m) || refs.has(m.split("/").pop() ?? m))
132327
- return true;
132328
- const def = getCanonicalName(getDefaultMainLoopModel()).toLowerCase();
132329
- return m === def || m === def.split("/").pop();
132330
- }
132331
- var AUTO_MODE_ROLES;
132332
- var init_modelAllowlist = __esm(() => {
132333
- init_settings3();
132334
- init_aliases();
132335
- init_model();
132336
- init_modelprovider2();
132337
- AUTO_MODE_ROLES = ["premium", "fast", "small"];
132338
- });
132339
-
132340
- // src/tui/utils/model/model.ts
132341
- function getDefaultFastModel() {
132342
- const settings = getSettings_DEPRECATED() || {};
132343
- const roleModel = settings.modelRoles?.fast?.model;
132344
- if (roleModel) {
132345
- return roleModel;
132346
- }
132347
- return process.env.ATLAS_FAST_MODEL || getRoleModel("fast");
132348
- }
132349
- function getAsrModel() {
132350
- return process.env.ATLAS_ASR_MODEL || getSettings_DEPRECATED()?.asrModel || "funasr";
132351
- }
132352
- function getUserSpecifiedModelSetting() {
132353
- let specifiedModel;
132354
- const modelOverride = getMainLoopModelOverride();
132355
- if (modelOverride !== undefined) {
132356
- specifiedModel = modelOverride;
132357
- } else {
132358
- const settings = getSettings_DEPRECATED() || {};
132359
- specifiedModel = process.env.ATLAS_MODEL || settings.model || undefined;
132360
- }
132361
- if (specifiedModel && !isModelAllowed(specifiedModel)) {
132362
- return;
132363
- }
132364
- return specifiedModel;
132365
- }
132366
- function getMainLoopModel() {
132367
- const model = getUserSpecifiedModelSetting();
132368
- const settings = getSettings_DEPRECATED() || {};
132369
- const roleModel = settings.modelRoles?.small?.model;
132370
- if (roleModel && getMainLoopModelOverride() === undefined) {
132371
- return parseUserSpecifiedModel2(roleModel);
132372
- }
132373
- if (model !== undefined && model !== null) {
132374
- return parseUserSpecifiedModel2(model);
132375
- }
132376
- return getDefaultMainLoopModel();
132377
- }
132378
- function getDefaultPremiumModel() {
132379
- return getRoleModel("premium");
132380
- }
132381
- function getDefaultSmallModel() {
132382
- return getRoleModel("small");
132383
- }
132384
- function getRuntimeMainLoopModel(params) {
132385
- const { permissionMode, mainLoopModel, exceeds200kTokens = false } = params;
132386
- if (permissionMode === "plan" && !exceeds200kTokens) {
132387
- const premiumModel = getDefaultPremiumModel();
132388
- if (premiumModel)
132389
- return premiumModel;
132390
- const smallModel = getDefaultSmallModel();
132391
- if (smallModel)
132392
- return smallModel;
132393
- }
132394
- return mainLoopModel;
132395
- }
132396
- function getDefaultMainLoopModelSetting() {
132397
- return getDefaultSmallModel();
132398
- }
132399
- function getDefaultMainLoopModel() {
132400
- return parseUserSpecifiedModel2(getDefaultMainLoopModelSetting());
132401
- }
132402
- function getCanonicalName(fullModelName) {
132403
- const resolved = resolveModel(fullModelName);
132404
- if (resolved) {
132405
- return resolved.modelId;
132406
- }
132407
- return fullModelName.toLowerCase();
132408
- }
132409
- function renderDefaultModelSetting(setting) {
132410
- return renderModelName(parseUserSpecifiedModel2(setting));
132411
- }
132412
- function renderModelSetting(setting) {
132413
- if (isModelAlias(setting)) {
132414
- return capitalize3(setting);
132415
- }
132416
- return renderModelName(setting);
132417
- }
132418
- function getPublicModelDisplayName(model) {
132419
- const premium = getRoleModel("premium");
132420
- const small = getRoleModel("small");
132421
- const fast = getRoleModel("fast");
132422
- switch (model) {
132423
- case premium:
132424
- return premium;
132425
- case small:
132426
- return small;
132427
- case fast:
132428
- return fast;
132429
- default:
132430
- return null;
132431
- }
132432
- }
132433
- function renderModelName(model) {
132434
- const publicName = getPublicModelDisplayName(model);
132435
- if (publicName) {
132436
- return publicName;
132437
- }
132438
- return model;
132439
- }
132440
- function getPublicModelName(model) {
132441
- const publicName = getPublicModelDisplayName(model);
132442
- if (publicName) {
132443
- return `AtlasCode ${publicName}`;
132444
- }
132445
- return `AtlasCode (${model})`;
132446
- }
132447
- function parseUserSpecifiedModel2(modelInput) {
132448
- const modelInputTrimmed = (typeof modelInput === "string" ? modelInput : String(modelInput || "")).trim();
132449
- const normalizedModel = modelInputTrimmed.toLowerCase();
132450
- if (isModelAlias(normalizedModel)) {
132451
- switch (normalizedModel) {
132452
- case "premium":
132453
- return getDefaultPremiumModel();
132454
- case "fast":
132455
- return getDefaultFastModel();
132456
- case "small":
132457
- return getDefaultSmallModel();
132458
- default:
132459
- }
132460
- }
132461
- return modelInputTrimmed;
132462
- }
132463
- function resolveSkillModelOverride2(skillModel, _currentModel) {
132464
- return skillModel;
132465
- }
132466
- function modelDisplayString(model) {
132467
- if (model === null) {
132468
- return `Default (${getDefaultMainLoopModel()})`;
132469
- }
132470
- const resolvedModel = parseUserSpecifiedModel2(model);
132471
- return model === resolvedModel ? resolvedModel : `${model} (${resolvedModel})`;
132472
- }
132473
- function formatContextWindow(tokens) {
132474
- if (tokens >= 1e6)
132475
- return `${(tokens / 1e6).toFixed(1)}M`;
132476
- if (tokens >= 1000)
132477
- return `${Math.round(tokens / 1000)}K`;
132478
- return `${tokens}`;
132479
- }
132480
- function getMarketingNameForModel(modelId) {
132481
- return resolveModel(modelId)?.name;
132482
- }
132483
- var init_model = __esm(() => {
132484
- init_bootstrapState();
132485
- init_settings3();
132486
- init_modelprovider2();
132487
- init_modelAllowlist();
132488
- init_aliases();
132489
- init_stringUtils2();
132490
- });
132491
-
132492
132836
  // src/tui/utils/pdfUtils.ts
132493
132837
  function parsePDFPageRange2(pages) {
132494
132838
  const trimmed = pages.trim();
@@ -169274,225 +169618,6 @@ var init_pluginDirectories = __esm(() => {
169274
169618
  init_pathValidation3();
169275
169619
  });
169276
169620
 
169277
- // src/tui/utils/thinking.ts
169278
- function isUltrathinkEnabled2() {
169279
- if (!feature("ULTRATHINK")) {
169280
- return false;
169281
- }
169282
- return getFeatureValue_CACHED_MAY_BE_STALE("atlas_turtle_carbon", true);
169283
- }
169284
- function hasUltrathinkKeyword(text) {
169285
- return /\bultrathink\b/i.test(text);
169286
- }
169287
- function findThinkingTriggerPositions(text) {
169288
- const positions = [];
169289
- const matches = text.matchAll(/\bultrathink\b/gi);
169290
- for (const match of matches) {
169291
- if (match.index !== undefined) {
169292
- positions.push({
169293
- word: match[0],
169294
- start: match.index,
169295
- end: match.index + match[0].length
169296
- });
169297
- }
169298
- }
169299
- return positions;
169300
- }
169301
- function getRainbowColor(charIndex, shimmer = false) {
169302
- const colors = shimmer ? RAINBOW_SHIMMER_COLORS : RAINBOW_COLORS;
169303
- return colors[charIndex % colors.length];
169304
- }
169305
- function shouldEnableThinkingByDefault() {
169306
- if (process.env.MAX_THINKING_TOKENS) {
169307
- return parseInt(process.env.MAX_THINKING_TOKENS, 10) > 0;
169308
- }
169309
- const { settings } = getSettingsWithErrors2();
169310
- if (settings.alwaysThinkingEnabled === false) {
169311
- return false;
169312
- }
169313
- return true;
169314
- }
169315
- var RAINBOW_COLORS, RAINBOW_SHIMMER_COLORS;
169316
- var init_thinking = __esm(() => {
169317
- init_shared();
169318
- init_growthbook();
169319
- init_model();
169320
- init_settings3();
169321
- RAINBOW_COLORS = [
169322
- "rainbow_red",
169323
- "rainbow_orange",
169324
- "rainbow_yellow",
169325
- "rainbow_green",
169326
- "rainbow_blue",
169327
- "rainbow_indigo",
169328
- "rainbow_violet"
169329
- ];
169330
- RAINBOW_SHIMMER_COLORS = [
169331
- "rainbow_red_shimmer",
169332
- "rainbow_orange_shimmer",
169333
- "rainbow_yellow_shimmer",
169334
- "rainbow_green_shimmer",
169335
- "rainbow_blue_shimmer",
169336
- "rainbow_indigo_shimmer",
169337
- "rainbow_violet_shimmer"
169338
- ];
169339
- });
169340
-
169341
- // src/tui/utils/effort.ts
169342
- function modelSupportsEffort2(model) {
169343
- const m = model.toLowerCase();
169344
- if (isEnvTruthy2(process.env.ATLAS_ALWAYS_ENABLE_EFFORT)) {
169345
- return true;
169346
- }
169347
- if (m.includes("fast") || m.includes("small") || m.includes("premium")) {
169348
- return false;
169349
- }
169350
- return true;
169351
- }
169352
- function isEffortLevel2(value) {
169353
- return EFFORT_LEVELS2.includes(value);
169354
- }
169355
- function cycleEffortLevel(current, direction) {
169356
- const levels = EFFORT_LEVELS2;
169357
- const idx = levels.indexOf(current);
169358
- const currentIndex = idx !== -1 ? idx : levels.indexOf("medium");
169359
- if (direction === "right") {
169360
- return levels[(currentIndex + 1) % levels.length];
169361
- }
169362
- return levels[(currentIndex - 1 + levels.length) % levels.length];
169363
- }
169364
- function parseEffortValue2(value) {
169365
- if (value === undefined || value === null || value === "") {
169366
- return;
169367
- }
169368
- if (typeof value === "number" && isValidNumericEffort2(value)) {
169369
- return value;
169370
- }
169371
- const str = String(value).toLowerCase();
169372
- if (isEffortLevel2(str)) {
169373
- return str;
169374
- }
169375
- const numericValue = parseInt(str, 10);
169376
- if (!isNaN(numericValue) && isValidNumericEffort2(numericValue)) {
169377
- return numericValue;
169378
- }
169379
- return;
169380
- }
169381
- function toPersistableEffort(value) {
169382
- if (value === "low" || value === "medium" || value === "high" || value === "xhigh") {
169383
- return value;
169384
- }
169385
- return;
169386
- }
169387
- function getInitialEffortSetting() {
169388
- return toPersistableEffort(getInitialSettings2().effortLevel);
169389
- }
169390
- function getEffortByModel() {
169391
- const raw = getSettingsForSource2("userSettings")?.effortByModel;
169392
- const out = {};
169393
- if (raw && typeof raw === "object" && !Array.isArray(raw)) {
169394
- for (const [key, value] of Object.entries(raw)) {
169395
- if (isEffortLevel2(value))
169396
- out[key] = value;
169397
- }
169398
- }
169399
- return out;
169400
- }
169401
- function getPersistedEffortForModel(model) {
169402
- if (!model)
169403
- return;
169404
- const wanted = model.toLowerCase();
169405
- for (const [key, level] of Object.entries(getEffortByModel())) {
169406
- if (key.toLowerCase() === wanted)
169407
- return level;
169408
- }
169409
- return;
169410
- }
169411
- function withEffortForModel(model, level) {
169412
- return { ...getEffortByModel(), [model]: level };
169413
- }
169414
- function getStartupEffortValue(startupModel) {
169415
- return getPersistedEffortForModel(startupModel) ?? getInitialEffortSetting();
169416
- }
169417
- function getPickerDisplayEffort(focusedModel, sessionEffort, modelDefault) {
169418
- return getPersistedEffortForModel(focusedModel) ?? (sessionEffort !== undefined ? convertEffortValueToLevel2(sessionEffort) : modelDefault);
169419
- }
169420
- function resolvePickerEffortPersistence(picked, modelDefault, priorPersisted, toggledInPicker) {
169421
- const hadExplicit = priorPersisted !== undefined || toggledInPicker;
169422
- return hadExplicit || picked !== modelDefault ? picked : undefined;
169423
- }
169424
- function getEffortEnvOverride2() {
169425
- const envOverride = process.env.ATLAS_EFFORT_LEVEL;
169426
- return envOverride?.toLowerCase() === "unset" || envOverride?.toLowerCase() === "auto" ? null : parseEffortValue2(envOverride);
169427
- }
169428
- function resolveAppliedEffort2(model, appStateEffortValue) {
169429
- const envOverride = getEffortEnvOverride2();
169430
- if (envOverride === null) {
169431
- return;
169432
- }
169433
- return envOverride ?? appStateEffortValue ?? getDefaultEffortForModel2(model);
169434
- }
169435
- function getDisplayedEffortLevel(model, appStateEffort) {
169436
- const resolved = resolveAppliedEffort2(model, appStateEffort) ?? "medium";
169437
- return convertEffortValueToLevel2(resolved);
169438
- }
169439
- function getEffortSuffix(model, effortValue) {
169440
- if (effortValue === undefined)
169441
- return "";
169442
- const resolved = resolveAppliedEffort2(model, effortValue);
169443
- if (resolved === undefined)
169444
- return "";
169445
- return ` with ${convertEffortValueToLevel2(resolved)} effort`;
169446
- }
169447
- function isValidNumericEffort2(value) {
169448
- return Number.isInteger(value);
169449
- }
169450
- function convertEffortValueToLevel2(value) {
169451
- if (typeof value === "string") {
169452
- return isEffortLevel2(value) ? value : "high";
169453
- }
169454
- return "high";
169455
- }
169456
- function getEffortLevelDescription(level) {
169457
- switch (level) {
169458
- case "low":
169459
- return "Quick, straightforward implementation with minimal overhead";
169460
- case "medium":
169461
- return "Balanced approach with standard implementation and testing";
169462
- case "high":
169463
- return "Comprehensive implementation with extensive testing and documentation";
169464
- case "xhigh":
169465
- return "Extra-high reasoning above high (supported by some models, e.g. Qwen)";
169466
- case "max":
169467
- return "Maximum capability with deepest reasoning (supported models only)";
169468
- }
169469
- }
169470
- function getEffortValueDescription(value) {
169471
- if (typeof value === "string") {
169472
- return getEffortLevelDescription(value);
169473
- }
169474
- return "Balanced approach with standard implementation and testing";
169475
- }
169476
- function getDefaultEffortForModel2(model) {
169477
- if (isUltrathinkEnabled2() && modelSupportsEffort2(model)) {
169478
- return "medium";
169479
- }
169480
- return "medium";
169481
- }
169482
- var EFFORT_LEVELS2;
169483
- var init_effort2 = __esm(() => {
169484
- init_thinking();
169485
- init_settings3();
169486
- init_envUtils2();
169487
- EFFORT_LEVELS2 = [
169488
- "low",
169489
- "medium",
169490
- "high",
169491
- "xhigh",
169492
- "max"
169493
- ];
169494
- });
169495
-
169496
169621
  // src/tui/tools/FileWriteTool/prompt.ts
169497
169622
  function getPreReadInstruction3() {
169498
169623
  return `
@@ -180344,6 +180469,7 @@ __export(exports_engineCompat, {
180344
180469
  dequeueAllMatching: () => dequeueAllMatching,
180345
180470
  dequeuePendingNotification: () => dequeuePendingNotification,
180346
180471
  doesMessageExistInSession: () => doesMessageExistInSession,
180472
+ drainPendingBackgroundAgents: () => drainPendingBackgroundAgents,
180347
180473
  drainPendingMessages: () => drainPendingMessages,
180348
180474
  drainSdkEvents: () => drainSdkEvents,
180349
180475
  emitTaskTerminatedSdk: () => emitTaskTerminatedSdk,
@@ -180511,6 +180637,7 @@ __export(exports_engineCompat, {
180511
180637
  hasForegroundTasks: () => hasForegroundTasks,
180512
180638
  hasMetInitializationThreshold: () => hasMetInitializationThreshold,
180513
180639
  hasMetUpdateThreshold: () => hasMetUpdateThreshold,
180640
+ hasPendingBackgroundAgents: () => hasPendingBackgroundAgents,
180514
180641
  hasPendingNotifications: () => hasPendingNotifications,
180515
180642
  hasSessionMessagesCache: () => hasSessionMessagesCache,
180516
180643
  hasWorkingInProcessTeammates: () => hasWorkingInProcessTeammates,
@@ -180583,7 +180710,7 @@ __export(exports_engineCompat, {
180583
180710
  isWithheldPromptTooLong: () => isWithheldPromptTooLong,
180584
180711
  jitteredNextCronRunMs: () => jitteredNextCronRunMs,
180585
180712
  jsonParse: () => jsonParse,
180586
- jsonStringify: () => jsonStringify2,
180713
+ jsonStringify: () => jsonStringify,
180587
180714
  keepWorktree: () => keepWorktree,
180588
180715
  killAllRunningAgentTasks: () => killAllRunningAgentTasks,
180589
180716
  killAsyncAgent: () => killAsyncAgent,
@@ -180693,6 +180820,7 @@ __export(exports_engineCompat, {
180693
180820
  renderableSearchText: () => renderableSearchText,
180694
180821
  reportAutoCompactCircuitFailures: () => reportAutoCompactCircuitFailures,
180695
180822
  resetAutoCompactCircuitForTesting: () => resetAutoCompactCircuitForTesting,
180823
+ resetBackgroundAgentTracker: () => resetBackgroundAgentTracker,
180696
180824
  resetBuiltinCommandNamesSourceForTesting: () => resetBuiltinCommandNamesSourceForTesting,
180697
180825
  resetCheckInState: () => resetCheckInState,
180698
180826
  resetCommandQueue: () => resetCommandQueue,
@@ -180801,6 +180929,7 @@ __export(exports_engineCompat, {
180801
180929
  tokenCountWithEstimation: () => tokenCountWithEstimation,
180802
180930
  toolResultSearchText: () => toolResultSearchText,
180803
180931
  toolUseSearchText: () => toolUseSearchText,
180932
+ trackBackgroundAgent: () => trackBackgroundAgent,
180804
180933
  truncateHeadForPTLRetry: () => truncateHeadForPTLRetry,
180805
180934
  tryAcquireSchedulerLock: () => tryAcquireSchedulerLock,
180806
180935
  tryReactiveCompact: () => tryReactiveCompact,
@@ -276301,8 +276430,8 @@ ${whenNotToUseSection}
276301
276430
  Usage notes:
276302
276431
  - Always include a short description (3-5 words) summarizing what the agent will do${concurrencyNote}
276303
276432
  - When the agent is done, it will return a single message back to you. The result returned by the agent is not visible to the user. To show the user the result, you should send a text message back to the user with a concise summary of the result.${!isEnvTruthy2(process.env.ATLAS_DISABLE_BACKGROUND_TASKS) && !isInProcessTeammate3() && !forkEnabled ? `
276304
- - You can optionally run agents in the background using the run_in_background parameter. When an agent runs in the background, you will be automatically notified when it completes — do NOT sleep, poll, or proactively check on its progress. Continue with other work or respond to the user instead.
276305
- - **Foreground vs background**: Use foreground (default) when you need the agent's results before you can proceed — e.g., research agents whose findings inform your next steps. Use background when you have genuinely independent work to do in parallel.` : ""}
276433
+ - Agents run in the background by default. When an agent runs in the background, you will be automatically notified when it completes — do NOT sleep, poll, or proactively check on its progress. Continue with other work or respond to the user instead.
276434
+ - **Foreground vs background**: Agents run in the background by default. Use foreground (set run_in_background to false) when you need the agent's results before you can proceed — e.g., research agents whose findings inform your next steps. Use background when you have genuinely independent work to do in parallel.` : ""}
276306
276435
  - To continue a previously spawned agent, use ${SEND_MESSAGE_TOOL_NAME3} with the agent's ID or name as the \`to\` field. The agent resumes with its full context preserved. ${forkEnabled ? "Each fresh Agent invocation with a subagent_type starts without context — provide a complete task description." : "Each Agent invocation starts fresh — provide a complete task description."}
276307
276436
  - The agent's outputs should generally be trusted
276308
276437
  - Clearly tell the agent whether you expect it to write code or just to do research (search, file reads, web fetches, etc.)${forkEnabled ? "" : ", since it is not aware of the user's intent"}
@@ -276327,6 +276456,15 @@ var init_prompt13 = __esm(() => {
276327
276456
  });
276328
276457
 
276329
276458
  // src/tui/tools/AgentTool/AgentTool.ts
276459
+ function isAgentBackgroundByDefault2() {
276460
+ return !isEnvTruthy2(process.env.ATLAS_AGENT_DEFAULT_FOREGROUND);
276461
+ }
276462
+ function shouldRunInBackground2(runInBg) {
276463
+ if (isAgentBackgroundByDefault2()) {
276464
+ return runInBg !== false;
276465
+ }
276466
+ return !!runInBg;
276467
+ }
276330
276468
  function resolveAgentDefinition2(subagentType, agents) {
276331
276469
  if (!subagentType)
276332
276470
  return GENERAL_PURPOSE_AGENT2;
@@ -276359,6 +276497,7 @@ var init_AgentTool2 = __esm(() => {
276359
276497
  init_prompt13();
276360
276498
  init_runAgent2();
276361
276499
  init_UI9();
276500
+ init_envUtils2();
276362
276501
  inputSchema13 = lazySchema2(() => object({
276363
276502
  description: string2().describe("A short (3-5 word) description of the task"),
276364
276503
  prompt: string2().describe("The task for the agent to perform"),
@@ -276428,7 +276567,7 @@ var init_AgentTool2 = __esm(() => {
276428
276567
  },
276429
276568
  async call(args, context, canUseTool, parentMessage, onProgress) {
276430
276569
  const agents = getBuiltInAgents2();
276431
- const isAsync = !!args.run_in_background;
276570
+ const isAsync = shouldRunInBackground2(args.run_in_background);
276432
276571
  const agentId = createAgentId(args.description);
276433
276572
  const parentModel = context && context.options && (context.options.mainLoopModel || context.options.model) || "small";
276434
276573
  logForDebugging3("[AGENT] launching agent, type=" + (args.subagent_type ?? (isForkSubagentEnabled2() ? "fork" : "general-purpose")));
@@ -321148,6 +321287,7 @@ function buildAgentLoopParams(m) {
321148
321287
  ...m.systemContext,
321149
321288
  autoCompactCircuit: `Auto-compact is paused after ${circuitFailures} consecutive failures: respond concisely and avoid requests that expand the context — manual /compact, switching to a smaller model, or starting a new session are the recovery paths.`
321150
321289
  } : m.systemContext;
321290
+ let pendingReplacement = Promise.resolve();
321151
321291
  const deps = {
321152
321292
  modelProvider,
321153
321293
  role,
@@ -321186,8 +321326,16 @@ function buildAgentLoopParams(m) {
321186
321326
  }),
321187
321327
  transcript: {
321188
321328
  record: (msgs) => recordTranscript(msgs),
321189
- recordContentReplacement: (recs) => recordContentReplacement(recs),
321190
- saveGoalState: (goal) => saveGoalState(goal)
321329
+ recordContentReplacement: (recs) => {
321330
+ pendingReplacement = recordContentReplacement(recs);
321331
+ return pendingReplacement;
321332
+ },
321333
+ saveGoalState: (goal) => saveGoalState(goal),
321334
+ reAppendSessionMetadata: () => {
321335
+ pendingReplacement.catch(() => {
321336
+ return;
321337
+ }).then(() => reAppendSessionMetadata2()).catch((error) => logForDebugging(`reAppendSessionMetadata failed: ${errorMessage(error)}`));
321338
+ }
321191
321339
  },
321192
321340
  systemPrompt: asSystemPrompt(appendSystemContext(m.systemPrompt, systemContext)),
321193
321341
  effortValue: m.effort !== undefined ? String(m.effort) : undefined
@@ -321210,6 +321358,7 @@ var init_agentLoopDeps = __esm(() => {
321210
321358
  init_engine();
321211
321359
  init_Task();
321212
321360
  init_settings3();
321361
+ init_sessionStorage();
321213
321362
  init_shared();
321214
321363
  init_bootstrap();
321215
321364
  init_api2();
@@ -353222,7 +353371,6 @@ function ModelPicker(t0) {
353222
353371
  const selectedModelForPersist = resolveOptionModel(value_0);
353223
353372
  if (selectedModelForPersist && modelSupportsEffort2(selectedModelForPersist)) {
353224
353373
  updateSettingsForSource2("userSettings", {
353225
- effortLevel: persistable,
353226
353374
  effortByModel: withEffortForModel(selectedModelForPersist, persistable)
353227
353375
  });
353228
353376
  } else {
@@ -421446,6 +421594,7 @@ __export(exports_sessionStorage, {
421446
421594
  saveAgentSetting: () => saveAgentSetting,
421447
421595
  saveCustomTitle: () => saveCustomTitle,
421448
421596
  saveMode: () => saveMode2,
421597
+ saveSessionModelSetting: () => saveSessionModelSetting,
421449
421598
  saveTag: () => saveTag,
421450
421599
  saveWorktreeState: () => saveWorktreeState,
421451
421600
  searchSessionsByCustomTitle: () => searchSessionsByCustomTitle,
@@ -421572,6 +421721,7 @@ class Project2 {
421572
421721
  static METADATA_REWRITE_INTERVAL = 20;
421573
421722
  currentSessionAgentSetting;
421574
421723
  currentSessionMode;
421724
+ currentSessionModelSetting;
421575
421725
  currentSessionWorktree;
421576
421726
  currentSessionPrNumber;
421577
421727
  currentSessionPrUrl;
@@ -421765,6 +421915,13 @@ class Project2 {
421765
421915
  sessionId
421766
421916
  });
421767
421917
  }
421918
+ if (this.currentSessionModelSetting) {
421919
+ appendEntryToFile2(this.sessionFile, {
421920
+ type: "model-setting",
421921
+ modelSetting: this.currentSessionModelSetting,
421922
+ sessionId
421923
+ });
421924
+ }
421768
421925
  if (this.currentSessionWorktree !== undefined) {
421769
421926
  appendEntryToFile2(this.sessionFile, {
421770
421927
  type: "worktree-state",
@@ -422005,6 +422162,8 @@ class Project2 {
422005
422162
  this.enqueueWrite(sessionFile, entry);
422006
422163
  } else if (entry.type === "agent-setting") {
422007
422164
  this.enqueueWrite(sessionFile, entry);
422165
+ } else if (entry.type === "model-setting") {
422166
+ this.enqueueWrite(sessionFile, entry);
422008
422167
  } else if (entry.type === "pr-link") {
422009
422168
  this.enqueueWrite(sessionFile, entry);
422010
422169
  } else if (entry.type === "file-history-snapshot") {
@@ -422675,6 +422834,8 @@ function restoreSessionMetadata2(meta) {
422675
422834
  project.currentSessionAgentColor = meta.agentColor;
422676
422835
  if (meta.agentSetting)
422677
422836
  project.currentSessionAgentSetting = meta.agentSetting;
422837
+ if (meta.modelSetting)
422838
+ project.currentSessionModelSetting = meta.modelSetting;
422678
422839
  if (meta.mode)
422679
422840
  project.currentSessionMode = meta.mode;
422680
422841
  if (meta.worktreeSession !== undefined)
@@ -422694,6 +422855,7 @@ function clearSessionMetadata2() {
422694
422855
  project.currentSessionAgentColor = undefined;
422695
422856
  project.currentSessionLastPrompt = undefined;
422696
422857
  project.currentSessionAgentSetting = undefined;
422858
+ project.currentSessionModelSetting = undefined;
422697
422859
  project.currentSessionMode = undefined;
422698
422860
  project.currentSessionWorktree = undefined;
422699
422861
  project.currentSessionPrNumber = undefined;
@@ -422731,6 +422893,9 @@ function cacheSessionTitle2(customTitle) {
422731
422893
  function saveMode2(mode) {
422732
422894
  getProject2().currentSessionMode = mode;
422733
422895
  }
422896
+ function saveSessionModelSetting(modelSetting) {
422897
+ getProject2().currentSessionModelSetting = modelSetting ?? undefined;
422898
+ }
422734
422899
  function saveWorktreeState(worktreeSession) {
422735
422900
  const stripped = worktreeSession ? {
422736
422901
  originalCwd: worktreeSession.originalCwd,
@@ -422779,6 +422944,7 @@ async function loadFullLog(log) {
422779
422944
  agentNames,
422780
422945
  agentColors,
422781
422946
  agentSettings,
422947
+ modelSettings,
422782
422948
  prNumbers,
422783
422949
  prUrls,
422784
422950
  prRepositories,
@@ -422811,6 +422977,7 @@ async function loadFullLog(log) {
422811
422977
  agentName: sessionId ? agentNames.get(sessionId) : log.agentName,
422812
422978
  agentColor: sessionId ? agentColors.get(sessionId) : log.agentColor,
422813
422979
  agentSetting: sessionId ? agentSettings.get(sessionId) : log.agentSetting,
422980
+ modelSetting: sessionId ? modelSettings.get(sessionId) : log.modelSetting,
422814
422981
  mode: sessionId ? modes.get(sessionId) : log.mode,
422815
422982
  worktreeSession: sessionId && worktreeStates.has(sessionId) ? worktreeStates.get(sessionId) : log.worktreeSession,
422816
422983
  prNumber: sessionId ? prNumbers.get(sessionId) : log.prNumber,
@@ -423068,6 +423235,7 @@ async function loadTranscriptFile2(filePath, opts) {
423068
423235
  const agentNames = new Map;
423069
423236
  const agentColors = new Map;
423070
423237
  const agentSettings = new Map;
423238
+ const modelSettings = new Map;
423071
423239
  const prNumbers = new Map;
423072
423240
  const prUrls = new Map;
423073
423241
  const prRepositories = new Map;
@@ -423114,6 +423282,8 @@ async function loadTranscriptFile2(filePath, opts) {
423114
423282
  agentColors.set(entry.sessionId, entry.agentColor);
423115
423283
  } else if (entry.type === "agent-setting" && entry.sessionId) {
423116
423284
  agentSettings.set(entry.sessionId, entry.agentSetting);
423285
+ } else if (entry.type === "model-setting" && entry.sessionId) {
423286
+ modelSettings.set(entry.sessionId, entry.modelSetting);
423117
423287
  } else if (entry.type === "mode" && entry.sessionId) {
423118
423288
  modes.set(entry.sessionId, entry.mode);
423119
423289
  } else if (entry.type === "worktree-state" && entry.sessionId) {
@@ -423154,6 +423324,8 @@ async function loadTranscriptFile2(filePath, opts) {
423154
423324
  agentColors.set(entry.sessionId, entry.agentColor);
423155
423325
  } else if (entry.type === "agent-setting" && entry.sessionId) {
423156
423326
  agentSettings.set(entry.sessionId, entry.agentSetting);
423327
+ } else if (entry.type === "model-setting" && entry.sessionId) {
423328
+ modelSettings.set(entry.sessionId, entry.modelSetting);
423157
423329
  } else if (entry.type === "mode" && entry.sessionId) {
423158
423330
  modes.set(entry.sessionId, entry.mode);
423159
423331
  } else if (entry.type === "worktree-state" && entry.sessionId) {
@@ -423242,6 +423414,7 @@ async function loadTranscriptFile2(filePath, opts) {
423242
423414
  agentNames,
423243
423415
  agentColors,
423244
423416
  agentSettings,
423417
+ modelSettings,
423245
423418
  prNumbers,
423246
423419
  prUrls,
423247
423420
  prRepositories,
@@ -423709,7 +423882,10 @@ async function readLiteMetadata(filePath, fileSize, buf) {
423709
423882
  const agentName = extractLastJsonStringField2(tail, "agentName");
423710
423883
  const agentColor = extractLastJsonStringField2(tail, "agentColor");
423711
423884
  const firstPrompt = extractLastJsonStringField2(tail, "lastPrompt") || extractFirstPromptFromChunk(head) || extractJsonStringFieldPrefix(head, "content", 200) || extractJsonStringFieldPrefix(head, "text", 200) || "";
423712
- const customTitle = extractLastJsonStringField2(tail, "customTitle") ?? extractLastJsonStringField2(head, "customTitle") ?? extractLastJsonStringField2(tail, "aiTitle") ?? extractLastJsonStringField2(head, "aiTitle");
423885
+ let customTitle = extractLastJsonStringField2(tail, "customTitle") ?? extractLastJsonStringField2(head, "customTitle") ?? extractLastJsonStringField2(tail, "aiTitle") ?? extractLastJsonStringField2(head, "aiTitle");
423886
+ if (!customTitle) {
423887
+ customTitle = await scanMidForSessionTitle(filePath, fileSize);
423888
+ }
423713
423889
  const summary = extractLastJsonStringField2(tail, "summary");
423714
423890
  const tag = extractLastJsonStringField2(tail, "tag");
423715
423891
  const gitBranch = extractLastJsonStringField2(tail, "gitBranch") ?? extractJsonStringField(head, "gitBranch");
@@ -423999,7 +424175,8 @@ var init_sessionStorage = __esm(() => {
423999
424175
  MAX_TRANSCRIPT_READ_BYTES2 = 50 * 1024 * 1024;
424000
424176
  agentTranscriptSubdirs2 = new Map;
424001
424177
  getProjectDir3 = memoize_default((projectDir) => {
424002
- return join161(getProjectsDir3(), sanitizePath3(projectDir));
424178
+ const normalized = process.platform === "win32" ? projectDir.toLowerCase() : projectDir;
424179
+ return join161(getProjectsDir3(), sanitizePath3(normalized));
424003
424180
  });
424004
424181
  METADATA_TYPE_MARKERS2 = [
424005
424182
  '"type":"summary"',
@@ -432844,6 +433021,7 @@ function wireContextHostPorts() {
432844
433021
  setAutoCompactSettingsSource(() => getGlobalConfig().autoCompactEnabled);
432845
433022
  setAutoCompactWindowSettingsSource(() => getInitialSettings2().autoCompactWindow);
432846
433023
  setLlmTimeoutSettingsSource(() => getInitialSettings2().llmTimeoutMs);
433024
+ setEffortByModelSource(() => getEffortByModel());
432847
433025
  setTimeBasedMCConfigSource(() => getFeatureValue_CACHED_MAY_BE_STALE("atlas_slate_heron", TIME_BASED_MC_CONFIG_DEFAULTS));
432848
433026
  clearPostCompactResetsForTesting();
432849
433027
  if (feature("CONTEXT_COLLAPSE")) {
@@ -432876,6 +433054,7 @@ var init_contextHostWiring = __esm(() => {
432876
433054
  init_engine();
432877
433055
  init_config6();
432878
433056
  init_settings3();
433057
+ init_effort2();
432879
433058
  init_growthbook();
432880
433059
  init_hooks7();
432881
433060
  init_sessionStart();
@@ -435243,10 +435422,12 @@ function onChangeAppState({
435243
435422
  if (newState.mainLoopModel !== oldState.mainLoopModel && newState.mainLoopModel === null) {
435244
435423
  updateSettingsForSource2("userSettings", { model: undefined });
435245
435424
  setMainLoopModelOverride(null);
435425
+ saveSessionModelSetting(null);
435246
435426
  }
435247
435427
  if (newState.mainLoopModel !== oldState.mainLoopModel && newState.mainLoopModel !== null) {
435248
435428
  updateSettingsForSource2("userSettings", { model: newState.mainLoopModel });
435249
435429
  setMainLoopModelOverride(newState.mainLoopModel);
435430
+ saveSessionModelSetting(newState.mainLoopModel);
435250
435431
  }
435251
435432
  if (newState.expandedView !== oldState.expandedView) {
435252
435433
  const showExpandedTodos = newState.expandedView === "tasks";
@@ -435287,6 +435468,7 @@ var init_onChangeAppState = __esm(() => {
435287
435468
  init_PermissionMode();
435288
435469
  init_sessionState();
435289
435470
  init_settings3();
435471
+ init_sessionStorage();
435290
435472
  });
435291
435473
 
435292
435474
  // src/tui/components/App.tsx
@@ -470248,6 +470430,7 @@ async function loadConversationForResume(source, sourceJsonlFile) {
470248
470430
  agentName: log?.agentName,
470249
470431
  agentColor: log?.agentColor,
470250
470432
  agentSetting: log?.agentSetting,
470433
+ modelSetting: log?.modelSetting,
470251
470434
  customTitle: log?.customTitle,
470252
470435
  tag: log?.tag,
470253
470436
  mode: log?.mode,
@@ -470573,6 +470756,15 @@ async function processResumedConversation2(result, opts, context) {
470573
470756
  if (feature("CONTEXT_COLLAPSE")) {
470574
470757
  __toCommonJS(exports_persist).restoreFromEntries(result.contextCollapseCommits ?? [], result.contextCollapseSnapshot);
470575
470758
  }
470759
+ if (result.modelSetting && !getMainLoopModelOverride()) {
470760
+ setMainLoopModelOverride(parseUserSpecifiedModel2(result.modelSetting));
470761
+ }
470762
+ if (!result.modelSetting) {
470763
+ const modelRejected = globalModelRejectedNotice();
470764
+ if (modelRejected) {
470765
+ result.messages.push(createSystemMessage(modelRejected, "warning"));
470766
+ }
470767
+ }
470576
470768
  const { agentDefinition: restoredAgent, agentType: resumedAgentType } = restoreAgentFromSession(result.agentSetting, context.mainThreadAgentDefinition, context.agentDefinitions);
470577
470769
  if (feature("COORDINATOR_MODE")) {
470578
470770
  saveMode2(context.modeApi?.isCoordinatorMode() ? "coordinator" : "normal");
@@ -494393,6 +494585,21 @@ function createCoreDependencies() {
494393
494585
  return;
494394
494586
  }
494395
494587
  });
494588
+ setEffortByModelSource(() => {
494589
+ try {
494590
+ const raw = getInitialSettings().effortByModel;
494591
+ if (!raw)
494592
+ return;
494593
+ const out = {};
494594
+ for (const [k, v] of Object.entries(raw)) {
494595
+ if (isEffortLevel(v))
494596
+ out[k] = v;
494597
+ }
494598
+ return out;
494599
+ } catch {
494600
+ return;
494601
+ }
494602
+ });
494396
494603
  return {
494397
494604
  sandboxManager,
494398
494605
  modelProvider: getModelProvider(),