mocode-ai 0.4.7 → 0.4.9

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 (118) hide show
  1. package/dist/agent/core.d.ts +112 -0
  2. package/dist/agent/core.js +51 -11
  3. package/dist/agent/index.d.ts +19 -0
  4. package/dist/agent/mode.d.ts +29 -0
  5. package/dist/agent/spawn.d.ts +36 -0
  6. package/dist/attachments/image.d.ts +22 -0
  7. package/dist/commands/config.d.ts +8 -0
  8. package/dist/config/file.d.ts +23 -0
  9. package/dist/config/index.d.ts +114 -0
  10. package/dist/config/index.js +48 -1
  11. package/dist/config/presets.d.ts +57 -0
  12. package/dist/context/budget.d.ts +79 -0
  13. package/dist/context/classifier.d.ts +14 -0
  14. package/dist/context/encoders/_util.d.ts +11 -0
  15. package/dist/context/encoders/code.d.ts +2 -0
  16. package/dist/context/encoders/doc.d.ts +14 -0
  17. package/dist/context/encoders/graph.d.ts +11 -0
  18. package/dist/context/encoders/index.d.ts +2 -0
  19. package/dist/context/encoders/log.d.ts +2 -0
  20. package/dist/context/encoders/memory.d.ts +2 -0
  21. package/dist/context/encoders/passthrough.d.ts +11 -0
  22. package/dist/context/encoders/search.d.ts +2 -0
  23. package/dist/context/encoders/summary.d.ts +12 -0
  24. package/dist/context/encoders/table.d.ts +2 -0
  25. package/dist/context/encoders/tree.d.ts +2 -0
  26. package/dist/context/index.d.ts +6 -0
  27. package/dist/context/lifecycle.d.ts +51 -0
  28. package/dist/context/pipeline.d.ts +9 -0
  29. package/dist/context/registry.d.ts +9 -0
  30. package/dist/context/relevance.d.ts +65 -0
  31. package/dist/context/types.d.ts +36 -0
  32. package/dist/index.d.ts +1 -0
  33. package/dist/llm/capabilities.d.ts +19 -0
  34. package/dist/llm/index.d.ts +111 -0
  35. package/dist/memory/discover.d.ts +15 -0
  36. package/dist/memory/index.d.ts +13 -0
  37. package/dist/memory/reflect.d.ts +34 -0
  38. package/dist/memory/store.d.ts +124 -0
  39. package/dist/permissions/index.js +138 -0
  40. package/dist/pet/bridge.d.ts +73 -0
  41. package/dist/pet/protocol.d.ts +83 -0
  42. package/dist/pet/state.d.ts +28 -0
  43. package/dist/plan/active.d.ts +23 -0
  44. package/dist/plan/index.d.ts +13 -0
  45. package/dist/plan/state.d.ts +2 -0
  46. package/dist/plan/store.d.ts +78 -0
  47. package/dist/project-skill/index.js +129 -0
  48. package/dist/project-skill/initializer.js +179 -0
  49. package/dist/project-snapshot/index.js +177 -0
  50. package/dist/project-snapshot/static-files.js +87 -0
  51. package/dist/repl/index.d.ts +22 -0
  52. package/dist/repl/index.js +159 -1
  53. package/dist/rollback/index.d.ts +79 -0
  54. package/dist/sandbox/command.d.ts +3 -0
  55. package/dist/sandbox/index.d.ts +4 -0
  56. package/dist/sandbox/jail.d.ts +17 -0
  57. package/dist/sandbox/policy.d.ts +21 -0
  58. package/dist/sandbox/root.d.ts +5 -0
  59. package/dist/session/compact.d.ts +92 -0
  60. package/dist/session/drop.d.ts +19 -0
  61. package/dist/session/index.d.ts +13 -0
  62. package/dist/session/persist.d.ts +30 -0
  63. package/dist/session/scheduler.d.ts +53 -0
  64. package/dist/skills/discover.d.ts +33 -0
  65. package/dist/skills/index.d.ts +13 -0
  66. package/dist/tools/builtins/ask-human.d.ts +9 -0
  67. package/dist/tools/builtins/codegraph.d.ts +2 -0
  68. package/dist/tools/builtins/codegraph.js +17 -4
  69. package/dist/tools/builtins/drop-context.d.ts +18 -0
  70. package/dist/tools/builtins/edit-file.d.ts +2 -0
  71. package/dist/tools/builtins/edit-file.js +1 -0
  72. package/dist/tools/builtins/glob.d.ts +2 -0
  73. package/dist/tools/builtins/grep.d.ts +2 -0
  74. package/dist/tools/builtins/index.d.ts +2 -0
  75. package/dist/tools/builtins/index.js +7 -0
  76. package/dist/tools/builtins/memory-forget.d.ts +2 -0
  77. package/dist/tools/builtins/memory-forget.js +1 -0
  78. package/dist/tools/builtins/memory-list.d.ts +2 -0
  79. package/dist/tools/builtins/memory-save.d.ts +2 -0
  80. package/dist/tools/builtins/memory-save.js +1 -0
  81. package/dist/tools/builtins/memory-search.d.ts +2 -0
  82. package/dist/tools/builtins/memory-update.d.ts +2 -0
  83. package/dist/tools/builtins/memory-update.js +1 -0
  84. package/dist/tools/builtins/project-skill-update.js +73 -0
  85. package/dist/tools/builtins/read-file.d.ts +2 -0
  86. package/dist/tools/builtins/read-file.js +17 -1
  87. package/dist/tools/builtins/run-command.d.ts +2 -0
  88. package/dist/tools/builtins/run-command.js +1 -0
  89. package/dist/tools/builtins/switch-mode.d.ts +2 -0
  90. package/dist/tools/builtins/task.d.ts +2 -0
  91. package/dist/tools/builtins/task.js +1 -0
  92. package/dist/tools/builtins/todolist.d.ts +2 -0
  93. package/dist/tools/builtins/use-skill.d.ts +2 -0
  94. package/dist/tools/builtins/web-fetch.d.ts +2 -0
  95. package/dist/tools/builtins/web-search.d.ts +2 -0
  96. package/dist/tools/builtins/web-search.js +12 -1
  97. package/dist/tools/builtins/write-file.d.ts +2 -0
  98. package/dist/tools/builtins/write-file.js +1 -0
  99. package/dist/tools/constants.d.ts +52 -0
  100. package/dist/tools/registry.d.ts +18 -0
  101. package/dist/tools/types.d.ts +42 -0
  102. package/dist/ui/batch.d.ts +67 -0
  103. package/dist/ui/clipboard.d.ts +9 -0
  104. package/dist/ui/content.d.ts +55 -0
  105. package/dist/ui/content.js +14 -3
  106. package/dist/ui/diff.d.ts +34 -0
  107. package/dist/ui/diff.js +15 -24
  108. package/dist/ui/intervention.d.ts +46 -0
  109. package/dist/ui/layout.d.ts +225 -0
  110. package/dist/ui/layout.js +10 -0
  111. package/dist/ui/markdown.d.ts +46 -0
  112. package/dist/ui/mouse.d.ts +29 -0
  113. package/dist/ui/prompt.d.ts +61 -0
  114. package/dist/ui/render.d.ts +60 -0
  115. package/dist/ui/spinner.d.ts +26 -0
  116. package/dist/ui/theme.d.ts +47 -0
  117. package/dist/updater/index.d.ts +22 -0
  118. package/package.json +1 -1
