minimal-agent 0.18.8 → 0.18.10

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 (46) hide show
  1. package/package.json +1 -1
  2. package/src/loop.js +35 -5
  3. package/src/loop.ts +35 -5
  4. package/src/memory/factLearning.js +3 -3
  5. package/src/memory/factLearning.ts +3 -7
  6. package/src/memory/jobPolicy.js +21 -13
  7. package/src/memory/jobPolicy.ts +22 -11
  8. package/src/memory/learning.js +3 -3
  9. package/src/memory/learning.ts +3 -3
  10. package/src/memory/learningModel.js +4 -2
  11. package/src/memory/learningModel.ts +4 -2
  12. package/src/prompts/delegation.js +15 -0
  13. package/src/prompts/delegation.ts +20 -0
  14. package/src/prompts/policyRegistry.js +3 -2
  15. package/src/prompts/policyRegistry.ts +3 -2
  16. package/src/tools/agent/agent.js +2 -1
  17. package/src/tools/agent/agent.ts +2 -1
  18. package/src/tools/applypatch/applyPatch.js +1 -1
  19. package/src/tools/applypatch/applyPatch.ts +1 -1
  20. package/src/tools/edit/edit.js +11 -15
  21. package/src/tools/edit/edit.ts +10 -15
  22. package/src/tools/edit/multi-edit.js +14 -4
  23. package/src/tools/edit/multi-edit.ts +10 -4
  24. package/src/tools/memory/maintenance.js +2 -0
  25. package/src/tools/memory/maintenance.ts +2 -0
  26. package/src/tools/memory/memory.js +58 -14
  27. package/src/tools/memory/memory.ts +57 -13
  28. package/src/tools/memory/policy.js +16 -1
  29. package/src/tools/memory/policy.ts +16 -1
  30. package/src/tools/read/read.js +91 -47
  31. package/src/tools/read/read.ts +77 -46
  32. package/src/tools/shared/diffSummary.js +25 -3
  33. package/src/tools/shared/diffSummary.ts +23 -3
  34. package/src/tools/shared/editTransaction.js +45 -0
  35. package/src/tools/shared/editTransaction.ts +39 -0
  36. package/src/tools/shared/fileActivity.js +10 -2
  37. package/src/tools/shared/fileActivity.ts +11 -2
  38. package/src/tools/shared/fileState.js +2 -0
  39. package/src/tools/shared/fileState.ts +4 -0
  40. package/src/tools/shared/readBudget.js +12 -0
  41. package/src/tools/shared/readBudget.ts +12 -0
  42. package/src/tools/toolPromptGuides.js +6 -5
  43. package/src/tools/toolPromptGuides.ts +6 -5
  44. package/src/tools/types.js +2 -6
  45. package/src/tools/types.ts +2 -6
  46. package/src/types.ts +4 -2
@@ -1,5 +1,6 @@
1
1
  import { createHash } from 'node:crypto';
2
- import { readFile, realpath } from 'node:fs/promises';
2
+ import { realpath, stat } from 'node:fs/promises';
3
+ import { createReadStream } from 'node:fs';
3
4
  import { extname, isAbsolute, relative, resolve, sep } from 'node:path';
4
5
 
5
6
  import { getWorkingDir } from '../../bootstrap/workingDir.js';
