@atlasharness/atlascode 0.1.68 → 0.1.69

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 (3) hide show
  1. package/README.md +18 -3
  2. package/dist/cli.js +259 -112
  3. package/package.json +1 -1
package/README.md CHANGED
@@ -5,8 +5,8 @@
5
5
  (OpenAI-protocol 静态键车道,任意 OpenAI-compatible 端点)与国产平台工具链预留
6
6
  (Ascend NPU 域包为可插拔叠加层,W6 起接入)。
7
7
 
8
- > 版本现状:G-α 前置阶段(v0.1.0 发布待 W2–W4 闭环 + P-1 远端仓库,见
9
- > `docs/roadmap-domestic-and-residuals.md`)。
8
+ > 版本现状:v0.1.x 持续发布(npm `@atlasharness/atlascode` live,P-1 远端仓已解除,
9
+ > 见 `docs/roadmap-domestic-and-residuals.md`)。
10
10
 
11
11
  ## 安装
12
12
 
@@ -20,7 +20,22 @@ npm install -g @atlasharness/atlascode
20
20
  atlascode --help # 别名 `atlas` 同效
21
21
  ```
22
22
 
23
- **② git 源码**(前置:`git` + [bun](https://bun.sh)(构建)+ `node`(运行))
23
+ **Windows(PowerShell / cmd)**
24
+
25
+ ```powershell
26
+ # npm 通道(与 Unix 同款,仅需 Node ≥ 20)
27
+ npm install -g @atlasharness/atlascode
28
+ atlascode --help # 别名 `atlas` 同效
29
+ ```
30
+
31
+ > - 装完 `atlascode`/`atlas` 不识别 → 重开终端(或把 npm 全局 bin 目录加入 `PATH`)。
32
+ > - git 源码通道 `./install.sh` 为 Unix shell 脚本,Windows 不可直接用;Windows 走 npm 通道,
33
+ > 或手动 `git clone <repo-url>` + [bun](https://bun.sh)(`bun install && bun run build`)。
34
+ > - 镜像 registry(如 npmmirror)超时/403 时切官方源:
35
+ > `npm install -g @atlasharness/atlascode --registry https://registry.npmjs.org`
36
+ > (Windows 多 OS 波 0.1.43 已验 npm 通道安装 + 启动链)。
37
+
38
+ **② git 源码**(Unix;前置:`git` + [bun](https://bun.sh)(构建)+ `node`(运行))
24
39
 
25
40
  ```bash
26
41
  ./install.sh [repo-url]
package/dist/cli.js CHANGED
@@ -81394,7 +81394,17 @@ REMINDER: Do NOT call any tools. Respond with plain text only — ` + "an <analy
81394
81394
  });
81395
81395
 
81396
81396
  // src/engine/context/autoCompactWindow.ts
