@atlasharness/atlascode 0.1.63 → 0.1.65

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 +221 -39
  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();
@@ -37047,9 +37092,9 @@ function formatAgentLine(agent) {
37047
37092
  function getPrompt(agents) {
37048
37093
  const list = agents.length > 0 ? agents.map(formatAgentLine).join(`
37049
37094
  `) : "- general-purpose: General-purpose agent for researching and executing multi-step tasks.";
37050
- return "Launch a subagent to run a self-contained task in an isolated context. " + "Provide a short description (3-5 words) and a fully self-contained prompt " + "(the subagent cannot see this conversation). " + "Be cost-aware about delegating: prefer to do the work inline in this " + "conversation for a small task with a known, bounded target (a single-file " + "edit, a quick lookup, a change you can finish without broad exploration) — " + "spawning a subagent has overhead. Delegate when the task is genuinely " + "parallelizable or would otherwise flood this context with material you do " + "not need to keep (a broad multi-file search, an isolated multi-step " + "implementation, or independent work that can run alongside your own). Keep " + "each delegated brief narrow and evidence-focused: name the exact goal, the " + "files or area, and the expected deliverable rather than a broad " + '"figure this out." Because the subagent cannot see this conversation, its ' + "prompt must be fully self-contained — state every constraint, file, and " + "reporting requirement it needs. " + `Available agent types and the tools they have access to:
37095
+ return "Launch a subagent to run a self-contained task in an isolated context. " + "Provide a short description (3-5 words) and a fully self-contained prompt " + "(the subagent cannot see this conversation). " + "Be cost-aware about delegating: prefer to do the work inline in this " + "conversation for a small task with a known, bounded target (a single-file " + "edit, a quick lookup, a change you can finish without broad exploration) — " + "spawning a subagent has overhead. Delegate when the task is genuinely " + "parallelizable or would otherwise flood this context with material you do " + "not need to keep (a broad multi-file search, an isolated multi-step " + "implementation, or independent work that can run alongside your own). Keep " + "each delegated brief narrow and evidence-focused: name the exact goal, the " + "files or area, and the expected deliverable rather than a broad " + '"figure this out." Because the subagent cannot see this conversation, its ' + "prompt must be fully self-contained — state every constraint, file, and " + "reporting requirement it needs. " + "Set run_in_background to true to launch a subagent that runs while you " + "continue working in this conversation; you will receive a task-notification " + "when it completes. Use this only for genuinely parallel work, not to defer " + "a result you need before you can proceed. " + `Available agent types and the tools they have access to:
37051
37096
  ${list}
37052
- ` + `The ${AGENT_TOOL_NAME} tool runs the subagent and returns its final result ` + "when it completes; act on that result once it is returned.";
37097
+ ` + `The ${AGENT_TOOL_NAME} tool runs the subagent and returns its final result ` + "when it completes; act on that result once it is returned. " + "Do not predict or assume what the subagent will find — wait for its " + "returned result and act on what it actually reports.";
37053
37098
  }
37054
37099
  var init_prompt = () => {};
37055
37100
 
@@ -37091,9 +37136,72 @@ async function runAgent(args) {
37091
37136
  turns: loopResult.turns
37092
37137
  };
37093
37138
  }