@@ -48,7 +49,15 @@ export async function fileActivityMetadata(
48
49
 
49
50
  let sha256: string | undefined;
50
51
  if (activity !== 'deleted') {
51
- try { sha256 = createHash('sha256').update(await readFile(candidate)).digest('hex'); }
52
+ try {
53
+ // A range Read must not secretly load/hash a gigabyte for UI metadata.
54
+ // Hash is optional for sources; committed artifacts use bounded buffers.
55
+ if (activity !== 'read' || (await stat(candidate)).size <= 8 * 1024 * 1024) {
56
+ const hash = createHash('sha256');
57
+ for await (const chunk of createReadStream(candidate)) hash.update(chunk);
58
+ sha256 = hash.digest('hex');
59
+ }
60
+ }
52
61
  catch { /* The file activity remains useful even when hashing fails. */ }
53
62
  }
54
63
  return {
@@ -16,6 +16,7 @@ export function recordRead(absPath, opts, state = defaultState) {
16
16
  && st.size === prev.size;
17
17
  const sameRegionUnchanged = sameSnapshot
18
18
  && prev.offset === opts?.offset
19
+ && prev.column === opts?.column
19
20
  && prev.limit === opts?.limit;
20
21
  const reads = sameRegionUnchanged ? (prev.reads ?? 1) + 1 : 1;
21
22
  // A bounded Read may be repeated in several adjacent calls. Keep the
@@ -64,6 +65,7 @@ export function recordRead(absPath, opts, state = defaultState) {
64
65
  truncated: opts?.truncated ?? false,
65
66
  partial,
66
67
  offset: opts?.offset,
68
+ column: opts?.column,
67
69
  limit: opts?.limit,
68
70
  reads,
69
71
  ...(opts?.contentHash ? { contentHash: opts.contentHash } : {}),
@@ -7,6 +7,7 @@ export interface FileStateEntry {
7
7
  truncated: boolean;
8
8
  partial: boolean;
9
9
  offset?: number;
10
+ column?: number;
10
11
  limit?: number;
11
12
  reads?: number;
12
13
  /** SHA-256 is recorded only for a complete read. */
@@ -42,6 +43,7 @@ export function recordRead(
42
43
  truncated?: boolean;
43
44
  partial?: boolean;
44
45
  offset?: number;
46
+ column?: number;
45
47
  limit?: number;
46
48
  contentHash?: string;
47
49
  range?: FileReadRange;
@@ -57,6 +59,7 @@ export function recordRead(
57
59
  && st.size === prev.size;
58
60
  const sameRegionUnchanged = sameSnapshot
59
61
  && prev.offset === opts?.offset
62
+ && prev.column === opts?.column
60
63
  && prev.limit === opts?.limit;
61
64
  const reads = sameRegionUnchanged ? (prev.reads ?? 1) + 1 : 1;
62
65
 
@@ -107,6 +110,7 @@ export function recordRead(
107
110
  truncated: opts?.truncated ?? false,
108
111
  partial,
109
112
  offset: opts?.offset,
113
+ column: opts?.column,
110
114
  limit: opts?.limit,
111
115
  reads,
112
116
  ...(opts?.contentHash ? { contentHash: opts.contentHash } : {}),
@@ -0,0 +1,12 @@
1
+ /** Conservative chars/token reservation works for mixed code and CJK text.
2
+ * A response's parallel Read calls share this closure, not separate quotas.
3
+ */
4
+ export function createReadBudget(remainingTokens) {
5
+ let available = Math.max(0, Math.floor(remainingTokens * 0.5));
6
+ const perRead = Math.min(1_000_000, Math.max(1000, Math.floor(available / 2)));
7
+ return (requested = Math.min(240_000, perRead)) => {
8
+ const granted = Math.min(Math.max(0, requested), perRead, available);
9
+ available -= granted;
10
+ return granted;
11
+ };
12
+ }
@@ -0,0 +1,12 @@
1
+ /** Conservative chars/token reservation works for mixed code and CJK text.
2
+ * A response's parallel Read calls share this closure, not separate quotas.
3
+ */
4
+ export function createReadBudget(remainingTokens: number) {
5
+ let available = Math.max(0, Math.floor(remainingTokens * 0.5));
6
+ const perRead = Math.min(1_000_000, Math.max(1000, Math.floor(available / 2)));
7
+ return (requested = Math.min(240_000, perRead)) => {
8
+ const granted = Math.min(Math.max(0, requested), perRead, available);
9
+ available -= granted;
10
+ return granted;
11
+ };
12
+ }
@@ -1,3 +1,4 @@
1
+ import { AGENT_TOOL_DESCRIPTION } from '../prompts/delegation.js';
1
2
  import { bashShellNotice } from './bash/bash.js';
2
3
  import { COMPUTER_USE_TOOL_ACTIONS } from './computeruse/protocol.js';
3
4
  export const TOOL_CATEGORY_LABELS = {
@@ -42,7 +43,7 @@ export const BUILTIN_TOOL_PROMPT_GUIDES = {
42
43
  BrowserCDP: g('web', '需要现有浏览器工具未覆盖的原始 CDP 能力', '发送精确方法并按事件序列读取结果', '常规网页自动化优先 WebBrowser/BrowserBatch', 'last-resort'),
43
44
  Download: g('web', '把已知 URL 的原始资源保存到本机', '给出目标路径并校验下载结果', '只阅读正文时用 WebFetch'),
44
45
  ComputerUse: g('desktop', '用户明确要求观察或操作原生应用、系统窗口或桌面界面', '观察当前界面,执行一个动作,再验证结果', '文件、静态图片、Shell 和网页任务优先专用工具', 'last-resort'),
45
- Agent: g('agents', '派生独立且边界清晰的子任务', '给出自包含任务书并在返回后核验整合', '不要拆分琐碎或强顺序工作'),
46
+ Agent: g('agents', '大型多模块调查优先委派独立只读问题', '先定位入口,再同轮派发 explore,核验整合证据', '少量已知文件或强顺序工作直接处理'),
46
47
  AgentMessage: g('agents', '向运行中的子 Agent 补充非触发消息', '按稳定 agent id 发送必要上下文', '需要追加新工作使用 AgentFollowup'),
47
48
  AgentList: g('agents', '查看子 Agent 状态和稳定 ID', '按任务路径列出后选择目标', '已知目标 ID 时无需调用'),
48
49
  AgentWait: g('agents', '等待指定子 Agent 进展或结果', '优先长等待,收到更新后再整合', '忙轮询'),
@@ -58,7 +59,7 @@ export const BUILTIN_TOOL_PROMPT_GUIDES = {
58
59
  RecallMemory: g('memory', '当前回答依赖跨会话稳定偏好、决定或背景', '按主题召回并核对证据', '当前消息已足够时不要装饰性召回'),
59
60
  MemoryMaintenance: g('memory', '处理学习队列、项目事实冲突及经验反馈', 'status 定位;summaries 按 query 找近期任务线索、按 turnId 查证据;resolve/resolveKnowledge 结清候选;明确跨项目适用条件后 promoteExperience/promoteKnowledge;adopt 后 feedback', '召回不算使用;失败摘要不是已确认事实;不每轮调用'),
60
61
  RememberMemory: g('memory', '用户明确要求记住长期有效事实、偏好或决定', '保存原话证据和适用范围', '普通陈述交由已启用的后台提炼,不重复保存'),
61
- UpdateMemory: g('memory', '当前用户陈述纠正一条已有记忆', '先 Recall 定位版本,再完整替换', '不要创建冲突副本'),
62
+ UpdateMemory: g('memory', '纠正用户事实', '读版本后 update/review/confirm', '项目知识/经验走 MemoryMaintenance'),
62
63
  ListMemories: g('memory', '用户要查看已保存记忆或需要管理总览', '按范围列出后再决定操作', '正常任务无需全量列出'),
63
64
  ForgetMemory: g('memory', '用户明确要求忘记某条记忆', '定位准确 ID 后删除', '不得主动清理'),
64
65
  SetPersona: g('memory', '用户明确要求改变长期角色或协作风格', '写入清晰、稳定的人格要求', '一次性语气请求不要持久化'),
@@ -87,7 +88,7 @@ export const BUILTIN_TOOL_PROMPT_GUIDES = {
87
88
  // 测试就是从这次真实回归里补的,锁住"压缩后仍要包含这些内容"而不是简单地
88
89
  // 锁住某个具体的压缩产物。
89
90
  export const CONTRACT_DESCRIPTION_OVERRIDES = {
90
- Read: '读取文本、图片、Notebook 或 PDF。文本 offset 从 1 开始;截断后缩小 limit 重读区间,不能跳过未显示内容。PDF 用 pages 指定范围,一次最多 20 页。',
91
+ Read: '读取文本、图片、Notebook 或 PDF。offset 从 1 开始;大范围阅读可提高 limit/max_chars,实际预算由 Runtime 分配。按回执 offset/column 续读,不能跳过截断行。PDF 用 pages,一次最多 20 页。',
91
92
  Edit: '精确替换已有文本。先 Read 最新内容,old_string 必须唯一;多处相同替换传 replace_all=true。new_string 按字面写入。',
92
93
  Write: '创建文件或整体覆盖;新文件可直接写入。覆盖已有文件前须完整 Read(一次全量或分段覆盖全部范围)且内容未变化;仅有局部读取时使用 Edit/ApplyPatch。',
93
94
  ApplyPatch: '提交 Codex 格式补丁,必须用 *** Begin Patch / *** End Patch 包络,不接受裸 git diff。支持 Add/Update/Delete File、Move to;路径相对工作区。先校验,写入失败尝试回滚,不保证跨文件断电原子性。',
@@ -111,13 +112,13 @@ export const CONTRACT_DESCRIPTION_OVERRIDES = {
111
112
  Advisor: '向无工具权限的顾问模型请求一次结构化第二意见。默认 reviewMode=brief 只给重点短评;完整代码审查用 full,并提供范围、基线和证据。full 不扩大上下文或输出预算,材料不足时必须说明未完成。',
112
113
  // 保留决策必填条件,与 schema 的 superRefine 一致;不能只概括成“记录决定”。
113
114
  AdvisorDecision: '记录主 Agent 对顾问第二意见的 accept、partial 或 reject 判断;是否采纳由主 Agent 决定,登记不是执行许可。partial 同时填 acceptedPoints/rejectedPoints;reject 填 rejectedPoints,列出被拒绝点及依据;evidenceRefs 只引用真实 tool_call_id,没有引用则记录待验证。登记失败不阻止任务继续。',
114
- MultiEdit: '同文件有序批量精确替换,先 Read;全部匹配成功才写盘。old_string 非空且唯一,或显式 replace_all。后续匹配前序生成文本会被拒绝,请合并 edits。',
115
+ MultiEdit: '同文件有序批量精确替换,先 Read 相关范围;全部匹配成功才写盘。old_string 非空且唯一,或显式 replace_all。后续匹配前序生成文本会被拒绝,请合并 edits。操作条数不等于替换次数,diff 预览可能不完整。',
115
116
  LSP: '查询定义、引用、类型、符号和诊断。line/character 为 1-based UTF-16;尚未收到诊断不等于没有错误,编辑前读取源码。',
116
117
  WebFetch: '读取已知 HTTP(S) URL 的静态文本,HTML 转 Markdown;不执行 JavaScript、不继承登录态。PDF/图片用 Download 后 Read;动态页面用 WebBrowser。',
117
118
  WebSearch: 'Tavily 搜索返回标题、URL、片段及可选综合答案,不是完整原文或浏览器。重要结论读取来源正文;按子问题查询,重试改变关键词或来源。recency 控制时效,历史范围用 start_date/end_date,none 关闭自动时效;advanced 更慢,news 偏新闻。需配置 Tavily。',
118
119
  PowerShell: '运行宿主 PowerShell 独立进程并检查结果;长任务用 TaskOutput/TaskStop。永久删除用 Trash;不可逆操作先确认,非交互时取消。',
119
120
  Download: '下载 HTTP(S) 原始字节到指定路径;相对路径基于工作目录,会覆盖已有文件;失败或中断不保留部分下载。',
120
- Agent: '启动隔离上下文子任务并返回 agent_id。explore 只读,general 按 write_scopes 或 worktree 执行。run_in_background 立即返回;resume_agent_id 续接私有历史。context.researchQuestions 定义问题契约,AgentReport.findings 按 ID 回传证据结论;reportMaxChars 限制返回预览,完整交接可由 TaskOutput 获取。',
121
+ Agent: AGENT_TOOL_DESCRIPTION,
121
122
  EnterWorktree: '从已提交 HEAD 创建并进入隔离工作树,不自动复制原工作区未提交修改;后续文件工具使用隔离目录,项目记忆仍属于原工作区。',
122
123
  ExitWorktree: '退出隔离工作树:apply 检查并应用补丁到原工作区但不自动提交;keep 保留;discard 有改动则归档保留。实际应用成功后的清理告警不表示应重新应用。',
123
124
  };
@@ -1,4 +1,5 @@
1
1
  import type { Tool, ToolCategory, ToolPromptGuide } from '../types.js';
2
+ import { AGENT_TOOL_DESCRIPTION } from '../prompts/delegation.js';
2
3
  import { bashShellNotice } from './bash/bash.js';
3
4
  import { COMPUTER_USE_TOOL_ACTIONS } from './computeruse/protocol.js';
4
5
 
@@ -56,7 +57,7 @@ export const BUILTIN_TOOL_PROMPT_GUIDES: Readonly<Record<string, ToolPromptGuide
56
57
 
57
58
  ComputerUse: g('desktop', '用户明确要求观察或操作原生应用、系统窗口或桌面界面', '观察当前界面,执行一个动作,再验证结果', '文件、静态图片、Shell 和网页任务优先专用工具', 'last-resort'),
58
59
 
59
- Agent: g('agents', '派生独立且边界清晰的子任务', '给出自包含任务书并在返回后核验整合', '不要拆分琐碎或强顺序工作'),
60
+ Agent: g('agents', '大型多模块调查优先委派独立只读问题', '先定位入口,再同轮派发 explore,核验整合证据', '少量已知文件或强顺序工作直接处理'),
60
61
  AgentMessage: g('agents', '向运行中的子 Agent 补充非触发消息', '按稳定 agent id 发送必要上下文', '需要追加新工作使用 AgentFollowup'),
61
62
  AgentList: g('agents', '查看子 Agent 状态和稳定 ID', '按任务路径列出后选择目标', '已知目标 ID 时无需调用'),
62
63
  AgentWait: g('agents', '等待指定子 Agent 进展或结果', '优先长等待,收到更新后再整合', '忙轮询'),
@@ -73,7 +74,7 @@ export const BUILTIN_TOOL_PROMPT_GUIDES: Readonly<Record<string, ToolPromptGuide
73
74
  RecallMemory: g('memory', '当前回答依赖跨会话稳定偏好、决定或背景', '按主题召回并核对证据', '当前消息已足够时不要装饰性召回'),
74
75
  MemoryMaintenance: g('memory', '处理学习队列、项目事实冲突及经验反馈', 'status 定位;summaries 按 query 找近期任务线索、按 turnId 查证据;resolve/resolveKnowledge 结清候选;明确跨项目适用条件后 promoteExperience/promoteKnowledge;adopt 后 feedback', '召回不算使用;失败摘要不是已确认事实;不每轮调用'),
75
76
  RememberMemory: g('memory', '用户明确要求记住长期有效事实、偏好或决定', '保存原话证据和适用范围', '普通陈述交由已启用的后台提炼,不重复保存'),
76
- UpdateMemory: g('memory', '当前用户陈述纠正一条已有记忆', '先 Recall 定位版本,再完整替换', '不要创建冲突副本'),
77
+ UpdateMemory: g('memory', '纠正用户事实', '读版本后 update/review/confirm', '项目知识/经验走 MemoryMaintenance'),
77
78
  ListMemories: g('memory', '用户要查看已保存记忆或需要管理总览', '按范围列出后再决定操作', '正常任务无需全量列出'),
78
79
  ForgetMemory: g('memory', '用户明确要求忘记某条记忆', '定位准确 ID 后删除', '不得主动清理'),
79
80
  SetPersona: g('memory', '用户明确要求改变长期角色或协作风格', '写入清晰、稳定的人格要求', '一次性语气请求不要持久化'),
@@ -104,7 +105,7 @@ export const BUILTIN_TOOL_PROMPT_GUIDES: Readonly<Record<string, ToolPromptGuide
104
105
  // 测试就是从这次真实回归里补的,锁住"压缩后仍要包含这些内容"而不是简单地
105
106
  // 锁住某个具体的压缩产物。
106
107
  export const CONTRACT_DESCRIPTION_OVERRIDES: Readonly<Record<string, string | (() => string)>> = {
107
- Read: '读取文本、图片、Notebook 或 PDF。文本 offset 从 1 开始;截断后缩小 limit 重读区间,不能跳过未显示内容。PDF 用 pages 指定范围,一次最多 20 页。',
108
+ Read: '读取文本、图片、Notebook 或 PDF。offset 从 1 开始;大范围阅读可提高 limit/max_chars,实际预算由 Runtime 分配。按回执 offset/column 续读,不能跳过截断行。PDF 用 pages,一次最多 20 页。',
108
109
  Edit: '精确替换已有文本。先 Read 最新内容,old_string 必须唯一;多处相同替换传 replace_all=true。new_string 按字面写入。',
109
110
  Write: '创建文件或整体覆盖;新文件可直接写入。覆盖已有文件前须完整 Read(一次全量或分段覆盖全部范围)且内容未变化;仅有局部读取时使用 Edit/ApplyPatch。',
110
111
  ApplyPatch: '提交 Codex 格式补丁,必须用 *** Begin Patch / *** End Patch 包络,不接受裸 git diff。支持 Add/Update/Delete File、Move to;路径相对工作区。先校验,写入失败尝试回滚,不保证跨文件断电原子性。',
@@ -129,13 +130,13 @@ export const CONTRACT_DESCRIPTION_OVERRIDES: Readonly<Record<string, string | ((
129
130
  Advisor: '向无工具权限的顾问模型请求一次结构化第二意见。默认 reviewMode=brief 只给重点短评;完整代码审查用 full,并提供范围、基线和证据。full 不扩大上下文或输出预算,材料不足时必须说明未完成。',
130
131
  // 保留决策必填条件,与 schema 的 superRefine 一致;不能只概括成“记录决定”。
131
132
  AdvisorDecision: '记录主 Agent 对顾问第二意见的 accept、partial 或 reject 判断;是否采纳由主 Agent 决定,登记不是执行许可。partial 同时填 acceptedPoints/rejectedPoints;reject 填 rejectedPoints,列出被拒绝点及依据;evidenceRefs 只引用真实 tool_call_id,没有引用则记录待验证。登记失败不阻止任务继续。',
132
- MultiEdit: '同文件有序批量精确替换,先 Read;全部匹配成功才写盘。old_string 非空且唯一,或显式 replace_all。后续匹配前序生成文本会被拒绝,请合并 edits。',
133
+ MultiEdit: '同文件有序批量精确替换,先 Read 相关范围;全部匹配成功才写盘。old_string 非空且唯一,或显式 replace_all。后续匹配前序生成文本会被拒绝,请合并 edits。操作条数不等于替换次数,diff 预览可能不完整。',
133
134
  LSP: '查询定义、引用、类型、符号和诊断。line/character 为 1-based UTF-16;尚未收到诊断不等于没有错误,编辑前读取源码。',
134
135
  WebFetch: '读取已知 HTTP(S) URL 的静态文本,HTML 转 Markdown;不执行 JavaScript、不继承登录态。PDF/图片用 Download 后 Read;动态页面用 WebBrowser。',
135
136
  WebSearch: 'Tavily 搜索返回标题、URL、片段及可选综合答案,不是完整原文或浏览器。重要结论读取来源正文;按子问题查询,重试改变关键词或来源。recency 控制时效,历史范围用 start_date/end_date,none 关闭自动时效;advanced 更慢,news 偏新闻。需配置 Tavily。',
136
137
  PowerShell: '运行宿主 PowerShell 独立进程并检查结果;长任务用 TaskOutput/TaskStop。永久删除用 Trash;不可逆操作先确认,非交互时取消。',
137
138
  Download: '下载 HTTP(S) 原始字节到指定路径;相对路径基于工作目录,会覆盖已有文件;失败或中断不保留部分下载。',
138
- Agent: '启动隔离上下文子任务并返回 agent_id。explore 只读,general 按 write_scopes 或 worktree 执行。run_in_background 立即返回;resume_agent_id 续接私有历史。context.researchQuestions 定义问题契约,AgentReport.findings 按 ID 回传证据结论;reportMaxChars 限制返回预览,完整交接可由 TaskOutput 获取。',
139
+ Agent: AGENT_TOOL_DESCRIPTION,
139
140
  EnterWorktree: '从已提交 HEAD 创建并进入隔离工作树,不自动复制原工作区未提交修改;后续文件工具使用隔离目录,项目记忆仍属于原工作区。',
140
141
  ExitWorktree: '退出隔离工作树:apply 检查并应用补丁到原工作区但不自动提交;keep 保留;discard 有改动则归档保留。实际应用成功后的清理告警不表示应重新应用。',
141
142
  };
@@ -11,11 +11,7 @@ export const DEFAULT_MAX_RESULT_SIZE_CHARS = 30_000;
11
11
  /** Read 工具默认行数上限(与 kakadeai 主仓库一致) */
12
12
  export const MAX_LINES_TO_READ = 2000;
13
13
  /**
14
- * Read 工具默认字节上限(防止超大文件灌进上下文)。
15
- * 基于 200K 上下文窗口设计:
16
- * - system prompt + 工具定义 ≈ 30KB
17
- * - 对话历史 ≈ 100KB
18
- * - 单次读取安全上限 ≈ 256KB(~64K tokens)
19
- * 超过此限制请用 offset/limit 分段读。
14
+ * Text input IO ceiling, independent of the model's returned-content budget.
15
+ * Read windows are bounded separately and can reserve runtime context capacity.
20
16
  */
21
17
  export const MAX_FILE_SIZE_BYTES = 1024 * 1024 * 1024; // 1 GiB; returned content remains independently bounded
@@ -14,11 +14,7 @@ export const DEFAULT_MAX_RESULT_SIZE_CHARS = 30_000;
14
14
  export const MAX_LINES_TO_READ = 2000;
15
15
 
16
16
  /**
17
- * Read 工具默认字节上限(防止超大文件灌进上下文)。
18
- * 基于 200K 上下文窗口设计:
19
- * - system prompt + 工具定义 ≈ 30KB
20
- * - 对话历史 ≈ 100KB
21
- * - 单次读取安全上限 ≈ 256KB(~64K tokens)
22
- * 超过此限制请用 offset/limit 分段读。
17
+ * Text input IO ceiling, independent of the model's returned-content budget.
18
+ * Read windows are bounded separately and can reserve runtime context capacity.
23
19
  */
24
20
  export const MAX_FILE_SIZE_BYTES = 1024 * 1024 * 1024; // 1 GiB; returned content remains independently bounded
package/src/types.ts CHANGED
@@ -291,8 +291,8 @@ export interface FilePatchSummary {
291
291
  unifiedDiff?: string;
292
292
  beforeHash?: string;
293
293
  afterHash: string;
294
- additions: number;
295
- deletions: number;
294
+ additions?: number;
295
+ deletions?: number;
296
296
  truncated: boolean;
297
297
  omittedReason?: 'too_large';
298
298
  }
@@ -570,6 +570,8 @@ export type ToolResult = { problem?: ToolProblemOutcome; observation?: ReadObser
570
570
  * 避免按工具名写特判分支。
571
571
  */
572
572
  export interface ToolCallContext {
573
+ /** Shared per-model-response read allowance; reservations happen before IO. */
574
+ reserveReadChars?: (requested?: number) => number;
573
575
  /** Host presentation only; cannot grant tools to a delegated agent. */
574
576
  output?: import('./runtime/outputContract.js').OutputContract;
575
577
  /** Live effective catalog, including per-turn restrictions. */