@armadra/agent 0.7.1 → 0.7.2
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.
- package/CHANGELOG.md +57 -0
- package/CHANGELOG.zh-CN.md +34 -0
- package/dist/agent/session-cache.d.ts +4 -2
- package/dist/agent/session-cache.js +5 -3
- package/dist/agent/session-compaction.d.ts +13 -1
- package/dist/agent/session-compaction.js +36 -0
- package/dist/agent/session-core.d.ts +2 -0
- package/dist/agent/session-state.d.ts +9 -3
- package/dist/agent/session-state.js +8 -6
- package/dist/agent/session.js +3 -3
- package/dist/agent/types-w5.d.ts +3 -0
- package/dist/agent/types.d.ts +18 -0
- package/dist/agents/task-record.d.ts +4 -0
- package/dist/agents/task-record.js +18 -0
- package/dist/ai/context.d.ts +7 -2
- package/dist/ai/context.js +45 -7
- package/dist/ai/providers/catalog-data.js +1 -1
- package/dist/bundle/ama.cjs +1643 -486
- package/dist/compaction/breakdown.d.ts +51 -0
- package/dist/compaction/breakdown.js +159 -0
- package/dist/compaction/estimate.d.ts +6 -0
- package/dist/compaction/estimate.js +1 -1
- package/dist/compaction/prefix-estimate.d.ts +23 -0
- package/dist/compaction/prefix-estimate.js +34 -0
- package/dist/config/json-schema.js +1 -0
- package/dist/config/key-docs.js +1 -0
- package/dist/config/schema.js +2 -0
- package/dist/config/settings-registry.js +1 -0
- package/dist/config/types.d.ts +2 -0
- package/dist/drivers/native/codex-app-server.js +6 -0
- package/dist/drivers/runner.js +17 -0
- package/dist/drivers/store.d.ts +3 -0
- package/dist/drivers/store.js +4 -0
- package/dist/i18n/catalog.d.ts +53 -0
- package/dist/i18n/messages/agents.d.ts +3 -0
- package/dist/i18n/messages/agents.js +3 -0
- package/dist/i18n/messages/config-keys.d.ts +2 -0
- package/dist/i18n/messages/config-keys.js +2 -0
- package/dist/i18n/messages/config.d.ts +2 -0
- package/dist/i18n/messages/interactive.d.ts +6 -0
- package/dist/i18n/messages/interactive.js +6 -0
- package/dist/i18n/messages/panels.d.ts +3 -0
- package/dist/i18n/messages/panels.js +5 -2
- package/dist/i18n/messages/report-context.d.ts +94 -0
- package/dist/i18n/messages/report-context.js +95 -0
- package/dist/i18n/messages/report.d.ts +96 -0
- package/dist/i18n/messages/report.js +13 -2
- package/dist/i18n/messages/settings.d.ts +2 -0
- package/dist/i18n/messages/settings.js +2 -0
- package/dist/i18n/messages/subcommands.js +2 -2
- package/dist/modes/acp/acp-events.d.ts +17 -4
- package/dist/modes/acp/acp-events.js +32 -6
- package/dist/modes/commands-core.js +4 -0
- package/dist/modes/context-report.d.ts +35 -0
- package/dist/modes/context-report.js +172 -0
- package/dist/modes/interactive/agent-bar.d.ts +2 -0
- package/dist/modes/interactive/agent-bar.js +6 -0
- package/dist/modes/interactive/commands.d.ts +2 -1
- package/dist/modes/interactive/commands.js +10 -1
- package/dist/modes/interactive/interactive-mode.d.ts +3 -0
- package/dist/modes/interactive/interactive-mode.js +6 -1
- package/dist/modes/interactive/panels.d.ts +2 -1
- package/dist/modes/interactive/panels.js +13 -5
- package/dist/modes/interactive/program-status-ui.d.ts +72 -0
- package/dist/modes/interactive/program-status-ui.js +229 -0
- package/dist/modes/interactive/session-events.d.ts +4 -0
- package/dist/modes/interactive/session-events.js +24 -2
- package/dist/modes/interactive/status-bar.d.ts +21 -3
- package/dist/modes/interactive/status-bar.js +64 -25
- package/dist/modes/interactive/status-ctx.d.ts +55 -0
- package/dist/modes/interactive/status-ctx.js +125 -0
- package/dist/modes/interactive/status-line.d.ts +2 -1
- package/dist/modes/interactive/status-line.js +3 -2
- package/dist/modes/interactive/tasks-report.js +4 -0
- package/dist/modes/print/print-mode.js +12 -0
- package/dist/modes/session-report.d.ts +10 -2
- package/dist/modes/session-report.js +26 -2
- package/dist/sdk.d.ts +1 -1
- package/dist/tools/types.d.ts +6 -0
- package/dist/tui/components/meter.d.ts +2 -0
- package/dist/tui/components/meter.js +1 -1
- package/dist/tui/program-status.d.ts +90 -0
- package/dist/tui/program-status.js +259 -0
- package/docs/acp.md +4 -4
- package/docs/agents.md +1 -1
- package/docs/en/acp.md +4 -4
- package/docs/en/providers.md +5 -3
- package/docs/en/rpc.md +3 -0
- package/docs/en/sessions.md +23 -0
- package/docs/en/tui.md +79 -22
- package/docs/providers.md +8 -5
- package/docs/rpc.md +1 -0
- package/docs/session-format.md +3 -3
- package/docs/sessions.md +22 -0
- package/docs/tui-design.md +2 -2
- package/docs/tui.md +79 -22
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,63 @@ English · [简体中文](CHANGELOG.zh-CN.md)
|
|
|
5
5
|
> This file is in English starting with 0.6.0. Release notes for 0.1 through 0.5.1 are in Chinese in
|
|
6
6
|
> [CHANGELOG.zh-CN.md](CHANGELOG.zh-CN.md). New entries go into both files.
|
|
7
7
|
|
|
8
|
+
## 0.7.2 (2026-10-09)
|
|
9
|
+
|
|
10
|
+
- **Prompt cache survives mid-session context changes**: when AGENTS.md, Skills or SessionStart hook output changed on
|
|
11
|
+
resume, host instructions were refreshed or the memory section was re-rendered after compaction, the changed section
|
|
12
|
+
used to be folded back into the leading system prompt on endpoints without mid-conversation system messages, so the
|
|
13
|
+
whole context was billed at full price from token 0. It is now delivered as a `<system-reminder>` user message at the
|
|
14
|
+
end, and the previous request stays a byte-for-byte prefix; only a patch that removes tools still rewrites the head.
|
|
15
|
+
DeepSeek accepts a mid-conversation system message but measurably keeps answering from the leading one, so it stays off
|
|
16
|
+
there (docs/benchmarks/cache-midconvo-2026-10-09.md).
|
|
17
|
+
- **No early pruning on a guessed cache lifetime**: tier-one pruning no longer treats the cache as cold after an implicit
|
|
18
|
+
10 minutes when the catalog promises no TTL (implicit caches may live for hours); the 10 minutes remain for miss
|
|
19
|
+
attribution only.
|
|
20
|
+
- **DeepSeek catalog cache data**: `promptCache: { short: 3600, minTokens: 2048 }` (the vendor says unused cache is
|
|
21
|
+
cleared after a few hours to a few days; reads were measured in 2048-token blocks).
|
|
22
|
+
- **`ama models cache-probe` advice**: without a catalog lifetime it no longer suggests filling in `short: 300`; it
|
|
23
|
+
explains that ama then neither warms nor prunes early and to fill in only a documented lifetime.
|
|
24
|
+
- **Terminal program status (OSC 7501)**: the interactive interface reports idle / working / blocked (permission,
|
|
25
|
+
question, auth) / done / error to the terminal with the
|
|
26
|
+
[Program Status Protocol](https://www.superlogical.com/rex/docs/build/program-status), sub-agent tasks as child records
|
|
27
|
+
`task/<id>`, and clears its records on exit. `ui.programStatus`: `auto` (default, only after the terminal answers the
|
|
28
|
+
detection query; off inside tmux), `on` (no detection; tmux passthrough), `off`. Detection replies never reach the input
|
|
29
|
+
box. Print / RPC / ACP modes send nothing.
|
|
30
|
+
- **ACP context usage right away**: `ama --mode acp` now sends `usage_update` after the `session/new`, `session/load`
|
|
31
|
+
(after the replay) and `session/resume` responses, after a model change and at the end of every assistant message (so
|
|
32
|
+
multi-tool turns update too), instead of only at the end of a turn; unchanged values are not resent. With an unknown
|
|
33
|
+
context window there is still no `usage_update` (`size` is required by the schema).
|
|
34
|
+
- **`-p --output-format json` context**: the result object carries `context: { tokens, window, percent }`; unknown items
|
|
35
|
+
are omitted.
|
|
36
|
+
- **External agents' context**: when an external agent reports its context usage and window (ACP `usage_update`, Codex
|
|
37
|
+
app-server `tokenUsage`), the numbers go into the task record and `ama.agent-usage`, `getStats().external.byAgent`
|
|
38
|
+
keeps the latest, and `/tasks` and the Agent bar show `ctx 34%`.
|
|
39
|
+
- **`/context`**: a new command that breaks the context down by category — system prompt (per section), tool
|
|
40
|
+
declarations (per tool), user messages, assistant text, reasoning, tool-call arguments, tool results (per tool name),
|
|
41
|
+
images, summaries and custom messages — with estimated tokens, share and a bar each. The top shows used / window, tokens
|
|
42
|
+
left, the source ("reported usage X + estimated Y" or "estimated in full") and the auto-compact trigger; the bottom
|
|
43
|
+
lists the largest tool results by ordinal, tool name and size only, never their content. Panel in the TUI, plain text
|
|
44
|
+
in line mode. Read-only; the request body and cache prefix are unchanged.
|
|
45
|
+
- **Context usage from the start**: before the first request, `contextTokens` is now a baseline estimated from the system
|
|
46
|
+
prompt and tool declarations that are about to be sent (stats only; nothing is written to the session and the request
|
|
47
|
+
body is unchanged), so a new session no longer shows `Ctx 0.0%`. `SessionStats.context` (`getStats()`, RPC
|
|
48
|
+
`get_session_stats`) tells where the number comes from (`usage` / `estimate` / `prefix`) and carries the
|
|
49
|
+
auto-compaction thresholds `autoCompactAt` / `pruneAt`; absent fields mean "unknown" (docs/sessions.md).
|
|
50
|
+
- **Status bar**: `full` shows `Ctx 3.0% 8.2k/272k auto` (used / window, `auto` while auto-compaction is on; narrow
|
|
51
|
+
screens drop `auto`, then `/window`, then the used tokens); estimates get a leading `≈`; the warning color starts at
|
|
52
|
+
the tier-one pruning threshold; `compact` keeps one decimal below 1%. Ctx refreshes right after a message is submitted
|
|
53
|
+
and, while streaming, follows usage reported by the reply (at most twice a second). The rate line marks billed tokens
|
|
54
|
+
as the session total `Σ↑ ↓` with cache reads / writes as `R` / `W`. A model without a context window gets a one-time
|
|
55
|
+
hint on how to set one.
|
|
56
|
+
- **`/session`**: the usage row is labeled as the session total; the context row adds the distance to auto-compaction
|
|
57
|
+
(or "auto-compaction off") and `≈` for estimates.
|
|
58
|
+
- **Contributing**: the repository now has issue forms (bug report, feature request, provider / model compatibility,
|
|
59
|
+
documentation), a pull request template, `CONTRIBUTING.md`, `SECURITY.md` and an `AGENTS.md` with the hard constraints
|
|
60
|
+
and review rules. None of these ship in the npm package.
|
|
61
|
+
- **Docs**: design notes, plans and research reports no longer name the third-party projects they were compared with;
|
|
62
|
+
those are described generically or by code names. Agents, providers and protocols that ama actually drives or supports
|
|
63
|
+
keep their names.
|
|
64
|
+
|
|
8
65
|
## 0.7.1 (2026-10-05)
|
|
9
66
|
|
|
10
67
|
- **Windows: concurrent OAuth refresh**: while one ama process releases the `auth.json.lock`, another one opening it
|
package/CHANGELOG.zh-CN.md
CHANGED
|
@@ -4,6 +4,40 @@
|
|
|
4
4
|
|
|
5
5
|
> 从 0.6.0 起 [CHANGELOG.md](CHANGELOG.md) 为英文,本文件保留中文记录(0.1–0.5.1 的完整历史在此)。新条目两份都要加。
|
|
6
6
|
|
|
7
|
+
## 0.7.2(2026-10-09)
|
|
8
|
+
|
|
9
|
+
- **会话中途上下文变化不再打断提示缓存**:resume 时 AGENTS.md、Skills 或 SessionStart Hook 输出变了、宿主 instructions 刷新、压缩后记忆节
|
|
10
|
+
重新渲染,在不支持对话中途 system 消息的端点上原先会把变化的节并回开头的 system,整段上下文从第 0 个 token 起按全价重读。现在改为在
|
|
11
|
+
尾部追加一条 `<system-reminder>` 包裹的 user 消息,上一次请求仍是逐字节前缀;只有移除工具的补丁仍改写开头。DeepSeek 接受对话中途的
|
|
12
|
+
system 消息,但实测模型仍按开头那条回答,所以不为它打开(docs/benchmarks/cache-midconvo-2026-10-09.md)。
|
|
13
|
+
- **不按猜测的缓存寿命提前裁剪**:目录没有承诺 TTL 时,档一裁剪不再按隐式 10 分钟判冷(隐式缓存可能存活数小时);10 分钟只用于未命中归因。
|
|
14
|
+
- **DeepSeek 目录补缓存信息**:`promptCache: { short: 3600, minTokens: 2048 }`(官方说未使用的缓存「几小时到几天」后清除;缓存读实测按
|
|
15
|
+
2048 token 一块计)。
|
|
16
|
+
- **`ama models cache-probe` 建议**:目录没有寿命时不再建议自填 `short: 300`,改为说明此时 ama 不保温、不提前裁剪,只有上游文档写明寿命时才填。
|
|
17
|
+
- **终端程序状态(OSC 7501)**:交互界面用 [程序状态协议](https://www.superlogical.com/rex/docs/build/program-status) 把
|
|
18
|
+
idle / working / blocked(permission、question、auth)/ done / error 报告给终端,子 Agent 任务为子记录 `task/<id>`,退出时清掉记录。
|
|
19
|
+
`ui.programStatus`:`auto`(缺省,终端回应检测查询后才发;tmux 里不发)、`on`(不检测;tmux 里经 passthrough)、`off`。检测回复不会
|
|
20
|
+
进输入框。print / RPC / ACP 模式不发。
|
|
21
|
+
- **ACP 立即有上下文用量**:`ama --mode acp` 在 `session/new`、`session/load`(回放之后)、`session/resume` 答复之后、换模型时与每条助手
|
|
22
|
+
消息结束时都发 `usage_update`(多工具回合中途也更新),不再只在回合结束时发;与上次同值不重发。窗口未知时仍不发(schema 里 `size` 必填)。
|
|
23
|
+
- **`-p --output-format json` 带上下文**:结果对象加 `context: { tokens, window, percent }`,未知项省略。
|
|
24
|
+
- **外部 Agent 的上下文**:外部 Agent 报告了上下文占用与窗口(ACP `usage_update`、Codex app-server `tokenUsage`)时,数字记进任务记录与
|
|
25
|
+
`ama.agent-usage`,`getStats().external.byAgent` 取最近一次,`/tasks` 与 Agent 栏显示 `ctx 34%`。
|
|
26
|
+
- **`/context`**:新命令,把上下文按类别拆开——系统提示(按节)、工具声明(按工具)、用户消息、助手文本、推理、工具调用参数、
|
|
27
|
+
工具结果(按工具名汇总)、附件图片、摘要、自定义消息——每类给 token 估算、占比与条形;顶部是已用 / 窗口、剩余、来源(「usage
|
|
28
|
+
实测 X + 估算 Y」或「全量估算」)与自动压缩触发点,底部只按序号、工具名与大小列出最大的工具结果,不显示正文。交互模式是面板,
|
|
29
|
+
line 模式是纯文本。统计只读,不改请求体与缓存前缀。
|
|
30
|
+
- **上下文一开始就有数**:第一次请求前,`contextTokens` 改为按即将发送的系统提示 + 工具声明估算的基线(只统计,不写会话、不改请求体),
|
|
31
|
+
新会话不再显示 `Ctx 0.0%`。`SessionStats.context`(`getStats()`、RPC `get_session_stats`)标明数字来源(`usage` / `estimate` /
|
|
32
|
+
`prefix`)并给出自动压缩阈值 `autoCompactAt` / `pruneAt`;字段缺省表示「不知道」(docs/sessions.md)。
|
|
33
|
+
- **状态栏**:`full` 显示 `Ctx 3.0% 8.2k/272k auto`(已用量 / 窗口,自动压缩开着时有 `auto`;窄屏先丢 `auto`,再丢 `/窗口`,最后丢已用量);
|
|
34
|
+
估算值前加 `≈`;黄色从档一裁剪阈值开始;`compact` 占用 < 1% 时保留一位小数。提交消息后立刻刷新 Ctx,流式中按回复带回的 usage 更新
|
|
35
|
+
(每秒至多 2 次)。速率行用 `Σ↑ ↓` 标明是会话累计计费量,缓存读写另列 `R` / `W`。模型没有上下文窗口时提示一次怎么补。
|
|
36
|
+
- **`/session`**:用量行注明「累计」;上下文行加上距自动压缩的余量(或「自动压缩关闭」),估算值带 `≈`。
|
|
37
|
+
- **参与贡献**:仓库新增 issue 表单(缺陷报告、功能建议、供应商 / 模型兼容问题、文档问题)、PR 模板、`CONTRIBUTING.md`、
|
|
38
|
+
`SECURITY.md`,以及写明硬约束与评审规则的 `AGENTS.md`;这些文件都不进 npm 包。
|
|
39
|
+
- **文档**:设计、计划与调研文档不再点名作为参照的第三方项目,改为不具名表述或代号;ama 实际驱动或兼容的外部 Agent、供应商与协议照常写名字。
|
|
40
|
+
|
|
7
41
|
## 0.7.1(2026-10-05)
|
|
8
42
|
|
|
9
43
|
- **Windows:并发刷新 OAuth**:一个 ama 进程刚释放 `auth.json.lock` 时,另一个进程打开它会报 EPERM(NTFS 上文件处于删除挂起),刷新
|
|
@@ -82,8 +82,10 @@ export declare class SessionCacheController {
|
|
|
82
82
|
window?: number | undefined;
|
|
83
83
|
}): SessionCacheStats;
|
|
84
84
|
/**
|
|
85
|
-
* [W5-H1] 缓存是否已冷(wave5 §8.2 C3
|
|
86
|
-
*
|
|
85
|
+
* [W5-H1] 缓存是否已冷(wave5 §8.2 C3):上一次请求(含保温)距今超过目录承诺的 TTL。
|
|
86
|
+
* 目录没有承诺 TTL 时返回 false:隐式缓存的寿命可能远长于 10 分钟,按猜测的寿命提前裁剪会改写
|
|
87
|
+
* 仍然有效的缓存(隐式 600 s 只用于未命中归因)。只对 `reported` 端点判断;`silent` / `unknown`
|
|
88
|
+
* 返回 false,档一退化为只按阈值。
|
|
87
89
|
*/
|
|
88
90
|
isCold(): boolean;
|
|
89
91
|
/**
|
|
@@ -299,8 +299,10 @@ export class SessionCacheController {
|
|
|
299
299
|
return stats;
|
|
300
300
|
}
|
|
301
301
|
/**
|
|
302
|
-
* [W5-H1] 缓存是否已冷(wave5 §8.2 C3
|
|
303
|
-
*
|
|
302
|
+
* [W5-H1] 缓存是否已冷(wave5 §8.2 C3):上一次请求(含保温)距今超过目录承诺的 TTL。
|
|
303
|
+
* 目录没有承诺 TTL 时返回 false:隐式缓存的寿命可能远长于 10 分钟,按猜测的寿命提前裁剪会改写
|
|
304
|
+
* 仍然有效的缓存(隐式 600 s 只用于未命中归因)。只对 `reported` 端点判断;`silent` / `unknown`
|
|
305
|
+
* 返回 false,档一退化为只按阈值。
|
|
304
306
|
*/
|
|
305
307
|
isCold() {
|
|
306
308
|
const prev = this.prev;
|
|
@@ -311,7 +313,7 @@ export class SessionCacheController {
|
|
|
311
313
|
if (this.tracker.get(endpoint, model.compat?.cacheReporting) !== "reported")
|
|
312
314
|
return false;
|
|
313
315
|
const ttl = cacheTtlMs(this.modelOf(prev), prev.options.cacheRetention);
|
|
314
|
-
return this.now() - prev.at >
|
|
316
|
+
return ttl !== undefined && this.now() - prev.at > ttl;
|
|
315
317
|
}
|
|
316
318
|
/**
|
|
317
319
|
* 摘要续写的前缀(第三波 §1.8):当前转录按回合同样的方式转换,且上一次 turn 请求的消息
|
|
@@ -14,6 +14,8 @@
|
|
|
14
14
|
* `overflow`,受跳闸限制)→ 压缩后估算 ≤ 0.8 × 窗口才重试。
|
|
15
15
|
* - 手动 `/compact`:PreCompact(trigger `manual`)→ 摘要;成功清零熔断。
|
|
16
16
|
* PreCompact 的 `decision: "block"` 取消本次压缩;`customInstructions` 追加到摘要提示。
|
|
17
|
+
* - 统计(`contextStats`,供 getStats):投影估算标来源;系统消息落盘前加系统提示 + 工具声明的前缀基线
|
|
18
|
+
* (只统计,不写分支、不改请求);附档一 / 档二阈值。压缩调度本身仍只看 `estimate()`。
|
|
17
19
|
* [W3-C1b] 阈值 / 手动压缩与分支摘要优先走会话前缀续写(缓存控制器给前缀),溢出恢复不走
|
|
18
20
|
* (前缀本身已超窗口);续写失败回落独立请求并记 warning。
|
|
19
21
|
*/
|
|
@@ -22,7 +24,7 @@ import { type ContextEstimate } from "../compaction/estimate.js";
|
|
|
22
24
|
import { type PrunePolicy } from "../compaction/prune-tier.js";
|
|
23
25
|
import type { BranchSummaryEntry } from "../session/types.js";
|
|
24
26
|
import type { SessionCore } from "./session-core.js";
|
|
25
|
-
import type { CompactionResult, CompactionSettings } from "./types.js";
|
|
27
|
+
import type { CompactionResult, CompactionSettings, SessionContextStats } from "./types.js";
|
|
26
28
|
export declare const DEFAULT_COMPACTION_SETTINGS: CompactionSettings;
|
|
27
29
|
/** 保留区不超过 (窗口 − 预留) 的 40%,否则小窗口模型上摘要后仍然溢出。 */
|
|
28
30
|
export declare const KEEP_RECENT_MAX_RATIO = 0.4;
|
|
@@ -40,6 +42,16 @@ export declare class CompactionController {
|
|
|
40
42
|
refresh(): void;
|
|
41
43
|
setAuto(enabled: boolean): void;
|
|
42
44
|
estimate(): ContextEstimate;
|
|
45
|
+
/**
|
|
46
|
+
* 统计用的上下文量(`getStats`):投影估算标上来源;系统消息还没落盘时加上前缀基线(系统提示 +
|
|
47
|
+
* 工具声明,只统计不写分支)。附自动压缩的两个阈值(自动压缩可用时)。压缩调度仍用 `estimate()`。
|
|
48
|
+
*/
|
|
49
|
+
contextStats(): {
|
|
50
|
+
tokens: number;
|
|
51
|
+
detail: SessionContextStats;
|
|
52
|
+
};
|
|
53
|
+
/** 将要发送的系统提示 + 工具声明的估算(与首条 system 消息同样装配,不落盘)。 */
|
|
54
|
+
private prefixTokens;
|
|
43
55
|
private budget;
|
|
44
56
|
private keepRecent;
|
|
45
57
|
/** 摘要请求的公共选项;`continuation` 时附上会话前缀续写的材料。 */
|
|
@@ -14,18 +14,22 @@
|
|
|
14
14
|
* `overflow`,受跳闸限制)→ 压缩后估算 ≤ 0.8 × 窗口才重试。
|
|
15
15
|
* - 手动 `/compact`:PreCompact(trigger `manual`)→ 摘要;成功清零熔断。
|
|
16
16
|
* PreCompact 的 `decision: "block"` 取消本次压缩;`customInstructions` 追加到摘要提示。
|
|
17
|
+
* - 统计(`contextStats`,供 getStats):投影估算标来源;系统消息落盘前加系统提示 + 工具声明的前缀基线
|
|
18
|
+
* (只统计,不写分支、不改请求);附档一 / 档二阈值。压缩调度本身仍只看 `estimate()`。
|
|
17
19
|
* [W3-C1b] 阈值 / 手动压缩与分支摘要优先走会话前缀续写(缓存控制器给前缀),溢出恢复不走
|
|
18
20
|
* (前缀本身已超窗口);续写失败回落独立请求并记 warning。
|
|
19
21
|
*/
|
|
20
22
|
import { AmaError } from "../errors.js";
|
|
21
23
|
import { CompactionBreaker } from "../compaction/breaker.js";
|
|
22
24
|
import { estimateMessageTokens, estimateProjectedTokens, } from "../compaction/estimate.js";
|
|
25
|
+
import { estimatePrefixTokens, withPrefixBaseline } from "../compaction/prefix-estimate.js";
|
|
23
26
|
import { planPrune, prunePolicy } from "../compaction/prune-tier.js";
|
|
24
27
|
import { createProtection, skillLocations } from "../compaction/protect.js";
|
|
25
28
|
import { buildPostCompactBlock } from "../compaction/post-compact.js";
|
|
26
29
|
import { prepareCompaction, prepareCompactionAt, runCompaction, } from "../compaction/summarize-tier.js";
|
|
27
30
|
import { prepareBranchSummary, runBranchSummary } from "../compaction/branch-summary.js";
|
|
28
31
|
import { buildProjection } from "../session/projection.js";
|
|
32
|
+
import { assembleSections, definedSections, toolDecls } from "./system-prompt.js";
|
|
29
33
|
export const DEFAULT_COMPACTION_SETTINGS = {
|
|
30
34
|
enabled: true,
|
|
31
35
|
reserveTokens: 16_384,
|
|
@@ -69,6 +73,38 @@ export class CompactionController {
|
|
|
69
73
|
const branch = this.core.manager.branch();
|
|
70
74
|
return estimateProjectedTokens(buildProjection(branch).items, branch);
|
|
71
75
|
}
|
|
76
|
+
/**
|
|
77
|
+
* 统计用的上下文量(`getStats`):投影估算标上来源;系统消息还没落盘时加上前缀基线(系统提示 +
|
|
78
|
+
* 工具声明,只统计不写分支)。附自动压缩的两个阈值(自动压缩可用时)。压缩调度仍用 `estimate()`。
|
|
79
|
+
*/
|
|
80
|
+
contextStats() {
|
|
81
|
+
const branch = this.core.manager.branch();
|
|
82
|
+
const items = buildProjection(branch).items;
|
|
83
|
+
const sourced = withPrefixBaseline(estimateProjectedTokens(items, branch), items.some((item) => item.message.role === "system"), () => this.prefixTokens());
|
|
84
|
+
const detail = {
|
|
85
|
+
source: sourced.source,
|
|
86
|
+
usageTokens: sourced.usageTokens,
|
|
87
|
+
trailingTokens: sourced.trailingTokens,
|
|
88
|
+
};
|
|
89
|
+
const budget = this.budget();
|
|
90
|
+
const policy = this.prunePolicy();
|
|
91
|
+
if (this.breaker.autoEnabled && budget !== undefined && policy !== undefined) {
|
|
92
|
+
detail.autoCompactAt = budget;
|
|
93
|
+
detail.pruneAt = Math.floor(policy.triggerTokens);
|
|
94
|
+
}
|
|
95
|
+
return { tokens: sourced.tokens, detail };
|
|
96
|
+
}
|
|
97
|
+
/** 将要发送的系统提示 + 工具声明的估算(与首条 system 消息同样装配,不落盘)。 */
|
|
98
|
+
prefixTokens() {
|
|
99
|
+
const core = this.core;
|
|
100
|
+
const tools = core
|
|
101
|
+
.activeToolNames()
|
|
102
|
+
.map((name) => core.activeTool(name))
|
|
103
|
+
.filter((tool) => tool !== undefined);
|
|
104
|
+
const system = core.childBase?.().system ?? core.options.system ?? {};
|
|
105
|
+
const sections = definedSections(assembleSections({ ...system, tools, cwd: core.cwd }));
|
|
106
|
+
return estimatePrefixTokens(sections, toolDecls(tools));
|
|
107
|
+
}
|
|
72
108
|
budget() {
|
|
73
109
|
const window = this.core.model().contextWindow;
|
|
74
110
|
return window === undefined ? undefined : Math.max(0, window - this.settings.reserveTokens);
|
|
@@ -130,6 +130,8 @@ export interface SessionCore {
|
|
|
130
130
|
/** 任一已登记工具(不限于活动集;嵌套调用用)。 */
|
|
131
131
|
tool(name: string): ToolDefinition | undefined;
|
|
132
132
|
activeToolNames(): string[];
|
|
133
|
+
/** 当前的系统提示静态部分(`updateSystem` 之后的;统计启动基线用)。缺省时用 `options.system`。 */
|
|
134
|
+
childBase?(): Pick<AgentSessionOptions, "system">;
|
|
133
135
|
runHook(event: HookEvent, payload: HookEventPayload, signal?: AbortSignal): Promise<HookOutcome | undefined>;
|
|
134
136
|
/** Hook 返回 continue:false 时记下,finishTurn 据此结束 run。 */
|
|
135
137
|
requestStop(reason: string | undefined): void;
|
|
@@ -3,14 +3,15 @@
|
|
|
3
3
|
*
|
|
4
4
|
* 统计口径:活动分支上的全部条目(不是投影)——被压缩 / 剔除的消息仍计入用量与成本;
|
|
5
5
|
* 压缩与分支摘要请求的 usage 也计入;`usage` 条目(缓存保温等不进上下文的请求,第三波 §1.7)
|
|
6
|
-
* 计入 token 与费用但不算消息。上下文 % 用投影感知估算(§9
|
|
6
|
+
* 计入 token 与费用但不算消息。上下文 % 用投影感知估算(§9);`context` 标明估算来源(usage / 全量估算 /
|
|
7
|
+
* 启动前缀基线)与自动压缩阈值。
|
|
7
8
|
*/
|
|
8
9
|
import type { Model, ModelThinkingLevel } from "../ai/types.js";
|
|
9
10
|
import type { PermissionMode } from "../permissions/types.js";
|
|
10
11
|
import type { SessionManager } from "../session/manager.js";
|
|
11
12
|
import type { SessionEntry } from "../session/types.js";
|
|
12
13
|
import type { Agent } from "./agent.js";
|
|
13
|
-
import type { SessionCacheStats, SessionState, SessionStats } from "./types.js";
|
|
14
|
+
import type { SessionCacheStats, SessionContextStats, SessionState, SessionStats } from "./types.js";
|
|
14
15
|
import type { QuotaUpdateEvent } from "./types-w6.js";
|
|
15
16
|
export interface StateInput {
|
|
16
17
|
agent: Agent;
|
|
@@ -28,7 +29,12 @@ export interface StatsInput {
|
|
|
28
29
|
sessionId: string;
|
|
29
30
|
sessionFile: string | undefined;
|
|
30
31
|
branch: readonly SessionEntry[];
|
|
31
|
-
contextTokens
|
|
32
|
+
contextTokens?: number | undefined;
|
|
33
|
+
/** 会话的上下文估算(CompactionController.contextStats,含来源与阈值);给了以它的 tokens 为准。 */
|
|
34
|
+
context?: {
|
|
35
|
+
tokens: number;
|
|
36
|
+
detail: SessionContextStats;
|
|
37
|
+
};
|
|
32
38
|
contextWindow: number | undefined;
|
|
33
39
|
/** [W3-C1b] 会话层缓存控制器的统计(未接线时缺省)。 */
|
|
34
40
|
cache?: SessionCacheStats;
|
|
@@ -3,7 +3,8 @@
|
|
|
3
3
|
*
|
|
4
4
|
* 统计口径:活动分支上的全部条目(不是投影)——被压缩 / 剔除的消息仍计入用量与成本;
|
|
5
5
|
* 压缩与分支摘要请求的 usage 也计入;`usage` 条目(缓存保温等不进上下文的请求,第三波 §1.7)
|
|
6
|
-
* 计入 token 与费用但不算消息。上下文 % 用投影感知估算(§9
|
|
6
|
+
* 计入 token 与费用但不算消息。上下文 % 用投影感知估算(§9);`context` 标明估算来源(usage / 全量估算 /
|
|
7
|
+
* 启动前缀基线)与自动压缩阈值。
|
|
7
8
|
*/
|
|
8
9
|
import { modelRefOf } from "../ai/providers/channels.js";
|
|
9
10
|
export function buildSessionState(input) {
|
|
@@ -87,11 +88,10 @@ export function computeStats(input) {
|
|
|
87
88
|
addCost(entry.usage);
|
|
88
89
|
}
|
|
89
90
|
}
|
|
90
|
-
const
|
|
91
|
-
|
|
92
|
-
input.contextWindow <= 0
|
|
91
|
+
const contextTokens = input.context?.tokens ?? input.contextTokens;
|
|
92
|
+
const contextPercent = input.contextWindow === undefined || contextTokens === undefined || input.contextWindow <= 0
|
|
93
93
|
? undefined
|
|
94
|
-
: Math.min(100, Math.round((
|
|
94
|
+
: Math.min(100, Math.round((contextTokens / input.contextWindow) * 1000) / 10);
|
|
95
95
|
const stats = {
|
|
96
96
|
sessionId: input.sessionId,
|
|
97
97
|
sessionFile: input.sessionFile,
|
|
@@ -101,10 +101,12 @@ export function computeStats(input) {
|
|
|
101
101
|
toolResults,
|
|
102
102
|
tokens,
|
|
103
103
|
cost,
|
|
104
|
-
contextTokens
|
|
104
|
+
contextTokens,
|
|
105
105
|
contextWindow: input.contextWindow,
|
|
106
106
|
contextPercent,
|
|
107
107
|
};
|
|
108
|
+
if (input.context !== undefined)
|
|
109
|
+
stats.context = { ...input.context.detail };
|
|
108
110
|
const rate = cacheHitRate(tokens);
|
|
109
111
|
if (rate !== undefined)
|
|
110
112
|
stats.cacheHitRate = rate;
|
package/dist/agent/session.js
CHANGED
|
@@ -445,15 +445,15 @@ export class AgentSessionImpl {
|
|
|
445
445
|
return lastAssistantText(this.manager.branch());
|
|
446
446
|
}
|
|
447
447
|
getStats() {
|
|
448
|
-
const
|
|
448
|
+
const context = this.compaction.contextStats();
|
|
449
449
|
const contextWindow = this.settings.model.contextWindow;
|
|
450
450
|
const stats = computeStats({
|
|
451
451
|
sessionId: this.manager.id,
|
|
452
452
|
sessionFile: this.manager.file(),
|
|
453
453
|
branch: this.manager.branch(),
|
|
454
|
-
|
|
454
|
+
context,
|
|
455
455
|
contextWindow,
|
|
456
|
-
cache: this.cache.stats({ tokens:
|
|
456
|
+
cache: this.cache.stats({ tokens: context.tokens, window: contextWindow }),
|
|
457
457
|
quota: this.lastQuota,
|
|
458
458
|
});
|
|
459
459
|
return this.extensions.contributeStats(stats);
|
package/dist/agent/types-w5.d.ts
CHANGED
|
@@ -179,6 +179,9 @@ export interface ExternalAgentStats {
|
|
|
179
179
|
unit: ExternalUsageUnit;
|
|
180
180
|
amount: number;
|
|
181
181
|
tokens?: number;
|
|
182
|
+
/** 最近一次报告的上下文占用与窗口(token);驱动不报时缺省。 */
|
|
183
|
+
contextTokens?: number;
|
|
184
|
+
contextWindow?: number;
|
|
182
185
|
}>;
|
|
183
186
|
}
|
|
184
187
|
/** 子 Agent 任务注册表的汇总(`/session` 与 `get_session_stats`)。 */
|
package/dist/agent/types.d.ts
CHANGED
|
@@ -356,6 +356,8 @@ export interface SessionStats extends SessionStatsW5, SessionStatsW6 {
|
|
|
356
356
|
contextWindow: number | undefined;
|
|
357
357
|
/** 0–100;无窗口时 undefined(显示 `ctx ?`)。 */
|
|
358
358
|
contextPercent: number | undefined;
|
|
359
|
+
/** 上下文用量的来源与压缩阈值(`contextTokens` 怎么来的);旧实现与测试替身可缺省。 */
|
|
360
|
+
context?: SessionContextStats;
|
|
359
361
|
/**
|
|
360
362
|
* 缓存命中率 0–1 = cacheRead /(input + cacheRead + cacheWrite)(设计 §9.1);
|
|
361
363
|
* 还没有任何输入用量时不给。
|
|
@@ -364,6 +366,22 @@ export interface SessionStats extends SessionStatsW5, SessionStatsW6 {
|
|
|
364
366
|
/** [W3-C0] 缓存可观测性(第三波 §1.10);会话层缓存控制器(C1b)未接线时缺省。 */
|
|
365
367
|
cache?: SessionCacheStats;
|
|
366
368
|
}
|
|
369
|
+
/**
|
|
370
|
+
* `SessionStats.context`:`contextTokens` 的来源与自动压缩阈值(只统计,不改请求)。
|
|
371
|
+
* - `usage`:最后一条有效助手消息的 usage(`usageTokens`)+ 其后消息的估算(`trailingTokens`);
|
|
372
|
+
* - `estimate`:没有可信的 usage(压缩 / 上下文编辑之后、新 usage 到来之前,或从未有 usage),按投影全量估算;
|
|
373
|
+
* - `prefix`:系统消息还没落盘(第一次请求前),用当前系统提示 + 工具声明估算的基线加上已有消息的估算。
|
|
374
|
+
* 后两种 `usageTokens` 为 0、`trailingTokens` 等于 `contextTokens`。
|
|
375
|
+
*/
|
|
376
|
+
export interface SessionContextStats {
|
|
377
|
+
source: "usage" | "estimate" | "prefix";
|
|
378
|
+
usageTokens: number;
|
|
379
|
+
trailingTokens: number;
|
|
380
|
+
/** 档二自动摘要的阈值(窗口 − reserveTokens);自动压缩关闭、熔断或窗口未知时缺省。 */
|
|
381
|
+
autoCompactAt?: number;
|
|
382
|
+
/** 档一裁剪的阈值(0.7 ×(窗口 − reserveTokens));缺省条件同上。 */
|
|
383
|
+
pruneAt?: number;
|
|
384
|
+
}
|
|
367
385
|
/** [W3-C0] `SessionStats.cache`(`get_session_stats` / `/session` / `-p --output-format json`)。 */
|
|
368
386
|
export interface SessionCacheStats {
|
|
369
387
|
/** 当前端点的三态。 */
|
|
@@ -150,6 +150,10 @@ export interface ProgressSink {
|
|
|
150
150
|
export declare function flushText(record: TaskRecord, sink: ProgressSink): void;
|
|
151
151
|
/** runner 进度 → 记录与 `subagent_update`(文本 ≥ 250 ms 合并,轮次与结束时冲刷)。 */
|
|
152
152
|
export declare function applyRunnerEvent(record: TaskRecord, event: SubagentEvent, sink: ProgressSink): void;
|
|
153
|
+
/** 任务的上下文占用(0–100,一位小数,封顶 100);占用或窗口未知时 undefined。 */
|
|
154
|
+
export declare function taskContextPercent(info: Pick<TaskInfo, "contextTokens" | "contextWindow">): number | undefined;
|
|
155
|
+
/** 上下文占用的显示:≥ 10% 取整,以下保留一位小数(`34%`、`0.4%`);未知时 undefined。 */
|
|
156
|
+
export declare function formatTaskContext(info: Pick<TaskInfo, "contextTokens" | "contextWindow">): string | undefined;
|
|
153
157
|
/** `subagent_start` 事件(新开或续聊都发)。 */
|
|
154
158
|
export declare function startEvent(record: TaskRecord, handle: TaskHandle): SubagentStartEvent;
|
|
155
159
|
/** `getStats().tasks`:没有任务时 undefined。 */
|
|
@@ -163,6 +163,10 @@ export function applyRunnerEvent(record, event, sink) {
|
|
|
163
163
|
record.info.usage = event.usage;
|
|
164
164
|
if (event.unit === "usd" && event.amount !== undefined)
|
|
165
165
|
record.info.costUsd = event.amount;
|
|
166
|
+
if (event.contextTokens !== undefined)
|
|
167
|
+
record.info.contextTokens = event.contextTokens;
|
|
168
|
+
if (event.contextWindow !== undefined)
|
|
169
|
+
record.info.contextWindow = event.contextWindow;
|
|
166
170
|
return;
|
|
167
171
|
case "notice":
|
|
168
172
|
sink.log(event.level, `[task ${taskId}] ${event.text}`);
|
|
@@ -209,6 +213,20 @@ function recordDisplay(record, event, now) {
|
|
|
209
213
|
return;
|
|
210
214
|
}
|
|
211
215
|
}
|
|
216
|
+
/** 任务的上下文占用(0–100,一位小数,封顶 100);占用或窗口未知时 undefined。 */
|
|
217
|
+
export function taskContextPercent(info) {
|
|
218
|
+
const { contextTokens: used, contextWindow: size } = info;
|
|
219
|
+
if (used === undefined || size === undefined || size <= 0)
|
|
220
|
+
return undefined;
|
|
221
|
+
return Math.min(100, Math.round((used / size) * 1000) / 10);
|
|
222
|
+
}
|
|
223
|
+
/** 上下文占用的显示:≥ 10% 取整,以下保留一位小数(`34%`、`0.4%`);未知时 undefined。 */
|
|
224
|
+
export function formatTaskContext(info) {
|
|
225
|
+
const percent = taskContextPercent(info);
|
|
226
|
+
if (percent === undefined)
|
|
227
|
+
return undefined;
|
|
228
|
+
return `${percent >= 10 ? Math.round(percent) : percent.toFixed(1)}%`;
|
|
229
|
+
}
|
|
212
230
|
/** `subagent_start` 事件(新开或续聊都发)。 */
|
|
213
231
|
export function startEvent(record, handle) {
|
|
214
232
|
const event = {
|
package/dist/ai/context.d.ts
CHANGED
|
@@ -2,8 +2,11 @@
|
|
|
2
2
|
* normalizeContext(设计 §1.2 ai/context.ts):把循环交来的转录(含 `system` 补丁消息)变成
|
|
3
3
|
* 协议可直接拼请求体的形状。
|
|
4
4
|
*
|
|
5
|
-
* - system
|
|
6
|
-
* `systemSections`(保持节首次出现的顺序)与拼好的 `systemPrompt`(节间空一行);
|
|
5
|
+
* - system 折叠:首条非 system 消息之前的 system 消息按出现顺序重放(节名级替换,null 删除),
|
|
6
|
+
* 得到 `systemSections`(保持节首次出现的顺序)与拼好的 `systemPrompt`(节间空一行);
|
|
7
|
+
* - 中途节补丁(设计 §9.1「会话中途变化的上下文只追加」):对话开始之后的 system 补丁不改写开头,
|
|
8
|
+
* 渲染成 `<system-reminder>` 包裹的 user 消息按位置插回,开头与之前的消息逐字节不变;
|
|
9
|
+
* 例外是补丁移除了工具——工具表本身已变、前缀必然失效,这时全部补丁照旧折回开头;
|
|
7
10
|
* - 工具表:按顺序重放 `toolsRemoved`(先)与 `toolsAdded`(后),同名后者覆盖;
|
|
8
11
|
* - 模态过滤:模型不收图片时,用户消息与工具结果里的图片块换成文字占位。
|
|
9
12
|
*
|
|
@@ -18,6 +21,8 @@ export interface NormalizeOptions {
|
|
|
18
21
|
}
|
|
19
22
|
export declare const IMAGE_OMITTED_TEXT = "[image omitted: the model does not accept image input]";
|
|
20
23
|
export declare function normalizeContext(context: TranscriptContext, options?: NormalizeOptions): NormalizedContext;
|
|
24
|
+
/** 中途节补丁作为尾部上下文消息送达时的文本(固定英文,与界面语言无关)。 */
|
|
25
|
+
export declare function systemReminderText(updates: readonly string[]): string;
|
|
21
26
|
/** 渲染一条中途 system 补丁的文本(节变更;工具表变化由请求的工具列表体现)。 */
|
|
22
27
|
export declare function renderSystemUpdate(message: SystemMessage): string;
|
|
23
28
|
export interface InlineSystemUpdate {
|
package/dist/ai/context.js
CHANGED
|
@@ -2,8 +2,11 @@
|
|
|
2
2
|
* normalizeContext(设计 §1.2 ai/context.ts):把循环交来的转录(含 `system` 补丁消息)变成
|
|
3
3
|
* 协议可直接拼请求体的形状。
|
|
4
4
|
*
|
|
5
|
-
* - system
|
|
6
|
-
* `systemSections`(保持节首次出现的顺序)与拼好的 `systemPrompt`(节间空一行);
|
|
5
|
+
* - system 折叠:首条非 system 消息之前的 system 消息按出现顺序重放(节名级替换,null 删除),
|
|
6
|
+
* 得到 `systemSections`(保持节首次出现的顺序)与拼好的 `systemPrompt`(节间空一行);
|
|
7
|
+
* - 中途节补丁(设计 §9.1「会话中途变化的上下文只追加」):对话开始之后的 system 补丁不改写开头,
|
|
8
|
+
* 渲染成 `<system-reminder>` 包裹的 user 消息按位置插回,开头与之前的消息逐字节不变;
|
|
9
|
+
* 例外是补丁移除了工具——工具表本身已变、前缀必然失效,这时全部补丁照旧折回开头;
|
|
7
10
|
* - 工具表:按顺序重放 `toolsRemoved`(先)与 `toolsAdded`(后),同名后者覆盖;
|
|
8
11
|
* - 模态过滤:模型不收图片时,用户消息与工具结果里的图片块换成文字占位。
|
|
9
12
|
*
|
|
@@ -55,16 +58,51 @@ function allowsImages(options) {
|
|
|
55
58
|
return options?.model === undefined || options.model.input.includes("image");
|
|
56
59
|
}
|
|
57
60
|
export function normalizeContext(context, options) {
|
|
58
|
-
const
|
|
61
|
+
const head = new SystemState();
|
|
62
|
+
const tools = new SystemState();
|
|
59
63
|
const messages = [];
|
|
60
64
|
const allowImages = allowsImages(options);
|
|
65
|
+
const fold = removesToolsMidway(context.messages);
|
|
66
|
+
let pending = [];
|
|
67
|
+
const flush = () => {
|
|
68
|
+
if (pending.length === 0)
|
|
69
|
+
return;
|
|
70
|
+
messages.push({ role: "user", content: systemReminderText(pending), timestamp: 0 });
|
|
71
|
+
pending = [];
|
|
72
|
+
};
|
|
61
73
|
for (const message of context.messages) {
|
|
62
|
-
if (message.role
|
|
63
|
-
|
|
64
|
-
else
|
|
74
|
+
if (message.role !== "system") {
|
|
75
|
+
flush();
|
|
65
76
|
messages.push(filterMessage(message, allowImages));
|
|
77
|
+
continue;
|
|
78
|
+
}
|
|
79
|
+
tools.apply(message);
|
|
80
|
+
if (fold || messages.length === 0) {
|
|
81
|
+
head.apply(message);
|
|
82
|
+
continue;
|
|
83
|
+
}
|
|
84
|
+
const text = renderSystemUpdate(message);
|
|
85
|
+
if (text.length > 0)
|
|
86
|
+
pending.push(text);
|
|
66
87
|
}
|
|
67
|
-
|
|
88
|
+
flush();
|
|
89
|
+
return { ...head.snapshot(), tools: tools.snapshot().tools, messages };
|
|
90
|
+
}
|
|
91
|
+
/** 对话开始之后有补丁移除了工具(这时整段前缀必然失效,补丁全部折回开头)。 */
|
|
92
|
+
function removesToolsMidway(transcript) {
|
|
93
|
+
let started = false;
|
|
94
|
+
for (const message of transcript) {
|
|
95
|
+
if (message.role !== "system")
|
|
96
|
+
started = true;
|
|
97
|
+
else if (started && (message.toolsRemoved?.length ?? 0) > 0)
|
|
98
|
+
return true;
|
|
99
|
+
}
|
|
100
|
+
return false;
|
|
101
|
+
}
|
|
102
|
+
/** 中途节补丁作为尾部上下文消息送达时的文本(固定英文,与界面语言无关)。 */
|
|
103
|
+
export function systemReminderText(updates) {
|
|
104
|
+
return (`<system-reminder>\n${updates.join("\n\n")}\n\n` +
|
|
105
|
+
"These updates replace the earlier versions of those system prompt sections.\n</system-reminder>");
|
|
68
106
|
}
|
|
69
107
|
/** 渲染一条中途 system 补丁的文本(节变更;工具表变化由请求的工具列表体现)。 */
|
|
70
108
|
export function renderSystemUpdate(message) {
|
|
@@ -6,7 +6,7 @@ export const CATALOG_SOURCES = {
|
|
|
6
6
|
anthropic: '{"version":1,"provider":"anthropic","modelsDev":"anthropic","models":[{"id":"claude-fable-5-1","thinkingLevelMap":{"off":null,"xhigh":"xhigh"},"promptCache":{"short":300,"long":3600,"minTokens":512},"compat":{"adaptiveThinking":true}},{"id":"claude-fable-5","thinkingLevelMap":{"off":null,"xhigh":"xhigh"},"promptCache":{"short":300,"long":3600,"minTokens":512},"compat":{"adaptiveThinking":true}},{"id":"claude-opus-5-5","thinkingLevelMap":{"off":null,"minimal":null,"low":"low","medium":"medium","high":"high","xhigh":"xhigh"},"promptCache":{"short":300,"long":3600,"minTokens":512},"compat":{"adaptiveThinking":true}},{"id":"claude-opus-5","thinkingLevelMap":{"off":null,"xhigh":"xhigh"},"promptCache":{"short":300,"long":3600,"minTokens":512},"compat":{"adaptiveThinking":true}},{"id":"claude-opus-4-8","thinkingLevelMap":{"xhigh":"xhigh"},"promptCache":{"short":300,"long":3600,"minTokens":1024},"compat":{"adaptiveThinking":true}},{"id":"claude-opus-4-7","thinkingLevelMap":{"xhigh":"xhigh"},"promptCache":{"short":300,"long":3600,"minTokens":2048},"compat":{"adaptiveThinking":true}},{"id":"claude-opus-4-6","promptCache":{"short":300,"long":3600,"minTokens":4096},"compat":{"adaptiveThinking":true}},{"id":"claude-sonnet-5-5","thinkingLevelMap":{"off":null,"minimal":null,"low":"low","medium":"medium","high":"high","xhigh":"xhigh"},"promptCache":{"short":300,"long":3600,"minTokens":512},"compat":{"adaptiveThinking":true}},{"id":"claude-sonnet-5","thinkingLevelMap":{"xhigh":"xhigh"},"promptCache":{"short":300,"long":3600,"minTokens":1024},"compat":{"adaptiveThinking":true}},{"id":"claude-sonnet-4-6","promptCache":{"short":300,"long":3600,"minTokens":1024},"compat":{"adaptiveThinking":true}},{"id":"claude-sonnet-4-5","promptCache":{"short":300,"long":3600,"minTokens":1024}},{"id":"claude-haiku-4-5","promptCache":{"short":300,"long":3600,"minTokens":4096}},{"id":"claude-opus-4-5","promptCache":{"short":300,"long":3600,"minTokens":4096}}]}',
|
|
7
7
|
chatgpt: '{"version":1,"provider":"chatgpt","modelsDev":false,"models":[]}',
|
|
8
8
|
dashscope: '{"version":1,"provider":"dashscope","modelsDev":"alibaba-cn","models":[{"id":"qwen3.8-max","thinkingLevelMap":{"off":null,"minimal":null,"low":"low","medium":"medium","high":null,"xhigh":"xhigh"},"compat":{"supportsReasoningEffort":true}},{"id":"qwen3.8-flash","thinkingLevelMap":{"off":null,"minimal":null,"low":"low","medium":"medium","high":null,"xhigh":"xhigh"},"compat":{"supportsReasoningEffort":true}},{"id":"qwen3.7-max","maxTokens":131072,"compat":{"supportsReasoningEffort":false}},{"id":"qwen3.7-plus","maxTokens":65536,"compat":{"supportsReasoningEffort":false}},{"id":"qwen3.6-plus","compat":{"supportsReasoningEffort":false}},{"id":"qwen3.6-flash","compat":{"supportsReasoningEffort":false}}]}',
|
|
9
|
-
deepseek: '{"version":1,"provider":"deepseek","modelsDev":"deepseek","models":[{"id":"deepseek-v4-pro","maxTokens":384000,"cost":{"input":1.32,"output":3.96,"cacheRead":0.044},"thinkingLevelMap":{"minimal":null,"low":null,"medium":null,"high":"high"},"_reason":"按官方价格页的高峰价(UTC 工作日 01–04、06–10 时)计,作上界;平峰为半价。快照价是平峰价或旧价"},{"id":"deepseek-flash","maxTokens":384000,"cost":{"input":0.3,"output":1.2,"cacheRead":0.006},"thinkingLevelMap":{"minimal":null,"low":"low","medium":null,"high":"high"},"_reason":"按官方价格页的高峰价(UTC 工作日 01–04、06–10 时)计,作上界;平峰为半价。快照价是平峰价或旧价"}]}',
|
|
9
|
+
deepseek: '{"version":1,"provider":"deepseek","modelsDev":"deepseek","models":[{"id":"deepseek-v4-pro","maxTokens":384000,"cost":{"input":1.32,"output":3.96,"cacheRead":0.044},"thinkingLevelMap":{"minimal":null,"low":null,"medium":null,"high":"high"},"_reason":"按官方价格页的高峰价(UTC 工作日 01–04、06–10 时)计,作上界;平峰为半价。快照价是平峰价或旧价","promptCache":{"short":3600,"minTokens":2048}},{"id":"deepseek-flash","maxTokens":384000,"cost":{"input":0.3,"output":1.2,"cacheRead":0.006},"thinkingLevelMap":{"minimal":null,"low":"low","medium":null,"high":"high"},"_reason":"按官方价格页的高峰价(UTC 工作日 01–04、06–10 时)计,作上界;平峰为半价。快照价是平峰价或旧价","promptCache":{"short":3600,"minTokens":2048}}]}',
|
|
10
10
|
google: '{"version":1,"provider":"google","modelsDev":"google","models":[{"id":"gemini-3.8-flash","thinkingLevelMap":{"off":null,"minimal":null,"low":"low","medium":"medium","high":"high","xhigh":null}},{"id":"gemini-3.7-flash","thinkingLevelMap":{"off":null,"minimal":null,"low":"low","medium":"medium","high":"high","xhigh":null}},{"id":"gemini-3.5-flash","thinkingLevelMap":{"off":null,"minimal":"minimal","low":"low","medium":"medium","high":"high","xhigh":null}},{"id":"gemini-3.5-flash-lite","thinkingLevelMap":{"off":null,"minimal":"minimal","low":"low","medium":"medium","high":"high","xhigh":null}},{"id":"gemini-3.1-pro-preview","thinkingLevelMap":{"off":null,"minimal":null,"low":"low","medium":"medium","high":"high","xhigh":null}},{"id":"gemini-3-flash-preview","thinkingLevelMap":{"off":null,"minimal":"minimal","low":"low","medium":"medium","high":"high","xhigh":null}},{"id":"gemini-2.5-pro","thinkingLevelMap":{"off":null,"minimal":128,"low":2048,"medium":8192,"high":32768}},{"id":"gemini-2.5-flash","thinkingLevelMap":{"minimal":128,"low":2048,"medium":8192,"high":24576}},{"id":"gemini-2.5-flash-lite","thinkingLevelMap":{"minimal":512,"low":2048,"medium":8192,"high":24576}}]}',
|
|
11
11
|
groq: '{"version":1,"provider":"groq","modelsDev":"groq","models":[{"id":"openai/gpt-oss-120b","thinkingLevelMap":{"off":null,"minimal":null,"low":"low","medium":"medium","high":"high","xhigh":null}},{"id":"openai/gpt-oss-20b","thinkingLevelMap":{"off":null,"minimal":null,"low":"low","medium":"medium","high":"high","xhigh":null}},{"id":"openai/gpt-oss-safeguard-20b","thinkingLevelMap":{"off":null,"minimal":null,"low":"low","medium":"medium","high":"high","xhigh":null}},{"id":"qwen/qwen3.8-27b","thinkingLevelMap":{"off":"none","minimal":null,"low":"low","medium":"medium","high":"high","xhigh":null}},{"id":"qwen/qwen3.6-27b","thinkingLevelMap":{"off":"none","minimal":null,"low":null,"medium":null,"high":"default","xhigh":null}},{"id":"llama-3.3-70b-versatile"},{"id":"llama-3.1-8b-instant"}]}',
|
|
12
12
|
lmstudio: '{"version":1,"provider":"lmstudio","modelsDev":false,"models":[]}',
|