tnega 0.1.0 → 0.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (79) hide show
  1. package/README.md +63 -152
  2. package/dist/agent.js +531 -0
  3. package/dist/agent.js.map +7 -0
  4. package/dist/bin.js +3173 -640
  5. package/dist/bin.js.map +4 -4
  6. package/dist/cli-runtime.js +7808 -0
  7. package/dist/cli-runtime.js.map +7 -0
  8. package/dist/core.js +1325 -0
  9. package/dist/core.js.map +7 -0
  10. package/dist/eval.js +2736 -0
  11. package/dist/eval.js.map +7 -0
  12. package/dist/events.js +1194 -0
  13. package/dist/events.js.map +7 -0
  14. package/dist/evolve.js +2487 -0
  15. package/dist/evolve.js.map +7 -0
  16. package/dist/index.js +5019 -2154
  17. package/dist/index.js.map +4 -4
  18. package/dist/llm.js +1008 -0
  19. package/dist/llm.js.map +7 -0
  20. package/dist/services.js +1131 -0
  21. package/dist/services.js.map +7 -0
  22. package/dist/session.js +374 -0
  23. package/dist/session.js.map +7 -0
  24. package/dist/tools.js +2470 -0
  25. package/dist/tools.js.map +7 -0
  26. package/dist/types/packages/agent/src/definition.d.ts +17 -0
  27. package/dist/types/packages/agent/src/index.d.ts +3 -0
  28. package/dist/types/packages/agent/src/service.d.ts +44 -0
  29. package/dist/types/packages/agent/src/types.d.ts +141 -0
  30. package/dist/types/packages/cli/src/bin.d.ts +2 -0
  31. package/dist/types/packages/cli/src/commands.d.ts +122 -0
  32. package/dist/types/packages/cli/src/config.d.ts +26 -0
  33. package/dist/types/packages/cli/src/index.d.ts +7 -0
  34. package/dist/types/packages/cli/src/server.d.ts +12 -0
  35. package/dist/types/packages/cli/src/store.d.ts +59 -0
  36. package/dist/types/packages/cli/src/yaml.d.ts +1 -0
  37. package/dist/types/packages/core/src/context.d.ts +28 -0
  38. package/dist/types/packages/core/src/events.d.ts +54 -0
  39. package/dist/types/packages/core/src/fiber.d.ts +79 -0
  40. package/dist/types/packages/core/src/index.d.ts +9 -0
  41. package/dist/types/packages/core/src/logger.d.ts +48 -0
  42. package/dist/types/packages/core/src/reflect.d.ts +42 -0
  43. package/dist/types/packages/core/src/registry.d.ts +54 -0
  44. package/dist/types/packages/core/src/service.d.ts +19 -0
  45. package/dist/types/packages/core/src/utils.d.ts +54 -0
  46. package/dist/types/packages/eval/src/index.d.ts +5 -0
  47. package/dist/types/packages/eval/src/runner.d.ts +27 -0
  48. package/dist/types/packages/eval/src/service.d.ts +23 -0
  49. package/dist/types/packages/eval/src/strategies.d.ts +48 -0
  50. package/dist/types/packages/eval/src/types.d.ts +185 -0
  51. package/dist/types/packages/eval/src/utils.d.ts +5 -0
  52. package/dist/types/packages/evolve/src/diagnose.d.ts +9 -0
  53. package/dist/types/packages/evolve/src/index.d.ts +7 -0
  54. package/dist/types/packages/evolve/src/llm.d.ts +39 -0
  55. package/dist/types/packages/evolve/src/log.d.ts +26 -0
  56. package/dist/types/packages/evolve/src/select.d.ts +3 -0
  57. package/dist/types/packages/evolve/src/service.d.ts +29 -0
  58. package/dist/types/packages/evolve/src/types.d.ts +176 -0
  59. package/dist/types/packages/llm/src/anthropic-messages.d.ts +4 -0
  60. package/dist/types/packages/llm/src/errors.d.ts +6 -0
  61. package/dist/types/packages/llm/src/index.d.ts +7 -0
  62. package/dist/types/packages/llm/src/models.d.ts +29 -0
  63. package/dist/types/packages/llm/src/openai.d.ts +4 -0
  64. package/dist/types/packages/llm/src/provider.d.ts +3 -0
  65. package/dist/types/packages/llm/src/shared.d.ts +15 -0
  66. package/dist/types/packages/llm/src/types.d.ts +11 -0
  67. package/dist/types/packages/session/src/index.d.ts +115 -0
  68. package/dist/types/packages/tools/src/builtins.d.ts +23 -0
  69. package/dist/types/packages/tools/src/calc.d.ts +4 -0
  70. package/dist/types/packages/tools/src/index.d.ts +90 -0
  71. package/dist/types/packages/tools/src/path.d.ts +4 -0
  72. package/dist/types/packages/tools/src/policy.d.ts +14 -0
  73. package/dist/types/src/events.d.ts +1 -0
  74. package/dist/types/src/index.d.ts +15 -0
  75. package/dist/types/src/services.d.ts +4 -0
  76. package/dist/web/assets/index-C3jFlR4V.css +1 -0
  77. package/dist/web/assets/index-DeFGh2h4.js +268 -0
  78. package/dist/web/index.html +13 -0
  79. package/package.json +63 -10
