@atlasharness/atlascode 0.1.62 → 0.1.64

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 +909 -573
  2. package/package.json +1 -1
package/dist/cli.js CHANGED
@@ -26901,7 +26901,39 @@ function llmTimeoutRemediationHint(error, currentTimeoutMs) {
26901
26901
  const head = typeof currentTimeoutMs === "number" && currentTimeoutMs > 0 ? `当前超时 ${Math.round(currentTimeoutMs / 1000)}s` : "慢模型长生成可能超过缺省超时";
26902
26902
  return `LLM 请求超时(${head})。可调大:env ATLAS_LLM_TIMEOUT=<毫秒> 或 settings.json llmTimeoutMs 键(上限 ${Math.round(LLM_TIMEOUT_CAP_MS / 60000)}min)。`;
26903
26903
  }
26904
- function gatewayUnreachableRemediationHint(error) {
26904
+ function describeEndpointFailure(baseURL) {
26905
+ if (!baseURL)
26906
+ return "LLM 端点";
26907
+ let host;
26908
+ let port;
26909
+ try {
26910
+ const u = new URL(baseURL);
26911
+ host = u.hostname;
26912
+ port = u.port;
26913
+ } catch {
26914
+ return "LLM 端点";
26915
+ }
26916
+ if (host === "localhost" || host === "0.0.0.0" || host === "[::1]" || host.startsWith("127.")) {
26917
+ return port ? `本地端口 ${port}` : "本地网关";
26918
+ }
26919
+ const knownProviders = [
26920
+ [/api\.deepseek\.com$/i, "DeepSeek"],
26921
+ [/api\.openai\.com$/i, "OpenAI"],
26922
+ [/^(dashscope|api)\.aliyuncs\.com$/i, "阿里百炼"],
26923
+ [/api\.moonshot\.cn$/i, "Kimi"],
26924
+ [/api\.minimax\.chat$/i, "MiniMax"],
26925
+ [/api\.baichuan-ai\.com$/i, "百川"],
26926
+ [/api\.01\.ai$/i, "零一万物"],
26927
+ [/api\.siliconflow\.cn$/i, "硅基流动"],
26928
+ [/api\.lkeap\.com$/i, "腾讯混元"]
26929
+ ];
26930
+ for (const [re, name] of knownProviders) {
26931
+ if (re.test(host))
26932
+ return `${name} 服务`;
26933
+ }
26934
+ return host;
26935
+ }
26936
+ function gatewayUnreachableRemediationHint(error, endpointLabel) {
26905
26937
  if (!error || typeof error !== "object")
26906
26938
  return null;
26907
26939
  const e = error;
@@ -26918,7 +26950,7 @@ function gatewayUnreachableRemediationHint(error) {
26918
26950
  const isNetworkErrno = /ECONNREFUSED|ECONNRESET|ENOTFOUND|ENETUNREACH|EHOSTUNREACH|EAI_AGAIN|fetch failed|socket hang up/i.test(haystack);
26919
26951
  if (!isSdkConnection && !isNetworkErrno)
26920
26952
  return null;
26921
- return "IFF 不可达:已切人工确认 —— /doctor 排查";
26953
+ return `${endpointLabel ?? "LLM 端点"} 不可达:已切人工确认 —— /doctor 排查`;
26922
26954
  }
26923
26955
  function modelRetryBackoffMs(attempt, baseMs = MODEL_RETRY_BACKOFF_BASE_MS, capMs = MODEL_RETRY_BACKOFF_CAP_MS) {
26924
26956
  const base = Math.max(0, baseMs);
@@ -27824,6 +27856,18 @@ function setLlmTimeoutSettingsSource(next) {
27824
27856
  function getCurrentLlmTimeoutMs() {
27825
27857
  return resolveLlmTimeoutMs(process.env.ATLAS_LLM_TIMEOUT, llmTimeoutSettingsSource?.());
27826
27858
  }
27859
+ function getCurrentEndpointLabel(modelRef) {
27860
+ let baseURL;
27861
+ if (modelRef) {
27862
+ const resolved = resolveModel(modelRef);
27863
+ if (resolved?.baseURL)
27864
+ baseURL = resolved.baseURL;
27865
+ }
27866
+ if (!baseURL) {
27867
+ baseURL = getRoleConfig("small").baseURL;
27868
+ }
27869
+ return describeEndpointFailure(baseURL);
27870
+ }
27827
27871
  function resolveLlmTimeoutMs(envRaw = process.env.ATLAS_LLM_TIMEOUT, settingsMs) {
27828
27872
  const fromSettings = () => typeof settingsMs === "number" && Number.isInteger(settingsMs) && settingsMs >= 1 ? Math.min(settingsMs, LLM_TIMEOUT_CAP_MS) : LLM_TIMEOUT_DEFAULT_MS;
27829
27873
  if (envRaw === undefined || envRaw === "")
@@ -27847,6 +27891,7 @@ var init_modelprovider2 = __esm(() => {
27847
27891
  init_modelprovider();
27848
27892
  init_constants2();
27849
27893
  init_shared();
27894
+ init_roles7();
27850
27895
  init_constants2();
27851
27896
  init_modelprovider();
27852
27897
  init_types2();
@@ -27966,11 +28011,31 @@ function armGoal(condition) {
27966
28011
  reason: `Goal condition exceeds ${MAX_GOAL_CONDITION_CHARS} characters (got ${trimmed.length}).`
27967
28012
  };
27968
28013
  }
27969
- goalState = { armed: true, condition: trimmed };
28014
+ goalState = { armed: true, condition: trimmed, paused: false, pausedReason: undefined };
27970
28015
  return { ok: true };
27971
28016
  }
27972
28017
  function clearGoal() {
27973
- goalState = { armed: false, condition: undefined };
28018
+ goalState = { armed: false, condition: undefined, paused: false, pausedReason: undefined };
28019
+ }
28020
+ function pauseGoal(reason) {
28021
+ if (!goalState.armed)
28022
+ return;
28023
+ goalState = { ...goalState, paused: true, pausedReason: reason };
28024
+ }
28025
+ function resumeGoal() {
28026
+ if (!goalState.paused)
28027
+ return;
28028
+ goalState = { ...goalState, paused: false, pausedReason: undefined };
28029
+ }
28030
+ function isGoalPaused() {
28031
+ return goalState.armed && goalState.paused;
28032
+ }
28033
+ function getGoalPausedReason() {
28034
+ return goalState.armed && goalState.paused ? goalState.pausedReason : undefined;
28035
+ }
28036
+ function goalPausedNotification(reason) {
28037
+ return `Goal paused: ${reason}
28038
+ The goal will resume when the condition recovers.`;
27974
28039
  }
27975
28040
  function isGoalArmed() {
27976
28041
  return goalState.armed;
@@ -27986,13 +28051,27 @@ function getGoalStateForPersistence() {
27986
28051
  }
27987
28052
  function restoreGoalState(snapshot) {
27988
28053
  if (snapshot && snapshot.armed && snapshot.condition.trim() !== "") {
27989
- goalState = { armed: true, condition: snapshot.condition.trim() };
28054
+ goalState = { armed: true, condition: snapshot.condition.trim(), paused: false, pausedReason: undefined };
27990
28055
  } else {
27991
- goalState = { armed: false, condition: undefined };
28056
+ goalState = { armed: false, condition: undefined, paused: false, pausedReason: undefined };
27992
28057
  }
27993
28058
  }
27994
28059
  function resetGoalStateForTesting() {
27995
- goalState = { armed: false, condition: undefined };
28060
+ goalState = { armed: false, condition: undefined, paused: false, pausedReason: undefined };
28061
+ }
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";
28066
+ }
28067
+ if (msg.includes("context length exceeded") || msg.includes("prompt too long") || msg.includes("context window")) {
28068
+ return "unrecoverable";
28069
+ }
28070
+ return "recoverable";
28071
+ }
28072
+ function goalUnrecoverableNotification(reason) {
28073
+ return `Goal cleared (unrecoverable): ${reason}
28074
+ The goal can no longer be pursued. Set a new goal if needed.`;
27996
28075
  }
27997
28076
  function extractConversationEvidence(messages, maxMessages = 12) {
27998
28077
  const recent = messages.slice(-maxMessages);
@@ -28070,297 +28149,146 @@ The goal has been auto-cleared.`;
28070
28149
  function goalClearedNotification() {
28071
28150
  return "Goal cleared.";
28072
28151
  }
28152
+ function goalHookGateNotification() {
28153
+ return "Goal cleared: hooks are disabled (disableAllHooks). Goals require hooks to continue.";
28154
+ }
28073
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.
28074
28156
 
28075
28157
  Respond on the first line with exactly "MET" or "UNMET". On the following line, give a one-sentence reason citing the conversation evidence.`;
28076
28158
  var init_goalState = __esm(() => {
28077
- goalState = { armed: false, condition: undefined };
28159
+ goalState = { armed: false, condition: undefined, paused: false, pausedReason: undefined };
28078
28160
  });
28079
28161
 
28080
- // src/engine/pipeline/errorClassification.ts
28081
- function classifyToolError(error) {
28082
- if (error instanceof Error) {
28083
- const errnoCode = error.code;
28084
- if (typeof errnoCode === "string") {
28085
- return `Error:${errnoCode}`;
28086
- }
28087
- if (error.name && error.name !== "Error" && error.name.length > 3) {
28088
- return error.name.slice(0, 60);
28089
- }
28090
- return "Error";
28091
- }
28092
- return "UnknownError";
28162
+ // src/engine/config/settingsCache.ts
28163
+ function getSessionSettingsCache() {
28164
+ return sessionSettingsCache;
28093
28165
  }
28094
-
28095
- // src/engine/pipeline/schemaValidation.ts
28096
- function typeName(v) {
28097
- if (v === null)
28098
- return "null";
28099
- if (Array.isArray(v))
28100
- return "array";
28101
- return typeof v;
28166
+ function setSessionSettingsCache(value) {
28167
+ sessionSettingsCache = value;
28102
28168
  }
28103
- function checkBasicType(value, type) {
28104
- switch (type) {
28105
- case "string":
28106
- return typeof value === "string" ? null : `expected string, got ${typeName(value)}`;
28107
- case "number":
28108
- if (typeof value === "number") {
28109
- return Number.isFinite(value) ? null : "expected number, got non-finite number";
28110
- }
28111
- return `expected number, got ${typeName(value)}`;
28112
- case "integer":
28113
- if (typeof value === "number") {
28114
- return Number.isInteger(value) ? null : "expected integer, got non-integer number";
28115
- }
28116
- return `expected integer, got ${typeName(value)}`;
28117
- case "boolean":
28118
- return typeof value === "boolean" ? null : `expected boolean, got ${typeName(value)}`;
28119
- case "array":
28120
- return Array.isArray(value) ? null : `expected array, got ${typeName(value)}`;
28121
- case "object":
28122
- return typeof value === "object" && value !== null && !Array.isArray(value) ? null : `expected object, got ${typeName(value)}`;
28123
- case "null":
28124
- return value === null ? null : `expected null, got ${typeName(value)}`;
28125
- default:
28126
- return null;
28127
- }
28169
+ function getCachedSettingsForSource(source) {
28170
+ return perSourceCache.has(source) ? perSourceCache.get(source) : undefined;
28128
28171
  }
28129
- function validateInputBySchema(input, schema) {
28130
- if (!schema) {
28131
- return { valid: true };
28132
- }
28133
- if (input === null || typeof input !== "object" || Array.isArray(input)) {
28134
- return { valid: false, message: "expected object input" };
28135
- }
28136
- const record = input;
28137
- const errors = [];
28138
- const required = schema.required;
28139
- if (Array.isArray(required)) {
28140
- for (const rawKey of required) {
28141
- const key = String(rawKey);
28142
- if (!(key in record) || record[key] === undefined) {
28143
- errors.push(`missing required field "${key}"`);
28144
- }
28145
- }
28146
- }
28147
- const properties = schema.properties;
28148
- if (properties) {
28149
- for (const [key, value] of Object.entries(record)) {
28150
- if (value === undefined)
28151
- continue;
28152
- const propSchema = properties[key];
28153
- if (!propSchema || typeof propSchema !== "object")
28154
- continue;
28155
- const type = propSchema.type;
28156
- if (typeof type !== "string")
28157
- continue;
28158
- const err = checkBasicType(value, type);
28159
- if (err)
28160
- errors.push(`field "${key}": ${err}`);
28161
- }
28162
- }
28163
- return errors.length > 0 ? { valid: false, message: errors.join("; ") } : { valid: true };
28172
+ function setCachedSettingsForSource(source, value) {
28173
+ perSourceCache.set(source, value);
28164
28174
  }
28165
- function buildSchemaNotSentHint(tool, discoveredToolNames) {
28166
- if (!tool.shouldDefer)
28167
- return null;
28168
- if (discoveredToolNames.has(tool.name))
28169
- return null;
28170
- return `
28171
-
28172
- 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).`;
28175
+ function getCachedParsedFile(path) {
28176
+ return parseFileCache.get(path);
28177
+ }
28178
+ function setCachedParsedFile(path, value) {
28179
+ parseFileCache.set(path, value);
28173
28180
  }
28181
+ function resetSettingsCache() {
28182
+ sessionSettingsCache = null;
28183
+ perSourceCache.clear();
28184
+ parseFileCache.clear();
28185
+ }
28186
+ function getPluginSettingsBase() {
28187
+ return pluginSettingsBase;
28188
+ }
28189
+ function setPluginSettingsBase(settings) {
28190
+ pluginSettingsBase = settings;
28191
+ }
28192
+ function clearPluginSettingsBase() {
28193
+ pluginSettingsBase = undefined;
28194
+ }
28195
+ var sessionSettingsCache = null, perSourceCache, parseFileCache, pluginSettingsBase;
28196
+ var init_settingsCache = __esm(() => {
28197
+ perSourceCache = new Map;
28198
+ parseFileCache = new Map;
28199
+ });
28174
28200
 
28175
- // src/engine/pipeline/toolExecution.ts
28176
- function mergeHookPermission(hookBehavior, gate, hookReason) {
28177
- if (hookBehavior === "defer") {
28178
- return {
28179
- allowed: false,
28180
- deferred: true,
28181
- reason: hookReason ?? "deferred by hook"
28182
- };
28183
- }
28184
- if (hookBehavior === "deny") {
28185
- return { allowed: false, reason: "blocked by hook" };
28186
- }
28187
- if (!gate.allowed)
28188
- return gate;
28189
- if (hookBehavior === "ask") {
28190
- return { allowed: false, ask: true, reason: "hook requested confirmation" };
28191
- }
28192
- return gate;
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");
28193
28212
  }
28194
- function findTool(tools, name) {
28195
- return tools.find((t) => t.name === name || (t.aliases?.includes(name) ?? false));
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);
28196
28223
  }
28197
- async function executeToolUse(tu, assistantMsg, deps) {
28198
- const tool = findTool(deps.tools, tu.name);
28199
- if (!tool) {
28200
- return {
28201
- block: {
28202
- type: "tool_result",
28203
- tool_use_id: tu.id,
28204
- content: `unknown tool: ${tu.name}`,
28205
- is_error: true
28206
- },
28207
- isError: true
28208
- };
28209
- }
28210
- const toolCallContext = deps.toolContext !== undefined ? { ...deps.toolContext, signal: deps.signal, checkPermission: deps.checkPermission } : { signal: deps.signal, checkPermission: deps.checkPermission };
28211
- const schemaResult = validateInputBySchema(tu.input, tool.inputSchema);
28212
- if (schemaResult.valid === false) {
28213
- const discovered = deps.discoveredToolNames ?? new Set(deps.tools.map((t) => t.name));
28214
- const schemaHint = buildSchemaNotSentHint(tool, discovered);
28215
- const errorContent = schemaHint ? `${schemaResult.message}${schemaHint}` : schemaResult.message;
28216
- return {
28217
- block: {
28218
- type: "tool_result",
28219
- tool_use_id: tu.id,
28220
- content: `<tool_use_error>InputValidationError: ${errorContent}</tool_use_error>`,
28221
- is_error: true
28222
- },
28223
- isError: true
28224
- };
28225
- }
28226
- const validation = await tool.validateInput?.(tu.input, toolCallContext);
28227
- if (validation && validation.result === false) {
28228
- return {
28229
- block: {
28230
- type: "tool_result",
28231
- tool_use_id: tu.id,
28232
- content: `<tool_use_error>InputValidationError: ${validation.message}</tool_use_error>`,
28233
- is_error: true
28234
- },
28235
- isError: true
28236
- };
28237
- }
28238
- const preOutcome = await deps.hooks?.preToolUse?.(tool, tu.input, tu.id);
28239
- if (preOutcome?.blockingError) {
28240
- return {
28241
- block: {
28242
- type: "tool_result",
28243
- tool_use_id: tu.id,
28244
- content: `<tool_use_error>hook blocked: ${preOutcome.blockingError}</tool_use_error>`,
28245
- is_error: true
28246
- },
28247
- isError: true
28248
- };
28249
- }
28250
- if (preOutcome?.preventContinuation) {
28251
- return {
28252
- block: {
28253
- type: "tool_result",
28254
- tool_use_id: tu.id,
28255
- content: `<tool_use_error>Execution stopped by PreToolUse hook${preOutcome.stopReason ? `: ${preOutcome.stopReason}` : ""}</tool_use_error>`,
28256
- is_error: true
28257
- },
28258
- isError: true
28259
- };
28260
- }
28261
- const effectiveInput = preOutcome?.updatedInput ?? tu.input;
28262
- const gateVerdict = deps.checkPermission ? await deps.checkPermission(tool, effectiveInput, {
28263
- toolUseId: tu.id,
28264
- assistantMessage: assistantMsg
28265
- }) : { allowed: true };
28266
- const verdict = mergeHookPermission(preOutcome?.hookBehavior, gateVerdict, preOutcome?.hookPermissionDecisionReason);
28267
- if (verdict.deferred) {
28268
- return { deferred: true, deferReason: verdict.reason, isError: false };
28269
- }
28270
- if (!verdict.allowed) {
28271
- 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>`;
28272
- return {
28273
- block: {
28274
- type: "tool_result",
28275
- tool_use_id: tu.id,
28276
- content,
28277
- is_error: true
28278
- },
28279
- isError: true
28280
- };
28281
- }
28282
- const callInput = verdict.updatedInput ?? effectiveInput;
28283
- let block;
28284
- let isError = false;
28285
- let toolUseResult;
28286
- try {
28287
- const res = await tool.call(callInput, toolCallContext, undefined, assistantMsg);
28288
- block = tool.mapToolResultToToolResultBlockParam(res.data, tu.id);
28289
- toolUseResult = res.data;
28290
- } catch (error) {
28291
- const errorText = `tool error [${classifyToolError(error)}]: ${String(error?.message ?? error)}`;
28292
- block = {
28293
- type: "tool_result",
28294
- tool_use_id: tu.id,
28295
- content: `<tool_use_error>${errorText}</tool_use_error>`,
28296
- is_error: true
28297
- };
28298
- isError = true;
28299
- toolUseResult = errorText;
28300
- }
28301
- const postOutcome = await deps.hooks?.postToolUse?.(tool, callInput, block, tu.id);
28302
- if (postOutcome?.updatedToolOutput !== undefined) {
28303
- block = { ...block, content: postOutcome.updatedToolOutput };
28304
- toolUseResult = postOutcome.updatedToolOutput;
28305
- }
28306
- return { block, isError, toolUseResult };
28224
+ function isSettingSourceEnabled(source) {
28225
+ const enabled = getEnabledSettingSources();
28226
+ return enabled.includes(source);
28307
28227
  }
28308
- var init_toolExecution = () => {};
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
+ });
28309
28239
 
28310
- // src/engine/pipeline/toolOrchestration.ts
28311
- function partitionToolCalls(toolUses, tools) {
28312
- return toolUses.reduce((acc, tu) => {
28313
- const tool = findTool(tools, tu.name);
28314
- let safe = false;
28315
- try {
28316
- safe = tool ? tool.isConcurrencySafe(tu.input) : false;
28317
- } catch {
28318
- safe = false;
28240
+ // src/engine/config/merge.ts
28241
+ function isPlainObject2(v) {
28242
+ return typeof v === "object" && v !== null && !Array.isArray(v);
28243
+ }
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
+ }
28319
28254
  }
28320
- if (safe && acc[acc.length - 1]?.isConcurrencySafe) {
28321
- acc[acc.length - 1].blocks.push(tu);
28255
+ if (srcValue === undefined)
28256
+ continue;
28257
+ if (isPlainObject2(objValue) && isPlainObject2(srcValue)) {
28258
+ mergeWith(objValue, srcValue, customizer);
28322
28259
  } else {
28323
- acc.push({ isConcurrencySafe: safe, blocks: [tu] });
28260
+ target[key] = srcValue;
28324
28261
  }
28325
- return acc;
28326
- }, []);
28262
+ }
28263
+ return target;
28327
28264
  }
28328
- async function runToolBatch(toolUses, assistantMsg, deps) {
28329
- const outcomes = [];
28330
- for (const batch of partitionToolCalls(toolUses, deps.tools)) {
28331
- for (const tu of batch.blocks) {
28332
- const r = await executeToolUse(tu, assistantMsg, deps);
28333
- outcomes.push({
28334
- toolUseId: tu.id,
28335
- name: tu.name,
28336
- block: r.block,
28337
- isError: r.isError,
28338
- toolUseResult: r.toolUseResult,
28339
- deferred: r.deferred,
28340
- deferReason: r.deferReason
28341
- });
28342
- if (r.deferred) {
28343
- return outcomes;
28344
- }
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);
28345
28272
  }
28346
28273
  }
28347
- return outcomes;
28274
+ return out;
28275
+ }
28276
+ function settingsMergeCustomizer(objValue, srcValue) {
28277
+ if (Array.isArray(objValue) && Array.isArray(srcValue)) {
28278
+ return uniq([...objValue, ...srcValue]);
28279
+ }
28280
+ return;
28348
28281
  }
28349
- var init_toolOrchestration = __esm(() => {
28350
- init_toolExecution();
28351
- });
28352
-
28353
- // src/engine/pipeline/index.ts
28354
- var init_pipeline = __esm(() => {
28355
- init_toolExecution();
28356
- init_toolOrchestration();
28357
- });
28358
28282
 
28359
- // node_modules/zod/index.js
28360
- var init_zod = __esm(() => {
28361
- init_external();
28362
- init_external();
28363
- });
28283
+ // src/engine/config/managedPath.ts
28284
+ import { join as join3 } from "path";
28285
+ function getManagedSettingsDir() {
28286
+ return "/etc/atlas";
28287
+ }
28288
+ function getManagedSettingsDropInDir() {
28289
+ return join3(getManagedSettingsDir(), "managed-settings.d");
28290
+ }
28291
+ var init_managedPath = () => {};
28364
28292
 
28365
28293
  // src/hooks/hookEvents.ts
28366
28294
  var HOOK_EVENTS;
@@ -28950,131 +28878,6 @@ var init_types3 = __esm(() => {
28950
28878
  init_hooksSchema();
28951
28879
  });
28952
28880
 
28953
- // src/engine/config/constants.ts
28954
- function getEnabledSettingSources() {
28955
- const result = new Set(ALLOWED_SETTING_SOURCES);
28956
- result.add("policySettings");
28957
- result.add("flagSettings");
28958
- return Array.from(result);
28959
- }
28960
- function isSettingSourceEnabled(source) {
28961
- const enabled = getEnabledSettingSources();
28962
- return enabled.includes(source);
28963
- }
28964
- var SETTING_SOURCES, ALLOWED_SETTING_SOURCES;
28965
- var init_constants3 = __esm(() => {
28966
- SETTING_SOURCES = [
28967
- "userSettings",
28968
- "projectSettings",
28969
- "localSettings",
28970
- "flagSettings",
28971
- "policySettings"
28972
- ];
28973
- ALLOWED_SETTING_SOURCES = ["userSettings"];
28974
- });
28975
-
28976
- // src/engine/config/settingsCache.ts
28977
- function getSessionSettingsCache() {
28978
- return sessionSettingsCache;
28979
- }
28980
- function setSessionSettingsCache(value) {
28981
- sessionSettingsCache = value;
28982
- }
28983
- function getCachedSettingsForSource(source) {
28984
- return perSourceCache.has(source) ? perSourceCache.get(source) : undefined;
28985
- }
28986
- function setCachedSettingsForSource(source, value) {
28987
- perSourceCache.set(source, value);
28988
- }
28989
- function getCachedParsedFile(path) {
28990
- return parseFileCache.get(path);
28991
- }
28992
- function setCachedParsedFile(path, value) {
28993
- parseFileCache.set(path, value);
28994
- }
28995
- function resetSettingsCache() {
28996
- sessionSettingsCache = null;
28997
- perSourceCache.clear();
28998
- parseFileCache.clear();
28999
- }
29000
- function getPluginSettingsBase() {
29001
- return pluginSettingsBase;
29002
- }
29003
- function setPluginSettingsBase(settings) {
29004
- pluginSettingsBase = settings;
29005
- }
29006
- function clearPluginSettingsBase() {
29007
- pluginSettingsBase = undefined;
29008
- }
29009
- var sessionSettingsCache = null, perSourceCache, parseFileCache, pluginSettingsBase;
29010
- var init_settingsCache = __esm(() => {
29011
- perSourceCache = new Map;
29012
- parseFileCache = new Map;
29013
- });
29014
-
29015
- // src/engine/config/managedPath.ts
29016
- import { join as join2 } from "path";
29017
- function getManagedSettingsDir() {
29018
- return "/etc/atlas";
29019
- }
29020
- function getManagedSettingsDropInDir() {
29021
- return join2(getManagedSettingsDir(), "managed-settings.d");
29022
- }
29023
- var init_managedPath = () => {};
29024
-
29025
- // src/engine/config/configRoot.ts
29026
- import { homedir as homedir2 } from "os";
29027
- import { join as join3 } from "path";
29028
- function getAtlasConfigHomeDir() {
29029
- return (process.env.ATLAS_CONFIG_DIR ?? join3(homedir2(), getConfigDirName())).normalize("NFC");
29030
- }
29031
- var init_configRoot = __esm(() => {
29032
- init_shared();
29033
- });
29034
-
29035
- // src/engine/config/merge.ts
29036
- function isPlainObject2(v) {
29037
- return typeof v === "object" && v !== null && !Array.isArray(v);
29038
- }
29039
- function mergeWith(target, source, customizer) {
29040
- for (const key of Object.keys(source)) {
29041
- const srcValue = source[key];
29042
- const objValue = target[key];
29043
- if (customizer) {
29044
- const customized = customizer(objValue, srcValue, key, target);
29045
- if (customized !== undefined) {
29046
- target[key] = customized;
29047
- continue;
29048
- }
29049
- }
29050
- if (srcValue === undefined)
29051
- continue;
29052
- if (isPlainObject2(objValue) && isPlainObject2(srcValue)) {
29053
- mergeWith(objValue, srcValue, customizer);
29054
- } else {
29055
- target[key] = srcValue;
29056
- }
29057
- }
29058
- return target;
29059
- }
29060
- function uniq(arr) {
29061
- const seen = new Set;
29062
- const out = [];
29063
- for (const x of arr) {
29064
- if (!seen.has(x)) {
29065
- seen.add(x);
29066
- out.push(x);
29067
- }
29068
- }
29069
- return out;
29070
- }
29071
- function settingsMergeCustomizer(objValue, srcValue) {
29072
- if (Array.isArray(objValue) && Array.isArray(srcValue)) {
29073
- return uniq([...objValue, ...srcValue]);
29074
- }
29075
- return;
29076
- }
29077
-
29078
28881
  // src/permissions/PermissionRule.ts
29079
28882
  var permissionBehaviorSchema, permissionRuleValueSchema;
29080
28883
  var init_PermissionRule = __esm(() => {
@@ -31706,6 +31509,285 @@ var init_hooksConfig = __esm(() => {
31706
31509
  init_settings();
31707
31510
  });
31708
31511
 
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
+
31709
31791
  // src/engine/config/managedEnv.ts
31710
31792
  function applySafeConfigEnvironmentVariables() {
31711
31793
  for (const source of TRUSTED_SETTING_SOURCES) {
@@ -33876,7 +33958,7 @@ var init_project = __esm(() => {
33876
33958
  var AGENT_TOOL_NAME = "Agent", MAX_WORKER_SPAWN_DEPTH = 2;
33877
33959
 
33878
33960
  // src/engine/tools/toolNames.ts
33879
- var FILE_READ_TOOL_NAME = "Read", WEB_SEARCH_TOOL_NAME = "WebSearch", TODO_WRITE_TOOL_NAME = "TodoWrite", GREP_TOOL_NAME = "Grep", WEB_FETCH_TOOL_NAME = "WebFetch", GLOB_TOOL_NAME = "Glob", BASH_TOOL_NAME2 = "Bash", POWERSHELL_TOOL_NAME = "PowerShell", FILE_EDIT_TOOL_NAME = "Edit", FILE_WRITE_TOOL_NAME = "Write", NOTEBOOK_EDIT_TOOL_NAME = "NotebookEdit", SKILL_TOOL_NAME = "Skill", SYNTHETIC_OUTPUT_TOOL_NAME = "StructuredOutput", TOOL_SEARCH_TOOL_NAME = "ToolSearch", ENTER_WORKTREE_TOOL_NAME = "EnterWorktree", EXIT_WORKTREE_TOOL_NAME = "ExitWorktree", TEAM_CREATE_TOOL_NAME = "TeamCreate", TEAM_DELETE_TOOL_NAME = "TeamDelete", SNIP_TOOL_NAME = "Snip", SEND_MESSAGE_TOOL_NAME = "SendMessage", TASK_STOP_TOOL_NAME = "TaskStop", TASK_OUTPUT_TOOL_NAME = "TaskOutput", ENTER_PLAN_MODE_TOOL_NAME = "EnterPlanMode", EXIT_PLAN_MODE_V2_TOOL_NAME = "ExitPlanMode", ASK_USER_QUESTION_TOOL_NAME = "AskUserQuestion", TASK_CREATE_TOOL_NAME = "TaskCreate", TASK_GET_TOOL_NAME = "TaskGet", TASK_LIST_TOOL_NAME = "TaskList", TASK_UPDATE_TOOL_NAME = "TaskUpdate", CRON_CREATE_TOOL_NAME = "CronCreate", CRON_DELETE_TOOL_NAME = "CronDelete", CRON_LIST_TOOL_NAME = "CronList", CONFIG_TOOL_NAME = "Config", WORKFLOW_TOOL_NAME = "Workflow", REPL_TOOL_NAME = "REPL", LIST_MCP_RESOURCES_TOOL_NAME = "ListMcpResourcesTool", READ_MCP_RESOURCE_TOOL_NAME = "ReadMcpResourceTool", LSP_TOOL_NAME = "LSP", SHELL_TOOL_NAMES, ASYNC_AGENT_ALLOWED_TOOLS, INTERNAL_WORKER_TOOLS, ALL_AGENT_DISALLOWED_TOOLS, CUSTOM_AGENT_DISALLOWED_TOOLS, IN_PROCESS_TEAMMATE_ALLOWED_TOOLS, COORDINATOR_MODE_ALLOWED_TOOLS;
33961
+ var FILE_READ_TOOL_NAME = "Read", WEB_SEARCH_TOOL_NAME = "WebSearch", TODO_WRITE_TOOL_NAME = "TodoWrite", GREP_TOOL_NAME = "Grep", WEB_FETCH_TOOL_NAME = "WebFetch", GLOB_TOOL_NAME = "Glob", BASH_TOOL_NAME2 = "Bash", POWERSHELL_TOOL_NAME = "PowerShell", FILE_EDIT_TOOL_NAME = "Edit", FILE_WRITE_TOOL_NAME = "Write", NOTEBOOK_EDIT_TOOL_NAME = "NotebookEdit", SKILL_TOOL_NAME = "Skill", SYNTHETIC_OUTPUT_TOOL_NAME = "StructuredOutput", TOOL_SEARCH_TOOL_NAME = "ToolSearch", ENTER_WORKTREE_TOOL_NAME = "EnterWorktree", EXIT_WORKTREE_TOOL_NAME = "ExitWorktree", TEAM_CREATE_TOOL_NAME = "TeamCreate", TEAM_DELETE_TOOL_NAME = "TeamDelete", SNIP_TOOL_NAME = "Snip", SEND_MESSAGE_TOOL_NAME = "SendMessage", TASK_STOP_TOOL_NAME = "TaskStop", TASK_OUTPUT_TOOL_NAME = "TaskOutput", ENTER_PLAN_MODE_TOOL_NAME = "EnterPlanMode", EXIT_PLAN_MODE_V2_TOOL_NAME = "ExitPlanMode", ASK_USER_QUESTION_TOOL_NAME = "AskUserQuestion", TASK_CREATE_TOOL_NAME = "TaskCreate", TASK_GET_TOOL_NAME = "TaskGet", TASK_LIST_TOOL_NAME = "TaskList", TASK_UPDATE_TOOL_NAME = "TaskUpdate", CRON_CREATE_TOOL_NAME = "CronCreate", CRON_DELETE_TOOL_NAME = "CronDelete", CRON_LIST_TOOL_NAME = "CronList", CONFIG_TOOL_NAME = "Config", WORKFLOW_TOOL_NAME = "Workflow", REPL_TOOL_NAME = "REPL", LIST_MCP_RESOURCES_TOOL_NAME = "ListMcpResourcesTool", READ_MCP_RESOURCE_TOOL_NAME = "ReadMcpResourceTool", LSP_TOOL_NAME = "LSP", PROPOSE_GOAL_TOOL_NAME = "ProposeGoal", SHELL_TOOL_NAMES, ASYNC_AGENT_ALLOWED_TOOLS, INTERNAL_WORKER_TOOLS, ALL_AGENT_DISALLOWED_TOOLS, CUSTOM_AGENT_DISALLOWED_TOOLS, IN_PROCESS_TEAMMATE_ALLOWED_TOOLS, COORDINATOR_MODE_ALLOWED_TOOLS;
33880
33962
  var init_toolNames = __esm(() => {
33881
33963
  SHELL_TOOL_NAMES = [BASH_TOOL_NAME2, POWERSHELL_TOOL_NAME];
33882
33964
  ASYNC_AGENT_ALLOWED_TOOLS = new Set([
@@ -82033,6 +82115,18 @@ async function queryAgentLoop(deps, args) {
82033
82115
  effectiveDeps = { ...deps, sessionModel: nextRef };
82034
82116
  continue;
82035
82117
  }
82118
+ if (isGoalArmed() && !deps.signal?.aborted) {
82119
+ const goalCondition = getGoalCondition();
82120
+ const errorReason = errorMessage(err);
82121
+ if (classifyGoalError(err) === "unrecoverable") {
82122
+ clearGoal();
82123
+ deps.transcript?.saveGoalState?.(null);
82124
+ deps.emit?.({ type: "goal_unrecoverable", condition: goalCondition, reason: errorReason });
82125
+ } else {
82126
+ pauseGoal(errorReason);
82127
+ deps.emit?.({ type: "goal_paused", condition: goalCondition, reason: errorReason });
82128
+ }
82129
+ }
82036
82130
  throw err;
82037
82131
  }
82038
82132
  messages = lastRound.messages;
@@ -82050,7 +82144,7 @@ async function queryAgentLoop(deps, args) {
82050
82144
  break;
82051
82145
  }
82052
82146
  if (lastRound.toolResults.length === 0) {
82053
- if (isGoalArmed()) {
82147
+ if (isGoalArmed() && !isGoalPaused()) {
82054
82148
  const condition = getGoalCondition();
82055
82149
  if (goalTurns >= maxGoalTurns) {
82056
82150
  clearGoal();
@@ -82058,13 +82152,45 @@ async function queryAgentLoop(deps, args) {
82058
82152
  terminated = true;
82059
82153
  break;
82060
82154
  }
82155
+ if (shouldDisableAllHooksIncludingManaged()) {
82156
+ clearGoal();
82157
+ deps.transcript?.saveGoalState?.(null);
82158
+ deps.emit?.({
82159
+ type: "goal_unrecoverable",
82160
+ condition,
82161
+ reason: goalHookGateNotification()
82162
+ });
82163
+ terminated = true;
82164
+ break;
82165
+ }
82166
+ if (deps.hasPendingBackgroundTasks?.()) {
82167
+ terminated = true;
82168
+ break;
82169
+ }
82061
82170
  goalTurns++;
82062
- const evalResult = await evaluateGoal({
82063
- modelProvider: deps.modelProvider,
82064
- signal: deps.signal,
82065
- messages,
82066
- condition
82067
- });
82171
+ let evalResult;
82172
+ try {
82173
+ evalResult = await evaluateGoal({
82174
+ modelProvider: deps.modelProvider,
82175
+ signal: deps.signal,
82176
+ messages,
82177
+ condition
82178
+ });
82179
+ } catch (evalErr) {
82180
+ if (deps.signal?.aborted)
82181
+ throw evalErr;
82182
+ const errorReason = errorMessage(evalErr);
82183
+ if (classifyGoalError(evalErr) === "unrecoverable") {
82184
+ clearGoal();
82185
+ deps.transcript?.saveGoalState?.(null);
82186
+ deps.emit?.({ type: "goal_unrecoverable", condition, reason: errorReason });
82187
+ } else {
82188
+ pauseGoal(errorReason);
82189
+ deps.emit?.({ type: "goal_paused", condition, reason: errorReason });
82190
+ }
82191
+ terminated = true;
82192
+ break;
82193
+ }
82068
82194
  if (evalResult.met) {
82069
82195
  clearGoal();
82070
82196
  deps.transcript?.saveGoalState?.(null);
@@ -82083,6 +82209,9 @@ async function queryAgentLoop(deps, args) {
82083
82209
  turn: turns,
82084
82210
  reason: evalResult.reason
82085
82211
  });
82212
+ } else if (isGoalPaused()) {
82213
+ terminated = true;
82214
+ break;
82086
82215
  } else {
82087
82216
  const stop = deps.hooks?.stopHooks;
82088
82217
  const preventStop = stop ? (await stop(deps.signal)).preventContinuation : false;
@@ -82115,6 +82244,7 @@ var init_loop = __esm(() => {
82115
82244
  init_modelprovider2();
82116
82245
  init_turnRecovery();
82117
82246
  init_goalState();
82247
+ init_hooksConfig();
82118
82248
  init_pipeline();
82119
82249
  init_context();
82120
82250
  init_reactiveCompactError();
@@ -82192,6 +82322,105 @@ var init_toolHooks = __esm(() => {
82192
82322
  init_hooks();
82193
82323
  });
82194
82324
 
82325
+ // src/engine/tools/proposeGoal/proposeGoalPrompt.ts
82326
+ var PROPOSE_GOAL_PROMPT = `Propose a goal condition that can be verified across multiple turns of conversation. The goal will be armed and the agent will continue working until an evaluator determines the condition has been met based solely on conversation evidence.
82327
+
82328
+ Parameters:
82329
+ - condition (string, required): A single testable end-state condition, maximum 500 characters. The condition should describe a verifiable outcome, not a process.
82330
+ - ask_user (boolean, default true): Whether to ask the user to approve the goal.
82331
+
82332
+ ask_user semantics:
82333
+ - ask_user=true (default): Present the goal to the user for single-key approval. If the user approves, the goal is armed. If the user declines, no goal is armed and no notification is sent.
82334
+ - ask_user=false: Arm the goal directly without asking. Use this ONLY when the user's own words explicitly stated the desired outcome and they want the agent to pursue it as a goal. Setting ask_user=false when the user did not explicitly request this outcome is a misuse of the tool.
82335
+
82336
+ Evaluator behavior: A separate evaluator checks whether the goal condition has been met based only on the conversation. It does not run commands, does not read files, and does not make assumptions beyond what is shown in the conversation.
82337
+
82338
+ One goal at a time: If a goal is already armed, proposing a new goal replaces the previous one (after approval if ask_user=true).
82339
+
82340
+ Use this tool when the user describes an outcome they want achieved that can be verified from the conversation, and that may require multiple turns of work.`;
82341
+
82342
+ // src/engine/tools/proposeGoal/ProposeGoal.ts
82343
+ var PROPOSE_GOAL_INPUT_SCHEMA, ProposeGoalTool;
82344
+ var init_ProposeGoal = __esm(() => {
82345
+ init_json();
82346
+ init_toolNames();
82347
+ init_goalState();
82348
+ PROPOSE_GOAL_INPUT_SCHEMA = {
82349
+ type: "object",
82350
+ properties: {
82351
+ condition: {
82352
+ type: "string",
82353
+ description: `A single testable end-state condition (maximum ${MAX_GOAL_CONDITION_CHARS} characters). Describes a verifiable outcome, not a process.`
82354
+ },
82355
+ ask_user: {
82356
+ type: "boolean",
82357
+ description: "Whether to ask the user to approve the goal (default true). Set to false ONLY when the user explicitly requested this outcome."
82358
+ }
82359
+ },
82360
+ required: ["condition"],
82361
+ additionalProperties: false
82362
+ };
82363
+ ProposeGoalTool = {
82364
+ name: PROPOSE_GOAL_TOOL_NAME,
82365
+ inputSchema: PROPOSE_GOAL_INPUT_SCHEMA,
82366
+ inputJSONSchema: PROPOSE_GOAL_INPUT_SCHEMA,
82367
+ searchHint: "propose a verifiable goal condition to pursue across multiple turns",
82368
+ maxResultSizeChars: 2000,
82369
+ isEnabled: () => true,
82370
+ isReadOnly: () => false,
82371
+ isConcurrencySafe: () => false,
82372
+ isDestructive: () => false,
82373
+ userFacingName: () => "ProposeGoal",
82374
+ toAutoClassifierInput: () => "",
82375
+ async checkPermissions(input) {
82376
+ const { condition, ask_user = true } = input;
82377
+ if (ask_user) {
82378
+ return {
82379
+ behavior: "ask",
82380
+ message: `Approve goal: "${condition}"?`,
82381
+ updatedInput: input
82382
+ };
82383
+ }
82384
+ return {
82385
+ behavior: "allow",
82386
+ updatedInput: input
82387
+ };
82388
+ },
82389
+ async description() {
82390
+ return PROPOSE_GOAL_PROMPT;
82391
+ },
82392
+ mapToolResultToToolResultBlockParam(data, toolUseID) {
82393
+ return {
82394
+ tool_use_id: toolUseID,
82395
+ type: "tool_result",
82396
+ content: jsonStringify2(data)
82397
+ };
82398
+ },
82399
+ async call(args, _context) {
82400
+ const { condition } = args ?? { condition: "" };
82401
+ const result = armGoal(condition);
82402
+ if (result.ok === true) {
82403
+ return {
82404
+ data: {
82405
+ armed: true,
82406
+ condition: condition.trim()
82407
+ }
82408
+ };
82409
+ }
82410
+ return {
82411
+ data: {
82412
+ armed: false,
82413
+ condition: condition ?? "",
82414
+ reason: result.reason
82415
+ }
82416
+ };
82417
+ },
82418
+ renderToolUseMessage() {
82419
+ return null;
82420
+ }
82421
+ };
82422
+ });
82423
+
82195
82424
  // src/engine/loopDeps.ts
82196
82425
  function setAgentLoopDepsTeammatePoolSync(fn) {
82197
82426
  teammatePoolSync = fn;
@@ -82208,7 +82437,8 @@ async function createAgentLoopDeps(config = {}) {
82208
82437
  ...config.toolRegistryDeps?.baseTools ?? [],
82209
82438
  SnipTool,
82210
82439
  TeamCreateTool,
82211
- TeamDeleteTool
82440
+ TeamDeleteTool,
82441
+ ProposeGoalTool
82212
82442
  ],
82213
82443
  mcpTools: [...config.toolRegistryDeps?.mcpTools ?? [], ...mcpTools],
82214
82444
  ascendTools: getDomainMount()?.tools
@@ -82293,6 +82523,7 @@ var init_loopDeps = __esm(() => {
82293
82523
  init_snipTool();
82294
82524
  init_teamCreateTool();
82295
82525
  init_teamDeleteTool();
82526
+ init_ProposeGoal();
82296
82527
  init_context();
82297
82528
  });
82298
82529
 
@@ -82343,6 +82574,62 @@ var init_hooks2 = __esm(() => {
82343
82574
  init_hooks();
82344
82575
  });
82345
82576
 
82577
+ // src/engine/goal/goalCheckIn.ts
82578
+ function getGoalCheckInMinutes() {
82579
+ const raw = process.env.ATLAS_GOAL_CHECKIN_MINUTES;
82580
+ if (raw === undefined || raw === "")
82581
+ return DEFAULT_GOAL_CHECKIN_MINUTES;
82582
+ const parsed = Number(raw);
82583
+ if (!Number.isFinite(parsed) || parsed < 0)
82584
+ return DEFAULT_GOAL_CHECKIN_MINUTES;
82585
+ return parsed;
82586
+ }
82587
+ function getCheckInDelayMs(checkInIndex, baseMinutes) {
82588
+ const multiplier = GOAL_CHECKIN_BACKOFF_MULTIPLIERS[checkInIndex];
82589
+ if (multiplier === undefined)
82590
+ return Infinity;
82591
+ return baseMinutes * MS_PER_MINUTE * multiplier;
82592
+ }
82593
+ function resetCheckInState() {
82594
+ checkInState = { checkInCount: 0 };
82595
+ }
82596
+ function recordCheckIn() {
82597
+ checkInState = { checkInCount: checkInState.checkInCount + 1 };
82598
+ }
82599
+ function refreshOnUserMessage() {
82600
+ checkInState = { checkInCount: 0 };
82601
+ }
82602
+ function getRemainingCheckIns() {
82603
+ return Math.max(0, MAX_GOAL_CHECKINS - checkInState.checkInCount);
82604
+ }
82605
+ function canCheckIn() {
82606
+ if (getGoalCheckInMinutes() === 0)
82607
+ return false;
82608
+ return checkInState.checkInCount < MAX_GOAL_CHECKINS;
82609
+ }
82610
+ function getCheckInStateForTesting() {
82611
+ return { ...checkInState };
82612
+ }
82613
+ function goalCheckInPrompt(condition) {
82614
+ return `This is an automated goal check-in. A goal is still active and the session appears idle or blocked by background work.
82615
+
82616
+ Goal condition: ${condition}
82617
+
82618
+ Review the progress toward this goal based on the conversation so far:
82619
+ - If work toward the goal is unfinished, continue it.
82620
+ - If background tasks are still running, wait for them and then reassess.
82621
+ - If the goal appears unachievable, explain why and what was attempted.
82622
+
82623
+ Do not start new unrelated work. Focus on the goal condition above. Assess whether meaningful progress has been made since the last check-in.`;
82624
+ }
82625
+ var DEFAULT_GOAL_CHECKIN_MINUTES = 30, GOAL_CHECKIN_BACKOFF_MULTIPLIERS, MAX_GOAL_CHECKINS, CHECKIN_REFRESH_AMOUNT, MS_PER_MINUTE = 60000, checkInState;
82626
+ var init_goalCheckIn = __esm(() => {
82627
+ GOAL_CHECKIN_BACKOFF_MULTIPLIERS = [1, 2, 4];
82628
+ MAX_GOAL_CHECKINS = GOAL_CHECKIN_BACKOFF_MULTIPLIERS.length;
82629
+ CHECKIN_REFRESH_AMOUNT = MAX_GOAL_CHECKINS;
82630
+ checkInState = { checkInCount: 0 };
82631
+ });
82632
+
82346
82633
  // src/engine/index.ts
82347
82634
  var init_engine = __esm(() => {
82348
82635
  init_query2();
@@ -82379,6 +82666,7 @@ var init_engine = __esm(() => {
82379
82666
  init_tasks2();
82380
82667
  init_messaging();
82381
82668
  init_goalState();
82669
+ init_goalCheckIn();
82382
82670
  });
82383
82671
 
82384
82672
  // src/cli/entryInit.ts
@@ -179712,6 +180000,7 @@ __export(exports_engineCompat, {
179712
180000
  BASH_TOOL_NAME: () => BASH_TOOL_NAME2,
179713
180001
  BING_DEFAULT_ENDPOINT: () => BING_DEFAULT_ENDPOINT,
179714
180002
  BashTool: () => BashTool,
180003
+ CHECKIN_REFRESH_AMOUNT: () => CHECKIN_REFRESH_AMOUNT,
179715
180004
  COMMAND_NAME_TAG: () => COMMAND_NAME_TAG,
179716
180005
  COMPACT_MAX_OUTPUT_TOKENS: () => COMPACT_MAX_OUTPUT_TOKENS,
179717
180006
  CONFIG_TOOL_NAME: () => CONFIG_TOOL_NAME,
@@ -179726,6 +180015,7 @@ __export(exports_engineCompat, {
179726
180015
  CronListTool: () => CronListTool,
179727
180016
  DEFAULT_AGENT_LOOP_MAX_TURNS: () => DEFAULT_AGENT_LOOP_MAX_TURNS,
179728
180017
  DEFAULT_CRON_JITTER_CONFIG: () => DEFAULT_CRON_JITTER_CONFIG,
180018
+ DEFAULT_GOAL_CHECKIN_MINUTES: () => DEFAULT_GOAL_CHECKIN_MINUTES,
179729
180019
  DEFAULT_MAX_GOAL_TURNS: () => DEFAULT_MAX_GOAL_TURNS,
179730
180020
  DEFAULT_SESSION_MEMORY_CONFIG: () => DEFAULT_SESSION_MEMORY_CONFIG,
179731
180021
  DEFAULT_TASKS_MODE_TASK_LIST_ID: () => DEFAULT_TASKS_MODE_TASK_LIST_ID,
@@ -179754,6 +180044,7 @@ __export(exports_engineCompat, {
179754
180044
  GENERAL_PURPOSE_AGENT: () => GENERAL_PURPOSE_AGENT,
179755
180045
  GIT_NO_PROMPT_ENV: () => GIT_NO_PROMPT_ENV,
179756
180046
  GLOB_TOOL_NAME: () => GLOB_TOOL_NAME,
180047
+ GOAL_CHECKIN_BACKOFF_MULTIPLIERS: () => GOAL_CHECKIN_BACKOFF_MULTIPLIERS,
179757
180048
  GREP_TOOL_NAME: () => GREP_TOOL_NAME,
179758
180049
  GlobTool: () => GlobTool,
179759
180050
  GrepTool: () => GrepTool,
@@ -179773,6 +180064,7 @@ __export(exports_engineCompat, {
179773
180064
  LocalShellTask: () => LocalShellTask,
179774
180065
  MANUAL_COMPACT_BUFFER_TOKENS: () => MANUAL_COMPACT_BUFFER_TOKENS,
179775
180066
  MAX_CONSECUTIVE_AUTOCOMPACT_FAILURES: () => MAX_CONSECUTIVE_AUTOCOMPACT_FAILURES,
180067
+ MAX_GOAL_CHECKINS: () => MAX_GOAL_CHECKINS,
179776
180068
  MAX_GOAL_CONDITION_CHARS: () => MAX_GOAL_CONDITION_CHARS,
179777
180069
  MAX_PTL_RETRIES: () => MAX_PTL_RETRIES,
179778
180070
  MAX_TRANSCRIPT_READ_BYTES: () => MAX_TRANSCRIPT_READ_BYTES,
@@ -179870,9 +180162,11 @@ __export(exports_engineCompat, {
179870
180162
  builtInCommandNames: () => builtInCommandNames2,
179871
180163
  cacheSessionTitle: () => cacheSessionTitle,
179872
180164
  calculateTokenWarningState: () => calculateTokenWarningState,
180165
+ canCheckIn: () => canCheckIn,
179873
180166
  captureHooksConfigSnapshot: () => captureHooksConfigSnapshot,
179874
180167
  check: () => check,
179875
180168
  claimTask: () => claimTask,
180169
+ classifyGoalError: () => classifyGoalError,
179876
180170
  classifyToolError: () => classifyToolError,
179877
180171
  cleanMessagesForLogging: () => cleanMessagesForLogging,
179878
180172
  cleanupStaleAgentWorktrees: () => cleanupStaleAgentWorktrees,
@@ -180000,6 +180294,8 @@ __export(exports_engineCompat, {
180000
180294
  getCachedMCModulePort: () => getCachedMCModulePort,
180001
180295
  getCachedParsedFile: () => getCachedParsedFile,
180002
180296
  getCachedSettingsForSource: () => getCachedSettingsForSource,
180297
+ getCheckInDelayMs: () => getCheckInDelayMs,
180298
+ getCheckInStateForTesting: () => getCheckInStateForTesting,
180003
180299
  getCommandQueue: () => getCommandQueue,
180004
180300
  getCommandQueueLength: () => getCommandQueueLength,
180005
180301
  getCommandQueueSnapshot: () => getCommandQueueSnapshot,
@@ -180024,7 +180320,9 @@ __export(exports_engineCompat, {
180024
180320
  getEntrypoint: () => getEntrypoint,
180025
180321
  getFirstMeaningfulUserMessageTextContent: () => getFirstMeaningfulUserMessageTextContent,
180026
180322
  getGitBranch: () => getGitBranch,
180323
+ getGoalCheckInMinutes: () => getGoalCheckInMinutes,
180027
180324
  getGoalCondition: () => getGoalCondition,
180325
+ getGoalPausedReason: () => getGoalPausedReason,
180028
180326
  getGoalStateForPersistence: () => getGoalStateForPersistence,
180029
180327
  getHooksConfigFromSnapshot: () => getHooksConfigFromSnapshot,
180030
180328
  getInboxPath: () => getInboxPath,
@@ -180048,6 +180346,7 @@ __export(exports_engineCompat, {
180048
180346
  getPrompt: () => getPrompt,
180049
180347
  getPromptTooLongTokenGap: () => getPromptTooLongTokenGap,
180050
180348
  getRelativeSettingsFilePathForSource: () => getRelativeSettingsFilePathForSource,
180349
+ getRemainingCheckIns: () => getRemainingCheckIns,
180051
180350
  getRunningTasks: () => getRunningTasks,
180052
180351
  getSchedulerEnv: () => getSchedulerEnv,
180053
180352
  getSessionContextPort: () => getSessionContextPort,
@@ -180086,9 +180385,13 @@ __export(exports_engineCompat, {
180086
180385
  getUserType: () => getUserType,
180087
180386
  getVersion: () => getVersion2,
180088
180387
  gitExe: () => gitExe,
180388
+ goalCheckInPrompt: () => goalCheckInPrompt,
180089
180389
  goalClearedNotification: () => goalClearedNotification,
180090
180390
  goalContinuationReminder: () => goalContinuationReminder,
180391
+ goalHookGateNotification: () => goalHookGateNotification,
180091
180392
  goalMetNotification: () => goalMetNotification,
180393
+ goalPausedNotification: () => goalPausedNotification,
180394
+ goalUnrecoverableNotification: () => goalUnrecoverableNotification,
180092
180395
  groupMessagesByApiRound: () => groupMessagesByApiRound,
180093
180396
  hasActiveInProcessTeammates: () => hasActiveInProcessTeammates,
180094
180397
  hasAutoModeOptIn: () => hasAutoModeOptIn,
@@ -180117,6 +180420,7 @@ __export(exports_engineCompat, {
180117
180420
  isEphemeralToolProgress: () => isEphemeralToolProgress,
180118
180421
  isForkSubagentEnabled: () => isForkSubagentEnabled,
180119
180422
  isGoalArmed: () => isGoalArmed,
180423
+ isGoalPaused: () => isGoalPaused,
180120
180424
  isHumanTurn: () => isHumanTurn,
180121
180425
  isIdleNotification: () => isIdleNotification,
180122
180426
  isInForkChild: () => isInForkChild,
@@ -180231,6 +180535,7 @@ __export(exports_engineCompat, {
180231
180535
  parseWorktreeListPorcelain: () => parseWorktreeListPorcelain,
180232
180536
  partialCompactConversation: () => partialCompactConversation,
180233
180537
  partitionToolCalls: () => partitionToolCalls,
180538
+ pauseGoal: () => pauseGoal,
180234
180539
  peek: () => peek,
180235
180540
  persistPermissionUpdate: () => persistPermissionUpdate,
180236
180541
  persistPermissionUpdates: () => persistPermissionUpdates,
@@ -180255,10 +180560,12 @@ __export(exports_engineCompat, {
180255
180560
  readWorktreeHeadSha: () => readWorktreeHeadSha,
180256
180561
  recheckCommandQueue: () => recheckCommandQueue,
180257
180562
  recheckPendingNotifications: () => recheckPendingNotifications,
180563
+ recordCheckIn: () => recordCheckIn,
180258
180564
  recordContentReplacement: () => recordContentReplacement,
180259
180565
  recordExtractionTokenCount: () => recordExtractionTokenCount,
180260
180566
  recordSidechainTranscript: () => recordSidechainTranscript,
180261
180567
  recordTranscript: () => recordTranscript,
180568
+ refreshOnUserMessage: () => refreshOnUserMessage,
180262
180569
  registerAgentForeground: () => registerAgentForeground,
180263
180570
  registerAsyncAgent: () => registerAsyncAgent,
180264
180571
  registerCleanup: () => registerCleanup2,
@@ -180276,6 +180583,7 @@ __export(exports_engineCompat, {
180276
180583
  reportAutoCompactCircuitFailures: () => reportAutoCompactCircuitFailures,
180277
180584
  resetAutoCompactCircuitForTesting: () => resetAutoCompactCircuitForTesting,
180278
180585
  resetBuiltinCommandNamesSourceForTesting: () => resetBuiltinCommandNamesSourceForTesting,
180586
+ resetCheckInState: () => resetCheckInState,
180279
180587
  resetCommandQueue: () => resetCommandQueue,
180280
180588
  resetDomainMountForTests: () => resetDomainMountForTests,
180281
180589
  resetGoalStateForTesting: () => resetGoalStateForTesting,
@@ -180308,6 +180616,7 @@ __export(exports_engineCompat, {
180308
180616
  restoreGoalState: () => restoreGoalState,
180309
180617
  restoreSessionMetadata: () => restoreSessionMetadata,
180310
180618
  restoreWorktreeSession: () => restoreWorktreeSession,
180619
+ resumeGoal: () => resumeGoal,
180311
180620
  roughTokenCountEstimation: () => roughTokenCountEstimation2,
180312
180621
  roughTokenCountEstimationForContent: () => roughTokenCountEstimationForContent,
180313
180622
  roughTokenCountEstimationForMessages: () => roughTokenCountEstimationForMessages,
@@ -366024,6 +366333,25 @@ var init_GlimmerMessage = __esm(() => {
366024
366333
  };
366025
366334
  });
366026
366335
 
366336
+ // src/tui/components/Spinner/spinnerGates.ts
366337
+ function getSpinnerDisplayGates(input) {
366338
+ const { verbose, hasRunningTeammates, effectiveElapsedMs } = input;
366339
+ const forceShow = verbose || hasRunningTeammates;
366340
+ const wantsTimer = forceShow || effectiveElapsedMs > SHOW_TIMER_AFTER_MS;
366341
+ return {
366342
+ wantsTimer,
366343
+ wantsTokens: forceShow || effectiveElapsedMs > SHOW_TOKENS_AFTER_MS,
366344
+ wantsStatusIndicator: wantsTimer
366345
+ };
366346
+ }
366347
+ function computeStallState(input) {
366348
+ const { timeSinceLastToken, currentResponseLength, hasActiveTools } = input;
366349
+ const isStalled = timeSinceLastToken > STALL_AFTER_MS && !hasActiveTools && currentResponseLength > 0;
366350
+ const stalledIntensity = isStalled ? Math.min((timeSinceLastToken - STALL_AFTER_MS) / STALL_FADE_MS, 1) : 0;
366351
+ return { isStalled, stalledIntensity };
366352
+ }
366353
+ var SHOW_TIMER_AFTER_MS = 1000, SHOW_TOKENS_AFTER_MS = 5000, STALL_AFTER_MS = 3000, STALL_FADE_MS = 2000;
366354
+
366027
366355
  // src/tui/components/Spinner/useStalledAnimation.ts
366028
366356
  function useStalledAnimation(time, currentResponseLength, hasActiveTools = false, reducedMotion = false) {
366029
366357
  const lastTokenTime = import_react103.useRef(time);
@@ -366046,8 +366374,11 @@ function useStalledAnimation(time, currentResponseLength, hasActiveTools = false
366046
366374
  } else {
366047
366375
  timeSinceLastToken = time - mountTime.current;
366048
366376
  }
366049
- const isStalled = timeSinceLastToken > 3000 && !hasActiveTools;
366050
- const intensity = isStalled ? Math.min((timeSinceLastToken - 3000) / 2000, 1) : 0;
366377
+ const { isStalled, stalledIntensity: intensity } = computeStallState({
366378
+ timeSinceLastToken,
366379
+ currentResponseLength,
366380
+ hasActiveTools
366381
+ });
366051
366382
  if (!reducedMotion && (intensity > 0 || stalledIntensityRef.current > 0)) {
366052
366383
  const dt = time - lastSmoothTime.current;
366053
366384
  if (dt >= 50) {
@@ -366076,17 +366407,6 @@ var init_useStalledAnimation = __esm(() => {
366076
366407
  import_react103 = __toESM(require_react(), 1);
366077
366408
  });
366078
366409
 
366079
- // src/tui/components/Spinner/spinnerGates.ts
366080
- function getSpinnerDisplayGates(input) {
366081
- const { verbose, hasRunningTeammates, effectiveElapsedMs } = input;
366082
- const forceShow = verbose || hasRunningTeammates;
366083
- return {
366084
- wantsTimer: forceShow || effectiveElapsedMs > SHOW_TIMER_AFTER_MS,
366085
- wantsTokens: forceShow || effectiveElapsedMs > SHOW_TOKENS_AFTER_MS
366086
- };
366087
- }
366088
- var SHOW_TIMER_AFTER_MS = 1000, SHOW_TOKENS_AFTER_MS = 5000;
366089
-
366090
366410
  // src/tui/components/Spinner/SpinnerAnimationRow.tsx
366091
366411
  function SpinnerAnimationRow({
366092
366412
  mode,
@@ -366125,7 +366445,8 @@ function SpinnerAnimationRow({
366125
366445
  } = useStalledAnimation(time, currentResponseLength, hasActiveTools || leaderIsIdle, reducedMotion);
366126
366446
  const frame = reducedMotion ? 0 : Math.floor(time / 120);
366127
366447
  const glimmerSpeed = mode === "requesting" ? 50 : 200;
366128
- const glimmerMessageWidth = import_react104.useMemo(() => stringWidth2(message), [message]);
366448
+ const displayMessage = mode === "requesting" ? message + "…" : message;
366449
+ const glimmerMessageWidth = import_react104.useMemo(() => stringWidth2(displayMessage), [displayMessage]);
366129
366450
  const cycleLength = glimmerMessageWidth + 20;
366130
366451
  const cyclePosition = Math.floor(time / glimmerSpeed);
366131
366452
  const glimmerIndex = reducedMotion ? -100 : isStalled ? -100 : mode === "requesting" ? cyclePosition % cycleLength - 10 : glimmerMessageWidth + 10 - cyclePosition % cycleLength;
@@ -366161,7 +366482,7 @@ function SpinnerAnimationRow({
366161
366482
  const messageWidth = glimmerMessageWidth + 2;
366162
366483
  const sep = SEP_WIDTH;
366163
366484
  const wantsThinking = thinkingStatus !== null;
366164
- const { wantsTimer, wantsTokens } = getSpinnerDisplayGates({
366485
+ const { wantsTimer, wantsTokens, wantsStatusIndicator } = getSpinnerDisplayGates({
366165
366486
  verbose,
366166
366487
  hasRunningTeammates,
366167
366488
  effectiveElapsedMs
@@ -366179,7 +366500,8 @@ function SpinnerAnimationRow({
366179
366500
  const showTimer = wantsTimer && availableSpace > usedAfterThinking + timerWidth;
366180
366501
  const usedAfterTimer = usedAfterThinking + (showTimer ? timerWidth + sep : 0);
366181
366502
  const showTokens = wantsTokens && totalTokens > 0 && availableSpace > usedAfterTimer + tokensWidth;
366182
- const thinkingOnly = showThinking && thinkingStatus === "thinking" && !spinnerSuffix && !showTimer && !showTokens && true;
366503
+ const showStatusIndicator = !showTokens && wantsStatusIndicator && mode === "requesting" && !hasRunningTeammates && availableSpace > usedAfterTimer + 2;
366504
+ const thinkingOnly = showThinking && thinkingStatus === "thinking" && !spinnerSuffix && !showTimer && !showTokens && !showStatusIndicator && true;
366183
366505
  const thinkingElapsedSec = (time - THINKING_DELAY_MS) / 1000;
366184
366506
  const thinkingOpacity = time < THINKING_DELAY_MS ? 0 : (Math.sin(thinkingElapsedSec * Math.PI * 2 / THINKING_GLOW_PERIOD_S) + 1) / 2;
366185
366507
  const thinkingShimmerColor = toRGBColor(interpolateColor(THINKING_INACTIVE, THINKING_INACTIVE_SHIMMER, thinkingOpacity));
@@ -366203,7 +366525,9 @@ function SpinnerAnimationRow({
366203
366525
  ]
366204
366526
  }, undefined, true, undefined, this)
366205
366527
  ]
366206
- }, "tokens", true, undefined, this)] : [], ...showThinking && thinkingText ? [thinkingStatus === "thinking" && !reducedMotion ? /* @__PURE__ */ jsx_dev_runtime184.jsxDEV(ThemedText, {
366528
+ }, "tokens", true, undefined, this)] : [], ...showStatusIndicator ? [/* @__PURE__ */ jsx_dev_runtime184.jsxDEV(SpinnerModeGlyph, {
366529
+ mode
366530
+ }, "statusGlyph", false, undefined, this)] : [], ...showThinking && thinkingText ? [thinkingStatus === "thinking" && !reducedMotion ? /* @__PURE__ */ jsx_dev_runtime184.jsxDEV(ThemedText, {
366207
366531
  color: thinkingShimmerColor,
366208
366532
  children: thinkingOnly ? `(${thinkingText})` : thinkingText
366209
366533
  }, "thinking", false, undefined, this) : /* @__PURE__ */ jsx_dev_runtime184.jsxDEV(ThemedText, {
@@ -366257,7 +366581,7 @@ function SpinnerAnimationRow({
366257
366581
  time
366258
366582
  }, undefined, false, undefined, this),
366259
366583
  /* @__PURE__ */ jsx_dev_runtime184.jsxDEV(GlimmerMessage, {
366260
- message,
366584
+ message: displayMessage,
366261
366585
  mode,
366262
366586
  messageColor,
366263
366587
  glimmerIndex,
@@ -411296,7 +411620,7 @@ var init_output_style2 = __esm(() => {
411296
411620
  });
411297
411621
 
411298
411622
  // src/tui/components/GoalOverlay.tsx
411299
- function GoalOverlay({
411623
+ function GoalOverlayInner({
411300
411624
  armed,
411301
411625
  condition,
411302
411626
  turns,
@@ -411335,11 +411659,13 @@ function GoalOverlay({
411335
411659
  ]
411336
411660
  }, undefined, true, undefined, this);
411337
411661
  }
411338
- var jsx_dev_runtime296;
411662
+ var React87, jsx_dev_runtime296, GoalOverlay;
411339
411663
  var init_GoalOverlay = __esm(() => {
411340
411664
  init_ink2();
411341
411665
  init_format2();
411666
+ React87 = __toESM(require_react(), 1);
411342
411667
  jsx_dev_runtime296 = __toESM(require_jsx_dev_runtime(), 1);
411668
+ GoalOverlay = React87.memo(GoalOverlayInner);
411343
411669
  });
411344
411670
 
411345
411671
  // src/tui/commands/goal/goal.tsx
@@ -414009,7 +414335,7 @@ function SetModelAndClose({
414009
414335
  }) {
414010
414336
  const setAppState = useSetAppState();
414011
414337
  const model = args === "default" ? null : args;
414012
- React90.useEffect(() => {
414338
+ React91.useEffect(() => {
414013
414339
  async function handleModelChange() {
414014
414340
  if (model && !isModelAllowed(model)) {
414015
414341
  onDone(`Model '${model}' is not available. Your organization restricts model selection.`, {
@@ -414096,7 +414422,7 @@ function renderModelLabel(model) {
414096
414422
  const rendered = renderDefaultModelSetting(model ?? getDefaultMainLoopModelSetting());
414097
414423
  return model === null ? `${rendered} (default)` : rendered;
414098
414424
  }
414099
- var import_compiler_runtime237, React90, jsx_dev_runtime309, call57 = async (onDone, _context, args) => {
414425
+ var import_compiler_runtime237, React91, jsx_dev_runtime309, call57 = async (onDone, _context, args) => {
414100
414426
  args = args?.trim() || "";
414101
414427
  if (COMMON_INFO_ARGS.includes(args)) {
414102
414428
  return /* @__PURE__ */ jsx_dev_runtime309.jsxDEV(ShowModelAndClose, {
@@ -414131,7 +414457,7 @@ var init_model2 = __esm(() => {
414131
414457
  init_validateModel();
414132
414458
  init_modelSwitchHooks();
414133
414459
  import_compiler_runtime237 = __toESM(require_compiler_runtime(), 1);
414134
- React90 = __toESM(require_react(), 1);
414460
+ React91 = __toESM(require_react(), 1);
414135
414461
  jsx_dev_runtime309 = __toESM(require_jsx_dev_runtime(), 1);
414136
414462
  });
414137
414463
 
@@ -414239,8 +414565,8 @@ function ToggleTagAndClose(t0) {
414239
414565
  tagName,
414240
414566
  onDone
414241
414567
  } = t0;
414242
- const [showConfirm, setShowConfirm] = React91.useState(false);
414243
- const [sessionId, setSessionId] = React91.useState(null);
414568
+ const [showConfirm, setShowConfirm] = React92.useState(false);
414569
+ const [sessionId, setSessionId] = React92.useState(null);
414244
414570
  let t1;
414245
414571
  if ($[0] !== tagName) {
414246
414572
  t1 = recursivelySanitizeUnicode2(tagName).trim();
@@ -414291,7 +414617,7 @@ function ToggleTagAndClose(t0) {
414291
414617
  t2 = $[4];
414292
414618
  t3 = $[5];
414293
414619
  }
414294
- React91.useEffect(t2, t3);
414620
+ React92.useEffect(t2, t3);
414295
414621
  if (showConfirm && sessionId) {
414296
414622
  let t4;
414297
414623
  if ($[6] !== normalizedTag || $[7] !== onDone || $[8] !== sessionId) {
@@ -414371,7 +414697,7 @@ Examples:
414371
414697
  t1 = $[1];
414372
414698
  t2 = $[2];
414373
414699
  }
414374
- React91.useEffect(t1, t2);
414700
+ React92.useEffect(t1, t2);
414375
414701
  return null;
414376
414702
  }
414377
414703
  async function call58(onDone, _context, args) {
@@ -414391,7 +414717,7 @@ async function call58(onDone, _context, args) {
414391
414717
  onDone
414392
414718
  }, undefined, false, undefined, this);
414393
414719
  }
414394
- var import_compiler_runtime238, React91, jsx_dev_runtime310;
414720
+ var import_compiler_runtime238, React92, jsx_dev_runtime310;
414395
414721
  var init_tag = __esm(() => {
414396
414722
  init_source2();
414397
414723
  init_bootstrap();
@@ -414401,7 +414727,7 @@ var init_tag = __esm(() => {
414401
414727
  init_ink2();
414402
414728
  init_sessionStorage();
414403
414729
  import_compiler_runtime238 = __toESM(require_compiler_runtime(), 1);
414404
- React91 = __toESM(require_react(), 1);
414730
+ React92 = __toESM(require_react(), 1);
414405
414731
  jsx_dev_runtime310 = __toESM(require_jsx_dev_runtime(), 1);
414406
414732
  });
414407
414733
 
@@ -414592,7 +414918,7 @@ function ApplyEffortAndClose(t0) {
414592
414918
  t1 = $[4];
414593
414919
  t2 = $[5];
414594
414920
  }
414595
- React92.useEffect(t1, t2);
414921
+ React93.useEffect(t1, t2);
414596
414922
  return null;
414597
414923
  }
414598
414924
  async function call59(onDone, _context, args) {
@@ -414620,14 +414946,14 @@ Effort levels:
414620
414946
  onDone
414621
414947
  }, undefined, false, undefined, this);
414622
414948
  }
414623
- var import_compiler_runtime239, React92, jsx_dev_runtime311, COMMON_HELP_ARGS2;
414949
+ var import_compiler_runtime239, React93, jsx_dev_runtime311, COMMON_HELP_ARGS2;
414624
414950
  var init_effort3 = __esm(() => {
414625
414951
  init_useMainLoopModel();
414626
414952
  init_AppState();
414627
414953
  init_effort2();
414628
414954
  init_settings3();
414629
414955
  import_compiler_runtime239 = __toESM(require_compiler_runtime(), 1);
414630
- React92 = __toESM(require_react(), 1);
414956
+ React93 = __toESM(require_react(), 1);
414631
414957
  jsx_dev_runtime311 = __toESM(require_jsx_dev_runtime(), 1);
414632
414958
  COMMON_HELP_ARGS2 = ["help", "-h", "--help"];
414633
414959
  });
@@ -449960,7 +450286,7 @@ function AutoUpdater({
449960
450286
  }, []);
449961
450287
  const isUpdatingRef = import_react204.useRef(isUpdating);
449962
450288
  isUpdatingRef.current = isUpdating;
449963
- const checkForUpdates = React109.useCallback(async () => {
450289
+ const checkForUpdates = React110.useCallback(async () => {
449964
450290
  if (isUpdatingRef.current) {
449965
450291
  return;
449966
450292
  }
@@ -450091,7 +450417,7 @@ function AutoUpdater({
450091
450417
  ]
450092
450418
  }, undefined, true, undefined, this);
450093
450419
  }
450094
- var React109, import_react204, jsx_dev_runtime358;
450420
+ var React110, import_react204, jsx_dev_runtime358;
450095
450421
  var init_AutoUpdater = __esm(() => {
450096
450422
  init_dist3();
450097
450423
  init_useUpdateNotification();
@@ -450103,7 +450429,7 @@ var init_AutoUpdater = __esm(() => {
450103
450429
  init_localInstaller();
450104
450430
  init_nativeInstaller();
450105
450431
  init_settings3();
450106
- React109 = __toESM(require_react(), 1);
450432
+ React110 = __toESM(require_react(), 1);
450107
450433
  import_react204 = __toESM(require_react(), 1);
450108
450434
  jsx_dev_runtime358 = __toESM(require_jsx_dev_runtime(), 1);
450109
450435
  });
@@ -450147,7 +450473,7 @@ function NativeAutoUpdater({
450147
450473
  const channel = getInitialSettings2()?.autoUpdatesChannel ?? "latest";
450148
450474
  const isUpdatingRef = import_react205.useRef(isUpdating);
450149
450475
  isUpdatingRef.current = isUpdating;
450150
- const checkForUpdates = React110.useCallback(async () => {
450476
+ const checkForUpdates = React111.useCallback(async () => {
450151
450477
  if (isUpdatingRef.current) {
450152
450478
  return;
450153
450479
  }
@@ -450243,7 +450569,7 @@ function NativeAutoUpdater({
450243
450569
  ]
450244
450570
  }, undefined, true, undefined, this);
450245
450571
  }
450246
- var React110, import_react205, jsx_dev_runtime359;
450572
+ var React111, import_react205, jsx_dev_runtime359;
450247
450573
  var init_NativeAutoUpdater = __esm(() => {
450248
450574
  init_debug();
450249
450575
  init_log5();
@@ -450254,7 +450580,7 @@ var init_NativeAutoUpdater = __esm(() => {
450254
450580
  init_config6();
450255
450581
  init_nativeInstaller();
450256
450582
  init_settings3();
450257
- React110 = __toESM(require_react(), 1);
450583
+ React111 = __toESM(require_react(), 1);
450258
450584
  import_react205 = __toESM(require_react(), 1);
450259
450585
  jsx_dev_runtime359 = __toESM(require_jsx_dev_runtime(), 1);
450260
450586
  });
@@ -450310,7 +450636,7 @@ function PackageManagerAutoUpdater(t0) {
450310
450636
  t2 = $[1];
450311
450637
  t3 = $[2];
450312
450638
  }
450313
- React111.useEffect(t2, t3);
450639
+ React112.useEffect(t2, t3);
450314
450640
  useInterval(checkForUpdates, 1800000);
450315
450641
  if (!updateAvailable) {
450316
450642
  return null;
@@ -450365,7 +450691,7 @@ function PackageManagerAutoUpdater(t0) {
450365
450691
  }
450366
450692
  return t6;
450367
450693
  }
450368
- var import_compiler_runtime278, React111, import_react206, jsx_dev_runtime360;
450694
+ var import_compiler_runtime278, React112, import_react206, jsx_dev_runtime360;
450369
450695
  var init_PackageManagerAutoUpdater = __esm(() => {
450370
450696
  init_dist3();
450371
450697
  init_ink2();
@@ -450375,7 +450701,7 @@ var init_PackageManagerAutoUpdater = __esm(() => {
450375
450701
  init_packageManagers();
450376
450702
  init_settings3();
450377
450703
  import_compiler_runtime278 = __toESM(require_compiler_runtime(), 1);
450378
- React111 = __toESM(require_react(), 1);
450704
+ React112 = __toESM(require_react(), 1);
450379
450705
  import_react206 = __toESM(require_react(), 1);
450380
450706
  jsx_dev_runtime360 = __toESM(require_jsx_dev_runtime(), 1);
450381
450707
  });
@@ -450391,8 +450717,8 @@ function AutoUpdaterWrapper(t0) {
450391
450717
  showSuccessMessage,
450392
450718
  verbose
450393
450719
  } = t0;
450394
- const [useNativeInstaller, setUseNativeInstaller] = React112.useState(null);
450395
- const [isPackageManager, setIsPackageManager] = React112.useState(null);
450720
+ const [useNativeInstaller, setUseNativeInstaller] = React113.useState(null);
450721
+ const [isPackageManager, setIsPackageManager] = React113.useState(null);
450396
450722
  let t1;
450397
450723
  let t2;
450398
450724
  if ($[0] === Symbol.for("react.memo_cache_sentinel")) {
@@ -450416,7 +450742,7 @@ function AutoUpdaterWrapper(t0) {
450416
450742
  t1 = $[0];
450417
450743
  t2 = $[1];
450418
450744
  }
450419
- React112.useEffect(t1, t2);
450745
+ React113.useEffect(t1, t2);
450420
450746
  if (useNativeInstaller === null || isPackageManager === null) {
450421
450747
  return null;
450422
450748
  }
@@ -450467,7 +450793,7 @@ function AutoUpdaterWrapper(t0) {
450467
450793
  }
450468
450794
  return t3;
450469
450795
  }
450470
- var import_compiler_runtime279, React112, jsx_dev_runtime361;
450796
+ var import_compiler_runtime279, React113, jsx_dev_runtime361;
450471
450797
  var init_AutoUpdaterWrapper = __esm(() => {
450472
450798
  init_shared();
450473
450799
  init_config6();
@@ -450477,7 +450803,7 @@ var init_AutoUpdaterWrapper = __esm(() => {
450477
450803
  init_NativeAutoUpdater();
450478
450804
  init_PackageManagerAutoUpdater();
450479
450805
  import_compiler_runtime279 = __toESM(require_compiler_runtime(), 1);
450480
- React112 = __toESM(require_react(), 1);
450806
+ React113 = __toESM(require_react(), 1);
450481
450807
  jsx_dev_runtime361 = __toESM(require_jsx_dev_runtime(), 1);
450482
450808
  });
450483
450809
 
@@ -455748,7 +456074,7 @@ function useCoordinatorTaskCount() {
455748
456074
  function _temp164(s) {
455749
456075
  return s.tasks;
455750
456076
  }
455751
- var import_compiler_runtime286, React115;
456077
+ var import_compiler_runtime286, React116;
455752
456078
  var init_CoordinatorAgentStatus = __esm(() => {
455753
456079
  init_figures2();
455754
456080
  init_useTerminalSize();
@@ -455761,7 +456087,7 @@ var init_CoordinatorAgentStatus = __esm(() => {
455761
456087
  init_framework2();
455762
456088
  init_taskStatusUtils();
455763
456089
  import_compiler_runtime286 = __toESM(require_compiler_runtime(), 1);
455764
- React115 = __toESM(require_react(), 1);
456090
+ React116 = __toESM(require_react(), 1);
455765
456091
  });
455766
456092
 
455767
456093
  // src/tui/utils/highlightMatch.tsx
@@ -459535,9 +459861,9 @@ var init_gitStore = __esm(() => {
459535
459861
  });
459536
459862
 
459537
459863
  // src/tui/components/StatusLine/segments/GitBranchSegment.tsx
459538
- var React118, import_react225, jsx_dev_runtime387, GitBranchSegment = () => {
459864
+ var React119, import_react225, jsx_dev_runtime387, GitBranchSegment = () => {
459539
459865
  const gitState = import_react225.useSyncExternalStore(subscribeToGitState, getGitSnapshot);
459540
- const ref = React118.useRef(false);
459866
+ const ref = React119.useRef(false);
459541
459867
  if (!ref.current) {
459542
459868
  ref.current = true;
459543
459869
  refreshGitState();
@@ -459565,15 +459891,15 @@ var React118, import_react225, jsx_dev_runtime387, GitBranchSegment = () => {
459565
459891
  var init_GitBranchSegment = __esm(() => {
459566
459892
  init_ink2();
459567
459893
  init_gitStore();
459568
- React118 = __toESM(require_react(), 1);
459894
+ React119 = __toESM(require_react(), 1);
459569
459895
  import_react225 = __toESM(require_react(), 1);
459570
459896
  jsx_dev_runtime387 = __toESM(require_jsx_dev_runtime(), 1);
459571
459897
  });
459572
459898
 
459573
459899
  // src/tui/components/StatusLine/segments/GitFilesSegment.tsx
459574
- var React119, import_react226, jsx_dev_runtime388, GitFilesSegment = () => {
459900
+ var React120, import_react226, jsx_dev_runtime388, GitFilesSegment = () => {
459575
459901
  const gitState = import_react226.useSyncExternalStore(subscribeToGitState, getGitSnapshot);
459576
- const ref = React119.useRef(false);
459902
+ const ref = React120.useRef(false);
459577
459903
  if (!ref.current) {
459578
459904
  ref.current = true;
459579
459905
  refreshGitState();
@@ -459595,15 +459921,15 @@ var React119, import_react226, jsx_dev_runtime388, GitFilesSegment = () => {
459595
459921
  var init_GitFilesSegment = __esm(() => {
459596
459922
  init_ink2();
459597
459923
  init_gitStore();
459598
- React119 = __toESM(require_react(), 1);
459924
+ React120 = __toESM(require_react(), 1);
459599
459925
  import_react226 = __toESM(require_react(), 1);
459600
459926
  jsx_dev_runtime388 = __toESM(require_jsx_dev_runtime(), 1);
459601
459927
  });
459602
459928
 
459603
459929
  // src/tui/components/StatusLine/segments/GitCombinedSegment.tsx
459604
- var React120, import_react227, jsx_dev_runtime389, GitCombinedSegment = () => {
459930
+ var React121, import_react227, jsx_dev_runtime389, GitCombinedSegment = () => {
459605
459931
  const gitState = import_react227.useSyncExternalStore(subscribeToGitState, getGitSnapshot);
459606
- const ref = React120.useRef(false);
459932
+ const ref = React121.useRef(false);
459607
459933
  if (!ref.current) {
459608
459934
  ref.current = true;
459609
459935
  refreshGitState();
@@ -459632,7 +459958,7 @@ var React120, import_react227, jsx_dev_runtime389, GitCombinedSegment = () => {
459632
459958
  var init_GitCombinedSegment = __esm(() => {
459633
459959
  init_ink2();
459634
459960
  init_gitStore();
459635
- React120 = __toESM(require_react(), 1);
459961
+ React121 = __toESM(require_react(), 1);
459636
459962
  import_react227 = __toESM(require_react(), 1);
459637
459963
  jsx_dev_runtime389 = __toESM(require_jsx_dev_runtime(), 1);
459638
459964
  });
@@ -459780,18 +460106,27 @@ var init_SessionDurationSegment = __esm(() => {
459780
460106
  });
459781
460107
 
459782
460108
  // src/tui/components/StatusLine/segments/GoalSegment.tsx
459783
- var jsx_dev_runtime395, GOAL_PREFIX = "\uD83C\uDFAF ", MAX_GOAL_DISPLAY_CHARS = 40, GoalSegment = () => {
459784
- if (!isGoalArmed())
459785
- return null;
459786
- const condition = getGoalCondition() ?? "";
459787
- const truncated = truncateToWidth3(condition, MAX_GOAL_DISPLAY_CHARS);
459788
- return /* @__PURE__ */ jsx_dev_runtime395.jsxDEV(ThemedText, {
459789
- color: "yellow",
459790
- children: [
459791
- GOAL_PREFIX,
459792
- truncated
459793
- ]
459794
- }, undefined, true, undefined, this);
460109
+ var jsx_dev_runtime395, GOAL_PREFIX = "\uD83C\uDFAF ", MAX_GOAL_DISPLAY_CHARS = 40, _cachedArmed = false, _cachedCondition, _cachedNode = null, GoalSegment = () => {
460110
+ const armed = isGoalArmed();
460111
+ const condition = getGoalCondition();
460112
+ if (armed === _cachedArmed && condition === _cachedCondition) {
460113
+ return _cachedNode;
460114
+ }
460115
+ _cachedArmed = armed;
460116
+ _cachedCondition = condition;
460117
+ if (!armed) {
460118
+ _cachedNode = null;
460119
+ } else {
460120
+ const truncated = truncateToWidth3(condition ?? "", MAX_GOAL_DISPLAY_CHARS);
460121
+ _cachedNode = /* @__PURE__ */ jsx_dev_runtime395.jsxDEV(ThemedText, {
460122
+ color: "yellow",
460123
+ children: [
460124
+ GOAL_PREFIX,
460125
+ truncated
460126
+ ]
460127
+ }, undefined, true, undefined, this);
460128
+ }
460129
+ return _cachedNode;
459795
460130
  };
459796
460131
  var init_GoalSegment = __esm(() => {
459797
460132
  init_ink2();
@@ -460219,9 +460554,9 @@ function StatusLineInner({
460219
460554
  ]
460220
460555
  }, undefined, true, undefined, this);
460221
460556
  }
460222
- const handleMouseEnter = React121.useCallback(() => setHover(true), []);
460223
- const handleMouseLeave = React121.useCallback(() => setHover(false), []);
460224
- const handleClick = React121.useCallback(() => toggleDensity(), []);
460557
+ const handleMouseEnter = React122.useCallback(() => setHover(true), []);
460558
+ const handleMouseLeave = React122.useCallback(() => setHover(false), []);
460559
+ const handleClick = React122.useCallback(() => toggleDensity(), []);
460225
460560
  const hoverHint = hovered && useChannelB ? /* @__PURE__ */ jsx_dev_runtime396.jsxDEV(ThemedText, {
460226
460561
  dimColor: true,
460227
460562
  children: [
@@ -460250,7 +460585,7 @@ function StatusLineInner({
460250
460585
  ]
460251
460586
  }, undefined, true, undefined, this);
460252
460587
  }
460253
- var React121, import_react228, jsx_dev_runtime396, StatusLine;
460588
+ var React122, import_react228, jsx_dev_runtime396, StatusLine;
460254
460589
  var init_StatusLine = __esm(() => {
460255
460590
  init_AppState();
460256
460591
  init_bootstrap();
@@ -460277,7 +460612,7 @@ var init_StatusLine = __esm(() => {
460277
460612
  init_statusLineConfig();
460278
460613
  init_densityStore();
460279
460614
  init_useTerminalSize();
460280
- React121 = __toESM(require_react(), 1);
460615
+ React122 = __toESM(require_react(), 1);
460281
460616
  import_react228 = __toESM(require_react(), 1);
460282
460617
  jsx_dev_runtime396 = __toESM(require_jsx_dev_runtime(), 1);
460283
460618
  StatusLine = import_react228.memo(StatusLineInner);
@@ -460627,7 +460962,7 @@ function BackgroundTaskStatus(t0) {
460627
460962
  if ($[25] !== selectedIdx || $[26] !== setAppState || $[27] !== viewedIdx || $[28] !== visiblePills) {
460628
460963
  t13 = visiblePills.map((pill_1, i_1) => {
460629
460964
  const needsSeparator = i_1 > 0;
460630
- return /* @__PURE__ */ jsx_dev_runtime398.jsxDEV(React122.Fragment, {
460965
+ return /* @__PURE__ */ jsx_dev_runtime398.jsxDEV(React123.Fragment, {
460631
460966
  children: [
460632
460967
  needsSeparator && /* @__PURE__ */ jsx_dev_runtime398.jsxDEV(ThemedText, {
460633
460968
  children: " "
@@ -460997,7 +461332,7 @@ function getAgentThemeColor(colorName) {
460997
461332
  }
460998
461333
  return;
460999
461334
  }
461000
- var import_compiler_runtime293, React122, import_react231, jsx_dev_runtime398;
461335
+ var import_compiler_runtime293, React123, import_react231, jsx_dev_runtime398;
461001
461336
  var init_BackgroundTaskStatus = __esm(() => {
461002
461337
  init_figures();
461003
461338
  init_useTerminalSize();
@@ -461012,7 +461347,7 @@ var init_BackgroundTaskStatus = __esm(() => {
461012
461347
  init_KeyboardShortcutHint();
461013
461348
  init_taskStatusUtils();
461014
461349
  import_compiler_runtime293 = __toESM(require_compiler_runtime(), 1);
461015
- React122 = __toESM(require_react(), 1);
461350
+ React123 = __toESM(require_react(), 1);
461016
461351
  import_react231 = __toESM(require_react(), 1);
461017
461352
  jsx_dev_runtime398 = __toESM(require_jsx_dev_runtime(), 1);
461018
461353
  });
@@ -462123,7 +462458,7 @@ function PromptInputQueuedCommandsImpl() {
462123
462458
  }, i, false, undefined, this))
462124
462459
  }, undefined, false, undefined, this);
462125
462460
  }
462126
- var React123, import_react235, jsx_dev_runtime404, EMPTY_SET2, MAX_VISIBLE_NOTIFICATIONS = 3, PromptInputQueuedCommands;
462461
+ var React124, import_react235, jsx_dev_runtime404, EMPTY_SET2, MAX_VISIBLE_NOTIFICATIONS = 3, PromptInputQueuedCommands;
462127
462462
  var init_PromptInputQueuedCommands = __esm(() => {
462128
462463
  init_ink2();
462129
462464
  init_AppState();
@@ -462134,11 +462469,11 @@ var init_PromptInputQueuedCommands = __esm(() => {
462134
462469
  init_messages3();
462135
462470
  init_slowOperations();
462136
462471
  init_Message();
462137
- React123 = __toESM(require_react(), 1);
462472
+ React124 = __toESM(require_react(), 1);
462138
462473
  import_react235 = __toESM(require_react(), 1);
462139
462474
  jsx_dev_runtime404 = __toESM(require_jsx_dev_runtime(), 1);
462140
462475
  EMPTY_SET2 = new Set;
462141
- PromptInputQueuedCommands = React123.memo(PromptInputQueuedCommandsImpl);
462476
+ PromptInputQueuedCommands = React124.memo(PromptInputQueuedCommandsImpl);
462142
462477
  });
462143
462478
 
462144
462479
  // src/tui/components/PromptInput/PromptInputStashNotice.tsx
@@ -462455,8 +462790,8 @@ function useSwarmBanner() {
462455
462790
  const agent = useAppState((s) => s.agent);
462456
462791
  useAppState((s) => s.viewingAgentTaskId);
462457
462792
  const store = useAppStateStore();
462458
- const [insideTmux, setInsideTmux] = React124.useState(null);
462459
- React124.useEffect(() => {
462793
+ const [insideTmux, setInsideTmux] = React125.useState(null);
462794
+ React125.useEffect(() => {
462460
462795
  isInsideTmux3().then(setInsideTmux);
462461
462796
  }, []);
462462
462797
  const state = store.getState();
@@ -462523,7 +462858,7 @@ function useSwarmBanner() {
462523
462858
  function toThemeColor(colorName, fallback = "cyan_FOR_SUBAGENTS_ONLY") {
462524
462859
  return colorName && AGENT_COLORS2.includes(colorName) ? AGENT_COLOR_TO_THEME_COLOR[colorName] : fallback;
462525
462860
  }
462526
- var React124;
462861
+ var React125;
462527
462862
  var init_useSwarmBanner = __esm(() => {
462528
462863
  init_AppState();
462529
462864
  init_selectors();
@@ -462533,7 +462868,7 @@ var init_useSwarmBanner = __esm(() => {
462533
462868
  init_registry3();
462534
462869
  init_teammate2();
462535
462870
  init_teammateContext3();
462536
- React124 = __toESM(require_react(), 1);
462871
+ React125 = __toESM(require_react(), 1);
462537
462872
  });
462538
462873
 
462539
462874
  // src/tui/components/PromptInput/PromptInput.tsx
@@ -462589,12 +462924,12 @@ function PromptInput({
462589
462924
  show: false
462590
462925
  });
462591
462926
  const [cursorOffset, setCursorOffset] = import_react238.useState(input.length);
462592
- const lastInternalInputRef = React125.useRef(input);
462927
+ const lastInternalInputRef = React126.useRef(input);
462593
462928
  if (input !== lastInternalInputRef.current) {
462594
462929
  setCursorOffset(input.length);
462595
462930
  lastInternalInputRef.current = input;
462596
462931
  }
462597
- const trackAndSetInput = React125.useCallback((value) => {
462932
+ const trackAndSetInput = React126.useCallback((value) => {
462598
462933
  lastInternalInputRef.current = value;
462599
462934
  onInputChange(value);
462600
462935
  }, [onInputChange]);
@@ -464249,7 +464584,7 @@ function getInitialPasteId(messages) {
464249
464584
  }
464250
464585
  return maxId + 1;
464251
464586
  }
464252
- var React125, import_react238, jsx_dev_runtime406, PROMPT_FOOTER_LINES = 5, MIN_INPUT_VIEWPORT_LINES = 3, PromptInput_default;
464587
+ var React126, import_react238, jsx_dev_runtime406, PROMPT_FOOTER_LINES = 5, MIN_INPUT_VIEWPORT_LINES = 3, PromptInput_default;
464253
464588
  var init_PromptInput = __esm(() => {
464254
464589
  init_shared();
464255
464590
  init_notifications();
@@ -464336,10 +464671,10 @@ var init_PromptInput = __esm(() => {
464336
464671
  init_usePromptInputPlaceholder();
464337
464672
  init_useSwarmBanner();
464338
464673
  init_utils11();
464339
- React125 = __toESM(require_react(), 1);
464674
+ React126 = __toESM(require_react(), 1);
464340
464675
  import_react238 = __toESM(require_react(), 1);
464341
464676
  jsx_dev_runtime406 = __toESM(require_jsx_dev_runtime(), 1);
464342
- PromptInput_default = React125.memo(PromptInput);
464677
+ PromptInput_default = React126.memo(PromptInput);
464343
464678
  });
464344
464679
 
464345
464680
  // src/tui/utils/hooks/apiQueryHookHelper.ts
@@ -472574,7 +472909,7 @@ function useLspInitializationNotification() {
472574
472909
  addNotification
472575
472910
  } = useNotifications();
472576
472911
  const setAppState = useSetAppState();
472577
- const [shouldPoll, setShouldPoll] = React126.useState(_temp183);
472912
+ const [shouldPoll, setShouldPoll] = React127.useState(_temp183);
472578
472913
  let t0;
472579
472914
  if ($[0] === Symbol.for("react.memo_cache_sentinel")) {
472580
472915
  t0 = new Set;
@@ -472582,7 +472917,7 @@ function useLspInitializationNotification() {
472582
472917
  } else {
472583
472918
  t0 = $[0];
472584
472919
  }
472585
- const notifiedErrorsRef = React126.useRef(t0);
472920
+ const notifiedErrorsRef = React127.useRef(t0);
472586
472921
  let t1;
472587
472922
  if ($[1] !== addNotification || $[2] !== setAppState) {
472588
472923
  t1 = (source, errorMessage) => {
@@ -472693,7 +473028,7 @@ function useLspInitializationNotification() {
472693
473028
  t3 = $[8];
472694
473029
  t4 = $[9];
472695
473030
  }
472696
- React126.useEffect(t3, t4);
473031
+ React127.useEffect(t3, t4);
472697
473032
  }
472698
473033
  function _temp280(e) {
472699
473034
  if (e.type === "generic-error") {
@@ -472704,7 +473039,7 @@ function _temp280(e) {
472704
473039
  function _temp183() {
472705
473040
  return isEnvTruthy2("true");
472706
473041
  }
472707
- var import_compiler_runtime308, React126, jsx_dev_runtime418, LSP_POLL_INTERVAL_MS = 5000;
473042
+ var import_compiler_runtime308, React127, jsx_dev_runtime418, LSP_POLL_INTERVAL_MS = 5000;
472708
473043
  var init_useLspInitializationNotification = __esm(() => {
472709
473044
  init_dist3();
472710
473045
  init_bootstrapState();
@@ -472715,7 +473050,7 @@ var init_useLspInitializationNotification = __esm(() => {
472715
473050
  init_debug();
472716
473051
  init_envUtils2();
472717
473052
  import_compiler_runtime308 = __toESM(require_compiler_runtime(), 1);
472718
- React126 = __toESM(require_react(), 1);
473053
+ React127 = __toESM(require_react(), 1);
472719
473054
  jsx_dev_runtime418 = __toESM(require_jsx_dev_runtime(), 1);
472720
473055
  });
472721
473056
 
@@ -472928,8 +473263,8 @@ var init_lspRecommendation = __esm(() => {
472928
473263
  // src/tui/hooks/usePluginRecommendationBase.tsx
472929
473264
  function usePluginRecommendationBase() {
472930
473265
  const $ = import_compiler_runtime309.c(6);
472931
- const [recommendation, setRecommendation] = React127.useState(null);
472932
- const isCheckingRef = React127.useRef(false);
473266
+ const [recommendation, setRecommendation] = React128.useState(null);
473267
+ const isCheckingRef = React128.useRef(false);
472933
473268
  let t0;
472934
473269
  if ($[0] !== recommendation) {
472935
473270
  t0 = (resolve) => {
@@ -473017,7 +473352,7 @@ async function installPluginAndNotify(pluginId, pluginName, keyPrefix, addNotifi
473017
473352
  });
473018
473353
  }
473019
473354
  }
473020
- var import_compiler_runtime309, React127, jsx_dev_runtime419;
473355
+ var import_compiler_runtime309, React128, jsx_dev_runtime419;
473021
473356
  var init_usePluginRecommendationBase = __esm(() => {
473022
473357
  init_figures();
473023
473358
  init_bootstrapState();
@@ -473025,7 +473360,7 @@ var init_usePluginRecommendationBase = __esm(() => {
473025
473360
  init_log5();
473026
473361
  init_marketplaceManager();
473027
473362
  import_compiler_runtime309 = __toESM(require_compiler_runtime(), 1);
473028
- React127 = __toESM(require_react(), 1);
473363
+ React128 = __toESM(require_react(), 1);
473029
473364
  jsx_dev_runtime419 = __toESM(require_jsx_dev_runtime(), 1);
473030
473365
  });
473031
473366
 
@@ -473044,7 +473379,7 @@ function useLspPluginRecommendation() {
473044
473379
  } else {
473045
473380
  t0 = $[0];
473046
473381
  }
473047
- const checkedFilesRef = React128.useRef(t0);
473382
+ const checkedFilesRef = React129.useRef(t0);
473048
473383
  const {
473049
473384
  recommendation,
473050
473385
  clearRecommendation,
@@ -473097,7 +473432,7 @@ function useLspPluginRecommendation() {
473097
473432
  t1 = $[3];
473098
473433
  t2 = $[4];
473099
473434
  }
473100
- React128.useEffect(t1, t2);
473435
+ React129.useEffect(t1, t2);
473101
473436
  let t3;
473102
473437
  if ($[5] !== addNotification || $[6] !== clearRecommendation || $[7] !== recommendation) {
473103
473438
  t3 = (response) => {
@@ -473180,7 +473515,7 @@ function _temp281(current) {
473180
473515
  function _temp184(s) {
473181
473516
  return s.fileHistory.trackedFiles;
473182
473517
  }
473183
- var import_compiler_runtime310, React128, TIMEOUT_THRESHOLD_MS = 28000;
473518
+ var import_compiler_runtime310, React129, TIMEOUT_THRESHOLD_MS = 28000;
473184
473519
  var init_useLspPluginRecommendation = __esm(() => {
473185
473520
  init_bootstrapState();
473186
473521
  init_notifications();
@@ -473193,7 +473528,7 @@ var init_useLspPluginRecommendation = __esm(() => {
473193
473528
  init_settings3();
473194
473529
  init_usePluginRecommendationBase();
473195
473530
  import_compiler_runtime310 = __toESM(require_compiler_runtime(), 1);
473196
- React128 = __toESM(require_react(), 1);
473531
+ React129 = __toESM(require_react(), 1);
473197
473532
  });
473198
473533
 
473199
473534
  // src/tui/components/LspRecommendation/LspRecommendationMenu.tsx
@@ -473203,9 +473538,9 @@ function LspRecommendationMenu({
473203
473538
  fileExtension,
473204
473539
  onResponse
473205
473540
  }) {
473206
- const onResponseRef = React129.useRef(onResponse);
473541
+ const onResponseRef = React130.useRef(onResponse);
473207
473542
  onResponseRef.current = onResponse;
473208
- React129.useEffect(() => {
473543
+ React130.useEffect(() => {
473209
473544
  const timeoutId = setTimeout((ref) => ref.current("no"), AUTO_DISMISS_MS, onResponseRef);
473210
473545
  return () => clearTimeout(timeoutId);
473211
473546
  }, []);
@@ -473320,19 +473655,19 @@ function LspRecommendationMenu({
473320
473655
  }, undefined, true, undefined, this)
473321
473656
  }, undefined, false, undefined, this);
473322
473657
  }
473323
- var React129, jsx_dev_runtime420, AUTO_DISMISS_MS = 30000;
473658
+ var React130, jsx_dev_runtime420, AUTO_DISMISS_MS = 30000;
473324
473659
  var init_LspRecommendationMenu = __esm(() => {
473325
473660
  init_ink2();
473326
473661
  init_select();
473327
473662
  init_PermissionDialog();
473328
- React129 = __toESM(require_react(), 1);
473663
+ React130 = __toESM(require_react(), 1);
473329
473664
  jsx_dev_runtime420 = __toESM(require_jsx_dev_runtime(), 1);
473330
473665
  });
473331
473666
 
473332
473667
  // src/tui/hooks/useAtlasCodeHintRecommendation.tsx
473333
473668
  function useAtlasCodeHintRecommendation() {
473334
473669
  const $ = import_compiler_runtime311.c(11);
473335
- const pendingHint = React130.useSyncExternalStore(subscribeToPendingHint, getPendingHintSnapshot);
473670
+ const pendingHint = React131.useSyncExternalStore(subscribeToPendingHint, getPendingHintSnapshot);
473336
473671
  const {
473337
473672
  addNotification
473338
473673
  } = useNotifications();
@@ -473369,7 +473704,7 @@ function useAtlasCodeHintRecommendation() {
473369
473704
  t0 = $[2];
473370
473705
  t1 = $[3];
473371
473706
  }
473372
- React130.useEffect(t0, t1);
473707
+ React131.useEffect(t0, t1);
473373
473708
  let t2;
473374
473709
  if ($[4] !== addNotification || $[5] !== clearRecommendation || $[6] !== recommendation) {
473375
473710
  t2 = (response) => {
@@ -473429,7 +473764,7 @@ function useAtlasCodeHintRecommendation() {
473429
473764
  }
473430
473765
  return t3;
473431
473766
  }
473432
- var import_compiler_runtime311, React130;
473767
+ var import_compiler_runtime311, React131;
473433
473768
  var init_useAtlasCodeHintRecommendation = __esm(() => {
473434
473769
  init_notifications();
473435
473770
  init_atlasCodeHints();
@@ -473438,7 +473773,7 @@ var init_useAtlasCodeHintRecommendation = __esm(() => {
473438
473773
  init_pluginInstallationHelpers();
473439
473774
  init_usePluginRecommendationBase();
473440
473775
  import_compiler_runtime311 = __toESM(require_compiler_runtime(), 1);
473441
- React130 = __toESM(require_react(), 1);
473776
+ React131 = __toESM(require_react(), 1);
473442
473777
  });
473443
473778
 
473444
473779
  // src/tui/components/PluginHint/PluginHintMenu.tsx
@@ -473449,9 +473784,9 @@ function PluginHintMenu({
473449
473784
  sourceCommand,
473450
473785
  onResponse
473451
473786
  }) {
473452
- const onResponseRef = React131.useRef(onResponse);
473787
+ const onResponseRef = React132.useRef(onResponse);
473453
473788
  onResponseRef.current = onResponse;
473454
- React131.useEffect(() => {
473789
+ React132.useEffect(() => {
473455
473790
  const timeoutId = setTimeout((ref) => ref.current("no"), AUTO_DISMISS_MS2, onResponseRef);
473456
473791
  return () => clearTimeout(timeoutId);
473457
473792
  }, []);
@@ -473557,12 +473892,12 @@ function PluginHintMenu({
473557
473892
  }, undefined, true, undefined, this)
473558
473893
  }, undefined, false, undefined, this);
473559
473894
  }
473560
- var React131, jsx_dev_runtime421, AUTO_DISMISS_MS2 = 30000;
473895
+ var React132, jsx_dev_runtime421, AUTO_DISMISS_MS2 = 30000;
473561
473896
  var init_PluginHintMenu = __esm(() => {
473562
473897
  init_ink2();
473563
473898
  init_select();
473564
473899
  init_PermissionDialog();
473565
- React131 = __toESM(require_react(), 1);
473900
+ React132 = __toESM(require_react(), 1);
473566
473901
  jsx_dev_runtime421 = __toESM(require_jsx_dev_runtime(), 1);
473567
473902
  });
473568
473903
 
@@ -475157,31 +475492,31 @@ function SessionTreeScreen({
475157
475492
  onResume,
475158
475493
  onAgenticSearch
475159
475494
  }) {
475160
- const [logs, setLogs] = React134.useState([]);
475161
- const [loading, setLoading] = React134.useState(true);
475162
- const [focusedIdx, setFocusedIdx] = React134.useState(0);
475163
- const [selectedIdx, setSelectedIdx] = React134.useState(null);
475164
- const [rowStates, setRowStates] = React134.useState(new Map);
475165
- const [scrollOffset, setScrollOffset] = React134.useState(0);
475166
- const [expanded, setExpanded] = React134.useState(false);
475495
+ const [logs, setLogs] = React135.useState([]);
475496
+ const [loading, setLoading] = React135.useState(true);
475497
+ const [focusedIdx, setFocusedIdx] = React135.useState(0);
475498
+ const [selectedIdx, setSelectedIdx] = React135.useState(null);
475499
+ const [rowStates, setRowStates] = React135.useState(new Map);
475500
+ const [scrollOffset, setScrollOffset] = React135.useState(0);
475501
+ const [expanded, setExpanded] = React135.useState(false);
475167
475502
  const expandedIdx = expanded ? focusedIdx : null;
475168
- const [searchMode, setSearchMode] = React134.useState(false);
475169
- const [query, setQuery] = React134.useState("");
475170
- const [sortKey, setSortKey] = React134.useState("modified");
475171
- const [agenticResults, setAgenticResults] = React134.useState(null);
475172
- const exactCountCacheRef = React134.useRef(makeLru(64));
475173
- const [, bumpExactCounts] = React134.useReducer((x) => x + 1, 0);
475174
- const confirmTimerRef = React134.useRef(null);
475175
- const forkInFlightRef = React134.useRef(false);
475176
- const fileMetaCacheRef = React134.useRef(new Map);
475177
- const setRowState = React134.useCallback((sid, s) => {
475503
+ const [searchMode, setSearchMode] = React135.useState(false);
475504
+ const [query, setQuery] = React135.useState("");
475505
+ const [sortKey, setSortKey] = React135.useState("modified");
475506
+ const [agenticResults, setAgenticResults] = React135.useState(null);
475507
+ const exactCountCacheRef = React135.useRef(makeLru(64));
475508
+ const [, bumpExactCounts] = React135.useReducer((x) => x + 1, 0);
475509
+ const confirmTimerRef = React135.useRef(null);
475510
+ const forkInFlightRef = React135.useRef(false);
475511
+ const fileMetaCacheRef = React135.useRef(new Map);
475512
+ const setRowState = React135.useCallback((sid, s) => {
475178
475513
  setRowStates((prev) => {
475179
475514
  const next = new Map(prev);
475180
475515
  next.set(sid, s);
475181
475516
  return next;
475182
475517
  });
475183
475518
  }, []);
475184
- const loadLogs = React134.useCallback(async () => {
475519
+ const loadLogs = React135.useCallback(async () => {
475185
475520
  const wt = getCurrentWorktreeSession2();
475186
475521
  const paths = wt ? [wt.worktreePath] : [getOriginalCwd()];
475187
475522
  const l = await loadSameRepoAllMessageLogs(paths);
@@ -475200,14 +475535,14 @@ function SessionTreeScreen({
475200
475535
  setLogs(l);
475201
475536
  setLoading(false);
475202
475537
  }, []);
475203
- React134.useEffect(() => {
475538
+ React135.useEffect(() => {
475204
475539
  loadLogs();
475205
475540
  return () => {
475206
475541
  if (confirmTimerRef.current)
475207
475542
  clearTimeout(confirmTimerRef.current);
475208
475543
  };
475209
475544
  }, [loadLogs]);
475210
- const doFork = React134.useCallback(async (target) => {
475545
+ const doFork = React135.useCallback(async (target) => {
475211
475546
  if (!target.sessionId || !target.fullPath)
475212
475547
  return;
475213
475548
  if (forkInFlightRef.current)
@@ -475240,12 +475575,12 @@ function SessionTreeScreen({
475240
475575
  setFocusedIdx(idx);
475241
475576
  setSelectedIdx(null);
475242
475577
  }
475243
- const computeViewLogs = React134.useCallback((base, q, sk, agentic) => {
475578
+ const computeViewLogs = React135.useCallback((base, q, sk, agentic) => {
475244
475579
  const local = q ? filterLogs(base, q) : base;
475245
475580
  const chosen = agentic && local.length === 0 ? agentic : local;
475246
475581
  return sortLogsBy(chosen, sk);
475247
475582
  }, []);
475248
- const ensureExactCount = React134.useCallback(async (log) => {
475583
+ const ensureExactCount = React135.useCallback(async (log) => {
475249
475584
  const sid = log.sessionId ?? "";
475250
475585
  if (!sid)
475251
475586
  return;
@@ -475520,7 +475855,7 @@ function SessionTreeScreen({
475520
475855
  }
475521
475856
  line += " " + flags;
475522
475857
  const summaryLine = " └ " + truncateToVisibleWidth(getSummaryLine(log), termCols - 4 - 6);
475523
- return /* @__PURE__ */ jsx_dev_runtime428.jsxDEV(React134.Fragment, {
475858
+ return /* @__PURE__ */ jsx_dev_runtime428.jsxDEV(React135.Fragment, {
475524
475859
  children: [
475525
475860
  /* @__PURE__ */ jsx_dev_runtime428.jsxDEV(ThemedBox_default, {
475526
475861
  noSelect: true,
@@ -475577,7 +475912,7 @@ function SessionTreeScreen({
475577
475912
  ]
475578
475913
  }, undefined, true, undefined, this);
475579
475914
  }
475580
- var React134, jsx_dev_runtime428, AGENT_COLOR_THEME_FIELD, SESSION_ROW_HINT = "\uD83D\uDDB1 点击移动光标 · 滚轮/↑↓ 滚动 · enter 选中/进入 · f fork · x 摘要 · q 返回", SESSION_SORT_KEYS, SESSION_SORT_LABELS, HEADER_ROWS = 4, FOOTER_ROWS = 2;
475915
+ var React135, jsx_dev_runtime428, AGENT_COLOR_THEME_FIELD, SESSION_ROW_HINT = "\uD83D\uDDB1 点击移动光标 · 滚轮/↑↓ 滚动 · enter 选中/进入 · f fork · x 摘要 · q 返回", SESSION_SORT_KEYS, SESSION_SORT_LABELS, HEADER_ROWS = 4, FOOTER_ROWS = 2;
475581
475916
  var init_SessionTreeScreen = __esm(() => {
475582
475917
  init_ink2();
475583
475918
  init_config6();
@@ -475590,7 +475925,7 @@ var init_SessionTreeScreen = __esm(() => {
475590
475925
  init_displayTags();
475591
475926
  init_sessionStorage();
475592
475927
  init_branch();
475593
- React134 = __toESM(require_react(), 1);
475928
+ React135 = __toESM(require_react(), 1);
475594
475929
  jsx_dev_runtime428 = __toESM(require_jsx_dev_runtime(), 1);
475595
475930
  AGENT_COLOR_THEME_FIELD = {
475596
475931
  red: "red_FOR_SUBAGENTS_ONLY",
@@ -477495,8 +477830,8 @@ function TranscriptSearchBar({
477495
477830
  onExit: () => onClose(query),
477496
477831
  onCancel
477497
477832
  });
477498
- const [indexStatus, setIndexStatus] = React137.useState("building");
477499
- React137.useEffect(() => {
477833
+ const [indexStatus, setIndexStatus] = React138.useState("building");
477834
+ React138.useEffect(() => {
477500
477835
  let alive = true;
477501
477836
  const warm = jumpRef.current?.warmSearchIndex;
477502
477837
  if (!warm) {
@@ -477681,8 +478016,8 @@ function REPL({
477681
478016
  const viewingAgentTaskId = useAppState((s) => s.viewingAgentTaskId);
477682
478017
  const setAppState = useSetAppState();
477683
478018
  const pendingScreen = useAppState((s) => s.pendingScreen);
477684
- const statuslineMouseWriteRef = React137.useContext(TerminalWriteContext);
477685
- React137.useEffect(() => {
478019
+ const statuslineMouseWriteRef = React138.useContext(TerminalWriteContext);
478020
+ React138.useEffect(() => {
477686
478021
  if (!statuslineMouseWriteRef)
477687
478022
  return;
477688
478023
  if (!isMouseTrackingEnabled())
@@ -477692,7 +478027,7 @@ function REPL({
477692
478027
  statuslineMouseWriteRef(DISABLE_MOUSE_TRACKING);
477693
478028
  };
477694
478029
  }, [statuslineMouseWriteRef]);
477695
- React137.useEffect(() => {
478030
+ React138.useEffect(() => {
477696
478031
  if (pendingScreen === "session-tree") {
477697
478032
  setAppState((prev) => ({ ...prev, pendingScreen: undefined }));
477698
478033
  setScreen("session-tree");
@@ -477848,36 +478183,36 @@ function REPL({
477848
478183
  const scrollRef = import_react281.useRef(null);
477849
478184
  const modalScrollRef = import_react281.useRef(null);
477850
478185
  const lastUserScrollTsRef = import_react281.useRef(0);
477851
- const queryGuard = React137.useRef(new QueryGuard).current;
477852
- const isQueryActive = React137.useSyncExternalStore(queryGuard.subscribe, queryGuard.getSnapshot);
477853
- const [isExternalLoading, setIsExternalLoadingRaw] = React137.useState(remoteSessionConfig?.hasInitialPrompt ?? false);
478186
+ const queryGuard = React138.useRef(new QueryGuard).current;
478187
+ const isQueryActive = React138.useSyncExternalStore(queryGuard.subscribe, queryGuard.getSnapshot);
478188
+ const [isExternalLoading, setIsExternalLoadingRaw] = React138.useState(remoteSessionConfig?.hasInitialPrompt ?? false);
477854
478189
  const isLoading = isQueryActive || isExternalLoading;
477855
- const [userInputOnProcessing, setUserInputOnProcessingRaw] = React137.useState(undefined);
477856
- const userInputBaselineRef = React137.useRef(0);
477857
- const userMessagePendingRef = React137.useRef(false);
477858
- const loadingStartTimeRef = React137.useRef(0);
477859
- const totalPausedMsRef = React137.useRef(0);
477860
- const pauseStartTimeRef = React137.useRef(null);
477861
- const resetTimingRefs = React137.useCallback(() => {
478190
+ const [userInputOnProcessing, setUserInputOnProcessingRaw] = React138.useState(undefined);
478191
+ const userInputBaselineRef = React138.useRef(0);
478192
+ const userMessagePendingRef = React138.useRef(false);
478193
+ const loadingStartTimeRef = React138.useRef(0);
478194
+ const totalPausedMsRef = React138.useRef(0);
478195
+ const pauseStartTimeRef = React138.useRef(null);
478196
+ const resetTimingRefs = React138.useCallback(() => {
477862
478197
  loadingStartTimeRef.current = Date.now();
477863
478198
  totalPausedMsRef.current = 0;
477864
478199
  pauseStartTimeRef.current = null;
477865
478200
  }, []);
477866
- const wasQueryActiveRef = React137.useRef(false);
478201
+ const wasQueryActiveRef = React138.useRef(false);
477867
478202
  if (isQueryActive && !wasQueryActiveRef.current) {
477868
478203
  resetTimingRefs();
477869
478204
  }
477870
478205
  wasQueryActiveRef.current = isQueryActive;
477871
- const setIsExternalLoading = React137.useCallback((value) => {
478206
+ const setIsExternalLoading = React138.useCallback((value) => {
477872
478207
  setIsExternalLoadingRaw(value);
477873
478208
  if (value)
477874
478209
  resetTimingRefs();
477875
478210
  }, [resetTimingRefs]);
477876
- const swarmStartTimeRef = React137.useRef(null);
477877
- const swarmBudgetInfoRef = React137.useRef(undefined);
477878
- const focusedInputDialogRef = React137.useRef(undefined);
478211
+ const swarmStartTimeRef = React138.useRef(null);
478212
+ const swarmBudgetInfoRef = React138.useRef(undefined);
478213
+ const focusedInputDialogRef = React138.useRef(undefined);
477879
478214
  const PROMPT_SUPPRESSION_MS = 1500;
477880
- const [isPromptInputActive, setIsPromptInputActive] = React137.useState(false);
478215
+ const [isPromptInputActive, setIsPromptInputActive] = React138.useState(false);
477881
478216
  const [autoUpdaterResult, setAutoUpdaterResult] = import_react281.useState(null);
477882
478217
  import_react281.useEffect(() => {
477883
478218
  if (autoUpdaterResult?.notifications) {
@@ -479006,7 +479341,8 @@ Error: sandbox required but unavailable: ${reason}
479006
479341
  } catch (error) {
479007
479342
  logError3(error);
479008
479343
  const llmTimeoutHint = llmTimeoutRemediationHint(error, getCurrentLlmTimeoutMs());
479009
- const gwHint = gatewayUnreachableRemediationHint(error);
479344
+ const endpointLabel = getCurrentEndpointLabel(mainLoopModelParam);
479345
+ const gwHint = gatewayUnreachableRemediationHint(error, endpointLabel);
479010
479346
  setMessages((prev) => [...prev, createSystemMessage(`本轮执行出错:${errorMessage2(error)}。${llmTimeoutHint ? `${llmTimeoutHint} ` : ""}${gwHint ? `${gwHint} ` : ""}请重试。`, "error")]);
479011
479347
  } finally {
479012
479348
  if (queryGuard.end(thisGeneration)) {
@@ -479894,8 +480230,8 @@ Note: ctrl + z now suspends AtlasCode, ctrl + _ undoes input.
479894
480230
  setPositions
479895
480231
  } = useSearchHighlight();
479896
480232
  const transcriptCols = useTerminalSize().columns;
479897
- const prevColsRef = React137.useRef(transcriptCols);
479898
- React137.useEffect(() => {
480233
+ const prevColsRef = React138.useRef(transcriptCols);
480234
+ React138.useEffect(() => {
479899
480235
  if (prevColsRef.current !== transcriptCols) {
479900
480236
  prevColsRef.current = transcriptCols;
479901
480237
  if (searchQuery || searchOpen) {
@@ -480691,7 +481027,7 @@ Note: ctrl + z now suspends AtlasCode, ctrl + _ undoes input.
480691
481027
  }
480692
481028
  return mainReturn;
480693
481029
  }
480694
- var import_compiler_runtime320, React137, import_react281, jsx_dev_runtime431, UltraplanChoiceDialog = () => null, UltraplanLaunchDialog = () => null, launchUltraplan2 = null, useVoiceIntegration2, VoiceKeybindingHandler2, useAntOrgWarningNotification = () => {}, getCoordinatorUserContext3, SUGGEST_BG_PR_NOOP = (_p, _n) => false, useScheduledTasks2, EMPTY_MCP_CLIENTS2, RECENT_SCROLL_REPIN_WINDOW_MS = 3000, TITLE_ANIMATION_FRAMES, TITLE_STATIC_PREFIX = "✳", TITLE_ANIMATION_INTERVAL_MS = 960;
481030
+ var import_compiler_runtime320, React138, import_react281, jsx_dev_runtime431, UltraplanChoiceDialog = () => null, UltraplanLaunchDialog = () => null, launchUltraplan2 = null, useVoiceIntegration2, VoiceKeybindingHandler2, useAntOrgWarningNotification = () => {}, getCoordinatorUserContext3, SUGGEST_BG_PR_NOOP = (_p, _n) => false, useScheduledTasks2, EMPTY_MCP_CLIENTS2, RECENT_SCROLL_REPIN_WINDOW_MS = 3000, TITLE_ANIMATION_FRAMES, TITLE_STATIC_PREFIX = "✳", TITLE_ANIMATION_INTERVAL_MS = 960;
480695
481031
  var init_REPL = __esm(() => {
480696
481032
  init_shared();
480697
481033
  init_modelprovider2();
@@ -480879,7 +481215,7 @@ var init_REPL = __esm(() => {
480879
481215
  init_osc();
480880
481216
  init_attachments();
480881
481217
  import_compiler_runtime320 = __toESM(require_compiler_runtime(), 1);
480882
- React137 = __toESM(require_react(), 1);
481218
+ React138 = __toESM(require_react(), 1);
480883
481219
  import_react281 = __toESM(require_react(), 1);
480884
481220
  jsx_dev_runtime431 = __toESM(require_jsx_dev_runtime(), 1);
480885
481221
  useVoiceIntegration2 = feature("VOICE_MODE") ? (init_useVoiceIntegration(), __toCommonJS(exports_useVoiceIntegration)).useVoiceIntegration : () => ({