@ssk_dev/pi-subagents-lean 0.16.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.
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 kunkun9527
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,87 @@
1
+ # @ssk_dev/pi-subagents-lean
2
+
3
+ > **Lean Pi subagent plugin, same functionality — 268 initialization tokens, 81% fewer than the original.**
4
+ > [See my full setup for Pi](https://github.com/kunkun9527/my-lean-pi-setup)
5
+
6
+ [简体中文](README.zh-CN.md)
7
+
8
+ A token-lean Pi facade over [`@tintinweb/pi-subagents`](https://github.com/tintinweb/pi-subagents). It keeps the complete upstream subagent runtime and routes its provider-facing operations through one compact schema.
9
+
10
+ ## What it keeps
11
+
12
+ - Upstream subagent discovery, spawning, background execution, result retrieval, steering, rendering, and lifecycle behavior.
13
+ - The upstream `Agent`, `get_subagent_result`, and `steer_subagent` operations behind one `subagent` facade.
14
+ - Full advanced parameters through on-demand `help` and JSON input.
15
+
16
+ This package does **not** replace the upstream runtime with a minimal implementation. It only reduces the persistent model-facing tool surface.
17
+
18
+ ## Install
19
+
20
+ ```bash
21
+ pi install npm:@ssk_dev/pi-subagents-lean
22
+ ```
23
+
24
+ Do not load it together with another `pi-subagents` wrapper, or subagent tools may be registered twice.
25
+
26
+ ## Use
27
+
28
+ The model sees one tool:
29
+
30
+ ```text
31
+ subagent
32
+ ```
33
+
34
+ Supported operations are `run`, `result`, `steer`, and `help`.
35
+
36
+ ```json
37
+ {
38
+ "op": "run",
39
+ "prompt": "Find the implementation of the cache key.",
40
+ "description": "Locate cache key",
41
+ "subagent_type": "Explore",
42
+ "run_in_background": true
43
+ }
44
+ ```
45
+
46
+ Use `result` with `agent_id` to inspect a completed run and `steer` with `agent_id` plus `message` to redirect a running agent. Use `help` for advanced upstream parameters.
47
+
48
+ ## Important: review your agent definitions
49
+
50
+ The upstream runtime can discover built-in agents and custom agents from global, workspace, and project Pi locations. This repository does not ship your private agents, sessions, or memory, but it intentionally preserves that upstream discovery behavior.
51
+
52
+ After installation:
53
+
54
+ 1. Inspect every discovered agent definition and set its `model` to a provider/model available in your Pi environment.
55
+ 2. Delete agent types you do not want.
56
+ 3. Rename or modify agent types, prompts, tools, and extension lists to match your workflow.
57
+ 4. Check duplicate names: a custom agent with the same name may override a built-in type depending on upstream discovery precedence.
58
+
59
+ The upstream package includes built-in `general-purpose`, `Explore`, and `Plan` definitions; your installation may expose additional custom types.
60
+
61
+ ## Measured initialization footprint
62
+
63
+ With only this extension enabled, its recurring model-facing initialization contribution is:
64
+
65
+ | Model-facing tool | Lean | Upstream `@tintinweb/pi-subagents@0.16.1` |
66
+ | --- | ---: | ---: |
67
+ | Facade / `Agent` | `subagent`: 268 | `Agent`: 1,111 |
68
+ | Result retrieval | Included in facade | `get_subagent_result`: 149 |
69
+ | Steering | Included in facade | `steer_subagent`: 156 |
70
+ | **Total** | **268** | **1,416** |
71
+
72
+ That is **1,148 fewer tokens (81.1%)** than the pinned upstream extension. The measurement used Pi 0.84.4 and `pi-context-view@0.4.3` in a fresh isolated session, excluding Pi built-in tools, skills, context files, messages, and unrelated extensions. Context View estimates text as `ceil(characters / 4)`, so these are reproducible context-footprint estimates rather than exact GPT tokenizer counts. Runtime-only UI and slash commands are not included because they are not sent to the model.
73
+
74
+ ## Versions
75
+
76
+ The upstream runtime is pinned to `@tintinweb/pi-subagents@0.16.1`.
77
+
78
+ ## Development
79
+
80
+ ```bash
81
+ npm ci
82
+ npm run check
83
+ ```
84
+
85
+ ## License and upstream
86
+
87
+ MIT. This project wraps the MIT-licensed [`@tintinweb/pi-subagents`](https://github.com/tintinweb/pi-subagents).
@@ -0,0 +1,87 @@
1
+ # @ssk_dev/pi-subagents-lean
2
+
3
+ > **Lean Pi subagent 插件,功能相同:268 个初始化 tokens,较原插件减少 81%。**
4
+ > **整套配置:** [查看 Pi Lean Setup](https://github.com/kunkun9527/my-lean-pi-setup)
5
+
6
+ [English](README.md)
7
+
8
+ [`@tintinweb/pi-subagents`](https://github.com/tintinweb/pi-subagents) 的 token 精简版 Pi facade。它保留完整的上游 subagent 运行时,并通过一个紧凑 schema 路由面向模型的操作。
9
+
10
+ ## 保留的能力
11
+
12
+ - 上游的 subagent 发现、启动、后台执行、结果获取、steering、渲染和生命周期行为。
13
+ - 通过一个 `subagent` facade 提供上游 `Agent`、`get_subagent_result` 和 `steer_subagent` 操作。
14
+ - 通过按需 `help` 和 JSON input 使用完整高级参数。
15
+
16
+ 本包**不会**用最小化实现替换上游运行时,只减少长期存在的模型可见工具表面。
17
+
18
+ ## 安装
19
+
20
+ ```bash
21
+ pi install npm:@ssk_dev/pi-subagents-lean
22
+ ```
23
+
24
+ 不要同时加载另一个 `pi-subagents` 包装层,否则 subagent 工具可能被重复注册。
25
+
26
+ ## 使用
27
+
28
+ 模型只看到一个工具:
29
+
30
+ ```text
31
+ subagent
32
+ ```
33
+
34
+ 支持的操作为 `run`、`result`、`steer` 和 `help`。
35
+
36
+ ```json
37
+ {
38
+ "op": "run",
39
+ "prompt": "Find the implementation of the cache key.",
40
+ "description": "Locate cache key",
41
+ "subagent_type": "Explore",
42
+ "run_in_background": true
43
+ }
44
+ ```
45
+
46
+ 使用带 `agent_id` 的 `result` 查看已完成任务;使用带 `agent_id` 和 `message` 的 `steer` 调整运行中的 agent。高级上游参数通过 `help` 查看。
47
+
48
+ ## 重要:检查你的 agent 定义
49
+
50
+ 上游运行时可以从全局、workspace 和项目 Pi 位置发现内置及自定义 agents。本仓库不会携带你的私有 agents、sessions 或 memory,但会有意保留这种上游发现行为。
51
+
52
+ 安装后:
53
+
54
+ 1. 检查每个被发现的 agent 定义,将其 `model` 设置为你的 Pi 环境中可用的供应商/模型。
55
+ 2. 删除你不需要的 agent 类型。
56
+ 3. 按工作流重命名或修改 agent 类型、提示词、工具和扩展列表。
57
+ 4. 检查重名:根据上游发现优先级,同名自定义 agent 可能覆盖内置类型。
58
+
59
+ 上游包包含内置 `general-purpose`、`Explore` 和 `Plan` 定义;你的安装还可能暴露其他自定义类型。
60
+
61
+ ## 实测初始化上下文占用
62
+
63
+ 仅启用本扩展时,它持续贡献给模型的初始化上下文为:
64
+
65
+ | 模型可见工具 | Lean | 上游 `@tintinweb/pi-subagents@0.16.1` |
66
+ | --- | ---: | ---: |
67
+ | Facade / `Agent` | `subagent`:268 | `Agent`:1,111 |
68
+ | 结果获取 | 已包含在 facade 中 | `get_subagent_result`:149 |
69
+ | Steering | 已包含在 facade 中 | `steer_subagent`:156 |
70
+ | **合计** | **268** | **1,416** |
71
+
72
+ 相比固定版本的上游扩展,减少 **1,148 tokens(81.1%)**。测量使用 Pi 0.84.4 和 `pi-context-view@0.4.3`,在全新隔离会话中只启用目标扩展,并排除 Pi 内置工具、skills、context files、消息及无关扩展。Context View 按 `ceil(字符数 / 4)` 估算,因此这些是可复现的上下文占用估值,不是 GPT tokenizer 的精确计数。未计入不会发送给模型的纯运行时 UI 和 slash commands。
73
+
74
+ ## 版本
75
+
76
+ 上游运行时固定为 `@tintinweb/pi-subagents@0.16.1`。
77
+
78
+ ## 开发
79
+
80
+ ```bash
81
+ npm ci
82
+ npm run check
83
+ ```
84
+
85
+ ## 许可证与上游
86
+
87
+ MIT。本项目包装了采用 MIT 许可证的 [`@tintinweb/pi-subagents`](https://github.com/tintinweb/pi-subagents)。
package/index.ts ADDED
@@ -0,0 +1,161 @@
1
+ // pi-subagents-lean: one provider-facing facade over the full subagents runtime.
2
+ // Complete operation schemas stay local and are disclosed through help on demand.
3
+ import type { ExtensionAPI, ToolDefinition } from "@earendil-works/pi-coding-agent";
4
+ import { Type } from "@sinclair/typebox";
5
+ import { Value } from "@sinclair/typebox/value";
6
+ import subagents from "@tintinweb/pi-subagents/src/index.ts";
7
+ import { Text } from "@earendil-works/pi-tui";
8
+
9
+ type CapturedTool = ToolDefinition<any, any, any>;
10
+ type UpstreamExtension = (pi: ExtensionAPI) => void;
11
+ type FacadeOperation = "run" | "result" | "steer" | "help";
12
+
13
+ const FACADE_PARAMETERS = Type.Object({
14
+ op: Type.Unsafe<FacadeOperation>({
15
+ type: "string",
16
+ enum: ["run", "result", "steer", "help"],
17
+ }),
18
+ prompt: Type.Optional(Type.String({ description: "Task for run." })),
19
+ description: Type.Optional(Type.String({ description: "3-5 word UI label for run." })),
20
+ subagent_type: Type.Optional(
21
+ Type.String({ description: "general-purpose, Explore, Plan, or a custom agent type." }),
22
+ ),
23
+ run_in_background: Type.Optional(Type.Boolean()),
24
+ agent_id: Type.Optional(Type.String()),
25
+ message: Type.Optional(Type.String()),
26
+ input: Type.Optional(Type.String({ description: "JSON object string for advanced parameters." })),
27
+ });
28
+
29
+ function capturePi(pi: ExtensionAPI, tools: Map<string, CapturedTool>): ExtensionAPI {
30
+ return new Proxy(pi, {
31
+ get(target, property, receiver) {
32
+ if (property === "registerTool") {
33
+ return (tool: CapturedTool) => {
34
+ tools.set(tool.name, tool);
35
+ };
36
+ }
37
+ const value = Reflect.get(target, property, receiver);
38
+ return typeof value === "function" ? value.bind(target) : value;
39
+ },
40
+ });
41
+ }
42
+
43
+ function renderParams(params: Record<string, unknown>): Record<string, unknown> {
44
+ const { op: _op, input, ...common } = params;
45
+ if (typeof input !== "string" || !input) return common;
46
+ try {
47
+ const parsed = JSON.parse(input) as unknown;
48
+ return parsed && typeof parsed === "object" && !Array.isArray(parsed)
49
+ ? { ...(parsed as Record<string, unknown>), ...common }
50
+ : common;
51
+ } catch {
52
+ return common;
53
+ }
54
+ }
55
+
56
+ export function createSubagentsFacade(
57
+ upstream: UpstreamExtension = subagents,
58
+ ): (pi: ExtensionAPI) => void {
59
+ return (pi: ExtensionAPI): void => {
60
+ const tools = new Map<string, CapturedTool>();
61
+ upstream(capturePi(pi, tools));
62
+
63
+ const facadeTool: ToolDefinition<typeof FACADE_PARAMETERS, any, any> = {
64
+ name: "subagent",
65
+ label: "Subagent",
66
+ description: "Launch, inspect, or steer a subagent. Use help for advanced parameters.",
67
+ parameters: FACADE_PARAMETERS,
68
+ promptGuidelines: [
69
+ "run requires prompt, description (3-5 words), and subagent_type; use a matching agent for broad work, and direct tools when the target is known.",
70
+ "Put advanced options in input as a JSON object; direct fields override duplicate JSON keys. result uses agent_id; steer uses agent_id and message. Use help only when advanced parameters are unclear.",
71
+ "Background completion is notified; never poll or sleep. Summarize results and verify claimed code changes.",
72
+ ],
73
+ renderCall(args, theme, context) {
74
+ const routed = renderParams(args);
75
+ const toolName = args.op === "result"
76
+ ? "get_subagent_result"
77
+ : args.op === "steer"
78
+ ? "steer_subagent"
79
+ : "Agent";
80
+ const target = tools.get(toolName);
81
+ if (target?.renderCall) {
82
+ return target.renderCall(routed, theme, { ...context, args: routed });
83
+ }
84
+ return new Text(theme.fg("toolTitle", `subagent ${args.op}`), 0, 0);
85
+ },
86
+ renderResult(result, options, theme, context) {
87
+ const facadeArgs = context.args;
88
+ const routed = renderParams(facadeArgs);
89
+ const toolName = facadeArgs.op === "result"
90
+ ? "get_subagent_result"
91
+ : facadeArgs.op === "steer"
92
+ ? "steer_subagent"
93
+ : "Agent";
94
+ const target = tools.get(toolName);
95
+ if (target?.renderResult) {
96
+ return target.renderResult(result, options, theme, { ...context, args: routed });
97
+ }
98
+ const text = result.content
99
+ .filter((entry): entry is { type: "text"; text: string } => entry.type === "text")
100
+ .map((entry) => entry.text)
101
+ .join("\n");
102
+ return new Text(text, 0, 0);
103
+ },
104
+ async execute(callId, params, signal, onUpdate, ctx) {
105
+ if (params.op === "help") {
106
+ const requested = params.input?.trim();
107
+ const helpToolName = requested === "run"
108
+ ? "Agent"
109
+ : requested === "result"
110
+ ? "get_subagent_result"
111
+ : requested === "steer"
112
+ ? "steer_subagent"
113
+ : undefined;
114
+ const helpTool = helpToolName ? tools.get(helpToolName) : undefined;
115
+ const text = helpTool
116
+ ? `${requested} -> ${helpToolName}\n\n${helpTool.description ?? ""}\n\nParameters:\n${JSON.stringify(helpTool.parameters, null, 2)}`
117
+ : "Subagent operations: run, result, steer. Use op=help with input set to one operation for its complete parameters.";
118
+ return { content: [{ type: "text", text }], details: {} };
119
+ }
120
+ const toolName = params.op === "result"
121
+ ? "get_subagent_result"
122
+ : params.op === "steer"
123
+ ? "steer_subagent"
124
+ : "Agent";
125
+ const target = tools.get(toolName);
126
+ if (!target) {
127
+ return {
128
+ content: [{ type: "text", text: `subagent operation is unavailable: ${params.op}` }],
129
+ details: {},
130
+ };
131
+ }
132
+ const { op: _op, input, ...common } = params;
133
+ let advanced: Record<string, unknown> = {};
134
+ if (input) {
135
+ try {
136
+ const parsed = JSON.parse(input) as unknown;
137
+ if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) {
138
+ throw new Error("expected a JSON object");
139
+ }
140
+ advanced = parsed as Record<string, unknown>;
141
+ } catch (error) {
142
+ const message = error instanceof Error ? error.message : String(error);
143
+ throw new Error(`subagent input is invalid JSON: ${message}`);
144
+ }
145
+ }
146
+ const routedParams = { ...advanced, ...common };
147
+ const validationErrors = [...Value.Errors(target.parameters, routedParams)];
148
+ if (validationErrors.length > 0) {
149
+ const summary = validationErrors
150
+ .map((error) => `${error.path || "/"}: ${error.message}`)
151
+ .join("; ");
152
+ throw new Error(`subagent ${params.op} parameters are invalid: ${summary}`);
153
+ }
154
+ return target.execute(callId, routedParams, signal, onUpdate, ctx);
155
+ },
156
+ };
157
+ pi.registerTool(facadeTool);
158
+ };
159
+ }
160
+
161
+ export default createSubagentsFacade();
package/package.json ADDED
@@ -0,0 +1,61 @@
1
+ {
2
+ "name": "@ssk_dev/pi-subagents-lean",
3
+ "version": "0.16.1",
4
+ "type": "module",
5
+ "description": "Lean Pi subagent plugin, same functionality — 268 initialization tokens, 81% fewer than the original.",
6
+ "license": "MIT",
7
+ "publishConfig": {
8
+ "access": "public"
9
+ },
10
+ "author": "kunkun9527",
11
+ "repository": {
12
+ "type": "git",
13
+ "url": "git+https://github.com/kunkun9527/pi-subagents-lean.git"
14
+ },
15
+ "homepage": "https://github.com/kunkun9527/pi-subagents-lean#readme",
16
+ "bugs": {
17
+ "url": "https://github.com/kunkun9527/pi-subagents-lean/issues"
18
+ },
19
+ "keywords": [
20
+ "pi-package",
21
+ "pi-extension",
22
+ "subagents",
23
+ "multi-agent",
24
+ "token-efficient"
25
+ ],
26
+ "files": [
27
+ "index.ts",
28
+ "README.md",
29
+ "README.zh-CN.md",
30
+ "LICENSE"
31
+ ],
32
+ "engines": {
33
+ "node": ">=22.19.0"
34
+ },
35
+ "scripts": {
36
+ "test": "node --test tests/*.test.mjs",
37
+ "typecheck": "tsc -p tsconfig.json",
38
+ "check": "npm run typecheck && npm test"
39
+ },
40
+ "dependencies": {
41
+ "@sinclair/typebox": "0.34.52",
42
+ "@tintinweb/pi-subagents": "0.16.1"
43
+ },
44
+ "peerDependencies": {
45
+ "@earendil-works/pi-ai": ">=0.84.1 <1.0.0",
46
+ "@earendil-works/pi-coding-agent": ">=0.84.1 <1.0.0",
47
+ "@earendil-works/pi-tui": ">=0.84.1 <1.0.0"
48
+ },
49
+ "devDependencies": {
50
+ "@earendil-works/pi-ai": "0.84.3",
51
+ "@earendil-works/pi-coding-agent": "0.84.3",
52
+ "@earendil-works/pi-tui": "0.84.3",
53
+ "jiti": "2.7.0",
54
+ "typescript": "5.9.3"
55
+ },
56
+ "pi": {
57
+ "extensions": [
58
+ "./index.ts"
59
+ ]
60
+ }
61
+ }