@pi-unipi/unipi 3.0.0-alpha.23 → 3.0.0-alpha.24
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 +7 -0
- package/package.json +21 -21
- package/packages/ask-user/package.json +2 -2
- package/packages/autocomplete/package.json +1 -1
- package/packages/autocomplete/src/constants.ts +2 -0
- package/packages/background-tasks/package.json +2 -2
- package/packages/btw/package.json +2 -2
- package/packages/compactor/package.json +3 -3
- package/packages/core/constants.ts +1 -0
- package/packages/core/package.json +1 -1
- package/packages/footer/package.json +3 -3
- package/packages/fusion/package.json +4 -4
- package/packages/info-screen/package.json +2 -2
- package/packages/input-shortcuts/package.json +2 -2
- package/packages/kanboard/package.json +7 -7
- package/packages/long-horizon/package.json +2 -2
- package/packages/mcp/package.json +2 -2
- package/packages/memory/package.json +3 -3
- package/packages/notify/package.json +2 -2
- package/packages/skill-registry/README.md +1 -1
- package/packages/skill-registry/index.ts +3 -1
- package/packages/skill-registry/package.json +2 -2
- package/packages/skill-registry/src/editor.ts +5 -5
- package/packages/skill-registry/src/registry.ts +15 -3
- package/packages/subagents/package.json +3 -3
- package/packages/unipi/bundled.js +51 -8
- package/packages/updater/package.json +2 -2
- package/packages/utility/README.md +19 -0
- package/packages/utility/package.json +2 -2
- package/packages/utility/skills/summarize/SKILL.md +304 -0
- package/packages/utility/skills/utility/SKILL.md +2 -1
- package/packages/utility/src/index.ts +2 -0
- package/packages/utility/src/summarize/index.ts +51 -0
- package/packages/watchdog/package.json +3 -3
- package/packages/web-api/package.json +2 -2
- package/packages/workflow/package.json +2 -2
package/CHANGELOG.md
CHANGED
|
@@ -6,6 +6,13 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/).
|
|
|
6
6
|
|
|
7
7
|
## [Unreleased]
|
|
8
8
|
|
|
9
|
+
## [3.0.0-alpha.24] — 2026-10-04
|
|
10
|
+
|
|
11
|
+
### Added
|
|
12
|
+
- `utility`: bundled **`summarize` skill** — the default shape for the agent's final reply after work: a one-sentence answer, numbered sections that open with a bold takeaway, optional mermaid diagram for 3+ step flows, "Problems and fixes", "Not verified", "Still open", and typed questions (`Q1 (pick one)` / `(pick any)` / `(your answer)`, a recommendation only when the work gives a reason). A level gate matches the user's technical depth. Skipped when the user asks for full detail or raw output. Tuned against `ds/deepseek-flash` in a blind A/B arena over 12 real long-session turns.
|
|
13
|
+
- `utility`: **`/unipi:summarize [focus]`** — asks the agent for that summary of the session now (expands `/skill:summarize`, so the skill is always applied; waits for the turn in print mode).
|
|
14
|
+
- `skill-registry`: bundled skills can be **must show by default** (`DEFAULT_MUST_SHOW`, currently `summarize`), with the proxy on or off. A scope can still clear **M** or **E** in `/unipi:skills`.
|
|
15
|
+
|
|
9
16
|
## [3.0.0-alpha.23] — 2026-10-04
|
|
10
17
|
|
|
11
18
|
### Added
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pi-unipi/unipi",
|
|
3
|
-
"version": "3.0.0-alpha.
|
|
3
|
+
"version": "3.0.0-alpha.24",
|
|
4
4
|
"description": "All-in-one extension suite for Pi coding agent",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
@@ -82,26 +82,26 @@
|
|
|
82
82
|
"typebox": "^1.1.38"
|
|
83
83
|
},
|
|
84
84
|
"dependencies": {
|
|
85
|
-
"@pi-unipi/ask-user": "3.0.0-alpha.
|
|
86
|
-
"@pi-unipi/background-tasks": "3.0.0-alpha.
|
|
87
|
-
"@pi-unipi/btw": "3.0.0-alpha.
|
|
88
|
-
"@pi-unipi/command-enchantment": "3.0.0-alpha.
|
|
89
|
-
"@pi-unipi/compactor": "3.0.0-alpha.
|
|
90
|
-
"@pi-unipi/core": "3.0.0-alpha.
|
|
91
|
-
"@pi-unipi/footer": "3.0.0-alpha.
|
|
92
|
-
"@pi-unipi/fusion": "3.0.0-alpha.
|
|
93
|
-
"@pi-unipi/info-screen": "3.0.0-alpha.
|
|
94
|
-
"@pi-unipi/input-shortcuts": "3.0.0-alpha.
|
|
95
|
-
"@pi-unipi/kanboard": "3.0.0-alpha.
|
|
96
|
-
"@pi-unipi/mcp": "3.0.0-alpha.
|
|
97
|
-
"@pi-unipi/memory": "3.0.0-alpha.
|
|
98
|
-
"@pi-unipi/notify": "3.0.0-alpha.
|
|
99
|
-
"@pi-unipi/skill-registry": "3.0.0-alpha.
|
|
100
|
-
"@pi-unipi/subagents": "3.0.0-alpha.
|
|
101
|
-
"@pi-unipi/updater": "3.0.0-alpha.
|
|
102
|
-
"@pi-unipi/utility": "3.0.0-alpha.
|
|
103
|
-
"@pi-unipi/web-api": "3.0.0-alpha.
|
|
104
|
-
"@pi-unipi/workflow": "3.0.0-alpha.
|
|
85
|
+
"@pi-unipi/ask-user": "3.0.0-alpha.24",
|
|
86
|
+
"@pi-unipi/background-tasks": "3.0.0-alpha.24",
|
|
87
|
+
"@pi-unipi/btw": "3.0.0-alpha.24",
|
|
88
|
+
"@pi-unipi/command-enchantment": "3.0.0-alpha.24",
|
|
89
|
+
"@pi-unipi/compactor": "3.0.0-alpha.24",
|
|
90
|
+
"@pi-unipi/core": "3.0.0-alpha.24",
|
|
91
|
+
"@pi-unipi/footer": "3.0.0-alpha.24",
|
|
92
|
+
"@pi-unipi/fusion": "3.0.0-alpha.24",
|
|
93
|
+
"@pi-unipi/info-screen": "3.0.0-alpha.24",
|
|
94
|
+
"@pi-unipi/input-shortcuts": "3.0.0-alpha.24",
|
|
95
|
+
"@pi-unipi/kanboard": "3.0.0-alpha.24",
|
|
96
|
+
"@pi-unipi/mcp": "3.0.0-alpha.24",
|
|
97
|
+
"@pi-unipi/memory": "3.0.0-alpha.24",
|
|
98
|
+
"@pi-unipi/notify": "3.0.0-alpha.24",
|
|
99
|
+
"@pi-unipi/skill-registry": "3.0.0-alpha.24",
|
|
100
|
+
"@pi-unipi/subagents": "3.0.0-alpha.24",
|
|
101
|
+
"@pi-unipi/updater": "3.0.0-alpha.24",
|
|
102
|
+
"@pi-unipi/utility": "3.0.0-alpha.24",
|
|
103
|
+
"@pi-unipi/web-api": "3.0.0-alpha.24",
|
|
104
|
+
"@pi-unipi/workflow": "3.0.0-alpha.24"
|
|
105
105
|
},
|
|
106
106
|
"devDependencies": {
|
|
107
107
|
"@earendil-works/pi-agent-core": "^0.87.1",
|
|
@@ -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.24",
|
|
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.24"
|
|
44
44
|
},
|
|
45
45
|
"peerDependencies": {
|
|
46
46
|
"@earendil-works/pi-coding-agent": "^0.87.1",
|
|
@@ -74,6 +74,7 @@ export const COMMAND_REGISTRY: Record<string, string> = {
|
|
|
74
74
|
"unipi:cleanup": "utility",
|
|
75
75
|
"unipi:doctor": "utility",
|
|
76
76
|
"unipi:answer": "utility",
|
|
77
|
+
"unipi:summarize": "utility",
|
|
77
78
|
|
|
78
79
|
// skill-registry
|
|
79
80
|
"unipi:skills": "skill-registry",
|
|
@@ -160,6 +161,7 @@ export const COMMAND_DESCRIPTIONS: Record<string, string> = {
|
|
|
160
161
|
"unipi:cleanup": "Remove stale UniPi temp files and leftovers (preview first)",
|
|
161
162
|
"unipi:doctor": "Check UniPi's runtime: config, model cache, Decision Model, skills",
|
|
162
163
|
"unipi:answer": "Answer the last reply — fixed input under the scrollable reply, per question, or web form",
|
|
164
|
+
"unipi:summarize": "Summarize this session — answer first, then findings, open items, questions; add text to set a focus",
|
|
163
165
|
"unipi:skills": "Manage skills — on/off per project, listed or not, the skill vault",
|
|
164
166
|
|
|
165
167
|
"unipi:kanboard": "Kanboard — capture tasks, run them, open the board",
|
|
@@ -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.24",
|
|
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.24",
|
|
14
14
|
"turndown": "^7.2.4"
|
|
15
15
|
},
|
|
16
16
|
"devDependencies": {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pi-unipi/btw",
|
|
3
|
-
"version": "3.0.0-alpha.
|
|
3
|
+
"version": "3.0.0-alpha.24",
|
|
4
4
|
"description": "A pi extension for parallel side conversations with /unipi:btw — part of the Unipi suite",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "extensions/btw.ts",
|
|
@@ -37,7 +37,7 @@
|
|
|
37
37
|
"@earendil-works/pi-tui": "^0.87.1"
|
|
38
38
|
},
|
|
39
39
|
"dependencies": {
|
|
40
|
-
"@pi-unipi/core": "3.0.0-alpha.
|
|
40
|
+
"@pi-unipi/core": "3.0.0-alpha.24"
|
|
41
41
|
},
|
|
42
42
|
"pi": {
|
|
43
43
|
"extensions": [
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pi-unipi/compactor",
|
|
3
|
-
"version": "3.0.0-alpha.
|
|
3
|
+
"version": "3.0.0-alpha.24",
|
|
4
4
|
"description": "Compaction for Pi — lossless zero-LLM or model summaries, rebuilt from full history, with session recall",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "src/index.ts",
|
|
@@ -33,8 +33,8 @@
|
|
|
33
33
|
"access": "public"
|
|
34
34
|
},
|
|
35
35
|
"dependencies": {
|
|
36
|
-
"@pi-unipi/core": "3.0.0-alpha.
|
|
37
|
-
"@pi-unipi/info-screen": "3.0.0-alpha.
|
|
36
|
+
"@pi-unipi/core": "3.0.0-alpha.24",
|
|
37
|
+
"@pi-unipi/info-screen": "3.0.0-alpha.24",
|
|
38
38
|
"@earendil-works/pi-agent-core": "^0.87.1"
|
|
39
39
|
},
|
|
40
40
|
"peerDependencies": {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pi-unipi/footer",
|
|
3
|
-
"version": "3.0.0-alpha.
|
|
3
|
+
"version": "3.0.0-alpha.24",
|
|
4
4
|
"description": "Persistent status bar for Unipi — subscribes to UNIPI_EVENTS and renders key stats from all unipi packages",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "index.ts",
|
|
@@ -32,8 +32,8 @@
|
|
|
32
32
|
"access": "public"
|
|
33
33
|
},
|
|
34
34
|
"dependencies": {
|
|
35
|
-
"@pi-unipi/core": "3.0.0-alpha.
|
|
36
|
-
"@pi-unipi/background-tasks": "3.0.0-alpha.
|
|
35
|
+
"@pi-unipi/core": "3.0.0-alpha.24",
|
|
36
|
+
"@pi-unipi/background-tasks": "3.0.0-alpha.24"
|
|
37
37
|
},
|
|
38
38
|
"peerDependencies": {
|
|
39
39
|
"@earendil-works/pi-coding-agent": "^0.87.1",
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pi-unipi/fusion",
|
|
3
|
-
"version": "3.0.0-alpha.
|
|
3
|
+
"version": "3.0.0-alpha.24",
|
|
4
4
|
"description": "Devin-style model picker, fusion presets (lead + sidekick), and Local Fusion runtime for UniPi",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "src/index.ts",
|
|
@@ -32,9 +32,9 @@
|
|
|
32
32
|
"access": "public"
|
|
33
33
|
},
|
|
34
34
|
"dependencies": {
|
|
35
|
-
"@pi-unipi/core": "3.0.0-alpha.
|
|
36
|
-
"@pi-unipi/subagents": "3.0.0-alpha.
|
|
37
|
-
"@pi-unipi/utility": "3.0.0-alpha.
|
|
35
|
+
"@pi-unipi/core": "3.0.0-alpha.24",
|
|
36
|
+
"@pi-unipi/subagents": "3.0.0-alpha.24",
|
|
37
|
+
"@pi-unipi/utility": "3.0.0-alpha.24"
|
|
38
38
|
},
|
|
39
39
|
"peerDependencies": {
|
|
40
40
|
"@earendil-works/pi-ai": "^0.87.1",
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pi-unipi/info-screen",
|
|
3
|
-
"version": "3.0.0-alpha.
|
|
3
|
+
"version": "3.0.0-alpha.24",
|
|
4
4
|
"description": "Dashboard and module registry for Unipi — configurable info overlay with tabbed groups",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "index.ts",
|
|
@@ -32,7 +32,7 @@
|
|
|
32
32
|
"access": "public"
|
|
33
33
|
},
|
|
34
34
|
"dependencies": {
|
|
35
|
-
"@pi-unipi/core": "3.0.0-alpha.
|
|
35
|
+
"@pi-unipi/core": "3.0.0-alpha.24"
|
|
36
36
|
},
|
|
37
37
|
"peerDependencies": {
|
|
38
38
|
"@earendil-works/pi-coding-agent": "^0.87.1",
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pi-unipi/input-shortcuts",
|
|
3
|
-
"version": "3.0.0-alpha.
|
|
3
|
+
"version": "3.0.0-alpha.24",
|
|
4
4
|
"description": "Keyboard shortcuts for stash/restore, undo/redo, clipboard, and thinking toggle — chord-based overlay system",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "src/index.ts",
|
|
@@ -33,7 +33,7 @@
|
|
|
33
33
|
"access": "public"
|
|
34
34
|
},
|
|
35
35
|
"dependencies": {
|
|
36
|
-
"@pi-unipi/core": "3.0.0-alpha.
|
|
36
|
+
"@pi-unipi/core": "3.0.0-alpha.24"
|
|
37
37
|
},
|
|
38
38
|
"peerDependencies": {
|
|
39
39
|
"@earendil-works/pi-coding-agent": "^0.87.1",
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pi-unipi/kanboard",
|
|
3
|
-
"version": "3.0.0-alpha.
|
|
3
|
+
"version": "3.0.0-alpha.24",
|
|
4
4
|
"description": "Kanboard v3 — deferred-work board: CLI/daemon bridge, task runner and skill",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "index.ts",
|
|
@@ -31,7 +31,7 @@
|
|
|
31
31
|
"access": "public"
|
|
32
32
|
},
|
|
33
33
|
"dependencies": {
|
|
34
|
-
"@pi-unipi/core": "3.0.0-alpha.
|
|
34
|
+
"@pi-unipi/core": "3.0.0-alpha.24"
|
|
35
35
|
},
|
|
36
36
|
"peerDependencies": {
|
|
37
37
|
"@earendil-works/pi-coding-agent": "^0.87.1",
|
|
@@ -48,10 +48,10 @@
|
|
|
48
48
|
"themes": []
|
|
49
49
|
},
|
|
50
50
|
"optionalDependencies": {
|
|
51
|
-
"@pi-unipi/kanboard-linux-x64": "3.0.0-alpha.
|
|
52
|
-
"@pi-unipi/kanboard-linux-arm64": "3.0.0-alpha.
|
|
53
|
-
"@pi-unipi/kanboard-darwin-x64": "3.0.0-alpha.
|
|
54
|
-
"@pi-unipi/kanboard-darwin-arm64": "3.0.0-alpha.
|
|
55
|
-
"@pi-unipi/kanboard-win32-x64": "3.0.0-alpha.
|
|
51
|
+
"@pi-unipi/kanboard-linux-x64": "3.0.0-alpha.24",
|
|
52
|
+
"@pi-unipi/kanboard-linux-arm64": "3.0.0-alpha.24",
|
|
53
|
+
"@pi-unipi/kanboard-darwin-x64": "3.0.0-alpha.24",
|
|
54
|
+
"@pi-unipi/kanboard-darwin-arm64": "3.0.0-alpha.24",
|
|
55
|
+
"@pi-unipi/kanboard-win32-x64": "3.0.0-alpha.24"
|
|
56
56
|
}
|
|
57
57
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pi-unipi/long-horizon",
|
|
3
|
-
"version": "3.0.0-alpha.
|
|
3
|
+
"version": "3.0.0-alpha.24",
|
|
4
4
|
"description": "Long-horizon execution for Pi — mode-gated /goal /ralph /swarm /graph orchestration with a TypeSafe prompt judge",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "index.ts",
|
|
@@ -37,7 +37,7 @@
|
|
|
37
37
|
"access": "public"
|
|
38
38
|
},
|
|
39
39
|
"dependencies": {
|
|
40
|
-
"@pi-unipi/core": "3.0.0-alpha.
|
|
40
|
+
"@pi-unipi/core": "3.0.0-alpha.24"
|
|
41
41
|
},
|
|
42
42
|
"peerDependencies": {
|
|
43
43
|
"@earendil-works/pi-coding-agent": "^0.87.1",
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pi-unipi/mcp",
|
|
3
|
-
"version": "3.0.0-alpha.
|
|
3
|
+
"version": "3.0.0-alpha.24",
|
|
4
4
|
"description": "MCP server management extension for Pi coding agent — browse, add, configure, and use MCP servers",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "src/index.ts",
|
|
@@ -30,7 +30,7 @@
|
|
|
30
30
|
"test": "npx tsx --test tests/**/*.test.ts"
|
|
31
31
|
},
|
|
32
32
|
"dependencies": {
|
|
33
|
-
"@pi-unipi/core": "3.0.0-alpha.
|
|
33
|
+
"@pi-unipi/core": "3.0.0-alpha.24"
|
|
34
34
|
},
|
|
35
35
|
"peerDependencies": {
|
|
36
36
|
"@earendil-works/pi-coding-agent": "^0.87.1",
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pi-unipi/memory",
|
|
3
|
-
"version": "3.0.0-alpha.
|
|
3
|
+
"version": "3.0.0-alpha.24",
|
|
4
4
|
"description": "Persistent cross-session memory on MemPalace (auto-installed): daemon-routed writes, shared palace with other agents, for Pi coding agent",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "index.ts",
|
|
@@ -42,8 +42,8 @@
|
|
|
42
42
|
"README.md"
|
|
43
43
|
],
|
|
44
44
|
"dependencies": {
|
|
45
|
-
"@pi-unipi/core": "3.0.0-alpha.
|
|
46
|
-
"@pi-unipi/info-screen": "3.0.0-alpha.
|
|
45
|
+
"@pi-unipi/core": "3.0.0-alpha.24",
|
|
46
|
+
"@pi-unipi/info-screen": "3.0.0-alpha.24",
|
|
47
47
|
"js-yaml": "^4.1.0"
|
|
48
48
|
},
|
|
49
49
|
"peerDependencies": {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pi-unipi/notify",
|
|
3
|
-
"version": "3.0.0-alpha.
|
|
3
|
+
"version": "3.0.0-alpha.24",
|
|
4
4
|
"description": "Cross-platform notification extension for Pi — native OS, Gotify, and Telegram notifications for agent lifecycle events",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "index.ts",
|
|
@@ -34,7 +34,7 @@
|
|
|
34
34
|
"access": "public"
|
|
35
35
|
},
|
|
36
36
|
"dependencies": {
|
|
37
|
-
"@pi-unipi/core": "3.0.0-alpha.
|
|
37
|
+
"@pi-unipi/core": "3.0.0-alpha.24",
|
|
38
38
|
"node-notifier": "^10.0.1"
|
|
39
39
|
},
|
|
40
40
|
"peerDependencies": {
|
|
@@ -39,7 +39,7 @@ Changes apply from the next prompt. You do not need `/reload`.
|
|
|
39
39
|
**Skill settings…** shows each skill with its source (`vault`, `project`, `user`, `unipi` or `package`) and two columns:
|
|
40
40
|
|
|
41
41
|
- **E** (enabled): the agent can see the skill. Off removes it from the session, and blocks `/skill:name`.
|
|
42
|
-
- **M** (must show): the agent always sees the skill, also when exposure judging would hide it.
|
|
42
|
+
- **M** (must show): the agent always sees the skill, also when exposure judging would hide it. The bundled `summarize` skill has **M** on by default.
|
|
43
43
|
|
|
44
44
|
| Key | What it does |
|
|
45
45
|
|---|---|
|
|
@@ -16,7 +16,7 @@ import type { ExtensionAPI, ExtensionContext } from "@earendil-works/pi-coding-a
|
|
|
16
16
|
import { emitEvent, getPackageVersion, harnessMetadata, HUB_OVERLAY_OPTIONS, MODULES, openSettingsHub, registerCommandRunner, setSettings, UNIPI_EVENTS } from "@pi-unipi/core";
|
|
17
17
|
import { dirname } from "node:path";
|
|
18
18
|
import { fileURLToPath } from "node:url";
|
|
19
|
-
import { applyRegistry, isBundledSkillLocation, isUnderDir, skillCommandName, skillDir, skillSource, type CatalogSkill } from "./src/registry.js";
|
|
19
|
+
import { applyRegistry, defaultMustShow, isBundledSkillLocation, isUnderDir, skillCommandName, skillDir, skillSource, type CatalogSkill } from "./src/registry.js";
|
|
20
20
|
import { readSkillsSettings, readStateLayers, writeStateLayers } from "./src/settings.js";
|
|
21
21
|
import { SkillEditor, type EditorResult } from "./src/editor.js";
|
|
22
22
|
import { listVaultSkills, vaultDir } from "./src/vault.js";
|
|
@@ -187,6 +187,8 @@ export default function skillRegistry(pi: ExtensionAPI) {
|
|
|
187
187
|
if (inVault) disabled.add(s.name);
|
|
188
188
|
return !inVault;
|
|
189
189
|
});
|
|
190
|
+
// Proxy off: per-skill states are ignored, defaults still apply.
|
|
191
|
+
for (const s of pool) if (defaultMustShow(s.name, skillSource(s, cwd, vault))) mustShow.add(s.name);
|
|
190
192
|
}
|
|
191
193
|
|
|
192
194
|
const setSkills = (list: CatalogSkill[]) => {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pi-unipi/skill-registry",
|
|
3
|
-
"version": "3.0.0-alpha.
|
|
3
|
+
"version": "3.0.0-alpha.24",
|
|
4
4
|
"description": "Skill registry for pi — per-project skill on/off, a skill vault, and jev-judged skill exposure",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
@@ -33,7 +33,7 @@
|
|
|
33
33
|
},
|
|
34
34
|
"main": "index.ts",
|
|
35
35
|
"dependencies": {
|
|
36
|
-
"@pi-unipi/core": "3.0.0-alpha.
|
|
36
|
+
"@pi-unipi/core": "3.0.0-alpha.24"
|
|
37
37
|
},
|
|
38
38
|
"peerDependencies": {
|
|
39
39
|
"@earendil-works/pi-coding-agent": "^0.87.1",
|
|
@@ -18,7 +18,7 @@
|
|
|
18
18
|
|
|
19
19
|
import { Key, matchesKey, truncateToWidth, visibleWidth } from "@earendil-works/pi-tui";
|
|
20
20
|
import { frameOverlay } from "@pi-unipi/core";
|
|
21
|
-
import type
|
|
21
|
+
import { defaultMustShow, type SkillSource } from "./registry.js";
|
|
22
22
|
import type { SkillState } from "./settings.js";
|
|
23
23
|
|
|
24
24
|
export type Column = "enabled" | "mustShow";
|
|
@@ -52,9 +52,9 @@ export interface EditorOptions {
|
|
|
52
52
|
visibleRows?: number;
|
|
53
53
|
}
|
|
54
54
|
|
|
55
|
-
function defaultFor(column: Column,
|
|
56
|
-
if (column === "enabled") return source !== "vault";
|
|
57
|
-
return
|
|
55
|
+
function defaultFor(column: Column, skill: EditorSkill): boolean {
|
|
56
|
+
if (column === "enabled") return skill.source !== "vault";
|
|
57
|
+
return defaultMustShow(skill.name, skill.source);
|
|
58
58
|
}
|
|
59
59
|
|
|
60
60
|
/** Effective value of one cell: project over global over the source default. */
|
|
@@ -63,7 +63,7 @@ export function cellValue(layers: Layers, skill: EditorSkill, column: Column): {
|
|
|
63
63
|
if (typeof p === "boolean") return { value: p, from: "project" };
|
|
64
64
|
const g = layers.global[skill.name]?.[column];
|
|
65
65
|
if (typeof g === "boolean") return { value: g, from: "global" };
|
|
66
|
-
return { value: defaultFor(column, skill
|
|
66
|
+
return { value: defaultFor(column, skill), from: "default" };
|
|
67
67
|
}
|
|
68
68
|
|
|
69
69
|
function printable(data: string): string | undefined {
|
|
@@ -43,13 +43,25 @@ export function skillSource(s: CatalogSkill, cwd: string, vault: string): SkillS
|
|
|
43
43
|
return "package";
|
|
44
44
|
}
|
|
45
45
|
|
|
46
|
+
/**
|
|
47
|
+
* Bundled UniPi skills that are listed by default ("Must show" on unless a
|
|
48
|
+
* scope turns it off). summarize sets the shape of the agent's final reply,
|
|
49
|
+
* so judging must not hide it on prompts that never mention a summary.
|
|
50
|
+
*/
|
|
51
|
+
export const DEFAULT_MUST_SHOW: ReadonlySet<string> = new Set(["summarize"]);
|
|
52
|
+
|
|
53
|
+
/** The default "Must show" value of a skill from its name and source. */
|
|
54
|
+
export function defaultMustShow(name: string, source: SkillSource): boolean {
|
|
55
|
+
return source === "unipi" && DEFAULT_MUST_SHOW.has(name);
|
|
56
|
+
}
|
|
57
|
+
|
|
46
58
|
export interface EffectiveState {
|
|
47
59
|
enabled: boolean;
|
|
48
60
|
mustShow: boolean;
|
|
49
61
|
}
|
|
50
62
|
|
|
51
|
-
export function effectiveState(state: SkillState | undefined, source: SkillSource): EffectiveState {
|
|
52
|
-
const mustShow = state?.mustShow
|
|
63
|
+
export function effectiveState(state: SkillState | undefined, source: SkillSource, name = ""): EffectiveState {
|
|
64
|
+
const mustShow = state?.mustShow ?? defaultMustShow(name, source);
|
|
53
65
|
// Must show implies enabled and is always listed.
|
|
54
66
|
return { enabled: mustShow || (state?.enabled ?? source !== "vault"), mustShow };
|
|
55
67
|
}
|
|
@@ -73,7 +85,7 @@ export function applyRegistry<T extends CatalogSkill>(
|
|
|
73
85
|
const disabled = new Set<string>();
|
|
74
86
|
const mustShow = new Set<string>();
|
|
75
87
|
for (const skill of catalog) {
|
|
76
|
-
const eff = effectiveState(states[skill.name], skillSource(skill, cwd, vault));
|
|
88
|
+
const eff = effectiveState(states[skill.name], skillSource(skill, cwd, vault), skill.name);
|
|
77
89
|
if (eff.mustShow) mustShow.add(skill.name);
|
|
78
90
|
if (!eff.enabled) disabled.add(skill.name);
|
|
79
91
|
else listed.push(skill);
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pi-unipi/subagents",
|
|
3
|
-
"version": "3.0.0-alpha.
|
|
3
|
+
"version": "3.0.0-alpha.24",
|
|
4
4
|
"description": "Subagents for UniPi — Devin-model independent child agents",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "src/index.ts",
|
|
@@ -9,8 +9,8 @@
|
|
|
9
9
|
"test": "npx tsx --test src/__tests__/*.test.ts"
|
|
10
10
|
},
|
|
11
11
|
"dependencies": {
|
|
12
|
-
"@pi-unipi/core": "3.0.0-alpha.
|
|
13
|
-
"@pi-unipi/utility": "3.0.0-alpha.
|
|
12
|
+
"@pi-unipi/core": "3.0.0-alpha.24",
|
|
13
|
+
"@pi-unipi/utility": "3.0.0-alpha.24",
|
|
14
14
|
"@earendil-works/pi-agent-core": "^0.87.1",
|
|
15
15
|
"acorn": "8.18.0"
|
|
16
16
|
},
|
|
@@ -96,7 +96,8 @@ var init_constants = __esm({
|
|
|
96
96
|
RETRY: "retry",
|
|
97
97
|
CLEANUP: "cleanup",
|
|
98
98
|
DOCTOR: "doctor",
|
|
99
|
-
ANSWER: "answer"
|
|
99
|
+
ANSWER: "answer",
|
|
100
|
+
SUMMARIZE: "summarize"
|
|
100
101
|
};
|
|
101
102
|
ASK_USER_TOOLS = {
|
|
102
103
|
ASK: "ask_user"
|
|
@@ -9529,6 +9530,40 @@ function registerAnswerCommand(pi) {
|
|
|
9529
9530
|
});
|
|
9530
9531
|
}
|
|
9531
9532
|
|
|
9533
|
+
// packages/utility/src/summarize/index.ts
|
|
9534
|
+
init_core();
|
|
9535
|
+
var SUMMARIZE_SKILL = "summarize";
|
|
9536
|
+
function summarizePrompt(focus) {
|
|
9537
|
+
const f = focus.trim();
|
|
9538
|
+
const scope = f ? `Summarize this session for me, with the focus on: ${f}` : "Summarize this session for me: what we did, why, and where it stands now.";
|
|
9539
|
+
return `/skill:${SUMMARIZE_SKILL} ${scope} Use only what happened in this session. Do not call tools.`;
|
|
9540
|
+
}
|
|
9541
|
+
function hasSummarizeSkill(pi) {
|
|
9542
|
+
try {
|
|
9543
|
+
return pi.getCommands().some((c2) => c2.name === `skill:${SUMMARIZE_SKILL}`);
|
|
9544
|
+
} catch {
|
|
9545
|
+
return false;
|
|
9546
|
+
}
|
|
9547
|
+
}
|
|
9548
|
+
function registerSummarizeCommand(pi) {
|
|
9549
|
+
pi.registerCommand(`${UNIPI_PREFIX}${UTILITY_COMMANDS.SUMMARIZE}`, {
|
|
9550
|
+
description: "Summarize this session for you (answer first, then findings, open items, questions); add text to set a focus",
|
|
9551
|
+
handler: async (args, ctx) => {
|
|
9552
|
+
if (!ctx.isIdle()) {
|
|
9553
|
+
if (ctx.hasUI) ctx.ui.notify("Agent is busy. Press ESC to interrupt, then try again.", "warning");
|
|
9554
|
+
return;
|
|
9555
|
+
}
|
|
9556
|
+
if (!hasSummarizeSkill(pi)) {
|
|
9557
|
+
if (ctx.hasUI) ctx.ui.notify("The summarize skill is off or missing. Turn it on in /unipi:skills.", "warning");
|
|
9558
|
+
return;
|
|
9559
|
+
}
|
|
9560
|
+
pi.sendUserMessage(summarizePrompt(args ?? ""), { expandPromptTemplates: true });
|
|
9561
|
+
await new Promise((r) => setTimeout(r, 0));
|
|
9562
|
+
await ctx.waitForIdle?.();
|
|
9563
|
+
}
|
|
9564
|
+
});
|
|
9565
|
+
}
|
|
9566
|
+
|
|
9532
9567
|
// packages/utility/src/attach/index.ts
|
|
9533
9568
|
import { readFileSync as readFileSync9 } from "node:fs";
|
|
9534
9569
|
import { getCapabilities as getCapabilities2, Image, Key as Key7, matchesKey as matchesKey6, truncateToWidth as truncateToWidth8 } from "@earendil-works/pi-tui";
|
|
@@ -12562,6 +12597,7 @@ function src_default(pi) {
|
|
|
12562
12597
|
registerUtilityCommands(pi);
|
|
12563
12598
|
registerAutoRename(pi);
|
|
12564
12599
|
registerAnswerCommand(pi);
|
|
12600
|
+
registerSummarizeCommand(pi);
|
|
12565
12601
|
registerAttachments(pi);
|
|
12566
12602
|
registerImage(pi);
|
|
12567
12603
|
const style = readUtilSettings().render.style;
|
|
@@ -30664,8 +30700,12 @@ function skillSource(s, cwd, vault) {
|
|
|
30664
30700
|
if (isUnderDir(dir, `${home}/.agents/skills`) || isUnderDir(dir, `${home}/.pi/agent/skills`)) return "user";
|
|
30665
30701
|
return "package";
|
|
30666
30702
|
}
|
|
30667
|
-
|
|
30668
|
-
|
|
30703
|
+
var DEFAULT_MUST_SHOW = /* @__PURE__ */ new Set(["summarize"]);
|
|
30704
|
+
function defaultMustShow(name, source) {
|
|
30705
|
+
return source === "unipi" && DEFAULT_MUST_SHOW.has(name);
|
|
30706
|
+
}
|
|
30707
|
+
function effectiveState(state2, source, name = "") {
|
|
30708
|
+
const mustShow = state2?.mustShow ?? defaultMustShow(name, source);
|
|
30669
30709
|
return { enabled: mustShow || (state2?.enabled ?? source !== "vault"), mustShow };
|
|
30670
30710
|
}
|
|
30671
30711
|
function applyRegistry(catalog, states, cwd, vault) {
|
|
@@ -30673,7 +30713,7 @@ function applyRegistry(catalog, states, cwd, vault) {
|
|
|
30673
30713
|
const disabled = /* @__PURE__ */ new Set();
|
|
30674
30714
|
const mustShow = /* @__PURE__ */ new Set();
|
|
30675
30715
|
for (const skill of catalog) {
|
|
30676
|
-
const eff = effectiveState(states[skill.name], skillSource(skill, cwd, vault));
|
|
30716
|
+
const eff = effectiveState(states[skill.name], skillSource(skill, cwd, vault), skill.name);
|
|
30677
30717
|
if (eff.mustShow) mustShow.add(skill.name);
|
|
30678
30718
|
if (!eff.enabled) disabled.add(skill.name);
|
|
30679
30719
|
else listed.push(skill);
|
|
@@ -30864,16 +30904,16 @@ init_core();
|
|
|
30864
30904
|
import { Key as Key13, matchesKey as matchesKey13, truncateToWidth as truncateToWidth22, visibleWidth as visibleWidth17 } from "@earendil-works/pi-tui";
|
|
30865
30905
|
var COLUMNS = ["enabled", "mustShow"];
|
|
30866
30906
|
var LETTER = { enabled: "E", mustShow: "M" };
|
|
30867
|
-
function defaultFor(column,
|
|
30868
|
-
if (column === "enabled") return source !== "vault";
|
|
30869
|
-
return
|
|
30907
|
+
function defaultFor(column, skill) {
|
|
30908
|
+
if (column === "enabled") return skill.source !== "vault";
|
|
30909
|
+
return defaultMustShow(skill.name, skill.source);
|
|
30870
30910
|
}
|
|
30871
30911
|
function cellValue(layers, skill, column) {
|
|
30872
30912
|
const p = layers.project[skill.name]?.[column];
|
|
30873
30913
|
if (typeof p === "boolean") return { value: p, from: "project" };
|
|
30874
30914
|
const g = layers.global[skill.name]?.[column];
|
|
30875
30915
|
if (typeof g === "boolean") return { value: g, from: "global" };
|
|
30876
|
-
return { value: defaultFor(column, skill
|
|
30916
|
+
return { value: defaultFor(column, skill), from: "default" };
|
|
30877
30917
|
}
|
|
30878
30918
|
function printable(data) {
|
|
30879
30919
|
if (data.length !== 1) return void 0;
|
|
@@ -31401,6 +31441,7 @@ function skillRegistry(pi) {
|
|
|
31401
31441
|
if (inVault) disabled.add(s.name);
|
|
31402
31442
|
return !inVault;
|
|
31403
31443
|
});
|
|
31444
|
+
for (const s of pool) if (defaultMustShow(s.name, skillSource(s, cwd, vault))) mustShow.add(s.name);
|
|
31404
31445
|
}
|
|
31405
31446
|
const setSkills = (list) => {
|
|
31406
31447
|
options.skills = list;
|
|
@@ -39665,6 +39706,7 @@ var COMMAND_REGISTRY = {
|
|
|
39665
39706
|
"unipi:cleanup": "utility",
|
|
39666
39707
|
"unipi:doctor": "utility",
|
|
39667
39708
|
"unipi:answer": "utility",
|
|
39709
|
+
"unipi:summarize": "utility",
|
|
39668
39710
|
// skill-registry
|
|
39669
39711
|
"unipi:skills": "skill-registry",
|
|
39670
39712
|
// ask-user (1 command)
|
|
@@ -39727,6 +39769,7 @@ var COMMAND_DESCRIPTIONS = {
|
|
|
39727
39769
|
"unipi:cleanup": "Remove stale UniPi temp files and leftovers (preview first)",
|
|
39728
39770
|
"unipi:doctor": "Check UniPi's runtime: config, model cache, Decision Model, skills",
|
|
39729
39771
|
"unipi:answer": "Answer the last reply \u2014 fixed input under the scrollable reply, per question, or web form",
|
|
39772
|
+
"unipi:summarize": "Summarize this session \u2014 answer first, then findings, open items, questions; add text to set a focus",
|
|
39730
39773
|
"unipi:skills": "Manage skills \u2014 on/off per project, listed or not, the skill vault",
|
|
39731
39774
|
"unipi:kanboard": "Kanboard \u2014 capture tasks, run them, open the board",
|
|
39732
39775
|
"unipi:kanboard-add": "Kanboard \u2014 capture a task into Backlog",
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pi-unipi/updater",
|
|
3
|
-
"version": "3.0.0-alpha.
|
|
3
|
+
"version": "3.0.0-alpha.24",
|
|
4
4
|
"description": "Auto-updater, changelog browser, and readme browser for Unipi — checks npm registry, renders CHANGELOG.md and README.md files in TUI overlays",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "index.ts",
|
|
@@ -34,7 +34,7 @@
|
|
|
34
34
|
"access": "public"
|
|
35
35
|
},
|
|
36
36
|
"dependencies": {
|
|
37
|
-
"@pi-unipi/core": "3.0.0-alpha.
|
|
37
|
+
"@pi-unipi/core": "3.0.0-alpha.24"
|
|
38
38
|
},
|
|
39
39
|
"peerDependencies": {
|
|
40
40
|
"@earendil-works/pi-coding-agent": "^0.87.1",
|
|
@@ -35,9 +35,28 @@ pi install npm:@pi-unipi/utility
|
|
|
35
35
|
| `/unipi:cleanup` | Lists stale UniPi files, then asks before it removes them. `--dry-run` only lists. `--yes` does not ask. |
|
|
36
36
|
| `/unipi:doctor` | Checks folders, config files, Node, the model cache, the Decision Model and skill exposure. |
|
|
37
37
|
| `/unipi:answer [reply\|questions\|web]` | Opens a screen to answer the last agent reply. |
|
|
38
|
+
| `/unipi:summarize [focus]` | Asks the agent for a summary of the session. Add text to set a focus. |
|
|
38
39
|
|
|
39
40
|
The skill manager is in [Skill Registry](../skill-registry/README.md) (`/unipi:skills`).
|
|
40
41
|
|
|
42
|
+
## Summaries
|
|
43
|
+
|
|
44
|
+
Utility ships the `summarize` skill. The skill sets the shape of the agent's
|
|
45
|
+
final reply after work:
|
|
46
|
+
|
|
47
|
+
1. One sentence with the answer or the result.
|
|
48
|
+
2. Numbered sections. Each section starts with one bold sentence.
|
|
49
|
+
3. Problems and fixes, when the work hit a problem.
|
|
50
|
+
4. Not verified, then Still open.
|
|
51
|
+
5. Questions for you. Each question has a type: pick one, pick any or your answer.
|
|
52
|
+
|
|
53
|
+
The agent uses the skill for every final reply, unless you ask for full detail
|
|
54
|
+
or raw output. `/unipi:summarize` asks for this summary at any time.
|
|
55
|
+
|
|
56
|
+
The skill is "must show" by default, so exposure judging does not hide it. To
|
|
57
|
+
turn this off, open `/unipi:skills` and clear **M** on `summarize`. Clear **E**
|
|
58
|
+
to remove the skill.
|
|
59
|
+
|
|
41
60
|
## Agent tools
|
|
42
61
|
|
|
43
62
|
| Tool | What it does |
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pi-unipi/utility",
|
|
3
|
-
"version": "3.0.0-alpha.
|
|
3
|
+
"version": "3.0.0-alpha.24",
|
|
4
4
|
"description": "Utility commands and tools for Pi coding agent — lifecycle, diagnostics, cache, analytics, display, batch execution",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "src/index.ts",
|
|
@@ -36,7 +36,7 @@
|
|
|
36
36
|
"access": "public"
|
|
37
37
|
},
|
|
38
38
|
"dependencies": {
|
|
39
|
-
"@pi-unipi/core": "3.0.0-alpha.
|
|
39
|
+
"@pi-unipi/core": "3.0.0-alpha.24"
|
|
40
40
|
},
|
|
41
41
|
"devDependencies": {},
|
|
42
42
|
"peerDependencies": {
|
|
@@ -0,0 +1,304 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: summarize
|
|
3
|
+
description: |
|
|
4
|
+
Use for every final reply that ends a piece of work (a task, a fix, an
|
|
5
|
+
investigation), and for /unipi:summarize, unless the user asked for full
|
|
6
|
+
detail, raw output, or exact text. Shape: one-sentence answer, numbered
|
|
7
|
+
sections, problems and fixes, not verified, still open, typed questions.
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
# Summarize for the user
|
|
11
|
+
|
|
12
|
+
Use this skill for the final reply after work (a task, an investigation, a
|
|
13
|
+
fix), and when the user runs /unipi:summarize. "The work" below means the
|
|
14
|
+
session, or the part of it you are summarizing: the user's messages, your
|
|
15
|
+
tool calls and their results, and your replies.
|
|
16
|
+
|
|
17
|
+
## When not to use it
|
|
18
|
+
|
|
19
|
+
- The user asked for full detail, raw output, a file, code, or exact text.
|
|
20
|
+
Give them that.
|
|
21
|
+
- The reply is short by nature: a one-line answer, a yes or no, a command,
|
|
22
|
+
a question back to the user. Answer in plain sentences.
|
|
23
|
+
- The reply is in the middle of the work, not at its end.
|
|
24
|
+
|
|
25
|
+
Scale the shape to the work. A small task gets the answer sentence and one
|
|
26
|
+
or two bullets. Use the full shape only when the work has several findings,
|
|
27
|
+
changes, or open items.
|
|
28
|
+
|
|
29
|
+
The reader is the user. They asked for the work but did not watch it. They
|
|
30
|
+
read the summary once, quickly, top to bottom. Each line should tell them
|
|
31
|
+
more than the line before. The answer comes first, then the reasons, then
|
|
32
|
+
the details, then what is left for them.
|
|
33
|
+
|
|
34
|
+
You did the work. Write as "I" and call the reader "you".
|
|
35
|
+
|
|
36
|
+
## Step 1: pick the level
|
|
37
|
+
|
|
38
|
+
Read the user's own messages in the work before you write. Pick one level.
|
|
39
|
+
|
|
40
|
+
- Product level (the default). The user talks about features, screens,
|
|
41
|
+
customers, money, speed, or decisions. Describe what people see and why it
|
|
42
|
+
matters. Use at most three code names in total, and only ones the user needs
|
|
43
|
+
to act on (a file to open, a command to run, a setting to change).
|
|
44
|
+
- Technical level. The user's messages use code names, file paths, commands,
|
|
45
|
+
or error text, or they ask how something works inside the code. Match them:
|
|
46
|
+
name the functions, files, and settings that carry the answer, and explain
|
|
47
|
+
the mechanism. Still start each point with the effect, then the mechanism.
|
|
48
|
+
Count your code names (anything in backticks, plus file, function, route,
|
|
49
|
+
and setting names). Use six or fewer in total. Describe the rest in words. Never give style values, line
|
|
50
|
+
numbers, or full lists of files or pages. Say "about 15 table pages".
|
|
51
|
+
|
|
52
|
+
If the user mixes both, use product level for the answer and the findings.
|
|
53
|
+
Put technical names only where the user must act.
|
|
54
|
+
|
|
55
|
+
## Step 2: the shape
|
|
56
|
+
|
|
57
|
+
```
|
|
58
|
+
<Answer: one sentence. No heading above it.>
|
|
59
|
+
|
|
60
|
+
## 1. <First topic>
|
|
61
|
+
**<One-sentence takeaway of this section.>**
|
|
62
|
+
<diagram, if one fits>
|
|
63
|
+
- **<Label>**: <one or two sentences>
|
|
64
|
+
- **<Label>**: <one or two sentences>
|
|
65
|
+
|
|
66
|
+
## 2. <Next topic>
|
|
67
|
+
...
|
|
68
|
+
|
|
69
|
+
## Problems and fixes (only if the work hit a real obstacle)
|
|
70
|
+
- **<Problem>**: <what blocked the work>. **Fix**: <what I did about it>.
|
|
71
|
+
|
|
72
|
+
## Not verified
|
|
73
|
+
- **<Label>**: <one sentence>
|
|
74
|
+
|
|
75
|
+
## Still open
|
|
76
|
+
- **<Label>**: <one sentence>
|
|
77
|
+
|
|
78
|
+
## Questions for you
|
|
79
|
+
...
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
Read the shape as a report to a manager: what we achieved, how, what got in
|
|
83
|
+
the way and how we solved it, what we did not check, what needs approval.
|
|
84
|
+
|
|
85
|
+
The answer line:
|
|
86
|
+
- Exactly one sentence, 25 words or fewer, with no semicolon. It gives the
|
|
87
|
+
answer, the result, or the main finding. Keep caveats out of it. The one
|
|
88
|
+
exception: a caveat that flips the answer ("the fix is not deployed yet").
|
|
89
|
+
- It states what is true, never what you did. "I traced each issue and
|
|
90
|
+
wrote a plan" is wrong. "The filter count is right, but the list hides 4
|
|
91
|
+
of the 6 statuses" is right. If nothing changed yet, say that after the
|
|
92
|
+
finding, in the same sentence.
|
|
93
|
+
- No label such as "Status:" or "Summary:". Do not restate the request.
|
|
94
|
+
|
|
95
|
+
Topic sections:
|
|
96
|
+
- Use two to four sections, numbered. A heading names its content in two to
|
|
97
|
+
six words: "1. Why wake got slow", "2. What I changed".
|
|
98
|
+
- Put the most important section first. Build from the answer: what is true
|
|
99
|
+
now, then why, then what changed.
|
|
100
|
+
- Every section starts with one bold sentence: the takeaway of that section.
|
|
101
|
+
The user can read only the bold sentences and still get the whole story.
|
|
102
|
+
- Details follow as bullets. Each bullet starts with a bold label of one to
|
|
103
|
+
four words, a colon, then one or two sentences.
|
|
104
|
+
- A section has four bullets or fewer, and the whole summary has 14 bullets
|
|
105
|
+
or fewer. If you have more, group them or keep the ones that matter to the
|
|
106
|
+
user. A bullet that only lists items ("chat, posts, captions, comments")
|
|
107
|
+
can usually merge into the bullet above it.
|
|
108
|
+
|
|
109
|
+
## Step 3: plain words
|
|
110
|
+
|
|
111
|
+
Jargon hides in plain text too, not only in backticks. Before you send, find
|
|
112
|
+
every word a manager outside this project would not know: internal system
|
|
113
|
+
names ("warm assignment", "supernode", "lane"), infrastructure names, and
|
|
114
|
+
abbreviations.
|
|
115
|
+
|
|
116
|
+
- Product level: replace each one with what it does ("the spare pod kept
|
|
117
|
+
ready for the user"). If it appears three times or more, explain it once
|
|
118
|
+
in eight words or fewer and keep it.
|
|
119
|
+
- Technical level: keep it, but explain it once in eight words or fewer the
|
|
120
|
+
first time it appears, unless the user used it first.
|
|
121
|
+
- Write a number with a unit the reader knows: "35 seconds", not "35s p50".
|
|
122
|
+
|
|
123
|
+
## Step 4: break the text
|
|
124
|
+
|
|
125
|
+
- No paragraph longer than three sentences or about 50 words. Break every
|
|
126
|
+
longer block into bullets.
|
|
127
|
+
- Put the important word first in each sentence. Write "**8 of 12** checks
|
|
128
|
+
failed", not "Of the twelve checks that I ran, eight failed".
|
|
129
|
+
- Bold only these: the section takeaway, the bullet labels, and at most one
|
|
130
|
+
key number or name inside a bullet.
|
|
131
|
+
- Use a short paragraph only for one connected line of reasoning, three
|
|
132
|
+
sentences at most.
|
|
133
|
+
|
|
134
|
+
## Step 5: add a diagram when it fits
|
|
135
|
+
|
|
136
|
+
Add a mermaid diagram when the work has one of these:
|
|
137
|
+
- a flow of three or more steps,
|
|
138
|
+
- a chain of three or more causes,
|
|
139
|
+
- three or more parts that send things to each other.
|
|
140
|
+
|
|
141
|
+
Do not draw a diagram for a plain list.
|
|
142
|
+
|
|
143
|
+
Diagram rules:
|
|
144
|
+
- Use `flowchart TD` or `sequenceDiagram`. Never use `flowchart LR`: wide
|
|
145
|
+
diagrams break in a terminal.
|
|
146
|
+
- The diagram shows the subject of its own section, nothing else.
|
|
147
|
+
- Use 7 nodes or fewer. If you need more, split the diagram into two, each
|
|
148
|
+
with its own one-line caption.
|
|
149
|
+
- Labels are one to four plain words. Node ids are single letters: A, B, C.
|
|
150
|
+
Put labels in square brackets. Do not put parentheses, quotes, or colons
|
|
151
|
+
inside a label. Edge labels are one to three words: `A -->|fails| B`.
|
|
152
|
+
- Use the same names in the diagram and in the text.
|
|
153
|
+
- Put the diagram right after the bold takeaway of its section.
|
|
154
|
+
- Use two diagrams at most, and one when the summary is product level.
|
|
155
|
+
|
|
156
|
+
## Step 6: problems and fixes
|
|
157
|
+
|
|
158
|
+
Add this section only when the work hit a real obstacle: something failed,
|
|
159
|
+
blocked progress, or forced a change of plan. Leave it out for normal work.
|
|
160
|
+
|
|
161
|
+
- One bullet per obstacle, three or fewer. Format:
|
|
162
|
+
**<Problem in 2 to 4 words>**: what went wrong, in one sentence.
|
|
163
|
+
**Fix**: what I did about it, in one sentence.
|
|
164
|
+
- If the obstacle is not solved, write **Fix**: none yet, and put the open
|
|
165
|
+
work under "Still open".
|
|
166
|
+
- Do not repeat an obstacle that a topic section already explains.
|
|
167
|
+
|
|
168
|
+
## Step 7: not verified, then still open
|
|
169
|
+
|
|
170
|
+
Write two short sections. Leave out a section when it is empty. Never write
|
|
171
|
+
a bullet that says there is nothing to report.
|
|
172
|
+
|
|
173
|
+
- "Not verified": what the user should trust less. Numbers that came from
|
|
174
|
+
docs or estimates, tests that did not run, causes that are not confirmed.
|
|
175
|
+
- "Still open": work that is not done yet, and risks.
|
|
176
|
+
|
|
177
|
+
Use bullets with bold labels, three or fewer in each section. Include only
|
|
178
|
+
items that bear on what the user asked.
|
|
179
|
+
|
|
180
|
+
## Step 8: questions for you
|
|
181
|
+
|
|
182
|
+
Ask only when the work is blocked on a user decision or on information that
|
|
183
|
+
only the user has. If nothing is blocked, leave out this section.
|
|
184
|
+
|
|
185
|
+
Ask two questions or fewer. Ask a third only when the work is blocked on it. Label each question with its type:
|
|
186
|
+
|
|
187
|
+
```
|
|
188
|
+
**Q1 (pick one)**: Which tier should I cut first?
|
|
189
|
+
- a) Diff rendering, about 1,800 lines **(recommended: largest cut, no runtime risk)**
|
|
190
|
+
- b) Memory fallback, about 800 lines
|
|
191
|
+
- c) Compactor display code, about 900 lines
|
|
192
|
+
|
|
193
|
+
**Q2 (pick any)**: Which tables should get translations in this pass?
|
|
194
|
+
- a) Onboarding review
|
|
195
|
+
- b) Users
|
|
196
|
+
- c) Orders
|
|
197
|
+
|
|
198
|
+
**Q3 (your answer)**: Which three slow users should I check?
|
|
199
|
+
```
|
|
200
|
+
|
|
201
|
+
- Use "pick one" for a single choice, "pick any" when several can apply, and
|
|
202
|
+
"your answer" when the user must type something: a name, a number, a
|
|
203
|
+
preference, or access.
|
|
204
|
+
- Take the question and the options from the work. Never invent a question
|
|
205
|
+
the work did not raise. A question about a step you only propose is an
|
|
206
|
+
offer, so leave it out.
|
|
207
|
+
- Give two or three options. Merge or drop the weakest.
|
|
208
|
+
- Mark an option **(recommended: reason)** only when the work gives a reason.
|
|
209
|
+
Mark one at most. You can mark a risky option **(not recommended: reason)**.
|
|
210
|
+
- A thing the user must do (not a choice) is one line: **To do**: Set the
|
|
211
|
+
search key on the server.
|
|
212
|
+
- A step that waits for the user's permission is one line:
|
|
213
|
+
**Needs approval**: Deploy the fix to production.
|
|
214
|
+
- Do not offer more work ("Do you want me to...", "I can also...").
|
|
215
|
+
|
|
216
|
+
## Sentences
|
|
217
|
+
|
|
218
|
+
- One idea per sentence, 20 words or fewer when you can. Active voice.
|
|
219
|
+
- Simple verbs. No semicolons. One name for one thing, every time.
|
|
220
|
+
- Keep the confidence of the work with one short word inline: "likely",
|
|
221
|
+
"about", "estimated". Put every longer caveat at the end (see Step 5):
|
|
222
|
+
where a number came from, what was not tested, what was not confirmed.
|
|
223
|
+
Never write a section or a bullet about what was measured versus claimed.
|
|
224
|
+
- Copy cause and effect only as the work states it. Never add a fact, number,
|
|
225
|
+
cause, or opinion that is not in the work. This applies to diagram arrows
|
|
226
|
+
too: draw an arrow between two things only when the work says one leads to
|
|
227
|
+
the other.
|
|
228
|
+
- Keep the certainty of the work in both directions. If the work states a
|
|
229
|
+
fact plainly, do not soften it to "likely". If the work guesses, do not
|
|
230
|
+
harden it.
|
|
231
|
+
- Copy numbers exactly: "$26.60", not "about $27".
|
|
232
|
+
- Put a baseline next to a number when the work has one that measures the
|
|
233
|
+
same thing: "3.2 s (was 11 s)".
|
|
234
|
+
|
|
235
|
+
## Cut
|
|
236
|
+
|
|
237
|
+
- Each fact or caveat appears once.
|
|
238
|
+
- Three examples at most in any list inside a sentence.
|
|
239
|
+
- No framing phrases ("The bigger finding is", "In short", "Overall").
|
|
240
|
+
- No "not X but Y", no "X rather than Y", and no "X, not Y" ("mid-June, not months ago", "from a
|
|
241
|
+
test, not production"). State the positive claim. If the user believed
|
|
242
|
+
the wrong thing, say the right thing once.
|
|
243
|
+
- No em dashes. No emoji. No opener, no closer, no offer of more help.
|
|
244
|
+
- No inflated words: robust, seamless, comprehensive, crucial, leverage,
|
|
245
|
+
pivotal, significant, enhance, streamline.
|
|
246
|
+
|
|
247
|
+
## Length
|
|
248
|
+
|
|
249
|
+
- Product level: 120 to 240 words, not counting diagrams.
|
|
250
|
+
- Technical level or very large work: 300 words at most.
|
|
251
|
+
- If the draft is longer, cut the least important bullets first. Do not cut
|
|
252
|
+
the answer, the bold takeaways, or the questions.
|
|
253
|
+
|
|
254
|
+
## Example
|
|
255
|
+
|
|
256
|
+
The work: the user said "people keep getting logged out, fix it". The agent
|
|
257
|
+
found a setting in seconds that the code read as minutes, fixed it, tested on
|
|
258
|
+
staging, and found a second, unrelated bug.
|
|
259
|
+
|
|
260
|
+
```
|
|
261
|
+
Logins now last 24 hours again, after I fixed a setting that ended every session after 24 minutes.
|
|
262
|
+
|
|
263
|
+
## 1. Why people were logged out
|
|
264
|
+
**The session timer used the wrong unit since the 3 May release.**
|
|
265
|
+
- **Cause**: the setting was written in minutes but read as seconds.
|
|
266
|
+
- **Effect**: every session ended after **24 minutes** (should be 24 hours).
|
|
267
|
+
|
|
268
|
+
## 2. What I changed
|
|
269
|
+
**I fixed the unit and tested the fix on staging.**
|
|
270
|
+
- **Fix**: the setting now states its unit, and the code reads it the same way.
|
|
271
|
+
- **Test**: a staging login stayed active for 3 hours with no logout.
|
|
272
|
+
|
|
273
|
+
## Problems and fixes
|
|
274
|
+
- **Bug did not show locally**: my machine kept old sessions alive. **Fix**: I tested on staging with a fresh login.
|
|
275
|
+
|
|
276
|
+
## Not verified
|
|
277
|
+
- **Long sessions**: the staging test ran 3 hours, so a full 24-hour session is untested.
|
|
278
|
+
|
|
279
|
+
## Still open
|
|
280
|
+
- **Production**: the fix is not deployed yet.
|
|
281
|
+
- **Second bug**: the "remember me" box does nothing. It is a separate problem.
|
|
282
|
+
|
|
283
|
+
## Questions for you
|
|
284
|
+
**Q1 (pick one)**: When should I deploy?
|
|
285
|
+
- a) Now **(recommended: users are logged out every 24 minutes)**
|
|
286
|
+
- b) With Friday's release
|
|
287
|
+
```
|
|
288
|
+
|
|
289
|
+
## Check before you send
|
|
290
|
+
|
|
291
|
+
- Is the answer one sentence, with no label and no restated request?
|
|
292
|
+
- Does every section start with a bold takeaway?
|
|
293
|
+
- Is any paragraph longer than three sentences? Break it.
|
|
294
|
+
- Did you match the user's level?
|
|
295
|
+
- If there is a flow of three or more steps, is there a diagram?
|
|
296
|
+
- Is each question labeled with its type, with a recommendation only where
|
|
297
|
+
the work gives a reason?
|
|
298
|
+
- Does any fact, caveat, or number appear twice? Delete the second one.
|
|
299
|
+
- Is there a caveat longer than one word in the answer, a takeaway, or a
|
|
300
|
+
bullet? Move it to the end.
|
|
301
|
+
- Is the word count inside the limit for the level?
|
|
302
|
+
- Would a manager outside this project understand every word? Replace or
|
|
303
|
+
explain the rest.
|
|
304
|
+
- Does every diagram arrow match a cause or step the work states?
|
|
@@ -4,7 +4,7 @@ scope: agent
|
|
|
4
4
|
description: |
|
|
5
5
|
What the @pi-unipi/utility extension does for the user: the /unipi:settings
|
|
6
6
|
hub, /unipi:continue (/unipi:retry), /unipi:cleanup, /unipi:doctor,
|
|
7
|
-
and automatic session naming. It gives the agent no tools.
|
|
7
|
+
/unipi:summarize, and automatic session naming. It gives the agent no tools.
|
|
8
8
|
---
|
|
9
9
|
|
|
10
10
|
# @pi-unipi/utility
|
|
@@ -17,6 +17,7 @@ description: |
|
|
|
17
17
|
| `/unipi:continue` / `/unipi:retry` | Take another turn without new text |
|
|
18
18
|
| `/unipi:cleanup` | Remove stale UniPi temp files (previews and asks first; `--dry-run`, `--yes`) |
|
|
19
19
|
| `/unipi:doctor` | Check config, model cache, Decision Model key, skill exposure |
|
|
20
|
+
| `/unipi:summarize [focus]` | Ask the agent for a session summary (uses the `summarize` skill) |
|
|
20
21
|
|
|
21
22
|
## Notes for the agent
|
|
22
23
|
|
|
@@ -27,6 +27,7 @@ import {
|
|
|
27
27
|
import { registerUtilityCommands } from "./commands.js";
|
|
28
28
|
import { registerAutoRename } from "./rename/index.js";
|
|
29
29
|
import { registerAnswerCommand } from "./answer/index.js";
|
|
30
|
+
import { registerSummarizeCommand } from "./summarize/index.js";
|
|
30
31
|
import { registerAttachments } from "./attach/index.js";
|
|
31
32
|
import { imageCatalogEntries, loadImageConfig, refreshImageModelCache, registerImage } from "./image/index.js";
|
|
32
33
|
import { registerToolRenderers } from "./render/tools.js";
|
|
@@ -66,6 +67,7 @@ export default function (pi: ExtensionAPI) {
|
|
|
66
67
|
registerUtilityCommands(pi);
|
|
67
68
|
registerAutoRename(pi);
|
|
68
69
|
registerAnswerCommand(pi);
|
|
70
|
+
registerSummarizeCommand(pi);
|
|
69
71
|
registerAttachments(pi);
|
|
70
72
|
registerImage(pi);
|
|
71
73
|
const style = readUtilSettings().render.style;
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @pi-unipi/utility — /unipi:summarize [focus]
|
|
3
|
+
*
|
|
4
|
+
* Asks the agent for a summary of the session in the shape the bundled
|
|
5
|
+
* `summarize` skill sets. The command sends `/skill:summarize`, so pi
|
|
6
|
+
* inlines the skill file into the turn, and the agent cannot skip it.
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
import type { ExtensionAPI, ExtensionCommandContext } from "@earendil-works/pi-coding-agent";
|
|
10
|
+
import { UNIPI_PREFIX, UTILITY_COMMANDS } from "@pi-unipi/core";
|
|
11
|
+
|
|
12
|
+
export const SUMMARIZE_SKILL = "summarize";
|
|
13
|
+
|
|
14
|
+
/** The prompt the command sends. `focus` narrows the summary; empty means the whole session. */
|
|
15
|
+
export function summarizePrompt(focus: string): string {
|
|
16
|
+
const f = focus.trim();
|
|
17
|
+
const scope = f
|
|
18
|
+
? `Summarize this session for me, with the focus on: ${f}`
|
|
19
|
+
: "Summarize this session for me: what we did, why, and where it stands now.";
|
|
20
|
+
return `/skill:${SUMMARIZE_SKILL} ${scope} Use only what happened in this session. Do not call tools.`;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
/** True when pi can expand `/skill:summarize` (the skill is loaded and on). */
|
|
24
|
+
export function hasSummarizeSkill(pi: ExtensionAPI): boolean {
|
|
25
|
+
try {
|
|
26
|
+
return pi.getCommands().some((c) => c.name === `skill:${SUMMARIZE_SKILL}`);
|
|
27
|
+
} catch {
|
|
28
|
+
return false;
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
export function registerSummarizeCommand(pi: ExtensionAPI): void {
|
|
33
|
+
pi.registerCommand(`${UNIPI_PREFIX}${UTILITY_COMMANDS.SUMMARIZE}`, {
|
|
34
|
+
description: "Summarize this session for you (answer first, then findings, open items, questions); add text to set a focus",
|
|
35
|
+
handler: async (args: string, ctx: ExtensionCommandContext) => {
|
|
36
|
+
if (!ctx.isIdle()) {
|
|
37
|
+
if (ctx.hasUI) ctx.ui.notify("Agent is busy. Press ESC to interrupt, then try again.", "warning");
|
|
38
|
+
return;
|
|
39
|
+
}
|
|
40
|
+
if (!hasSummarizeSkill(pi)) {
|
|
41
|
+
if (ctx.hasUI) ctx.ui.notify("The summarize skill is off or missing. Turn it on in /unipi:skills.", "warning");
|
|
42
|
+
return;
|
|
43
|
+
}
|
|
44
|
+
pi.sendUserMessage(summarizePrompt(args ?? ""), { expandPromptTemplates: true });
|
|
45
|
+
// sendUserMessage does not wait. Print mode (-p) exits when the handler
|
|
46
|
+
// returns, so wait for the summary turn to start and end.
|
|
47
|
+
await new Promise((r) => setTimeout(r, 0));
|
|
48
|
+
await ctx.waitForIdle?.();
|
|
49
|
+
},
|
|
50
|
+
});
|
|
51
|
+
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pi-unipi/watchdog",
|
|
3
|
-
"version": "3.0.0-alpha.
|
|
3
|
+
"version": "3.0.0-alpha.24",
|
|
4
4
|
"description": "Jev watchdog for long-running tool calls and background tasks — judges stuck work via TypeSafe System One and kills or warns",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "index.ts",
|
|
@@ -32,8 +32,8 @@
|
|
|
32
32
|
"access": "public"
|
|
33
33
|
},
|
|
34
34
|
"dependencies": {
|
|
35
|
-
"@pi-unipi/background-tasks": "3.0.0-alpha.
|
|
36
|
-
"@pi-unipi/core": "3.0.0-alpha.
|
|
35
|
+
"@pi-unipi/background-tasks": "3.0.0-alpha.24",
|
|
36
|
+
"@pi-unipi/core": "3.0.0-alpha.24"
|
|
37
37
|
},
|
|
38
38
|
"peerDependencies": {
|
|
39
39
|
"@earendil-works/pi-coding-agent": "^0.87.1",
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pi-unipi/web-api",
|
|
3
|
-
"version": "3.0.0-alpha.
|
|
3
|
+
"version": "3.0.0-alpha.24",
|
|
4
4
|
"description": "Web search, read, and summarize tools with provider-based backend selection for Pi coding agent",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "src/index.ts",
|
|
@@ -31,7 +31,7 @@
|
|
|
31
31
|
"README.md"
|
|
32
32
|
],
|
|
33
33
|
"dependencies": {
|
|
34
|
-
"@pi-unipi/core": "3.0.0-alpha.
|
|
34
|
+
"@pi-unipi/core": "3.0.0-alpha.24",
|
|
35
35
|
"defuddle": "^0.18.1",
|
|
36
36
|
"linkedom": "^0.18.12",
|
|
37
37
|
"wreq-js": "^2.3.0"
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pi-unipi/workflow",
|
|
3
|
-
"version": "3.0.0-alpha.
|
|
3
|
+
"version": "3.0.0-alpha.24",
|
|
4
4
|
"description": "Plan mode and permission modes for the Pi coding agent",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "index.ts",
|
|
@@ -27,7 +27,7 @@
|
|
|
27
27
|
"access": "public"
|
|
28
28
|
},
|
|
29
29
|
"dependencies": {
|
|
30
|
-
"@pi-unipi/core": "3.0.0-alpha.
|
|
30
|
+
"@pi-unipi/core": "3.0.0-alpha.24"
|
|
31
31
|
},
|
|
32
32
|
"peerDependencies": {
|
|
33
33
|
"@earendil-works/pi-ai": "^0.87.1",
|