81397
- function resolveAutoCompactWindow(setting) {
81397
+ function isAutoCompactWindowSetting(x) {
81398
+ return typeof x === "object" && x !== null && "kind" in x;
81399
+ }
81400
+ function normalizeAutoCompactWindowSetting(raw) {
81401
+ if (!raw)
81402
+ return {};
81403
+ if (isAutoCompactWindowSetting(raw))
81404
+ return { default: raw };
81405
+ return raw;
81406
+ }
81407
+ function resolveAutoCompactWindowSingle(setting) {
81398
81408
  if (!setting || setting.kind === "auto") {
81399
81409
  return {};
81400
81410
  }
@@ -81412,6 +81422,11 @@ function resolveAutoCompactWindow(setting) {
81412
81422
  }
81413
81423
  return {};
81414
81424
  }
81425
+ function resolveAutoCompactWindow(setting, model) {
81426
+ const perModel = normalizeAutoCompactWindowSetting(setting);
81427
+ const chosen = model && perModel[model] || perModel.default;
81428
+ return resolveAutoCompactWindowSingle(chosen);
81429
+ }
81415
81430
  function parseAutoCompactTierInput(raw) {
81416
81431
  const s = raw.trim();
81417
81432
  if (s === "") {
@@ -81464,16 +81479,16 @@ function setAutoCompactSettingsSource(next) {
81464
81479
  function setAutoCompactWindowSettingsSource(next) {
81465
81480
  autoCompactWindowSettingsSource = next;
81466
81481
  }
81467
- function mergeAutoCompactOverrides(env, setting) {
81468
- const tier = resolveAutoCompactWindow(setting);
81482
+ function mergeAutoCompactOverrides(env, setting, model) {
81483
+ const tier = resolveAutoCompactWindow(setting, model);
81469
81484
  return {
81470
81485
  pctOverride: env.pctOverride ?? tier.pctOverride,
81471
81486
  windowOverride: env.windowOverride ?? tier.windowOverride,
81472
81487
  autoCompactDisabled: env.disabled === true || env.autoCompactDisabled === true || tier.autoCompactDisabled === true
81473
81488
  };
81474
81489
  }
81475
- function getMergedAutoCompactOverrides() {
81476
- return mergeAutoCompactOverrides(getAutoCompactEnvOverrides(), autoCompactWindowSettingsSource?.() ?? null);
81490
+ function getMergedAutoCompactOverrides(model) {
81491
+ return mergeAutoCompactOverrides(getAutoCompactEnvOverrides(), autoCompactWindowSettingsSource?.() ?? null, model);
81477
81492
  }
81478
81493
  function getEffectiveContextWindowSizeCore(contextWindow, maxOutputTokens, windowOverride) {
81479
81494
  const window2 = windowOverride !== undefined && windowOverride > 0 ? Math.min(contextWindow, windowOverride) : contextWindow;
@@ -81482,7 +81497,7 @@ function getEffectiveContextWindowSizeCore(contextWindow, maxOutputTokens, windo
81482
81497
  }
81483
81498
  function getEffectiveContextWindowSize(contextWindowOrModel, maxOutputTokens, windowOverride) {
81484
81499
  if (typeof contextWindowOrModel === "string") {
81485
- const { windowOverride } = getMergedAutoCompactOverrides();
81500
+ const { windowOverride } = getMergedAutoCompactOverrides(contextWindowOrModel);
81486
81501
  return getEffectiveContextWindowSizeCore(resolveModelContextWindow(contextWindowOrModel), undefined, windowOverride);
81487
81502
  }
81488
81503
  return getEffectiveContextWindowSizeCore(contextWindowOrModel, maxOutputTokens, windowOverride);
@@ -81497,7 +81512,7 @@ function getAutoCompactThresholdCore(contextWindow, maxOutputTokens, pctOverride
81497
81512
  }
81498
81513
  function getAutoCompactThreshold(contextWindowOrModel, maxOutputTokens, pctOverride, windowOverride) {
81499
81514
  if (typeof contextWindowOrModel === "string") {
81500
- const o = getMergedAutoCompactOverrides();
81515
+ const o = getMergedAutoCompactOverrides(contextWindowOrModel);
81501
81516
  return getAutoCompactThresholdCore(resolveModelContextWindow(contextWindowOrModel), undefined, o.pctOverride, o.windowOverride);
81502
81517
  }
81503
81518
  return getAutoCompactThresholdCore(contextWindowOrModel, maxOutputTokens, pctOverride, windowOverride);
@@ -81508,10 +81523,10 @@ function isAutoCompactThresholdPositive(contextWindow, maxOutputTokens, pctOverr
81508
81523
  function calculateTokenWarningState(tokenUsage, paramsOrModel) {
81509
81524
  if (typeof paramsOrModel === "string") {
81510
81525
  const env = getAutoCompactEnvOverrides();
81511
- const o = getMergedAutoCompactOverrides();
81526
+ const o = getMergedAutoCompactOverrides(paramsOrModel);
81512
81527
  return calculateTokenWarningStateCore(tokenUsage, {
81513
81528
  contextWindow: resolveModelContextWindow(paramsOrModel),
81514
- autoCompactEnabled: isAutoCompactEnabled(),
81529
+ autoCompactEnabled: isAutoCompactEnabledForModel(paramsOrModel),
81515
81530
  pctOverride: o.pctOverride,
81516
81531
  windowOverride: o.windowOverride,
81517
81532
  blockingLimitOverride: env.blockingLimitOverride
@@ -81570,6 +81585,17 @@ function isAutoCompactEnabled(flags) {
81570
81585
  return false;
81571
81586
  return flags.settingsEnabled !== false;
81572
81587
  }
81588
+ function isAutoCompactEnabledForModel(model) {
81589
+ const o = getAutoCompactEnvOverrides();
81590
+ if (o.disabled)
81591
+ return false;
81592
+ if (o.autoCompactDisabled)
81593
+ return false;
81594
+ if (getMergedAutoCompactOverrides(model).autoCompactDisabled) {
81595
+ return false;
81596
+ }
81597
+ return autoCompactSettingsSource ? autoCompactSettingsSource() ?? true : true;
81598
+ }
81573
81599
  async function shouldAutoCompact(messages, deps) {
81574
81600
  if (deps.querySource === "compact" || deps.querySource === "session_memory") {
81575
81601
  return false;
@@ -123897,7 +123923,7 @@ var init_internalWrites = __esm(() => {
123897
123923
  timestamps = new Map;
123898
123924
  });
123899
123925
  // src/tui/utils/settings/types.ts
123900
- var isMcpServerCommandEntry = () => ({}), isMcpServerNameEntry = () => ({}), isMcpServerUrlEntry = () => ({}), SettingsSchema2 = () => object({
123926
+ var isMcpServerCommandEntry = () => ({}), isMcpServerNameEntry = () => ({}), isMcpServerUrlEntry = () => ({}), autoCompactWindowSettingSchema, SettingsSchema2 = () => object({
123901
123927
  model: string2().optional(),
123902
123928
  modelRoles: record(string2(), any()).optional(),
123903
123929
  defaultRole: string2().optional(),
@@ -123940,11 +123966,9 @@ var isMcpServerCommandEntry = () => ({}), isMcpServerNameEntry = () => ({}), isM
123940
123966
  language: string2().optional(),
123941
123967
  theme: string2().optional(),
123942
123968
  tui: object({ fullscreen: boolean2().optional() }).optional(),
123943
- autoCompactWindow: discriminatedUnion("kind", [
123944
- object({ kind: literal("auto") }),
123945
- object({ kind: literal("off") }),
123946
- object({ kind: literal("window"), tokens: number2().int().min(1000) }),
123947
- object({ kind: literal("pct"), pct: number2().min(1).max(100) })
123969
+ autoCompactWindow: union([
123970
+ autoCompactWindowSettingSchema,
123971
+ record(string2(), autoCompactWindowSettingSchema)
123948
123972
  ]).optional(),
123949
123973
  llmTimeoutMs: number2().int().positive().optional(),
123950
123974
  prefersReducedMotion: boolean2().optional(),
@@ -123983,6 +124007,12 @@ var isMcpServerCommandEntry = () => ({}), isMcpServerNameEntry = () => ({}), isM
123983
124007
  }).passthrough(), CUSTOMIZATION_SURFACES;
123984
124008
  var init_types7 = __esm(() => {
123985
124009
  init_zod();
124010
+ autoCompactWindowSettingSchema = discriminatedUnion("kind", [
124011
+ object({ kind: literal("auto") }),
124012
+ object({ kind: literal("off") }),
124013
+ object({ kind: literal("window"), tokens: number2().int().min(1000) }),
124014
+ object({ kind: literal("pct"), pct: number2().min(1).max(100) })
124015
+ ]);
123986
124016
  CUSTOMIZATION_SURFACES = ["mcp", "command", "agent"];
123987
124017
  });
123988
124018
 
@@ -180679,7 +180709,9 @@ __export(exports_engineCompat, {
180679
180709
  isAscendToolsEnabled: () => isAscendToolsEnabled,
180680
180710
  isAutoCompactCircuitTripped: () => isAutoCompactCircuitTripped,
180681
180711
  isAutoCompactEnabled: () => isAutoCompactEnabled,
180712
+ isAutoCompactEnabledForModel: () => isAutoCompactEnabledForModel,
180682
180713
  isAutoCompactThresholdPositive: () => isAutoCompactThresholdPositive,
180714
+ isAutoCompactWindowSetting: () => isAutoCompactWindowSetting,
180683
180715
  isAutoModeGateEnabled: () => isAutoModeGateEnabled,
180684
180716
  isBuiltInAgent: () => isBuiltInAgent,
180685
180717
  isBypassPermissionsModeDisabled: () => isBypassPermissionsModeDisabled,
@@ -180780,6 +180812,7 @@ __export(exports_engineCompat, {
180780
180812
  mergeWith: () => mergeWith,
180781
180813
  microcompactMessages: () => microcompactMessages,
180782
180814
  nextCronRunMs: () => nextCronRunMs,
180815
+ normalizeAutoCompactWindowSetting: () => normalizeAutoCompactWindowSetting,
180783
180816
  normalizeControlMessageKeys: () => normalizeControlMessageKeys,
180784
180817
  normalizeNameForMCP: () => normalizeNameForMCP2,
180785
180818
  notifyTasksUpdated: () => notifyTasksUpdated,
@@ -321290,7 +321323,7 @@ function buildAgentLoopParams(m) {
321290
321323
  const resolved = pool.length > 0 ? resolveModel(pool[0]) : undefined;
321291
321324
  const toolList = m.tools;
321292
321325
  const countTokens = (msgs) => modelProvider.countTokens(role, sessionModel, msgs, toolList);
321293
- const mergedAutoCompact = mergeAutoCompactOverrides(getAutoCompactEnvOverrides(), getInitialSettings2().autoCompactWindow);
321326
+ const mergedAutoCompact = mergeAutoCompactOverrides(getAutoCompactEnvOverrides(), getInitialSettings2().autoCompactWindow, mainLoopModel);
321294
321327
  const autoCompact = {
321295
321328
  contextWindow: resolved?.contextWindow ?? HARD_DEFAULT_CONTEXT_WINDOW,
321296
321329
  maxOutputTokens: resolved?.maxTokens,
@@ -325748,7 +325781,7 @@ async function analyzeContextUsage(messages, model, getToolPermissionContext, to
325748
325781
  const skillInfo = skillResult.skillInfo;
325749
325782
  const skillFrontmatterTokens = skillInfo.skillFrontmatter.reduce((sum, skill) => sum + skill.tokens, 0);
325750
325783
  const messageTokens = messageBreakdown.totalTokens;
325751
- const isAutoCompact = isAutoCompactEnabled();
325784
+ const isAutoCompact = isAutoCompactEnabledForModel(model);
325752
325785
  const autoCompactThreshold = isAutoCompact ? getEffectiveContextWindowSize(model) - AUTOCOMPACT_BUFFER_TOKENS : undefined;
325753
325786
  const cats = [];
325754
325787
  if (systemPromptTokens > 0) {
@@ -329411,7 +329444,7 @@ function getCompactionReminderAttachment(messages, model) {
329411
329444
  if (!getFeatureValue_CACHED_MAY_BE_STALE("atlas_marble_fox", false)) {
329412
329445
  return [];
329413
329446
  }
329414
- if (!isAutoCompactEnabled()) {
329447
+ if (!isAutoCompactEnabledForModel(model)) {
329415
329448
  return [];
329416
329449
  }
329417
329450
  const contextWindow = getContextWindowForModel(model, getSdkBetas());
@@ -337311,6 +337344,13 @@ ${attachment.snippet}`,
337311
337344
  isMeta: true
337312
337345
  })
337313
337346
  ]);
337347
+ case "git_status_refresh":
337348
+ return wrapMessagesInSystemReminder([
337349
+ createUserMessage2({
337350
+ content: attachment.status,
337351
+ isMeta: true
337352
+ })
337353
+ ]);
337314
337354
  case "file": {
337315
337355
  const fileContent = attachment.content;
337316
337356
  switch (fileContent.type) {
@@ -349063,6 +349103,10 @@ var exports_autocompact = {};
349063
349103
  __export(exports_autocompact, {
349064
349104
  call: () => call9
349065
349105
  });
349106
+ function currentTierFor(raw, model) {
349107
+ const map = normalizeAutoCompactWindowSetting(raw);
349108
+ return map[model] ?? map.default;
349109
+ }
349066
349110
  function currentToOptionValue(setting) {
349067
349111
  if (!setting || setting.kind === "auto")
349068
349112
  return "auto";
@@ -349079,21 +349123,25 @@ function customInitialValue(setting) {
349079
349123
  }
349080
349124
  return setting.kind === "window" ? `${setting.tokens / 1000}k` : `${setting.pct}%`;
349081
349125
  }
349082
- function describeTier(setting) {
349126
+ function describeTier(setting, model) {
349127
+ const label = ` [${renderModelName(model)}]`;
349083
349128
  switch (setting.kind) {
349084
349129
  case "auto":
349085
- return "Auto-compact: Auto (default) — compact near the model window limit";
349130
+ return `Auto-compact: Auto (default)${label} — compact near the model window limit`;
349086
349131
  case "off":
349087
- return "Auto-compact: Off (manual /compact still works)";
349132
+ return `Auto-compact: Off${label} (manual /compact still works)`;
349088
349133
  case "window":
349089
- return `Auto-compact window: ${setting.tokens / 1000}k tokens`;
349134
+ return `Auto-compact window: ${setting.tokens / 1000}k tokens${label}`;
349090
349135
  case "pct":
349091
- return `Auto-compact threshold: ${setting.pct}% of the effective window`;
349136
+ return `Auto-compact threshold: ${setting.pct}% of the effective window${label}`;
349092
349137
  }
349093
349138
  }
349094
- function persistTier(setting, setAppState, onDone) {
349139
+ function persistTier(setting, model, setAppState, onDone) {
349140
+ const map = normalizeAutoCompactWindowSetting(getInitialSettings2().autoCompactWindow);
349141
+ map[model] = setting;
349142
+ const mapForSettings = map;
349095
349143
  const { error } = updateSettingsForSource2("userSettings", {
349096
- autoCompactWindow: setting
349144
+ autoCompactWindow: mapForSettings
349097
349145
  });
349098
349146
  if (error) {
349099
349147
  onDone(`Failed to persist auto-compact tier: ${error.message}`, {
@@ -349103,9 +349151,9 @@ function persistTier(setting, setAppState, onDone) {
349103
349151
  }
349104
349152
  setAppState((prev) => ({
349105
349153
  ...prev,
349106
- settings: { ...prev.settings, autoCompactWindow: setting }
349154
+ settings: { ...prev.settings, autoCompactWindow: mapForSettings }
349107
349155
  }));
349108
- onDone(describeTier(setting));
349156
+ onDone(describeTier(setting, model));
349109
349157
  }
349110
349158
  function AutoCompactApply({
349111
349159
  setting,
@@ -349113,34 +349161,23 @@ function AutoCompactApply({
349113
349161
  }) {
349114
349162
  const setAppState = useSetAppState();
349115
349163
  const doneRef = React41.useRef(false);
349164
+ const model = getMainLoopModel();
349116
349165
  React41.useEffect(() => {
349117
349166
  if (doneRef.current) {
349118
349167
  return;
349119
349168
  }
349120
349169
  doneRef.current = true;
349121
- persistTier(setting, setAppState, onDone);
349122
- }, [setting, onDone, setAppState]);
349170
+ persistTier(setting, model, setAppState, onDone);
349171
+ }, [setting, model, onDone, setAppState]);
349123
349172
  return null;
349124
349173
  }
349125
349174
  function AutoCompactCommand({ onDone }) {
349126
349175
  const setAppState = useSetAppState();
349176
+ const model = getMainLoopModel();
349127
349177
  const current = useAppState((s) => s.settings.autoCompactWindow);
349128
349178
  const [inputError, setInputError] = React41.useState(null);
349129
349179
  const apply = (setting) => {
349130
- const { error } = updateSettingsForSource2("userSettings", {
349131
- autoCompactWindow: setting
349132
- });
349133
- if (error) {
349134
- onDone(`Failed to persist auto-compact tier: ${error.message}`, {
349135
- display: "system"
349136
- });
349137
- return;
349138
- }
349139
- setAppState((prev) => ({
349140
- ...prev,
349141
- settings: { ...prev.settings, autoCompactWindow: setting }
349142
- }));
349143
- onDone(describeTier(setting));
349180
+ persistTier(setting, model, setAppState, onDone);
349144
349181
  };
349145
349182
  const options = [
349146
349183
  {
@@ -349158,7 +349195,7 @@ function AutoCompactCommand({ onDone }) {
349158
349195
  value: "custom",
349159
349196
  type: "input",
349160
349197
  placeholder: "e.g. 150k (window) or 75% (bare number = percent)",
349161
- initialValue: customInitialValue(current),
349198
+ initialValue: customInitialValue(currentTierFor(current, model)),
349162
349199
  onChange: (raw) => {
349163
349200
  const parsed = parseAutoCompactTierInput(raw);
349164
349201
  if (!parsed) {
@@ -349180,10 +349217,10 @@ function AutoCompactCommand({ onDone }) {
349180
349217
  children: [
349181
349218
  /* @__PURE__ */ jsx_dev_runtime140.jsxDEV(ThemedText, {
349182
349219
  bold: true,
349183
- children: "Auto-compact window tier"
349220
+ children: `Auto-compact window tier — ${renderModelName(model)}`
349184
349221
  }, undefined, false, undefined, this),
349185
349222
  /* @__PURE__ */ jsx_dev_runtime140.jsxDEV(Select, {
349186
- defaultValue: currentToOptionValue(current),
349223
+ defaultValue: currentToOptionValue(currentTierFor(current, model)),
349187
349224
  options,
349188
349225
  onChange: (value) => {
349189
349226
  if (value === "auto") {
@@ -349227,6 +349264,7 @@ var init_autocompact = __esm(() => {
349227
349264
  init_CustomSelect();
349228
349265
  init_ink2();
349229
349266
  init_AppState();
349267
+ init_model();
349230
349268
  init_settings3();
349231
349269
  init_engine();
349232
349270
  React41 = __toESM(require_react(), 1);
@@ -374960,6 +374998,7 @@ var init_nullRenderingAttachments = __esm(() => {
374960
374998
  "critical_system_reminder",
374961
374999
  "edited_image_file",
374962
375000
  "edited_text_file",
375001
+ "git_status_refresh",
374963
375002
  "opened_file_in_ide",
374964
375003
  "output_style",
374965
375004
  "plan_mode",
@@ -432146,7 +432185,8 @@ async function streamCompactSummary({
432146
432185
  appState,
432147
432186
  context,
432148
432187
  preCompactTokenCount,
432149
- cacheSafeParams
432188
+ cacheSafeParams,
432189
+ modelOverride
432150
432190
  }) {
432151
432191
  const promptCacheSharingEnabled = getFeatureValue_CACHED_MAY_BE_STALE("atlas_compact_cache_prefix", true);
432152
432192
  const activityInterval = isSessionActivityTrackingActive() ? setInterval((statusSetter) => {
@@ -432154,7 +432194,7 @@ async function streamCompactSummary({
432154
432194
  statusSetter?.("compacting");
432155
432195
  }, 30000, context.setSDKStatus) : undefined;
432156
432196
  try {
432157
- if (promptCacheSharingEnabled) {
432197
+ if (promptCacheSharingEnabled && !modelOverride) {
432158
432198
  try {
432159
432199
  const result = await runForkedAgent({
432160
432200
  promptMessages: [summaryRequest],
@@ -432179,11 +432219,12 @@ async function streamCompactSummary({
432179
432219
  }
432180
432220
  const retryEnabled = getFeatureValue_CACHED_MAY_BE_STALE("atlas_compact_streaming_retry", false);
432181
432221
  const maxAttempts = retryEnabled ? MAX_COMPACT_STREAMING_RETRIES : 1;
432222
+ const compactModel = modelOverride ?? context.options.mainLoopModel;
432182
432223
  for (let attempt = 1;attempt <= maxAttempts; attempt++) {
432183
432224
  let hasStartedStreaming = false;
432184
432225
  let response;
432185
432226
  context.setResponseLength?.(() => 0);
432186
- const useToolSearch = await isToolSearchEnabled(context.options.mainLoopModel, context.options.tools, async () => appState.toolPermissionContext, context.options.agentDefinitions.activeAgents, "compact");
432227
+ const useToolSearch = await isToolSearchEnabled(compactModel, context.options.tools, async () => appState.toolPermissionContext, context.options.agentDefinitions.activeAgents, "compact");
432187
432228
  const tools = useToolSearch ? uniqBy_default([
432188
432229
  FileReadTool,
432189
432230
  ToolSearchTool2,
@@ -432193,7 +432234,6 @@ async function streamCompactSummary({
432193
432234
  ...getMessagesAfterCompactBoundary(messages),
432194
432235
  summaryRequest
432195
432236
  ])), context.options.tools);
432196
- const compactModel = context.options.mainLoopModel;
432197
432237
  const compactRole = modelToRole(compactModel);
432198
432238
  const params = await buildOpenAIParams({
432199
432239
  messages: compactMessages,
@@ -432283,6 +432323,23 @@ async function createPostCompactFileAttachments(readFileState, toolUseContext, m
432283
432323
  return false;
432284
432324
  });
432285
432325
  }
432326
+ async function createCurrentGitStatusAttachment() {
432327
+ const baseline = getSessionStartGitStatusBlocks();
432328
+ if (!baseline) {
432329
+ return null;
432330
+ }
432331
+ const fresh = await getGitStatusFresh();
432332
+ if (!fresh) {
432333
+ return null;
432334
+ }
432335
+ if (JSON.stringify(fresh.blocks) === JSON.stringify(baseline)) {
432336
+ return null;
432337
+ }
432338
+ return createAttachmentMessage({
432339
+ type: "git_status_refresh",
432340
+ status: fresh.text
432341
+ });
432342
+ }
432286
432343
  function createPlanAttachmentIfNeeded(agentId) {
432287
432344
  const planContent = getPlan2(agentId);
432288
432345
  if (!planContent) {
@@ -432423,6 +432480,7 @@ var init_compact4 = __esm(() => {
432423
432480
  init_attachments();
432424
432481
  init_config6();
432425
432482
  init_context2();
432483
+ init_context5();
432426
432484
  init_debug();
432427
432485
  init_errors4();
432428
432486
  init_fileStateCache();
@@ -432453,6 +432511,62 @@ var init_compact4 = __esm(() => {
432453
432511
  init_prompt22();
432454
432512
  });
432455
432513
 
432514
+ // src/tui/contextBodies/summarizeFallback.ts
432515
+ function isFallbackEligibleError(err) {
432516
+ let msg = "";
432517
+ if (err instanceof Error) {
432518
+ if (err.name === "APIUserAbortError")
432519
+ return false;
432520
+ msg = err.message;
432521
+ } else if (typeof err === "string") {
432522
+ msg = err;
432523
+ } else {
432524
+ return false;
432525
+ }
432526
+ if (msg.includes(PROMPT_TOO_LONG_ERROR_MESSAGE))
432527
+ return false;
432528
+ if (msg.includes("Request was aborted."))
432529
+ return false;
432530
+ return true;
432531
+ }
432532
+ function isFallbackEligibleResult(msg, text) {
432533
+ if (!text)
432534
+ return false;
432535
+ if (text.includes(PROMPT_TOO_LONG_ERROR_MESSAGE))
432536
+ return false;
432537
+ if (text.includes("Request was aborted."))
432538
+ return false;
432539
+ const flagged = typeof msg === "object" && msg !== null && msg.isApiErrorMessage === true;
432540
+ return flagged || startsWithApiErrorPrefix(text);
432541
+ }
432542
+ function createSummarizeWithFallback(primary, opts) {
432543
+ return async (p) => {
432544
+ let result;
432545
+ try {
432546
+ result = await primary(p);
432547
+ } catch (err) {
432548
+ const fb = opts.resolveFallbackModel(p);
432549
+ if (!fb || !isFallbackEligibleError(err)) {
432550
+ throw err;
432551
+ }
432552
+ return primary({ ...p, modelOverride: fb });
432553
+ }
432554
+ if (opts.isEligibleResult?.(result)) {
432555
+ const fb = opts.resolveFallbackModel(p);
432556
+ if (fb) {
432557
+ const retried = await primary({ ...p, modelOverride: fb });
432558
+ if (!opts.isEligibleResult(retried)) {
432559
+ return retried;
432560
+ }
432561
+ }
432562
+ }
432563
+ return result;
432564
+ };
432565
+ }
432566
+ var init_summarizeFallback = __esm(() => {
432567
+ init_modelprovider2();
432568
+ });
432569
+
432456
432570
  // src/tui/services/SessionMemory/prompts.ts
432457
432571
  import { readFile as readFile61 } from "fs/promises";
432458
432572
  import { join as join165 } from "path";
@@ -433012,6 +433126,9 @@ async function composePostCompactAttachments(preCompactReadFileState, context) {
433012
433126
  createAsyncAgentAttachmentsIfNeeded(ctx)
433013
433127
  ]);
433014
433128
  const out = [...fileAttachments, ...asyncAgentAttachments];
433129
+ const gitStatusAttachment = await createCurrentGitStatusAttachment();
433130
+ if (gitStatusAttachment)
433131
+ out.push(gitStatusAttachment);
433015
433132
  const planAttachment = createPlanAttachmentIfNeeded(ctx.agentId);
433016
433133
  if (planAttachment)
433017
433134
  out.push(planAttachment);
@@ -433033,8 +433150,20 @@ async function composePostCompactAttachments(preCompactReadFileState, context) {
433033
433150
  return out;
433034
433151
  }
433035
433152
  function wireContextHostPorts() {
433153
+ const summarizePrimary = (p) => streamCompactSummary(p);
433154
+ const summarizeWithFallback = createSummarizeWithFallback(summarizePrimary, {
433155
+ resolveFallbackModel: (p) => {
433156
+ const fb = getRoleModel("small");
433157
+ if (!fb)
433158
+ return;
433159
+ if (p.context.options.mainLoopModel === fb)
433160
+ return;
433161
+ return fb;
433162
+ },
433163
+ isEligibleResult: (r) => isFallbackEligibleResult(r, getAssistantMessageText2(r))
433164
+ });
433036
433165
  setCompactPorts({
433037
- summarize: (p) => streamCompactSummary({
433166
+ summarize: (p) => summarizeWithFallback({
433038
433167
  messages: p.messages,
433039
433168
  summaryRequest: p.summaryRequest,
433040
433169
  appState: p.context.getAppState(),
@@ -433110,7 +433239,9 @@ var init_contextHostWiring = __esm(() => {
433110
433239
  init_sessionStorage();
433111
433240
  init_betaSessionTracing();
433112
433241
  init_compact4();
433242
+ init_messages3();
433113
433243
  init_compact4();
433244
+ init_summarizeFallback();
433114
433245
  init_sessionMemoryCompact();
433115
433246
  init_compact4();
433116
433247
  });
@@ -434287,7 +434418,77 @@ function setSystemPromptInjection(value) {
434287
434418
  getUserContext.cache.clear?.();
434288
434419
  getSystemContext.cache.clear?.();
434289
434420
  }
434290
- var MAX_STATUS_CHARS = 2000, systemPromptInjection = null, getGitStatus, getSystemContext, getUserContext;
434421
+ async function fetchGitStatusBlocks() {
434422
+ if (false) {}
434423
+ const startTime = Date.now();
434424
+ logForDiagnosticsNoPII("info", "git_status_started");
434425
+ const isGitStart = Date.now();
434426
+ const isGit = await getIsGit();
434427
+ logForDiagnosticsNoPII("info", "git_is_git_check_completed", {
434428
+ duration_ms: Date.now() - isGitStart,
434429
+ is_git: isGit
434430
+ });
434431
+ if (!isGit) {
434432
+ logForDiagnosticsNoPII("info", "git_status_skipped_not_git", {
434433
+ duration_ms: Date.now() - startTime
434434
+ });
434435
+ return null;
434436
+ }
434437
+ try {
434438
+ const gitCmdsStart = Date.now();
434439
+ const [branch, mainBranch, status, log, userName] = await Promise.all([
434440
+ getBranch2(),
434441
+ getDefaultBranch2(),
434442
+ execFileNoThrow3(gitExe2(), ["--no-optional-locks", "status", "--short"], {
434443
+ preserveOutputOnError: false
434444
+ }).then(({ stdout }) => stdout.trim()),
434445
+ execFileNoThrow3(gitExe2(), ["--no-optional-locks", "log", "--oneline", "-n", "5"], {
434446
+ preserveOutputOnError: false
434447
+ }).then(({ stdout }) => stdout.trim()),
434448
+ execFileNoThrow3(gitExe2(), ["config", "user.name"], {
434449
+ preserveOutputOnError: false
434450
+ }).then(({ stdout }) => stdout.trim())
434451
+ ]);
434452
+ logForDiagnosticsNoPII("info", "git_commands_completed", {
434453
+ duration_ms: Date.now() - gitCmdsStart,
434454
+ status_length: status.length
434455
+ });
434456
+ const truncatedStatus = status.length > MAX_STATUS_CHARS ? status.substring(0, MAX_STATUS_CHARS) + `
434457
+ ... (truncated because it exceeds 2k characters. If you need more information, run "git status" using BashTool)` : status;
434458
+ logForDiagnosticsNoPII("info", "git_status_completed", {
434459
+ duration_ms: Date.now() - startTime,
434460
+ truncated: status.length > MAX_STATUS_CHARS
434461
+ });
434462
+ return { branch, mainBranch, status: truncatedStatus, log, userName };
434463
+ } catch (error) {
434464
+ logForDiagnosticsNoPII("error", "git_status_failed", {
434465
+ duration_ms: Date.now() - startTime
434466
+ });
434467
+ logError3(error);
434468
+ return null;
434469
+ }
434470
+ }
434471
+ function formatGitStatus(blocks, header) {
434472
+ return [
434473
+ header,
434474
+ `Current branch: ${blocks.branch}`,
434475
+ `Main branch (you will usually use this for PRs): ${blocks.mainBranch}`,
434476
+ ...blocks.userName ? [`Git user: ${blocks.userName}`] : [],
434477
+ `Status:
434478
+ ${blocks.status || "(clean)"}`,
434479
+ `Recent commits:
434480
+ ${blocks.log}`
434481
+ ].join(`
434482
+
434483
+ `);
434484
+ }
434485
+ function getGitStatusFresh() {
434486
+ return fetchGitStatusBlocks().then((blocks) => blocks ? { text: formatGitStatus(blocks, GIT_STATUS_FRESH_HEADER), blocks } : null);
434487
+ }
434488
+ function getSessionStartGitStatusBlocks() {
434489
+ return sessionStartGitStatusBlocks;
434490
+ }
434491
+ var MAX_STATUS_CHARS = 2000, systemPromptInjection = null, GIT_STATUS_START_HEADER = "This is the git status at the start of the conversation. Note that this status is a snapshot in time, and will not update during the conversation.", GIT_STATUS_FRESH_HEADER = "This is the current git status, re-injected after context compaction. It reflects the working tree as of now and supersedes any earlier session-start snapshot.", sessionStartGitStatusBlocks = null, getGitStatus, getSystemContext, getUserContext;
434291
434492
  var init_context5 = __esm(() => {
434292
434493
  init_shared();
434293
434494
  init_memoize();
@@ -434301,65 +434502,11 @@ var init_context5 = __esm(() => {
434301
434502
  init_gitSettings();
434302
434503
  init_log5();
434303
434504
  getGitStatus = memoize_default(async () => {
434304
- if (false) {}
434305
- const startTime = Date.now();
434306
- logForDiagnosticsNoPII("info", "git_status_started");
434307
- const isGitStart = Date.now();
434308
- const isGit = await getIsGit();
434309
- logForDiagnosticsNoPII("info", "git_is_git_check_completed", {
434310
- duration_ms: Date.now() - isGitStart,
434311
- is_git: isGit
434312
- });
434313
- if (!isGit) {
434314
- logForDiagnosticsNoPII("info", "git_status_skipped_not_git", {
434315
- duration_ms: Date.now() - startTime
434316
- });
434505
+ const blocks = await fetchGitStatusBlocks();
434506
+ if (!blocks)
434317
434507
  return null;
434318
- }
434319
- try {
434320
- const gitCmdsStart = Date.now();
434321
- const [branch, mainBranch, status, log, userName] = await Promise.all([
434322
- getBranch2(),
434323
- getDefaultBranch2(),
434324
- execFileNoThrow3(gitExe2(), ["--no-optional-locks", "status", "--short"], {
434325
- preserveOutputOnError: false
434326
- }).then(({ stdout }) => stdout.trim()),
434327
- execFileNoThrow3(gitExe2(), ["--no-optional-locks", "log", "--oneline", "-n", "5"], {
434328
- preserveOutputOnError: false
434329
- }).then(({ stdout }) => stdout.trim()),
434330
- execFileNoThrow3(gitExe2(), ["config", "user.name"], {
434331
- preserveOutputOnError: false
434332
- }).then(({ stdout }) => stdout.trim())
434333
- ]);
434334
- logForDiagnosticsNoPII("info", "git_commands_completed", {
434335
- duration_ms: Date.now() - gitCmdsStart,
434336
- status_length: status.length
434337
- });
434338
- const truncatedStatus = status.length > MAX_STATUS_CHARS ? status.substring(0, MAX_STATUS_CHARS) + `
434339
- ... (truncated because it exceeds 2k characters. If you need more information, run "git status" using BashTool)` : status;
434340
- logForDiagnosticsNoPII("info", "git_status_completed", {
434341
- duration_ms: Date.now() - startTime,
434342
- truncated: status.length > MAX_STATUS_CHARS
434343
- });
434344
- return [
434345
- `This is the git status at the start of the conversation. Note that this status is a snapshot in time, and will not update during the conversation.`,
434346
- `Current branch: ${branch}`,
434347
- `Main branch (you will usually use this for PRs): ${mainBranch}`,
434348
- ...userName ? [`Git user: ${userName}`] : [],
434349
- `Status:
434350
- ${truncatedStatus || "(clean)"}`,
434351
- `Recent commits:
434352
- ${log}`
434353
- ].join(`
434354
-
434355
- `);
434356
- } catch (error) {
434357
- logForDiagnosticsNoPII("error", "git_status_failed", {
434358
- duration_ms: Date.now() - startTime
434359
- });
434360
- logError3(error);
434361
- return null;
434362
- }
434508
+ sessionStartGitStatusBlocks = blocks;
434509
+ return formatGitStatus(blocks, GIT_STATUS_START_HEADER);
434363
434510
  });
434364
434511
  getSystemContext = memoize_default(async () => {
434365
434512
  const startTime = Date.now();
@@ -451387,7 +451534,7 @@ function TokenWarning(t0) {
451387
451534
  }
451388
451535
  let t2;
451389
451536
  if ($[3] === Symbol.for("react.memo_cache_sentinel")) {
451390
- t2 = isAutoCompactEnabled();
451537
+ t2 = isAutoCompactEnabledForModel(model);
451391
451538
  $[3] = t2;
451392
451539
  } else {
451393
451540
  t2 = $[3];
@@ -459943,7 +460090,7 @@ var jsx_dev_runtime381, ContextBarSegment = ({ input }) => {
459943
460090
  }
459944
460091
  const color = contextColorForPercentage(pct);
459945
460092
  const modelId = input.model?.id;
459946
- const showCompactWarning = modelId != null && isAutoCompactEnabled() && calculateTokenWarningState(used, modelId).isAboveWarningThreshold;
460093
+ const showCompactWarning = modelId != null && isAutoCompactEnabledForModel(modelId) && calculateTokenWarningState(used, modelId).isAboveWarningThreshold;
459947
460094
  return /* @__PURE__ */ jsx_dev_runtime381.jsxDEV(ThemedText, {
459948
460095
  color,
459949
460096
  children: [
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@atlasharness/atlascode",
3
- "version": "0.1.68",
3
+ "version": "0.1.69",
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",