@pi-unipi/unipi 3.0.0-alpha.21 → 3.0.0-alpha.22
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 +13 -0
- package/README.md +193 -158
- package/package.json +21 -21
- package/packages/ask-user/README.md +82 -39
- package/packages/ask-user/index.ts +17 -2
- package/packages/ask-user/package.json +2 -2
- package/packages/ask-user/tools.ts +40 -6
- package/packages/autocomplete/README.md +46 -21
- package/packages/autocomplete/package.json +1 -1
- package/packages/background-tasks/README.md +69 -67
- package/packages/background-tasks/package.json +2 -2
- package/packages/btw/README.md +59 -13
- package/packages/btw/package.json +2 -2
- package/packages/compactor/README.md +78 -61
- package/packages/compactor/package.json +3 -3
- package/packages/core/README.md +98 -94
- package/packages/core/package.json +1 -1
- package/packages/footer/README.md +73 -116
- package/packages/footer/package.json +3 -3
- package/packages/fusion/README.md +83 -150
- package/packages/fusion/package.json +4 -4
- package/packages/info-screen/README.md +81 -69
- package/packages/info-screen/package.json +2 -2
- package/packages/input-shortcuts/README.md +47 -47
- package/packages/input-shortcuts/package.json +2 -2
- package/packages/kanboard/README.md +98 -182
- package/packages/kanboard/package.json +7 -7
- package/packages/long-horizon/README.md +98 -16
- package/packages/long-horizon/package.json +2 -2
- package/packages/long-horizon/src/gate.ts +9 -0
- package/packages/mcp/README.md +74 -62
- package/packages/mcp/package.json +2 -2
- package/packages/memory/README.md +93 -118
- package/packages/memory/package.json +3 -3
- package/packages/notify/README.md +85 -120
- package/packages/notify/package.json +2 -2
- package/packages/skill-registry/README.md +78 -44
- package/packages/skill-registry/package.json +2 -2
- package/packages/subagents/README.md +77 -31
- package/packages/subagents/package.json +3 -3
- package/packages/unipi/bundled.js +1210 -1099
- package/packages/updater/README.md +53 -55
- package/packages/updater/package.json +2 -2
- package/packages/utility/README.md +87 -78
- package/packages/utility/package.json +2 -2
- package/packages/utility/src/index.ts +12 -4
- package/packages/utility/src/render/delegated.ts +3 -0
- package/packages/utility/src/render/harness.ts +11 -2
- package/packages/utility/src/render/images.ts +51 -0
- package/packages/utility/src/render/reply-bg.ts +30 -2
- package/packages/utility/src/render/simple.ts +3 -0
- package/packages/utility/src/render/spacing.ts +13 -1
- package/packages/utility/src/settings.ts +2 -2
- package/packages/watchdog/README.md +66 -41
- package/packages/watchdog/package.json +3 -3
- package/packages/web-api/README.md +78 -126
- package/packages/web-api/package.json +2 -2
- package/packages/workflow/README.md +80 -103
- package/packages/workflow/package.json +2 -2
|
@@ -1,72 +1,115 @@
|
|
|
1
|
-
#
|
|
1
|
+
# Ask User
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Let the agent stop and ask you multiple-choice questions when it needs a decision.
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
`@pi-unipi/ask-user` · part of [UniPi](../../README.md)
|
|
6
|
+
|
|
7
|
+
## What it does
|
|
8
|
+
|
|
9
|
+
- Adds the `ask_user` tool. The tool is **off** by default.
|
|
10
|
+
- Shows 1 to 4 questions in one dialog. Each question has 2 to 4 options.
|
|
11
|
+
- Adds an "Other (type your own)" option, so you can type a free answer. You can paste or drop images and files into this answer.
|
|
12
|
+
- Sends a question that you do not answer as "skipped". A skipped question does not stop the dialog.
|
|
13
|
+
- Shows each answer in the transcript as a short tree.
|
|
14
|
+
- Can send a notification while it waits for you, through [Notify](../notify/README.md).
|
|
15
|
+
|
|
16
|
+
```text
|
|
6
17
|
── Planet ✓ · Foods 2 · Last book ─────────────────────────────────────
|
|
7
18
|
What was the last book you read?
|
|
8
19
|
Can't remember
|
|
9
20
|
Don't read books
|
|
10
21
|
❭ Other (type your own)
|
|
11
22
|
└ Dune, cover: [Image #1]
|
|
12
|
-
[Image #1] red-cube.png · 570 KB
|
|
13
23
|
───────────────────────────────────────────────────────────────────────
|
|
14
24
|
↑↓ navigate · ↵ select · ctrl+v image · ←→ switch question · esc cancel
|
|
15
25
|
? Not ready to answer, help me out!
|
|
16
26
|
```
|
|
17
27
|
|
|
18
|
-
##
|
|
28
|
+
## Quick start
|
|
29
|
+
|
|
30
|
+
UniPi installs this package:
|
|
31
|
+
|
|
32
|
+
```bash
|
|
33
|
+
pi install npm:@pi-unipi/unipi
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
To install this package alone:
|
|
37
|
+
|
|
38
|
+
```bash
|
|
39
|
+
pi install npm:@pi-unipi/ask-user
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
To turn on the tool:
|
|
43
|
+
|
|
44
|
+
1. Open `/unipi:settings`.
|
|
45
|
+
2. Select the **Ask User** group.
|
|
46
|
+
3. Set **Enable ask_user** to on.
|
|
47
|
+
|
|
48
|
+
When the tool is off, it tells the agent to ask in its reply.
|
|
49
|
+
|
|
50
|
+
## Answer the questions
|
|
19
51
|
|
|
20
|
-
| Key |
|
|
21
|
-
|
|
22
|
-
| `↑` `↓` |
|
|
23
|
-
| `1`–`9` |
|
|
24
|
-
| `
|
|
25
|
-
| `
|
|
26
|
-
| `←` `→`, `
|
|
27
|
-
|
|
|
28
|
-
|
|
|
29
|
-
|
|
|
30
|
-
| `esc` | Cancel and stop the agent's turn (or send what's answered — see Settings) |
|
|
52
|
+
| Key | What it does |
|
|
53
|
+
|---|---|
|
|
54
|
+
| `↑` / `↓` | Moves between options. |
|
|
55
|
+
| `1`–`9` | Selects that option. In a multi-select question, it toggles the option. |
|
|
56
|
+
| `Space` | Toggles an option in a multi-select question. |
|
|
57
|
+
| `Enter` | Selects and goes to the next question. On the last question, it sends all answers. |
|
|
58
|
+
| `←` / `→`, `Tab`, `Shift+Tab` | Goes to another question. In an "Other" field with text, `←` and `→` move the cursor. |
|
|
59
|
+
| `Ctrl+V` | Pastes an image from the clipboard into the "Other" field. |
|
|
60
|
+
| `?` | Tells the agent that you are not ready to answer and want to talk first. |
|
|
61
|
+
| `Esc` | Stops the agent turn. A setting can make `Esc` send your answers. |
|
|
31
62
|
|
|
32
|
-
|
|
63
|
+
In the "Other" field, you type text directly. The option numbers disappear, so digits go into the text. A pasted image becomes `[Image #N]`, and a file path becomes `[File #N]`. The tool sends images to the model with your answers.
|
|
33
64
|
|
|
34
|
-
|
|
65
|
+
## Agent tools
|
|
35
66
|
|
|
36
|
-
|
|
67
|
+
| Tool | What it does |
|
|
68
|
+
|---|---|
|
|
69
|
+
| `ask_user` | Asks 1 to 4 questions in one dialog and waits for the answers. |
|
|
37
70
|
|
|
38
71
|
```ts
|
|
39
72
|
ask_user({
|
|
40
73
|
questions: [{
|
|
41
|
-
header: "Database", //
|
|
74
|
+
header: "Database", // 16 characters or fewer
|
|
42
75
|
question: "Which database should the service use?",
|
|
43
|
-
options: [ // 2–4
|
|
76
|
+
options: [ // 2–4 options
|
|
44
77
|
{ label: "Postgres", description: "JSON columns, full-text search" },
|
|
45
|
-
{ label: "SQLite", description: "
|
|
78
|
+
{ label: "SQLite", description: "No setup, single writer" },
|
|
46
79
|
],
|
|
47
80
|
multi_select: false, // optional
|
|
48
|
-
other: true, // optional
|
|
81
|
+
other: true, // optional, false removes "Other"
|
|
49
82
|
}],
|
|
50
83
|
})
|
|
51
84
|
```
|
|
52
85
|
|
|
53
|
-
The result
|
|
86
|
+
The result starts with `User answered your questions:`. A JSON object follows, with one key for each question: `{ "selected": [...], "custom_text": "...", "skipped": false }`. Images follow as image content.
|
|
54
87
|
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
-
|
|
58
|
-
-
|
|
88
|
+
Other facts:
|
|
89
|
+
|
|
90
|
+
- An option can have `action: "end_turn"`. This option ends the turn.
|
|
91
|
+
- An option can have `action: "new_session"` and a `prefill` message. You then select **Compact & run** or **Run directly**. Workflow skills use this to start the next step.
|
|
92
|
+
- The tool runs one dialog at a time. Thus several calls in one message cannot hide each other.
|
|
93
|
+
- The tool also accepts the older single-question form: `question`, `context`, `options`, `allowMultiple`, `allowFreeform`. It ignores `timeout`.
|
|
94
|
+
- In a subagent, the tool fails. The error tells the subagent to give the question to its lead.
|
|
95
|
+
- With no interactive UI, the tool tells the agent to ask in its reply.
|
|
59
96
|
|
|
60
97
|
## Settings
|
|
61
98
|
|
|
62
|
-
`/unipi:settings` → Ask User
|
|
63
|
-
|
|
64
|
-
|
|
|
65
|
-
|
|
66
|
-
|
|
|
67
|
-
|
|
|
68
|
-
|
|
|
69
|
-
|
|
|
70
|
-
|
|
|
71
|
-
|
|
|
72
|
-
|
|
|
99
|
+
Open `/unipi:settings` → **Ask User**. A change applies to the next question.
|
|
100
|
+
|
|
101
|
+
| Key | Default | What it does |
|
|
102
|
+
|---|---|---|
|
|
103
|
+
| `enabled` | `false` | Gives the agent the `ask_user` tool. |
|
|
104
|
+
| `notifyOnAsk` | `true` | Sends a notification while the agent waits. |
|
|
105
|
+
| `maxQuestions` | `4` | Maximum questions in one dialog (1–4). The tool description changes in new sessions. |
|
|
106
|
+
| `escape` | `stop` | `stop` ends the agent turn. `send` sends your answers and skips the rest. |
|
|
107
|
+
| `digitAdvance` | `true` | In a single-choice question, a number key also goes to the next question. |
|
|
108
|
+
| `other` | `agent` | `agent` lets the agent decide. `always` and `never` override the agent. |
|
|
109
|
+
| `helpLine` | `true` | Shows the "Not ready to answer" line. The `?` key works in all cases. |
|
|
110
|
+
|
|
111
|
+
## See also
|
|
112
|
+
|
|
113
|
+
- [Notify](../notify/README.md)
|
|
114
|
+
- [BTW](../btw/README.md)
|
|
115
|
+
- [Tools reference](../../docs/reference/tools.md)
|
|
@@ -15,7 +15,8 @@ import {
|
|
|
15
15
|
emitEvent,
|
|
16
16
|
getPackageVersion,
|
|
17
17
|
} from "@pi-unipi/core";
|
|
18
|
-
import {
|
|
18
|
+
import { getAskUserSettings } from "./config.js";
|
|
19
|
+
import { isSubagentChild, registerAskUserTools, syncAskUserTool } from "./tools.js";
|
|
19
20
|
|
|
20
21
|
/** Package version */
|
|
21
22
|
const VERSION = getPackageVersion(dirname(fileURLToPath(import.meta.url)));
|
|
@@ -25,8 +26,18 @@ export default function (pi: ExtensionAPI) {
|
|
|
25
26
|
// Register tools
|
|
26
27
|
registerAskUserTools(pi);
|
|
27
28
|
|
|
29
|
+
const sync = (cwd?: string) => {
|
|
30
|
+
try {
|
|
31
|
+
const want = getAskUserSettings(cwd).enabled && !isSubagentChild();
|
|
32
|
+
syncAskUserTool(pi, want);
|
|
33
|
+
} catch {
|
|
34
|
+
// tools may not be ready
|
|
35
|
+
}
|
|
36
|
+
};
|
|
37
|
+
|
|
28
38
|
// Session lifecycle — announce module
|
|
29
|
-
pi.on("session_start", async () => {
|
|
39
|
+
pi.on("session_start", async (_event, ctx) => {
|
|
40
|
+
sync(ctx?.cwd);
|
|
30
41
|
emitEvent(pi, UNIPI_EVENTS.MODULE_READY, {
|
|
31
42
|
name: MODULES.ASK_USER,
|
|
32
43
|
version: VERSION,
|
|
@@ -34,4 +45,8 @@ export default function (pi: ExtensionAPI) {
|
|
|
34
45
|
tools: [ASK_USER_TOOLS.ASK],
|
|
35
46
|
});
|
|
36
47
|
});
|
|
48
|
+
|
|
49
|
+
pi.on("before_agent_start", async (_event, ctx) => {
|
|
50
|
+
sync(ctx?.cwd);
|
|
51
|
+
});
|
|
37
52
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pi-unipi/ask-user",
|
|
3
|
-
"version": "3.0.0-alpha.
|
|
3
|
+
"version": "3.0.0-alpha.22",
|
|
4
4
|
"description": "Structured user input tool for Pi coding agent — single-select, multi-select, freeform",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "index.ts",
|
|
@@ -40,7 +40,7 @@
|
|
|
40
40
|
"access": "public"
|
|
41
41
|
},
|
|
42
42
|
"dependencies": {
|
|
43
|
-
"@pi-unipi/core": "3.0.0-alpha.
|
|
43
|
+
"@pi-unipi/core": "3.0.0-alpha.22"
|
|
44
44
|
},
|
|
45
45
|
"peerDependencies": {
|
|
46
46
|
"@earendil-works/pi-coding-agent": "^0.87.1",
|
|
@@ -28,11 +28,29 @@ export interface AskDetails {
|
|
|
28
28
|
questions: AskQuestion[];
|
|
29
29
|
answers?: QuestionAnswer[];
|
|
30
30
|
outcome: "answered" | "clarify" | "cancelled" | "action" | "unavailable";
|
|
31
|
+
reason?: "disabled" | "no-ui";
|
|
31
32
|
/** Legacy single-question fields, kept for older consumers (compactor, notify). */
|
|
32
33
|
question?: string;
|
|
33
34
|
attachments?: Array<Pick<Attachment, "id" | "kind" | "path" | "name">>;
|
|
34
35
|
}
|
|
35
36
|
|
|
37
|
+
/**
|
|
38
|
+
* Adds the ask_user tool to pi's active set when enabled, removes it otherwise,
|
|
39
|
+
* touching ONLY `ask_user`, never another module's tools. Skips `setActiveTools`
|
|
40
|
+
* when nothing would change.
|
|
41
|
+
*/
|
|
42
|
+
export function syncAskUserTool(
|
|
43
|
+
pi: Pick<ExtensionAPI, "getActiveTools" | "setActiveTools">,
|
|
44
|
+
want: boolean,
|
|
45
|
+
): void {
|
|
46
|
+
const current = pi.getActiveTools();
|
|
47
|
+
if (current.includes(ASK_USER_TOOLS.ASK) === want) return;
|
|
48
|
+
const set = new Set(current);
|
|
49
|
+
if (want) set.add(ASK_USER_TOOLS.ASK);
|
|
50
|
+
else set.delete(ASK_USER_TOOLS.ASK);
|
|
51
|
+
pi.setActiveTools([...set]);
|
|
52
|
+
}
|
|
53
|
+
|
|
36
54
|
const OPTION = Type.Object({
|
|
37
55
|
label: Type.String({ description: "Display text (1–5 words)" }),
|
|
38
56
|
description: Type.Optional(Type.String({ description: "What this option means or its trade-offs" })),
|
|
@@ -51,8 +69,8 @@ const QUESTION = Type.Object({
|
|
|
51
69
|
other: Type.Optional(Type.Boolean({ description: "Offer \"Other (type your own)\" (default true)" })),
|
|
52
70
|
});
|
|
53
71
|
|
|
54
|
-
function unavailable(questions: AskQuestion[], text: string) {
|
|
55
|
-
return { content: [{ type: "text" as const, text }], details: { questions, outcome: "unavailable" } as AskDetails };
|
|
72
|
+
function unavailable(questions: AskQuestion[], text: string, reason?: "disabled" | "no-ui") {
|
|
73
|
+
return { content: [{ type: "text" as const, text }], details: { questions, outcome: "unavailable", reason } as AskDetails };
|
|
56
74
|
}
|
|
57
75
|
|
|
58
76
|
function imageParts(attachments: readonly Attachment[]) {
|
|
@@ -120,8 +138,8 @@ export function registerAskUserTools(pi: ExtensionAPI): void {
|
|
|
120
138
|
"ask_user is not available inside a subagent. You cannot talk to the user directly — only your lead can. Do not guess an answer: state the question, the options you considered and your recommendation in your report.",
|
|
121
139
|
);
|
|
122
140
|
}
|
|
123
|
-
if (!settings.enabled) return unavailable(questions, "ask_user is turned off in settings — ask in your reply instead.");
|
|
124
|
-
if (!ctx.hasUI) return unavailable(questions, "No interactive UI (non-interactive mode) — ask in your reply instead.");
|
|
141
|
+
if (!settings.enabled) return unavailable(questions, "ask_user is turned off in settings — ask in your reply instead.", "disabled");
|
|
142
|
+
if (!ctx.hasUI) return unavailable(questions, "No interactive UI (non-interactive mode) — ask in your reply instead.", "no-ui");
|
|
125
143
|
if (questions.length === 0) throw new Error("ask_user needs at least one question with a question text.");
|
|
126
144
|
|
|
127
145
|
if (settings.notifyOnAsk) {
|
|
@@ -186,7 +204,15 @@ export function askRows(details: AskDetails | undefined, theme: Theme): string[]
|
|
|
186
204
|
if (details === undefined || questions.length === 0) return [];
|
|
187
205
|
if (details.outcome === "cancelled") return [` ${theme.fg("error", "Canceled by the user")}`];
|
|
188
206
|
if (details.outcome === "clarify") return [` ${theme.fg("warning", "Not ready to answer — wants to clarify first")}`];
|
|
189
|
-
if (details.outcome === "unavailable")
|
|
207
|
+
if (details.outcome === "unavailable") {
|
|
208
|
+
const text =
|
|
209
|
+
details.reason === "disabled"
|
|
210
|
+
? "not shown — ask_user is turned off in settings"
|
|
211
|
+
: details.reason === "no-ui"
|
|
212
|
+
? "not shown — no interactive UI"
|
|
213
|
+
: "not shown (no interactive UI or turned off)";
|
|
214
|
+
return [` ${theme.fg("dim", text)}`];
|
|
215
|
+
}
|
|
190
216
|
if (details.outcome === "action") return [` ${theme.fg("muted", "picked an action")}`];
|
|
191
217
|
return questions.map((q, i) => ` ${theme.fg("muted", `${q.header}: ${answerSummary(q, details.answers?.[i])}`)}`);
|
|
192
218
|
}
|
|
@@ -228,7 +254,15 @@ export function renderAskResult(details: AskDetails | undefined, theme: Theme):
|
|
|
228
254
|
const rows: string[] = [];
|
|
229
255
|
if (details!.outcome === "cancelled") rows.push(t.fg("error", "Canceled by the user"));
|
|
230
256
|
else if (details!.outcome === "clarify") rows.push(t.fg("warning", "Not ready to answer — wants to clarify first"));
|
|
231
|
-
else if (details!.outcome === "unavailable")
|
|
257
|
+
else if (details!.outcome === "unavailable") {
|
|
258
|
+
const text =
|
|
259
|
+
details!.reason === "disabled"
|
|
260
|
+
? "not shown — ask_user is turned off in settings"
|
|
261
|
+
: details!.reason === "no-ui"
|
|
262
|
+
? "not shown — no interactive UI"
|
|
263
|
+
: "not shown (no interactive UI or turned off)";
|
|
264
|
+
rows.push(t.fg("dim", text));
|
|
265
|
+
}
|
|
232
266
|
else {
|
|
233
267
|
questions.forEach((q, i) => {
|
|
234
268
|
const a = details!.answers?.[i];
|
|
@@ -1,37 +1,62 @@
|
|
|
1
|
-
#
|
|
1
|
+
# Command Enchantment
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Command Enchantment makes `/unipi:*` suggestions in the editor easy to scan, with package tags, colors and a stable order.
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
`@pi-unipi/command-enchantment` · part of [UniPi](../../README.md) · source folder `packages/autocomplete`
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
## What it does
|
|
8
8
|
|
|
9
|
-
|
|
9
|
+
- Adds a colored package tag, for example `[workflow]`, to each `/unipi:*` suggestion. The tag replaces the pi source tag.
|
|
10
|
+
- Sorts suggestions by match quality: exact, then prefix, then fuzzy.
|
|
11
|
+
- Puts `/unipi:settings` first when you type `/settings`.
|
|
12
|
+
- Hides `/skill:*` suggestions until you type `/skill:`.
|
|
13
|
+
- Keeps argument suggestions for `/unipi:*` commands, also when you press Tab after a space.
|
|
10
14
|
|
|
11
|
-
|
|
12
|
-
- Shows full command values like `unipi:permission` while replacing Pi source tags with concise package tags like `[workflow]`.
|
|
13
|
-
- Sorts matches in predictable tiers: exact Unipi matches first, then other Unipi matches, then system commands.
|
|
14
|
-
- Preserves dynamic argument completions from command providers (per-command `getArgumentCompletions`).
|
|
15
|
-
- Ships an audit test that checks registered Unipi commands are represented in the autocomplete registry and have descriptions.
|
|
15
|
+
## Quick start
|
|
16
16
|
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
Run the registry audit before releases:
|
|
17
|
+
Command Enchantment ships in `@pi-unipi/unipi`. To install it alone:
|
|
20
18
|
|
|
21
19
|
```bash
|
|
22
|
-
|
|
20
|
+
pi install npm:@pi-unipi/command-enchantment
|
|
23
21
|
```
|
|
24
22
|
|
|
25
|
-
|
|
23
|
+
1. Type `/unipi:` in the editor.
|
|
24
|
+
2. Read the package tag next to each suggestion.
|
|
25
|
+
3. Type a short name, for example `/plan`. The exact match `/unipi:plan` comes first.
|
|
26
|
+
|
|
27
|
+
The package has no commands and no agent tools.
|
|
28
|
+
|
|
29
|
+
## Settings
|
|
30
|
+
|
|
31
|
+
Open `/unipi:settings` → Command Enchantment. The namespace is `command-enchantment`.
|
|
32
|
+
|
|
33
|
+
| Key | Default | What it does |
|
|
34
|
+
|---|---|---|
|
|
35
|
+
| `autocompleteEnhanced` | `true` | Turns the enhanced suggestions on or off. Applies at the next session start. |
|
|
36
|
+
|
|
37
|
+
With `false`, the package does not add its provider. Pi suggestions stay as they are.
|
|
38
|
+
|
|
39
|
+
## How it works
|
|
40
|
+
|
|
41
|
+
At session start, Command Enchantment wraps the pi autocomplete provider. It changes only text that starts with `/`. Other text goes to the pi provider without a change.
|
|
42
|
+
|
|
43
|
+
For a command name, it uses this order:
|
|
44
|
+
|
|
45
|
+
1. A UniPi command that replaces a pi command with the same name (`settings`).
|
|
46
|
+
2. An exact match of the full command.
|
|
47
|
+
3. An exact match of the short name after `unipi:`.
|
|
48
|
+
4. A prefix match.
|
|
49
|
+
5. A fuzzy match. A shorter name comes first.
|
|
50
|
+
|
|
51
|
+
In the same tier, pi commands come before UniPi commands. UniPi commands then follow a fixed package order.
|
|
52
|
+
|
|
53
|
+
The command list is in `src/constants.ts`. An audit test checks that each registered `/unipi:*` command is in this list and has a description. Run it before a release:
|
|
26
54
|
|
|
27
55
|
```bash
|
|
28
56
|
npm --workspace packages/autocomplete test
|
|
29
57
|
```
|
|
30
58
|
|
|
31
|
-
##
|
|
32
|
-
|
|
33
|
-
Autocomplete enhancement is enabled by default. The package stores its toggle in the Unipi config and can be disabled by setting `autocompleteEnhanced` to `false`.
|
|
34
|
-
|
|
35
|
-
## License
|
|
59
|
+
## See also
|
|
36
60
|
|
|
37
|
-
|
|
61
|
+
- [Commands reference](../../docs/reference/commands.md)
|
|
62
|
+
- [Settings reference](../../docs/reference/settings.md)
|
|
@@ -1,76 +1,79 @@
|
|
|
1
|
-
#
|
|
1
|
+
# Background Tasks
|
|
2
2
|
|
|
3
|
-
Background
|
|
4
|
-
|
|
5
|
-
agent keeps working. Originally adopted from
|
|
6
|
-
[pi-background-tasks](https://github.com/ismailsaleekh/pi-background-tasks);
|
|
7
|
-
the Fusion council, attested Pi runs, and Anthropic attribution surfaces were
|
|
8
|
-
removed in 2.17.0 so the module does exactly one thing.
|
|
3
|
+
Background Tasks runs long shell commands in the background, so the agent can
|
|
4
|
+
continue to work. When a task finishes, the agent gets a notice.
|
|
9
5
|
|
|
10
|
-
|
|
6
|
+
`@pi-unipi/background-tasks` · part of [UniPi](../../README.md)
|
|
11
7
|
|
|
12
|
-
|
|
8
|
+
## What it does
|
|
13
9
|
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
Open `/unipi:settings` (Background Tasks group) for the master toggle,
|
|
23
|
-
defaults, output caps, delegate defaults).
|
|
24
|
-
|
|
25
|
-
## Surfaces
|
|
10
|
+
- Starts a named shell command and returns at once with a task ID and an output file.
|
|
11
|
+
- When the task stops, sends a `<background-task-notification>` message. By
|
|
12
|
+
default, this message starts a new agent turn.
|
|
13
|
+
- Gives the agent bounded log reads, so large output does not fill the context.
|
|
14
|
+
- Stops a task when its output is more than 20 MiB.
|
|
15
|
+
- Shows a start card, a completion card and a task dock.
|
|
16
|
+
- Shows a wait line above the editor while the agent waits for a task.
|
|
26
17
|
|
|
27
|
-
|
|
18
|
+
## Quick start
|
|
28
19
|
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
| `bg_delegate` + `bg_result` | One read-only child Pi agent seeded with a frozen projection of this conversation; hash-verified answer retrieval |
|
|
20
|
+
1. Install UniPi: `pi install npm:@pi-unipi/unipi`. You can also install this
|
|
21
|
+
package alone: `pi install npm:@pi-unipi/background-tasks`.
|
|
22
|
+
2. Ask the agent to run a long test suite in the background. The agent calls `bg_run`.
|
|
23
|
+
3. Push `Shift+Down` to open the task dock.
|
|
34
24
|
|
|
35
|
-
|
|
25
|
+
## Commands
|
|
36
26
|
|
|
37
|
-
|
|
38
|
-
|
|
27
|
+
| Command or key | What it does |
|
|
28
|
+
|---|---|
|
|
29
|
+
| `/unipi:bg [--agent] [--name "Name"] <command>` | Starts a background task. It sends a notice, but does not start a turn. |
|
|
30
|
+
| `/unipi:bg-tasks` | Opens the task manager. |
|
|
31
|
+
| `Shift+Down` | Opens the task dock. |
|
|
32
|
+
| `Ctrl+Alt+C` | Clears the notices of finished tasks. |
|
|
39
33
|
|
|
40
|
-
|
|
34
|
+
## Agent tools
|
|
41
35
|
|
|
42
|
-
|
|
36
|
+
| Tool | What it does |
|
|
37
|
+
|---|---|
|
|
38
|
+
| `bg_run` | Starts a named shell command. Set `isAgent` to `true` only for a command that starts an LLM agent. |
|
|
39
|
+
| `bg_status` | Shows the state of one task or all tasks at one time. |
|
|
40
|
+
| `bg_logs` | Reads bounded output from a task. |
|
|
41
|
+
| `bg_kill` | Stops a running task by ID. |
|
|
43
42
|
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
- **Completion card** — the terminal notification renders as a tinted card (`✓ bg done <name> · exit 0 · 25s · agent woken`) with the last three output lines. Failed / stopped tasks use the error tint.
|
|
47
|
-
- **Dock** (`Shift↓`) — rows show `⏰ wakes agent` for tasks that will resume the agent, and the last output line for running shell tasks.
|
|
43
|
+
Do not call `bg_status` or `bg_logs` in a loop to wait. The notification
|
|
44
|
+
message is the final state of the task.
|
|
48
45
|
|
|
49
|
-
|
|
46
|
+
| `notifyOnCompletion` | `triggerOnCompletion` | Result |
|
|
47
|
+
|---|---|---|
|
|
48
|
+
| `true` | `true` (`bg_run` default) | A notice and a new agent turn. |
|
|
49
|
+
| `true` | `false` (`/unipi:bg` default) | A notice only. |
|
|
50
|
+
| `false` | any | No notice. Check the task yourself. |
|
|
50
51
|
|
|
51
|
-
|
|
52
|
-
- Durable delegate artifacts: `<workspace>/.unipi/delegate/<session>-<pid>/<task-id>/`
|
|
53
|
-
- Config: `~/.unipi/config/background-tasks.json` + workspace override
|
|
52
|
+
## Settings
|
|
54
53
|
|
|
55
|
-
|
|
54
|
+
Namespace `background-tasks`. Open it with `/unipi:settings`.
|
|
56
55
|
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
`
|
|
56
|
+
| Key | Default | What it does |
|
|
57
|
+
|---|---|---|
|
|
58
|
+
| `enabled` | `true` | Master switch. When it is `false`, the package registers no tools, commands or UI. |
|
|
59
|
+
| `notifyOnCompletion` | `true` | Sends a notice when a task stops. |
|
|
60
|
+
| `triggerOnCompletion` | `true` | Starts an agent turn when a task stops. |
|
|
61
|
+
| `defaultTimeoutSeconds` | `0` | Stops a task after this time. `0` means no limit. |
|
|
62
|
+
| `maxFinishedTasks` | `30` | Number of finished tasks to keep. |
|
|
63
|
+
| `maxOutputBytes` | `20971520` | Stops and fails a task above this output size. Minimum 1024. |
|
|
60
64
|
|
|
61
|
-
|
|
65
|
+
| Variable | What it does |
|
|
66
|
+
|---|---|
|
|
67
|
+
| `UNIPI_BG_TMP_DIR` | Folder for task output. The default is `TMPDIR` or `/tmp`. |
|
|
68
|
+
| `UNIPI_BG_MAX_OUTPUT_BYTES` | Default output limit. The `maxOutputBytes` setting wins. |
|
|
69
|
+
| `UNIPI_BG_SHELL`, `UNIPI_BG_SHELL_PATH` | On Windows, sets the shell: `cmd` or `bash`. |
|
|
70
|
+
| `UNIPI_BG_DISABLE_PI_TELEMETRY` | Set to `1` to stop the telemetry wrap of agent commands. |
|
|
62
71
|
|
|
63
|
-
|
|
64
|
-
| --- | --- | --- |
|
|
65
|
-
| true (default) | true (bg_run default) | Durable terminal notification + automatic follow-up turn |
|
|
66
|
-
| true | false (`/unipi:bg` default) | Notification only |
|
|
67
|
-
| false | — | Manual monitoring |
|
|
72
|
+
Task output goes to `<tmp>/unipi-bg-tasks/<session>-<pid>-<nonce>/`.
|
|
68
73
|
|
|
69
|
-
|
|
74
|
+
## For other packages
|
|
70
75
|
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
Other packages can read the live task registry synchronously — no events, no polling:
|
|
76
|
+
Read the live task list without events:
|
|
74
77
|
|
|
75
78
|
```ts
|
|
76
79
|
import { getSharedTaskRegistry } from "@pi-unipi/background-tasks";
|
|
@@ -79,19 +82,18 @@ const tasks = getSharedTaskRegistry()?.allTasks() ?? [];
|
|
|
79
82
|
const running = tasks.filter((t) => t.status === "running").length;
|
|
80
83
|
```
|
|
81
84
|
|
|
82
|
-
The
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
85
|
+
The function returns `undefined` when the package is off. Treat that as "no data".
|
|
86
|
+
|
|
87
|
+
## How it works
|
|
88
|
+
|
|
89
|
+
Read [Turn arbiter](../../docs/architecture/turn-arbiter.md) and
|
|
90
|
+
[Harness messages](../../docs/architecture/harness-messages.md).
|
|
86
91
|
|
|
87
|
-
##
|
|
92
|
+
## See also
|
|
88
93
|
|
|
89
|
-
-
|
|
90
|
-
-
|
|
91
|
-
|
|
92
|
-
- The reference's `update-check` footer surface is dropped (unipi's updater
|
|
93
|
-
module owns updates).
|
|
94
|
-
- Removed: attested Pi runs, the five-slot Fusion council tools, and the
|
|
95
|
-
Anthropic attribution provider override.
|
|
94
|
+
- [Subagents](../subagents/README.md)
|
|
95
|
+
- [Tools reference](../../docs/reference/tools.md)
|
|
96
|
+
- [Shortcuts reference](../../docs/reference/shortcuts.md)
|
|
96
97
|
|
|
97
|
-
|
|
98
|
+
Based on [pi-background-tasks](https://github.com/ismailsaleekh/pi-background-tasks)
|
|
99
|
+
(ISC license, Copyright Ismail).
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pi-unipi/background-tasks",
|
|
3
|
-
"version": "3.0.0-alpha.
|
|
3
|
+
"version": "3.0.0-alpha.22",
|
|
4
4
|
"description": "Background tasks for UniPi — durable shell jobs and delegated background agents with a footer dock",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "src/index.ts",
|
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
},
|
|
11
11
|
"dependencies": {
|
|
12
12
|
"@earendil-works/pi-ai": "^0.87.1",
|
|
13
|
-
"@pi-unipi/core": "3.0.0-alpha.
|
|
13
|
+
"@pi-unipi/core": "3.0.0-alpha.22",
|
|
14
14
|
"turndown": "^7.2.4"
|
|
15
15
|
},
|
|
16
16
|
"devDependencies": {
|