package/README.md CHANGED
@@ -1,189 +1,100 @@
1
1
  # Tnega
2
2
 
3
- Tnega 是 "agent" 的逆写,也是本项目想做的事:把 Agent 本身当作可以被观察、修改、回滚和进化的对象。
3
+ [中文](docs/zh-CN.md)
4
4
 
5
- Tnega 是一个自研核心的 Agent Harness,参照 DeepSeek Harness 的时空可组合思想,同时把简洁性作为硬约束,并把 Eval 提升为与 Agent Loop、Tools 平级的一等公民。
5
+ **Tnega** is "agent" spelled backwards. It is an eval-first agent harness with spacetime-composable plugin lifecycles: components can be hot-swapped and rolled back safely, and Eval is a first-class citizen on par with the agent loop and tools.
6
6
 
7
- ## 为什么做 Tnega
7
+ ## Install
8
8
 
9
- - Agent = Model + Harness。模型负责思考,Harness 负责模型之外的一切:记忆、工具、权限、执行、评估。
10
- - 大多数 Harness 是固定系统。Tnega 的目标是让 Harness 本身可以被安全地热插拔和回滚,从而为 Agent 自进化提供基础。
11
- - dsh 证明了 "一切皆插件" 可以做到,但整个工程很大。Tnega 自研一个语义完整、体积可控的核心,再叠加薄业务层。
9
+ Requires Node.js >= 22.
12
10
 
13
- ## 核心语义
14
-
15
- - Context:运行环境与作用域树。服务查找沿父链向上,子 Context 可覆盖服务,隔离通过 scope 实现。
16
- - Fiber:插件实例的生命周期。状态为 pending / loading / active / failed / unloading / disposed。
17
- - Effect:每次修改都携带撤销函数,卸载时逆序执行,保证无残留。
18
- - Event:emit / serial / bail / waterfall 四种派发模式,所有扩展点都是事件。
19
-
20
- 时空可组合:
21
-
22
- - 时间可组合:组件可以热插入、热拔出、热替换,失败可回滚。
23
- - 空间可组合:依赖齐备才激活,provider 消失时依赖方先停;不同 scope 拥有不同组合。
24
-
25
- ## 模块规划
26
-
27
- | 包 | 职责 |
28
- | --- | --- |
29
- | core | Context / Fiber / Effect / Event / Registry / Reflect |
30
- | agent | 最小 Agent Loop,作为可替换 service |
31
- | tools | 工具注册与执行管线 |
32
- | session | JSONL 事件日志,支持 replay / fork / compact |
33
- | eval | 评测运行时:策略注册、任务执行、证据收集、判分、持久化 |
34
- | evolve | 进化循环:生成候选、评估、比较、接受或拒绝 |
35
- | llm | OpenAI 兼容 LLM 适配器,默认对接 OpenCode Go DeepSeek |
36
- | cli | headless 命令行入口 |
37
-
38
- ## Eval 是一等公民
39
-
40
- Eval 不是测试工具,而是 runtime 的裁判,也是进化的 fitness function。它与 Agent Loop、Tools 平级,共享同一套 Fiber / Effect / Event 机制。
41
-
42
- 核心对象:
43
-
44
- - EvalStrategy:评测策略,以插件形式注册和卸载。
45
- - Task:任务定义,包含输入、setup、超时与预算。
46
- - Evidence:不可变证据,由 session log 与 artifacts 组成,可 keyless replay。
47
- - Verdict:单个策略对单个任务给出的判分结果。
48
- - EvalRun:一次完整评测,包含候选组件、baseline、verdicts 与 summary。
49
-
50
- 原则:
51
-
52
- - Evidence 是不可变证据:session log + artifacts,重放不需要重新调用模型。
53
- - Strategy 是插件:可注册、可卸载、可热替换。
54
- - Run 是隔离实验:候选组件在独立 scope 中加载,跑完自动卸载。
55
- - Gate 是确定性的:接受或拒绝由阈值、regression、safety 规则决定,而非模型自我评价。
56
-
57
- ## 自进化
58
-
59
- Tnega 把自进化拆成三个可独立验证的阶段:
60
-
61
- 1. 安全变异:core 的时空语义保证组件可以安全地插入、替换、回滚。
62
- 2. 可靠评估:eval 对候选组件运行同一套任务与策略,产生可比较的分数。
63
- 3. 选择与持久化:通过 gate 的候选成为新 baseline,失败的进入 experiment log。
64
-
65
- Experiment log 是一棵树,每个节点包含 candidate、verdicts 与 parent baseline,可回放、可 fork。
66
-
67
- evolve 是进化循环本身:`propose` 根据当前 baseline 的诊断结果生成候选,`evaluate` 在 eval 的隔离 scope 中运行候选,`decide` 用可插拔的 gate 比较 baseline 与 candidate,接受后持久化为新 baseline,拒绝后保留旧 baseline。人工审批通过 `evolve/approval-request` 事件暂停,调用方可以异步 approve / reject。
68
-
69
- ## 与 dsh 的关系
70
-
71
- - 理念参照 DeepSeek Harness 与 Cordis 的时空可组合。
72
- - 核心语义自研,代码自维护,不依赖 Cordis 运行时。
73
- - 暂时不做:Web UI、子代理、插件市场、生产级沙箱、多模态。
74
-
75
- ## 路线图
76
-
77
- - M1:core 时空语义,插件热重载与回滚。
78
- - M2:agent loop + tools + session。
79
- - M3:eval runner 与策略(assert / llm-judge / regression)。
80
- - M4:evolve 进化循环与 experiment log。
81
- - M5:真实 LLM 接入与 `tnega run`。
82
- - M6:时空可组合极端压力测试。
83
- - M7:真实 LLM 自进化闭环。
84
- - M8:最小内置工具集与路径沙箱。
85
- - M9:真实 LLM 工具调用端到端测试。
86
- - M10:npm / pnpm 发布准备,`tnega` 作为自包含 CLI 包可安装。
11
+ ```bash
12
+ npm install -g tnega
13
+ # or
14
+ pnpm add -g tnega
15
+ ```
87
16
 
