bingocode 1.1.200-beta.9 → 1.1.201

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.
@@ -64,6 +64,7 @@ import {
64
64
  } from 'src/types/textInputTypes.js'
65
65
  import { randomUUID, type UUID } from 'crypto'
66
66
  import { getInitialSettings, getSettings_DEPRECATED } from './settings/settings.js'
67
+ import { getCurrentSessionBrainMode } from './sessionStorage.js'
67
68
  import { getSnippetForTwoFileDiff } from 'src/tools/FileEditTool/utils.js'
68
69
  import type {
69
70
  ContentBlockParam,
@@ -1594,7 +1595,6 @@ function getCriticalSystemReminderAttachment(
1594
1595
  }
1595
1596
 
1596
1597
  function getBrainModeReminderAttachment(): Attachment[] {
1597
- const { getCurrentSessionBrainMode } = require('./sessionStorage.js')
1598
1598
  if (!getInitialSettings().brainMode && !getCurrentSessionBrainMode()) {
1599
1599
  return []
1600
1600
  }
@@ -1602,7 +1602,7 @@ function getBrainModeReminderAttachment(): Attachment[] {
1602
1602
  {
1603
1603
  type: 'system_reminder' as const,
1604
1604
  content:
1605
- '/brain active — Only use Agent and AskUserQuestion. Do NOT use Bash/Read/Grep/Glob/Write/Edit directly. Delegate everything.',
1605
+ '/brain active — You are the high-dimensional thinker. Delegate everything through Agent.',
1606
1606
  },
1607
1607
  ]
1608
1608
  }
@@ -6,7 +6,7 @@ import { getCanonicalName } from './model/model.js'
6
6
  import { getModelCapability } from './model/modelCapabilities.js'
7
7
 
8
8
  // Model context window size (200k tokens for all models right now)
9
- export const MODEL_CONTEXT_WINDOW_DEFAULT = 200_000
9
+ export const MODEL_CONTEXT_WINDOW_DEFAULT = 1_000_000
10
10
 
11
11
  // Maximum output tokens for compact operations
12
12
  export const COMPACT_MAX_OUTPUT_TOKENS = 20_000
@@ -2303,6 +2303,7 @@ export async function loadTranscriptFromFile(
2303
2303
  filePath: string,
2304
2304
  ): Promise<LogOption> {
2305
2305
  if (filePath.endsWith('.jsonl')) {
2306
+ const data = await loadTranscriptFile(filePath)
2306
2307
  const {
2307
2308
  messages,
2308
2309
  summaries,
@@ -2315,7 +2316,7 @@ export async function loadTranscriptFromFile(
2315
2316
  leafUuids,
2316
2317
  contentReplacements,
2317
2318
  worktreeStates,
2318
- } = await loadTranscriptFile(filePath)
2319
+ } = data
2319
2320
 
2320
2321
  if (messages.size === 0) {
2321
2322
  throw new Error('No messages found in JSONL file')
@@ -2360,6 +2361,7 @@ export async function loadTranscriptFromFile(
2360
2361
  worktreeSession: worktreeStates.has(sessionId)
2361
2362
  ? worktreeStates.get(sessionId)
2362
2363
  : undefined,
2364
+ brainMode: resolveBrainMode(data, sessionId),
2363
2365
  }
2364
2366
  }
2365
2367
 
@@ -2988,6 +2990,7 @@ export async function loadFullLog(log: LogOption): Promise<LogOption> {
2988
2990
  }
2989
2991
 
2990
2992
  try {
2993
+ const data = await loadTranscriptFile(sessionFile)
2991
2994
  const {
2992
2995
  messages,
2993
2996
  summaries,
@@ -3008,7 +3011,7 @@ export async function loadFullLog(log: LogOption): Promise<LogOption> {
3008
3011
  contextCollapseCommits,
3009
3012
  contextCollapseSnapshot,
3010
3013
  leafUuids,
3011
- } = await loadTranscriptFile(sessionFile)
3014
+ } = data
3012
3015
 
3013
3016
  if (messages.size === 0) {
3014
3017
  return log
@@ -3044,7 +3047,7 @@ export async function loadFullLog(log: LogOption): Promise<LogOption> {
3044
3047
  agentColor: sessionId ? agentColors.get(sessionId) : log.agentColor,
3045
3048
  agentSetting: sessionId ? agentSettings.get(sessionId) : log.agentSetting,
3046
3049
  mode: sessionId ? (modes.get(sessionId) as LogOption['mode']) : log.mode,
3047
- brainMode: sessionId ? brainModes.get(sessionId) : log.brainMode,
3050
+ brainMode: sessionId ? resolveBrainMode(data, sessionId) : log.brainMode,
3048
3051
  worktreeSession:
3049
3052
  sessionId && worktreeStates.has(sessionId)
3050
3053
  ? worktreeStates.get(sessionId)
@@ -3633,7 +3636,7 @@ export async function loadTranscriptFile(
3633
3636
  agentColors.set(entry.sessionId, entry.agentColor)
3634
3637
  } else if (entry.type === 'agent-setting' && entry.sessionId) {
3635
3638
  agentSettings.set(entry.sessionId, entry.agentSetting)
3636
- } else if (entry.type === 'mode' && entry.sessionId) {
3639
+ } else if (entry.type === 'mode' && entry.sessionId) {
3637
3640
  modes.set(entry.sessionId, entry.mode)
3638
3641
  } else if (entry.type === 'brain-mode' && entry.sessionId) {
3639
3642
  brainModes.set(entry.sessionId, entry.brainMode)
@@ -3851,6 +3854,17 @@ export async function loadTranscriptFile(
3851
3854
  }
3852
3855
  }
3853
3856
 
3857
+ /**
3858
+ * Resolves the brainMode flag for a given session from a loaded transcript.
3859
+ * Encapsulates the Map.get() pattern so callers do not need to remember it.
3860
+ */
3861
+ export function resolveBrainMode(
3862
+ transcript: Awaited<ReturnType<typeof loadTranscriptFile>>,
3863
+ sessionId: string,
3864
+ ): boolean | undefined {
3865
+ return transcript.brainModes.get(sessionId as UUID)
3866
+ }
3867
+
3854
3868
  /**
3855
3869
  * Loads all messages, summaries, file history snapshots, and attribution snapshots from a specific session file.
3856
3870
  */
@@ -3860,6 +3874,11 @@ async function loadSessionFile(sessionId: UUID): Promise<{
3860
3874
  customTitles: Map<UUID, string>
3861
3875
  tags: Map<UUID, string>
3862
3876
  agentSettings: Map<UUID, string>
3877
+ agentColors: Map<UUID, string>
3878
+ modes: Map<UUID, string>
3879
+ prNumbers: Map<UUID, number>
3880
+ prUrls: Map<UUID, string>
3881
+ prRepositories: Map<UUID, string>
3863
3882
  worktreeStates: Map<UUID, PersistedWorktreeSession | null>
3864
3883
  fileHistorySnapshots: Map<UUID, FileHistorySnapshotMessage>
3865
3884
  attributionSnapshots: Map<UUID, AttributionSnapshotMessage>
@@ -3910,12 +3929,18 @@ export async function getLastSessionLog(
3910
3929
  sessionId: UUID,
3911
3930
  ): Promise<LogOption | null> {
3912
3931
  // Single read: load all session data at once instead of reading the file twice
3932
+ const data = await loadSessionFile(sessionId)
3913
3933
  const {
3914
3934
  messages,
3915
3935
  summaries,
3916
3936
  customTitles,
3917
3937
  tags,
3918
3938
  agentSettings,
3939
+ modes,
3940
+ agentColors,
3941
+ prNumbers,
3942
+ prUrls,
3943
+ prRepositories,
3919
3944
  worktreeStates,
3920
3945
  brainModes,
3921
3946
  fileHistorySnapshots,
@@ -3923,7 +3948,7 @@ export async function getLastSessionLog(
3923
3948
  contentReplacements,
3924
3949
  contextCollapseCommits,
3925
3950
  contextCollapseSnapshot,
3926
- } = await loadSessionFile(sessionId)
3951
+ } = data
3927
3952
  if (messages.size === 0) return null
3928
3953
  // Prime getSessionMessages cache so recordTranscript (called after REPL
3929
3954
  // mount on --resume) skips a second full file load. -170~227ms on large sessions.
@@ -3962,7 +3987,12 @@ export async function getLastSessionLog(
3962
3987
  contentReplacements.get(sessionId) ?? [],
3963
3988
  ),
3964
3989
  worktreeSession: worktreeStates.get(sessionId),
3965
- brainMode: brainModes.get(sessionId),
3990
+ brainMode: resolveBrainMode(data, sessionId),
3991
+ mode: modes.get(sessionId) as 'coordinator' | 'normal' | undefined,
3992
+ agentColor: agentColors.get(sessionId),
3993
+ prNumber: prNumbers.get(sessionId),
3994
+ prUrl: prUrls.get(sessionId),
3995
+ prRepository: prRepositories.get(sessionId),
3966
3996
  contextCollapseCommits: contextCollapseCommits.filter(
3967
3997
  e => e.sessionId === sessionId,
3968
3998
  ),
@@ -4641,6 +4671,7 @@ export async function loadAllLogsFromSessionFile(
4641
4671
  sessionFile: string,
4642
4672
  projectPathOverride?: string,
4643
4673
  ): Promise<LogOption[]> {
4674
+ const data = await loadTranscriptFile(sessionFile, { keepAllLeaves: true })
4644
4675
  const {
4645
4676
  messages,
4646
4677
  summaries,
@@ -4658,7 +4689,7 @@ export async function loadAllLogsFromSessionFile(
4658
4689
  attributionSnapshots,
4659
4690
  contentReplacements,
4660
4691
  leafUuids,
4661
- } = await loadTranscriptFile(sessionFile, { keepAllLeaves: true })
4692
+ } = data
4662
4693
 
4663
4694
  if (messages.size === 0) return []
4664
4695
 
@@ -4716,7 +4747,7 @@ export async function loadAllLogsFromSessionFile(
4716
4747
  agentColor: agentColors.get(sessionId),
4717
4748
  agentSetting: agentSettings.get(sessionId),
4718
4749
  mode: modes.get(sessionId) as LogOption['mode'],
4719
- brainMode: brainModes.get(sessionId),
4750
+ brainMode: resolveBrainMode(data, sessionId),
4720
4751
  prNumber: prNumbers.get(sessionId),
4721
4752
  prUrl: prUrls.get(sessionId),
4722
4753
  prRepository: prRepositories.get(sessionId),
@@ -52,6 +52,29 @@ export function getTokenCountFromUsage(usage: Usage): number {
52
52
  )
53
53
  }
54
54
 
55
+ /**
56
+ * Calculate total tokens across all agent messages, matching the ProgressTracker
57
+ * accumulation logic in LocalAgentTask. In Claude's API:
58
+ * - input_tokens (and cache tokens) are cumulative per turn — each call already
59
+ * includes all previous context, so we keep only the LATEST value.
60
+ * - output_tokens are per-turn independent, so we SUM them across all turns.
61
+ */
62
+ export function getTokenCountFromMessages(messages: Message[]): number {
63
+ let latestInputTokens = 0
64
+ let cumulativeOutputTokens = 0
65
+ for (const message of messages) {
66
+ const usage = getTokenUsage(message)
67
+ if (usage) {
68
+ latestInputTokens =
69
+ usage.input_tokens +
70
+ (usage.cache_creation_input_tokens ?? 0) +
71
+ (usage.cache_read_input_tokens ?? 0)
72
+ cumulativeOutputTokens += usage.output_tokens
73
+ }
74
+ }
75
+ return latestInputTokens + cumulativeOutputTokens
76
+ }
77
+
55
78
  export function tokenCountFromLastAPIResponse(messages: Message[]): number {
56
79
  let i = messages.length - 1
57
80
  while (i >= 0) {