@jangmanj/pi-bgtasks

中文文档
0.1.1发布于 2026/11/01MITES Module零依赖构建来源已验证

Background shell tasks and declared in-process subagents for Pi: bg_run, bg_logs, bg_kill, subagent.

原始使用文档
文档目录12 节
  1. Install
  2. Declaring a subagent
  3. Undeclared names
  4. Choosing a provider
  5. What the caller gets
  6. Behaviour
  7. Subagent concurrency
  8. Footer
  9. Integration protocol
  10. Code map
  11. Development
  12. Known limits

@jangmanj/pi-bgtasks

Background shell tasks and declared in-process subagents for Pi. Four tools, no commands, no settings.

ToolDoesThe model is told
bg_runStart a shell command in the background. Returns an id and a log path.Start long commands before blocking work; completion wakes you, so never sleep or poll; report done only once every task has exited and been checked.
subagentRun a declared agent, foreground or background: true.Hand off self-contained adjacent work (mapping, long reads, research, review, independent slices), several at once before blocking work; the prompt is the whole brief; a report is evidence, not completion.
bg_logsList tasks and subagents, or read one by id (shell tail or subagent report).For reading more than a wake-up preview, or fresh state for a decision; not a way to wait.
bg_killStop one by id.For work no longer needed or run away; never wakes a turn.

The tool descriptions carry those instructions, so they travel with the tools into any session. Three short promptGuidelines add what a general AGENTS.md usually does not: start side work before blocking work, write a complete brief, never poll.

Do not load it with pi-bg-tasks or @gotgenes/pi-subagents; the tool names clash.

Install

pi install npm:@jangmanj/pi-bgtasks

Needs Pi 1.4.0 or later and Node 22.19 or later.

Declaring a subagent

A subagent exists only if a file declares all of it. Files: <cwd>/.pi/agents/<name>.md over $PI_CODING_AGENT_DIR/agents/<name>.md (default ~/.pi/agent/agents/). The project file wins by name. Edits apply on the next spawn.

---
description: Reads code and reports findings
tools: read, grep, find, ls
model: provider/model-id
thinking: high
max_turns: 20
---
You read code and report what you find. Do not edit files.
KeyRequiredRule
descriptionyesOne line, shown to the parent model.
toolsyesExact allowlist: names or * patterns, comma list or [a, b]. none means no tools.
modelyesprovider/id (exact), or a bare model id, resolved as below. Never inherited; inherit is invalid.
thinkingnooff minimal low medium high xhigh max.
max_turnsno1-500, default 30. Reaching it fails the run and keeps the partial result.
bodyyesThe whole system prompt. No parent prompt, context files, skills, or conversation is inherited.

Undeclared names

Calling subagent with a name that has no file creates a safe default instead of failing: tools read, grep, find, ls (read-only), max_turns 30, and a prompt that asks for batched work, observed and cited claims, and a final message ending in done or partial with the open items. It is saved to ~/.pi/agent/agents/<name>.md so it becomes a normal declaration you can edit; an existing file is never overwritten. The model parameter is required for this and picks its model; without it the call fails and lists available models. The model is checked before anything is saved, and the result tells the caller what was created and where. model on an already-declared agent is rejected: a declaration's model is authoritative. A name whose file exists but is invalid is an error, not a trigger to create.

Parsing is strict. An unknown key, a missing field, or a bad value makes that file invalid; it is not spawnable and the error is shown when the model asks for it. An invalid project file does not fall back to the global one it shadows.

A child never receives this extension's tools (subagent, bg_*), even through a * pattern. A declaration that names them is invalid.

Choosing a provider

provider/id is used exactly as written; it is never swapped for another route. A bare model id (no provider) is looked up across every provider that has credentials and resolves to the subscription-backed one, using Pi's own auth data (isUsingSubscription, falling back to OAuth when the runtime does not expose it). Two providers tied at the best tier is an error that lists them; Pi never guesses between them. The resolved provider/id appears in every report header.