@@ -10,8 +10,9 @@ import { MAX_OUTPUT } from '../constants.js';
10
10
  function hasCodegraphIndex() {
11
11
  return existsSync(path.join(process.cwd(), '.codegraph'));
12
12
  }
13
- /** 跑 codegraph CLI 子进程,返回合并 stdout+stderr(带退出码),超时 60s。 */
14
- function runCodegraph(args) {
13
+ /** 跑 codegraph CLI 子进程,返回合并 stdout+stderr(带退出码),超时 60s。
14
+ * signal 透传(用户 Ctrl+C) 即时杀子进程,不等 60s 超时。 */
15
+ function runCodegraph(args, signal) {
15
16
  return new Promise((done) => {
16
17
  const isWin = process.platform === 'win32';
17
18
  // win32 必须走 cmd.exe /c:Node 自 CVE-2024-27980 修复后,shell:false 直接 spawn
@@ -26,6 +27,7 @@ function runCodegraph(args) {
26
27
  return;
27
28
  finished = true;
28
29
  clearTimeout(timer);
30
+ signal?.removeEventListener('abort', onAbort);
29
31
  done(s);
30
32
  };
31
33
  const onChunk = (chunk) => {
@@ -46,6 +48,17 @@ function runCodegraph(args) {
46
48
  child.kill();
47
49
  finish(`[超时,已终止]\n${out.trim()}`);
48
50
  }, 60000);
51
+ // abort(用户 Ctrl+C,经 executeTool ctx.signal 透传)→ 杀子进程 + 返[已中断]
52
+ const onAbort = () => {
53
+ child.kill();
54
+ finish(`[已中断]\n${out.trim()}`);
55
+ };
56
+ if (signal) {
57
+ if (signal.aborted)
58
+ onAbort();
59
+ else
60
+ signal.addEventListener('abort', onAbort, { once: true });
61
+ }
49
62
  });
50
63
  }
51
64
  export const codegraphTool = {
@@ -84,7 +97,7 @@ export const codegraphTool = {
84
97
  },
85
98
  required: ['action', 'query'],
86
99
  },
87
- async execute(args) {
100
+ async execute(args, ctx) {
88
101
  if (!hasCodegraphIndex()) {
89
102
  return ('当前目录无 .codegraph/ 索引。codegraph 工具不可用。\n' +
90
103
  '建索引:运行 `codegraph init`(需要 codegraph CLI:`npm i -g @colbymchenry/codegraph`)。\n' +
@@ -110,6 +123,6 @@ export const codegraphTool = {
110
123
  else {
111
124
  return `错误:未知 action "${action}",可选 explore 或 node。`;
112
125
  }
113
- return runCodegraph(cliArgs);
126
+ return runCodegraph(cliArgs, ctx?.signal);
114
127
  },
115
128
  };
@@ -0,0 +1,18 @@
1
+ import type { Tool } from '../types.js';
2
+ /**
3
+ * 运行中上下文剔除工具:agent 检索到大量无关信息后,主动把历史里无关的 tool 结果替换为存根,
4
+ * 释放上下文空间(保 tool_call_id 配对不变量,只改 content)。
5
+ *
6
+ * 与 compact 的区别:compact 是阈值触发的整体压缩(微截 + 摘要);drop_context 是 agent 主动、
7
+ * 精准剔除"已判定无关"的具体 tool 结果。
8
+ *
9
+ * 保护:history[0](system)与当前轮(最后一个 user 及其之后)永不剔除——agent 还在用。
10
+ * 已是存根的不重复剔除(幂等)。永不抛错。
11
+ *
12
+ * 筛选(各维度 AND 组合,全部可选;不传 = 剔除所有可剔除的旧 tool 结果):
13
+ * - toolNames:只剔除这些工具名的结果(如 ["grep","read_file"])
14
+ * - contains:只剔除内容包含所有这些词(AND、大小写不敏感)的结果
15
+ *
16
+ * plan 模式不禁用:纯上下文管理,无文件 / 命令副作用。
17
+ */
18
+ export declare const dropContextTool: Tool;
@@ -0,0 +1,2 @@
1
+ import type { Tool } from '../types.js';
2
+ export declare const editFileTool: Tool;
@@ -4,6 +4,7 @@ import { resolve } from 'node:path';
4
4
  export const editFileTool = {
5
5
  name: 'edit_file',
6
6
  description: 'Replace a string in a file. old_string must occur exactly once and match exactly (including indentation/newlines). Use write_file for new files.',
7
+ risk: 'confirm',
7
8
  parameters: {
8
9
  type: 'object',
9
10
  properties: {
@@ -0,0 +1,2 @@
1
+ import type { Tool } from '../types.js';
2
+ export declare const globTool: Tool;
@@ -0,0 +1,2 @@
1
+ import type { Tool } from '../types.js';
2
+ export declare const grepTool: Tool;
@@ -0,0 +1,2 @@
1
+ import type { Tool } from '../types.js';
2
+ export declare const builtinTools: Tool[];
@@ -18,6 +18,7 @@ import { memoryUpdateTool } from './memory-update.js';
18
18
  import { memoryForgetTool } from './memory-forget.js';
19
19
  import { taskTool } from './task.js';
20
20
  import { todolistTool } from './todolist.js';
21
+ import { projectSkillUpdateTool } from './project-skill-update.js';
21
22
  /**
22
23
  * 所有内置工具,按注册顺序排列。
23
24
  * 加新工具:在本目录新建 `xxx.ts` 导出一个 Tool,再在下面数组里加一行。无需改 agent / llm。
@@ -41,6 +42,11 @@ const _memoryTools = _memoryEnabledAtBoot
41
42
  memoryForgetTool,
42
43
  ]
43
44
  : [];
45
+ /** 项目专属 Skill 工具:仅在 MOCODE_PROJECT_SKILL=true 时注册,与 memory 同模式。 */
46
+ const _projectSkillEnabledAtBoot = process.env.MOCODE_PROJECT_SKILL === 'true';
47
+ const _projectSkillTools = _projectSkillEnabledAtBoot
48
+ ? [projectSkillUpdateTool]
49
+ : [];
44
50
  export const builtinTools = [
45
51
  readFileTool,
46
52
  writeFileTool,
@@ -56,6 +62,7 @@ export const builtinTools = [
56
62
  switchModeTool, // plan↔auto 自切(两模式都可见,不进 PLAN_DISABLED_TOOLS;副作用控制工具→串行分支)
57
63
  dropContextTool, // 运行中剔除无关 tool 结果(上下文管理,无副作用;两模式都可见,串行分支)
58
64
  ..._memoryTools,
65
+ ..._projectSkillTools,
59
66
  taskTool, // 派生子 agent(独立 history + 可受限工具集);plan 模式禁用(见 PLAN_DISABLED_TOOLS)
60
67
  todolistTool, // 工作记事本(plan 文件:复杂任务 checklist,落盘抗压缩);plan 模式可用(便于「先 plan 再 auto」时落地执行清单)
61
68
  ];
@@ -0,0 +1,2 @@
1
+ import type { Tool } from '../types.js';
2
+ export declare const memoryForgetTool: Tool;
@@ -4,6 +4,7 @@ import { forgetEntry } from '../../memory/store.js';
4
4
  export const memoryForgetTool = {
5
5
  name: 'memory_forget',
6
6
  description: 'Forget a memory entry: default archive (hidden, revivable via memory_update); mode=delete hard-deletes. Pinned entries can\'t be deleted (unpin first).',
7
+ risk: 'confirm',
7
8
  parameters: {
8
9
  type: 'object',
9
10
  properties: {
@@ -0,0 +1,2 @@
1
+ import type { Tool } from '../types.js';
2
+ export declare const memoryListTool: Tool;
@@ -0,0 +1,2 @@
1
+ import type { Tool } from '../types.js';
2
+ export declare const memorySaveTool: Tool;
@@ -5,6 +5,7 @@ import { saveEntry } from '../../memory/store.js';
5
5
  export const memorySaveTool = {
6
6
  name: 'memory_save',
7
7
  description: 'Save a cross-session long-term memory entry. Store only non-obvious, useful facts/decisions/pitfalls. Title enters the startup index; retrieve body via memory_search.',
8
+ risk: 'confirm',
8
9
  parameters: {
9
10
  type: 'object',
10
11
  properties: {
@@ -0,0 +1,2 @@
1
+ import type { Tool } from '../types.js';
2
+ export declare const memorySearchTool: Tool;
@@ -0,0 +1,2 @@
1
+ import type { Tool } from '../types.js';
2
+ export declare const memoryUpdateTool: Tool;
@@ -4,6 +4,7 @@ import { updateEntry } from '../../memory/store.js';
4
4
  export const memoryUpdateTool = {
5
5
  name: 'memory_update',
6
6
  description: 'Update a memory entry in place (id unchanged). Use when facts changed / correcting outdated info / toggling pinned. Get id from memory_list or memory_search.',
7
+ risk: 'confirm',
7
8
  parameters: {
8
9
  type: 'object',
9
10
  properties: {
@@ -0,0 +1,73 @@
1
+ import { readProjectSkill, writeProjectSkill, appendProjectSkill, } from '../../project-skill/index.js';
2
+ /**
3
+ * 项目专属 Skill 更新工具。
4
+ * 支持三种操作:
5
+ * - read: 读取当前 skill 内容
6
+ * - write: 全量覆盖(适合重构整个 skill)
7
+ * - append: 追加到末尾(适合发现新坑点/约定时增量更新)
8
+ *
9
+ * 使用场景:
10
+ * - 开发过程中发现项目特有的架构模式、命名约定
11
+ * - 踩坑后记录避坑指南
12
+ * - 总结项目关键决策和设计理由
13
+ * - 随着项目开发,skill 越来越了解项目,开发效率越来越高
14
+ */
15
+ export const projectSkillUpdateTool = {
16
+ name: 'project_skill_update',
17
+ description: 'Update the project-specific skill file (.mocode/project-skill.md). ' +
18
+ 'Use this to record architectural patterns, naming conventions, common pitfalls, ' +
19
+ 'and key decisions specific to this project. The skill persists across sessions and ' +
20
+ 'is injected into the system prompt when MOCODE_PROJECT_SKILL=true. ' +
21
+ 'Actions: "read" (view current content), "write" (replace all), "append" (add to end).',
22
+ risk: 'safe',
23
+ parameters: {
24
+ type: 'object',
25
+ properties: {
26
+ action: {
27
+ type: 'string',
28
+ enum: ['read', 'write', 'append'],
29
+ description: 'Action to perform: "read" to view current content, "write" to replace all, "append" to add to end',
30
+ },
31
+ content: {
32
+ type: 'string',
33
+ description: 'Content to write or append (required for "write" and "append" actions, ignored for "read")',
34
+ },
35
+ },
36
+ required: ['action'],
37
+ },
38
+ execute: async (args) => {
39
+ const action = String(args.action ?? '').trim();
40
+ const content = String(args.content ?? '');
41
+ switch (action) {
42
+ case 'read': {
43
+ const current = readProjectSkill();
44
+ if (!current) {
45
+ return 'Project skill is empty or does not exist yet.';
46
+ }
47
+ return `Current project skill:\n\n${current}`;
48
+ }
49
+ case 'write': {
50
+ if (!content.trim()) {
51
+ return 'Error: "write" action requires non-empty content parameter.';
52
+ }
53
+ const result = writeProjectSkill(content);
54
+ if (!result.ok) {
55
+ return `Error: ${result.error}`;
56
+ }
57
+ return 'Project skill updated successfully (full replacement).';
58
+ }
59
+ case 'append': {
60
+ if (!content.trim()) {
61
+ return 'Error: "append" action requires non-empty content parameter.';
62
+ }
63
+ const result = appendProjectSkill(content);
64
+ if (!result.ok) {
65
+ return `Error: ${result.error}`;
66
+ }
67
+ return 'Project skill updated successfully (appended).';
68
+ }
69
+ default:
70
+ return `Error: Unknown action "${action}". Use "read", "write", or "append".`;
71
+ }
72
+ },
73
+ };
@@ -0,0 +1,2 @@
1
+ import type { Tool } from '../types.js';
2
+ export declare const readFileTool: Tool;
@@ -1,6 +1,8 @@
1
1
  import { readFile } from 'node:fs/promises';
2
2
  import { resolve } from 'node:path';
3
3
  import { MAX_FILE_LINES } from '../constants.js';
4
+ import { lookupSnapshotFile } from '../../project-snapshot/index.js';
5
+ import { config } from '../../config/index.js';
4
6
  /** 默认单次 read_file 拉取的行数。刻意压低,逼 LLM 分块读大文件,
5
7
  * 配合 description 中的 PAGINATION IS MANDATORY 引导。
6
8
  * 300 行 ≈ 一个屏幕的源码量,够定位一段逻辑而不至于吃光上下文。 */
@@ -29,7 +31,21 @@ export const readFileTool = {
29
31
  const offset = Number(args.offset ?? 1);
30
32
  // 无论 LLM 传多大,单次硬钳到 MAX_FILE_LINES,杜绝「绕过分页引导一把全拿」。
31
33
  const limit = Math.min(Number(args.limit ?? DEFAULT_READ_LIMIT), MAX_FILE_LINES);
32
- const data = await readFile(resolve(path), 'utf8');
34
+ // 项目快照 cache hit:mtime 校验通过则直接返回,省磁盘读
35
+ let data;
36
+ if (config.projectSnapshotEnabled) {
37
+ const absPath = resolve(path);
38
+ const cached = lookupSnapshotFile(absPath);
39
+ if (cached) {
40
+ data = cached.content;
41
+ }
42
+ else {
43
+ data = await readFile(absPath, 'utf8');
44
+ }
45
+ }
46
+ else {
47
+ data = await readFile(resolve(path), 'utf8');
48
+ }
33
49
  const lines = data.split(/\r?\n/);
34
50
  const start = Math.max(0, offset - 1);
35
51
  const end = Math.min(lines.length, start + limit);
@@ -0,0 +1,2 @@
1
+ import type { Tool } from '../types.js';
2
+ export declare const runCommandTool: Tool;
@@ -5,6 +5,7 @@ import { getSandboxRoot, filterEnv, isCommandDenied } from '../../sandbox/index.
5
5
  export const runCommandTool = {
6
6
  name: 'run_command',
7
7
  description: 'Run a shell command, merging stdout+stderr. Default timeout 120s. For tests, builds, git, etc.',
8
+ risk: 'dangerous',
8
9
  parameters: {
9
10
  type: 'object',
10
11
  properties: {
@@ -0,0 +1,2 @@
1
+ import type { Tool } from '../types.js';
2
+ export declare const switchModeTool: Tool;
@@ -0,0 +1,2 @@
1
+ import type { Tool } from '../types.js';
2
+ export declare const taskTool: Tool;
@@ -8,6 +8,7 @@ import { MAX_OUTPUT } from '../constants.js';
8
8
  // 子 agent 中间过程不写主屏,只返回最终摘要;主 agent 据摘要决定下一步。
9
9
  export const taskTool = {
10
10
  name: 'task',
11
+ risk: 'dangerous',
11
12
  description: [
12
13
  'Spawn a sub-agent for an isolated sub-task (independent history; only its final summary returns to you).',
13
14
  'Use when a task splits into independent parts or its many tool calls would bloat your context.',
@@ -0,0 +1,2 @@
1
+ import type { Tool } from '../types.js';
2
+ export declare const todolistTool: Tool;
@@ -0,0 +1,2 @@
1
+ import type { Tool } from '../types.js';
2
+ export declare const useSkillTool: Tool;
@@ -0,0 +1,2 @@
1
+ import type { Tool } from '../types.js';
2
+ export declare const webFetchTool: Tool;
@@ -0,0 +1,2 @@
1
+ import type { Tool } from '../types.js';
2
+ export declare const webSearchTool: Tool;
@@ -24,7 +24,7 @@ export const webSearchTool = {
24
24
  },
25
25
  required: ['query'],
26
26
  },
27
- async execute(args) {
27
+ async execute(args, ctx) {
28
28
  const query = String(args.query ?? '').trim();
29
29
  if (!query)
30
30
  return '错误:query 不能为空。';
@@ -53,6 +53,15 @@ export const webSearchTool = {
53
53
  }
54
54
  const ctrl = new AbortController();
55
55
  const timer = setTimeout(() => ctrl.abort(), SEARCH_TIMEOUT_MS);
56
+ // 外部 abort signal(用户 Ctrl+C,经 executeTool ctx.signal 透传)→ 合并到 ctrl,fetch 即时取消(不等 30s 超时)
57
+ const onExternalAbort = () => ctrl.abort();
58
+ const externalSignal = ctx?.signal;
59
+ if (externalSignal) {
60
+ if (externalSignal.aborted)
61
+ ctrl.abort();
62
+ else
63
+ externalSignal.addEventListener('abort', onExternalAbort, { once: true });
64
+ }
56
65
  try {
57
66
  const resp = await fetch(url, {
58
67
  method: 'POST',
@@ -127,6 +136,8 @@ export const webSearchTool = {
127
136
  }
128
137
  finally {
129
138
  clearTimeout(timer);
139
+ if (externalSignal)
140
+ externalSignal.removeEventListener('abort', onExternalAbort);
130
141
  }
131
142
  },
132
143
  };
@@ -0,0 +1,2 @@
1
+ import type { Tool } from '../types.js';
2
+ export declare const writeFileTool: Tool;
@@ -4,6 +4,7 @@ import { resolve, dirname } from 'node:path';
4
4
  export const writeFileTool = {
5
5
  name: 'write_file',
6
6
  description: 'Create or overwrite a file; parent dirs created.',
7
+ risk: 'confirm',
7
8
  parameters: {
8
9
  type: 'object',
9
10
  properties: {
@@ -0,0 +1,52 @@
1
+ export declare const MAX_FILE_LINES = 2000;
2
+ export declare const MAX_OUTPUT = 20000;
3
+ export declare const MAX_RESULTS = 100;
4
+ /** 进 history 的单条工具结果上限(字符)。push-time 第一层裁剪,保 head + 标记 + tail。 */
5
+ export declare const MAX_HISTORY_RESULT = 8000;
6
+ /** use_skill 结果(SKILL.md 正文)的放宽上限:指令须完整,中截会破坏语义。 */
7
+ export declare const MAX_SKILL_RESULT = 64000;
8
+ /** 微压缩时旧工具结果截到的存根长度(字符)。 */
9
+ export declare const MAX_OLD_TOOL_STUB = 600;
10
+ /** 单条记忆 body 上限(字符)。进 history 前 memory_search 结果另有 MAX_MEMORY_RESULT 兜底。 */
11
+ export declare const MAX_MEMORY_ENTRY = 4000;
12
+ /** 启动注入 systemPrompt 的索引条目上限(遗忘封顶后 active 条目 ≤ MAX_ACTIVE,索引再封一层)。 */
13
+ export declare const MAX_INDEX_ENTRIES = 50;
14
+ /** active 记忆封顶:超则按 recallCount 低 × lastRecalledAt 老 淘汰到 archived。 */
15
+ export declare const MAX_ACTIVE = 100;
16
+ /** 衰减:active + !pinned + (lastRecalledAt|createdAt) 早于 DECAY_DAYS → archived。 */
17
+ export declare const DECAY_DAYS = 30;
18
+ /** GC:archived 超 GC_DAYS → 硬删。 */
19
+ export declare const GC_DAYS = 90;
20
+ /** memory_search 结果(召回的记忆正文)的放宽上限:指令性内容,中截破坏语义,对齐 use_skill。 */
21
+ export declare const MAX_MEMORY_RESULT = 64000;
22
+ export declare const IGNORE: string[];
23
+ /** Hot/Cold 划分:当前 step 起往前 N 个 user turn 之内的工具结果视为 Hot(绝对不压),
24
+ * 之外的视为 Cold(可调度器压)。默认 4 = 跨过 4 个用户问题仍生效。 */
25
+ export declare const HOT_TURN_WINDOW = 4;
26
+ /** Cold 区内可被就地 stub 的 tool 消息最低 age(经过的消费者 push 数)。默认 2,
27
+ * 与 lifecycle.ts DEFAULT_AGE_THRESHOLD 对齐。 */
28
+ export declare const TOOL_OLD_AGE = 2;
29
+ /** 五区预算占比(总和 0.95,留 5% 给 Reserve)。对齐 user 修正版:
30
+ * System 15 / History 20 / Hot Tool 25 / Cold Tool 25 / Summary 10。 */
31
+ export declare const BUDGET_RATIO: {
32
+ readonly system: 0.15;
33
+ readonly history: 0.2;
34
+ readonly toolRecent: 0.25;
35
+ readonly toolOld: 0.25;
36
+ readonly summary: 0.1;
37
+ readonly reserve: 0.05;
38
+ };
39
+ /**
40
+ * plan 模式下从工具 schema 里剔除的工具(模型根本看不到 → 调不到):
41
+ * 写盘 / 命令 / 记忆写入类 + task(派生子 agent,plan 模式只读不可有副作用)。单一事实源,
42
+ * 被 llm(planChatTools)与 agent(防御 backstop)共用。
43
+ * 只读工具(read_file/glob/grep/codegraph/web_search/web_fetch/use_skill/ask_human/memory_search/memory_list)保留。
44
+ */
45
+ export declare const PLAN_DISABLED_TOOLS: Set<string>;
46
+ /**
47
+ * 按当前 isMemoryEnabled() 现算 plan 模式应屏蔽的工具。
48
+ * memoryEnabled=false 时记忆工具整体不在 builtinTools 里,plan 屏蔽集里也无须再列 ——
49
+ * 反之留着只是死名字。统一过滤,避免 Set 里残留与已下架工具不一致的概念性冗余。
50
+ * 调用方(agent/core 串行分支、llm/planChatTools)每次 chat 时调本函数拿当前值。
51
+ */
52
+ export declare function getPlanDisabledTools(): Set<string>;
@@ -0,0 +1,18 @@
1
+ import type { Tool, DropContextFilter, DropContextResult } from './types.js';
2
+ /**
3
+ * 工具注册表。当前 = 内置工具;
4
+ * 未来可在此合并 MCP 工具、用户自定义工具等(见 src/mcp/)。
5
+ */
6
+ export declare const tools: Tool[];
7
+ /**
8
+ * 按名调度工具,统一 try/catch + JSON 解析,返回字符串而非抛错。
9
+ * signal 透传给 tool.execute(经 ctx):长任务工具(run_command/web_fetch)abort 即时取消,
10
+ * 让用户 Ctrl+C 能跟手中断工具执行(而非等命令跑完 / 超时)。
11
+ * opts.skipRollback:子 agent 逻辑隔离用——跳过 recordMutation,子 agent 改动不进主回滚快照链。
12
+ * opts.dropContext:上下文剔除回调(drop_context 工具用),透传给 tool.execute 经 ctx。
13
+ */
14
+ export declare function executeTool(name: string, argsRaw: string, signal?: AbortSignal, opts?: {
15
+ skipRollback?: boolean;
16
+ dropContext?: (filter: DropContextFilter) => DropContextResult;
17
+ }): Promise<string>;
18
+ export type { Tool, ToolContext, DropContextFilter, DropContextResult } from './types.js';
@@ -0,0 +1,42 @@
1
+ /** 工具执行时收到的运行时上下文(可选)。不用的工具可忽略。 */
2
+ export interface ToolContext {
3
+ /** agent 循环的 abort signal(用户 Ctrl+C 中断当前轮)。长任务工具(run_command/web_fetch)
4
+ * 挂监听:abort 即取消(杀子进程 / 取消 fetch),让中断跟手而非等命令跑完或超时。
5
+ * 子 agent 透传主 signal:主 Ctrl+C 树杀子 agent(经 task→spawnAgent→runAgentCore→executeTool)。 */
6
+ signal?: AbortSignal;
7
+ /** 跳过回滚快照记录。子 agent(logical-isolation 模式)的 write_file/edit_file 改动不进主回滚链——
8
+ * 主 /rollback 不撤销子 agent 改动(靠 git 兜底)。主 agent 永远不设此 flag。 */
9
+ skipRollback?: boolean;
10
+ /** 上下文剔除回调(drop_context 工具用):把历史里命中的无关 tool 结果替换为存根(保
11
+ * tool_call_id 配对不变量,只改 content),原地修改 history。由 runAgentCore 闭包注入。
12
+ * 永不动 history[0](system)与当前轮(最后一个 user 消息及之后)的 tool 结果——agent 还在用。
13
+ * 返回剔除统计(条数 / 释放 token / 命中项),供 agent 确认。 */
14
+ dropContext?: (filter: DropContextFilter) => DropContextResult;
15
+ }
16
+ /** drop_context 的筛选条件(各字段 AND 组合,空/缺省 = 该维度不限)。 */
17
+ export interface DropContextFilter {
18
+ /** 只剔除这些工具名的结果(如 ["grep","read_file"]);空/缺省 = 不限工具名。 */
19
+ toolNames?: string[];
20
+ /** 只剔除内容包含所有这些词(AND、大小写不敏感)的结果;空/缺省 = 不限内容。 */
21
+ contains?: string[];
22
+ }
23
+ /** drop_context 的剔除结果(回灌给 agent 供确认)。 */
24
+ export interface DropContextResult {
25
+ /** 实际替换为存根的 tool 消息条数 */
26
+ dropped: number;
27
+ /** 估算释放的 token 数(剔除前后该区段 token 差) */
28
+ freedTokens: number;
29
+ /** 被剔除的 tool 消息(工具名 + tool_call_id 末 6 位)摘要 */
30
+ items: {
31
+ toolName: string;
32
+ toolCallId: string;
33
+ }[];
34
+ }
35
+ /** 工具统一接口。每个工具是一个 name + JSON Schema + execute。 */
36
+ export interface Tool {
37
+ name: string;
38
+ description: string;
39
+ parameters: Record<string, unknown>;
40
+ /** ctx 可选:不关心的工具签名写 execute(args) 即可(TS 允许少参赋多参类型,向后兼容)。 */
41
+ execute: (args: Record<string, unknown>, ctx?: ToolContext) => Promise<string>;
42
+ }
@@ -0,0 +1,67 @@
1
+ /**
2
+ * 工具调用批量折叠渲染(仿 Claude Code):
3
+ * agent 一轮返回 N 个 tool_calls 时,不逐个打印 `● name ↳ result`,
4
+ * 改输出一行摘要 `● Ran N tools · read 3, grep 1, glob 1`;
5
+ * 鼠标点击该摘要行 → 展开完整明细(● 头 + ↳ preview / diff 块),再点折回。
6
+ *
7
+ * 设计要点:
8
+ * - 实时执行 + renderHistory 回放共用本渲染器;
9
+ * - 仅 buffer 写一行,详情行展开时才插入(mid-buffer insert via layout.contentInsertAfter);
10
+ * - 默认折叠;展开/折叠不影响历史回放的 history 结构(history 仍存完整 tool_calls+tool 消息)。
11
+ *
12
+ * 状态全模块级(单实例)——一次 REPL 内所有 batch 共享,清内容区 / 退 alt 屏时统一重置。
13
+ */
14
+ /** 一条工具调用在批内的展示数据(由 agent 的 hooks 累积,endBatch 时收尾)。 */
15
+ export interface BatchEntry {
16
+ name: string;
17
+ /** summarizeToolCall(name, args):单行参数摘要(路径/模式/命令)。 */
18
+ callSummary: string;
19
+ /** summarizeToolResult(name, output):单行结果预览(行数/匹配数/首行)。mutation 工具为 ''。 */
20
+ resultSummary: string;
21
+ /** mutation 工具的成功 diff 块全文(由 renderFileChange 渲染出的多行 ANSI);非 mutation 为 null。
22
+ * 错误或非 mutation 走 resultSummary 的灰字 preview 行。 */
23
+ diffBlock: string | null;
24
+ }
25
+ /** 通知 buffer 整体清空(clearContent / exitAltScreen / 新一轮 turn)——本模块状态同步归零。 */
26
+ export declare function reset(): void;
27
+ /** 新建一个 batch(在 agent 拿到第一条 onToolHeader 时调)。返回 id。 */
28
+ export declare function beginBatch(): string;
29
+ /** 记一条工具调用(在 onToolHeader 时调,与 setEntryResult 配对;entries 顺序 = agent 调用顺序)。 */
30
+ export declare function recordCall(id: string, name: string, callSummary: string): void;
31
+ /** 记一条工具结果(diff 块或单行 preview);agent 在 onToolResult 时调,匹配最后一条未填的 entry。 */
32
+ export declare function recordResult(id: string, name: string, resultSummary: string, diffBlock: string | null): void;
33
+ /** 在 batch 收尾时(onToolBatchEnd):写摘要行 + 登记 summaryAbsIdx;若已展开(回放场景)立即插详情。 */
34
+ export declare function endBatch(id: string, layout: {
35
+ contentWrite(s: string): void;
36
+ contentInsertAfter(after: number, lines: string[]): void;
37
+ totalRows(): number;
38
+ }): void;
39
+ /** 绝对行索引 → 命中 batch id(用于鼠标 release 反查);非摘要行返 null。 */
40
+ export declare function findBatchByAbsLine(absLine: number): string | null;
41
+ /** 当前 batch 是否已展开。 */
42
+ export declare function isExpanded(id: string): boolean;
43
+ /**
44
+ * 切换 batch 展开/折叠;无变化时 no-op。
45
+ * 折叠:从 buffer 删详情行(mid-buffer delete);
46
+ * 展开:把详情行插入摘要行下方(mid-buffer insert)。
47
+ * 同步更新 absLineToBatchId 中所有受影响的索引:
48
+ * - 删除/插入点之后的 batch 摘要行索引相应平移。
49
+ * 含 mutation(write_file/edit_file)的 batch 强制展开——不允许折叠(写盘操作必须始终可见)。
50
+ */
51
+ export declare function toggleBatch(id: string, layout: {
52
+ contentInsertAfter(after: number, lines: string[]): void;
53
+ contentDeleteFrom(startIdx: number, n: number): void;
54
+ }): void;
55
+ /**
56
+ * 当 buffer 中段插/删 N 行后,所有受影响 batch 的 summaryAbsIdx 需平移。
57
+ * 由 layout.contentInsertAfter / contentDeleteFrom 在每次变动后调一次,
58
+ * 参数 afterIdx 是被插入/删除点的绝对索引(插入点之前索引不变;之后索引 += delta)。
59
+ */
60
+ export declare function shiftBatchesAfter(absIdx: number, delta: number): void;
61
+ /** 把已构造好的 BatchEntry[] 直接落成摘要行(用于 renderHistory 回放;不记录 id 也不需可切换)。
62
+ * 含 mutation(write_file/edit_file)时整批展开——与实时 endBatch 行为一致。 */
63
+ export declare function writeSummaryOnly(entries: BatchEntry[], layout: {
64
+ contentWrite(s: string): void;
65
+ contentInsertAfter(after: number, lines: string[]): void;
66
+ totalRows(): number;
67
+ }): void;
@@ -0,0 +1,9 @@
1
+ /** 写入系统剪贴板(OSC52 + 本地原生双通道)。 */
2
+ export declare function copyToClipboard(text: string): void;
3
+ /**
4
+ * 读取系统剪贴板(本地原生工具,OSC52 无法读取——终端不回传)。
5
+ * win32 用 PowerShell -NoProfile Get-Clipboard(比 clip.exe 只写无读更可靠,系统自带无需安装);
6
+ * darwin=pbpaste;linux 依次尝试 wl-paste / xclip -o / xsel -o,装了哪个用哪个。
7
+ * 都失败返回空串(不抛),调用方按"无内容可贴"处理。
8
+ */
9
+ export declare function readClipboard(): Promise<string>;
@@ -0,0 +1,55 @@
1
+ export declare function reset(): void;
2
+ /** 喂一个 SGR 码(\\x1B[...m):入 curRaw,并更新活跃状态(遇 reset 清空)。 */
3
+ export declare function feedSgr(code: string): void;
4
+ /** 喂一个可见字符(已按码点取出)。 */
5
+ export declare function feedChar(ch: string): void;
6
+ /** 提交当前行为自洽物理行,开新空行(SGR 状态继承到下行)。在 \\n / 折行 / tab 换行时调。 */
7
+ export declare function breakRow(): void;
8
+ /**
9
+ * 弹出 buffer 末尾 n 物理行(供 layout.rewindContent 撤回刚写入段用)。
10
+ * 当前行先 commit 再裁剪(消除 hasCurrent 边界);n ≥ totalRows 则全清,
11
+ * 但**不动 segMark** —— recall 走普通 contentWrite、不撞 md 段;
12
+ * segMark 由 reset() / commitSegment() 清,recall 不掺和。
13
+ */
14
+ export declare function rewind(n: number): void;
15
+ /** 标记段起点:快照当前缓冲状态,供 setLines 截断定位段头(md 流式渲染每 chunk 截断重渲)。 */
16
+ export declare function beginSegment(): void;
17
+ /**
18
+ * 用预渲染的自洽 ANSI 行替换当前段(从 segMark 起),供 markdown 流式渲染:
19
+ * layout.contentWriteMd 每 chunk 把累积 text 经 renderMarkdown 渲成自洽行,调此替换缓冲段。
20
+ * 截断 rows 到 segMark.rowIdx(擦上次渲染)+ push 新行;curSgr 复位为默认(行末 reset);
21
+ * **保留 segMark**(下次 setLines 还要截断),由 commitSegment 清除。
22
+ * 行须各自自洽(行内 SGR 自带、行末 reset)——不经 feedChar/feedSgr,直接入 rows,
23
+ * 故 setLines 后 hasCurrent=false(snapshot 只返 rows;续写位由 layout 跟踪)。
24
+ */
25
+ export declare function setLines(lines: string[]): void;
26
+ /** 提交段:清 segMark,后续写入不再被 setLines 截断(md 段结束、非 md 内容接续时调)。 */
27
+ export declare function commitSegment(): void;
28
+ /** 距尾 offset 行、取 count 行的窗口(映射到屏 1..count)。offset=0 即尾窗。 */
29
+ export declare function sliceFromEnd(offset: number, count: number): string[];
30
+ /** 快照总行数(含当前行),供 scrollBy 钳位。 */
31
+ export declare function totalRows(): number;
32
+ /** 取绝对行索引(0-based,含当前行)的原始自洽行;越界返 null。供鼠标选区文本提取。 */
33
+ export declare function lineAt(abs: number): string | null;
34
+ /**
35
+ * 在绝对行索引 after(0-based,已 commit)之后插入 N 条自洽行。
36
+ * 用于「折叠摘要行下展开明细」——把详情行在已写入摘要行后面塞入缓冲,
37
+ * 不重写尾部已有内容;且不影响更早的 buffer 行(hasCurrent 先 commit 再 splice)。
38
+ *
39
+ * 行须自洽(每行带行末 \x1B[0m),不经 feedChar/feedSgr,直接入 rows。
40
+ * after < 0 视为在所有已 commit 行之前插入;after ≥ 已 commit 行数则追加到末尾。
41
+ * 不动 segMark——此函数用于非 md 路径(BatchRenderer 展开/折叠);
42
+ * md 段切回 layout.contentWriteMd 时 setLines 仍按 segMark 截断。
43
+ *
44
+ * 后置条件:插入后 hasCurrent=false(新空行不由本函数建立);调用方须自行决定续写位
45
+ * (BatchRenderer 在插入后调 layout.contentWrite 续写,新 \n 自然在详情块后建新行)。
46
+ */
47
+ export declare function insertAfter(after: number, lines: string[]): void;
48
+ /**
49
+ * 从绝对行索引 startIdx(0-based,已 commit)起删 n 行。
50
+ * 用于「已展开明细折回摘要」——把详情行从中段裁掉,保留摘要行和后续内容。
51
+ * startIdx 越界或 n <= 0 直接 no-op。hasCurrent 时先 commit(同 insertAfter)。
52
+ *
53
+ * 后置条件:删除后 hasCurrent=false。后续 layout.contentWrite 自然续写。
54
+ */
55
+ export declare function deleteFrom(startIdx: number, n: number): void;