37139
+ function wrapPermissionGateForBackground(gate, onNeedsInput) {
37140
+ if (!gate)
37141
+ return;
37142
+ return async (tool, input, callContext) => {
37143
+ const verdict = await gate(tool, input, callContext);
37144
+ if (verdict.ask) {
37145
+ onNeedsInput({
37146
+ toolName: tool.name,
37147
+ reason: verdict.reason
37148
+ });
37149
+ }
37150
+ return verdict;
37151
+ };
37152
+ }
37153
+ async function runAsyncAgentLifecycle(args) {
37154
+ const { description, toolUseId, signal, agentId } = args;
37155
+ const wrappedCheckPermission = wrapPermissionGateForBackground(args.checkPermission, (req) => {
37156
+ enqueueAgentNotification({
37157
+ taskId: agentId,
37158
+ description,
37159
+ status: "needs_input",
37160
+ inputRequest: `Permission required for ${req.toolName}${req.reason ? `: ${req.reason}` : ""}`,
37161
+ ...toolUseId ? { toolUseId } : {}
37162
+ });
37163
+ });
37164
+ try {
37165
+ const { result } = await runAgent({
37166
+ ...args,
37167
+ checkPermission: wrappedCheckPermission
37168
+ });
37169
+ const finalMessage = result.content.map((b) => b.text).join("");
37170
+ enqueueAgentNotification({
37171
+ taskId: agentId,
37172
+ description,
37173
+ status: "completed",
37174
+ finalMessage: finalMessage || undefined,
37175
+ usage: {
37176
+ totalTokens: result.totalTokens,
37177
+ toolUses: result.totalToolUseCount,
37178
+ durationMs: result.totalDurationMs
37179
+ },
37180
+ ...toolUseId ? { toolUseId } : {}
37181
+ });
37182
+ } catch (err) {
37183
+ if (signal?.aborted) {
37184
+ enqueueAgentNotification({
37185
+ taskId: agentId,
37186
+ description,
37187
+ status: "killed",
37188
+ ...toolUseId ? { toolUseId } : {}
37189
+ });
37190
+ return;
37191
+ }
37192
+ enqueueAgentNotification({
37193
+ taskId: agentId,
37194
+ description,
37195
+ status: "failed",
37196
+ error: err instanceof Error ? err.message : String(err),
37197
+ ...toolUseId ? { toolUseId } : {}
37198
+ });
37199
+ }
37200
+ }
37094
37201
  var init_runAgent = __esm(() => {
37095
37202
  init_query2();
37096
37203
  init_agentToolUtils();
37204
+ init_localAgentTask();
37097
37205
  });
37098
37206
 
37099
37207
  // src/engine/tools/agent/AgentTool.ts