88
- ## 目录结构(规划)
17
+ ## Quick Start
89
18
 
90
- ```text
91
- packages/
92
- core/ # Context, Fiber, Effect, Event, Registry, Reflect
93
- agent/ # Agent Loop
94
- tools/ # Tool Registry & Execution
95
- session/ # JSONL Session Log
96
- eval/ # Eval Runtime
97
- evolve/ # Evolution Loop
98
- llm/ # OpenAI-compatible LLM Adapter
99
- cli/ # Headless CLI
19
+ ```bash
20
+ export OPENCODE_GO_API_KEY=sk-...
21
+ tnega run "Reply with: hello"
100
22
  ```
101
23
 
102
- ## 使用
24
+ `tnega run` uses OpenCode Go's `deepseek-v4-flash` model through the OpenAI compatible endpoint by default. `minimax-m3` is also available through the Anthropic Messages endpoint. The API key can also come from `~/.tnega/config.json` (Windows: `%USERPROFILE%\.tnega\config.json`) with fields `apiKey`, `model`, `baseUrl`, and `temperature`. Precedence: CLI flags > environment variables > config file > defaults.
103
25
 
104
- 发布后可通过 npm 或 pnpm 全局安装:
26
+ Run a deterministic eval without an API key:
105
27
 
106
- ```text
107
- npm install -g tnega
108
- pnpm add -g tnega
109
- tnega run "prompt"
28
+ ```bash
29
+ tnega eval run examples/tasks.yml
110
30
  ```
111
31
 
112
- 本地开发仍使用 workspace 脚本:
32
+ Start the local web UI:
113
33
 
114
- ```text
115
- pnpm tnega run "prompt" # 运行一次 agent 会话(读取环境变量 key)
116
- pnpm tnega run --allow-network "fetch https://example.com"
117
- pnpm tnega run --allow-shell "list files and summarize"
118
- pnpm tnega eval run tasks.yml # 运行评测
119
- pnpm tnega eval compare a b # 比较两次评测
120
- pnpm tnega evolve run tasks.yml # 运行真实 LLM 自进化闭环
34
+ ```bash
35
+ tnega web
36
+ # http://127.0.0.1:3080
121
37
  ```
122
38
 
123
- 不需要 API key 的快速试用:
39
+ ## CLI
124
40
 
125
41
  ```text
