♻️ refactor(test): rebuild agent runtime test flow

This commit is contained in:
csh 2026-06-24 10:50:06 +08:00
parent a34c6444a5
commit 0f59543409
9 changed files with 1158 additions and 5601 deletions

View File

@ -4,7 +4,7 @@
是否可直接用于生成代码:否
是否含可直接照写示例:否
是否含不可照写反例:否
遇到不确定时:先按“按任务跳转”分层;语法问题看 [syntax/index.md](syntax/index.md),函数库查询看 [reference/index.md](reference/index.md),模块 / 集成看 [modules/index.md](modules/index.md),项目执行问题回项目自身文档、`scripts/*` 入口脚本和 CI 配置
遇到不确定时:先按“按任务跳转”分层;语法问题看 [syntax/index.md](syntax/index.md)命名问题看 [naming.md](naming.md)函数库查询看 [reference/index.md](reference/index.md),模块 / 集成看 [modules/index.md](modules/index.md),项目执行问题回项目自身文档、`scripts/*` 入口脚本和 CI 配置
本页只决定第一跳。不要在这里生成代码,不要通读全部 TSL 文档,不要用相似语言补全 TSL 事实。
@ -14,6 +14,7 @@
| ------------------------------------------------- | ------------------------------------------------------------------------ | ------------------------------------------ |
| 写最短可运行骨架、核对语言核心事实 | [syntax/01_quickstart.md](syntax/01_quickstart.md) | `.tsl` / `.tsf` 文件模型不明 |
| 判断语法能不能写、查语言写法 | [syntax/index.md](syntax/index.md) | 没有命中具体语法专题 |
| 给变量、函数、类型、unit 或 `.tsf` 文件取名 | [naming.md](naming.md) | 文件模型或顶层声明规则不明 |
| 核对高频误写、反例、负向边界 | [syntax/11_pitfalls.md](syntax/11_pitfalls.md) | 反例没有指向正确专题 |
| 查行情、财务、板块、选股等金融函数 | [reference/catalog/datawarehouse.md](reference/catalog/datawarehouse.md) | 没有命中带参数表的函数事实条目 |
| 查通用函数库函数名、参数、返回值 | [reference/index.md](reference/index.md) | catalog 没有正式函数条目 |

View File

