forked from ultraworkers/claw-code
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathapiMicrocompact.ts
More file actions
153 lines (134 loc) · 4.88 KB
/
Copy pathapiMicrocompact.ts
File metadata and controls
153 lines (134 loc) · 4.88 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
import { FILE_EDIT_TOOL_NAME } from 'src/tools/FileEditTool/constants.js'
import { FILE_READ_TOOL_NAME } from 'src/tools/FileReadTool/prompt.js'
import { FILE_WRITE_TOOL_NAME } from 'src/tools/FileWriteTool/prompt.js'
import { GLOB_TOOL_NAME } from 'src/tools/GlobTool/prompt.js'
import { GREP_TOOL_NAME } from 'src/tools/GrepTool/prompt.js'
import { NOTEBOOK_EDIT_TOOL_NAME } from 'src/tools/NotebookEditTool/constants.js'
import { WEB_FETCH_TOOL_NAME } from 'src/tools/WebFetchTool/prompt.js'
import { WEB_SEARCH_TOOL_NAME } from 'src/tools/WebSearchTool/prompt.js'
import { SHELL_TOOL_NAMES } from 'src/utils/shell/shellToolUtils.js'
import { isEnvTruthy } from '../../utils/envUtils.js'
// docs: https://docs.google.com/document/d/1oCT4evvWTh3P6z-kcfNQwWTCxAhkoFndSaNS9Gm40uw/edit?tab=t.0
// Default values for context management strategies
// Match client-side microcompact token values
const DEFAULT_MAX_INPUT_TOKENS = 180_000 // Typical warning threshold
const DEFAULT_TARGET_INPUT_TOKENS = 40_000 // Keep last 40k tokens like client-side
const TOOLS_CLEARABLE_RESULTS = [
...SHELL_TOOL_NAMES,
GLOB_TOOL_NAME,
GREP_TOOL_NAME,
FILE_READ_TOOL_NAME,
WEB_FETCH_TOOL_NAME,
WEB_SEARCH_TOOL_NAME,
]
const TOOLS_CLEARABLE_USES = [
FILE_EDIT_TOOL_NAME,
FILE_WRITE_TOOL_NAME,
NOTEBOOK_EDIT_TOOL_NAME,
]
// Context management strategy types matching API documentation
export type ContextEditStrategy =
| {
type: 'clear_tool_uses_20250919'
trigger?: {
type: 'input_tokens'
value: number
}
keep?: {
type: 'tool_uses'
value: number
}
clear_tool_inputs?: boolean | string[]
exclude_tools?: string[]
clear_at_least?: {
type: 'input_tokens'
value: number
}
}
| {
type: 'clear_thinking_20251015'
keep: { type: 'thinking_turns'; value: number } | 'all'
}
// Context management configuration wrapper
export type ContextManagementConfig = {
edits: ContextEditStrategy[]
}
// API-based microcompact implementation that uses native context management
export function getAPIContextManagement(options?: {
hasThinking?: boolean
isRedactThinkingActive?: boolean
clearAllThinking?: boolean
}): ContextManagementConfig | undefined {
const {
hasThinking = false,
isRedactThinkingActive = false,
clearAllThinking = false,
} = options ?? {}
const strategies: ContextEditStrategy[] = []
// Preserve thinking blocks in previous assistant turns. Skip when
// redact-thinking is active — redacted blocks have no model-visible content.
// When clearAllThinking is set (>1h idle = cache miss), keep only the last
// thinking turn — the API schema requires value >= 1, and omitting the edit
// falls back to the model-policy default (often "all"), which wouldn't clear.
if (hasThinking && !isRedactThinkingActive) {
strategies.push({
type: 'clear_thinking_20251015',
keep: clearAllThinking ? { type: 'thinking_turns', value: 1 } : 'all',
})
}
// Tool clearing strategies are ant-only
if (process.env.USER_TYPE !== 'ant') {
return strategies.length > 0 ? { edits: strategies } : undefined
}
const useClearToolResults = isEnvTruthy(
process.env.USE_API_CLEAR_TOOL_RESULTS,
)
const useClearToolUses = isEnvTruthy(process.env.USE_API_CLEAR_TOOL_USES)
// If no tool clearing strategy is enabled, return early
if (!useClearToolResults && !useClearToolUses) {
return strategies.length > 0 ? { edits: strategies } : undefined
}
if (useClearToolResults) {
const triggerThreshold = process.env.API_MAX_INPUT_TOKENS
? parseInt(process.env.API_MAX_INPUT_TOKENS)
: DEFAULT_MAX_INPUT_TOKENS
const keepTarget = process.env.API_TARGET_INPUT_TOKENS
? parseInt(process.env.API_TARGET_INPUT_TOKENS)
: DEFAULT_TARGET_INPUT_TOKENS
const strategy: ContextEditStrategy = {
type: 'clear_tool_uses_20250919',
trigger: {
type: 'input_tokens',
value: triggerThreshold,
},
clear_at_least: {
type: 'input_tokens',
value: triggerThreshold - keepTarget,
},
clear_tool_inputs: TOOLS_CLEARABLE_RESULTS,
}
strategies.push(strategy)
}
if (useClearToolUses) {
const triggerThreshold = process.env.API_MAX_INPUT_TOKENS
? parseInt(process.env.API_MAX_INPUT_TOKENS)
: DEFAULT_MAX_INPUT_TOKENS
const keepTarget = process.env.API_TARGET_INPUT_TOKENS
? parseInt(process.env.API_TARGET_INPUT_TOKENS)
: DEFAULT_TARGET_INPUT_TOKENS
const strategy: ContextEditStrategy = {
type: 'clear_tool_uses_20250919',
trigger: {
type: 'input_tokens',
value: triggerThreshold,
},
clear_at_least: {
type: 'input_tokens',
value: triggerThreshold - keepTarget,
},
exclude_tools: TOOLS_CLEARABLE_USES,
}
strategies.push(strategy)
}
return strategies.length > 0 ? { edits: strategies } : undefined
}