diff --git a/docs/user-guide/en/token-saving/tokenless/QUICKSTART.md b/docs/user-guide/en/token-saving/tokenless/QUICKSTART.md index f5dd690a50..43c905cc73 100644 --- a/docs/user-guide/en/token-saving/tokenless/QUICKSTART.md +++ b/docs/user-guide/en/token-saving/tokenless/QUICKSTART.md @@ -165,5 +165,6 @@ standalone CLI from source, see - [User manual](user-manual.md): behavior boundaries and documentation map - [CLI reference](cli-reference.md): all subcommands and options - [Measuring savings](measuring-savings.md): statistics, dual runs, and AgentSight/SLS +- [Compression rates and applicable scenarios](compression-scenarios.md): expected rates per scenario and the standard test payloads - [Configuration and data privacy](configuration-and-privacy.md): toggles, storage, and sensitive data - [Troubleshooting](troubleshooting.md): common errors, upgrades, and uninstall diff --git a/docs/user-guide/en/token-saving/tokenless/compression-scenarios.md b/docs/user-guide/en/token-saving/tokenless/compression-scenarios.md new file mode 100644 index 0000000000..309070623e --- /dev/null +++ b/docs/user-guide/en/token-saving/tokenless/compression-scenarios.md @@ -0,0 +1,93 @@ +# Compression Rates and Applicable Scenarios + +[中文版](../../../zh/token-saving/tokenless/compression-scenarios.md) + +The compression rate Tokenless reports is a per-payload metric. This page explains the expected compression rate and the factors behind it for each strategy in different scenarios, and provides a set of standard test payloads so you can verify compression behavior in your own environment. + +## How the compression rate is computed + +- Compression rate = (before − after) ÷ before, with sizes measured in UTF-8 bytes. +- Token counts use the `ceil(bytes ÷ 4)` estimate; no model tokenizer is invoked. +- Operations with no savings are not recorded: when the estimated token count does not drop, the CLI emits the original text and produces no statistics record. +- The aggregated rate in `stats summary` and dashboards covers only payloads that passed through Tokenless; it is not the session-wide saving rate. See [Interpret the saving rate correctly](measuring-savings.md#interpret-the-saving-rate-correctly) for the conversion. + +## Applicable scenarios and reference rates per strategy + +| Strategy | Applicable scenarios | Reference rate | Main factors | +|----------|----------------------|----------------|--------------| +| Schema compression | Many Function Calling tool definitions, verbose tool/parameter descriptions, examples present | ~57% | Description length, examples/title presence, parameter count | +| Response compression | Structured tool/API JSON responses: repetitive record arrays, null/empty values, debug fields, long strings | ~26%–78% | Structural redundancy, array length, string length, truncation thresholds | +| TOON encoding | Tabular JSON with uniform fields and repetitive records | 15%–40% | Record homogeneity, field count | +| Command rewriting (RTK) | Noisy build/test/package-manager command output | 60%–90% | Command type, share of noise in the output | + +Reference rates are typical values observed on common workloads, not commitments; actual rates are determined by the content itself. Use the standard test payloads below to verify locally. + +### Scenarios with high compression rates + +- **Repetitive structured responses**: list endpoints, search results, bulk status queries. The longer the array and the more uniform the records, the higher the rate; array tails beyond the truncation threshold go into the Stash and stay retrievable, so compression remains end-to-end lossless. +- **API responses with redundant fields**: responses carrying `debug`, `trace`, or `logs` fields (default blacklist), `null` values, or empty strings/arrays/objects — that content is removed outright. +- **Sessions with many tool definitions**: when an agent registers dozens or hundreds of tools, schema compression strips examples, titles, and overly long descriptions from the definitions. +- **Command-line output**: noisy output from build tools, test frameworks, and package managers is filtered by RTK. RTK is a separate binary and works on command output rather than JSON payloads. + +### Scenarios with low or no compression + +| Scenario | Why | Expected behavior | +|----------|-----|-------------------| +| Short, compact responses | Compression yields no token savings | Original emitted, no statistics recorded (expected) | +| Natural-language prose (document retrieval, web pages) | Little removable structural redundancy | Low single digits to about ten percent | +| Source-code-dominated responses | Code itself has low redundancy | Around ten to twenty percent, depending on structure | +| High-entropy content: base64/binary, compressed or encrypted data, random strings | No redundancy to remove | Almost no savings | +| Output already trimmed upstream (fields filtered, pages truncated) | Redundancy already removed | Savings depend on the remaining content | +| Model reasoning output, system prompts, conversation history | Outside what Tokenless touches | Not involved | + +Different adapters use different truncation thresholds (shared shell policy `65536`/`128`/`8`, other structured-tool policy `1048576`/`65536`/`32`; see [Adapter processing rules](framework-integration.md#adapter-processing-rules)), so the same content can measure differently through the standalone CLI than inside an agent. + +## Verifying with the standard test payloads + +The repository ships a set of deterministic standard payloads under [`src/tokenless/benchmark/standard-payload/`](https://github.com/alibaba/anolisa/tree/main/src/tokenless/benchmark/standard-payload), covering the typical scenarios from high to low compression: + +| Payload | Scenario | Matching command | +|---------|----------|------------------| +| `schema_tools.json` | Function Calling schema array with verbose descriptions | `tokenless compress-schema --batch` | +| `response_api_records.json` | Structured API response (48 repetitive records, with debug/trace/logs fields) | `tokenless compress-response`, `tokenless compress-toon` | +| `response_code.json` | Code-search results (content is source code) | `tokenless compress-response` | +| `response_prose.json` | Document-search results (content is natural-language prose) | `tokenless compress-response` | + +All payload content is synthetic and contains no real user data. + +### Running + +Clone the repository and run the bundled check script (requires an installed tokenless): + +```bash +git clone https://github.com/alibaba/anolisa.git +cd anolisa/src/tokenless/benchmark/standard-payload +./run-standard-check.sh +``` + +Or download a single payload and run it by hand: + +```bash +curl -fsSL -O https://raw.githubusercontent.com/alibaba/anolisa/main/src/tokenless/benchmark/standard-payload/response_api_records.json +tokenless compress-response -f response_api_records.json \ + --session-id stdpay-api +tokenless stats summary --json +``` + +### Reference results + +The numbers below were measured with tokenless 0.7.6 and the default truncation thresholds on Linux x86_64. Character and token metrics are content-based and platform-independent, so they should reproduce on other supported platforms. + +| Case | Input (bytes) | Output (bytes) | Chars saved | Est. tokens saved | +|------|---------------|----------------|-------------|-------------------| +| Schema compression (`schema_tools.json`) | 10,060 | 4,976 | ~50.5% | ~50.7% | +| Response compression · structured (`response_api_records.json`) | 37,018 | 15,579 | ~57.9% | ~57.9% | +| Response compression · code (`response_code.json`) | 5,991 | 4,927 | ~17.8% | ~17.8% | +| Response compression · prose (`response_prose.json`) | 4,697 | 4,410 | ~6.1% | ~6.1% | +| TOON encoding (`response_api_records.json`) | 37,018 | 29,475 | ~20.4% | ~20.4% | + +### How to read the results + +- **Standard-payload results differ markedly from the reference table**: first check `tokenless --version`, then confirm the input files match the repository (`gen_standard_payload.py` regenerates them and the output must be byte-identical to the committed files). +- **Your real workload compresses differently from the reference table**: that is expected — the rate is determined by content redundancy. Use the two scenario tables above to place your workload in the right band. +- **Estimating session-wide savings**: overall estimated saving ≈ payload compression rate × tool-response share of total session tokens; see [Interpret the saving rate correctly](measuring-savings.md#interpret-the-saving-rate-correctly). diff --git a/docs/user-guide/en/token-saving/tokenless/measuring-savings.md b/docs/user-guide/en/token-saving/tokenless/measuring-savings.md index 30c5675b2a..c43d8a8bd5 100644 --- a/docs/user-guide/en/token-saving/tokenless/measuring-savings.md +++ b/docs/user-guide/en/token-saving/tokenless/measuring-savings.md @@ -173,6 +173,8 @@ Estimated overall saving rate For example, a 60% payload compression rate with tool payloads representing 20% of the session gives an estimated overall saving of about 12%. This is still not a provider billing guarantee. +For expected rates per scenario and the standard test payloads used to verify them locally, see [Compression rates and applicable scenarios](compression-scenarios.md). + ## Local AgentSight display AgentSight's Token savings view can aggregate `~/.tokenless/stats.db` read-only. When both run as the same user and AgentSight can access that database, SLS is not required to display local Tokenless statistics. diff --git a/docs/user-guide/en/token-saving/tokenless/user-manual.md b/docs/user-guide/en/token-saving/tokenless/user-manual.md index d3b4325ff8..dad8d1a27e 100644 --- a/docs/user-guide/en/token-saving/tokenless/user-manual.md +++ b/docs/user-guide/en/token-saving/tokenless/user-manual.md @@ -168,6 +168,7 @@ Command rewriting also changes the shell command submitted by the host. Most ada | Connect an Agent product or integrate AgentScope | [Agent and framework integration](framework-integration.md) | | Compress, retrieve, or run MCP manually | [CLI reference](cli-reference.md) | | Inspect savings or content changes, or run a dual comparison | [Measuring savings](measuring-savings.md) | +| Understand compression-rate scenarios or verify with standard payloads | [Compression rates and applicable scenarios](compression-scenarios.md) | | Change settings or understand local data | [Configuration and data privacy](configuration-and-privacy.md) | | Fix missing statistics, adapter, or Stash issues | [Troubleshooting](troubleshooting.md) | | Upgrade or uninstall | [Troubleshooting · Upgrade and uninstall](troubleshooting.md#upgrade-and-uninstall) | diff --git a/docs/user-guide/zh/token-saving/tokenless/QUICKSTART.md b/docs/user-guide/zh/token-saving/tokenless/QUICKSTART.md index 1c1dfe1edf..b08e5d0fb9 100644 --- a/docs/user-guide/zh/token-saving/tokenless/QUICKSTART.md +++ b/docs/user-guide/zh/token-saving/tokenless/QUICKSTART.md @@ -158,5 +158,6 @@ tokenless stats list --limit 1 - [用户手册](user-manual.md):能力边界和文档导航 - [CLI 参考](cli-reference.md):全部子命令和参数 - [效果度量](measuring-savings.md):统计、双跑对比和 AgentSight/SLS +- [压缩率与适用场景](compression-scenarios.md):各场景预期压缩率与标准测试负载 - [配置与数据隐私](configuration-and-privacy.md):开关、存储和敏感数据 - [故障排查](troubleshooting.md):常见错误、升级和卸载 diff --git a/docs/user-guide/zh/token-saving/tokenless/compression-scenarios.md b/docs/user-guide/zh/token-saving/tokenless/compression-scenarios.md new file mode 100644 index 0000000000..03088d6596 --- /dev/null +++ b/docs/user-guide/zh/token-saving/tokenless/compression-scenarios.md @@ -0,0 +1,93 @@ +# 压缩率与适用场景 + +[English](../../../en/token-saving/tokenless/compression-scenarios.md) + +Tokenless 报告的压缩率是 Payload 级指标。本页说明各策略在不同场景下的预期压缩率与影响因素,并提供一组标准测试负载,便于你在自己的环境中验证压缩行为。 + +## 如何计算压缩率 + +- 压缩率 =(压缩前 − 压缩后)÷ 压缩前,大小以 UTF-8 字节数计算。 +- Token 数使用 `ceil(字节数 ÷ 4)` 近似估算,不调用模型 Tokenizer。 +- 无收益的操作不入库:压缩后估算 Token 数没有下降时,CLI 输出原文,不产生统计记录。 +- `stats summary` 与面板中的聚合压缩率只覆盖经过 Tokenless 的 Payload,不等于会话总体节省率,换算方法见[正确解释节省率](measuring-savings.md#正确解释节省率)。 + +## 各策略的适用场景与参考压缩率 + +| 策略 | 适用场景 | 参考压缩率 | 主要影响因素 | +|------|----------|------------|--------------| +| Schema 压缩 | Function Calling 工具定义多、工具或参数描述冗长、带示例 | ~57% | 描述长度、examples/title 多少、参数数量 | +| 响应压缩 | 结构化工具/API JSON 响应:重复记录数组、null/空值、debug 字段、长字符串 | ~26%–78% | 结构冗余度、数组长度、字符串长度、截断阈值 | +| TOON 编码 | 字段统一、记录重复的表格型 JSON | 15%–40% | 记录同质性、字段数量 | +| 命令重写(RTK) | 构建、测试、包管理等高噪声命令输出 | 60%–90% | 命令类型、输出中噪声占比 | + +参考压缩率是常见负载下的典型值,不是承诺值;实际高低由内容本身决定,可用下文的标准测试负载在本地验证。 + +### 压缩率较高的典型场景 + +- **重复结构化响应**:列表接口、搜索结果、批量状态查询。数组越长、记录越同质,压缩率越高;数组超过截断阈值时尾部进入 Stash,可按标记取回,端到端无损。 +- **冗余字段多的 API 响应**:包含 `debug`、`trace`、`logs` 等默认黑名单字段、`null` 值、空字符串/数组/对象的响应,这些内容会被直接移除。 +- **工具定义多的会话**:Agent 注册几十上百个工具时,Schema 压缩移除定义中的示例、标题和超长描述。 +- **命令行输出**:构建工具、测试框架、包管理器的高噪声输出经 RTK 过滤。RTK 是独立二进制,作用于命令输出而非 JSON Payload。 + +### 压缩率偏低或不适用的场景 + +| 场景 | 原因 | 预期表现 | +|------|------|----------| +| 短响应、结构紧凑 | 压缩无 Token 收益 | 输出原文、不记录统计(预期行为) | +| 自然语言长文(文档检索、网页正文) | 可移除的结构冗余少 | 低个位数到一成左右 | +| 源码为主的响应 | 代码自身冗余低 | 一成到两成左右,取决于结构 | +| 高熵内容:base64/二进制、已压缩或加密数据、随机字符串 | 无冗余可移除 | 几乎无收益 | +| 已被上游精简的输出(已过滤字段、已分页截断) | 冗余已提前移除 | 收益取决于剩余内容 | +| 模型推理输出、system prompt、对话历史 | 不在 Tokenless 处理范围 | 不涉及 | + +不同 Adapter 使用不同的截断阈值(共享 Shell 策略 `65536`/`128`/`8`,其他结构化工具策略 `1048576`/`65536`/`32`,详见 [Adapter 处理规则](framework-integration.md#adapter-处理规则)),因此同一内容在独立 CLI 与 Agent 内的实测压缩率可能不同。 + +## 用标准测试负载验证 + +仓库提供一组确定性标准负载,位于 [`src/tokenless/benchmark/standard-payload/`](https://github.com/alibaba/anolisa/tree/main/src/tokenless/benchmark/standard-payload),覆盖从高到低的典型场景: + +| 负载 | 场景 | 对应命令 | +|------|------|----------| +| `schema_tools.json` | 描述冗长的 Function Calling Schema 数组 | `tokenless compress-schema --batch` | +| `response_api_records.json` | 结构化 API 响应(48 条重复记录,含 debug/trace/logs 字段) | `tokenless compress-response`、`tokenless compress-toon` | +| `response_code.json` | 代码搜索结果(内容为源码) | `tokenless compress-response` | +| `response_prose.json` | 文档搜索结果(内容为自然语言长文) | `tokenless compress-response` | + +负载内容全部为构造的合成数据,不含真实用户数据。 + +### 运行 + +克隆仓库并运行配套检查脚本(需要已安装 tokenless): + +```bash +git clone https://github.com/alibaba/anolisa.git +cd anolisa/src/tokenless/benchmark/standard-payload +./run-standard-check.sh +``` + +也可以只下载单个负载手动运行: + +```bash +curl -fsSL -O https://raw.githubusercontent.com/alibaba/anolisa/main/src/tokenless/benchmark/standard-payload/response_api_records.json +tokenless compress-response -f response_api_records.json \ + --session-id stdpay-api +tokenless stats summary --json +``` + +### 参考结果 + +以下数值在 tokenless 0.7.6、默认截断阈值下实测,环境为 Linux x86_64。字符与 Token 指标都是基于内容的度量,与平台无关,在其他受支持平台上应可复现。 + +| 用例 | 输入(字节) | 输出(字节) | 字符节省 | 估算 Token 节省 | +|------|--------------|--------------|----------|------------------| +| Schema 压缩(`schema_tools.json`) | 10,060 | 4,976 | ~50.5% | ~50.7% | +| 响应压缩 · 结构化(`response_api_records.json`) | 37,018 | 15,579 | ~57.9% | ~57.9% | +| 响应压缩 · 代码(`response_code.json`) | 5,991 | 4,927 | ~17.8% | ~17.8% | +| 响应压缩 · 长文(`response_prose.json`) | 4,697 | 4,410 | ~6.1% | ~6.1% | +| TOON 编码(`response_api_records.json`) | 37,018 | 29,475 | ~20.4% | ~20.4% | + +### 如何解读结果 + +- **标准负载结果与参考表差异明显**:先用 `tokenless --version` 确认版本,再确认输入文件与仓库一致(`gen_standard_payload.py` 可重新生成,输出应与仓库文件逐字节相同)。 +- **真实业务负载的压缩率与参考表不同**:这是正常现象,压缩率由内容冗余度决定。对照上文两个场景表,可以判断自己的负载落在哪一档。 +- **估算会话总体节省**:总体估算节省率 ≈ Payload 压缩率 × 工具响应占会话总 Token 的比例,见[正确解释节省率](measuring-savings.md#正确解释节省率)。 diff --git a/docs/user-guide/zh/token-saving/tokenless/measuring-savings.md b/docs/user-guide/zh/token-saving/tokenless/measuring-savings.md index a1393f223c..ef37fa1ba3 100644 --- a/docs/user-guide/zh/token-saving/tokenless/measuring-savings.md +++ b/docs/user-guide/zh/token-saving/tokenless/measuring-savings.md @@ -173,6 +173,8 @@ tokenless stats summary \ 例如,Payload 压缩率为 60%,但工具 Payload 只占会话总 Token 的 20%,则总体估算收益约为 12%。这个结果仍不是提供商账单保证值。 +不同场景下的预期压缩率,以及用于本地验证的标准测试负载,见[压缩率与适用场景](compression-scenarios.md)。 + ## AgentSight 本地展示 AgentSight 的 Token savings 页面可以只读聚合 `~/.tokenless/stats.db`。两者由同一用户运行,且 AgentSight 能访问该数据库时,不需要通过 SLS 才能看到本地 Tokenless 统计。 diff --git a/docs/user-guide/zh/token-saving/tokenless/user-manual.md b/docs/user-guide/zh/token-saving/tokenless/user-manual.md index 172a557c7d..fe9ada7335 100644 --- a/docs/user-guide/zh/token-saving/tokenless/user-manual.md +++ b/docs/user-guide/zh/token-saving/tokenless/user-manual.md @@ -166,6 +166,7 @@ Stash 并不能让所有压缩都可逆。被移除的 `debug`/`trace` 字段、 | 接入 Agent 产品或集成 AgentScope | [Agent 与框架集成](framework-integration.md) | | 手动压缩、取回或运行 MCP | [CLI 参考](cli-reference.md) | | 查看节省或内容变化、做双跑对比 | [效果度量](measuring-savings.md) | +| 了解压缩率适用场景或用标准负载验证 | [压缩率与适用场景](compression-scenarios.md) | | 修改配置或了解本地数据 | [配置与数据隐私](configuration-and-privacy.md) | | 解决无统计、Adapter 或 Stash 问题 | [故障排查](troubleshooting.md) | | 升级或卸载 | [故障排查 · 升级与卸载](troubleshooting.md#升级与卸载) | diff --git a/src/tokenless/benchmark/README.md b/src/tokenless/benchmark/README.md index b7906957f0..f727979e49 100644 --- a/src/tokenless/benchmark/README.md +++ b/src/tokenless/benchmark/README.md @@ -26,6 +26,11 @@ Each subdirectory is a standalone workspace (its own `Cargo.toml` with an empty `[workspace]` table) kept out of the main tokenless workspace on purpose — see the per-workspace `README.md` files for build/run instructions and methodology. +In addition to the two benchmark layers, [`standard-payload/`](standard-payload) +holds the deterministic user-facing payloads behind the user-guide page +"Compression rates and applicable scenarios" — see its own `README.md` for the +check script and stability policy. + Each layer also keeps its results in its own `reports/` directory (`l1-compressor/reports/`, `l2-module/reports/`) so the two layers' numbers never mix. Both directories are gitignored: benchmark reports are diff --git a/src/tokenless/benchmark/standard-payload/README.md b/src/tokenless/benchmark/standard-payload/README.md new file mode 100644 index 0000000000..185d7331bd --- /dev/null +++ b/src/tokenless/benchmark/standard-payload/README.md @@ -0,0 +1,84 @@ + + +# Tokenless Standard Test Payloads + +Stable, fully deterministic payloads for verifying tokenless compression +behavior and sanity-checking compression rates in your own environment. They +are the reference inputs behind the user-guide page +[Compression rates and applicable scenarios](../../../docs/user-guide/en/token-saving/tokenless/compression-scenarios.md) +([中文版](../../../docs/user-guide/zh/token-saving/tokenless/compression-scenarios.md)). + +All content is synthetic; the payloads contain no real user data, hosts, or +credentials. + +## Manifest + +| File | Scenario | Exercises | +|---|---|---| +| `schema_tools.json` | Function-calling schema array with verbose descriptions, examples and titles | `compress-schema --batch` (schema compression, high-savings case) | +| `response_api_records.json` | Structured API/tool response: envelope plus 48 repetitive records, null/empty values, `debug`/`trace`/`logs` fields | `compress-response` (high-savings case, includes array-tail stash) and `compress-toon` | +| `response_code.json` | Code-search results whose content is source code | `compress-response` (medium/low-savings case) | +| `response_prose.json` | Document-search results whose content is natural-language prose | `compress-response` (low-savings boundary case) | + +## Running the check + +With `tokenless` on PATH: + +```bash +./run-standard-check.sh +``` + +Or point the script at a specific binary: + +```bash +TOKENLESS_BIN=/path/to/tokenless ./run-standard-check.sh +``` + +The script runs each payload through the CLI inside an isolated +`TOKENLESS_DATA_DIR` (your real statistics and stash databases are never +touched) and prints the `stats summary --json` result per case. Compare the +`chars_saved_percent` / `tokens_saved_percent` values against the reference +table in the user-guide page. + +Manual single-payload runs work the same way: + +```bash +tokenless compress-response -f response_api_records.json --session-id stdpay-api +tokenless stats summary --json +``` + +## Regenerating the payloads + +`gen_standard_payload.py` is the single source of truth for the payload +content. It uses only the Python standard library, contains no randomness, +and writes byte-identical output on every run: + +```bash +python3 gen_standard_payload.py +``` + +The generated JSON files are committed so that the check script does not +require Python. + +## Stability policy + +These payloads are a published reference: the user guide quotes measured +compression rates for exactly these bytes. Treat them like a fixture set — + +- Do not edit the generated JSON files by hand; change the generator and + regenerate instead. +- Any change to the generator must re-measure and update the reference table + in the user-guide page (both locales) in the same change. +- Do not rename files without updating the user guide and the check script. diff --git a/src/tokenless/benchmark/standard-payload/gen_standard_payload.py b/src/tokenless/benchmark/standard-payload/gen_standard_payload.py new file mode 100644 index 0000000000..f24372c124 --- /dev/null +++ b/src/tokenless/benchmark/standard-payload/gen_standard_payload.py @@ -0,0 +1,722 @@ +#!/usr/bin/env python3 +# Copyright 2026 Alibaba Cloud +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +"""Standard test payloads for verifying tokenless compression behavior. + +These payloads are the documented reference inputs for the user-guide page +"Compression rates and applicable scenarios". They are fully deterministic +(no RNG, no timestamps, no environment input) so that anyone can regenerate +byte-identical files and compare measured compression rates against the +published reference table. + +Outputs (pretty-printed, UTF-8, natural key order): + schema_tools.json Function-calling schema array (schema compression) + response_api_records.json Structured API/tool response with repetitive + records, null/empty values and debug/trace/logs + fields (response compression, high-savings case) + response_code.json Code-search results whose content is source code + (response compression, medium/low-savings case) + response_prose.json Document-search results whose content is natural + language prose (response compression, low-savings + boundary case) + +Regenerate with: python3 gen_standard_payload.py + +The generated files are committed so that running the check script does not +require Python. If you change this generator, regenerate the files and update +the reference table in the user-guide page in the same change. +""" + +from __future__ import annotations + +import json +from pathlib import Path + +OUT_DIR = Path(__file__).resolve().parent + + +def _tool(name: str, description: str, properties: dict, required: list[str], + title: str | None = None, examples: list | None = None) -> dict: + parameters: dict = { + "type": "object", + "properties": properties, + "required": required, + } + if examples is not None: + parameters["examples"] = examples + function: dict = {"name": name, "description": description, "parameters": parameters} + if title is not None: + function["title"] = title + return {"type": "function", "function": function} + + +def build_schema_tools() -> list[dict]: + return [ + _tool( + name="search_codebase", + title="Codebase Search Tool", + description=( + "Search the entire codebase for symbols, definitions and free-text matches. " + "Use this tool first whenever you need to locate where a function, class or " + "configuration key is defined or referenced. The search index covers all " + "committed files and is refreshed at the start of every session.\n\n" + "Results are ranked by relevance and include the file path, line range and a " + "short snippet for every match. Prefer a narrow `query` over a broad one: " + "queries with more than three words rarely improve recall and make the result " + "set harder to read.\n\n" + "```python\n" + "# Example: find every caller of the retry helper\n" + "search_codebase(query=\"with_retry\", file_pattern=\"*.py\")\n" + "```\n\n" + "Do not use this tool for files that were created after the session started; " + "they are not indexed yet. Read such files directly with `read_file` instead." + ), + properties={ + "query": { + "type": "string", + "description": ( + "The search expression. Supports plain text, symbol names and simple " + "regular expressions. Keep it short and specific; the engine returns " + "at most 50 matches ranked by relevance." + ), + }, + "file_pattern": { + "type": "string", + "description": ( + "Optional glob that restricts the search to matching paths, for " + "example `src/**/*.rs` or `*.test.ts`. When omitted every indexed " + "file is searched." + ), + }, + "max_results": { + "type": "integer", + "description": "Maximum number of matches to return, between 1 and 50. Defaults to 20.", + "minimum": 1, + "maximum": 50, + }, + }, + required=["query"], + examples=[ + {"query": "parse_config", "file_pattern": "src/**/*.rs"}, + {"query": "TODO(.*timeout)", "max_results": 10}, + ], + ), + _tool( + name="read_file", + title="File Reader", + description=( + "Read the content of a single file from the workspace. The tool returns the " + "file as text together with its size and last modification time. Binary files " + "are rejected with an explicit error instead of being returned.\n\n" + "For large files prefer a line range over reading the whole file; responses " + "above the context budget are truncated and annotated. When you only need to " + "know whether a symbol exists, use `search_codebase` first and read exactly " + "the matching range afterwards.\n\n" + "```\n" + "read_file(path=\"src/server/router.rs\", start_line=120, end_line=180)\n" + "```" + ), + properties={ + "path": { + "type": "string", + "description": "Workspace-relative path of the file to read. Symbolic links are resolved.", + }, + "start_line": { + "type": "integer", + "description": "First line to read, 1-based. Optional; defaults to the first line.", + }, + "end_line": { + "type": "integer", + "description": "Last line to read, inclusive. Optional; defaults to the last line.", + }, + }, + required=["path"], + ), + _tool( + name="run_shell_command", + title="Shell Command Runner", + description=( + "Run a shell command inside the workspace sandbox and return its combined " + "standard output and standard error. The command runs with a configurable " + "timeout and is killed when the timeout is exceeded.\n\n" + "Use this tool for builds, tests, linters and version-control commands. " + "Commands that require network access must be declared in the session " + "manifest, otherwise they fail with a permission error.\n\n" + "```bash\n" + "# Example: run the unit tests for one crate\n" + "cargo test -p tokenless-stats\n" + "```\n\n" + "Never run destructive commands (force push, recursive delete of shared " + "directories) through this tool without an explicit user confirmation." + ), + properties={ + "command": { + "type": "string", + "description": "The shell command line to execute. It is passed to `bash -c` unchanged.", + }, + "timeout_seconds": { + "type": "integer", + "description": "Kill the command after this many seconds. Defaults to 120, maximum 1800.", + "default": 120, + }, + "working_directory": { + "type": "string", + "description": "Optional workspace-relative directory the command starts in.", + }, + }, + required=["command"], + examples=[{"command": "cargo fmt --check", "timeout_seconds": 60}], + ), + _tool( + name="list_directory", + title="Directory Lister", + description=( + "List the entries of a directory in the workspace. Each entry includes its " + "name, type (file or directory), size in bytes and last modification time. " + "Hidden entries are included only when requested.\n\n" + "The result is sorted alphabetically. Use `recursive` with care: deep trees " + "produce very large responses and are truncated beyond 5000 entries." + ), + properties={ + "path": { + "type": "string", + "description": "Workspace-relative path of the directory to list.", + }, + "recursive": { + "type": "boolean", + "description": "When true, list the whole subtree instead of a single level.", + "default": False, + }, + "include_hidden": { + "type": "boolean", + "description": "When true, include entries whose name starts with a dot.", + "default": False, + }, + }, + required=["path"], + ), + _tool( + name="create_merge_request", + title="Merge Request Creator", + description=( + "Create a merge request from the current branch to a target branch. The tool " + "pushes the branch if it has not been pushed yet, fills in the title and " + "description, and returns the merge request number and URL.\n\n" + "The description supports Markdown. Keep the title under 80 characters and " + "start it with a conventional-commit type such as `feat:` or `fix:` so the " + "release tooling can classify the change automatically.\n\n" + "```\n" + "create_merge_request(\n" + " title=\"fix(stats): record dry-run predictions\",\n" + " description=\"Dry-run records were dropped from the summary.\",\n" + " target_branch=\"main\",\n" + " labels=[\"tokenless\", \"bug\"],\n" + ")\n" + "```" + ), + properties={ + "title": { + "type": "string", + "description": "One-line summary of the change, under 80 characters.", + "maxLength": 80, + }, + "description": { + "type": "string", + "description": "Markdown body explaining motivation, approach and testing.", + }, + "target_branch": { + "type": "string", + "description": "Branch the change should merge into. Defaults to `main`.", + "default": "main", + }, + "labels": { + "type": "array", + "description": "Optional labels to attach. Unknown labels are created on demand.", + "items": {"type": "string"}, + }, + "reviewers": { + "type": "array", + "description": "Optional list of reviewer usernames.", + "items": {"type": "string"}, + }, + "draft": { + "type": "boolean", + "description": "Create the merge request as a draft that cannot be merged.", + "default": False, + }, + }, + required=["title", "description"], + ), + _tool( + name="query_database", + title="Analytics Database Query", + description=( + "Run a read-only SQL query against the analytics replica and return the rows " + "as JSON. Write statements are rejected before execution. Queries that return " + "more than 1000 rows are truncated and flagged so downstream consumers can " + "detect the limit.\n\n" + "Prefer explicit column lists over `SELECT *` and always include a `LIMIT` " + "clause; the replica enforces a 30 second statement timeout.\n\n" + "```sql\n" + "SELECT day, active_users, p95_latency_ms\n" + "FROM service_health_daily\n" + "WHERE day >= current_date - interval '7 days'\n" + "ORDER BY day DESC;\n" + "```" + ), + properties={ + "sql": { + "type": "string", + "description": "The read-only SQL statement to execute on the analytics replica.", + }, + "database": { + "type": "string", + "description": "Logical database name. One of `analytics`, `billing_readonly`, `events`.", + "enum": ["analytics", "billing_readonly", "events"], + }, + "parameters": { + "type": "object", + "description": ( + "Optional named parameters bound into the statement, which avoids " + "quoting issues and injection risk." + ), + "additionalProperties": {"type": ["string", "number", "boolean"]}, + }, + }, + required=["sql", "database"], + examples=[{"sql": "SELECT 1", "database": "analytics"}], + ), + ] + + +_REGIONS = ["cn-hangzhou", "cn-shanghai", "us-west-1", "eu-central-1"] +_ZONES = ["a", "b", "c"] +_STATUSES = ["active", "active", "active", "pending", "stopped"] + + +def _record(i: int) -> dict: + region = _REGIONS[i % len(_REGIONS)] + zone = _ZONES[i % len(_ZONES)] + status = _STATUSES[i % len(_STATUSES)] + hour = i % 24 + return { + "id": f"i-{20260000 + i}", + "name": f"worker-node-{i:03d}", + "region": region, + "zone": f"{region}-{zone}", + "status": status, + "cpu_percent": round(12.5 + (i * 7) % 80, 1), + "memory_mb": 1024 + (i * 256) % 15360, + "disk_mb": 20480 + (i * 512) % 81920, + "ip_address": f"192.0.2.{10 + (i % 240)}", + "created_at": f"2026-07-{(i % 28) + 1:02d}T{hour:02d}:15:00Z", + "updated_at": f"2026-08-{(i % 14) + 1:02d}T{hour:02d}:45:00Z", + "tags": ["pool:batch", f"tier:{'standard' if i % 3 else 'highmem'}"], + "labels": {"team": "data-platform", "cost-center": f"cc-{1000 + i % 7}"}, + "description": ( + f"Batch worker node {i:03d} scheduled by the capacity planner; " + f"runs nightly extraction jobs for shard {i % 16}." + ), + "last_error": None if i % 5 else "heartbeat timeout after 3 retries", + "metadata": {}, + "health_checks": [], + } + + +def build_api_records() -> dict: + records = [_record(i) for i in range(48)] + return { + "status": "success", + "request_id": "req-20260801-000123", + "took_ms": 187, + "page": 1, + "page_size": 48, + "total": 1234, + "debug": { + "cache_hit": False, + "shards_scanned": 16, + "query_plan": "index_scan on instances_by_region", + "internal_notes": "planner fallback disabled", + }, + "trace": [ + { + "span_id": f"span-{1000 + i}", + "name": stage, + "duration_ms": 4 + i * 3, + "attributes": {"shard": i % 16, "attempt": 1}, + } + for i, stage in enumerate( + [ + "auth.check", + "quota.check", + "planner.plan", + "index.open", + "index.scan", + "index.scan", + "rows.decode", + "response.encode", + ] + ) + ], + "logs": [ + f"2026-08-01T00:00:0{i % 10}Z INFO stage={stage} ok" + for i, stage in enumerate( + [ + "auth", + "quota", + "planner", + "index", + "scan", + "decode", + "encode", + "respond", + "metrics", + "cleanup", + ] + ) + ], + "records": records, + } + + +_CODE_SNIPPETS = [ + ( + "rust", + "src/net/retry.rs", + 12, + """\ +pub async fn with_retry(mut op: F, policy: &RetryPolicy) -> Result +where + F: FnMut() -> futures::future::BoxFuture<'static, Result>, + E: IsTransient, +{ + let mut attempt = 0usize; + loop { + match op().await { + Ok(value) => return Ok(value), + Err(err) if err.is_transient() && attempt < policy.max_attempts => { + attempt += 1; + let delay = policy.delay_for(attempt); + tokio::time::sleep(delay).await; + } + Err(err) => return Err(err), + } + } +}""", + ), + ( + "python", + "pipeline/retry.py", + 34, + """\ +def with_backoff(func, *, attempts=5, base=0.5, factor=2.0, retry_on=(TimeoutError,)): + delay = base + for attempt in range(1, attempts + 1): + try: + return func() + except retry_on as exc: + if attempt == attempts: + raise + logging.warning("attempt %d failed: %s; sleeping %.2fs", attempt, exc, delay) + time.sleep(delay) + delay *= factor""", + ), + ( + "go", + "internal/httpclient/retry.go", + 21, + """\ +func DoWithRetry(ctx context.Context, client *http.Client, req *http.Request, max int) (*http.Response, error) { + var resp *http.Response + var err error + for attempt := 0; attempt <= max; attempt++ { + resp, err = client.Do(req.Clone(ctx)) + if err == nil && resp.StatusCode < 500 { + return resp, nil + } + if attempt < max { + time.Sleep(backoff(attempt)) + } + } + return resp, err +}""", + ), + ( + "typescript", + "src/client/fetchRetry.ts", + 8, + """\ +export async function fetchRetry(url: string, init: RequestInit, attempts = 4): Promise { + let lastError: unknown; + for (let attempt = 0; attempt < attempts; attempt++) { + try { + const response = await fetch(url, init); + if (response.status < 500) return response; + lastError = new Error(`server error ${response.status}`); + } catch (error) { + lastError = error; + } + await sleep(2 ** attempt * 250); + } + throw lastError; +}""", + ), + ( + "bash", + "scripts/wait_for_endpoint.sh", + 3, + """\ +attempt=0 +until curl --fail --silent "$ENDPOINT/health" > /dev/null; do + attempt=$((attempt + 1)) + if [ "$attempt" -ge 30 ]; then + echo "endpoint never became healthy" >&2 + exit 1 + fi + sleep 2 +done +echo "endpoint healthy after $attempt retries\"""", + ), + ( + "rust", + "src/net/timeout.rs", + 40, + """\ +pub async fn with_timeout(future: F, limit: Duration) -> Result +where + F: Future, +{ + match tokio::time::timeout(limit, future).await { + Ok(output) => Ok(output), + Err(_) => Err(Elapsed { limit }), + } +}""", + ), + ( + "python", + "pipeline/circuit_breaker.py", + 12, + """\ +class CircuitBreaker: + def __init__(self, failure_threshold=5, recovery_timeout=30.0): + self.failure_threshold = failure_threshold + self.recovery_timeout = recovery_timeout + self.failures = 0 + self.opened_at = None + + def allow(self) -> bool: + if self.failures < self.failure_threshold: + return True + if self.opened_at is None: + return False + return time.monotonic() - self.opened_at >= self.recovery_timeout""", + ), + ( + "go", + "internal/jitter/jitter.go", + 9, + """\ +func BackoffWithJitter(attempt int, base, cap time.Duration) time.Duration { + exp := base << attempt + if exp > cap || exp <= 0 { + exp = cap + } + jitter := time.Duration(rand.Int63n(int64(exp)/2 + 1)) + return exp/2 + jitter +}""", + ), + ( + "typescript", + "src/client/sleep.ts", + 1, + """\ +export function sleep(ms: number): Promise { + return new Promise((resolve) => setTimeout(resolve, ms)); +} + +export const defaultRetryConfig = { + attempts: 4, + baseDelayMs: 250, + maxDelayMs: 8000, + jitter: true, +} as const;""", + ), + ( + "yaml", + "deploy/retry-policy.yaml", + 1, + """\ +retry_policy: + max_attempts: 5 + initial_backoff: 500ms + max_backoff: 30s + backoff_multiplier: 2.0 + retry_on: + - connection_reset + - upstream_timeout + - status_503 + non_retryable: + - status_400 + - status_401""", + ), +] + + +def build_code_response() -> dict: + results = [] + for index, (language, path, start_line, snippet) in enumerate(_CODE_SNIPPETS): + lines = snippet.splitlines() + results.append( + { + "path": path, + "language": language, + "start_line": start_line, + "end_line": start_line + len(lines) - 1, + "score": round(0.98 - index * 0.07, 2), + "snippet": snippet, + "error": None, + "warnings": [], + } + ) + return { + "tool": "code_search", + "query": "retry backoff", + "total_matches": 128, + "returned": len(results), + "results": results, + "truncated": False, + "index_version": None, + } + + +_PROSE_DOCS = [ + { + "title": "Capacity Planning Basics for Agent Platforms", + "url": "https://example.com/articles/capacity-planning-basics", + "published_at": "2026-03-18", + "summary": ( + "A practical introduction to capacity planning for platforms that serve " + "agent workloads, covering workload characterization, headroom policy and " + "percentile-based latency budgets." + ), + "content": ( + "Capacity planning starts with characterizing the workload. For agent " + "platforms this means measuring not only request rates but also the shape " + "of each session: how many tool calls a typical session makes, how large " + "the tool responses are, and how long sessions stay active. Two platforms " + "with identical requests-per-second can differ by an order of magnitude in " + "token throughput if their session shapes differ.\n\n" + "Once the workload is characterized, define a headroom policy. A common " + "starting point is to provision for the 95th percentile day plus thirty " + "percent spare capacity, then adjust after observing at least two full " + "weekly cycles. Headroom is cheapest when bought before the traffic " + "arrives; emergency capacity during an incident always costs more in both " + "money and reliability.\n\n" + "Finally, track latency budgets by percentile rather than by average. " + "Average latency hides the long sessions that matter most, because agent " + "sessions are heavy-tailed: a small number of sessions consume most of " + "the tokens. Budgeting against the 90th or 95th percentile keeps the " + "system sized for the sessions users actually notice." + ), + "highlights": [], + }, + { + "title": "Observability for Batch Pipelines", + "url": "https://example.com/articles/batch-pipeline-observability", + "published_at": "2026-05-02", + "summary": ( + "How to instrument batch pipelines so failures are attributable to a " + "single stage, with guidance on metrics, structured logs and trace " + "propagation across queued work." + ), + "content": ( + "Batch pipelines fail differently from request-driven services. A web " + "service either answers or times out, but a batch pipeline can silently " + "drop work, duplicate work, or fall behind without any visible error. " + "Observability for batch systems therefore starts with accounting: every " + "unit of work that enters the pipeline must be traceable to exactly one " + "terminal state, either completed, failed or expired.\n\n" + "Structured logs are the backbone of that accounting. Each stage should " + "emit one structured record per unit of work, carrying a stable work " + "identifier, the stage name, and the outcome. Free-form logging makes it " + "impossible to answer the simplest operational question, which is how many " + "units are currently stuck between two stages.\n\n" + "Traces add the time dimension. Propagating a trace identifier through " + "queue metadata lets operators see how long a unit of work waited in each " + "queue, which is usually where batch latency actually goes. The metric to " + "alert on is end-to-end age of the oldest incomplete unit, not the " + "duration of individual stages." + ), + "highlights": [], + }, + { + "title": "Load Testing Strategies That Predict Production", + "url": "https://example.com/articles/load-testing-strategies", + "published_at": "2026-06-21", + "summary": ( + "Why constant-rate load tests mislead, and how ramp profiles, soak tests " + "and saturation-point measurement produce numbers that actually predict " + "production behavior." + ), + "content": ( + "A constant-rate load test answers one question: does the system survive " + "this exact rate? Production traffic never looks like that. Real traffic " + "ramps, spikes, and recovers, and most production failures happen on the " + "ramp rather than at steady state. A useful load test therefore includes " + "a ramp profile that exceeds the fastest growth observed in production, " + "so the test exposes queue buildup and cache warm-up behavior before users " + "do.\n\n" + "Soak tests answer a different question: does the system leak? Memory " + "leaks, connection pool exhaustion and file descriptor growth only show " + "up after hours of steady operation. Running the representative workload " + "at seventy percent of the target rate for at least eight hours, while " + "watching resource counters, catches most of these defects.\n\n" + "The most valuable number a load test produces is the saturation point: " + "the rate at which latency stops scaling linearly and starts climbing " + "sharply. Measure it by increasing the rate in steps and recording the " + "95th percentile latency at each step. The saturation point, not the " + "failure point, is what capacity plans should be built on." + ), + "highlights": [], + }, +] + + +def build_prose_response() -> dict: + return { + "source": "web_search", + "query": "capacity planning best practices", + "total_results": 3, + "results": _PROSE_DOCS, + "next_cursor": None, + "suggestions": [], + } + + +def _write(name: str, value: object) -> None: + path = OUT_DIR / name + path.write_text(json.dumps(value, indent=2, ensure_ascii=False) + "\n", encoding="utf-8") + print(f"wrote {path.name} ({path.stat().st_size} bytes)") + + +def main() -> None: + _write("schema_tools.json", build_schema_tools()) + _write("response_api_records.json", build_api_records()) + _write("response_code.json", build_code_response()) + _write("response_prose.json", build_prose_response()) + + +if __name__ == "__main__": + main() diff --git a/src/tokenless/benchmark/standard-payload/response_api_records.json b/src/tokenless/benchmark/standard-payload/response_api_records.json new file mode 100644 index 0000000000..5f00fce262 --- /dev/null +++ b/src/tokenless/benchmark/standard-payload/response_api_records.json @@ -0,0 +1,1302 @@ +{ + "status": "success", + "request_id": "req-20260801-000123", + "took_ms": 187, + "page": 1, + "page_size": 48, + "total": 1234, + "debug": { + "cache_hit": false, + "shards_scanned": 16, + "query_plan": "index_scan on instances_by_region", + "internal_notes": "planner fallback disabled" + }, + "trace": [ + { + "span_id": "span-1000", + "name": "auth.check", + "duration_ms": 4, + "attributes": { + "shard": 0, + "attempt": 1 + } + }, + { + "span_id": "span-1001", + "name": "quota.check", + "duration_ms": 7, + "attributes": { + "shard": 1, + "attempt": 1 + } + }, + { + "span_id": "span-1002", + "name": "planner.plan", + "duration_ms": 10, + "attributes": { + "shard": 2, + "attempt": 1 + } + }, + { + "span_id": "span-1003", + "name": "index.open", + "duration_ms": 13, + "attributes": { + "shard": 3, + "attempt": 1 + } + }, + { + "span_id": "span-1004", + "name": "index.scan", + "duration_ms": 16, + "attributes": { + "shard": 4, + "attempt": 1 + } + }, + { + "span_id": "span-1005", + "name": "index.scan", + "duration_ms": 19, + "attributes": { + "shard": 5, + "attempt": 1 + } + }, + { + "span_id": "span-1006", + "name": "rows.decode", + "duration_ms": 22, + "attributes": { + "shard": 6, + "attempt": 1 + } + }, + { + "span_id": "span-1007", + "name": "response.encode", + "duration_ms": 25, + "attributes": { + "shard": 7, + "attempt": 1 + } + } + ], + "logs": [ + "2026-08-01T00:00:00Z INFO stage=auth ok", + "2026-08-01T00:00:01Z INFO stage=quota ok", + "2026-08-01T00:00:02Z INFO stage=planner ok", + "2026-08-01T00:00:03Z INFO stage=index ok", + "2026-08-01T00:00:04Z INFO stage=scan ok", + "2026-08-01T00:00:05Z INFO stage=decode ok", + "2026-08-01T00:00:06Z INFO stage=encode ok", + "2026-08-01T00:00:07Z INFO stage=respond ok", + "2026-08-01T00:00:08Z INFO stage=metrics ok", + "2026-08-01T00:00:09Z INFO stage=cleanup ok" + ], + "records": [ + { + "id": "i-20260000", + "name": "worker-node-000", + "region": "cn-hangzhou", + "zone": "cn-hangzhou-a", + "status": "active", + "cpu_percent": 12.5, + "memory_mb": 1024, + "disk_mb": 20480, + "ip_address": "192.0.2.10", + "created_at": "2026-07-01T00:15:00Z", + "updated_at": "2026-08-01T00:45:00Z", + "tags": [ + "pool:batch", + "tier:highmem" + ], + "labels": { + "team": "data-platform", + "cost-center": "cc-1000" + }, + "description": "Batch worker node 000 scheduled by the capacity planner; runs nightly extraction jobs for shard 0.", + "last_error": "heartbeat timeout after 3 retries", + "metadata": {}, + "health_checks": [] + }, + { + "id": "i-20260001", + "name": "worker-node-001", + "region": "cn-shanghai", + "zone": "cn-shanghai-b", + "status": "active", + "cpu_percent": 19.5, + "memory_mb": 1280, + "disk_mb": 20992, + "ip_address": "192.0.2.11", + "created_at": "2026-07-02T01:15:00Z", + "updated_at": "2026-08-02T01:45:00Z", + "tags": [ + "pool:batch", + "tier:standard" + ], + "labels": { + "team": "data-platform", + "cost-center": "cc-1001" + }, + "description": "Batch worker node 001 scheduled by the capacity planner; runs nightly extraction jobs for shard 1.", + "last_error": null, + "metadata": {}, + "health_checks": [] + }, + { + "id": "i-20260002", + "name": "worker-node-002", + "region": "us-west-1", + "zone": "us-west-1-c", + "status": "active", + "cpu_percent": 26.5, + "memory_mb": 1536, + "disk_mb": 21504, + "ip_address": "192.0.2.12", + "created_at": "2026-07-03T02:15:00Z", + "updated_at": "2026-08-03T02:45:00Z", + "tags": [ + "pool:batch", + "tier:standard" + ], + "labels": { + "team": "data-platform", + "cost-center": "cc-1002" + }, + "description": "Batch worker node 002 scheduled by the capacity planner; runs nightly extraction jobs for shard 2.", + "last_error": null, + "metadata": {}, + "health_checks": [] + }, + { + "id": "i-20260003", + "name": "worker-node-003", + "region": "eu-central-1", + "zone": "eu-central-1-a", + "status": "pending", + "cpu_percent": 33.5, + "memory_mb": 1792, + "disk_mb": 22016, + "ip_address": "192.0.2.13", + "created_at": "2026-07-04T03:15:00Z", + "updated_at": "2026-08-04T03:45:00Z", + "tags": [ + "pool:batch", + "tier:highmem" + ], + "labels": { + "team": "data-platform", + "cost-center": "cc-1003" + }, + "description": "Batch worker node 003 scheduled by the capacity planner; runs nightly extraction jobs for shard 3.", + "last_error": null, + "metadata": {}, + "health_checks": [] + }, + { + "id": "i-20260004", + "name": "worker-node-004", + "region": "cn-hangzhou", + "zone": "cn-hangzhou-b", + "status": "stopped", + "cpu_percent": 40.5, + "memory_mb": 2048, + "disk_mb": 22528, + "ip_address": "192.0.2.14", + "created_at": "2026-07-05T04:15:00Z", + "updated_at": "2026-08-05T04:45:00Z", + "tags": [ + "pool:batch", + "tier:standard" + ], + "labels": { + "team": "data-platform", + "cost-center": "cc-1004" + }, + "description": "Batch worker node 004 scheduled by the capacity planner; runs nightly extraction jobs for shard 4.", + "last_error": null, + "metadata": {}, + "health_checks": [] + }, + { + "id": "i-20260005", + "name": "worker-node-005", + "region": "cn-shanghai", + "zone": "cn-shanghai-c", + "status": "active", + "cpu_percent": 47.5, + "memory_mb": 2304, + "disk_mb": 23040, + "ip_address": "192.0.2.15", + "created_at": "2026-07-06T05:15:00Z", + "updated_at": "2026-08-06T05:45:00Z", + "tags": [ + "pool:batch", + "tier:standard" + ], + "labels": { + "team": "data-platform", + "cost-center": "cc-1005" + }, + "description": "Batch worker node 005 scheduled by the capacity planner; runs nightly extraction jobs for shard 5.", + "last_error": "heartbeat timeout after 3 retries", + "metadata": {}, + "health_checks": [] + }, + { + "id": "i-20260006", + "name": "worker-node-006", + "region": "us-west-1", + "zone": "us-west-1-a", + "status": "active", + "cpu_percent": 54.5, + "memory_mb": 2560, + "disk_mb": 23552, + "ip_address": "192.0.2.16", + "created_at": "2026-07-07T06:15:00Z", + "updated_at": "2026-08-07T06:45:00Z", + "tags": [ + "pool:batch", + "tier:highmem" + ], + "labels": { + "team": "data-platform", + "cost-center": "cc-1006" + }, + "description": "Batch worker node 006 scheduled by the capacity planner; runs nightly extraction jobs for shard 6.", + "last_error": null, + "metadata": {}, + "health_checks": [] + }, + { + "id": "i-20260007", + "name": "worker-node-007", + "region": "eu-central-1", + "zone": "eu-central-1-b", + "status": "active", + "cpu_percent": 61.5, + "memory_mb": 2816, + "disk_mb": 24064, + "ip_address": "192.0.2.17", + "created_at": "2026-07-08T07:15:00Z", + "updated_at": "2026-08-08T07:45:00Z", + "tags": [ + "pool:batch", + "tier:standard" + ], + "labels": { + "team": "data-platform", + "cost-center": "cc-1000" + }, + "description": "Batch worker node 007 scheduled by the capacity planner; runs nightly extraction jobs for shard 7.", + "last_error": null, + "metadata": {}, + "health_checks": [] + }, + { + "id": "i-20260008", + "name": "worker-node-008", + "region": "cn-hangzhou", + "zone": "cn-hangzhou-c", + "status": "pending", + "cpu_percent": 68.5, + "memory_mb": 3072, + "disk_mb": 24576, + "ip_address": "192.0.2.18", + "created_at": "2026-07-09T08:15:00Z", + "updated_at": "2026-08-09T08:45:00Z", + "tags": [ + "pool:batch", + "tier:standard" + ], + "labels": { + "team": "data-platform", + "cost-center": "cc-1001" + }, + "description": "Batch worker node 008 scheduled by the capacity planner; runs nightly extraction jobs for shard 8.", + "last_error": null, + "metadata": {}, + "health_checks": [] + }, + { + "id": "i-20260009", + "name": "worker-node-009", + "region": "cn-shanghai", + "zone": "cn-shanghai-a", + "status": "stopped", + "cpu_percent": 75.5, + "memory_mb": 3328, + "disk_mb": 25088, + "ip_address": "192.0.2.19", + "created_at": "2026-07-10T09:15:00Z", + "updated_at": "2026-08-10T09:45:00Z", + "tags": [ + "pool:batch", + "tier:highmem" + ], + "labels": { + "team": "data-platform", + "cost-center": "cc-1002" + }, + "description": "Batch worker node 009 scheduled by the capacity planner; runs nightly extraction jobs for shard 9.", + "last_error": null, + "metadata": {}, + "health_checks": [] + }, + { + "id": "i-20260010", + "name": "worker-node-010", + "region": "us-west-1", + "zone": "us-west-1-b", + "status": "active", + "cpu_percent": 82.5, + "memory_mb": 3584, + "disk_mb": 25600, + "ip_address": "192.0.2.20", + "created_at": "2026-07-11T10:15:00Z", + "updated_at": "2026-08-11T10:45:00Z", + "tags": [ + "pool:batch", + "tier:standard" + ], + "labels": { + "team": "data-platform", + "cost-center": "cc-1003" + }, + "description": "Batch worker node 010 scheduled by the capacity planner; runs nightly extraction jobs for shard 10.", + "last_error": "heartbeat timeout after 3 retries", + "metadata": {}, + "health_checks": [] + }, + { + "id": "i-20260011", + "name": "worker-node-011", + "region": "eu-central-1", + "zone": "eu-central-1-c", + "status": "active", + "cpu_percent": 89.5, + "memory_mb": 3840, + "disk_mb": 26112, + "ip_address": "192.0.2.21", + "created_at": "2026-07-12T11:15:00Z", + "updated_at": "2026-08-12T11:45:00Z", + "tags": [ + "pool:batch", + "tier:standard" + ], + "labels": { + "team": "data-platform", + "cost-center": "cc-1004" + }, + "description": "Batch worker node 011 scheduled by the capacity planner; runs nightly extraction jobs for shard 11.", + "last_error": null, + "metadata": {}, + "health_checks": [] + }, + { + "id": "i-20260012", + "name": "worker-node-012", + "region": "cn-hangzhou", + "zone": "cn-hangzhou-a", + "status": "active", + "cpu_percent": 16.5, + "memory_mb": 4096, + "disk_mb": 26624, + "ip_address": "192.0.2.22", + "created_at": "2026-07-13T12:15:00Z", + "updated_at": "2026-08-13T12:45:00Z", + "tags": [ + "pool:batch", + "tier:highmem" + ], + "labels": { + "team": "data-platform", + "cost-center": "cc-1005" + }, + "description": "Batch worker node 012 scheduled by the capacity planner; runs nightly extraction jobs for shard 12.", + "last_error": null, + "metadata": {}, + "health_checks": [] + }, + { + "id": "i-20260013", + "name": "worker-node-013", + "region": "cn-shanghai", + "zone": "cn-shanghai-b", + "status": "pending", + "cpu_percent": 23.5, + "memory_mb": 4352, + "disk_mb": 27136, + "ip_address": "192.0.2.23", + "created_at": "2026-07-14T13:15:00Z", + "updated_at": "2026-08-14T13:45:00Z", + "tags": [ + "pool:batch", + "tier:standard" + ], + "labels": { + "team": "data-platform", + "cost-center": "cc-1006" + }, + "description": "Batch worker node 013 scheduled by the capacity planner; runs nightly extraction jobs for shard 13.", + "last_error": null, + "metadata": {}, + "health_checks": [] + }, + { + "id": "i-20260014", + "name": "worker-node-014", + "region": "us-west-1", + "zone": "us-west-1-c", + "status": "stopped", + "cpu_percent": 30.5, + "memory_mb": 4608, + "disk_mb": 27648, + "ip_address": "192.0.2.24", + "created_at": "2026-07-15T14:15:00Z", + "updated_at": "2026-08-01T14:45:00Z", + "tags": [ + "pool:batch", + "tier:standard" + ], + "labels": { + "team": "data-platform", + "cost-center": "cc-1000" + }, + "description": "Batch worker node 014 scheduled by the capacity planner; runs nightly extraction jobs for shard 14.", + "last_error": null, + "metadata": {}, + "health_checks": [] + }, + { + "id": "i-20260015", + "name": "worker-node-015", + "region": "eu-central-1", + "zone": "eu-central-1-a", + "status": "active", + "cpu_percent": 37.5, + "memory_mb": 4864, + "disk_mb": 28160, + "ip_address": "192.0.2.25", + "created_at": "2026-07-16T15:15:00Z", + "updated_at": "2026-08-02T15:45:00Z", + "tags": [ + "pool:batch", + "tier:highmem" + ], + "labels": { + "team": "data-platform", + "cost-center": "cc-1001" + }, + "description": "Batch worker node 015 scheduled by the capacity planner; runs nightly extraction jobs for shard 15.", + "last_error": "heartbeat timeout after 3 retries", + "metadata": {}, + "health_checks": [] + }, + { + "id": "i-20260016", + "name": "worker-node-016", + "region": "cn-hangzhou", + "zone": "cn-hangzhou-b", + "status": "active", + "cpu_percent": 44.5, + "memory_mb": 5120, + "disk_mb": 28672, + "ip_address": "192.0.2.26", + "created_at": "2026-07-17T16:15:00Z", + "updated_at": "2026-08-03T16:45:00Z", + "tags": [ + "pool:batch", + "tier:standard" + ], + "labels": { + "team": "data-platform", + "cost-center": "cc-1002" + }, + "description": "Batch worker node 016 scheduled by the capacity planner; runs nightly extraction jobs for shard 0.", + "last_error": null, + "metadata": {}, + "health_checks": [] + }, + { + "id": "i-20260017", + "name": "worker-node-017", + "region": "cn-shanghai", + "zone": "cn-shanghai-c", + "status": "active", + "cpu_percent": 51.5, + "memory_mb": 5376, + "disk_mb": 29184, + "ip_address": "192.0.2.27", + "created_at": "2026-07-18T17:15:00Z", + "updated_at": "2026-08-04T17:45:00Z", + "tags": [ + "pool:batch", + "tier:standard" + ], + "labels": { + "team": "data-platform", + "cost-center": "cc-1003" + }, + "description": "Batch worker node 017 scheduled by the capacity planner; runs nightly extraction jobs for shard 1.", + "last_error": null, + "metadata": {}, + "health_checks": [] + }, + { + "id": "i-20260018", + "name": "worker-node-018", + "region": "us-west-1", + "zone": "us-west-1-a", + "status": "pending", + "cpu_percent": 58.5, + "memory_mb": 5632, + "disk_mb": 29696, + "ip_address": "192.0.2.28", + "created_at": "2026-07-19T18:15:00Z", + "updated_at": "2026-08-05T18:45:00Z", + "tags": [ + "pool:batch", + "tier:highmem" + ], + "labels": { + "team": "data-platform", + "cost-center": "cc-1004" + }, + "description": "Batch worker node 018 scheduled by the capacity planner; runs nightly extraction jobs for shard 2.", + "last_error": null, + "metadata": {}, + "health_checks": [] + }, + { + "id": "i-20260019", + "name": "worker-node-019", + "region": "eu-central-1", + "zone": "eu-central-1-b", + "status": "stopped", + "cpu_percent": 65.5, + "memory_mb": 5888, + "disk_mb": 30208, + "ip_address": "192.0.2.29", + "created_at": "2026-07-20T19:15:00Z", + "updated_at": "2026-08-06T19:45:00Z", + "tags": [ + "pool:batch", + "tier:standard" + ], + "labels": { + "team": "data-platform", + "cost-center": "cc-1005" + }, + "description": "Batch worker node 019 scheduled by the capacity planner; runs nightly extraction jobs for shard 3.", + "last_error": null, + "metadata": {}, + "health_checks": [] + }, + { + "id": "i-20260020", + "name": "worker-node-020", + "region": "cn-hangzhou", + "zone": "cn-hangzhou-c", + "status": "active", + "cpu_percent": 72.5, + "memory_mb": 6144, + "disk_mb": 30720, + "ip_address": "192.0.2.30", + "created_at": "2026-07-21T20:15:00Z", + "updated_at": "2026-08-07T20:45:00Z", + "tags": [ + "pool:batch", + "tier:standard" + ], + "labels": { + "team": "data-platform", + "cost-center": "cc-1006" + }, + "description": "Batch worker node 020 scheduled by the capacity planner; runs nightly extraction jobs for shard 4.", + "last_error": "heartbeat timeout after 3 retries", + "metadata": {}, + "health_checks": [] + }, + { + "id": "i-20260021", + "name": "worker-node-021", + "region": "cn-shanghai", + "zone": "cn-shanghai-a", + "status": "active", + "cpu_percent": 79.5, + "memory_mb": 6400, + "disk_mb": 31232, + "ip_address": "192.0.2.31", + "created_at": "2026-07-22T21:15:00Z", + "updated_at": "2026-08-08T21:45:00Z", + "tags": [ + "pool:batch", + "tier:highmem" + ], + "labels": { + "team": "data-platform", + "cost-center": "cc-1000" + }, + "description": "Batch worker node 021 scheduled by the capacity planner; runs nightly extraction jobs for shard 5.", + "last_error": null, + "metadata": {}, + "health_checks": [] + }, + { + "id": "i-20260022", + "name": "worker-node-022", + "region": "us-west-1", + "zone": "us-west-1-b", + "status": "active", + "cpu_percent": 86.5, + "memory_mb": 6656, + "disk_mb": 31744, + "ip_address": "192.0.2.32", + "created_at": "2026-07-23T22:15:00Z", + "updated_at": "2026-08-09T22:45:00Z", + "tags": [ + "pool:batch", + "tier:standard" + ], + "labels": { + "team": "data-platform", + "cost-center": "cc-1001" + }, + "description": "Batch worker node 022 scheduled by the capacity planner; runs nightly extraction jobs for shard 6.", + "last_error": null, + "metadata": {}, + "health_checks": [] + }, + { + "id": "i-20260023", + "name": "worker-node-023", + "region": "eu-central-1", + "zone": "eu-central-1-c", + "status": "pending", + "cpu_percent": 13.5, + "memory_mb": 6912, + "disk_mb": 32256, + "ip_address": "192.0.2.33", + "created_at": "2026-07-24T23:15:00Z", + "updated_at": "2026-08-10T23:45:00Z", + "tags": [ + "pool:batch", + "tier:standard" + ], + "labels": { + "team": "data-platform", + "cost-center": "cc-1002" + }, + "description": "Batch worker node 023 scheduled by the capacity planner; runs nightly extraction jobs for shard 7.", + "last_error": null, + "metadata": {}, + "health_checks": [] + }, + { + "id": "i-20260024", + "name": "worker-node-024", + "region": "cn-hangzhou", + "zone": "cn-hangzhou-a", + "status": "stopped", + "cpu_percent": 20.5, + "memory_mb": 7168, + "disk_mb": 32768, + "ip_address": "192.0.2.34", + "created_at": "2026-07-25T00:15:00Z", + "updated_at": "2026-08-11T00:45:00Z", + "tags": [ + "pool:batch", + "tier:highmem" + ], + "labels": { + "team": "data-platform", + "cost-center": "cc-1003" + }, + "description": "Batch worker node 024 scheduled by the capacity planner; runs nightly extraction jobs for shard 8.", + "last_error": null, + "metadata": {}, + "health_checks": [] + }, + { + "id": "i-20260025", + "name": "worker-node-025", + "region": "cn-shanghai", + "zone": "cn-shanghai-b", + "status": "active", + "cpu_percent": 27.5, + "memory_mb": 7424, + "disk_mb": 33280, + "ip_address": "192.0.2.35", + "created_at": "2026-07-26T01:15:00Z", + "updated_at": "2026-08-12T01:45:00Z", + "tags": [ + "pool:batch", + "tier:standard" + ], + "labels": { + "team": "data-platform", + "cost-center": "cc-1004" + }, + "description": "Batch worker node 025 scheduled by the capacity planner; runs nightly extraction jobs for shard 9.", + "last_error": "heartbeat timeout after 3 retries", + "metadata": {}, + "health_checks": [] + }, + { + "id": "i-20260026", + "name": "worker-node-026", + "region": "us-west-1", + "zone": "us-west-1-c", + "status": "active", + "cpu_percent": 34.5, + "memory_mb": 7680, + "disk_mb": 33792, + "ip_address": "192.0.2.36", + "created_at": "2026-07-27T02:15:00Z", + "updated_at": "2026-08-13T02:45:00Z", + "tags": [ + "pool:batch", + "tier:standard" + ], + "labels": { + "team": "data-platform", + "cost-center": "cc-1005" + }, + "description": "Batch worker node 026 scheduled by the capacity planner; runs nightly extraction jobs for shard 10.", + "last_error": null, + "metadata": {}, + "health_checks": [] + }, + { + "id": "i-20260027", + "name": "worker-node-027", + "region": "eu-central-1", + "zone": "eu-central-1-a", + "status": "active", + "cpu_percent": 41.5, + "memory_mb": 7936, + "disk_mb": 34304, + "ip_address": "192.0.2.37", + "created_at": "2026-07-28T03:15:00Z", + "updated_at": "2026-08-14T03:45:00Z", + "tags": [ + "pool:batch", + "tier:highmem" + ], + "labels": { + "team": "data-platform", + "cost-center": "cc-1006" + }, + "description": "Batch worker node 027 scheduled by the capacity planner; runs nightly extraction jobs for shard 11.", + "last_error": null, + "metadata": {}, + "health_checks": [] + }, + { + "id": "i-20260028", + "name": "worker-node-028", + "region": "cn-hangzhou", + "zone": "cn-hangzhou-b", + "status": "pending", + "cpu_percent": 48.5, + "memory_mb": 8192, + "disk_mb": 34816, + "ip_address": "192.0.2.38", + "created_at": "2026-07-01T04:15:00Z", + "updated_at": "2026-08-01T04:45:00Z", + "tags": [ + "pool:batch", + "tier:standard" + ], + "labels": { + "team": "data-platform", + "cost-center": "cc-1000" + }, + "description": "Batch worker node 028 scheduled by the capacity planner; runs nightly extraction jobs for shard 12.", + "last_error": null, + "metadata": {}, + "health_checks": [] + }, + { + "id": "i-20260029", + "name": "worker-node-029", + "region": "cn-shanghai", + "zone": "cn-shanghai-c", + "status": "stopped", + "cpu_percent": 55.5, + "memory_mb": 8448, + "disk_mb": 35328, + "ip_address": "192.0.2.39", + "created_at": "2026-07-02T05:15:00Z", + "updated_at": "2026-08-02T05:45:00Z", + "tags": [ + "pool:batch", + "tier:standard" + ], + "labels": { + "team": "data-platform", + "cost-center": "cc-1001" + }, + "description": "Batch worker node 029 scheduled by the capacity planner; runs nightly extraction jobs for shard 13.", + "last_error": null, + "metadata": {}, + "health_checks": [] + }, + { + "id": "i-20260030", + "name": "worker-node-030", + "region": "us-west-1", + "zone": "us-west-1-a", + "status": "active", + "cpu_percent": 62.5, + "memory_mb": 8704, + "disk_mb": 35840, + "ip_address": "192.0.2.40", + "created_at": "2026-07-03T06:15:00Z", + "updated_at": "2026-08-03T06:45:00Z", + "tags": [ + "pool:batch", + "tier:highmem" + ], + "labels": { + "team": "data-platform", + "cost-center": "cc-1002" + }, + "description": "Batch worker node 030 scheduled by the capacity planner; runs nightly extraction jobs for shard 14.", + "last_error": "heartbeat timeout after 3 retries", + "metadata": {}, + "health_checks": [] + }, + { + "id": "i-20260031", + "name": "worker-node-031", + "region": "eu-central-1", + "zone": "eu-central-1-b", + "status": "active", + "cpu_percent": 69.5, + "memory_mb": 8960, + "disk_mb": 36352, + "ip_address": "192.0.2.41", + "created_at": "2026-07-04T07:15:00Z", + "updated_at": "2026-08-04T07:45:00Z", + "tags": [ + "pool:batch", + "tier:standard" + ], + "labels": { + "team": "data-platform", + "cost-center": "cc-1003" + }, + "description": "Batch worker node 031 scheduled by the capacity planner; runs nightly extraction jobs for shard 15.", + "last_error": null, + "metadata": {}, + "health_checks": [] + }, + { + "id": "i-20260032", + "name": "worker-node-032", + "region": "cn-hangzhou", + "zone": "cn-hangzhou-c", + "status": "active", + "cpu_percent": 76.5, + "memory_mb": 9216, + "disk_mb": 36864, + "ip_address": "192.0.2.42", + "created_at": "2026-07-05T08:15:00Z", + "updated_at": "2026-08-05T08:45:00Z", + "tags": [ + "pool:batch", + "tier:standard" + ], + "labels": { + "team": "data-platform", + "cost-center": "cc-1004" + }, + "description": "Batch worker node 032 scheduled by the capacity planner; runs nightly extraction jobs for shard 0.", + "last_error": null, + "metadata": {}, + "health_checks": [] + }, + { + "id": "i-20260033", + "name": "worker-node-033", + "region": "cn-shanghai", + "zone": "cn-shanghai-a", + "status": "pending", + "cpu_percent": 83.5, + "memory_mb": 9472, + "disk_mb": 37376, + "ip_address": "192.0.2.43", + "created_at": "2026-07-06T09:15:00Z", + "updated_at": "2026-08-06T09:45:00Z", + "tags": [ + "pool:batch", + "tier:highmem" + ], + "labels": { + "team": "data-platform", + "cost-center": "cc-1005" + }, + "description": "Batch worker node 033 scheduled by the capacity planner; runs nightly extraction jobs for shard 1.", + "last_error": null, + "metadata": {}, + "health_checks": [] + }, + { + "id": "i-20260034", + "name": "worker-node-034", + "region": "us-west-1", + "zone": "us-west-1-b", + "status": "stopped", + "cpu_percent": 90.5, + "memory_mb": 9728, + "disk_mb": 37888, + "ip_address": "192.0.2.44", + "created_at": "2026-07-07T10:15:00Z", + "updated_at": "2026-08-07T10:45:00Z", + "tags": [ + "pool:batch", + "tier:standard" + ], + "labels": { + "team": "data-platform", + "cost-center": "cc-1006" + }, + "description": "Batch worker node 034 scheduled by the capacity planner; runs nightly extraction jobs for shard 2.", + "last_error": null, + "metadata": {}, + "health_checks": [] + }, + { + "id": "i-20260035", + "name": "worker-node-035", + "region": "eu-central-1", + "zone": "eu-central-1-c", + "status": "active", + "cpu_percent": 17.5, + "memory_mb": 9984, + "disk_mb": 38400, + "ip_address": "192.0.2.45", + "created_at": "2026-07-08T11:15:00Z", + "updated_at": "2026-08-08T11:45:00Z", + "tags": [ + "pool:batch", + "tier:standard" + ], + "labels": { + "team": "data-platform", + "cost-center": "cc-1000" + }, + "description": "Batch worker node 035 scheduled by the capacity planner; runs nightly extraction jobs for shard 3.", + "last_error": "heartbeat timeout after 3 retries", + "metadata": {}, + "health_checks": [] + }, + { + "id": "i-20260036", + "name": "worker-node-036", + "region": "cn-hangzhou", + "zone": "cn-hangzhou-a", + "status": "active", + "cpu_percent": 24.5, + "memory_mb": 10240, + "disk_mb": 38912, + "ip_address": "192.0.2.46", + "created_at": "2026-07-09T12:15:00Z", + "updated_at": "2026-08-09T12:45:00Z", + "tags": [ + "pool:batch", + "tier:highmem" + ], + "labels": { + "team": "data-platform", + "cost-center": "cc-1001" + }, + "description": "Batch worker node 036 scheduled by the capacity planner; runs nightly extraction jobs for shard 4.", + "last_error": null, + "metadata": {}, + "health_checks": [] + }, + { + "id": "i-20260037", + "name": "worker-node-037", + "region": "cn-shanghai", + "zone": "cn-shanghai-b", + "status": "active", + "cpu_percent": 31.5, + "memory_mb": 10496, + "disk_mb": 39424, + "ip_address": "192.0.2.47", + "created_at": "2026-07-10T13:15:00Z", + "updated_at": "2026-08-10T13:45:00Z", + "tags": [ + "pool:batch", + "tier:standard" + ], + "labels": { + "team": "data-platform", + "cost-center": "cc-1002" + }, + "description": "Batch worker node 037 scheduled by the capacity planner; runs nightly extraction jobs for shard 5.", + "last_error": null, + "metadata": {}, + "health_checks": [] + }, + { + "id": "i-20260038", + "name": "worker-node-038", + "region": "us-west-1", + "zone": "us-west-1-c", + "status": "pending", + "cpu_percent": 38.5, + "memory_mb": 10752, + "disk_mb": 39936, + "ip_address": "192.0.2.48", + "created_at": "2026-07-11T14:15:00Z", + "updated_at": "2026-08-11T14:45:00Z", + "tags": [ + "pool:batch", + "tier:standard" + ], + "labels": { + "team": "data-platform", + "cost-center": "cc-1003" + }, + "description": "Batch worker node 038 scheduled by the capacity planner; runs nightly extraction jobs for shard 6.", + "last_error": null, + "metadata": {}, + "health_checks": [] + }, + { + "id": "i-20260039", + "name": "worker-node-039", + "region": "eu-central-1", + "zone": "eu-central-1-a", + "status": "stopped", + "cpu_percent": 45.5, + "memory_mb": 11008, + "disk_mb": 40448, + "ip_address": "192.0.2.49", + "created_at": "2026-07-12T15:15:00Z", + "updated_at": "2026-08-12T15:45:00Z", + "tags": [ + "pool:batch", + "tier:highmem" + ], + "labels": { + "team": "data-platform", + "cost-center": "cc-1004" + }, + "description": "Batch worker node 039 scheduled by the capacity planner; runs nightly extraction jobs for shard 7.", + "last_error": null, + "metadata": {}, + "health_checks": [] + }, + { + "id": "i-20260040", + "name": "worker-node-040", + "region": "cn-hangzhou", + "zone": "cn-hangzhou-b", + "status": "active", + "cpu_percent": 52.5, + "memory_mb": 11264, + "disk_mb": 40960, + "ip_address": "192.0.2.50", + "created_at": "2026-07-13T16:15:00Z", + "updated_at": "2026-08-13T16:45:00Z", + "tags": [ + "pool:batch", + "tier:standard" + ], + "labels": { + "team": "data-platform", + "cost-center": "cc-1005" + }, + "description": "Batch worker node 040 scheduled by the capacity planner; runs nightly extraction jobs for shard 8.", + "last_error": "heartbeat timeout after 3 retries", + "metadata": {}, + "health_checks": [] + }, + { + "id": "i-20260041", + "name": "worker-node-041", + "region": "cn-shanghai", + "zone": "cn-shanghai-c", + "status": "active", + "cpu_percent": 59.5, + "memory_mb": 11520, + "disk_mb": 41472, + "ip_address": "192.0.2.51", + "created_at": "2026-07-14T17:15:00Z", + "updated_at": "2026-08-14T17:45:00Z", + "tags": [ + "pool:batch", + "tier:standard" + ], + "labels": { + "team": "data-platform", + "cost-center": "cc-1006" + }, + "description": "Batch worker node 041 scheduled by the capacity planner; runs nightly extraction jobs for shard 9.", + "last_error": null, + "metadata": {}, + "health_checks": [] + }, + { + "id": "i-20260042", + "name": "worker-node-042", + "region": "us-west-1", + "zone": "us-west-1-a", + "status": "active", + "cpu_percent": 66.5, + "memory_mb": 11776, + "disk_mb": 41984, + "ip_address": "192.0.2.52", + "created_at": "2026-07-15T18:15:00Z", + "updated_at": "2026-08-01T18:45:00Z", + "tags": [ + "pool:batch", + "tier:highmem" + ], + "labels": { + "team": "data-platform", + "cost-center": "cc-1000" + }, + "description": "Batch worker node 042 scheduled by the capacity planner; runs nightly extraction jobs for shard 10.", + "last_error": null, + "metadata": {}, + "health_checks": [] + }, + { + "id": "i-20260043", + "name": "worker-node-043", + "region": "eu-central-1", + "zone": "eu-central-1-b", + "status": "pending", + "cpu_percent": 73.5, + "memory_mb": 12032, + "disk_mb": 42496, + "ip_address": "192.0.2.53", + "created_at": "2026-07-16T19:15:00Z", + "updated_at": "2026-08-02T19:45:00Z", + "tags": [ + "pool:batch", + "tier:standard" + ], + "labels": { + "team": "data-platform", + "cost-center": "cc-1001" + }, + "description": "Batch worker node 043 scheduled by the capacity planner; runs nightly extraction jobs for shard 11.", + "last_error": null, + "metadata": {}, + "health_checks": [] + }, + { + "id": "i-20260044", + "name": "worker-node-044", + "region": "cn-hangzhou", + "zone": "cn-hangzhou-c", + "status": "stopped", + "cpu_percent": 80.5, + "memory_mb": 12288, + "disk_mb": 43008, + "ip_address": "192.0.2.54", + "created_at": "2026-07-17T20:15:00Z", + "updated_at": "2026-08-03T20:45:00Z", + "tags": [ + "pool:batch", + "tier:standard" + ], + "labels": { + "team": "data-platform", + "cost-center": "cc-1002" + }, + "description": "Batch worker node 044 scheduled by the capacity planner; runs nightly extraction jobs for shard 12.", + "last_error": null, + "metadata": {}, + "health_checks": [] + }, + { + "id": "i-20260045", + "name": "worker-node-045", + "region": "cn-shanghai", + "zone": "cn-shanghai-a", + "status": "active", + "cpu_percent": 87.5, + "memory_mb": 12544, + "disk_mb": 43520, + "ip_address": "192.0.2.55", + "created_at": "2026-07-18T21:15:00Z", + "updated_at": "2026-08-04T21:45:00Z", + "tags": [ + "pool:batch", + "tier:highmem" + ], + "labels": { + "team": "data-platform", + "cost-center": "cc-1003" + }, + "description": "Batch worker node 045 scheduled by the capacity planner; runs nightly extraction jobs for shard 13.", + "last_error": "heartbeat timeout after 3 retries", + "metadata": {}, + "health_checks": [] + }, + { + "id": "i-20260046", + "name": "worker-node-046", + "region": "us-west-1", + "zone": "us-west-1-b", + "status": "active", + "cpu_percent": 14.5, + "memory_mb": 12800, + "disk_mb": 44032, + "ip_address": "192.0.2.56", + "created_at": "2026-07-19T22:15:00Z", + "updated_at": "2026-08-05T22:45:00Z", + "tags": [ + "pool:batch", + "tier:standard" + ], + "labels": { + "team": "data-platform", + "cost-center": "cc-1004" + }, + "description": "Batch worker node 046 scheduled by the capacity planner; runs nightly extraction jobs for shard 14.", + "last_error": null, + "metadata": {}, + "health_checks": [] + }, + { + "id": "i-20260047", + "name": "worker-node-047", + "region": "eu-central-1", + "zone": "eu-central-1-c", + "status": "active", + "cpu_percent": 21.5, + "memory_mb": 13056, + "disk_mb": 44544, + "ip_address": "192.0.2.57", + "created_at": "2026-07-20T23:15:00Z", + "updated_at": "2026-08-06T23:45:00Z", + "tags": [ + "pool:batch", + "tier:standard" + ], + "labels": { + "team": "data-platform", + "cost-center": "cc-1005" + }, + "description": "Batch worker node 047 scheduled by the capacity planner; runs nightly extraction jobs for shard 15.", + "last_error": null, + "metadata": {}, + "health_checks": [] + } + ] +} diff --git a/src/tokenless/benchmark/standard-payload/response_code.json b/src/tokenless/benchmark/standard-payload/response_code.json new file mode 100644 index 0000000000..959701d444 --- /dev/null +++ b/src/tokenless/benchmark/standard-payload/response_code.json @@ -0,0 +1,110 @@ +{ + "tool": "code_search", + "query": "retry backoff", + "total_matches": 128, + "returned": 10, + "results": [ + { + "path": "src/net/retry.rs", + "language": "rust", + "start_line": 12, + "end_line": 29, + "score": 0.98, + "snippet": "pub async fn with_retry(mut op: F, policy: &RetryPolicy) -> Result\nwhere\n F: FnMut() -> futures::future::BoxFuture<'static, Result>,\n E: IsTransient,\n{\n let mut attempt = 0usize;\n loop {\n match op().await {\n Ok(value) => return Ok(value),\n Err(err) if err.is_transient() && attempt < policy.max_attempts => {\n attempt += 1;\n let delay = policy.delay_for(attempt);\n tokio::time::sleep(delay).await;\n }\n Err(err) => return Err(err),\n }\n }\n}", + "error": null, + "warnings": [] + }, + { + "path": "pipeline/retry.py", + "language": "python", + "start_line": 34, + "end_line": 44, + "score": 0.91, + "snippet": "def with_backoff(func, *, attempts=5, base=0.5, factor=2.0, retry_on=(TimeoutError,)):\n delay = base\n for attempt in range(1, attempts + 1):\n try:\n return func()\n except retry_on as exc:\n if attempt == attempts:\n raise\n logging.warning(\"attempt %d failed: %s; sleeping %.2fs\", attempt, exc, delay)\n time.sleep(delay)\n delay *= factor", + "error": null, + "warnings": [] + }, + { + "path": "internal/httpclient/retry.go", + "language": "go", + "start_line": 21, + "end_line": 34, + "score": 0.84, + "snippet": "func DoWithRetry(ctx context.Context, client *http.Client, req *http.Request, max int) (*http.Response, error) {\n var resp *http.Response\n var err error\n for attempt := 0; attempt <= max; attempt++ {\n resp, err = client.Do(req.Clone(ctx))\n if err == nil && resp.StatusCode < 500 {\n return resp, nil\n }\n if attempt < max {\n time.Sleep(backoff(attempt))\n }\n }\n return resp, err\n}", + "error": null, + "warnings": [] + }, + { + "path": "src/client/fetchRetry.ts", + "language": "typescript", + "start_line": 8, + "end_line": 21, + "score": 0.77, + "snippet": "export async function fetchRetry(url: string, init: RequestInit, attempts = 4): Promise {\n let lastError: unknown;\n for (let attempt = 0; attempt < attempts; attempt++) {\n try {\n const response = await fetch(url, init);\n if (response.status < 500) return response;\n lastError = new Error(`server error ${response.status}`);\n } catch (error) {\n lastError = error;\n }\n await sleep(2 ** attempt * 250);\n }\n throw lastError;\n}", + "error": null, + "warnings": [] + }, + { + "path": "scripts/wait_for_endpoint.sh", + "language": "bash", + "start_line": 3, + "end_line": 12, + "score": 0.7, + "snippet": "attempt=0\nuntil curl --fail --silent \"$ENDPOINT/health\" > /dev/null; do\n attempt=$((attempt + 1))\n if [ \"$attempt\" -ge 30 ]; then\n echo \"endpoint never became healthy\" >&2\n exit 1\n fi\n sleep 2\ndone\necho \"endpoint healthy after $attempt retries\"", + "error": null, + "warnings": [] + }, + { + "path": "src/net/timeout.rs", + "language": "rust", + "start_line": 40, + "end_line": 48, + "score": 0.63, + "snippet": "pub async fn with_timeout(future: F, limit: Duration) -> Result\nwhere\n F: Future,\n{\n match tokio::time::timeout(limit, future).await {\n Ok(output) => Ok(output),\n Err(_) => Err(Elapsed { limit }),\n }\n}", + "error": null, + "warnings": [] + }, + { + "path": "pipeline/circuit_breaker.py", + "language": "python", + "start_line": 12, + "end_line": 24, + "score": 0.56, + "snippet": "class CircuitBreaker:\n def __init__(self, failure_threshold=5, recovery_timeout=30.0):\n self.failure_threshold = failure_threshold\n self.recovery_timeout = recovery_timeout\n self.failures = 0\n self.opened_at = None\n\n def allow(self) -> bool:\n if self.failures < self.failure_threshold:\n return True\n if self.opened_at is None:\n return False\n return time.monotonic() - self.opened_at >= self.recovery_timeout", + "error": null, + "warnings": [] + }, + { + "path": "internal/jitter/jitter.go", + "language": "go", + "start_line": 9, + "end_line": 16, + "score": 0.49, + "snippet": "func BackoffWithJitter(attempt int, base, cap time.Duration) time.Duration {\n exp := base << attempt\n if exp > cap || exp <= 0 {\n exp = cap\n }\n jitter := time.Duration(rand.Int63n(int64(exp)/2 + 1))\n return exp/2 + jitter\n}", + "error": null, + "warnings": [] + }, + { + "path": "src/client/sleep.ts", + "language": "typescript", + "start_line": 1, + "end_line": 10, + "score": 0.42, + "snippet": "export function sleep(ms: number): Promise {\n return new Promise((resolve) => setTimeout(resolve, ms));\n}\n\nexport const defaultRetryConfig = {\n attempts: 4,\n baseDelayMs: 250,\n maxDelayMs: 8000,\n jitter: true,\n} as const;", + "error": null, + "warnings": [] + }, + { + "path": "deploy/retry-policy.yaml", + "language": "yaml", + "start_line": 1, + "end_line": 12, + "score": 0.35, + "snippet": "retry_policy:\n max_attempts: 5\n initial_backoff: 500ms\n max_backoff: 30s\n backoff_multiplier: 2.0\n retry_on:\n - connection_reset\n - upstream_timeout\n - status_503\n non_retryable:\n - status_400\n - status_401", + "error": null, + "warnings": [] + } + ], + "truncated": false, + "index_version": null +} diff --git a/src/tokenless/benchmark/standard-payload/response_prose.json b/src/tokenless/benchmark/standard-payload/response_prose.json new file mode 100644 index 0000000000..15434b2b1f --- /dev/null +++ b/src/tokenless/benchmark/standard-payload/response_prose.json @@ -0,0 +1,33 @@ +{ + "source": "web_search", + "query": "capacity planning best practices", + "total_results": 3, + "results": [ + { + "title": "Capacity Planning Basics for Agent Platforms", + "url": "https://example.com/articles/capacity-planning-basics", + "published_at": "2026-03-18", + "summary": "A practical introduction to capacity planning for platforms that serve agent workloads, covering workload characterization, headroom policy and percentile-based latency budgets.", + "content": "Capacity planning starts with characterizing the workload. For agent platforms this means measuring not only request rates but also the shape of each session: how many tool calls a typical session makes, how large the tool responses are, and how long sessions stay active. Two platforms with identical requests-per-second can differ by an order of magnitude in token throughput if their session shapes differ.\n\nOnce the workload is characterized, define a headroom policy. A common starting point is to provision for the 95th percentile day plus thirty percent spare capacity, then adjust after observing at least two full weekly cycles. Headroom is cheapest when bought before the traffic arrives; emergency capacity during an incident always costs more in both money and reliability.\n\nFinally, track latency budgets by percentile rather than by average. Average latency hides the long sessions that matter most, because agent sessions are heavy-tailed: a small number of sessions consume most of the tokens. Budgeting against the 90th or 95th percentile keeps the system sized for the sessions users actually notice.", + "highlights": [] + }, + { + "title": "Observability for Batch Pipelines", + "url": "https://example.com/articles/batch-pipeline-observability", + "published_at": "2026-05-02", + "summary": "How to instrument batch pipelines so failures are attributable to a single stage, with guidance on metrics, structured logs and trace propagation across queued work.", + "content": "Batch pipelines fail differently from request-driven services. A web service either answers or times out, but a batch pipeline can silently drop work, duplicate work, or fall behind without any visible error. Observability for batch systems therefore starts with accounting: every unit of work that enters the pipeline must be traceable to exactly one terminal state, either completed, failed or expired.\n\nStructured logs are the backbone of that accounting. Each stage should emit one structured record per unit of work, carrying a stable work identifier, the stage name, and the outcome. Free-form logging makes it impossible to answer the simplest operational question, which is how many units are currently stuck between two stages.\n\nTraces add the time dimension. Propagating a trace identifier through queue metadata lets operators see how long a unit of work waited in each queue, which is usually where batch latency actually goes. The metric to alert on is end-to-end age of the oldest incomplete unit, not the duration of individual stages.", + "highlights": [] + }, + { + "title": "Load Testing Strategies That Predict Production", + "url": "https://example.com/articles/load-testing-strategies", + "published_at": "2026-06-21", + "summary": "Why constant-rate load tests mislead, and how ramp profiles, soak tests and saturation-point measurement produce numbers that actually predict production behavior.", + "content": "A constant-rate load test answers one question: does the system survive this exact rate? Production traffic never looks like that. Real traffic ramps, spikes, and recovers, and most production failures happen on the ramp rather than at steady state. A useful load test therefore includes a ramp profile that exceeds the fastest growth observed in production, so the test exposes queue buildup and cache warm-up behavior before users do.\n\nSoak tests answer a different question: does the system leak? Memory leaks, connection pool exhaustion and file descriptor growth only show up after hours of steady operation. Running the representative workload at seventy percent of the target rate for at least eight hours, while watching resource counters, catches most of these defects.\n\nThe most valuable number a load test produces is the saturation point: the rate at which latency stops scaling linearly and starts climbing sharply. Measure it by increasing the rate in steps and recording the 95th percentile latency at each step. The saturation point, not the failure point, is what capacity plans should be built on.", + "highlights": [] + } + ], + "next_cursor": null, + "suggestions": [] +} diff --git a/src/tokenless/benchmark/standard-payload/run-standard-check.sh b/src/tokenless/benchmark/standard-payload/run-standard-check.sh new file mode 100755 index 0000000000..ba168df7c1 --- /dev/null +++ b/src/tokenless/benchmark/standard-payload/run-standard-check.sh @@ -0,0 +1,69 @@ +#!/usr/bin/env bash +# Copyright 2026 Alibaba Cloud +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# Run the installed tokenless CLI over the standard payloads in this +# directory and print the recorded savings for each case as +# `stats summary --json` output. Compare the numbers against the reference +# table in the user-guide page "Compression rates and applicable scenarios" +# (docs/user-guide//token-saving/tokenless/compression-scenarios.md). +# +# Usage: +# ./run-standard-check.sh # uses `tokenless` from PATH +# TOKENLESS_BIN=/path/to/tokenless ./run-standard-check.sh +# +# Each case runs with an isolated TOKENLESS_DATA_DIR, so your real +# statistics and stash databases are never touched. + +set -euo pipefail +cd "$(dirname "$0")" + +TOKENLESS_BIN="${TOKENLESS_BIN:-tokenless}" +if ! command -v "$TOKENLESS_BIN" >/dev/null 2>&1; then + echo "error: tokenless binary not found on PATH; install tokenless or set TOKENLESS_BIN" >&2 + exit 1 +fi + +echo "binary: $("$TOKENLESS_BIN" --version)" +echo + +workdir="$(mktemp -d)" +trap 'rm -rf "$workdir"' EXIT + +run_case() { + label="$1" + input="$2" + shift 2 + dir="$workdir/$label" + mkdir -p "$dir" + if ! TOKENLESS_DATA_DIR="$dir" TOKENLESS_SLS_ENABLED=0 \ + "$TOKENLESS_BIN" "$@" -f "$input" > "$dir/output.txt" 2> "$dir/stderr.txt"; then + echo "=== case $label: FAILED ===" + cat "$dir/stderr.txt" >&2 + return 1 + fi + echo "=== case $label: $* -f $input ===" + TOKENLESS_DATA_DIR="$dir" "$TOKENLESS_BIN" stats summary --json + echo +} + +run_case schema schema_tools.json compress-schema --batch --session-id stdpay-schema +run_case api response_api_records.json compress-response --session-id stdpay-api +run_case code response_code.json compress-response --session-id stdpay-code +run_case prose response_prose.json compress-response --session-id stdpay-prose +run_case toon response_api_records.json compress-toon --session-id stdpay-toon + +echo "All cases finished. If a case records 0 records, the payload produced no" +echo "estimated token savings on this tokenless version and the original input" +echo "was emitted unchanged." diff --git a/src/tokenless/benchmark/standard-payload/schema_tools.json b/src/tokenless/benchmark/standard-payload/schema_tools.json new file mode 100644 index 0000000000..9aa9799a09 --- /dev/null +++ b/src/tokenless/benchmark/standard-payload/schema_tools.json @@ -0,0 +1,232 @@ +[ + { + "type": "function", + "function": { + "name": "search_codebase", + "description": "Search the entire codebase for symbols, definitions and free-text matches. Use this tool first whenever you need to locate where a function, class or configuration key is defined or referenced. The search index covers all committed files and is refreshed at the start of every session.\n\nResults are ranked by relevance and include the file path, line range and a short snippet for every match. Prefer a narrow `query` over a broad one: queries with more than three words rarely improve recall and make the result set harder to read.\n\n```python\n# Example: find every caller of the retry helper\nsearch_codebase(query=\"with_retry\", file_pattern=\"*.py\")\n```\n\nDo not use this tool for files that were created after the session started; they are not indexed yet. Read such files directly with `read_file` instead.", + "parameters": { + "type": "object", + "properties": { + "query": { + "type": "string", + "description": "The search expression. Supports plain text, symbol names and simple regular expressions. Keep it short and specific; the engine returns at most 50 matches ranked by relevance." + }, + "file_pattern": { + "type": "string", + "description": "Optional glob that restricts the search to matching paths, for example `src/**/*.rs` or `*.test.ts`. When omitted every indexed file is searched." + }, + "max_results": { + "type": "integer", + "description": "Maximum number of matches to return, between 1 and 50. Defaults to 20.", + "minimum": 1, + "maximum": 50 + } + }, + "required": [ + "query" + ], + "examples": [ + { + "query": "parse_config", + "file_pattern": "src/**/*.rs" + }, + { + "query": "TODO(.*timeout)", + "max_results": 10 + } + ] + }, + "title": "Codebase Search Tool" + } + }, + { + "type": "function", + "function": { + "name": "read_file", + "description": "Read the content of a single file from the workspace. The tool returns the file as text together with its size and last modification time. Binary files are rejected with an explicit error instead of being returned.\n\nFor large files prefer a line range over reading the whole file; responses above the context budget are truncated and annotated. When you only need to know whether a symbol exists, use `search_codebase` first and read exactly the matching range afterwards.\n\n```\nread_file(path=\"src/server/router.rs\", start_line=120, end_line=180)\n```", + "parameters": { + "type": "object", + "properties": { + "path": { + "type": "string", + "description": "Workspace-relative path of the file to read. Symbolic links are resolved." + }, + "start_line": { + "type": "integer", + "description": "First line to read, 1-based. Optional; defaults to the first line." + }, + "end_line": { + "type": "integer", + "description": "Last line to read, inclusive. Optional; defaults to the last line." + } + }, + "required": [ + "path" + ] + }, + "title": "File Reader" + } + }, + { + "type": "function", + "function": { + "name": "run_shell_command", + "description": "Run a shell command inside the workspace sandbox and return its combined standard output and standard error. The command runs with a configurable timeout and is killed when the timeout is exceeded.\n\nUse this tool for builds, tests, linters and version-control commands. Commands that require network access must be declared in the session manifest, otherwise they fail with a permission error.\n\n```bash\n# Example: run the unit tests for one crate\ncargo test -p tokenless-stats\n```\n\nNever run destructive commands (force push, recursive delete of shared directories) through this tool without an explicit user confirmation.", + "parameters": { + "type": "object", + "properties": { + "command": { + "type": "string", + "description": "The shell command line to execute. It is passed to `bash -c` unchanged." + }, + "timeout_seconds": { + "type": "integer", + "description": "Kill the command after this many seconds. Defaults to 120, maximum 1800.", + "default": 120 + }, + "working_directory": { + "type": "string", + "description": "Optional workspace-relative directory the command starts in." + } + }, + "required": [ + "command" + ], + "examples": [ + { + "command": "cargo fmt --check", + "timeout_seconds": 60 + } + ] + }, + "title": "Shell Command Runner" + } + }, + { + "type": "function", + "function": { + "name": "list_directory", + "description": "List the entries of a directory in the workspace. Each entry includes its name, type (file or directory), size in bytes and last modification time. Hidden entries are included only when requested.\n\nThe result is sorted alphabetically. Use `recursive` with care: deep trees produce very large responses and are truncated beyond 5000 entries.", + "parameters": { + "type": "object", + "properties": { + "path": { + "type": "string", + "description": "Workspace-relative path of the directory to list." + }, + "recursive": { + "type": "boolean", + "description": "When true, list the whole subtree instead of a single level.", + "default": false + }, + "include_hidden": { + "type": "boolean", + "description": "When true, include entries whose name starts with a dot.", + "default": false + } + }, + "required": [ + "path" + ] + }, + "title": "Directory Lister" + } + }, + { + "type": "function", + "function": { + "name": "create_merge_request", + "description": "Create a merge request from the current branch to a target branch. The tool pushes the branch if it has not been pushed yet, fills in the title and description, and returns the merge request number and URL.\n\nThe description supports Markdown. Keep the title under 80 characters and start it with a conventional-commit type such as `feat:` or `fix:` so the release tooling can classify the change automatically.\n\n```\ncreate_merge_request(\n title=\"fix(stats): record dry-run predictions\",\n description=\"Dry-run records were dropped from the summary.\",\n target_branch=\"main\",\n labels=[\"tokenless\", \"bug\"],\n)\n```", + "parameters": { + "type": "object", + "properties": { + "title": { + "type": "string", + "description": "One-line summary of the change, under 80 characters.", + "maxLength": 80 + }, + "description": { + "type": "string", + "description": "Markdown body explaining motivation, approach and testing." + }, + "target_branch": { + "type": "string", + "description": "Branch the change should merge into. Defaults to `main`.", + "default": "main" + }, + "labels": { + "type": "array", + "description": "Optional labels to attach. Unknown labels are created on demand.", + "items": { + "type": "string" + } + }, + "reviewers": { + "type": "array", + "description": "Optional list of reviewer usernames.", + "items": { + "type": "string" + } + }, + "draft": { + "type": "boolean", + "description": "Create the merge request as a draft that cannot be merged.", + "default": false + } + }, + "required": [ + "title", + "description" + ] + }, + "title": "Merge Request Creator" + } + }, + { + "type": "function", + "function": { + "name": "query_database", + "description": "Run a read-only SQL query against the analytics replica and return the rows as JSON. Write statements are rejected before execution. Queries that return more than 1000 rows are truncated and flagged so downstream consumers can detect the limit.\n\nPrefer explicit column lists over `SELECT *` and always include a `LIMIT` clause; the replica enforces a 30 second statement timeout.\n\n```sql\nSELECT day, active_users, p95_latency_ms\nFROM service_health_daily\nWHERE day >= current_date - interval '7 days'\nORDER BY day DESC;\n```", + "parameters": { + "type": "object", + "properties": { + "sql": { + "type": "string", + "description": "The read-only SQL statement to execute on the analytics replica." + }, + "database": { + "type": "string", + "description": "Logical database name. One of `analytics`, `billing_readonly`, `events`.", + "enum": [ + "analytics", + "billing_readonly", + "events" + ] + }, + "parameters": { + "type": "object", + "description": "Optional named parameters bound into the statement, which avoids quoting issues and injection risk.", + "additionalProperties": { + "type": [ + "string", + "number", + "boolean" + ] + } + } + }, + "required": [ + "sql", + "database" + ], + "examples": [ + { + "sql": "SELECT 1", + "database": "analytics" + } + ] + }, + "title": "Analytics Database Query" + } + } +]