What the caller gets

Every outcome, foreground or in the wake-up, is one report: a header (id, agent, state, model, turns, tool calls, duration), then the outcome stated outright.

StateBody
RUNNINGThe latest assistant message that contained text, labelled Latest progress (not the final report). Before the first such message, the report says that no assistant progress is available yet.
COMPLETEDThe child's last message that contained text. Empty answers are never returned silently: NO RESULT: the subagent finished without writing a final answer…
FAILEDFAILED: <reason> (provider error, max_turns reached, start failure), then any partial output, labelled as partial.
KILLEDKILLED before finishing. plus partial output.

Failures and kills throw in the foreground, so they arrive as tool errors. Output over 32 KB is cut with [truncated: showing N of M characters]; the 4 KB wake-up preview points to bg_logs for the rest. bg_logs marks finished jobs that were never read as [completed, unread].

Behaviour

  • Foreground subagents return the result, or throw with the partial result on failure. Pi's abort stops them.
  • Background jobs wake a follow-up turn once on completion, unless started with notifyOnCompletion: false (both bg_run and subagent); then the result waits for bg_logs, and a failure turns the footer red until it is read. If the agent is busy, the result is injected at the next turn boundary. Reading it with bg_logs first suppresses the wake. bg_kill never wakes.
  • Wake-ups are display: false: the model gets the report, the transcript shows no card. The footer carries the user-visible state.
  • Limits: 16 running shell tasks, 4 running subagents, 32 finished records kept per kind.
  • Shell tasks run in their own process group (bash -lc): SIGTERM, then SIGKILL after 1.5 s. Logs are 0600 in a per-user 0700 directory (PI_BG_LOG_DIR overrides). Running groups are SIGKILLed if pi exits without its shutdown hook.
  • Jobs survive /reload; callbacks reach the current extension instance. They are stopped on any other shutdown.
  • Output placed in a wake-up message is XML-escaped and bounded.

Subagent concurrency

Up to four subagents run at once, counting session construction and teardown. Further requests are queued (Queued subagent <id>) and start in FIFO order as slots free; the queue holds at most 64, and a full queue rejects new requests. Foreground calls wait through the queue; background calls return an id at once and keep the usual completion wake-up. Reading queued work does not mark its future result read. bg_kill cancels queued work without starting it or waking a turn; shutdown cancels queued work before stopping running children. A session that fails to start is kept as a failed report and follows the normal wake-up rules. The footer counts running work, not queued work.