@ -46,6 +46,14 @@
`if`、`for`、`class`、`function`、`unit`、`return` 等。
- 调用内置/标准库/第三方 API 时,推荐保持对方官方大小写形式(`aaBBCC`/lowerCamelCase例如
`getSysParams("xxx")`;自定义 wrapper 仍按本指南使用 `PascalCase`
- 常规自定义标识符不要使用 TSL 关键字、保留字或内置函数名。适用范围包括变量、
参数、函数/过程、类/类型、property、方法、字段、unit 名和文件基名。
- 关键字和保留名清单以
[16_lexical_structure_and_compile_options.md](syntax/16_lexical_structure_and_compile_options.md)
为准;例如 `label` 是控制流保留名,不要作为普通变量、函数或属性名。
- 如果业务术语与关键字或内置名冲突,优先换成语义清楚的替代名称。只有明确需要
演示同名遮蔽、绑定外部接口或保持协议兼容时,才允许使用冲突名。
- 函数参数场景可以使用 5.1 中的前导下划线例外。
## 3. 类型命名Type Names

View File

@ -1,8 +1,9 @@
{
"version": "2.0",
"version": "2.1",
"description": "Agent-optimized quick index for TSL syntax - read this FIRST",
"total_tokens_saved_per_query": "~2000-3000",
"changelog": {
"2.1": "Added naming/style routing for identifiers and TSF filename alignment",
"2.0": "Extended coverage from 7 to 14 scenarios, added understand_code and optimize_code decision paths",
"1.0": "Initial version with 7 high-frequency scenarios"
},
@ -62,6 +63,12 @@
"token_cost": 80,
"example": "var a;\na := 1;"
},
"identifier_naming": {
"file": "../naming.md",
"line": 42,
"token_cost": 120,
"example": "UserAccount, LoadData, max_retry_count"
},
"class_basic": {
"file": "08_objects_and_classes.md",
"line": 98,
@ -122,6 +129,11 @@
"tsl_file_structure": {
"order": ["statements first", "declarations after"],
"wrong": "declarations before statements or after declarations"
},
"identifier_naming": {
"doc": "../naming.md#L42",
"avoid": "ordinary custom identifiers should not use TSL keywords, reserved words, or builtin function names",
"tsf_filename_rule": "02_core_model.md#L38"
}
},
@ -159,6 +171,7 @@
"simple_script": "01_quickstart.md#L182",
"function": "05_functions_and_calls.md#L103",
"procedure": "05_functions_and_calls.md#L130",
"naming": "../naming.md#L42",
"class": "08_objects_and_classes.md#L98",
"loop": "07_control_flow.md#L89",
"condition": "07_control_flow.md#L54",

View File

@ -7,6 +7,8 @@
"hello_world": "01_quickstart.md#L182",
"function": "05_functions_and_calls.md#L103",
"class": "08_objects_and_classes.md#L98",
"naming": "../naming.md#L42",
"tsf_filename": "02_core_model.md#L38",
"loop": "07_control_flow.md#L89",
"if": "07_control_flow.md#L54",
"fix_a=1_error": "11_pitfalls.md#L45",
@ -30,6 +32,7 @@
| ------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------ | ------------------------------ |
| 写最短骨架、核对语言核心事实 | [01_quickstart.md](01_quickstart.md) | 文件模型不明 |
| 判断 `.tsl` / `.tsf`、顶层语句区、声明区、文件模型 | [02_core_model.md](02_core_model.md) | 用户交付目标不足以判断后缀 |
| 给变量、函数、类型、unit 或 `.tsf` 文件取名 | [../naming.md](../naming.md) | 文件模型或顶层声明规则不明 |
| 写值、数组、字符串、字符串编码边界 | [03_values_and_literals.md](03_values_and_literals.md) | 需要未记录的字面量或编码写法 |
| 写变量、常量、显式声明 | [04_variables_and_constants.md](04_variables_and_constants.md) | 变量生命周期或作用域不明 |
| 写 `function` / `procedure`、参数、默认参数、命名参数、变参 | [05_functions_and_calls.md](05_functions_and_calls.md) | 需要未记录的调用外形 |

View File

@ -13,6 +13,7 @@ test/
├── test_no_backup_flags.py # no_backup 行为测试
├── test_sync_directory_actions.py # sync_memory_bank/sync_prompts 行为测试
├── test_main_loop_cli.py # main_loop CLI 测试
├── agent/ # Agent 题面/运行时验证测试定义
├── test_thirdparty_skills_pipeline.py # thirdparty skills 流水线配置与同步产物测试
├── test_sync_templates_placeholders.py # 占位符替换测试sync_rules/sync_standards
├── test_toml_edge_cases.py # TOML 解析边界测试

View File

@ -1,300 +1,304 @@
# TSL Agent 测试定义
这个目录包含 TSL 语法的 agent 测试用例定义,**支持测试任何 agent**
你是 TSL agent 测试执行方
---
阅读本 README 后,先向用户询问本机 `tsl` 可执行文件路径。
用户提供路径后,优先自动识别被测 agent 名称;无法可靠识别时,向用户确认一次
agent 短名。随后严格按本文的标准测试流程执行。
## 🎯 多 Agent 支持
轮次边界必须严格执行:
### 测试定义(通用)
- 第一轮只允许生成首答、落盘、运行验证和记录评分;禁止修复,禁止把运行错误回传给被测 agent禁止修改第一轮结果文件也禁止测试执行方在命令失败后自动编辑文件。
- 本轮计划测试的所有 case 完成第一轮评分后,才允许进入第二轮修复。
- 第二轮只修复第一轮已经记录为 `fail` 的 case每修复某个 case 一次,只增加该 case 的 `repair_count`
- **`test_cases.md`** - 100+ 测试用例定义(英文完整版)
这个目录包含 TSL 语法的 agent 测试用例定义。当前评分以运行时验证为准:
生成的 `.tsl``.tsf` 能按标准流程执行通过即为通过,执行报错、超时或文件类型错误即为失败。
- 适用于所有 agentClaude, GPT-4, Gemini, 等)
- 包含提示词、评分标准、预期代码
- 与具体 agent 无关
## 测试定义
- **`test_cases_zh.md`** - 100+ 测试用例定义(中文完整版)
- 完整翻译版本,包含所有测试用例
- 适合中文环境下的 agent 评估
- `prompts_zh.md`:给被测 agent 的题面文件。
- 包含 100 个唯一测试用例。
- 只包含题面,不包含答案、评分细则或 source docs 映射。
- 除非题面明确要求 `.tsf`,默认都要求生成 `.tsl`
### 测试结果(按 Agent 分类)
不再维护单独的 rubric 文件。不要用人工答案表给被测 agent 提供额外线索。
- **`result/results_<agent>_<date>.md`** - 特定 agent 的测试结果
- 存放目录:`test/agent/result/`(已加入 `.gitignore`
- 命名格式:`results_{agent}_{YYYYMMDD}.md`
- 示例:
- `result/results_claude_20260610.md` - Claude 的测试结果
- `result/results_gpt4_20240617.md` - GPT-4 的测试结果
- `result/results_gemini_20240617.md` - Gemini 的测试结果
## 测试产物
---
所有测试结果都落盘为 `.tsl``.tsf` 文件,不保存 agent 回答 markdown。
## 📁 目录结构
- 存放目录:`test/agent/result/<agent>/<YYYYMMDD>/`
- `<agent>` 由测试执行方优先自动识别。
- 识别来源优先使用被测 agent 的产品名、命令名、SDK provider 名或当前运行器已知的 agent 身份。
- 无法从运行器上下文、命令名或已知 provider 可靠识别时,向用户确认一次 agent 短名;不要猜测。
- 目录名统一转成小写短名,只使用 ASCII 字母、数字、短横线、下划线或点。
- 命名格式:
- `.tsl``tsl-001.tsl`
- `.tsf``tsl-037/<TopLevelName>.tsf`
- `.tsf` 调用验证脚本:`tsl-037/verify.tsl`
- 修复轮次按 case 计数:`repair-1/tsl-001.tsl`、`repair-1/tsl-037/<TopLevelName>.tsf`
- 示例:
- `result/claude/20260610/tsl-001.tsl`
- `result/claude/20260610/tsl-037/<TopLevelName>.tsf`
- `result/claude/20260610/tsl-037/verify.tsl`
### 当前文件
被测 agent 禁止读取、请求、搜索或引用 `result/`
## 目录结构
```text
test/agent/
├── README.md # 本文件
├── test_cases.md # 通用测试定义(英文完整版)⭐
├── test_cases_zh.md # 通用测试定义(中文完整版)⭐
└── result/ # 测试结果目录gitignore
├── results_claude_20260610.md
├── results_gpt4_20240617.md
└── results_gemini_20240617.md
```
### 添加新 Agent 的测试结果
```text
test/agent/
├── test_cases.md # 通用(不变)
├── test_cases_zh.md # 中文版(不变)
├── README.md
├── prompts_zh.md
└── result/
├── results_claude_20260610.md # Claude
├── results_gpt4_20240617.md # GPT-4新增
└── results_gemini_20240617.md # Gemini新增
└── claude/
└── 20260610/
├── tsl-001.tsl
├── tsl-037/
│ ├── <TopLevelName>.tsf
│ └── verify.tsl
└── repair-1/
├── tsl-001.tsl
└── tsl-037/
├── <TopLevelName>.tsf
└── verify.tsl
```
---
## 🎯 使用方式
### 测试不同的 Agent
1. **使用相同的测试定义**
```bash
# 所有 agent 都使用 test_cases.md 中的测试用例
cat test_cases.md
```
2. **为每个 Agent 记录结果**
```bash
# 创建结果目录
mkdir -p test/agent/result
# 测试 GPT-4
# 结果保存为test/agent/result/results_gpt4_20240617.md
# 测试 Gemini
# 结果保存为test/agent/result/results_gemini_20240617.md
# 测试 Claude
# 结果保存为test/agent/result/results_claude_20240617.md
```
3. **对比不同 Agent 的表现**
```bash
# 对比通过率、得分、常见错误等
diff test/agent/result/results_claude_20240617.md \
test/agent/result/results_gpt4_20240617.md
```
---
## 📊 测试流程
## 标准测试流程
### 1. 准备测试
```bash
# 查看测试用例
cat test_cases.md
阅读本 README 后,测试执行方必须在开始执行用例前询问并记录本机 `tsl`
可执行文件路径。该路径不写入配置文件,只在本轮运行时验证中使用。
# 选择要测试的 agent
AGENT="gpt4" # 或 claude, gemini, 等
DATE=$(date +%Y%m%d)
`TSL_HOME` 记为 `tsl` 可执行文件所在目录;如果用户提供的是 TSL 根目录,
则以用户提供的目录作为 `TSL_HOME`
```text
TSL executable path: /path/to/tsl
```
### 2. 执行测试
优先自动识别被测 agent 名称并记为 `AGENT`。`AGENT` 不是普通配置项;如果无法从
当前运行器上下文、命令名或已知 provider 可靠识别,则在开始执行用例前向用户确认一次
agent 短名;不要猜测。
```bash
AGENT="<auto-detected-agent>"
DATE=$(date +%Y%m%d)
mkdir -p "test/agent/result/$AGENT/$DATE"
```
### 2. 逐题生成文件
阅读 `prompts_zh.md`,然后按 case 逐题执行测试。
对于每个测试用例:
1. 复制提示词Prompt
2. 发送给目标 agent
3. 记录生成的代码
4. 根据评分标准打分0/1/2
1. 为当前 case 启动全新的被测 agent 会话。测试执行方可以保持同一个会话,
但被测 agent 不能在同一个会话里连续回答多个 case。
2. 只发送 `prompts_zh.md` 中的 `Runner Setup`、`Answer Rules` 加单个题面,
或只暴露 `prompts_zh.md``docs/index.md` 及其路由到的 `docs/` 子页。
3. 允许 agent 从 `docs/index.md` 自动路由并阅读相关文档。
4. 记录 agent 生成的第一次完整代码并立即落盘。
5. 落盘后冻结该 case 的第一轮结果文件;第一轮不允许 agent 根据运行结果或评分反馈修订答案。
6. 被测 agent 不得主动读取、请求、搜索或引用任何评分材料。
### 3. 保存结果
Codex 作为被测 agent 时:
```bash
# 创建结果目录
mkdir -p test/agent/result
- CLI 自动化:每个 case 单独执行一次 `codex exec`,不要使用 `codex exec resume`
- CLI 自动化如果不想保留会话记录,可使用 `codex exec --ephemeral`
- Codex App 或 IDE每个 case 新建一个 thread不要在同一个 thread 里继续下一个 case。
- Codex SDK/MCP每个 case 调用一次新的 thread/start不要用同一个 thread 连续 run 多个 case。
# 创建结果文件
# 格式result/results_{agent}_{YYYYMMDD}.md
任何被测 agent 都一样:第一轮运行时验证输出不能回传给被测 agent。第一轮发现错误时
只记录 `fail`,不得修复当前文件,不得让被测 agent 重新回答,不得把修改后的文件计入
第一轮成绩。测试执行方自己的自动修复/纠错行为在第一轮也必须关闭。如果工具在看到
第一轮运行错误后自动修改结果文件,必须按首次落盘文件评分;无法恢复首次落盘文件时,
该 case 标记为 `invalid`。第二轮修复阶段是例外,见“自动修复轮次”。
test/agent/result/results_gpt4_20240617.md
test/agent/result/results_claude_20240617.md
test/agent/result/results_gemini_20240617.md
评分材料包括:
- `result/`
- 运行时验证日志
- 其他 agent 的输出文件
- 对比报告或人工备注
若被测 agent 主动接触评分材料,该 case 或本轮测试应标记为 `invalid`
不计入有效成绩。
推荐的运行器设置:
```text
You are in this repository. The documentation entry point is docs/index.md.
When asked to write TSL, start from docs/index.md and follow its routing to the
relevant TSL pages. Do not infer syntax from Pascal, TypeScript, JavaScript,
Python, or SQL.
```
### 4. 对比分析
文件落盘规则:
- 默认每个 case 保存为 `.tsl`,例如 `test/agent/result/<agent>/<YYYYMMDD>/tsl-001.tsl`
- 只有题面明确要求输出 `.tsf` 时,才保存为 `.tsf`,并放入对应 case 目录,
例如 `test/agent/result/<agent>/<YYYYMMDD>/tsl-037/<TopLevelName>.tsf`
- `.tsf` 文件名不能使用 case 编号;文件基名必须与第一个顶层声明同名。
测试执行方应按被测 agent 代码中的第一个顶层声明命名文件,不为了凑文件名改写代码。
- 任何 `unit ... end.` 文件只能保存为 `.tsf`,不能保存为 `.tsl`
- 如果 agent 输出 markdown code fence测试执行方只提取代码内容保存到文件不保存回答 markdown。
### 3. 运行时验证
运行时验证是标准测试流程的一部分。保存 `.tsl``.tsf` 文件后,由测试执行方
逐个验证。第一轮验证必须在被测 agent 会话之外执行,不要把 stdout/stderr 或错误日志
发送回被测 agent即使第一轮发现错误也只记录评分不修复文件。第二轮自动修复阶段
按“自动修复轮次”规则处理。
`.tsl` 验证规则:
```bash
cd test/agent/result/<agent>/<YYYYMMDD>
tsl tsl-001.tsl
tsl tsl-002.tsl
```
`.tsf` 验证规则:
1. 将 case 目录中的 `.tsf` 文件复制到 `TSL_HOME/funcext/tmp/`
2. 在同一个 case 目录中编写 `verify.tsl` 调用脚本。
调用脚本应按被测 agent 实际生成的函数名、unit 名或类型名来调用。
验证脚本必须实际调用 `.tsf` 暴露的功能,不能只输出成功标记。
3. 调用脚本在所有验证调用成功后,用 TSL 输出语句最后输出一行 `__TSL__AGENT__OK__`
4. 执行 `tsl verify.tsl`
5. 验证完成后删除 `TSL_HOME/funcext/tmp/`
```bash
cd test/agent/result/<agent>/<YYYYMMDD>/tsl-037
mkdir -p "$TSL_HOME/funcext/tmp"
cp ./*.tsf "$TSL_HOME/funcext/tmp/"
tsl verify.tsl
rm -rf "$TSL_HOME/funcext/tmp"
```
`funcext/tmp` 由本流程独占。开始验证前不要在该目录保留人工文件;结束后必须清理。
### 4. 第一轮评分规则
- `pass`:按标准流程执行,最后一个非空输出行是 `__TSL__AGENT__OK__`
- `fail`:超时、缺少文件、文件类型错误、`.tsf` 调用脚本失败,
`.tsf` 文件名与第一个顶层声明不一致,`.tsf` 无法被 TSL 加载/编译,
或最后一个非空输出行不是 `__TSL__AGENT__OK__`
- `invalid`:被测 agent 主动读取、请求、搜索或引用评分材料。
TSL 可能在打印错误后仍返回退出码 0因此不能只看 `$LASTEXITCODE`
运行时评分以成功标记为准:脚本没有正常执行到最后,就不会输出最后的
`__TSL__AGENT__OK__`
最终成绩只统计有效 case
```text
pass_rate = pass / (pass + fail)
```
不由被测 agent 自评。
### 5. 自动修复轮次
本轮计划测试的所有 case 完成第一轮评分后,可以对 `fail` 的 case 启动第二轮自动修复。
修复规则:
1. 第一轮期间禁止修复;只有进入第二轮后,第一轮已经记录为 `fail` 的 case 才可以修复。
2. 修复阶段可以把当前文件内容和运行时验证输出发给被测 agent。
3. 每次 agent 产出修复版本,都保存到新的修复目录,不覆盖第一轮文件。
4. 第一次修复保存到 `repair-1/`,第二次修复保存到 `repair-2/`,依此类推。
5. `repair_count` 按 case/file 单独记录;修复 `tsl-019.tsl` 只增加 `tsl-019` 的次数,
不影响其他失败 case。
6. 修复版本仍按同样的运行时验证规则执行,最后一个非空输出行必须是 `__TSL__AGENT__OK__`
示例:
```text
test/agent/result/opencode/20260623/
├── tsl-019.tsl # 第一轮原始输出
├── repair-1/
│ └── tsl-019.tsl # 第 1 次修复
└── repair-2/
└── tsl-019.tsl # 第 2 次修复
```
修复统计:
```text
case_id = tsl-019
first_pass = 第一轮是否 pass
repair_pass = 修复后是否 pass
repair_count = 该 case 的修复版本数量
```
如果第一轮已经 `pass``repair_count = 0`。如果多次修复仍失败,
该 case 的 `repair_count` 记录实际修复次数,`repair_pass = false`。
### 6. 对比分析
不同 agent 的输出直接按目录对比:
```bash
diff -r test/agent/result/claude/20260617 \
test/agent/result/gpt4/20260617
```
建议人工记录汇总表,但不要把汇总表放入被测 agent 可读上下文。
```markdown
# 示例对比报告
| Agent | 测试日期 | 通过率 | 平均分 | 常见错误 |
|-------|---------|-------|--------|---------|
| Claude | 2026-06-10 | 100% (10/10) | 2.0 | 无 |
| GPT-4 | 2024-06-17 | 90% (9/10) | 1.8 | 赋值语法 |
| Gemini | 2024-06-17 | 85% (8.5/10) | 1.7 | 类定义 |
| Agent | 测试日期 | 有效用例 | Pass | Fail | Invalid | Pass rate |
|-------|---------|---------:|-----:|-----:|--------:|----------:|
| Claude | 2026-06-17 | 100 | 96 | 4 | 0 | 96% |
| GPT-4 | 2026-06-17 | 100 | 88 | 12 | 0 | 88% |
```
---
## 版本控制策略
## 📝 结果文件命名规范
### 格式
提交到 git
```text
test/agent/result/results_{agent}_{YYYYMMDD}.md
test/agent/README.md
test/agent/prompts_zh.md
```
**说明**
- `result/`: 测试结果统一存放目录(已加入 `.gitignore`
- `{agent}`: agent 名称(小写,如 claude, gpt4, gemini
- `{YYYYMMDD}`: 测试日期(如 20240617
### 示例
不提交:
```text
test/agent/result/results_claude_20260610.md # Claude 在 2026-06-10 的测试
test/agent/result/results_claude_20240617.md # Claude 在 2024-06-17 的测试
test/agent/result/results_gpt4_20240617.md # GPT-4 在 2024-06-17 的测试
test/agent/result/results_gpt4o_20240617.md # GPT-4o 在 2024-06-17 的测试
test/agent/result/results_gemini_20240617.md # Gemini 在 2024-06-17 的测试
test/agent/result/results_gemini15_20240617.md # Gemini 1.5 在 2024-06-17 的测试
test/agent/result/
```
---
## 测试用例覆盖
## 🎯 .gitignore 配置
### 版本控制策略
**提交到 git**
```text
✅ test/agent/test_cases.md # 测试定义(英文完整版)
✅ test/agent/test_cases_zh.md # 测试定义(中文完整版)
✅ test/agent/README.md # 说明文档
```
**不提交**(已加入 `.gitignore`
```text
❌ test/agent/result/ # 测试结果目录
```
---
## 📊 测试用例覆盖
`test_cases.md` 包含 100+ 测试用例,覆盖:
`prompts_zh.md` 包含 100 个测试用例,覆盖:
| 语法点 | 测试用例数 |
| ---------- | ---------- |
| 函数定义 | 15+ |
| 类与对象 | 10+ |
| ----------- | ---------- |
| 基础脚本 | 10+ |
| 控制流 | 10+ |
| 变量与赋值 | 8+ |
| Unit 模块 | 5+ |
| 参数传递 | 8+ |
| 类型系统 | 6+ |
| 错误边界 | 10+ |
| 其他 | 30+ |
| 函数调用 | 10+ |
| `.tsf`/Unit | 4+ |
| 集合与查询 | 10+ |
| 表达式 | 10+ |
| 类与对象 | 15+ |
| 运行时特性 | 10+ |
| 高级边界 | 10+ |
**总计**100+ 测试用例
## 相关文档
---
- 文档总入口:`docs/index.md`
## 🔗 相关文档
## 最佳实践
### TSL 文档
- TSL 语法文档:`docs/tsl/syntax/`
- TSL 快速索引:`docs/tsl/syntax/00_agent_index.json`
- TSL 语法入口:`docs/tsl/syntax/index.md`
### Agent 优化
- Agent 快速索引:`docs/tsl/syntax/00_agent_index.json`
- 为 agent 优化,减少 75% token 消耗
- 包含精确行号和示例代码
---
## 💡 最佳实践
### 1. 保持测试定义的通用性
- ✅ 测试用例应该对所有 agent 都适用
- ✅ 不要添加特定 agent 的专属测试
- ✅ 关注 TSL 语法本身,而非 agent 特性
### 2. 结果命名规范
- ✅ 使用统一的命名格式
- ✅ 包含 agent 名称和日期
- ✅ 便于排序和查找
### 3. 定期对比
- 建议每季度测试一次所有 agent
- 追踪 agent 的改进趋势
- 发现不同 agent 的优势和劣势
### 4. 基线管理
- 保留第一次测试结果作为基线
- 新结果与基线对比
- 追踪质量变化
---
## 🎉 示例:测试新 Agent
### 步骤
```bash
# 1. 选择测试用例
cat test_cases.md | grep "### TSL-001"
# 2. 复制提示词发送给新 agent如 GPT-4
# 3. 记录结果
cat > results_gpt4_20240617.md << 'EOF'
# TSL Codegen Test Results - GPT-4
Date: 2024-06-17
Agent: GPT-4 (gpt-4-turbo)
## Summary
- Cases run: 10
- Cases passed: 9
- First-pass score: 18 / 20
- Pass rate: 90%
## Results
| Case | Score | Notes |
|------|-------|-------|
| TSL-001 | 2 | Correct |
| TSL-002 | 2 | Correct |
| TSL-003 | 1 | Minor issue |
...
EOF
# 4. 对比 Claude 和 GPT-4
diff results_claude_20260610.md results_gpt4_20240617.md
```
---
- 测试用例应该对所有 agent 都适用。
- 不要添加特定 agent 的专属测试。
- 关注 TSL 语法本身,而非 agent 特性。
- 每轮测试使用独立日期目录。
- 保留第一次输出作为基线,不根据运行反馈让同一个 agent 修订答案。
- 定期对比不同 agent 的通过率和常见运行错误。
**维护者**TSL Team
**最后更新**2024-06-17
**支持的 Agent**:所有支持 TSL 的 agent

881
test/agent/prompts_zh.md Normal file
View File

@ -0,0 +1,881 @@
# TSL Agent Prompt Set (ZH)
本文件只包含发送给被测 agent 的题面。
## Runner Setup
```text
You are in this repository. The documentation entry point is docs/index.md.
When asked to write TSL, start from docs/index.md and follow its routing to the
relevant TSL pages. Do not infer syntax from Pascal, TypeScript, JavaScript,
Python, or SQL.
```
## Answer Rules
```text
每个 case 独立作答。
除非题面明确要求输出 .tsf否则默认输出可执行 .tsl 文件内容。
题面模拟普通用户的需求,不要复制文档中的样例代码。
请按题面里的名称、数据和业务动作重新编写。
如果输出 .tsl请在题面要求的业务输出全部完成后用 TSL 输出语句最后输出一行 __TSL__AGENT__OK__
如果输出 .tsf必须是 TSL 能从 funcext 加载的有效函数扩展或 unit 文件;
不要在 .tsf 中加入成功标记,成功标记由验证脚本输出。
只输出代码,不要解释。
```
## Prompts
### TSL-001: 订单折后金额
```text
请写一份 .tsl 代码:
一个订单里,单价是 19数量是 6优惠金额是 14。
请算出这行订单最后要收多少钱,并输出结果。
```
### TSL-002: 分页信息
```text
请写一份 .tsl 代码:
一共有 47 条记录,每页放 10 条。
请输出能装满的页数,以及最后一页还剩多少条。
```
### TSL-003: 订单编号
```text
请写一份 .tsl 代码:
把文字 "Order" 和编号 "42" 合成一个订单编号,然后输出它。
```
### TSL-004: 简单扣费
```text
请写一份 .tsl 代码:
账户余额是 12本次扣费是 3。
请输出扣费后的余额。不要提前列出额外的变量清单。
```
### TSL-005: 固定单价
```text
请写一份 .tsl 代码:
某个商品固定单价是 9本次买了 4 个。
请把固定单价作为常量保存,再输出总价。
```
### TSL-006: 严格模式库存
```text
请写一份 .tsl 代码:
这份脚本要开启显式变量模式。
请准备一个库存数 stock把它设为 18然后输出它。
```
### TSL-007: 读取分数
```text
请写一份 .tsl 代码:
有一组分数15、30、45。
请输出第一项和最后一项。
```
### TSL-008: 读取编码字符
```text
请写一份 .tsl 代码:
编码是 "ZX9"。
请输出第一个字符和第三个字符。
```
### TSL-009: 空列表检查
```text
请写一份 .tsl 代码:
准备一个空列表 bucket。
请检查 bucket 的第一个位置是不是 nil并输出检查结果。
```
### TSL-010: 文本数字参与计算
```text
请写一份 .tsl 代码:
有一个文本形式的数字 "58"。
请先把它变成整数,再减去 8并输出结果。
```
### TSL-011: 温度标签
```text
请写一份 .tsl 代码:
temperature 是 32。
如果温度大于等于 30level 就是 "hot";否则 level 是 "normal"。
请最后输出 level。
```
### TSL-012: 余额审核
```text
请写一份 .tsl 代码:
balance 是 80。
如果 balance 大于 50请先输出 "allow",再扣掉 10
否则输出 "deny"。最后输出 balance。
```
### TSL-013: 偶数累加
```text
请写一份 .tsl 代码:
请把 2、4、6、8 加起来并输出。
要求用带步长的循环完成。
```
### TSL-014: 权重检查
```text
请写一份 .tsl 代码:
weights 里有 3、5、9。
请逐个处理,每行输出“当前位置”和“这个位置的值”的乘积。
```
### TSL-015: 累加到上限
```text
请写一份 .tsl 代码:
从 n = 1 开始累加。
当 n 大于 4 时停止,最后输出累计结果。
```
### TSL-016: 跳过指定数字
```text
请写一份 .tsl 代码:
处理 1 到 5。
遇到 3 时跳过它,只累加其他数字,最后输出结果。
```
### TSL-017: 倒计时
```text
请写一份 .tsl 代码:
从 countdown = 4 开始倒数,一直到 0 停止。
请使用 repeat until并输出最后的 countdown。
```
### TSL-018: 状态码
```text
请写一份 .tsl 代码:
status_code 是 2。
如果是 1输出 "new";如果是 2 或 3输出 "active"
其他情况输出 "closed"。
```
### TSL-019: 等级文字
```text
请写一份 .tsl 代码:
grade 是 3。
请用 case 表达式得到一段等级文字1 是 "low"2 到 4 是 "mid",其他是 "high"。
最后输出这段等级文字。
```
### TSL-020: 捕获错误信息
```text
请写一份 .tsl 代码:
故意抛出 "network" 这个错误。
捕获它后,请输出错误对象里的错误信息。
```
### TSL-021: 清理动作
```text
请写一份 .tsl 代码:
先输出 "open"。
无论前面是否正常结束,最后都要输出 "close"。
请用 try/finally 完成。
```
### TSL-022: 计算数量乘积
```text
请写一份 .tsl 代码:
请做一个“计算两个整数乘积”的功能,名字由你自己取。
脚本里请用 6 和 8 调用它,并输出结果。
```
### TSL-023: 调整额度
```text
请写一份 .tsl 代码:
请做一个“把额度增加 5”的动作名字由你自己取。
脚本里 quota 一开始是 10调用后输出 quota。
```
### TSL-024: 默认手续费
```text
请写一份 .tsl 代码:
请做一个“计算手续费后金额”的功能,名字由你自己取。
如果没有传金额,就按 100 处理;最后结果是金额加 6。
请分别输出不传金额和传 20 时的结果。
```
### TSL-025: 下一批编号
```text
请写一份 .tsl 代码:
请做一个“取得下一批编号”的功能,名字由你自己取。
起始编号是整数,默认是 10结果也是整数。
它要返回起始编号加 1。请输出默认情况下的结果。
```
### TSL-026: 区间组装
```text
请写一份 .tsl 代码:
请做一个“组装左右边界”的功能,名字由你自己取,把两个边界值组成一个两项列表。
调用时请用命名方式传入right 是 90left 是 40。
最后输出这两项。
```
### TSL-027: 跳过中间值
```text
请写一份 .tsl 代码:
请做一个“检查中间位置”的功能,名字由你自己取,里面要输出第二个位置 b 是不是 nil。
调用时只给第一个和第三个位置传值,故意跳过 b。
```
### TSL-028: 按名字调用功能
```text
请写一份 .tsl 代码:
请做一个“三位数字编码”的功能,名字由你自己取。
它把三个输入算成 a * 100 + b * 10 + c。
脚本里请通过 call 按这个名字调用它,并输出结果。
```
### TSL-029: 多个数字相乘
```text
请写一份 .tsl 代码:
请做一个“多个数字相乘”的功能,名字由你自己取。
它可以接收任意多个数字,并把它们全部相乘。
请用 2、3、4 调用,并输出结果。
```
### TSL-030: 看到多少输入
```text
请写一份 .tsl 代码:
请做一个“统计收到多少输入”的功能,名字由你自己取。
前两个位置是固定的,后面还能继续接收更多值。
它要输出 ParamCount * 100 + RealParamCount 的结果。
请用 5、6、7 调用。
```
### TSL-031: 保存一个小计算
```text
请写一份 .tsl 代码:
把一个“小计算”保存到你自己命名的变量里。这个小计算接收两个值,结果是两者相乘。
请通过 call 调用这个变量,并用 4 和 9 输出结果。
```
### TSL-032: 把计算交给别人执行
```text
请写一份 .tsl 代码:
请做一个“执行后再翻倍”的功能,名字由你自己取,它接收另一个计算。
这个功能要先用 3 调用收到的计算,再把得到的结果乘以 2。
调用它时,直接给它一个“把输入加 5”的匿名计算并输出结果。
```
### TSL-033: 查找已有功能
```text
请写一份 .tsl 代码:
请做一个“把输入乘以 3”的功能名字由你自己取。
脚本里找到这个名字对应的函数值,再用支持的函数值调用方式处理 7并输出结果。
```
### TSL-034: 传递当前功能
```text
请写一份 .tsl 代码:
请做一个“把输入平方”的功能,名字由你自己取。
再做一个“调用传入计算”的功能,名字也由你自己取,它接收一个计算和一个值,并通过 call 执行。
脚本里取得平方功能的函数值,并输出调用结果。
```
### TSL-035: 函数里使用规则包
```text
请写一份 .tsl 代码:
请做一个“读取远程费率”的功能,名字由你自己取。
这个功能一进入函数体就要使用一个费率相关的 unit然后返回该 unit 中读取费率动作的结果。
```
### TSL-036: 脚本开头使用规则包
```text
请写一份 .tsl 代码:
脚本需要先使用两个你自己命名的规则包:一个处理价格,一个处理税费。
之后调用一个“计算最终金额”的动作,并输出结果。
```
### TSL-037: 手续费扩展
```text
请写一份 .tsf 代码:
提供一个“计算服务费”的功能,名字由你自己取,接收金额。
金额大于 1000 时,费用是 amount div 20否则费用是 30。
不要写可直接运行的脚本入口。
```
### TSL-038: 发票规则包
```text
请写一份 .tsf 代码:
请做一个“发票规则”unitunit 名由你自己取。
外部只需要能调用一个“默认额度”功能,并得到 500。
请写成完整的 unit 文件。
```
### TSL-039: 运费规则包
```text
请写一份 .tsf 代码:
请做一个“运费规则”unitunit 名由你自己取。
外部只能调用一个“计算可计费重量”的功能。
内部可以有一个不对外公开的小工具,用来把负数修正为 0。
可计费重量要返回修正后的毛重减去皮重。
```
### TSL-040: 会员积分规则包
```text
请写一份 .tsf 代码:
请做一个“会员积分规则”unitunit 名由你自己取。
外部可以调用“基础分”和“最终积分”两个功能。
level 大于等于 3 时基础分是 20否则是 5。
最终积分的结果是金额 div 10 加上基础分。
```
### TSL-041: 商品信息表
```text
请写一份 .tsl 代码:
准备一条商品信息,里面有 sku = "B17"qty = 12。
请输出 sku 和 qty。
```
### TSL-042: 只取第一个成绩
```text
请写一份 .tsl 代码:
有一组成绩 88、99、100。
请只取第一个值放到 first_mark然后输出 first_mark。
```
### TSL-043: 读取两行数据
```text
请写一份 .tsl 代码:
有两行数据:(8, 1) 和 (9, 2)。
请把两行分别取出来,再输出每行的两个值。
```
### TSL-044: 检查是否存在
```text
请写一份 .tsl 代码:
先检查 5 是否在 2、5、8 这一组数字里,并输出结果。
再检查整行 (2, 5) 是否在两行数据 (1, 1)、(2, 5) 里面,并输出结果。
```
### TSL-045: 两组行数据对比
```text
请写一份 .tsl 代码:
left_rows 是 (1, "a")、(2, "b")。
right_rows 是 (2, "b")、(3, "c")。
请分别算出合并、交集、左边独有、两边不重叠的结果,并输出每个结果的大小。
```
### TSL-046: 只保留允许状态
```text
请写一份 .tsl 代码:
有一批订单,每行包含订单号和状态。
再准备一份允许状态列表。
请只保留状态命中的订单,并输出保留下来的行数。
```
### TSL-047: 排除禁止状态
```text
请写一份 .tsl 代码:
有一批任务,每行包含任务号和状态。
再准备一份禁止状态列表。
请排除命中的任务,并输出剩余行数。
```
### TSL-048: 查询商品数量
```text
请写一份 .tsl 代码:
有一批商品数据,每行包含商品编号和数量。
请用 TS-SQL 只取数量大于 3 的行,并输出结果行数。
```
### TSL-049: 筛选并排序成绩
```text
请写一份 .tsl 代码:
有一批姓名和分数。
请用 TS-SQL 只保留分数大于等于 60 的人,并按分数从高到低排序。
最后输出第一行的姓名。
```
### TSL-050: 部门金额汇总
```text
请写一份 .tsl 代码:
有一批部门和金额数据。
请用 TS-SQL 按部门汇总金额,并输出汇总后的行数。
```
### TSL-051: 客户订单关联
```text
请写一份 .tsl 代码:
有一组客户数据和一组订单数据,它们通过客户编号关联。
请用 TS-SQL 得到客户名称和订单金额,并输出关联后的行数。
```
### TSL-052: 多种数字写法
```text
请写一份 .tsl 代码:
有几个配置值0x2A、0b1010、0o12、200L、6E2。
请分别输出它们对应的类型判断结果。
```
### TSL-053: 日期和时间
```text
请写一份 .tsl 代码:
有一个日期 20240618T还有一个带时间的值 20240618.1530T。
请分别输出日期字符串和时间字符串。
```
### TSL-054: 数字真假判断
```text
请写一份 .tsl 代码:
先输出 true 和 false。
再分别判断 4、0、-2 在 if 里会走哪个分支,并输出分支标记。
```
### TSL-055: Nil 参与计算
```text
请写一份 .tsl 代码:
请输出 ifNil(nil) 的结果。
再输出 nil + 5、5 + nil并检查 nil + nil 是不是 nil。
```
### TSL-056: 复数信息
```text
请写一份 .tsl 代码:
准备两个复数8 + 6j 和 complex(3, -4)。
请输出第一个复数的实部、虚部,并输出第二个值是不是复数。
```
### TSL-057: 批次报告
```text
请写一份 .tsl 代码:
一批货有 17 件,每箱装 5 件;优先级是 3距离是 9基准是 4ratio_base 是 7。
请输出完整箱数、剩余件数、优先级的四次方、距离与基准的按位关系结果,
以及 ratio_base 与 3 的左除计算结果。
```
### TSL-058: 补货数量
```text
请写一份 .tsl 代码:
最低库存是 20当前库存是 14。
如果库存不足reorder_count 就是最低库存减当前库存;否则是 0。
请用条件表达式得到 reorder_count并输出它。
```
### TSL-059: 候补分数
```text
请写一份 .tsl 代码:
primary_score 是 12missing_score 是 0候补值是 99。
请用省略真值的条件表达式分别得到两个最终分数,并输出。
```
### TSL-060: 发货判断
```text
请写一份 .tsl 代码:
paid 是 trueblocked 是 falseamount 是 120。
请用 and、or、not 判断是否允许发货,并输出结果。
```
### TSL-061: 权限掩码
```text
请写一份 .tsl 代码:
read_write 是 6audit_exec 是 3。
请输出共同权限、合并权限、差异权限,以及 read_write 取反后的结果。
```
### TSL-062: 计数调整
```text
请写一份 .tsl 代码:
counter 一开始是 5。
先加 4再自增一次最后输出 counter。
```
### TSL-063: 安全读取订单金额
```text
请写一份 .tsl 代码:
maybe_order 是 nil。
请安全读取 maybe_order.total并输出读取结果是不是 nil。
```
### TSL-064: 阈值范围
```text
请写一份 .tsl 代码:
请判断 3、8、20 是否满足从小到大的连续比较,并输出结果。
```
### TSL-065: 三组指标逐项比较
```text
请写一份 .tsl 代码:
有三组指标2、4、63、5、74、6、8。
请逐项判断第一组是否小于第二组、第二组是否小于第三组,
并输出得到的三个结果。
```
### TSL-066: 发票号格式
```text
请写一份 .tsl 代码:
发票号是 "INV-2024-07"。
请判断它是不是以 "INV-" 开头,并且后面包含数字,然后输出结果。
```
### TSL-067: 带注释的小脚本
```text
请写一份 .tsl 代码:
请包含两种 TSL 支持的注释写法。
然后把 daily_total 设为 31并输出它。
```
### TSL-068: 编译时模式选择
```text
请写一份 .tsl 代码:
如果定义了 FAST_MODE就输出 "fast";否则输出 "safe"。
请用条件编译完成。
```
### TSL-069: 临时上下文
```text
请写一份 .tsl 代码:
请使用运行时 with 单星块。
在临时上下文里设置一个字段,并在块内输出这个字段。
```
### TSL-070: 嵌套上下文
```text
请写一份 .tsl 代码:
请使用运行时 with 双星块。
在嵌套上下文里读取外层字段,并输出组合结果。
```
### TSL-071: 带超时的远程式调用
```text
请写一份 .tsl 代码:
准备一个“慢速评分”的功能,名字由你自己取,它返回 12。
请用网格调用方式调用它,并设置超时时间,然后输出得到的结果。
```
### TSL-072: 全局缓存
```text
请写一份 .tsl 代码:
把 "session_limit" 这个全局缓存设为 300。
再读取它并输出,同时输出这个缓存是否存在。
```
### TSL-073: 调试结果
```text
请写一份 .tsl 代码:
请做一个“检查金额”的功能,名字由你自己取。
如果输入小于 0请用 debugReturn 返回调试值;否则返回原值。
请用 -1 调用它并输出结果。
```
### TSL-074: 简单计时
```text
请写一份 .tsl 代码:
请用内置计时开始和结束功能包住一个小循环,并输出计时结果。
```
### TSL-075: 兜底跳转
```text
请写一份 .tsl 代码:
flag 是 false。
如果 flag 为 false就跳到 fallback 标签。
fallback 里输出 "fallback"。
```
### TSL-076: 账户卡片
```text
请写一份 .tsl 代码:
我需要一种“账户卡片”对象,类型名由你自己取。
它要有一个公开字段,用来保存持有人姓名,字段名也由你自己取。
脚本里创建一张卡,把持有人设为 "Lina",然后输出这个字段。
```
### TSL-077: 仪表盒
```text
请写一份 .tsl 代码:
我需要一种“仪表盒”对象,类型名由你自己取。
创建它时传入初始读数,保存到 reading。
它有一个“前进一步”的动作,动作名由你自己取,每次让读数增加 2并给出新的读数。
脚本里创建一个初始读数为 10 的对象,输出调用这个动作后的结果。
```
### TSL-078: 设备总数
```text
请写一份 .tsl 代码:
我需要一种“设备计数器”类型,类型名由你自己取,它有一个所有对象共享的 total_count。
脚本里把 total_count 设为 77然后输出它。
```
### TSL-079: 汇率工具
```text
请写一份 .tsl 代码:
我需要一种“汇率计算”类型,类型名由你自己取,上面直接提供一个“倍率相乘”的功能。
它返回 a * b。
脚本里通过类型本身调用这个功能处理 4 和 5并输出结果。
```
### TSL-080: 货架编码
```text
请写一份 .tsl 代码:
我需要一种“货架盒”对象,类型名由你自己取。
它内部有一个保存货架编码的字段,字段名由你自己取。
对外通过一个属性读写这个编码,属性名也由你自己取。
脚本里创建对象,把编码设为 "S-8",然后通过属性输出编码。
```
### TSL-081: 客户显示名
```text
请写一份 .tsl 代码:
我需要一种“客户名称”对象,类型名由你自己取。
它内部有一个 string 类型字段,用来保存原始姓名,字段名由你自己取。
对外通过一个带类型的属性访问显示姓名,属性名也由你自己取。
脚本里设置并输出这个显示姓名属性。
```
### TSL-082: 两种渲染方式
```text
请写一份 .tsl 代码:
我需要一种“格式化工具”对象,类型名由你自己取。
它有两个同名动作,动作名由你自己取:一个接收一个值,一个接收两个值。
脚本里分别调用这两种动作,并输出结果。
```
### TSL-083: 自行车对象
```text
请写一份 .tsl 代码:
我需要一种“交通工具基础对象”,类型名由你自己取。
它有一个说明类别的动作,动作名由你自己取,结果是 "vehicle"。
再做一种“自行车对象”,类型名也由你自己取,继承前面的基础对象,
并增加一个说明轮子数量的动作,动作名由你自己取,结果是 2。
脚本里创建自行车对象,输出类别和轮子数量。
```
### TSL-084: 折扣价格标签
```text
请写一份 .tsl 代码:
我需要一种“价格基础对象”,类型名由你自己取。
它有一个可被子类型改写的标签动作,动作名由你自己取,默认结果是 "base"。
再做一种“折扣价格对象”,类型名也由你自己取,把这个标签动作的结果改成 "discount"。
脚本里创建折扣价格对象并输出标签。
```
### TSL-085: 追加消息
```text
请写一份 .tsl 代码:
我需要一种“基础消息对象”,类型名由你自己取。
它有一个给出文字的动作,动作名由你自己取,结果是 "base"。
再做一种“提醒消息对象”,类型名也由你自己取。
它的文字动作要先调用父级同名动作,再追加 "-alert"。
脚本里输出提醒消息对象的文字。
```
### TSL-086: 类外补充方法
```text
请写一份 .tsl 代码:
我需要一种“票据打印器”,类型名由你自己取。
类型里面只先写出一个“打印编号”动作的名字,动作名由你自己取。
请在类型外面补上这个动作的内容,让它给出 "T-100"。
脚本里创建对象并输出结果。
```
### TSL-087: 按名称创建对象
```text
请写一份 .tsl 代码:
我需要一种“动态盒子”对象,类型名由你自己取。
它有一个给出数值的动作,动作名由你自己取,结果是 64。
脚本里请通过字符串里的类型名创建这个对象,并输出这个数值。
```
### TSL-088: 临时句柄清理
```text
请写一份 .tsl 代码:
我需要一种“临时句柄”对象,类型名由你自己取。
它被销毁时要输出 "released"。
脚本里创建它,然后把引用设为 nil。
```
### TSL-089: 外部评分函数
```text
请写一份 .tsl 代码:
有一个外部提供的“评分”功能TSL 中使用的名字由你自己取,它接收一个值并给出结果。
这里只需要写出它和外部功能的连接写法,不需要调用。
```
### TSL-090: 外部日志动作
```text
请写一份 .tsl 代码:
有一个外部提供的“写日志”动作TSL 中使用的名字由你自己取,它接收一段文本。
这里只需要写出它和外部动作的连接写法,不需要调用。
```
### TSL-091: 包装原生函数指针
```text
请写一份 .tsl 代码:
假设 native_ptr 已经保存了一个原生函数指针。
请按 TSL 支持的方式把它包装成可调用对象,并演示传入两个数字调用。
```
### TSL-092: 后台任务
```text
请写一份 .tsl 代码:
准备一个后台任务,名字由你自己取,里面输出 "work"。
请用线程相关写法启动它,并保持代码尽量小。
```
### TSL-093: FMArray 尺寸
```text
请写一份 .tsl 代码:
创建一个 2 行 3 列的 FMArray。
请输出它是不是 FMArray并输出行数、列数和总尺寸。
```
### TSL-094: 矩阵大小
```text
请写一份 .tsl 代码:
准备一个两行三列的数字矩阵。
请输出它的行数、列数和总尺寸。
```
### TSL-095: 金额对象相加
```text
请写一份 .tsl 代码:
我需要一种“金额盒子”对象,类型名由你自己取,里面有 value。
请让两个这种对象可以直接相加,相加后得到新的同类对象。
脚本里创建两个对象,并输出相加后的 value。
```
### TSL-096: 区分局部和全局功能
```text
请写一份 .tsl 代码:
写一个局部功能,名字故意和某个系统功能一样。
脚本里请分别调用局部功能和全局/系统功能,并输出两次结果。
```
### TSL-097: 关闭默认写回
```text
请写一份 .tsl 代码:
关闭默认的输入写回行为。
请做一个“双值触碰”动作,名字由你自己取:普通输入不要写回,明确标记为 var 的输入要写回。
脚本调用后输出两个变量,证明只有 var 那个改变了。
```
### TSL-098: In 和 Out
```text
请写一份 .tsl 代码:
关闭默认的输入写回行为。
请做一个“同步几个值”的动作,名字由你自己取,接收三个值,并只让 out 标记的值写回。
脚本调用时使用 in 和 out 前缀,然后输出三个变量。
```
### TSL-099: 提前退出
```text
请写一份 .tsl 代码:
请做一个“保护性计算”的功能,名字由你自己取。
如果输入小于 0就直接退出否则给出输入乘以 2 的结果。
脚本里分别用 -1 和 6 调用它,并输出两次结果。
```
### TSL-100: 订单汇总
```text
请写一份 .tsl 代码:
有一批订单行,每行包含商品名、数量、单价。
请做一个“计算单行金额”的功能,名字由你自己取。
遍历所有订单行,数量为 0 的行跳过,其他行累计金额。
如果总金额大于 100输出 "bulk",否则输出 "normal"。
最后输出总金额。
```

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff