Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,12 @@
# Changelog

## 0.5.2

### Fixes

- **Pi 0.62 metadata compatibility** — updated tool metadata wiring for recent Pi releases so teams tools continue to render the right prompt snippets/guidelines and stay compatible with current core APIs.
- **Non-interactive exit hang** — leader polling timers now call `unref()` so print/json child sessions can exit cleanly instead of hanging after the agent finishes. This fixes subagent and other nested Pi flows that load the teams extension in the background.

## 0.5.1

### Features
Expand Down
5 changes: 5 additions & 0 deletions extensions/teams/leader-teams-tool.ts
Original file line number Diff line number Diff line change
Expand Up @@ -191,6 +191,11 @@ export function registerTeamsTool(opts: {
"Optional overrides: model='<provider>/<modelId>' and thinking (off|minimal|low|medium|high|xhigh).",
"For governance, the user can run /team delegate on (leader restricted to coordination) or /team spawn <name> plan (worker needs plan approval).",
].join(" "),
promptSnippet: "Delegate work across teammates, inspect member status, message workers, and manage team lifecycle/tasks.",
promptGuidelines: [
"Use this tool when the user wants parallel agent work, worker coordination, or team lifecycle/task management.",
"Prefer member_status before interrupting or reassigning active teammates when the current state is unclear.",
],
parameters: TeamsToolParamsSchema,

async execute(_toolCallId, params: TeamsToolParamsType, signal, _onUpdate, ctx): Promise<AgentToolResult<unknown>> {
Expand Down
5 changes: 5 additions & 0 deletions extensions/teams/leader.ts
Original file line number Diff line number Diff line change
Expand Up @@ -750,6 +750,8 @@ export function runLeader(pi: ExtensionAPI): void {
refreshInFlight = false;
}
}, 1000);
// Don't keep non-interactive/child pi processes alive just because leader polling exists.
refreshTimer.unref?.();

inboxTimer = setInterval(async () => {
if (isStopping) return;
Expand All @@ -761,6 +763,7 @@ export function runLeader(pi: ExtensionAPI): void {
inboxInFlight = false;
}
}, 700);
inboxTimer.unref?.();
});

pi.on("session_switch", async (_event, ctx) => {
Expand Down Expand Up @@ -820,6 +823,7 @@ export function runLeader(pi: ExtensionAPI): void {
refreshInFlight = false;
}
}, 1000);
refreshTimer.unref?.();

inboxTimer = setInterval(async () => {
if (isStopping) return;
Expand All @@ -831,6 +835,7 @@ export function runLeader(pi: ExtensionAPI): void {
inboxInFlight = false;
}
}, 700);
inboxTimer.unref?.();
});

pi.on("session_shutdown", async () => {
Expand Down
5 changes: 5 additions & 0 deletions extensions/teams/worker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,11 @@ export function runWorker(pi: ExtensionAPI): void {
name: "team_message",
label: "Team Message",
description: "Send a message to a comrade. Use this to coordinate with peers on related tasks. Set urgent=true to interrupt their active turn (use sparingly — only for time-sensitive coordination).",
promptSnippet: "Send a coordination message to another teammate, optionally as an urgent interruption.",
promptGuidelines: [
"Use this tool for teammate-to-teammate coordination instead of overloading task status fields with freeform messages.",
"Set urgent=true only when the recipient must be interrupted before finishing their current turn.",
],
parameters: TeamMessageToolParamsSchema,
async execute(
_toolCallId,
Expand Down
10 changes: 5 additions & 5 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@tmustier/pi-agent-teams",
"version": "0.5.1",
"version": "0.5.2",
"description": "Claude Code agent teams style workflow for Pi.",
"license": "MIT",
"author": "Thomas Mustier",
Expand Down Expand Up @@ -39,10 +39,10 @@
},
"devDependencies": {
"@eslint/js": "^9.39.2",
"@mariozechner/pi-agent-core": "^0.52.8",
"@mariozechner/pi-ai": "^0.52.8",
"@mariozechner/pi-coding-agent": "^0.52.8",
"@mariozechner/pi-tui": "^0.52.8",
"@mariozechner/pi-agent-core": "^0.62.0",
"@mariozechner/pi-ai": "^0.62.0",
"@mariozechner/pi-coding-agent": "^0.62.0",
"@mariozechner/pi-tui": "^0.62.0",
"@sinclair/typebox": "^0.34.48",
"eslint": "^9.39.2",
"tsx": "^4.20.5",
Expand Down
6 changes: 5 additions & 1 deletion scripts/smoke-test.mts
Original file line number Diff line number Diff line change
Expand Up @@ -554,14 +554,18 @@ console.log("\n7. Pi extension loading");
return typeof c === "string" ? c : undefined;
})();

const versionOutput = `${res.stdout ?? ""}${res.stderr ?? ""}`.trim();

if (errCode === "ENOENT") {
console.log(" (skipped) pi CLI not found on PATH");
} else if (errCode === "ETIMEDOUT") {
console.log(" (skipped) pi --version timed out");
} else if (res.status !== 0) {
console.log(" (skipped) pi --version returned non-zero exit code");
} else if (versionOutput.length === 0) {
console.log(" (skipped) pi --version produced no output");
} else {
assert((res.stdout ?? "").trim().length > 0, "pi --version works");
assert(versionOutput.length > 0, "pi --version works");
}
}

Expand Down
Loading