126
- pnpm tnega eval run examples/tasks.yml
42
+ tnega run "prompt" # one agent session
43
+ tnega run --allow-shell "list files" # enable high-permission tools
44
+ tnega web # local web UI
45
+ tnega eval run tasks.yml # run evals
46
+ tnega eval compare <base> <head> # compare two eval runs
47
+ tnega evolve run tasks.yml # run a self-evolution loop
127
48
  ```
128
49
 
129
- ## 真实 LLM 接入
50
+ Options include `--model`, `--base-url`, `--max-tokens`, `--temperature`, `--cwd`, `--session`, `--timeout-ms`, `--max-retries`, and `--retry-delay-ms`. Sessions are recorded as JSONL under `.tnega/`.
130
51
 
131
- `tnega run` 通过 OpenAI 兼容协议调用 OpenCode Go 的 DeepSeek 端点,key 只从环境变量读取,不写入代码或仓库文件:
52
+ ## Built-in Tools
132
53
 
133
- ```text
134
- OPENCODE_GO_API_KEY=sk-xxx pnpm tnega run "Reply with: hello"
135
- ```
54
+ The default tool set is `echo`, `now`, `calculator`, `json`, `read_file`, `write_file`, `list_dir`, `glob`, and `grep`. High-permission tools are opt-in: `http_get` requires `--allow-network`, `shell` requires `--allow-shell`. File and shell tools are confined to the working directory.
136
55
 
137
- 也可以使用 `OPENAI_API_KEY` 或 `DEEPSEEK_API_KEY` 作为兼容变量。默认端点为 `https://opencode.ai/zen/go/v1`,默认模型为 `deepseek-v4-flash`;可通过 `OPENCODE_GO_BASE_URL`、`OPENCODE_GO_MODEL` 或 `--base-url`、`--model`、`--max-tokens`、`--temperature` 覆盖。
56
+ ## Library
138
57
 
139
- 会话记录默认写入 `.tnega/run.jsonl`,可以使用 `--session <file>` 指定位置。
58
+ Tnega is published as a library as well as a CLI. Use the root package or domain subpaths (`tnega/core`, `tnega/agent`, `tnega/eval`, `tnega/evolve`, `tnega/session`, `tnega/tools`, `tnega/llm`, ...):
140
59
 
141
- ## 内置工具
60
+ ```ts
61
+ import { Context, defineAgent, openaiCompatAdapter } from 'tnega'
142
62
 
143
- `tnega run` 默认挂载一个最小内置工具集,每个工具都是普通 `ToolDefinition`,通过 `builtinTools` 插件注册;插件卸载时工具自动注销,符合“工具也是可插拔”的架构。
63
+ const root = new Context()
64
+ const fiber = await root.plugin(
65
+ defineAgent({
66
+ name: 'coding-agent',
67
+ version: '0.1.1',
68
+ system: 'You are a coding agent.',
69
+ }),
70
+ { llm: openaiCompatAdapter({ apiKey: process.env.OPENCODE_GO_API_KEY! }) },
71
+ )
144
72
 
145
- 默认工具:
73
+ const loop = root.get('agentLoop')
74
+ const result = await loop({ text: 'implement the feature' })
75
+ console.log(result.output)
146
76
 
147
- ```text
148
- echo, now, calculator, json,
149
- read_file, write_file, list_dir, glob, grep
77
+ await fiber.dispose()
150
78
  ```
151
79
 
152
- 高权限工具默认不注册:
153
-
154
- - `http_get`:需要 `--allow-network`
155
- - `shell`:需要 `--allow-shell`,工作目录被限制在 `--cwd` 内
80
+ ## Concepts
156
81
 
157
- 文件工具使用路径沙箱:`read_file / write_file / list_dir / glob / grep / shell` 均被限制在 `--cwd` 内,拒绝绝对路径越界、`..` 越界与 symlink 越界。读取默认上限 256 KiB,写入与搜索默认上限 1 MiB,搜索结果默认 200 条,shell 默认 15 秒超时。
82
+ - **Spacetime composability**: components can be inserted, replaced, and removed at runtime; effects are reversed in order on teardown, so hot-swaps leave no residue.
83
+ - **Eval as infrastructure**: strategies, tasks, evidence, verdicts, and runs are pluggable primitives, and evaluation is also the fitness function for self-evolution.
84
+ - **Self-evolution**: `evolve` proposes candidates, evaluates them in isolated scopes, and accepts or rejects them through deterministic gates.
158
85
 
159
- 以插件方式接入时,`builtinTools` 接受 `BuiltinToolsConfig`:`cwd / allowNetwork / allowShell / disabled / maxReadBytes / maxWriteBytes / maxSearchBytes / maxResults / timeoutMs`,`disabled` 可进一步关闭任一内置工具。
86
+ See the [Chinese guide](docs/zh-CN.md) for the detailed design, model pricing table, library contracts, and roadmap.
160
87
 
161
- `tnega evolve run tasks.yml` 把自进化闭环接到真实 LLM:baseline 和候选都由 LLM 驱动,提案规则要求 LLM 返回 JSON 形态的系统提示词候选,评测后由确定性 gate 决定接受或拒绝。实验树默认写入 `.tnega/experiments/log.json`,候选 run 写入 `.tnega/experiments/runs/`,文件中不含 key。
88
+ ## Development
162
89
 
163
- tasks.yml 支持候选声明;没有接入真实 LLM 时可以用内置确定性 loop 跑通完整评测链路:
164
-
165
- ```yaml
166
- tasks:
167
- - id: echo-good
168
- inputText: good
169
- assertion:
170
- expect: good
171
- candidates:
172
- echo:
173
- version: "1"
174
- loop: echo
175
- defaultCandidate: echo
90
+ ```bash
91
+ pnpm install
92
+ pnpm test
93
+ pnpm typecheck
94
+ pnpm lint
95
+ pnpm build
176
96
  ```