One status key, bgtasks, through ctx.ui.setStatus, the channel every footer extension reads (Pi's own, zentui, powerline, statusline, starship styles). One key means one placement to choose. Same recipe as pi-webtasks: nerd-font icon, 256-colour, compact count, braille spinner while anything runs. Present from session start as dim zeros, so the footer keeps its shape when work begins; removed at session end. Set only on change. The spinner interval exists only while something is running.

Two lanes inside it, shell tasks then subagents. The number is how many are running; glyph and colour change in place to show the lane's state:

TextMeans
0 0 (dim)idle
2⠋ 1⠋ (blue, purple)two shell tasks and one subagent running
0 1⠋ (red, purple)a shell task failed and nobody has read it or been woken with it yet

The red clears once the failure is read with bg_logs, killed, or delivered to the model as a wake-up. Nothing is added to the transcript. zentui's colour mode Original keeps these colours, Zentui replaces them. Names and labels from tasks never reach the footer.

setStatus is the only channel, as in pi-webtasks; nothing is published as a zentui custom variable, so it is never shown twice.

Integration protocol

Unchanged from pi-bg-tasks v1, so existing readers (the simon-says bridge) keep working: globalThis[Symbol.for("jang.pi.bg.tasks.v1")] (Map<id, task>), globalThis[Symbol.for("jang.pi.bg.service.v1")] ({version, store, list, get}), and pi.events bg-tasks:changed / bg-tasks:terminal.

Subagents add globalThis[Symbol.for("jang.pi.bg.agents.v1")] (Map<id, run>) and bg-agents:changed / bg-agents:terminal, payload {version: 1, run}.

Code map

  • src/jobs.ts: the job ledger. One lifecycle for both lanes: v1 stores and events, ids, settle, kill, read/unread, pruning, footer counts.
  • src/shell.ts, src/agents.ts: the two lanes. Each supplies how its work starts, stops, and is shown; agents.ts also owns declarations and model choice.
  • src/scheduler.ts: FIFO run scheduler under a concurrency limit; the subagent queue.
  • src/notifier.ts: wake-up delivery. Idle: send now; busy: append to the next turn boundary; settled: send what is left; a read withdraws.
  • src/footer.ts: the footer line and its spinner.
  • src/port.ts: the seam to Pi that the notifier and the footer use; the real adapter. Tests use a recording fake with a manual clock.
  • src/host.ts: the one record on globalThis that outlives /reload (bound session, pending wake-ups, footer state), and the notifier and footer built over it.
  • src/index.ts: hooks and tool definitions.

Development

npm run check        # type checker and tests
npm run smoke:pack   # pack, install the tarball, and load it in Pi

A release is npm version patch (or minor, major) and git push --follow-tags; CI publishes through npm trusted publishing with provenance.

Known limits

  • A model provider registered only at runtime by the parent is not copied into the child; the child loads extensions itself and gets what they register.
  • Subagent extension tools come from the child's own extension load, so an allowlisted extension tool must be installed for the child.

版本与发布记录

@jangmanj/pi-bgtasks 共发布 3 个版本,首次发布于 2026/10/28;过去 12 个月发布了 3 个版本。最新版本附带 npm provenance 构建来源证明,可追溯到公开的 CI 构建记录。

版本发布日期距今
0.1.1latest2026/11/012 天前
0.1.02026/10/286 天前
0.0.0-stage2026/10/286 天前

关于 @jangmanj/pi-bgtasks 的常见问题

@jangmanj/pi-bgtasks 是什么?

后台shell任务和Pi的进程内子代理:bg_run, bg_logs, bg_kill, subagent。

如何安装 @jangmanj/pi-bgtasks?

在项目目录运行 npm install @jangmanj/pi-bgtasks,或使用 pnpm add / yarn add / bun add。它还需要宿主项目提供 peer 依赖:@earendil-works/pi-coding-agent(>=1.4.0)。npm 7 及以上与 pnpm 8 及以上默认会自动安装必需的 peer 依赖,Yarn 需要手动安装。

@jangmanj/pi-bgtasks 支持 TypeScript 吗?

该包的 package.json 没有声明类型入口。需要类型提示时,可以在 npm 上查找社区维护的 @types/jangmanj__pi-bgtasks 是否存在。

@jangmanj/pi-bgtasks 支持 ESM 还是 CommonJS?

以 ES Module 形式发布,推荐使用 import 引入。在 CommonJS 项目中,Node.js 20.19+ / 22.12+ 可以直接 require() 不含顶层 await 的 ES Module,更早的版本需要改用动态 import()。

@jangmanj/pi-bgtasks 需要什么版本的 Node.js?

package.json 的 engines 字段要求 Node.js >=22.19.0。版本不符时 npm 默认只给出警告,开启 engine-strict 后会拒绝安装。

@jangmanj/pi-bgtasks 可以商用吗?

@jangmanj/pi-bgtasks 使用 MIT 许可。宽松许可:允许商业使用、修改和再分发,通常只需在分发时保留原版权与许可声明。以上为概括,不构成法律意见,请以许可原文为准。

@jangmanj/pi-bgtasks 还在维护吗?

最新版本 0.1.1 发布于 2026/11/01(2 天前);至今共发布 3 个版本,其中过去 12 个月发布了 3 个;首次发布于 2026/10/28。发布频率只是参考信号:功能稳定的工具可能很少需要更新,建议结合源码仓库的 issue 和提交记录判断。