@cr1ms0n/pi-subagent 0.10.0 → 0.11.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +8 -1
- package/README.md +11 -101
- package/README.zh-CN.md +42 -132
- package/docs/ARCHITECTURE.md +12 -24
- package/docs/COST-ACCOUNTING.md +6 -7
- package/docs/REFERENCE.md +25 -7
- package/docs/UX.md +8 -12
- package/package.json +1 -1
- package/skills/subagent/SKILL.md +9 -8
- package/src/backend.ts +16 -1
- package/src/extension.ts +33 -15
- package/src/format.ts +98 -3
- package/src/jev-router.ts +56 -16
- package/src/model-failover.ts +445 -0
- package/src/notifications.ts +2 -0
- package/src/orchestrator.ts +522 -303
- package/src/output.ts +9 -4
- package/src/persistence.ts +127 -5
- package/src/policy.ts +26 -3
- package/src/process-lock.ts +16 -0
- package/src/protocol.ts +208 -11
- package/src/registry.ts +33 -7
- package/src/routing-policy.ts +1 -1
- package/src/routing-types.ts +22 -0
- package/src/runner.ts +101 -15
- package/src/schema.ts +3 -3
- package/src/types.ts +88 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,6 +1,13 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
-
##
|
|
3
|
+
## 0.11.0 - 2026-09-22
|
|
4
|
+
|
|
5
|
+
### Probability-ranked Jev failover
|
|
6
|
+
|
|
7
|
+
- Retain validated candidate probabilities and advance to the next eligible model after a recognized availability failure, only before any current-invocation tool execution begins. Unknown activity and task-quality failures do not authorize restart.
|
|
8
|
+
- Select one task-based tool subset for all attempts, resolve thinking per candidate, and verify each attempted model/tool set without another Jev request.
|
|
9
|
+
- Bound all extension-level extra attempts by `max_retries`, candidate exhaustion, the original deadline and cumulative execution budgets. Preserve Pi's internal retries and the trusted unranked SDK fallback contract.
|
|
10
|
+
- Record original and actual models, bounded attempt history and earlier output pointers across status, plan and reload. Preserve failure state and usage without publishing failed structured output or duplicating selector receipts.
|
|
4
11
|
|
|
5
12
|
## 0.10.0 — 2026-09-21
|
|
6
13
|
|
package/README.md
CHANGED
|
@@ -1,124 +1,34 @@
|
|
|
1
|
-
[English](README.md) | [简体中文](README.zh-CN.md)
|
|
2
|
-
|
|
3
1
|
# Pi Smart Subagents
|
|
4
2
|
|
|
5
|
-
|
|
3
|
+
[English](README.md) | [简体中文](README.zh-CN.md)
|
|
6
4
|
|
|
7
|
-
|
|
5
|
+
Run isolated child agents in [Pi](https://pi.dev/), with Jev selecting a model and tools for each task.
|
|
8
6
|
|
|
9
|
-
|
|
7
|
+
An independent community fork of Luke Parke's `@parke.dev/pi-subagent` from [LukasParke/pi-extensions](https://github.com/LukasParke/pi-extensions/tree/main/packages/pi-subagent). It retains the upstream engine's named agents, parallel and background tasks, worktrees and usage accounting, and adds Jev routing with child capability verification.
|
|
10
8
|
|
|
11
9
|
---
|
|
12
10
|
|
|
13
11
|
<a id="quick-start"></a>
|
|
14
|
-
###
|
|
15
|
-
|
|
16
|
-
Use Node.js 22.19.0 or newer and an installed Pi CLI with a working model provider. Pi 0.86.0 is the verified host baseline for enforcing built-in, extension and late-registered tool allowlists. A host that cannot verify the selected capabilities is refused rather than granted more tools.
|
|
17
|
-
|
|
18
|
-
**1. Install the published package.**
|
|
19
|
-
|
|
20
|
-
Install the exact `0.10.0` release. The earlier `0.9.0` release uses the older `apiKeyEnv` configuration contract and does not accept `apiKey`:
|
|
21
|
-
|
|
22
|
-
```bash
|
|
23
|
-
pi install npm:@cr1ms0n/pi-subagent@0.10.0
|
|
24
|
-
```
|
|
25
|
-
|
|
26
|
-
Pi loads the package directly. Do not enable another copy of this extension or `@parke.dev/pi-subagent` together with it: they register the same tools. The package provides `subagent`, `subagent_wait`, `/subagents`, `/subagent-cost` and `/btw`.
|
|
27
|
-
|
|
28
|
-
**2. Store your TypeSafe credential in private configuration.**
|
|
29
|
-
|
|
30
|
-
Set `jevRouting.apiKey` in your user-level `~/.pi/subagent.json`, as shown below. If you are upgrading from `0.9.0`, move the existing value from `jevRouting.apiKeyEnv` to `jevRouting.apiKey` and remove the old field before starting new dispatches. Do not paste the key into chat or repository files. The file stores the key in plaintext: restrict file access and protect backups. See [credential setup](docs/REFERENCE.md#credential-setup) for migration and security details. Provider authentication for the child models is configured separately in Pi.
|
|
31
|
-
|
|
32
|
-
**3. Configure your candidate models.**
|
|
33
|
-
|
|
34
|
-
Add this block to `~/.pi/subagent.json`, preserving unrelated settings. Replace the example model ID with an exact `provider/model-id` available in your Pi installation and write your own model characteristics. Remove any legacy `modelPolicy` block; it is not migrated automatically.
|
|
35
|
-
|
|
36
|
-
```json
|
|
37
|
-
{
|
|
38
|
-
"jevRouting": {
|
|
39
|
-
"selectorModel": "jev-latest",
|
|
40
|
-
"apiKey": "<your-typesafe-api-key>",
|
|
41
|
-
"timeoutMs": 15000,
|
|
42
|
-
"models": [
|
|
43
|
-
{
|
|
44
|
-
"model": "<provider/model-id>",
|
|
45
|
-
"description": "Describe this model's strengths and the tasks you want it to handle."
|
|
46
|
-
}
|
|
47
|
-
]
|
|
48
|
-
}
|
|
49
|
-
}
|
|
50
|
-
```
|
|
51
|
-
|
|
52
|
-
Replace the `apiKey` placeholder with your TypeSafe key and remove any old `apiKeyEnv` field. There is no environment fallback or automatic migration. Candidate descriptions may be written in Chinese. See the [configuration reference](docs/REFERENCE.md#configuration) for optional thinking defaults, profile defaults and limits.
|
|
53
|
-
|
|
54
|
-
Jev selection can incur TypeSafe charges. It receives the delegated task text, model IDs/descriptions, candidate tool names/descriptions and required constraints. It does not automatically upload repository files or conversation history; text you include in the task can still disclose sensitive information. `action: "plan"` also calls Jev, and a later execution selects again.
|
|
55
|
-
|
|
56
|
-
**4. Start Pi and delegate a read-only task.**
|
|
57
|
-
|
|
58
|
-
Start Pi, or reload/restart it after switching extension code. Once `0.10.0` is loaded, each new dispatch re-reads the configuration; changing `apiKey` does not require a shell environment update.
|
|
12
|
+
### Installation
|
|
59
13
|
|
|
60
14
|
```bash
|
|
61
|
-
pi
|
|
62
|
-
```
|
|
63
|
-
|
|
64
|
-
Ask the parent agent to use `subagent` with a request such as:
|
|
65
|
-
|
|
66
|
-
```json
|
|
67
|
-
{
|
|
68
|
-
"task": "Read README.md and summarize what this package does.",
|
|
69
|
-
"description": "Summarize the README",
|
|
70
|
-
"profile": "explore",
|
|
71
|
-
"tools": ["read"],
|
|
72
|
-
"max_turns": 4,
|
|
73
|
-
"timeout_ms": 120000,
|
|
74
|
-
"max_retries": 0
|
|
75
|
-
}
|
|
15
|
+
pi install npm:@cr1ms0n/pi-subagent
|
|
76
16
|
```
|
|
77
17
|
|
|
78
|
-
Omit `model` and `fallback_models`. Jev chooses from your configured model list and permitted tools; a routing failure stops the new dispatch without a fallback. Existing-run management remains available without a routing credential.
|
|
79
|
-
|
|
80
18
|
---
|
|
81
19
|
|
|
82
20
|
<a id="delegation"></a>
|
|
83
|
-
###
|
|
84
|
-
|
|
85
|
-
- **Model and tool routing:** this fork asks Jev to match each task to your model descriptions and select tools individually. Local permission checks and child startup verification enforce the result.
|
|
86
|
-
- **Named agents and parallel work:** the upstream engine supports reusable personas and concurrent child processes. This fork routes each new child through Jev; agent files do not pin its model or tool selection.
|
|
87
|
-
- **Background tasks:** the upstream engine supports status, interruptible waiting, cancellation and steering. The fork's display includes the selected model, with tool details in expanded results.
|
|
88
|
-
- **Isolated edits:** the upstream worktree flow lets you inspect, apply or discard changes without sharing one writable checkout between parallel agents.
|
|
89
|
-
- **Structured results and budgets:** the upstream engine validates structured output parent-side and preserves partial work. This fork keeps retries on the selected model/tool set and accounts for selector tokens separately.
|
|
21
|
+
### Usage
|
|
90
22
|
|
|
91
|
-
|
|
23
|
+
Before your first task, configure your TypeSafe API key and candidate models in `~/.pi/subagent.json`. See the [configuration example](docs/REFERENCE.md#jev-routing).
|
|
92
24
|
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
---
|
|
96
|
-
|
|
97
|
-
<a id="permissions-and-costs"></a>
|
|
98
|
-
### Permissions and costs
|
|
99
|
-
|
|
100
|
-
| Profile | Tool selection | Project-file writes |
|
|
101
|
-
| --- | --- | --- |
|
|
102
|
-
| `explore` | Jev-selected locally permitted read-only tools plus available Pi context controls | No |
|
|
103
|
-
| `review` | Same read-only policy | No |
|
|
104
|
-
| `general` | Jev-selected locally permitted tools plus available Pi context controls | Possible with selected write-capable tools |
|
|
105
|
-
|
|
106
|
-
Single tasks default to `general`; parallel tasks default to `explore`. An explicit `tools` list is a ceiling. Available Pi context-management controls are added locally even with `tools: []`. An empty tool selection never means all tools.
|
|
107
|
-
|
|
108
|
-
Profiles are tool-selection policy, not an OS sandbox. Children inherit the parent environment and can read files accessible to the same user, including the private config. Worktrees isolate the checkout only. Review the [security model](docs/SECURITY.md) before delegating untrusted work.
|
|
109
|
-
|
|
110
|
-
The ledger separates root, subagent, routing and combined usage. TypeSafe reports routing tokens, not currency, so selector cost is **unreported**, not free. `max_cost` limits provider-reported child execution cost; it does not cap TypeSafe fees. See [cost accounting](docs/COST-ACCOUNTING.md) for delivery, retry and branch semantics.
|
|
111
|
-
|
|
112
|
-
New extension-managed dispatch supports the Pi backend only. Native Codex/Claude requests are rejected. The [low-level SDK](docs/REFERENCE.md#using-the-runner-as-a-library) is a separate explicit-spec API: it does not automatically call Jev, and embedding code owns its model/tool choices.
|
|
113
|
-
|
|
114
|
-
---
|
|
25
|
+
Then ask Pi, for example:
|
|
115
26
|
|
|
116
|
-
|
|
117
|
-
### Development
|
|
27
|
+
> Use a read-only subagent to review this project's directory structure and summarize the main modules.
|
|
118
28
|
|
|
119
|
-
|
|
29
|
+
Jev chooses the model and tools. Open `/subagents` to inspect tasks and `/subagent-cost` to view usage.
|
|
120
30
|
|
|
121
|
-
|
|
31
|
+
See the [usage reference](docs/REFERENCE.md#quick-usage) for parallel tasks, background work, worktrees and structured results, or the [TUI guide](docs/UX.md) for keyboard controls.
|
|
122
32
|
|
|
123
33
|
---
|
|
124
34
|
|
package/README.zh-CN.md
CHANGED
|
@@ -1,132 +1,42 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
在 [Pi](https://pi.dev/) 中运行独立子代理,由 Jev
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
pi
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
{
|
|
44
|
-
"model": "<provider/model-id>",
|
|
45
|
-
"description": "Describe this model's strengths and the tasks you want it to handle."
|
|
46
|
-
}
|
|
47
|
-
]
|
|
48
|
-
}
|
|
49
|
-
}
|
|
50
|
-
```
|
|
51
|
-
|
|
52
|
-
将 `apiKey` 占位符替换为自己的 TypeSafe 密钥,并移除旧的 `apiKeyEnv` 字段。扩展不会回退读取环境变量,也不会自动迁移。模型描述可以使用中文。可选的 thinking 默认值、profile 默认值和限制见[配置参考](docs/REFERENCE.md#configuration)。
|
|
53
|
-
|
|
54
|
-
Jev 选择可能产生 TypeSafe 费用。它会接收委派任务文本、模型 ID 与描述、候选工具名称与描述,以及必要约束;不会自动上传仓库文件或对话历史,但任务中主动包含的文本仍可能泄露敏感信息。`action: "plan"` 同样会调用 Jev,之后实际执行时还会重新选择。
|
|
55
|
-
|
|
56
|
-
**4. 启动 Pi,委派一个只读任务。**
|
|
57
|
-
|
|
58
|
-
启动 Pi;如果刚切换扩展代码,需要重新加载或重启。加载 `0.10.0` 后,每次新任务都会重新读取配置,修改 `apiKey` 不需要更新 shell 环境变量。
|
|
59
|
-
|
|
60
|
-
```bash
|
|
61
|
-
pi
|
|
62
|
-
```
|
|
63
|
-
|
|
64
|
-
让主代理使用 `subagent`,例如传入下面的请求:
|
|
65
|
-
|
|
66
|
-
```json
|
|
67
|
-
{
|
|
68
|
-
"task": "Read README.md and summarize what this package does.",
|
|
69
|
-
"description": "Summarize the README",
|
|
70
|
-
"profile": "explore",
|
|
71
|
-
"tools": ["read"],
|
|
72
|
-
"max_turns": 4,
|
|
73
|
-
"timeout_ms": 120000,
|
|
74
|
-
"max_retries": 0
|
|
75
|
-
}
|
|
76
|
-
```
|
|
77
|
-
|
|
78
|
-
不要传入 `model` 或 `fallback_models`。Jev 从配置的模型列表和允许的工具中进行选择;路由失败会阻止本次新任务启动,不会改用兜底方案。已有任务的管理操作不依赖路由凭据。
|
|
79
|
-
|
|
80
|
-
---
|
|
81
|
-
|
|
82
|
-
<a id="delegation"></a>
|
|
83
|
-
### 任务委派
|
|
84
|
-
|
|
85
|
-
- **模型与工具路由:**本分支让 Jev 根据任务和模型描述进行匹配,逐个选择工具;本地权限检查和子进程启动核验负责落实选择结果。
|
|
86
|
-
- **命名代理与并行工作:**上游引擎支持可复用的代理角色和并发子进程。本分支为每个新子代理执行 Jev 路由,代理文件不能固定其模型或工具选择。
|
|
87
|
-
- **后台任务:**上游引擎支持状态查询、可中断等待、取消和中途指导。本分支会显示所选模型,并在展开结果中展示工具详情。
|
|
88
|
-
- **隔离修改:**上游工作树机制支持检查、应用或丢弃改动,避免并行代理共用同一个可写工作区。
|
|
89
|
-
- **结构化结果与预算:**上游引擎在父进程中校验结构化输出,并保留部分工作成果。本分支始终使用已选定的模型和工具集进行重试,单独统计选择器 token。
|
|
90
|
-
|
|
91
|
-
后台任务设置 `async: true`,之后使用 `subagent_wait` 或 `action: "wait"` 收取结果。中断等待或等待超时不会取消子代理,需要停止任务时使用 `action: "cancel"`。通过 `/subagents` 检查任务,通过 `/subagent-cost` 查看用量。
|
|
92
|
-
|
|
93
|
-
[使用参考](docs/REFERENCE.md#quick-usage)涵盖并行任务、结果汇总、恢复与分叉、结构化输出、预算,以及工作树的 diff/apply/discard 操作。[TUI 指南](docs/UX.md)介绍任务查看器和键盘操作。
|
|
94
|
-
|
|
95
|
-
---
|
|
96
|
-
|
|
97
|
-
<a id="permissions-and-costs"></a>
|
|
98
|
-
### 权限与费用
|
|
99
|
-
|
|
100
|
-
| Profile | 工具选择 | 修改项目文件 |
|
|
101
|
-
| --- | --- | --- |
|
|
102
|
-
| `explore` | Jev 选择的本地允许的只读工具,加上可用的 Pi 上下文控制工具 | 不允许 |
|
|
103
|
-
| `review` | 与 explore 相同的只读策略 | 不允许 |
|
|
104
|
-
| `general` | Jev 选择的本地允许的工具,加上可用的 Pi 上下文控制工具 | 选中可写工具时可以修改 |
|
|
105
|
-
|
|
106
|
-
单任务默认使用 `general`,并行任务默认使用 `explore`。显式传入的 `tools` 列表限定候选工具范围。即使传入 `tools: []`,本地仍会补充可用的 Pi 上下文管理工具。工具选择为空绝不表示允许所有工具。
|
|
107
|
-
|
|
108
|
-
Profile 是工具选择策略,不是操作系统沙箱。子进程继承主进程环境,也能读取同一用户有权访问的文件,包括私有配置。工作树只隔离代码工作区。委派不可信任务前,请阅读[安全模型](docs/SECURITY.md)。
|
|
109
|
-
|
|
110
|
-
用量账本分别记录主代理、子代理、路由和合计用量。TypeSafe 只报告路由 token,不报告金额,因此选择器费用标记为**未报告**,不代表免费。`max_cost` 限制子代理执行时由提供方报告的费用,不限制 TypeSafe 费用。结果交付、重试和会话分支的统计规则见[费用统计](docs/COST-ACCOUNTING.md)。
|
|
111
|
-
|
|
112
|
-
扩展管理的新任务只支持 Pi 后端,原生 Codex/Claude 后端请求会被拒绝。[底层 SDK](docs/REFERENCE.md#using-the-runner-as-a-library)是另一套显式任务规格 API,不会自动调用 Jev,嵌入方需要自行负责模型和工具选择。
|
|
113
|
-
|
|
114
|
-
---
|
|
115
|
-
|
|
116
|
-
<a id="development"></a>
|
|
117
|
-
### 开发
|
|
118
|
-
|
|
119
|
-
源码是使用 peer dependencies 的独立 TypeScript 包,没有构建步骤,也没有随仓库提供的测试运行器或类型检查脚本。本仓库支持的检查方式见[开发与验证](docs/DEVELOPMENT.md)。语法转换不等于语义类型检查;`npm pack --dry-run --ignore-scripts --json` 用于检查打包内容,不会发布包。
|
|
120
|
-
|
|
121
|
-
[架构约定](docs/ARCHITECTURE.md)记录模块职责和不变量。[发布维护](docs/RELEASING.md)说明如何选择性更新源码,以及需要单独明确授权的 npm 发布流程。
|
|
122
|
-
|
|
123
|
-
---
|
|
124
|
-
|
|
125
|
-
<a id="license"></a>
|
|
126
|
-
### 许可证
|
|
127
|
-
|
|
128
|
-
[MIT](LICENSE)。Copyright (c) 2026 Luke Parke。社区分支由 cr1ms0n(awoaCrim)维护。重新分发时请保留原始版权声明和许可证。
|
|
129
|
-
|
|
130
|
-
译自 [README.md](README.md),英文文件 blob:`02294faabd946a50be23551e43e694451628bc39`。中英文内容如有差异,以英文为准。
|
|
131
|
-
|
|
132
|
-
感谢 [Linux.do](https://linux.do/)。
|
|
1
|
+
# Pi Smart Subagents
|
|
2
|
+
|
|
3
|
+
[English](README.md) | [简体中文](README.zh-CN.md)
|
|
4
|
+
|
|
5
|
+
在 [Pi](https://pi.dev/) 中运行独立子代理,由 Jev 为每项任务选择模型和工具。
|
|
6
|
+
|
|
7
|
+
本项目是 Luke Parke 的 `@parke.dev/pi-subagent` 的独立社区分支,上游来自 [LukasParke/pi-extensions](https://github.com/LukasParke/pi-extensions/tree/main/packages/pi-subagent)。保留上游的命名代理、并行与后台任务、工作树和用量统计,增加 Jev 路由与子代理能力核验。
|
|
8
|
+
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
<a id="quick-start"></a>
|
|
12
|
+
### 安装
|
|
13
|
+
|
|
14
|
+
```bash
|
|
15
|
+
pi install npm:@cr1ms0n/pi-subagent
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
---
|
|
19
|
+
|
|
20
|
+
<a id="delegation"></a>
|
|
21
|
+
### 使用
|
|
22
|
+
|
|
23
|
+
首次使用前,在 `~/.pi/subagent.json` 中配置 TypeSafe API key 和候选模型,见[配置示例](docs/REFERENCE.md#jev-routing)。
|
|
24
|
+
|
|
25
|
+
然后直接对 Pi 说,例如:
|
|
26
|
+
|
|
27
|
+
> 用只读子代理查看这个项目的目录结构,并总结主要模块。
|
|
28
|
+
|
|
29
|
+
Jev 会选择模型和工具。使用 `/subagents` 查看任务,使用 `/subagent-cost` 查看用量。
|
|
30
|
+
|
|
31
|
+
并行任务、后台执行、工作树和结构化结果见[使用参考](docs/REFERENCE.md#quick-usage),键盘操作见 [TUI 指南](docs/UX.md)。
|
|
32
|
+
|
|
33
|
+
---
|
|
34
|
+
|
|
35
|
+
<a id="license"></a>
|
|
36
|
+
### 许可证
|
|
37
|
+
|
|
38
|
+
[MIT](LICENSE)。Copyright (c) 2026 Luke Parke。社区分支由 cr1ms0n(awoaCrim)维护。重新分发时请保留原始版权声明和许可证。
|
|
39
|
+
|
|
40
|
+
译自 [README.md](README.md),英文文件 blob:`f55b496dc010bd4242e6f6ffc8c987425ee9d7f4`。中英文内容如有差异,以英文为准。
|
|
41
|
+
|
|
42
|
+
感谢 [Linux.do](https://linux.do/)。
|
package/docs/ARCHITECTURE.md
CHANGED
|
@@ -12,10 +12,7 @@
|
|
|
12
12
|
after a second window so retry can take over. Group kills verify process start-time
|
|
13
13
|
identity (Linux `/proc`, macOS/BSD `ps lstart`) before signalling a possibly-recycled
|
|
14
14
|
PID; transcript joins happen only on message boundaries, not per-chunk ticks.
|
|
15
|
-
- Retry lives in
|
|
16
|
-
errors, and provider errors re-run the same already-selected spec (model and tool set)
|
|
17
|
-
with accumulated usage; there is no fallback-model escalation, and task-quality failures
|
|
18
|
-
never retry.
|
|
15
|
+
- Retry lives in [orchestrator.ts](../src/orchestrator.ts). Ranked extension tasks advance through a locally finalized Jev candidate plan only for recognized settled availability failures before any current-invocation tool starts. [model-failover.ts](../src/model-failover.ts) owns conservative evidence classification and bounded attempt helpers. Tools stay fixed, thinking resolves per candidate, and usage accumulates once. Unknown execution evidence blocks restart. The trusted unranked SDK retains its separate `isTransientFailure` and explicit fallback contract.
|
|
19
16
|
- `context: "fork"` spawns the child with `--fork <parent session file>` so it starts
|
|
20
17
|
from a real branched copy of the parent conversation. Fail-fast when the parent
|
|
21
18
|
session is not persisted; single-task only.
|
|
@@ -24,7 +21,7 @@
|
|
|
24
21
|
- `semaphore.ts`: per-parent-runtime child-process limit.
|
|
25
22
|
- `process-lock.ts`: machine-wide durable coordination under `~/.pi/subagent-locks/` —
|
|
26
23
|
exclusive per-child-session resume locks, global concurrency slots, and run process
|
|
27
|
-
identity records for orphan reconcile.
|
|
24
|
+
identity records for orphan reconcile. Ranked tasks keep one record running across attempts and final artifact/worktree work; the orchestrator terminalizes it once. A bounded list of attempt sessions protects earlier transcripts from other parents' maintenance while the task is live.
|
|
28
25
|
- `launch.ts`: resolve the child `pi` invocation via `PI_SUBAGENT_BIN` or
|
|
29
26
|
`process.execPath` + CLI entry (bare PATH name only as last-resort fallback).
|
|
30
27
|
- `persistence.ts`: versioned active-branch event folding, the bounded routing-event decoder
|
|
@@ -38,14 +35,12 @@
|
|
|
38
35
|
shapes and local resource limits; `routing-policy.ts` owns the strict `jevRouting`
|
|
39
36
|
parser, the candidate intersection with locally available models, and the injected
|
|
40
37
|
model-facing guidance; `jev-router.ts` owns the injectable TypeSafe transport,
|
|
41
|
-
response validation, deadlines and per-request receipts; `dispatch-routing.ts`
|
|
42
|
-
resolves every worker before any launch and refuses a partially selected fanout. The
|
|
43
|
-
router has no engine imports and makes no parent UI calls.
|
|
38
|
+
response validation, deadlines and per-request receipts, including a validated full probability ranking and model-independent task tool decisions; `dispatch-routing.ts` resolves every worker before any launch and refuses a partially selected fanout. Local policy finalizes a frozen candidate attempt plan with per-model thinking and one shared tool set. The router has no engine imports and makes no parent UI calls.
|
|
44
39
|
- `config.ts`: defaults ← `~/.pi/subagent.json` ← `PI_SUBAGENT_*` env overrides.
|
|
45
40
|
- `structured.ts`: structured-output contract (dependency-free JSON-Schema subset
|
|
46
41
|
validation, fenced json:result extraction, contract/repair prompts) and
|
|
47
42
|
conservative double-encoded-arg repair. The runner gates the child's settle on
|
|
48
|
-
validation and runs one steer-based repair round
|
|
43
|
+
validation and runs one steer-based repair round after an otherwise successful invalid answer. Ranked provider-error/aborted attempts skip repair and cannot publish structuredOutput from failed text. The latest completed assistant text replaces earlier text even when empty, so a host retry cannot reuse the failed turn's JSON.
|
|
49
44
|
- `agents.ts`: named agent files (`.pi/agents/`, `.agents/agents/`, global agent dir).
|
|
50
45
|
Flat-YAML frontmatter + markdown persona body; resolved in policy with explicit
|
|
51
46
|
params > agent file > profile taskDefaults > parent inheritance. Catalog refreshes
|
|
@@ -80,7 +75,7 @@ Invariants:
|
|
|
80
75
|
Selector usage is a separate category folded once per selector request ID, with currency
|
|
81
76
|
reported as unreported rather than inferred.
|
|
82
77
|
11. Checkpoint persistence events are lightweight (state, usage, process identity, pointers).
|
|
83
|
-
Full transcripts and final output are persisted exactly once, in the terminal event.
|
|
78
|
+
Full transcripts and final output are persisted exactly once, in the terminal event. Ranked attempt histories carry bounded metadata/session pointers at checkpoints, with output previews only in terminal projections (1 KiB per preview, 16 KiB total). Active-branch retention includes earlier attempt session references.
|
|
84
79
|
12. High-frequency registry "changed" events coalesce (trailing window); state transitions,
|
|
85
80
|
new child sessions, billed-usage advances, and terminal events flush immediately.
|
|
86
81
|
13. `wait` is interruptible: aborting a wait returns promptly and does NOT cancel the
|
|
@@ -108,18 +103,14 @@ Invariants:
|
|
|
108
103
|
20. Budget breaches (`max_turns`/`max_cost`) steer a wrap-up message and allow grace
|
|
109
104
|
turns before SIGTERM; a child that concludes within grace ends `partial` with
|
|
110
105
|
`wrappedUp: true`. `graceTurns: 0` restores immediate stops.
|
|
111
|
-
21.
|
|
112
|
-
truncation) retry up to `maxRetries` extra attempts on the already selected model and
|
|
113
|
-
tool set; there is no fallback-model escalation and no reselection. Usage accumulates
|
|
114
|
-
across attempts. Task-quality failures (nonzero exit with complete protocol,
|
|
115
|
-
cancellation, budget stop, running timeout) never retry.
|
|
106
|
+
21. Extension-managed ranked tasks permit at most `maxRetries` extra child attempts, locally capped at 255 total launches. A recognized settled availability failure advances to the next candidate only with conclusive no-tool activity; started or unknown activity blocks all new-child restart. Candidate exhaustion never wraps to the primary. Conclusively pre-work infrastructure retry may repeat the same candidate within the same budget. No retry calls Jev or broadens tools. Usage and budget comparisons include prior attempts. Authentication, quota/billing, invalid requests, context limits, task-quality, cancellation, task-deadline and budget stops do not cause model failover. The trusted unranked SDK keeps its legacy transient/explicit-fallback behavior.
|
|
116
107
|
22. The stall watchdog treats protocol silence as suspect, not fatal: after
|
|
117
108
|
`stallAfterMs` the task is flagged and probed via `get_state` (a live child's
|
|
118
109
|
answer clears the flag); only continued silence for `stallKillAfterMs` more kills
|
|
119
|
-
the child
|
|
110
|
+
the child. A stall does not authorize restart on the ranked path: silence cannot establish that no work began.
|
|
120
111
|
23. Only `async: true` runs notify on completion and appear in the ambient widget.
|
|
121
112
|
Notification delivery respects delivered-once: a `wait` that consumed the run
|
|
122
|
-
suppresses the notification.
|
|
113
|
+
suppresses the notification. The actual final model and a bounded attempt-chain tail with its total count use the same display projection as compact results.
|
|
123
114
|
24. Named agent files supply per-field defaults only; explicit request params always
|
|
124
115
|
win, and capability profiles fail closed regardless of what an agent file declares.
|
|
125
116
|
25. Structured-output validation never discards paid work: schema failure after the
|
|
@@ -137,11 +128,9 @@ Invariants:
|
|
|
137
128
|
local preflights of a real spawn and returns the resolved plan and its selector usage
|
|
138
129
|
without spawning. It creates no registry entry, and its fee-bearing selection is not
|
|
139
130
|
cached for a later dispatch.
|
|
140
|
-
29. Every new extension-managed
|
|
131
|
+
29. Every new extension-managed invocation (`task`/`tasks[]`, `action:"plan"`, `/btw`,
|
|
141
132
|
resume, fork, nested dispatch and the optional synthesis child) crosses one selector
|
|
142
|
-
interface before any child starts. The dedicated candidate list intersected with
|
|
143
|
-
locally available models is the only source of execution models; the full locally
|
|
144
|
-
permitted tool catalog is the only candidate source. Legacy `model`/`fallback_models`
|
|
133
|
+
interface before any child starts. The dedicated candidate list intersected with locally available models is the only source of execution models. One validated full probability ranking belongs to the invocation, and fallback reuses it without another selection. The original selectedModel/confidence remain immutable; result.model reports the actual attempt. The full locally permitted tool catalog is the only tool candidate source, and one model-independent selection is shared by every attempt. Legacy `model`/`fallback_models`
|
|
145
134
|
fields are rejected on new work, and an empty selected tool set never becomes
|
|
146
135
|
inheritance or "all tools".
|
|
147
136
|
30. The finalized tool subset is passed to the child as Pi's `--tools` allowlist
|
|
@@ -154,13 +143,12 @@ Invariants:
|
|
|
154
143
|
the nonce-specific bootstrap command exists from the expected package source, then
|
|
155
144
|
requires the child to acknowledge the exact selected model and finalized tool names
|
|
156
145
|
(including nested-tool source) before the real task prompt is sent. Missing or
|
|
157
|
-
mismatched acknowledgement is a capability/startup diagnostic, never compensated by
|
|
158
|
-
broadening tools or choosing another model.
|
|
146
|
+
mismatched acknowledgement is a capability/startup diagnostic, never compensated by broadening tools or choosing another model. Every ranked replacement gets its own exact-model/shared-tools acknowledgement before the task prompt.
|
|
159
147
|
31. An absolute task deadline is created before preflight/selection, and routing, setup,
|
|
160
148
|
queue and retries all count against it. Pending selector work is tracked per session
|
|
161
149
|
runtime, aborted on cancellation, shutdown or session switch, and every post-await
|
|
162
150
|
transition re-checks captured runtime/session ownership so a late response cannot
|
|
163
|
-
launch into a replaced session.
|
|
151
|
+
launch into a replaced session. Replacement attempts await prior child cleanup, retain run/worktree/resume ownership and recheck cancellation, deadline and cumulative task budgets before launch. Durable task records remain running during replacement and finalization, protecting all known attempt sessions and the worktree across parent processes; only child slots are released per attempt. Pi/provider internal retries and global retry settings remain unchanged.
|
|
164
152
|
32. Before any paid selection, plan and dispatch share a side-effect-free direct-resume
|
|
165
153
|
availability check (in-memory owner, `resumeBlocked`, durable lock ownership and
|
|
166
154
|
staleness) that acquires, renews or reaps nothing. Dispatch still takes the
|
package/docs/COST-ACCOUNTING.md
CHANGED
|
@@ -44,9 +44,7 @@ own record, and all of them count once by full request ID. Plan selections and
|
|
|
44
44
|
pre-spawn failures are included, because no child run exists to carry them.
|
|
45
45
|
|
|
46
46
|
Successful route metadata (decision ID, selector model and reported version(s),
|
|
47
|
-
selected
|
|
48
|
-
success outcome, latency and receipt IDs) travels with the run and both registry
|
|
49
|
-
projections. Per-request failure outcomes and safe error codes stay in selector receipts. It carries no descriptions, raw request bodies, headers,
|
|
47
|
+
original selected model, ranked candidate probabilities, shared selected tools, locally added control-plane tools, confidence, success outcome, latency and receipt IDs) travels with the run and both registry projections. Actual attempt models are recorded separately; fallback never rewrites the initial selection as a new decision. Per-request failure outcomes and safe error codes stay in selector receipts. It carries no descriptions, raw request bodies, headers,
|
|
50
48
|
credentials or invented rationale.
|
|
51
49
|
|
|
52
50
|
Receipts pending append visibility remain in a bounded session-local overlay until the
|
|
@@ -79,10 +77,7 @@ Because the native footer counts parent assistant messages plus delivered tool-r
|
|
|
79
77
|
4. If an old run is evicted from in-memory UI history, its latest persisted usage still contributes to the session ledger.
|
|
80
78
|
5. Active and immediately completed runs supplement or replace stale persisted checkpoints until newer session entries become visible; the full run UUID prevents double counting afterward.
|
|
81
79
|
6. Resumed and forked invocations are distinct billed runs. Their new provider usage is counted once, even though they reuse prior context.
|
|
82
|
-
7.
|
|
83
|
-
accumulate into their run's single usage record: every attempt's billed usage counts once
|
|
84
|
-
under one run UUID. There is no fallback-model escalation, so `attemptedModels` repeats the
|
|
85
|
-
selected model rather than recording a route change.
|
|
80
|
+
7. Ranked failover and permitted same-model pre-work retries accumulate into one run usage record. Every attempt's provider-reported usage counts once under the same run UUID; attempted-model metadata is descriptive, not another ledger input. Advancing to a ranked candidate makes no additional selector request and creates no new receipt. The initial selector decision remains distinct from the actual execution model.
|
|
86
81
|
8. The optional parallel `synthesis` child bills into the same run as an extra result.
|
|
87
82
|
9. Selector requests are counted once by full selector request ID, including plan
|
|
88
83
|
requests and pre-spawn rejected decisions. Route references inside task results
|
|
@@ -106,6 +101,10 @@ Only `sessionManager.getBranch()` is used. Costs from abandoned sibling branches
|
|
|
106
101
|
|
|
107
102
|
Any usage reported before a failure, timeout, budget stop, cancellation, or parent crash is retained in a cumulative checkpoint/terminal record. A run with no provider response contributes zero rather than an estimate.
|
|
108
103
|
|
|
104
|
+
All ranked attempts share the absolute task deadline and cumulative `max_cost`/`max_turns` budget. Prior usage is an offset for the next child's budget comparisons, not part of that child's returned usage, so aggregation adds each attempt only once. A replacement cannot start after reported cost or turns meets its ceiling. In-attempt completed-turn checks and wrap-up grace remain unchanged. Pi's internal provider retries are not counted as separately launched extension attempts.
|
|
105
|
+
|
|
106
|
+
When every attempt fails, earlier output previews retain their originating model/session and the final task remains failed. Preserving billed work does not convert failure into `partial` or success. The existing native undercount for thrown failures still applies; the extension ledger retains all reported attempt usage.
|
|
107
|
+
|
|
109
108
|
## Provider limitations
|
|
110
109
|
|
|
111
110
|
Accounting is only as precise as the provider data normalized by Pi:
|
package/docs/REFERENCE.md
CHANGED
|
@@ -6,7 +6,7 @@ Return to the [English README](../README.md) or [Chinese README](../README.zh-CN
|
|
|
6
6
|
|
|
7
7
|
### Credential setup
|
|
8
8
|
|
|
9
|
-
Version `0.10.0`
|
|
9
|
+
Version `0.10.0` and later read the TypeSafe key from `jevRouting.apiKey` in your private, user-level `~/.pi/subagent.json`. Set the key locally using an editor, preserve unrelated configuration and replace the placeholder in the [routing example](#jev-routing). Do not paste the key into chat, shell commands, source control or task descriptions.
|
|
10
10
|
|
|
11
11
|
This file stores the credential in plaintext. Restrict access to your user account and protect editor backups and synchronized copies. Same-user processes, including children with filesystem access, may read it; neither profiles nor worktrees provide an OS sandbox. See [SECURITY](SECURITY.md#routing-disclosure-and-credentials).
|
|
12
12
|
|
|
@@ -105,7 +105,7 @@ A plan runs local preflights and Jev selection without spawning a child or creat
|
|
|
105
105
|
|
|
106
106
|
#### Structured output
|
|
107
107
|
|
|
108
|
-
The child must produce a fenced `json:result` block matching the requested schema.
|
|
108
|
+
The child must produce a fenced `json:result` block matching the requested schema. After an otherwise successful answer, the parent validates it and allows one repair round. An unresolved schema failure preserves raw output as a partial result rather than discarding paid work. A terminal provider failure does not trigger a repair prompt or publish a structured result, even if its text contains valid JSON; it follows the availability-failure rules instead.
|
|
109
109
|
|
|
110
110
|
```json
|
|
111
111
|
{
|
|
@@ -144,7 +144,9 @@ Both operations select again. To guide an existing child instead, steer it; para
|
|
|
144
144
|
|
|
145
145
|
#### Budgets and retries
|
|
146
146
|
|
|
147
|
-
A budget breach requests a final answer and allows the configured grace turns.
|
|
147
|
+
A budget breach requests a final answer and allows the configured grace turns. Before any tool starts, a recognized model-availability failure can advance to the next candidate in Jev probability order. All attempts share the selected tools, task deadline and cumulative execution budgets. Switching does not call Jev again.
|
|
148
|
+
|
|
149
|
+
`max_retries` is the total number of extra child attempts: `0` permits the initial attempt only, `1` permits at most two attempts, and `2` permits at most three. The built-in default is `1`; task, agent, profile and configuration overrides still apply. The list never wraps back to an earlier candidate. Pi's own in-process/provider retries are separate and unchanged, so a child can make multiple provider requests before the extension sees its final failure. See [ranked failover](#probability-ranked-failover) for the failure boundary.
|
|
148
150
|
|
|
149
151
|
```json
|
|
150
152
|
{ "task": "Audit dependencies.", "profile": "review", "max_turns": 15, "grace_turns": 2, "max_retries": 1 }
|
|
@@ -319,6 +321,22 @@ The extension re-reads `jevRouting` on each dispatch and injects non-secret rout
|
|
|
319
321
|
|
|
320
322
|
The mandatory routing above is the Extension dispatch contract. The stable SDK exports (`runTasks` and `runSubagent`) are trusted low-level library APIs: they execute the explicit `TaskSpec` you pass and perform no implicit routing, config discovery or network call. Library callers own model and tool choice, and must not read these SDK calls as Jev enforcement.
|
|
321
323
|
|
|
324
|
+
#### Probability-ranked failover
|
|
325
|
+
|
|
326
|
+
Version `0.11.0` adds this behavior. Published `0.10.0` retries the selected model rather than advancing through the ranked candidates.
|
|
327
|
+
|
|
328
|
+
TypeSafe's Choice response includes a probability for every eligible option. The extension retains that distribution and tries higher-probability candidates first. These values express the selector's preference, not measured model uptime or success rates. The separate `confidence` value belongs to the original answer. A tied maximum keeps Jev's returned choice first; other ties follow configured candidate order. Low or zero probability is not a new exclusion threshold.
|
|
329
|
+
|
|
330
|
+
Jev selects one task-based tool subset, independent of the first execution model, for every attempt. The initial logical selection may use several HTTP batches; failover adds none. Each candidate still gets its own thinking default under the existing precedence and fresh exact-model/tool startup verification. An attestation mismatch stops the task instead of trying a broader capability set.
|
|
331
|
+
|
|
332
|
+
Switching requires a settled provider error and conclusive evidence that no tool execution has begun in this invocation. Recognized cases include an explicitly unavailable model, temporary throttling, service overload and identifiable transport failures. Authentication/configuration errors, quota or billing exhaustion, invalid requests, context limits, refusals, poor answers, schema failures, cancellation and exhausted budgets do not trigger a model switch. Recognition uses only the latest completed assistant error's bounded message and documented primitive `diagnostics.error.code`, never ordinary answer text or arbitrary diagnostic details. Authentication, quota and other excluded evidence take precedence over an availability code. Unfamiliar error formats stop conservatively. A tool-start event blocks restart even when no result arrived; missing or malformed protocol evidence is not permission to retry. Historical tool messages in a resumed or forked session are not new execution.
|
|
333
|
+
|
|
334
|
+
For an eligible failure, the next allowed extension attempt advances immediately to the next candidate; it does not first add a same-model retry. Conclusively pre-work local process failures can retry the same candidate under the same total attempt budget. Attempts also have a local resource ceiling of 255 launches, including infrastructure retries. Expired task deadlines, uncertainty after startup and stalls cannot be used to restart work that may have begun. Pi's internal retries remain enabled or disabled according to your existing Pi settings, which this extension does not change.
|
|
335
|
+
|
|
336
|
+
Plan and status distinguish the original selector choice from the actual execution model. Results retain bounded attempt metadata, failure categories, output previews and child-session pointers; previews are attributed to the attempt that produced them. A later successful structured answer is not concatenated with failed JSON. If Pi retries within the same child, an empty latest answer stays empty; it never reuses text or JSON from the failed turn. If all attempts fail, the final failure/model/session remain authoritative. Earlier output remains available while its session is referenced on the active branch. Usage accumulates under the same run, without duplicating selector receipts; existing native-accounting limitations for thrown failures still apply.
|
|
337
|
+
|
|
338
|
+
A selector timeout or invalid response still stops dispatch. Failover uses only the validated ranking from that invocation, never an emergency model or a new selection. New invocations, including resume/fork and synthesis, select afresh. Trusted SDK specs without a ranked route retain their existing explicit fallback behavior.
|
|
339
|
+
|
|
322
340
|
#### Named agent files
|
|
323
341
|
|
|
324
342
|
Define reusable subagent personas as markdown files, discovered from the same conventional roots skills use (higher root wins name conflicts):
|
|
@@ -364,10 +382,10 @@ Notes on behavior:
|
|
|
364
382
|
|
|
365
383
|
- `timeout_ms` is the absolute task deadline: local preflight, Jev selection, setup, queue time and runtime all count against it, and selection cannot reset it. Timed-out tasks report `state: "timeout"` with `timeoutPhase: "queued"|"starting"|"running"` so agents can retry capacity issues without confusing them for task failures.
|
|
366
384
|
- Budget stops (`max_turns`, `max_cost`) trigger a **graceful wrap-up**: the child is steered to produce its final answer NOW and allowed `graceTurns` more turns before SIGTERM. Results end as `partial` with `wrappedUp: true` when the child concluded in time. `graceTurns: 0` restores immediate stops.
|
|
367
|
-
- A **stall watchdog** flags children with no protocol activity for `stallAfterMs` (a liveness probe distinguishes quiet-but-thinking from dead), then kills after `stallKillAfterMs` more silence
|
|
368
|
-
- **
|
|
385
|
+
- A **stall watchdog** flags children with no protocol activity for `stallAfterMs` (a liveness probe distinguishes quiet-but-thinking from dead), then kills after `stallKillAfterMs` more silence. A stall is not proof that no tool ran and does not authorize ranked failover.
|
|
386
|
+
- **Ranked failover** follows the [availability and pre-tool rules](#probability-ranked-failover), bounded by total `maxRetries`, candidate exhaustion, cumulative budgets and the original deadline. A selector failure has no emergency fallback. Task-quality, cancellation and budget failures never trigger model reselection.
|
|
369
387
|
- `context: "fork"` starts a single child from a real branched copy of the parent conversation (`--fork` on the parent's session file). It requires a persisted parent session, cannot combine with `resume`, and is rejected for parallel fanout (context duplication × N is a cost bug, not a feature).
|
|
370
|
-
- **Structured output** (`output_schema`): the contract is appended to the child's system prompt; the final message must end with a fenced `json:result` block. Validation runs parent-side against a dependency-free JSON-Schema subset (type/properties/required/items/enum/const; unknown keywords are ignored, never rejected).
|
|
388
|
+
- **Structured output** (`output_schema`): the contract is appended to the child's system prompt; the final message must end with a fenced `json:result` block. Validation runs parent-side against a dependency-free JSON-Schema subset (type/properties/required/items/enum/const; unknown keywords are ignored, never rejected). An otherwise successful but invalid answer gets **one steer-based repair round**; still-invalid results end `partial` with `structuredError` and raw text retained. Failed provider attempts neither repair nor publish structured output. Validated successful parallel results feed the `synthesis` child as clean JSON instead of prose.
|
|
371
389
|
- **Arg repair**: double-encoded task text (literal `\n` / `\"` escapes from LLM re-encoding) is conservatively de-mangled once at validation time. Identifier fields and paths are never touched. Protocol streams truncated after useful assistant output also end as `partial`.
|
|
372
390
|
- Aborting a `wait` returns immediately without cancelling the background run.
|
|
373
391
|
- Child processes are launched via the same Node runtime + CLI entry as the parent when possible (`PI_SUBAGENT_BIN` overrides). Bare `pi` on PATH is only a logged last resort.
|
|
@@ -427,7 +445,7 @@ The Pi extension entry is unchanged: package `pi.extensions` still points at `./
|
|
|
427
445
|
|
|
428
446
|
`status`, `/subagent-cost`, and the `/subagents` overlay header show separate **root**, **subagent**, **routing**, and **combined** totals based on provider-reported usage. On Pi builds after v0.80.10, delivered runs also report their total usage natively on the tool result ([pi#6671](https://github.com/earendil-works/pi/pull/6671)), so Pi's own footer, `/session`, and RPC totals include subagent spend exactly once per run. Older Pi hosts ignore the field. Nested usage reported by a child's tool results (e.g. grandchild subagents) folds into the run's totals and budgets. The extension footer stays terse (running/ready counts only). Delivery and replay do not double count runs. See [docs/COST-ACCOUNTING.md](COST-ACCOUNTING.md).
|
|
429
447
|
|
|
430
|
-
Jev selection is billed separately from execution. TypeSafe reports tokens, not currency, so the ledger shows routing tokens as their own category, counts each selector request once by its request ID (including plan and pre-spawn failures), and marks routing cost as **unreported** rather than free. Numeric dollar totals exclude unreported routing spend, and `max_cost` caps provider-reported execution cost only; it does not cap TypeSafe charges. Route metadata (selected model, selected tools, locally added controls, selector version, confidence, outcome, latency) travels with the run alongside usage.
|
|
448
|
+
Jev selection is billed separately from execution. TypeSafe reports tokens, not currency, so the ledger shows routing tokens as their own category, counts each selector request once by its request ID (including plan and pre-spawn failures), and marks routing cost as **unreported** rather than free. Numeric dollar totals exclude unreported routing spend, and `max_cost` caps provider-reported execution cost only; it does not cap TypeSafe charges. Route metadata (original selected model, ranked probabilities, selected tools, locally added controls, selector version, confidence, outcome, latency) travels with the run alongside usage. Actual attempt models are recorded separately; advancing through the ranking does not create another selector receipt.
|
|
431
449
|
|
|
432
450
|
---
|
|
433
451
|
|
package/docs/UX.md
CHANGED
|
@@ -41,14 +41,9 @@ The standalone pi-subagent provides rich TUI support for monitoring, inspecting,
|
|
|
41
41
|
per-task stats, and a one-line tail (live activity or first output line).
|
|
42
42
|
- Expanded (Ctrl+O / `app.tools.expand`): full task output capped with a dim
|
|
43
43
|
`… +N lines` trailer pointing at the artifact/child session.
|
|
44
|
-
- Expanded detail adds
|
|
45
|
-
execution model, selected tools (plus locally added control-plane tools),
|
|
46
|
-
selector version, confidence, outcome and selection latency. Legacy runs
|
|
47
|
-
simply have no route line.
|
|
44
|
+
- Expanded detail adds a bounded route summary for Jev-routed runs: original selection, ranked probabilities, shared selected tools (plus locally added control-plane tools), selector version, answer-level confidence, outcome and selection latency. The actual execution model stays separate from the original choice. Large lists show a preview and total count; old runs without new fields remain readable. Compact results and completion notifications show at most the last five attempt models and label a shortened chain with its total attempt count.
|
|
48
45
|
- Durations freeze at `endedAt`; running durations tick at render time.
|
|
49
|
-
- Reliability annotations render inline: `[attempt 2]` during a
|
|
50
|
-
retry, `[stalled 2m]` while the stall watchdog is flagging silence, and
|
|
51
|
-
`◐ wrapped up` on budget-stopped runs that concluded gracefully.
|
|
46
|
+
- Reliability annotations render inline: `[attempt 2]` during retry/failover, the actual attempt model and bounded attempt chain, `[stalled 2m]` while the stall watchdog is flagging silence, and `◐ wrapped up` on budget-stopped runs that concluded gracefully. Availability failures can switch models only before tools begin; a stalled indicator is not a promise of another attempt.
|
|
52
47
|
|
|
53
48
|
### Footer status
|
|
54
49
|
Terse and actionable only: `⚙ 2 running · 1 ready · /subagents`. Cleared when
|
|
@@ -80,6 +75,7 @@ text with run ids and a `wait { id }` pointer.
|
|
|
80
75
|
failures bypass batching and flush immediately, carrying held successes.
|
|
81
76
|
- A `wait` that already delivered the run suppresses the redundant
|
|
82
77
|
notification (delivered-state is re-checked at flush time).
|
|
78
|
+
- Model/attempt annotations use the actual execution history, not the immutable original Jev choice. Fallback creates no extra completion notification or delivery path.
|
|
83
79
|
|
|
84
80
|
### `/subagents` overlay
|
|
85
81
|
- Header: title + running/ready counters + full usage ledger + rule.
|
|
@@ -129,11 +125,11 @@ usage and a bounded `Optional synthesis blocked: …` diagnostic instead of
|
|
|
129
125
|
discarding or re-routing them.
|
|
130
126
|
|
|
131
127
|
### Plan results (tool output, not TUI)
|
|
132
|
-
`action:"plan"` returns the
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
and
|
|
128
|
+
`action:"plan"` returns the initial model, a bounded probability-ranked candidate preview, common tools, effective total attempt limit and selector usage. Probabilities are selector preferences, not uptime estimates, and `confidence` belongs to the original answer. A plan reports no actual attempts; a later invocation selects again. It starts no child and creates no run entry, so plan never adds an overlay row or ambient widget. A plan whose optional synthesis selection fails still returns the valid worker plan and labels only that stage blocked with its diagnostic.
|
|
129
|
+
|
|
130
|
+
### Failed-attempt output
|
|
131
|
+
|
|
132
|
+
Earlier attempts retain bounded, attributed output previews and child-session pointers. If all attempts fail, the final state, failure reason, model and session stay authoritative; earlier text does not become that model's answer or a successful structured result. A human-readable earlier preview names its source attempt. Successful final JSON is never concatenated with failed JSON. Full output remains in existing child sessions, which are retained while referenced on the active branch. Compact views remain within their existing output limits.
|
|
137
133
|
|
|
138
134
|
## States
|
|
139
135
|
- **Queued/Running**: spinner + live stats + activity tail from live text.
|
package/package.json
CHANGED