@@ -37119,6 +37227,8 @@ var init_AgentTool = __esm(() => {
37119
37227
  init_prompt();
37120
37228
  init_runAgent();
37121
37229
  init_coordinator();
37230
+ init_task2();
37231
+ init_localAgentTask();
37122
37232
  AGENT_TOOL_INPUT_SCHEMA = {
37123
37233
  type: "object",
37124
37234
  properties: {
@@ -37137,6 +37247,10 @@ var init_AgentTool = __esm(() => {
37137
37247
  model: {
37138
37248
  enum: ["small", "premium", "fast"],
37139
37249
  description: "Optional model override for this agent. Takes precedence over the agent definition's model. If omitted, inherits from the parent."
37250
+ },
37251
+ run_in_background: {
37252
+ type: "boolean",
37253
+ description: "Set to true to run this agent in the background. You will be notified when it completes."
37140
37254
  }
37141
37255
  },
37142
37256
  required: ["description", "prompt"]
@@ -37173,6 +37287,13 @@ var init_AgentTool = __esm(() => {
37173
37287
  ` + text
37174
37288
  };
37175
37289
  }
37290
+ if (c && c.status === "async_launched") {
37291
+ return {
37292
+ type: "tool_result",
37293
+ tool_use_id: toolUseID,
37294
+ content: "[agent launched in background] agentId=" + (c.agentId ?? "") + " output=" + (c.outputFile ?? "")
37295
+ };
37296
+ }
37176
37297
  return {
37177
37298
  type: "tool_result",
37178
37299
  tool_use_id: toolUseID,
@@ -37190,6 +37311,38 @@ var init_AgentTool = __esm(() => {
37190
37311
  const allowFanOut = isCoordinatorMode() && childSpawnDepth < MAX_WORKER_SPAWN_DEPTH;
37191
37312
  const resolvedTools = resolveAgentTools(agentDefinition, availableTools, allowFanOut).resolvedTools;
37192
37313
  const agentId = "agent-" + randomUUID5();
37314
+ if (input.run_in_background) {
37315
+ const outputFile = getTaskOutputPath(agentId);
37316
+ runAsyncAgentLifecycle({
37317
+ agentDefinition,
37318
+ prompt: input.prompt,
37319
+ tools: resolvedTools,
37320
+ modelProvider,
37321
+ parentRole,
37322
+ overrideRole: input.model,
37323
+ agentId,
37324
+ spawnDepth: childSpawnDepth,
37325
+ signal: ctx.signal,
37326
+ checkPermission: ctx.checkPermission,
37327
+ description: input.description
37328
+ }).catch((err) => {
37329
+ enqueueAgentNotification({
37330
+ taskId: agentId,
37331
+ description: input.description,
37332
+ status: "failed",
37333
+ error: err instanceof Error ? err.message : String(err)
37334
+ });
37335
+ });
37336
+ return {
37337
+ data: {
37338
+ status: "async_launched",
37339
+ agentId,
37340
+ description: input.description,
37341
+ prompt: input.prompt,
37342
+ outputFile
37343
+ }
37344
+ };
37345
+ }
37193
37346
  const { result } = await runAgent({
37194
37347
  agentDefinition,
37195
37348
  prompt: input.prompt,
@@ -79576,24 +79729,27 @@ function enqueueAgentNotification({
79576
79729
  usage,
79577
79730
  toolUseId,
79578
79731
  worktreePath,
79579
- worktreeBranch
79732
+ worktreeBranch,
79733
+ inputRequest
79580
79734
  }) {
79581
- let shouldEnqueue = false;
79582
- updateTaskState(taskId, setAppState, (task) => {
79583
- if (task.notified) {
79584
- return task;
79735
+ if (setAppState && status !== "needs_input") {
79736
+ let shouldEnqueue = false;
79737
+ updateTaskState(taskId, setAppState, (task) => {
79738
+ if (task.notified) {
79739
+ return task;
79740
+ }
79741
+ shouldEnqueue = true;
79742
+ return {
79743
+ ...task,
79744
+ notified: true
79745
+ };
79746
+ });
79747
+ if (!shouldEnqueue) {
79748
+ return;
79585
79749
  }
79586
- shouldEnqueue = true;
79587
- return {
79588
- ...task,
79589
- notified: true
79590
- };
79591
- });
79592
- if (!shouldEnqueue) {
79593
- return;
79594
79750
  }
79595
79751
  const escapedDescription = escapeXml(description);
79596
- const summary = status === "completed" ? `Agent "${escapedDescription}" completed` : status === "failed" ? `Agent "${escapedDescription}" failed: ${escapeXml(error || "Unknown error")}` : `Agent "${escapedDescription}" was stopped`;
79752
+ const summary = status === "completed" ? `Agent "${escapedDescription}" completed` : status === "failed" ? `Agent "${escapedDescription}" failed: ${escapeXml(error || "Unknown error")}` : status === "killed" ? `Agent "${escapedDescription}" was stopped` : status === "needs_input" ? `Agent "${escapedDescription}" needs input: ${escapeXml(inputRequest || "Permission request or question pending")}` : `Agent "${escapedDescription}" ${escapeXml(status)}`;
79597
79753
  const outputPath = getTaskOutputPath(taskId);
79598
79754
  const toolUseIdLine = toolUseId ? `
79599
79755
  <${TOOL_USE_ID_TAG}>${escapeXml(toolUseId)}</${TOOL_USE_ID_TAG}>` : "";
@@ -180576,6 +180732,7 @@ __export(exports_engineCompat, {
180576
180732
  roughTokenCountEstimationForContent: () => roughTokenCountEstimationForContent,
180577
180733
  roughTokenCountEstimationForMessages: () => roughTokenCountEstimationForMessages,
180578
180734
  runAgent: () => runAgent,
180735
+ runAsyncAgentLifecycle: () => runAsyncAgentLifecycle,
180579
180736
  runCleanupFunctions: () => runCleanupFunctions2,
180580
180737
  runHooksStream: () => runHooksStream,
180581
180738
  runPostCompactCleanup: () => runPostCompactCleanup,
@@ -180667,6 +180824,7 @@ __export(exports_engineCompat, {
180667
180824
  waitForSessionMemoryExtraction: () => waitForSessionMemoryExtraction,
180668
180825
  waitForTeammatesToBecomeIdle: () => waitForTeammatesToBecomeIdle,
180669
180826
  worktreeBranchName: () => worktreeBranchName,
180827
+ wrapPermissionGateForBackground: () => wrapPermissionGateForBackground,
180670
180828
  writeCronTasks: () => writeCronTasks,
180671
180829
  writeToMailbox: () => writeToMailbox
180672
180830
  });
@@ -275816,7 +275974,7 @@ function extractPartialResult(messages) {
275816
275974
  }
275817
275975
  return;
275818
275976
  }
275819
- async function runAsyncAgentLifecycle({
275977
+ async function runAsyncAgentLifecycle2({
275820
275978
  taskId,
275821
275979
  abortController,
275822
275980
  makeStream,
@@ -311087,7 +311245,7 @@ async function resumeAgentBackground({
311087
311245
  invocationEmitted: false
311088
311246
  };
311089
311247
  const wrapWithCwd = (fn) => resumedWorktreePath ? runWithCwdOverride(resumedWorktreePath, fn) : fn();
311090
- runWithAgentContext(asyncAgentContext, () => wrapWithCwd(() => runAsyncAgentLifecycle({
311248
+ runWithAgentContext(asyncAgentContext, () => wrapWithCwd(() => runAsyncAgentLifecycle2({
311091
311249
  taskId: agentBackgroundTask.agentId,
311092
311250
  abortController: agentBackgroundTask.abortController,
311093
311251
  makeStream: (onCacheSafeParams) => runAgent2({
@@ -321015,6 +321173,10 @@ function buildAgentLoopParams(m) {
321015
321173
  toolUseContext: m.toolUseContext
321016
321174
  }),
321017
321175
  toolContext: m.toolUseContext,
321176
+ hasPendingBackgroundTasks: () => {
321177
+ const tasks = m.toolUseContext?.getAppState?.()?.tasks;
321178
+ return tasks ? hasNonTerminalTasks(tasks) : false;
321179
+ },
321018
321180
  hooks: createLoopHooks({
321019
321181
  options: {
321020
321182
  sessionId: getSessionId(),
@@ -321046,6 +321208,7 @@ function buildAgentLoopParams(m) {
321046
321208
  var init_agentLoopDeps = __esm(() => {
321047
321209
  init_modelprovider2();
321048
321210
  init_engine();
321211
+ init_Task();
321049
321212
  init_settings3();
321050
321213
  init_shared();
321051
321214
  init_bootstrap();
@@ -366288,6 +366451,25 @@ var init_GlimmerMessage = __esm(() => {
366288
366451
  };
366289
366452
  });
366290
366453
 
366454
+ // src/tui/components/Spinner/spinnerGates.ts
366455
+ function getSpinnerDisplayGates(input) {
366456
+ const { verbose, hasRunningTeammates, effectiveElapsedMs } = input;
366457
+ const forceShow = verbose || hasRunningTeammates;
366458
+ const wantsTimer = forceShow || effectiveElapsedMs > SHOW_TIMER_AFTER_MS;
366459
+ return {
366460
+ wantsTimer,
366461
+ wantsTokens: forceShow || effectiveElapsedMs > SHOW_TOKENS_AFTER_MS,
366462
+ wantsStatusIndicator: wantsTimer
366463
+ };
366464
+ }
366465
+ function computeStallState(input) {
366466
+ const { timeSinceLastToken, currentResponseLength, hasActiveTools } = input;
366467
+ const isStalled = timeSinceLastToken > STALL_AFTER_MS && !hasActiveTools && currentResponseLength > 0;
366468
+ const stalledIntensity = isStalled ? Math.min((timeSinceLastToken - STALL_AFTER_MS) / STALL_FADE_MS, 1) : 0;
366469
+ return { isStalled, stalledIntensity };
366470
+ }
366471
+ var SHOW_TIMER_AFTER_MS = 1000, SHOW_TOKENS_AFTER_MS = 5000, STALL_AFTER_MS = 3000, STALL_FADE_MS = 2000;
366472
+
366291
366473
  // src/tui/components/Spinner/useStalledAnimation.ts
366292
366474
  function useStalledAnimation(time, currentResponseLength, hasActiveTools = false, reducedMotion = false) {
366293
366475
  const lastTokenTime = import_react103.useRef(time);
@@ -366310,8 +366492,11 @@ function useStalledAnimation(time, currentResponseLength, hasActiveTools = false
366310
366492
  } else {
366311
366493
  timeSinceLastToken = time - mountTime.current;
366312
366494
  }
366313
- const isStalled = timeSinceLastToken > 3000 && !hasActiveTools;
366314
- const intensity = isStalled ? Math.min((timeSinceLastToken - 3000) / 2000, 1) : 0;
366495
+ const { isStalled, stalledIntensity: intensity } = computeStallState({
366496
+ timeSinceLastToken,
366497
+ currentResponseLength,
366498
+ hasActiveTools
366499
+ });
366315
366500
  if (!reducedMotion && (intensity > 0 || stalledIntensityRef.current > 0)) {
366316
366501
  const dt = time - lastSmoothTime.current;
366317
366502
  if (dt >= 50) {
@@ -366340,17 +366525,6 @@ var init_useStalledAnimation = __esm(() => {
366340
366525
  import_react103 = __toESM(require_react(), 1);
366341
366526
  });
366342
366527
 
366343
- // src/tui/components/Spinner/spinnerGates.ts
366344
- function getSpinnerDisplayGates(input) {
366345
- const { verbose, hasRunningTeammates, effectiveElapsedMs } = input;
366346
- const forceShow = verbose || hasRunningTeammates;
366347
- return {
366348
- wantsTimer: forceShow || effectiveElapsedMs > SHOW_TIMER_AFTER_MS,
366349
- wantsTokens: forceShow || effectiveElapsedMs > SHOW_TOKENS_AFTER_MS
366350
- };
366351
- }
366352
- var SHOW_TIMER_AFTER_MS = 1000, SHOW_TOKENS_AFTER_MS = 5000;
366353
-
366354
366528
  // src/tui/components/Spinner/SpinnerAnimationRow.tsx
366355
366529
  function SpinnerAnimationRow({
366356
366530
  mode,
@@ -366389,7 +366563,8 @@ function SpinnerAnimationRow({
366389
366563
  } = useStalledAnimation(time, currentResponseLength, hasActiveTools || leaderIsIdle, reducedMotion);
366390
366564
  const frame = reducedMotion ? 0 : Math.floor(time / 120);
366391
366565
  const glimmerSpeed = mode === "requesting" ? 50 : 200;
366392
- const glimmerMessageWidth = import_react104.useMemo(() => stringWidth2(message), [message]);
366566
+ const displayMessage = mode === "requesting" ? message + "…" : message;
366567
+ const glimmerMessageWidth = import_react104.useMemo(() => stringWidth2(displayMessage), [displayMessage]);
366393
366568
  const cycleLength = glimmerMessageWidth + 20;
366394
366569
  const cyclePosition = Math.floor(time / glimmerSpeed);
366395
366570
  const glimmerIndex = reducedMotion ? -100 : isStalled ? -100 : mode === "requesting" ? cyclePosition % cycleLength - 10 : glimmerMessageWidth + 10 - cyclePosition % cycleLength;
@@ -366425,7 +366600,7 @@ function SpinnerAnimationRow({
366425
366600
  const messageWidth = glimmerMessageWidth + 2;
366426
366601
  const sep = SEP_WIDTH;
366427
366602
  const wantsThinking = thinkingStatus !== null;
366428
- const { wantsTimer, wantsTokens } = getSpinnerDisplayGates({
366603
+ const { wantsTimer, wantsTokens, wantsStatusIndicator } = getSpinnerDisplayGates({
366429
366604
  verbose,
366430
366605
  hasRunningTeammates,
366431
366606
  effectiveElapsedMs
@@ -366443,7 +366618,8 @@ function SpinnerAnimationRow({
366443
366618
  const showTimer = wantsTimer && availableSpace > usedAfterThinking + timerWidth;
366444
366619
  const usedAfterTimer = usedAfterThinking + (showTimer ? timerWidth + sep : 0);
366445
366620
  const showTokens = wantsTokens && totalTokens > 0 && availableSpace > usedAfterTimer + tokensWidth;
366446
- const thinkingOnly = showThinking && thinkingStatus === "thinking" && !spinnerSuffix && !showTimer && !showTokens && true;
366621
+ const showStatusIndicator = !showTokens && wantsStatusIndicator && mode === "requesting" && !hasRunningTeammates && availableSpace > usedAfterTimer + 2;
366622
+ const thinkingOnly = showThinking && thinkingStatus === "thinking" && !spinnerSuffix && !showTimer && !showTokens && !showStatusIndicator && true;
366447
366623
  const thinkingElapsedSec = (time - THINKING_DELAY_MS) / 1000;
366448
366624
  const thinkingOpacity = time < THINKING_DELAY_MS ? 0 : (Math.sin(thinkingElapsedSec * Math.PI * 2 / THINKING_GLOW_PERIOD_S) + 1) / 2;
366449
366625
  const thinkingShimmerColor = toRGBColor(interpolateColor(THINKING_INACTIVE, THINKING_INACTIVE_SHIMMER, thinkingOpacity));
@@ -366467,7 +366643,9 @@ function SpinnerAnimationRow({
366467
366643
  ]
366468
366644
  }, undefined, true, undefined, this)
366469
366645
  ]
366470
- }, "tokens", true, undefined, this)] : [], ...showThinking && thinkingText ? [thinkingStatus === "thinking" && !reducedMotion ? /* @__PURE__ */ jsx_dev_runtime184.jsxDEV(ThemedText, {
366646
+ }, "tokens", true, undefined, this)] : [], ...showStatusIndicator ? [/* @__PURE__ */ jsx_dev_runtime184.jsxDEV(SpinnerModeGlyph, {
366647
+ mode
366648
+ }, "statusGlyph", false, undefined, this)] : [], ...showThinking && thinkingText ? [thinkingStatus === "thinking" && !reducedMotion ? /* @__PURE__ */ jsx_dev_runtime184.jsxDEV(ThemedText, {
366471
366649
  color: thinkingShimmerColor,
366472
366650
  children: thinkingOnly ? `(${thinkingText})` : thinkingText
366473
366651
  }, "thinking", false, undefined, this) : /* @__PURE__ */ jsx_dev_runtime184.jsxDEV(ThemedText, {
@@ -366521,7 +366699,7 @@ function SpinnerAnimationRow({
366521
366699
  time
366522
366700
  }, undefined, false, undefined, this),
366523
366701
  /* @__PURE__ */ jsx_dev_runtime184.jsxDEV(GlimmerMessage, {
366524
- message,
366702
+ message: displayMessage,
366525
366703
  mode,
366526
366704
  messageColor,
366527
366705
  glimmerIndex,
@@ -425223,6 +425401,9 @@ import { randomBytes as randomBytes22 } from "crypto";
425223
425401
  function isTerminalTaskStatus2(status) {
425224
425402
  return status === "completed" || status === "failed" || status === "killed";
425225
425403
  }
425404
+ function hasNonTerminalTasks(tasks) {
425405
+ return Object.values(tasks).some((t) => !isTerminalTaskStatus2(t.status));
425406
+ }
425226
425407
  function getTaskIdPrefix(type) {
425227
425408
  return TASK_ID_PREFIXES[type] ?? "x";
425228
425409
  }
@@ -479281,7 +479462,8 @@ Error: sandbox required but unavailable: ${reason}
479281
479462
  } catch (error) {
479282
479463
  logError3(error);
479283
479464
  const llmTimeoutHint = llmTimeoutRemediationHint(error, getCurrentLlmTimeoutMs());
479284
- const gwHint = gatewayUnreachableRemediationHint(error);
479465
+ const endpointLabel = getCurrentEndpointLabel(mainLoopModelParam);
479466
+ const gwHint = gatewayUnreachableRemediationHint(error, endpointLabel);
479285
479467
  setMessages((prev) => [...prev, createSystemMessage(`本轮执行出错:${errorMessage2(error)}。${llmTimeoutHint ? `${llmTimeoutHint} ` : ""}${gwHint ? `${gwHint} ` : ""}请重试。`, "error")]);
479286
479468
  } finally {
479287
479469
  if (queryGuard.end(thisGeneration)) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@atlasharness/atlascode",
3
- "version": "0.1.63",
3
+ "version": "0.1.65",
4
4
  "description": "AtlasCode \u2014 Coding Agent for the domestic computing ecosystem (Ascend NPU + domestic LLM backends)",
5
5
  "bin": {
6
6
  "atlas": "dist/cli.js",