177
97
 
178
- ## 状态
179
-
180
- - M1 core 时空语义:已完成。Context / Fiber / Effect / Event / Registry / Reflect 已落地,支持插件热插拔、失败回滚、依赖联动与 scope 隔离,配套 94 个 core 测试。
181
- - M2 agent + tools + session:已完成。SessionLog 以 JSONL 记录可重放的会话事件并支持 fork / compact;ToolsService 提供注册表与可插拔执行管线;AgentService 提供可替换 agentLoop、inbox 与 fake LLM 端到端工具调用,配套 45 个测试。
182
- - M3 eval 评测运行时:已完成。EvalRunner 在隔离子 Context 中加载候选,逐 task 创建独立会话与工具 scope,支持预算、缓存、持久化与 eval/* 事件;策略 assert / llm-judge / regression / all / weighted / gate 可注册、替换和卸载;CLI 支持 `tnega eval run` 与 `tnega eval compare`,配套 29 个测试。
183
- - M4 evolve 进化循环:已完成。Candidate / propose / ExperimentLog 树提供候选生成与可回放实验;selection gate 支持 min-score、safety、退化阈值、显著性规则与审批 seam;确定性多轮闭环验证候选失败不影响主 runtime,配套 11 个 evolve 测试。
184
- - M5 真实 LLM 接入:已完成。`@tnega/llm` 提供 OpenAI 兼容适配器与 `listModels`;`tnega run` 只从环境变量读取 key,支持模型、端点、温度、token 上限与 session 文件参数,配套 OpenAI 协议与 CLI 端到端测试。
185
- - M6 时空可组合极端压力测试:已完成。新增 10 个压力测试,覆盖 100 次热插拔、20 代 provider 替换、128 插件级联、64 scope 隔离、64 fiber 并发挂载卸载、65 次健康检查拨动与 update 风暴。
186
- - M7 真实 LLM 自进化闭环:已完成。`evolve run` 用真实 DeepSeek 驱动 baseline、提案与候选评测,gate 选择后持久化实验树;真实端到端实验与记录见 `docs/test/evolve-llm-e2e.md`。
187
- - M8 最小内置工具集:已完成。`builtinTools` 以插件形式提供 `echo / now / calculator / json / read_file / write_file / list_dir / glob / grep`,`http_get` 与 `shell` 默认关闭,文件与 shell 工具受路径沙箱与字节/结果/超时上限约束;配套 16 个测试。
188
- - M9 真实 LLM 工具调用端到端测试:已完成。mock 端到端 4 个测试覆盖 calculator / http_get / shell / 路径沙箱;真实 DeepSeek 冒烟 3 个测试覆盖 calculator / read_file / shell,session 记录 tool-call 与 tool-result,测试记录见 `docs/test/tools-llm-e2e.md`。
189
- - M10 npm / pnpm 发布准备:已完成。`tnega` 根包发布为公共自包含 CLI,`bin` 指向 esbuild 打包的 `dist/bin.js`,`prepublishOnly` 自动构建并跑发布测试;npm 与 pnpm 本地安装验证通过,测试记录见 `docs/test/npm-publish.md`。
98
+ ## License
99
+
100
+ MIT