@pi-unipi/unipi 2.16.0 → 2.16.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -6,7 +6,11 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/).
6
6
 
7
7
  ## [Unreleased]
8
8
 
9
- ## [2.16.0] — 2026-09-03
9
+ ## [2.16.1] — 2026-09-11
10
+
11
+ ### Fixed
12
+
13
+ - `notify`: **recap no longer silently degrades on thinking models** (GitHub [#36](https://github.com/Neuron-Mr-White/UniPi/issues/36)) — recap summarizes with a 100-token budget, and a thinking model served by llama.cpp/vLLM could burn the entire budget on reasoning tokens and return no visible content, falling back to the raw 100-character truncation. New `recap.disableThinking` config flag (default `false`) sends `chat_template_kwargs: { enable_thinking: false, preserve_thinking: false }` with recap requests so chat-template servers skip reasoning entirely. Opt-in because strict OpenAI-compatible endpoints reject unknown body params; the Anthropic path is unaffected. 5 new tests in `src/__tests__/summarize.test.ts`.
10
14
 
11
15
  ### Added
12
16
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pi-unipi/unipi",
3
- "version": "2.16.0",
3
+ "version": "2.16.1",
4
4
  "description": "All-in-one extension suite for Pi coding agent",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -82,28 +82,28 @@
82
82
  "typebox": "^1.1.38"
83
83
  },
84
84
  "dependencies": {
85
- "@pi-unipi/ask-user": "2.16.0",
86
- "@pi-unipi/background-tasks": "2.16.0",
87
- "@pi-unipi/btw": "2.16.0",
88
- "@pi-unipi/command-enchantment": "2.16.0",
89
- "@pi-unipi/compactor": "2.16.0",
90
- "@pi-unipi/core": "2.16.0",
91
- "@pi-unipi/footer": "2.16.0",
92
- "@pi-unipi/image": "2.16.0",
93
- "@pi-unipi/info-screen": "2.16.0",
94
- "@pi-unipi/input-shortcuts": "2.16.0",
95
- "@pi-unipi/kanboard": "2.16.0",
96
- "@pi-unipi/mcp": "2.16.0",
97
- "@pi-unipi/memory": "2.16.0",
98
- "@pi-unipi/milestone": "2.16.0",
99
- "@pi-unipi/notify": "2.16.0",
100
- "@pi-unipi/ralph": "2.16.0",
101
- "@pi-unipi/subagents": "2.16.0",
102
- "@pi-unipi/trajectory": "2.16.0",
103
- "@pi-unipi/updater": "2.16.0",
104
- "@pi-unipi/utility": "2.16.0",
105
- "@pi-unipi/web-api": "2.16.0",
106
- "@pi-unipi/workflow": "2.16.0"
85
+ "@pi-unipi/ask-user": "2.16.1",
86
+ "@pi-unipi/background-tasks": "2.16.1",
87
+ "@pi-unipi/btw": "2.16.1",
88
+ "@pi-unipi/command-enchantment": "2.16.1",
89
+ "@pi-unipi/compactor": "2.16.1",
90
+ "@pi-unipi/core": "2.16.1",
91
+ "@pi-unipi/footer": "2.16.1",
92
+ "@pi-unipi/image": "2.16.1",
93
+ "@pi-unipi/info-screen": "2.16.1",
94
+ "@pi-unipi/input-shortcuts": "2.16.1",
95
+ "@pi-unipi/kanboard": "2.16.1",
96
+ "@pi-unipi/mcp": "2.16.1",
97
+ "@pi-unipi/memory": "2.16.1",
98
+ "@pi-unipi/milestone": "2.16.1",
99
+ "@pi-unipi/notify": "2.16.1",
100
+ "@pi-unipi/ralph": "2.16.1",
101
+ "@pi-unipi/subagents": "2.16.1",
102
+ "@pi-unipi/trajectory": "2.16.1",
103
+ "@pi-unipi/updater": "2.16.1",
104
+ "@pi-unipi/utility": "2.16.1",
105
+ "@pi-unipi/web-api": "2.16.1",
106
+ "@pi-unipi/workflow": "2.16.1"
107
107
  },
108
108
  "devDependencies": {
109
109
  "@earendil-works/pi-agent-core": "^0.84.0",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pi-unipi/ask-user",
3
- "version": "2.16.0",
3
+ "version": "2.16.1",
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": "2.16.0"
43
+ "@pi-unipi/core": "2.16.1"
44
44
  },
45
45
  "peerDependencies": {
46
46
  "@earendil-works/pi-coding-agent": "^0.84.0",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pi-unipi/command-enchantment",
3
- "version": "2.16.0",
3
+ "version": "2.16.1",
4
4
  "description": "Enhanced TUI autocomplete for /unipi:* commands — colored, sorted, and grouped by package",
5
5
  "type": "module",
6
6
  "main": "src/index.ts",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pi-unipi/background-tasks",
3
- "version": "2.16.0",
3
+ "version": "2.16.1",
4
4
  "description": "Background tasks for UniPi — durable shell jobs, delegated agents, attested Pi runs, and fixed-purpose Fusion workflows",
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.84.0",
13
- "@pi-unipi/core": "2.16.0",
13
+ "@pi-unipi/core": "2.16.1",
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": "2.16.0",
3
+ "version": "2.16.1",
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.84.0"
38
38
  },
39
39
  "dependencies": {
40
- "@pi-unipi/core": "2.16.0"
40
+ "@pi-unipi/core": "2.16.1"
41
41
  },
42
42
  "pi": {
43
43
  "extensions": [
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pi-unipi/compactor",
3
- "version": "2.16.0",
3
+ "version": "2.16.1",
4
4
  "description": "Context engine for Pi — zero-LLM compaction, session continuity, sandbox execution, and tool display optimization",
5
5
  "type": "module",
6
6
  "main": "src/index.ts",
@@ -34,8 +34,8 @@
34
34
  "access": "public"
35
35
  },
36
36
  "dependencies": {
37
- "@pi-unipi/core": "2.16.0",
38
- "@pi-unipi/info-screen": "2.16.0",
37
+ "@pi-unipi/core": "2.16.1",
38
+ "@pi-unipi/info-screen": "2.16.1",
39
39
  "@earendil-works/pi-agent-core": "^0.84.0"
40
40
  },
41
41
  "peerDependencies": {
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pi-unipi/core",
3
- "version": "2.16.0",
3
+ "version": "2.16.1",
4
4
  "description": "Shared utilities, event types, and constants for Unipi extension suite",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pi-unipi/footer",
3
- "version": "2.16.0",
3
+ "version": "2.16.1",
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": "2.16.0",
36
- "@pi-unipi/background-tasks": "2.16.0"
35
+ "@pi-unipi/core": "2.16.1",
36
+ "@pi-unipi/background-tasks": "2.16.1"
37
37
  },
38
38
  "peerDependencies": {
39
39
  "@earendil-works/pi-coding-agent": "^0.84.0",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pi-unipi/image",
3
- "version": "2.16.0",
3
+ "version": "2.16.1",
4
4
  "description": "Image generation and image recognition tools for the Pi coding agent",
5
5
  "type": "module",
6
6
  "main": "src/index.ts",
@@ -34,7 +34,7 @@
34
34
  "access": "public"
35
35
  },
36
36
  "dependencies": {
37
- "@pi-unipi/core": "2.16.0"
37
+ "@pi-unipi/core": "2.16.1"
38
38
  },
39
39
  "peerDependencies": {
40
40
  "@earendil-works/pi-ai": "^0.84.0",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pi-unipi/info-screen",
3
- "version": "2.16.0",
3
+ "version": "2.16.1",
4
4
  "description": "Dashboard and module registry for Unipi — configurable info overlay with tabbed groups",
5
5
  "type": "module",
6
6
  "main": "index.ts",
@@ -33,7 +33,7 @@
33
33
  "access": "public"
34
34
  },
35
35
  "dependencies": {
36
- "@pi-unipi/core": "2.16.0"
36
+ "@pi-unipi/core": "2.16.1"
37
37
  },
38
38
  "peerDependencies": {
39
39
  "@earendil-works/pi-coding-agent": "^0.84.0",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pi-unipi/input-shortcuts",
3
- "version": "2.16.0",
3
+ "version": "2.16.1",
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": "2.16.0"
36
+ "@pi-unipi/core": "2.16.1"
37
37
  },
38
38
  "peerDependencies": {
39
39
  "@earendil-works/pi-coding-agent": "^0.84.0",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pi-unipi/kanboard",
3
- "version": "2.16.0",
3
+ "version": "2.16.1",
4
4
  "description": "Visualization layer for unipi workflow — HTTP server with htmx/Alpine.js UI, modular parsers, TUI overlay, and kanban board",
5
5
  "type": "module",
6
6
  "main": "index.ts",
@@ -39,7 +39,7 @@
39
39
  "access": "public"
40
40
  },
41
41
  "dependencies": {
42
- "@pi-unipi/core": "2.16.0"
42
+ "@pi-unipi/core": "2.16.1"
43
43
  },
44
44
  "peerDependencies": {
45
45
  "@earendil-works/pi-coding-agent": "^0.84.0",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pi-unipi/mcp",
3
- "version": "2.16.0",
3
+ "version": "2.16.1",
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": "2.16.0"
33
+ "@pi-unipi/core": "2.16.1"
34
34
  },
35
35
  "peerDependencies": {
36
36
  "@earendil-works/pi-coding-agent": "^0.84.0",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pi-unipi/memory",
3
- "version": "2.16.0",
3
+ "version": "2.16.1",
4
4
  "description": "Persistent cross-session memory with MemPalace backend (auto-installed) and SQLite fallback for Pi coding agent",
5
5
  "type": "module",
6
6
  "main": "index.ts",
@@ -39,8 +39,8 @@
39
39
  "README.md"
40
40
  ],
41
41
  "dependencies": {
42
- "@pi-unipi/core": "2.16.0",
43
- "@pi-unipi/info-screen": "2.16.0",
42
+ "@pi-unipi/core": "2.16.1",
43
+ "@pi-unipi/info-screen": "2.16.1",
44
44
  "js-yaml": "^4.1.0"
45
45
  },
46
46
  "peerDependencies": {
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pi-unipi/milestone",
3
- "version": "2.16.0",
3
+ "version": "2.16.1",
4
4
  "description": "Lifecycle layer for project-level goals — MILESTONES.md tracking, session hooks, auto-sync",
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": "2.16.0"
35
+ "@pi-unipi/core": "2.16.1"
36
36
  },
37
37
  "peerDependencies": {
38
38
  "@earendil-works/pi-coding-agent": "^0.84.0",
@@ -120,6 +120,22 @@ Settings stored at `~/.unipi/config/notify/config.json`. Edit via `/unipi:notify
120
120
 
121
121
  Per-event platform routing lets you control where each event type goes. The settings overlay shows all events with platform toggles.
122
122
 
123
+ ### Recap (thinking models)
124
+
125
+ Recap summarizes the last assistant message into a one-line push notification (100-token budget). Thinking models served by llama.cpp or vLLM can spend that entire budget on reasoning and return nothing, falling back to a plain 100-character truncation. If your recap endpoint supports chat-template kwargs, set `recap.disableThinking` to skip reasoning tokens:
126
+
127
+ ```json
128
+ {
129
+ "recap": {
130
+ "enabled": true,
131
+ "model": "localhost/gemma-4-e4b",
132
+ "disableThinking": true
133
+ }
134
+ }
135
+ ```
136
+
137
+ This sends `chat_template_kwargs: { enable_thinking: false, preserve_thinking: false }` with the request. Keep it `false` (the default) for strict OpenAI-compatible endpoints — they reject unknown params. Anthropic models are unaffected (thinking is opt-in there).
138
+
123
139
  ## License
124
140
 
125
141
  MIT
@@ -352,7 +352,9 @@ function registerAgentNotification(
352
352
  .then((apiKeyResult) => {
353
353
  const apiKey = apiKeyResult.ok ? (apiKeyResult as { apiKey?: string }).apiKey : undefined;
354
354
  if (apiKey) {
355
- return summarizeLastMessage(lastText, apiKey, model.baseUrl, model.api, modelId)
355
+ return summarizeLastMessage(lastText, apiKey, model.baseUrl, model.api, modelId, {
356
+ disableThinking: config.recap.disableThinking,
357
+ })
356
358
  .then((recap) => sessionName ? `${sessionName}: ${recap}` : recap);
357
359
  }
358
360
  return buildAgentLifecycleMessage(eventKey, sessionName);
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pi-unipi/notify",
3
- "version": "2.16.0",
3
+ "version": "2.16.1",
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": "2.16.0",
37
+ "@pi-unipi/core": "2.16.1",
38
38
  "node-notifier": "^10.0.1"
39
39
  },
40
40
  "peerDependencies": {
@@ -45,6 +45,7 @@ export const DEFAULT_CONFIG: NotifyConfig = {
45
45
  recap: {
46
46
  enabled: false,
47
47
  model: "openrouter/openai/gpt-oss-20b",
48
+ disableThinking: false,
48
49
  },
49
50
  silenceAfterInput: {
50
51
  enabled: false,
@@ -12,6 +12,17 @@ const MAX_TOKENS = 100;
12
12
  const TIMEOUT_MS = 10_000;
13
13
  const FALLBACK_TRUNCATE_CHARS = 100;
14
14
 
15
+ /** Options for summarizeLastMessage */
16
+ export interface SummarizeOptions {
17
+ /**
18
+ * Send `chat_template_kwargs: { enable_thinking: false, preserve_thinking: false }`
19
+ * on OpenAI-compatible requests (llama.cpp / vLLM chat templates) so thinking
20
+ * models don't burn the token budget on reasoning (issue #36). Anthropic
21
+ * ignores this — thinking is opt-in there already.
22
+ */
23
+ disableThinking?: boolean;
24
+ }
25
+
15
26
  /**
16
27
  * Summarize a message using an LLM.
17
28
  *
@@ -20,6 +31,7 @@ const FALLBACK_TRUNCATE_CHARS = 100;
20
31
  * @param baseUrl - Provider base URL (from Model.baseUrl)
21
32
  * @param api - API type (from Model.api, e.g. "openai-completions")
22
33
  * @param modelId - Model ID to use
34
+ * @param opts - Optional summarization options
23
35
  * @returns Summarized text, or truncated original on failure
24
36
  */
25
37
  export async function summarizeLastMessage(
@@ -28,6 +40,7 @@ export async function summarizeLastMessage(
28
40
  baseUrl: string,
29
41
  api: string,
30
42
  modelId: string,
43
+ opts?: SummarizeOptions,
31
44
  ): Promise<string> {
32
45
  // Truncate input if too long
33
46
  const input =
@@ -41,7 +54,7 @@ export async function summarizeLastMessage(
41
54
  return await callAnthropic(baseUrl, apiKey, modelId, input);
42
55
  }
43
56
  // Default: OpenAI-compatible (covers openai-completions, openai-responses, etc.)
44
- return await callOpenAICompatible(baseUrl, apiKey, modelId, input);
57
+ return await callOpenAICompatible(baseUrl, apiKey, modelId, input, opts);
45
58
  } catch {
46
59
  return fallbackSummary(messageText);
47
60
  }
@@ -53,6 +66,7 @@ async function callOpenAICompatible(
53
66
  apiKey: string,
54
67
  modelId: string,
55
68
  input: string,
69
+ opts?: SummarizeOptions,
56
70
  ): Promise<string> {
57
71
  const url = `${baseUrl.replace(/\/$/, "")}/chat/completions`;
58
72
  const controller = new AbortController();
@@ -68,6 +82,14 @@ async function callOpenAICompatible(
68
82
  body: JSON.stringify({
69
83
  model: modelId,
70
84
  max_tokens: MAX_TOKENS,
85
+ ...(opts?.disableThinking
86
+ ? {
87
+ chat_template_kwargs: {
88
+ enable_thinking: false,
89
+ preserve_thinking: false,
90
+ },
91
+ }
92
+ : {}),
71
93
  messages: [
72
94
  { role: "system", content: SYSTEM_PROMPT },
73
95
  { role: "user", content: input },
@@ -69,6 +69,15 @@ export interface RecapConfig {
69
69
  enabled: boolean;
70
70
  /** Model to use for recap (e.g. "openrouter/openai/gpt-oss-20b") */
71
71
  model: string;
72
+ /**
73
+ * Send `chat_template_kwargs: { enable_thinking: false, preserve_thinking: false }`
74
+ * with recap requests so llama.cpp/vLLM-style servers skip reasoning tokens.
75
+ * Without this, a thinking model can burn the entire 100-token budget on
76
+ * reasoning and return no summary (issue #36). Only enable for endpoints
77
+ * that accept these params — strict OpenAI-compatible servers reject them.
78
+ * The Anthropic path ignores this (thinking is opt-in there already).
79
+ */
80
+ disableThinking?: boolean;
72
81
  }
73
82
 
74
83
  /** Quiet listed platforms after recent terminal input */
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pi-unipi/ralph",
3
- "version": "2.16.0",
3
+ "version": "2.16.1",
4
4
  "description": "Long-running iterative development loops for Pi coding agent",
5
5
  "type": "module",
6
6
  "main": "index.ts",
@@ -31,8 +31,8 @@
31
31
  "test": "npx tsx --test reminder.test.ts"
32
32
  },
33
33
  "dependencies": {
34
- "@pi-unipi/core": "2.16.0",
35
- "@pi-unipi/info-screen": "2.16.0"
34
+ "@pi-unipi/core": "2.16.1",
35
+ "@pi-unipi/info-screen": "2.16.1"
36
36
  },
37
37
  "peerDependencies": {
38
38
  "@earendil-works/pi-ai": "^0.84.0",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pi-unipi/subagents",
3
- "version": "2.16.0",
3
+ "version": "2.16.1",
4
4
  "description": "Subagents for UniPi — parallel execution, file locking, workflow integration",
5
5
  "type": "module",
6
6
  "main": "src/index.ts",
@@ -9,7 +9,7 @@
9
9
  "test": "npx tsx --test src/__tests__/*.test.ts"
10
10
  },
11
11
  "dependencies": {
12
- "@pi-unipi/core": "2.16.0",
12
+ "@pi-unipi/core": "2.16.1",
13
13
  "@earendil-works/pi-agent-core": "^0.84.0",
14
14
  "acorn": "8.18.0"
15
15
  },
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pi-unipi/trajectory",
3
- "version": "2.16.0",
3
+ "version": "2.16.1",
4
4
  "description": "Live UniPi trajectory inspector for Pi sessions",
5
5
  "type": "module",
6
6
  "main": "index.ts",