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
@@ -0,0 +1,79 @@
1
+ import type { ChatMessage } from '../llm/index.js';
2
+ /** 五区分账(占比对齐 CONTEXT_WINDOW)。顺序固定,便于遍历。 */
3
+ export declare const BUDGET_LAYERS: readonly ["system", "history", "toolRecent", "toolOld", "summary", "reserve"];
4
+ export type BudgetLayer = (typeof BUDGET_LAYERS)[number];
5
+ /** 占比(总和 = 0.95,留 5% 给 Reserve)。对齐用户修正版:
6
+ * Recent Tool 25%(原 40% 偏大,因 Hot 区不该被压)+ Old Tool 25% 同等 +
7
+ * History 20% + System 15% + Summary 10%(平时 0 占用,触发后才用) */
8
+ export declare const BUDGET_RATIO: Record<BudgetLayer, number>;
9
+ /** Hot/Cold 划分:当前 step 起往前 HOT_TURN_WINDOW 个 user turn 之内的工具结果视为 Hot,
10
+ * 之外的视为 Cold。0 = 全 Cold(等同老路径);越短 Hot 越小,压缩越激进。 */
11
+ export declare const HOT_TURN_WINDOW = 4;
12
+ /** 工具消息推入历史后,经过的「消费者 push 次数」即 age。
13
+ * Cold 区内:age ≥ TOOL_OLD_AGE 的非观察类工具结果可被调度器就地 stub。
14
+ * 默认 2 = 跨过 2 个消费者 push 仍未被消费,等同 lifecycle 的 DEFAULT_AGE_THRESHOLD。 */
15
+ export declare const TOOL_OLD_AGE = 2;
16
+ /** 从 history 末尾向前找最后一个 user 消息的索引;无 user 返 -1。 */
17
+ export declare function lastUserIndex(history: ChatMessage[]): number;
18
+ /** 从 idx 处向前数第 N 个 user turn 的边界 index(含该 user 之后的内容)。
19
+ * 用于把 history 切成 Hot 区(tail 一段,endExclusive=history.length)与 Cold 区(0..endExclusive)。
20
+ * 若 N 个 user 不足,Hot 区 = history.length(全保护);Cold 区空,无压缩目标。 */
21
+ export declare function userTurnBoundary(history: ChatMessage[], window: number): number;
22
+ /** 单区预算分配。绝对值 = ratio * window。 */
23
+ export interface LayerBudget {
24
+ actual: number;
25
+ budget: number;
26
+ overBudget: boolean;
27
+ /** overBudget 比值 = max(0, actual - budget) / budget;无超 = 0。
28
+ * 调度器用此值做 ROI 排序——溢出越多,优先处理。 */
29
+ overRatio: number;
30
+ }
31
+ /** 一次评估的完整报告(供 agent/core.ts 决策)。 */
32
+ export interface BudgetReport {
33
+ step: number;
34
+ total: number;
35
+ window: number;
36
+ layers: Record<BudgetLayer, LayerBudget>;
37
+ /** 实际超预算的层(按 overRatio 降序,排前面先处理)。 */
38
+ triggers: BudgetLayer[];
39
+ /** 总占用超总阈(0.85*window)的兜底触发 — 单独字段,与 layers.triggers 分开。 */
40
+ totalOver: boolean;
41
+ /** Hot/Cold 边界:Cold 区 = [1, hotBoundary);Hot 区 = [hotBoundary, length)。
42
+ * agent/core.ts 拿到后可对 Cold 区做就地 stub,Hot 区只 cap。 */
43
+ hotBoundary: number;
44
+ }
45
+ /** 评估当前 history 的五区预算(纯函数,改不动 history)。
46
+ * 传入 step 是当前所在 step 编号(agent 循环 step 变量),用于日志/调试。 */
47
+ export declare function evaluateBudget(history: ChatMessage[], window: number, step?: number): BudgetReport;
48
+ /** 调度器决策动作(纯数据,不动 history)。agent/core.ts 据此调用既有闸。 */
49
+ export type ScheduleAction = {
50
+ kind: 'warn';
51
+ layer: BudgetLayer;
52
+ reason: string;
53
+ } | {
54
+ /** 对 Cold 区(hotBoundary 之前)的 tool 消息按 ROI 做 L1→L2→L3 渐进压缩。
55
+ * 注意:Hot 区永不发此 action——精细剔除由 lifecycle/pruner/drop_context 负责。 */
56
+ kind: 'shrink_cold_tools';
57
+ level: 1 | 2 | 3;
58
+ } | {
59
+ /** Hot 区只 cap(降单条上限),不 stub;aggressive = true 时调低阈值走更严的 cap。
60
+ * 精细剔除(cap 不够时)由 lifecycle age stub 与 drop_context 工具兜底。 */
61
+ kind: 'cap_hot_tools';
62
+ aggressive: boolean;
63
+ } | {
64
+ kind: 'compact_history';
65
+ focus?: string;
66
+ };
67
+ /** 根据 BudgetReport 生成调度动作(从轻到重,直至总占用回落到 0.85 以下)。
68
+ * 规则:
69
+ * - system 超 → warn(不压,配置问题不是内容问题)
70
+ * - toolOld 超 → 先 L1(中截超大)→ L2(same-path 已有 relevance)→ L3(age stub,新增)
71
+ * - toolRecent 超 → cap(只降低单条上限,不 stub)
72
+ * - history 超 或 totalOver → compact_history(调 maybeCompact / compactHistory)
73
+ * - summary 超 → 不动(摘要本身就压缩产物,删它等于丢历史,只能放任或扩 Recent 预算) */
74
+ export declare function scheduleActions(report: BudgetReport): ScheduleAction[];
75
+ /** 拍平成人类可读(供 /context 命令与 check-budget 脚本用)。 */
76
+ export declare function formatReport(report: BudgetReport): string;
77
+ /** 便捷:把 history 一把估成总 token 数(给 cap.js 等复用,避免重复实现)。
78
+ * 注意:此处是粗估(只看 content 长度),不区分五区——只用于「系统层整体还剩多少」快查。 */
79
+ export declare function quickEstimate(history: ChatMessage[]): number;
@@ -0,0 +1,14 @@
1
+ import type { ContextKind } from './types.js';
2
+ /**
3
+ * 判定 ContextKind。
4
+ * - 有 BY_NAME 强先验 → 用之(内置工具确定性强)。
5
+ * - 否则形状启发(MCP / 未来工具)。
6
+ * - 都不中 → passthrough(不动)。
7
+ *
8
+ * @param toolName 工具名
9
+ * @param output 工具原始输出(形状启发用;有 BY_NAME 时不读)
10
+ * @param _args 已解析参数(预留:未来 read_file 的 offset/limit 可影响 code 编码策略;Phase 1 不用)
11
+ */
12
+ export declare function classify(toolName: string, output: string, _args: Record<string, unknown> | null): ContextKind;
13
+ /** 暴露 BY_NAME 副本供调试 / 未来 /context 展示(只读视图)。 */
14
+ export declare function knownToolKinds(): Record<string, ContextKind>;
@@ -0,0 +1,11 @@
1
+ /** 去 ANSI CSI 序列(颜色 / 光标 / 清屏等)。语义无损:颜色码不含信息。 */
2
+ export declare function stripAnsi(s: string): string;
3
+ /**
4
+ * 折叠连续空行(只含空白字符的行)≥ threshold → 单个空行。
5
+ * 用于 prose / source dump(web_fetch / use_skill / task / codegraph):HTML→文本与 markdown 常留多余空行,
6
+ * 多空行与单空行语义等价,折叠无损。默认 threshold=3(只动真正过量的空行,常见 ≤2 空行不动)。
7
+ *
8
+ * 注意:用 `.trim() === ''` 判空——故 read_file 的 ` 2\t`(行号前缀 + tab,trim 后剩 `2`)不会被
9
+ * 视作空行。read_file 的空行折叠见 code encoder(前缀感知)。
10
+ */
11
+ export declare function collapseBlankRuns(text: string, threshold?: number): string;
@@ -0,0 +1,2 @@
1
+ import type { ContextEncoder } from '../types.js';
2
+ export declare const codeEncoder: ContextEncoder;
@@ -0,0 +1,14 @@
1
+ import type { ContextEncoder } from '../types.js';
2
+ /**
3
+ * Doc Encoder(web_fetch / use_skill):折叠连续空行(≥3 → 1)。
4
+ *
5
+ * 输入:
6
+ * - web_fetch 的 `URL (HTTP ...)\n\n<body>`(HTML→文本,常留多余空行)。
7
+ * - use_skill 的 `# Skill: name\n\n<body>`(SKILL.md 正文,frontmatter 已剥离)。
8
+ * 输出:空行折叠;正文 / 指令逐字保留。
9
+ *
10
+ * 不变量:URL 前缀行 / Skill 标题行保留;正文文本逐字保留(仅折叠空行——markdown / HTML 多空行与
11
+ * 单空行语义等价,无损)。use_skill 走放宽 cap(MAX_SKILL_RESULT)保指令完整——本 encoder 在 cap 前先
12
+ * 折叠空行,减少被 cap 截断的风险。
13
+ */
14
+ export declare const docEncoder: ContextEncoder;
@@ -0,0 +1,11 @@
1
+ import type { ContextEncoder } from '../types.js';
2
+ /**
3
+ * Graph Encoder(codegraph):去 ANSI + 折叠连续空行(≥3 → 1)。
4
+ *
5
+ * 输入:codegraph CLI 返回的 `[退出码 N]\n<源码 + 调用路径>`(可能含 ANSI 颜色、多余空行)。
6
+ * 输出:去 ANSI + 空行折叠;结构(调用路径块、源码段)不动。
7
+ *
8
+ * 不变量:退出码行保留;源码与调用路径文本逐字保留(仅去颜色码 + 折叠空行);不删内容行。
9
+ * 保守:不重构调用路径 / 不去重源码(codegraph CLI 输出格式未稳定,需先采样真实输出定不变量,留后续)。
10
+ */
11
+ export declare const graphEncoder: ContextEncoder;
@@ -0,0 +1,2 @@
1
+ import type { ContextEncoder } from '../types.js';
2
+ export declare const builtinEncoders: ContextEncoder[];
@@ -0,0 +1,2 @@
1
+ import type { ContextEncoder } from '../types.js';
2
+ export declare const logEncoder: ContextEncoder;
@@ -0,0 +1,2 @@
1
+ import type { ContextEncoder } from '../types.js';
2
+ export declare const memoryEncoder: ContextEncoder;
@@ -0,0 +1,11 @@
1
+ import type { ContextEncoder } from '../types.js';
2
+ /**
3
+ * 兜底 encoder:identity,原样返回。
4
+ * - classifier 未命中任何 kind(返回 'passthrough')时用。
5
+ * - pipeline 总开关关闭(MOCODE_CONTEXT_OPTIMIZE=false)时,所有 kind 都走它 → 行为与改造前逐字节一致。
6
+ * - Phase 1 阶段 registry 只注册它 → 全链路零行为变化。
7
+ * - 任何 encoder 报错时,pipeline catch 后回落到它(传原 output)。
8
+ *
9
+ * 永不抛错:output 可能是任意字符串(含 ANSI / 多行 / 非法 UTF-8 片段),identity 直接返回,无解析风险。
10
+ */
11
+ export declare const passthroughEncoder: ContextEncoder;
@@ -0,0 +1,2 @@
1
+ import type { ContextEncoder } from '../types.js';
2
+ export declare const searchEncoder: ContextEncoder;
@@ -0,0 +1,12 @@
1
+ import type { ContextEncoder } from '../types.js';
2
+ /**
3
+ * Summary Encoder(task):折叠连续空行(≥3 → 1)。
4
+ *
5
+ * 输入:task 工具返回的子 agent 最终摘要文本(已是摘要,可能含多余空行),可能带截断尾标
6
+ * `…(子 agent 摘要已截断 N 字符)`。
7
+ * 输出:空行折叠;摘要文本逐字保留。
8
+ *
9
+ * 不变量:摘要事实文本逐字保留(仅折叠空行);截断尾标保留。子 agent 摘要已是高密度文本,只做轻量去冗余,
10
+ * 不再做进一步压缩(避免丢事实)。
11
+ */
12
+ export declare const summaryEncoder: ContextEncoder;
@@ -0,0 +1,2 @@
1
+ import type { ContextEncoder } from '../types.js';
2
+ export declare const tableEncoder: ContextEncoder;
@@ -0,0 +1,2 @@
1
+ import type { ContextEncoder } from '../types.js';
2
+ export declare const treeEncoder: ContextEncoder;
@@ -0,0 +1,6 @@
1
+ export { optimizeToolResult } from './pipeline.js';
2
+ export type { ContextKind, ContextEncoder, EncoderInput, EncoderOutput, } from './types.js';
3
+ export { classify, knownToolKinds } from './classifier.js';
4
+ export { registerEncoder, registerAll, getEncoder, registeredKinds, } from './registry.js';
5
+ export { evaluateBudget, scheduleActions, formatReport, quickEstimate, userTurnBoundary, lastUserIndex, BUDGET_LAYERS, BUDGET_RATIO, HOT_TURN_WINDOW, TOOL_OLD_AGE, } from './budget.js';
6
+ export type { BudgetLayer, LayerBudget, BudgetReport, ScheduleAction, } from './budget.js';
@@ -0,0 +1,51 @@
1
+ import type { ChatMessage } from '../llm/index.js';
2
+ /** 工具消息的观察者生命周期状态。 */
3
+ export type LifeState = 'LIVE' | 'REFERENCED' | 'OBSOLETE' | 'STUB';
4
+ /**
5
+ * Observation Lifecycle Engine。
6
+ * 每个 runAgentCore 实例持一个;pushToolResult 出口调 pushTool、mutation 分支调 pushMutation。
7
+ * 内部 try/catch 兜底,对外永不抛错。
8
+ */
9
+ export declare class LifecycleEngine {
10
+ private readonly ageThreshold;
11
+ /** 工具消息 idx → 状态。 */
12
+ private readonly states;
13
+ /** 工具消息 idx → 被消费的次数(同一上游被多次消费也只算 REFERENCED,不计并发)。 */
14
+ private readonly consumerCount;
15
+ /** 工具消息 idx → 自 push 以来的「消费者 push」次数(用于老化判定)。
16
+ * 每次 pushTool 触发,所有 LIVE 工具消息 age++。 */
17
+ private readonly age;
18
+ /** producer 路径 → 生产者工具消息 idx 列表(逆查用:某个 path 被消费时,反查上游 producer)。
19
+ * 注意:不存 read_file,因为 read 自身就是消费者不充当 producer。 */
20
+ private readonly producersByPath;
21
+ /** 当前步序号(用于 age 老化:每次 pushTool 自增,对比 age 阈值)。 */
22
+ private step;
23
+ /** 最后 user 索引缓存(pushTool 时重算;pushMutation 时也重算,因为 mutation 可能跟 user 同行)。 */
24
+ private lastUser;
25
+ constructor(ageThreshold?: number);
26
+ /** 新工具结果 push 进 history 时调;idx = history.length - 1。
27
+ * mutation 工具(edit_file/write_file)的 push 跳过本轮的 autoStubOrphans(由调用方在
28
+ * pushMutation 标完 read REFERENCED 之后再触发),避免刚被 mutation 消费的 read 被提前 STUB。 */
29
+ pushTool(history: ChatMessage[], idx: number): void;
30
+ /** mutation 工具(edit_file/write_file)push 后调。语义与 pushTool 一致,但额外标记「被 mutation 消费」的 read。
31
+ * 注意:本层不直接 stub read(那是 Relevance Pruner 的职责);本层只更新状态图。
32
+ * 注意:puhToolResult 出口已经登记过 mutation 本身,这里不再调 pushTool(避免 age 翻倍)。 */
33
+ pushMutation(history: ChatMessage[], mutationIdx: number, path: string): void;
34
+ /** 老化自动 STUB:扫描所有 LIVE(且非观察类)且 age ≥ 阈值且不在保护区的工具消息 → OBSOLETE → STUB。 */
35
+ private autoStubOrphans;
36
+ /** 实际替换 content 为存根。 */
37
+ private stubOne;
38
+ /** 找某条 tool 消息对应的 assistant.tool_calls.arguments。 */
39
+ private findToolArgs;
40
+ /** 拿某 idx 的当前状态;不在图里返 null。 */
41
+ getState(idx: number): LifeState | null;
42
+ /** 拿当前各状态计数。供 /context 显示「live=N, referenced=M, obsolete=K, stubbed=S」。 */
43
+ stats(): {
44
+ live: number;
45
+ referenced: number;
46
+ obsolete: number;
47
+ stubbed: number;
48
+ };
49
+ }
50
+ /** 默认单例工厂。runAgentCore 入口 new 一个,后续 pushTool / pushMutation 共享。 */
51
+ export declare function createLifecycleEngine(ageThreshold?: number): LifecycleEngine;
@@ -0,0 +1,9 @@
1
+ /**
2
+ * 优化工具结果为进 LLM 的 tool 消息 content。
3
+ *
4
+ * @param name 工具名
5
+ * @param output executeTool 的原始返回字符串
6
+ * @param argsRaw 工具 arguments 原始 JSON 字符串(tc.arguments,可空;未传则 args=null)
7
+ * @returns 进 history 的 content 字符串(永不抛错)
8
+ */
9
+ export declare function optimizeToolResult(name: string, output: string, argsRaw?: string): string;
@@ -0,0 +1,9 @@
1
+ import type { ContextEncoder, ContextKind } from './types.js';
2
+ /** 注册一个 encoder(后注册覆盖先注册,允许 MCP 覆盖默认)。返回 encoder 自身供链式。 */
3
+ export declare function registerEncoder(enc: ContextEncoder): ContextEncoder;
4
+ /** 批量注册(启动期 pipeline 调一次)。幂等:重复调忽略。 */
5
+ export declare function registerAll(list: ContextEncoder[]): void;
6
+ /** 取某 kind 的 encoder;未注册返 undefined(pipeline 回落 passthrough)。 */
7
+ export declare function getEncoder(kind: ContextKind): ContextEncoder | undefined;
8
+ /** 调试:列出已注册 kind。 */
9
+ export declare function registeredKinds(): ContextKind[];
@@ -0,0 +1,65 @@
1
+ import type { ChatMessage } from '../llm/index.js';
2
+ /**
3
+ * 维护「path → 该 path 所有 read_file tool 消息的 history index」映射。
4
+ * - observePush:把刚 push 的 read_file tool 消息登记,并把同 path 的"更早" read 全部 stub。
5
+ * - observeMutation:把该 mutation path 的"在 mutation 之前的" read 全部 stub。
6
+ *
7
+ * 设计:每个 agent 会话(每个 runAgentCore 实例)持有一个 pruner。会话结束/换 plan 时
8
+ * 可新建;不持久化(history 重建时索引自然过期)。
9
+ *
10
+ * 零依赖:仅依赖 ChatMessage 形状;不 import llm / tools / agent。
11
+ */
12
+ export declare class RelevancePruner {
13
+ /** path → [history index, ...] 按插入序;最新在末尾。 */
14
+ private readonly readByPath;
15
+ /** 把刚 push 的消息通知 pruner。
16
+ * - 只处理 tool 消息(role==='tool')。
17
+ * - 只关心 read_file:登记 + 反向 stub 同 path 旧 read。
18
+ * - 非 read_file 的 tool 消息:无操作(本层只管 read_file)。
19
+ * - 非 tool 消息(assistant / user / system):无操作。
20
+ */
21
+ observePush(history: ChatMessage[], msg: ChatMessage): void;
22
+ /**
23
+ * 把该 mutation path 的"在 mutation 之前的" read 全部 stub。
24
+ * 通常用于 edit_file / write_file 工具:mutation 之后,之前的 read_file(p) 内容
25
+ * 已失效(已不再是文件当前状态),模型后续若依赖旧 read 来 edit_file 会失败,但 edit_file
26
+ * 的 old_string 来自模型记忆/后读,不依赖旧 read 结果文本。
27
+ *
28
+ * 调用时机:agent/core.ts 在 mutation 工具调用的 pushToolResult 之后立即调;
29
+ * 此时 history 末尾就是 mutation 的 tool 消息,prior reads 指 < idx。
30
+ */
31
+ observeMutation(history: ChatMessage[], path: string): void;
32
+ /**
33
+ * 把 history 里 "path 同 + index < beforeIdx + 不在当前轮保护区" 的所有 read_file
34
+ * tool 消息替换为存根(只改 .content,不动 id / 数组结构)。
35
+ *
36
+ * 实现:
37
+ * - 用 readByPath[path] 直接拿到所有 index(已登记过),筛 < beforeIdx 的 stub。
38
+ * - 同时扫一遍 [1, beforeIdx) 区间找未登记的(防御:索引可能漏登;不依赖索引也能 stub,
39
+ * 保证正确性。索引只用于"避免重复扫全表"的优化)。
40
+ * - protectedFrom = lastUserIndex(history):user 之后一律不动。
41
+ * - 幂等:已是 STUB_PREFIX 的跳过。
42
+ */
43
+ private stubPriorReads;
44
+ }
45
+ /** 默认单例:每个 agent 循环一个。runAgentCore 入口 new 一个,后续 observe 共享。 */
46
+ export declare function createRelevancePruner(): RelevancePruner;
47
+ /**
48
+ * 扫 history,统计被相关性裁剪 stub 的 read_file tool 消息(条数 + 原字节数)。
49
+ * 供 /context 渲染统计行用(让用户直观看到「prune 帮了多少」)。
50
+ * 永不抛错(对齐本模块契约);history 为空 / 无 stub 时返零值。
51
+ *
52
+ * 注意:stub 后只剩 stub 字符串(原 content 已丢失),故只能从 stub 字符串里 parse
53
+ * 原字节数,误差 = stub 时记录的 content.length(精确);token 估算走 estimateTokens。
54
+ */
55
+ export declare function computePruneStats(history: ChatMessage[]): {
56
+ stubbed: number;
57
+ /** 原 content 总字节数(仅 stubbed 的)。 */
58
+ originalChars: number;
59
+ /** 反推原 token 数(粗略:estimateTokens(originalChars 字符))。 */
60
+ originalTokens: number;
61
+ /** 当前 stub 字符串总字节数。 */
62
+ stubChars: number;
63
+ /** 估算释放的 token 数(originalTokens - 当前 stub 占的 token)。 */
64
+ freedTokens: number;
65
+ };
@@ -0,0 +1,36 @@
1
+ /** Context 的数据类型。classifier 据工具名 + 输出形状判定,选 encoder。 */
2
+ export type ContextKind = 'tree' | 'search' | 'graph' | 'log' | 'code' | 'table' | 'memory' | 'doc' | 'status' | 'summary' | 'diff' | 'ast' | 'repo' | 'passthrough';
3
+ /** encoder 的输入。pipeline 解析 argsRaw 后传入。 */
4
+ export interface EncoderInput {
5
+ /** 工具名(强先验信号)。 */
6
+ toolName: string;
7
+ /** 工具原始输出字符串(executeTool 的返回值,未经任何编码)。 */
8
+ output: string;
9
+ /** 已解析的工具参数;非法或空返 null。encoder 可据此做上下文感知编码(如 read_file 的 offset/limit)。 */
10
+ args: Record<string, unknown> | null;
11
+ /** 软目标字符数(来自 tools/constants.ts 的 cap 常量,按工具名取)。encoder 应尽量压到 budget 内,
12
+ * 但最终长度裁剪仍由 pipeline 末尾的 capToolResultForHistory 兜底(保 head+标记+tail)。 */
13
+ budget?: number;
14
+ }
15
+ /** encoder 的输出。 */
16
+ export interface EncoderOutput {
17
+ /** 编码后文本(喂给 LLM 的 tool 消息 content)。 */
18
+ text: string;
19
+ /** 编码元数据(调试 / 未来 /context 统计用;不影响喂给 LLM 的内容)。 */
20
+ meta?: {
21
+ kind: ContextKind;
22
+ originalLen: number;
23
+ encodedLen: number;
24
+ /** 给调试者的备注(如"12 files · tree-encoded")。 */
25
+ note?: string;
26
+ };
27
+ }
28
+ /**
29
+ * Encoder 统一接口:一类型一 encoder,纯函数,不抛错(失败由 pipeline 兜底)。
30
+ * 扩展:在 encoders/ 加 xxx.ts 导出 ContextEncoder,在 encoders/index.ts 的 builtinEncoders 加一行。
31
+ * 无需动 agent / llm / core。
32
+ */
33
+ export interface ContextEncoder {
34
+ kind: ContextKind;
35
+ encode(input: EncoderInput): EncoderOutput;
36
+ }
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,19 @@
1
+ /**
2
+ * 模型能力检测:仅用于 /image 等多模态输入的友好提示。
3
+ *
4
+ * 策略 — 保守 + 显式白名单/黑名单:
5
+ * - 命中 KNOWN_TEXT_ONLY_PREFIXES 任一前缀 → false(确定无视觉)
6
+ * - 命中 KNOWN_VISION_FAMILIES 任一前缀 → true(确定有视觉)
7
+ * - 其它(未识别 / 自定义代理 / 新发布模型)→ 默认 true(放行,让 API 拒收兜底)
8
+ *
9
+ * 理由:视觉能力在 2024 后已成新模型默认;自定义 OpenAI 代理常把上游视觉模型重命名;
10
+ * 过度保守会误伤合法配置。
11
+ */
12
+ /**
13
+ * 判断模型是否支持视觉(多模态 image_url)。
14
+ * - 模型未配置(`config.model` 为空或 default 兜底字符串)→ true(不阻断,等 API 报错)
15
+ * - 命中 KNOWN_TEXT_ONLY_PREFIXES 任一前缀 → false(确定无视觉,优先查,避免 gpt-4o-mini vs -search 系列名冲突)
16
+ * - 命中 KNOWN_VISION_FAMILIES 任一前缀 → true
17
+ * - 其它(未识别 / 自定义代理 / 新发布模型)→ true(保守放行)
18
+ */
19
+ export declare function modelSupportsVision(model: string): boolean;
@@ -0,0 +1,111 @@
1
+ import OpenAI from 'openai';
2
+ /**
3
+ * 运行时重建 OpenAI 客户端(/model 切换 baseURL/apiKey 后调)。
4
+ * config.model 已在 chat() 每次读取(热切),但 client 的 baseURL/apiKey 是构造时固化的实例字段,
5
+ * 改 config 后必须重建 client 才能让新 baseURL/apiKey 对后续请求生效。
6
+ * 子 agent 复用本模块 chat(),故只此一处重建即全链路生效。
7
+ */
8
+ export declare function reconfigureClient(): void;
9
+ /**
10
+ * 判定一个 chat 失败是否值得重试。
11
+ * 用户中断(signal.aborted / AbortError / APIUserAbortError)始终返回 false,避免退避中把中断吞了。
12
+ * 4xx(除 429)全不重试 —— 这是客户端请求错,重试只会再错一次。
13
+ */
14
+ export declare function isRetryableError(err: unknown, signal?: AbortSignal): boolean;
15
+ /** 从 OpenAI APIError.headers 解析 Retry-After(秒);不支持或缺失返回 undefined。封顶 RETRY_MAX_MS。 */
16
+ export declare function getRetryAfterMs(err: unknown): number | undefined;
17
+ /** 第 N 次失败后等多久(retryAfterMs 有就用它,否则指数;再加 ±RETRY_JITTER 抖动)。 */
18
+ export declare function computeBackoff(attempt: number, retryAfterMs?: number): number;
19
+ type CreateImpl = (body: Record<string, unknown>, opts: {
20
+ signal?: AbortSignal;
21
+ } | undefined) => Promise<AsyncIterable<unknown>>;
22
+ /** 仅供单测用:覆盖 chat() 内部实际调用的 create 桩。生产代码不要碰。 */
23
+ export declare function __setChatCreateImpl(impl: CreateImpl | null): void;
24
+ export type ChatMessage = OpenAI.Chat.Completions.ChatCompletionMessageParam;
25
+ /** 把内部工具定义转成 OpenAI 的 tool 格式 */
26
+ export declare const chatTools: OpenAI.Chat.Completions.ChatCompletionTool[];
27
+ /**
28
+ * plan 模式用的受限工具 schema:剔除写盘 / 命令 / 记忆写入类(getPlanDisabledTools())。
29
+ * 模型在 plan 模式下只看得到只读工具 → 调不到会改文件的工具。runAgent 在 plan 模式传给 chat()。
30
+ *
31
+ * 注意:planChatTools 是顶层 const(模块初始化时一次性求值);若运行时 /memory_switch 关闭
32
+ * 记忆,这里仍是按当前 isMemoryEnabled() 算出的快照——重启 REPL 才完全生效。
33
+ */
34
+ export declare const planChatTools: OpenAI.Chat.Completions.ChatCompletionTool[];
35
+ export interface ToolCallRef {
36
+ id: string;
37
+ name: string;
38
+ arguments: string;
39
+ }
40
+ /** 一次 chat 调用返回的真实 token 用量(include_usage 时由后端给出)。 */
41
+ export interface ChatUsage {
42
+ promptTokens: number;
43
+ completionTokens: number;
44
+ totalTokens: number;
45
+ /** prompt 中命中 cache 的 token 数(后端未报则为 0)。
46
+ * 计费时这部分按折扣价(DeepSeek 命中 $0.014/M vs 未命中 $0.14/M,差 10×)或免费
47
+ * ——成本监控要从 promptTokens 中剔除,否则高估一个数量级。
48
+ * 多 provider 字段名不一致,见 extractUsageExtras。 */
49
+ cachedTokens: number;
50
+ /** completion 中"思考"消耗的 token(CoT 模型:OpenAI o1 / DeepSeek R1 / GLM-Z1)。
51
+ * 仍按 completion 全价计费,但对调试 thinking 长度有用。 */
52
+ reasoningTokens: number;
53
+ }
54
+ /**
55
+ * 多 provider 兼容的 cache / reasoning 字段提取。
56
+ * 不同后端报 cached 字段名差异巨大,这里按"最常见的几种"顺序 probe,
57
+ * 首个合法非负数字即用(0 也算合法 —— cache miss 是合法状态,不是"无数据")。
58
+ * 字段全缺 → 0,UI 不会显示任何额外标注(零行为变化)。
59
+ *
60
+ * 已实测 / 字段名已知:
61
+ * - OpenAI / Azure / 多数 OpenAI 兼容中转:
62
+ * prompt_tokens_details.cached_tokens
63
+ * - DeepSeek(含 R1):
64
+ * prompt_cache_hit_tokens(扁平,顶层)
65
+ * - Anthropic Claude:
66
+ * cache_read_input_tokens
67
+ * - Moonshot Kimi / GLM-4.6 / Qwen:同 OpenAI 标准
68
+ * - Ollama / 本地 vLLM / 其它:无 usage details → 0(零行为变化)
69
+ *
70
+ * reasoning 字段(CoT 模型):
71
+ * - OpenAI o1 / DeepSeek R1 / GLM-Z1:
72
+ * completion_tokens_details.reasoning_tokens
73
+ * - 其它(个别):reasoning_tokens(顶层)
74
+ */
75
+ export declare function extractUsageExtras(usage: unknown): {
76
+ cachedTokens: number;
77
+ reasoningTokens: number;
78
+ };
79
+ export interface ChatResult {
80
+ content: string | null;
81
+ toolCalls: ToolCallRef[];
82
+ usage?: ChatUsage;
83
+ }
84
+ /** 流式回调:文本增量 / 首个 tool_call 工具名。 */
85
+ export interface StreamHandlers {
86
+ onText?: (delta: string) => void;
87
+ /** 首次得知某个 tool_call 的工具名时回调——模型开始生成工具调用参数(可能很长,如 write_file 大段内容),调用方可据此启「生成中」spinner,避免内容区干等。 */
88
+ onToolCall?: (name: string) => void;
89
+ }
90
+ /**
91
+ * 流式调一次 LLM:增量回调文本,内部累加 tool_calls 片段。
92
+ * tool_calls 跨 chunk 按 index 累加(id / name / arguments 拼接)。
93
+ * include_usage 时末尾 chunk 携带 usage,先读再 continue(末尾 chunk 无 delta)。
94
+ *
95
+ * 包了一层重试:429/5xx/timeout/网络错按指数退避重试(默认 4 次),400/401/用户中断立即抛。
96
+ * 重试由 chat() 统一管,chatOnce() 只负责单次请求,职责单一便于单测。
97
+ */
98
+ export declare function chat(messages: ChatMessage[], handlers?: StreamHandlers, signal?: AbortSignal,
99
+ /** 覆盖默认工具 schema;plan 模式传 planChatTools(只读子集),缺省=全量 chatTools。 */
100
+ toolsOverride?: OpenAI.Chat.Completions.ChatCompletionTool[]): Promise<ChatResult>;
101
+ /** 粗估一段文本的 token 数。CJK≈1/字,其余≈1/4字,向上取整。 */
102
+ export declare function estimateTokens(text: string): number;
103
+ /** 估算多模态 content 的 token(text parts + 固定每图 85);不把 base64 走 estimateTokens,避免 1MB 图算成 25 万 token。 */
104
+ export declare function contentTokens(content: unknown): number;
105
+ /** 估算单条消息的 token 数:结构开销 + content + tool_calls 参数。 */
106
+ export declare function messageTokens(m: ChatMessage): number;
107
+ /** 估算整段 messages 的 token 数(不含工具 schema,含 priming 常数)。 */
108
+ export declare function estimateMessagesTokens(messages: ChatMessage[]): number;
109
+ /** 估算 chatTools(工具 schema)占用的一次性 token,带缓存。 */
110
+ export declare function estimateToolSchemaTokens(): number;
111
+ export {};
@@ -0,0 +1,15 @@
1
+ export interface MemoryFile {
2
+ path: string;
3
+ content: string;
4
+ }
5
+ /**
6
+ * 返回要查找的 MOCODE.md 路径列表,按「远→近」顺序(合并时近的在后,更突出):
7
+ * 全局 ~/.mocode/MOCODE.md → 项目级从根到 cwd 逐级 MOCODE.md。
8
+ * 向上遍历 cwd 到根收集 [cwd..root],反转为 [root..cwd](远→近),前拼全局。
9
+ */
10
+ export declare function resolveMemoryFiles(): string[];
11
+ /**
12
+ * 读取所有存在的 MOCODE.md,返回 { path, content }(content 已 trim)。
13
+ * 全程静默容错(不存在 / 读失败 → 跳过,不抛),风格对齐 skills/discover.ts 与 session/persist.ts。
14
+ */
15
+ export declare function loadMemoryFiles(): MemoryFile[];
@@ -0,0 +1,13 @@
1
+ export { buildMemoryIndexSection, loadAll, gcMemories, type MemoryEntry, type MemoryIndexItem, type MemoryType, type MemoryStatus, type MemoryScope, } from './store.js';
2
+ export { kickoffReflection, drainMemoryBackground, getLastReflectResult, clearLastReflectResult, snapshotTranscript, formatReflectResult, runReflection, type ReflectResult, } from './reflect.js';
3
+ /**
4
+ * 合并全局 + 项目各级 MOCODE.md(远→近拼接,各段空行分隔),超 MAX_MEMORY_CHARS 截断 + 提示。
5
+ * 懒加载(首次调用触发扫描;启动期 repl 调一次)。无 MOCODE.md 返空串。
6
+ */
7
+ export declare function loadMemory(): string;
8
+ /**
9
+ * 拼进系统提示的 memory 段(Tier-1 MOCODE.md);无 memory 返空串(零行为变化)。
10
+ * 记忆子系统总开关关闭(isMemoryEnabled()==false)直接返空串:
11
+ * 提示词、Memory Index 段都不进 — 配合 tools/builtins 把 memory_* 工具屏蔽。
12
+ */
13
+ export declare function buildMemorySection(): string;
@@ -0,0 +1,34 @@
1
+ import { type ChatMessage } from '../llm/index.js';
2
+ export interface ReflectResult {
3
+ ts: string;
4
+ saves: number;
5
+ updates: number;
6
+ forgets: number;
7
+ gcDecayed: number;
8
+ gcCapped: number;
9
+ gcGced: number;
10
+ error?: string;
11
+ }
12
+ /**
13
+ * 同步拍平最近 K 条对话(跳过 history[0] 大系统提示)。每条裁到 600 字符、总体裁到 6000,
14
+ * 控制反思 prompt 体积。在 kickoff 调用前同步取快照,异步 pass 用这份文本,不再读 history。
15
+ */
16
+ export declare function snapshotTranscript(history: ChatMessage[], K: number): string;
17
+ /**
18
+ * 跑一次反思:chat() 空 handlers(静默)→ 解析 JSON → 经 store 落地 → gcMemories。
19
+ * 解析失败整 pass 放弃(不部分落地)。store 调用全同步,落地是一个原子块。
20
+ * 60s 超时(AbortSignal.timeout)防 exit 时 drain 挂死。
21
+ */
22
+ export declare function runReflection(transcript: string, signal?: AbortSignal): Promise<ReflectResult>;
23
+ /** 摘要串(供 repl flush):存N 改N 忘N;有错误附上。 */
24
+ export declare function formatReflectResult(r: ReflectResult): string;
25
+ /**
26
+ * fire-and-forget 触发反思。已有在飞任务 / autoReflect 关闭 / 记忆子系统总开关关闭 → 跳过。
27
+ * 记忆关闭时反思毫无意义(没有可存的地方),且会误打日志、误弹摘要,故一并短路。
28
+ * repl 轮末调:与下一轮 agent 并发跑,不阻塞。
29
+ */
30
+ export declare function kickoffReflection(transcript: string): void;
31
+ /** 退出前等在飞反思收尾(startRepl 尾调;Ctrl+C 走 SIGINT 直退不等)。 */
32
+ export declare function drainMemoryBackground(): Promise<void>;
33
+ export declare function getLastReflectResult(): ReflectResult | null;
34
+ export declare function clearLastReflectResult(): void;