pi-ui-extend 1.0.39 → 1.0.40

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.
@@ -3,7 +3,7 @@ import * as path from "node:path";
3
3
  import type { Api, AssistantMessage, ImageContent, Model, ProviderHeaders, TextContent } from "@earendil-works/pi-ai";
4
4
  import { Type } from "typebox";
5
5
 
6
- import { loadPiToolsSuiteConfig, DEFAULT_CODING_DISCIPLINE_STRICTNESS, type CodingDisciplineStrictness } from "../config.js";
6
+ import { loadPiToolsSuiteConfig } from "../config.js";
7
7
  import { ignoreStaleExtensionContextError } from "../context-usage.js";
8
8
  import { completeWithModelRegistry, type ModelCompletionRegistry } from "../model-completion.js";
9
9
 
@@ -41,13 +41,6 @@ const DEFAULT_LOOKUP_MAX_IMAGES = 6;
41
41
  const DEFAULT_LOOKUP_MAX_TOKENS = 1_600;
42
42
  const DEFAULT_LOOKUP_TIMEOUT_MS = 120_000;
43
43
  const MAX_IMAGE_BYTES = 16 * 1024 * 1024;
44
- // Keep recovery nudges sparse: newer GLM coding models are substantially better at
45
- // long-horizon tool use, and repeated developer reminders can become prompt noise.
46
- const SILENCE_REMINDER_MIN_VIOLATION_GAP = 5;
47
- const SILENCE_REMINDER_MIN_MESSAGE_GAP = 20;
48
- // When the visible history shrinks by more than this many messages (compaction or
49
- // truncation), the chatter baseline is reset so it isn't measured against a stale peak.
50
- const SILENCE_REMINDER_COMPACTION_MARGIN = 8;
51
44
  const LOOKUP_TOOL_NAME = "lookup";
52
45
 
53
46
  const LOOKUP_TOOL_PARAMS = Type.Object(
@@ -65,48 +58,46 @@ const LOOKUP_TOOL_PARAMS = Type.Object(
65
58
  { additionalProperties: false },
66
59
  );
67
60
 
68
- type DisciplinePromptOptions = { lookupEnabled?: boolean; strictness?: CodingDisciplineStrictness };
61
+ type DisciplinePromptOptions = { lookupEnabled?: boolean };
69
62
 
70
- /**
71
- * Builds the tool-only contract lines. The working-state rule is strictness-aware:
72
- * - "strict" — one tool call per turn, no assistant text at all (Opus-like);
73
- * - "lenient" — independent (especially read-only) calls may be batched, and brief
74
- * substantive reasoning text is acceptable when thinking is off.
75
- */
76
- function buildDisciplineLines(strictness: CodingDisciplineStrictness): readonly string[] {
77
- const isStrict = strictness === "strict";
78
- return [
79
- "TOOL-ONLY CODING AGENT CONTRACT.",
80
- "",
81
- "Follow this output-channel contract literally for coding tasks.",
82
- isStrict
83
- ? "WORKING STATE: from the first assistant turn until complete, final, or blocked, emit exactly one tool call with empty text."
84
- : "WORKING STATE: from the first assistant turn until complete, final, or blocked, emit tool calls with empty text.",
85
- isStrict
86
- ? "No prose, markdown, acknowledgments, plans, progress, summaries, explanations, or commentary before/after tool calls."
87
- : "Batch independent calls in one turn (especially read-only inspection: read/grep/glob/bash); make dependent calls sequentially. Avoid filler prose, acknowledgments, restatements, and narration of obvious next steps.",
88
- "Keep reasoning, planning, hypotheses, and retry decisions internal when thinking is on; when thinking is off, brief substantive reasoning text is acceptable.",
89
- "",
90
- "After every tool result, choose exactly one transition:",
91
- isStrict ? "- WORKING: exactly one next tool call with empty text;" : "- WORKING: one or more independent tool calls with empty text;",
92
- "- FINAL: one final answer after completion or practical verification;",
93
- "- BLOCKED: one concise question only when no safe/useful tool action can continue.",
94
- isStrict
95
- ? "No transition permits commentary between tool calls."
96
- : "When a thinking/reasoning channel is available, do not duplicate that reasoning as visible commentary between tool calls.",
97
- "",
98
- "PRIORITY: this overrides default assistant friendliness and conversational behavior.",
99
- "",
100
- "Coding discipline (express only through tool choices, not prose):",
101
- "- inspect before editing; do not invent APIs, files, commands, or behavior;",
102
- "- make the smallest change that fully fixes the issue; follow nearby conventions;",
103
- "- for bugs, prefer a failing repro first, then the minimal fix, then verify;",
104
- "- high-risk changes (security, data/schema, public APIs, concurrency, irreversible) need a short spec first;",
105
- "- handle edge cases, errors, cancellation, and async behavior; do not block UI/event loops;",
106
- "- avoid duplicate state, duplicate prompts, and repeated side effects;",
107
- "- write code, identifiers, comments, and commit messages in English.",
108
- ];
109
- }
63
+ const QUALITY_DISCIPLINE_LINES = [
64
+ "GLM CODING QUALITY CONTRACT.",
65
+ "",
66
+ "Optimize for correct, evidence-backed changes rather than fast patching or conversational polish.",
67
+ "",
68
+ "Evidence and hypothesis discipline:",
69
+ "- inspect before editing; do not invent APIs, files, commands, behavior, or repository conventions;",
70
+ "- separate observed facts from hypotheses; do not commit to the first plausible root cause;",
71
+ "- for non-obvious bugs, keep at least two plausible hypotheses until evidence distinguishes them, and choose the next inspection/test for information gain;",
72
+ "- do not use edits as diagnostic probes when read/search/repro/test evidence can answer the question first;",
73
+ "- when behavior crosses modules, trace the relevant execution/data flow before editing instead of serially opening plausible files; use indexed architecture/search/dependency tools when available;",
74
+ "- before changing an API, state contract, persistence format, or async lifecycle, inspect relevant callers, consumers, tests, persistence boundaries, and cancellation/error paths.",
75
+ "",
76
+ "Implementation discipline:",
77
+ "- make the smallest change that fully fixes the issue and follow nearby conventions;",
78
+ "- for bugs, reproduce the failure or its defining condition when practical before changing code;",
79
+ "- high-risk changes (security, data/schema, public APIs, concurrency, irreversible behavior) need a short evidence-backed spec before implementation;",
80
+ "- handle relevant edge cases, errors, cancellation, stale state, and async behavior; do not block UI/event loops;",
81
+ "- avoid duplicate state, duplicate prompts, repeated side effects, and speculative refactors unrelated to the verified cause;",
82
+ "- write code, identifiers, comments, and commit messages in English.",
83
+ "",
84
+ "Failure and retry discipline:",
85
+ "- treat failed verification as new evidence; do not repeat the same approach with cosmetic variations;",
86
+ "- after two materially failed fix/verification attempts, stop patching: re-inspect evidence, revise the root-cause hypothesis, or escalate for an independent opinion.",
87
+ "",
88
+ "Verification discipline:",
89
+ "- verification must cover the behavioral claim that justified the change; typecheck/build/lint prove structural validity, not behavioral correctness;",
90
+ "- for bug fixes, verify the old failure or its defining condition no longer occurs whenever practical;",
91
+ "- for async/stateful changes, verify the success path plus the relevant cancellation, error, retry, duplicate-event, or stale-state path;",
92
+ "- before finalizing a non-trivial change, actively inspect or test one likely counterexample, regression path, or missed edge case;",
93
+ "- never claim a test/check passed unless it actually ran and its result was observed.",
94
+ "",
95
+ "Escalation discipline:",
96
+ "- when async subagents are available, use an independent `oracle` (preferably Sol through the configured oracle role) when focused inspection still leaves conflicting evidence, multiple incompatible root causes, a subtle cross-module invariant you cannot verify locally, or a high-risk security/schema/public-API/concurrency/irreversible decision;",
97
+ "- also escalate after two materially different fixes fail for the same unresolved cause;",
98
+ "- do not escalate routine implementation, mechanical edits, straightforward test failures, or facts that local tools can verify directly;",
99
+ "- treat oracle output as a second opinion, not authority: reconcile it with repository evidence before acting.",
100
+ ];
110
101
 
111
102
  const LOOKUP_DISCIPLINE_LINES = [
112
103
  "",
@@ -120,17 +111,9 @@ const LOOKUP_DISCIPLINE_LINES = [
120
111
  const FINAL_DISCIPLINE_LINES = [
121
112
  "",
122
113
  "When uncertain, test or inspect instead of assuming; otherwise proceed with grounded best effort.",
123
- "Verify every non-trivial change. Never claim tests passed unless actually run.",
124
114
  "Final report: what changed, what was verified, what was not verified, and any risks.",
125
115
  ];
126
116
 
127
- const SILENCE_REMINDER_TEXT = [
128
- "GLM silence reminder: remain in WORKING state.",
129
- "Continue with tool-only discipline: inspect, verify, and act through tools only.",
130
- "For the next step, emit tool calls with no accompanying assistant text.",
131
- "Do not acknowledge this reminder.",
132
- ].join("\n");
133
-
134
117
  const LEGACY_SILENT_PROMPT_BLOCK_PATTERN = new RegExp(
135
118
  `${escapeRegExp(SILENT_PROMPT_MARKER_START)}[\\s\\S]*?${escapeRegExp(SILENT_PROMPT_MARKER_END)}\\s*`,
136
119
  "g",
@@ -167,10 +150,6 @@ const LOOKUP_SYSTEM_PROMPT = [
167
150
  export default function codingDiscipline(pi: ExtensionAPI) {
168
151
  let selectedModelRef: string | undefined;
169
152
  let lookupRegistered = false;
170
- let silenceViolationCount = 0;
171
- let lastReminderViolationCount = 0;
172
- let lastReminderMessageCount = -SILENCE_REMINDER_MIN_MESSAGE_GAP;
173
- let peakMessageCount = 0;
174
153
 
175
154
  function maybeRegisterLookupTool(cwd?: string): void {
176
155
  if (lookupRegistered) return;
@@ -220,7 +199,6 @@ export default function codingDiscipline(pi: ExtensionAPI) {
220
199
  const cwd = contextCwd(ctx);
221
200
  const injected = injectCodingDisciplineIntoPayload(event.payload, {
222
201
  lookupEnabled: Boolean(lookupModelFromConfig(cwd)) && isBlindGlmModel(modelRef),
223
- strictness: codingDisciplineStrictnessFromConfig(cwd),
224
202
  });
225
203
  if (process.env.PI_DEBUG_PROMPT === "1") {
226
204
  logFinalPrompt(injected, modelRef, contextCwd(ctx) ?? process.cwd());
@@ -292,36 +270,6 @@ export default function codingDiscipline(pi: ExtensionAPI) {
292
270
  return undefined;
293
271
  });
294
272
 
295
- pi.on("context", async (event: { messages?: unknown[] }, ctx: unknown) => {
296
- const modelRef = selectedModelRef ?? modelRefFromContext(ctx);
297
- if (!isGlmModel(modelRef) || !Array.isArray(event.messages)) return undefined;
298
-
299
- const messageCount = event.messages.length;
300
- // Compaction/truncation prunes the visible history. Reset the stale chatter
301
- // baseline so the post-compaction turn isn't measured against a pre-compaction
302
- // violation peak (otherwise the model could chatter freely until the count
303
- // climbed back above the old peak, or get nagged on a freshly small count).
304
- if (messageCount + SILENCE_REMINDER_COMPACTION_MARGIN < peakMessageCount) {
305
- silenceViolationCount = 0;
306
- lastReminderViolationCount = 0;
307
- lastReminderMessageCount = messageCount - SILENCE_REMINDER_MIN_MESSAGE_GAP;
308
- }
309
- peakMessageCount = Math.max(peakMessageCount, messageCount);
310
-
311
- const strictness = codingDisciplineStrictnessFromConfig(contextCwd(ctx));
312
- const violationCount = countAssistantToolChatter(event.messages, strictness);
313
- if (violationCount <= silenceViolationCount) return undefined;
314
-
315
- const violationGap = violationCount - lastReminderViolationCount;
316
- const messageGap = messageCount - lastReminderMessageCount;
317
- silenceViolationCount = violationCount;
318
-
319
- if (violationGap < SILENCE_REMINDER_MIN_VIOLATION_GAP && messageGap < SILENCE_REMINDER_MIN_MESSAGE_GAP) return undefined;
320
-
321
- lastReminderViolationCount = violationCount;
322
- lastReminderMessageCount = messageCount;
323
- return { messages: [...event.messages, createSilenceReminderMessage()] };
324
- });
325
273
  }
326
274
 
327
275
  export function prependCodingDisciplinePrompt(systemPrompt: string, options: DisciplinePromptOptions = {}): string {
@@ -335,10 +283,9 @@ export function prependCodingDisciplinePrompt(systemPrompt: string, options: Dis
335
283
  }
336
284
 
337
285
  export function buildCodingDisciplinePrompt(options: DisciplinePromptOptions = {}): string {
338
- const strictness = options.strictness ?? DEFAULT_CODING_DISCIPLINE_STRICTNESS;
339
286
  return [
340
287
  DISCIPLINE_PROMPT_MARKER_START,
341
- ...buildDisciplineLines(strictness),
288
+ ...QUALITY_DISCIPLINE_LINES,
342
289
  ...(options.lookupEnabled ? LOOKUP_DISCIPLINE_LINES : []),
343
290
  ...FINAL_DISCIPLINE_LINES,
344
291
  DISCIPLINE_PROMPT_MARKER_END,
@@ -637,58 +584,10 @@ function isInstructionMessage(message: unknown): boolean {
637
584
  return message.role === "system" || message.role === "developer";
638
585
  }
639
586
 
640
- function countAssistantToolChatter(messages: readonly unknown[], strictness: CodingDisciplineStrictness): number {
641
- let count = 0;
642
- for (const message of messages) {
643
- if (!isAssistantToolChatter(message, strictness)) continue;
644
- count++;
645
- }
646
- return count;
647
- }
648
-
649
- /**
650
- * Detects assistant chatter (text alongside a tool call).
651
- * - "strict" — any such text counts as chatter.
652
- * - "lenient" — text counts only when a thinking/reasoning block already captured the
653
- * reasoning; without a thinking block, the visible text is the model's only reasoning
654
- * channel and must not be suppressed.
655
- */
656
- function isAssistantToolChatter(message: unknown, strictness: CodingDisciplineStrictness): boolean {
657
- if (!isRecord(message) || message.role !== "assistant") return false;
658
- if (!Array.isArray(message.content)) return false;
659
- const hasToolCall = message.content.some((part) => isRecord(part) && part.type === "toolCall");
660
- if (!hasToolCall) return false;
661
- const hasText = message.content.some((part) => isRecord(part) && part.type === "text" && hasNonEmptyText(part.text));
662
- if (!hasText) return false;
663
- if (strictness === "strict") return true;
664
- const hasThinking = message.content.some(
665
- (part) => isRecord(part) && (part.type === "thinking" || part.type === "reasoning"),
666
- );
667
- return Boolean(hasThinking);
668
- }
669
-
670
- function hasNonEmptyText(value: unknown): boolean {
671
- return typeof value === "string" && value.trim().length > 0;
672
- }
673
-
674
- function createSilenceReminderMessage() {
675
- return {
676
- // Inject as a developer/system-level nudge rather than impersonating the user,
677
- // so it reads as an automated reminder, not a user instruction.
678
- role: "developer" as const,
679
- content: [{ type: "text" as const, text: SILENCE_REMINDER_TEXT }],
680
- timestamp: Date.now(),
681
- };
682
- }
683
-
684
587
  function lookupModelFromConfig(cwd?: string): string | undefined {
685
588
  return loadPiToolsSuiteConfig(["coding-discipline"], { cwd: cwd ?? process.cwd() }).lookupModel;
686
589
  }
687
590
 
688
- function codingDisciplineStrictnessFromConfig(cwd?: string): CodingDisciplineStrictness {
689
- return loadPiToolsSuiteConfig(["coding-discipline"], { cwd: cwd ?? process.cwd() }).codingDisciplineStrictness ?? DEFAULT_CODING_DISCIPLINE_STRICTNESS;
690
- }
691
-
692
591
  function buildLookupPrompt(params: LookupParams, recentContext: string, imageCount: number, warnings: string[]): string {
693
592
  return [
694
593
  "Lookup request from a text-only GLM parent model.",
@@ -12,14 +12,6 @@ export interface PiToolsSuiteConfig {
12
12
  todoThinkingOverrides: Record<string, TodoThinkingLevel>;
13
13
  /** Vision-capable model used by the coding-discipline lookup tool; unset disables lookup. */
14
14
  lookupModel?: string;
15
- /**
16
- * Chatter-detector strictness for the coding-discipline module:
17
- * "strict" — any assistant text alongside a tool call is chatter (Opus-like);
18
- * "lenient" — text is only chatter when a thinking block already captured the
19
- * reasoning; without thinking, visible text is the reasoning channel.
20
- * Default: "lenient".
21
- */
22
- codingDisciplineStrictness?: CodingDisciplineStrictness;
23
15
  }
24
16
 
25
17
  type MutableConfig = {
@@ -28,12 +20,8 @@ type MutableConfig = {
28
20
  todoThinking: boolean;
29
21
  todoThinkingOverrides: Map<string, TodoThinkingLevel>;
30
22
  lookupModel: string | undefined;
31
- codingDisciplineStrictness: CodingDisciplineStrictness;
32
23
  };
33
24
 
34
- export const CODING_DISCIPLINE_STRICTNESS_VALUES = ["strict", "lenient"] as const;
35
- export type CodingDisciplineStrictness = (typeof CODING_DISCIPLINE_STRICTNESS_VALUES)[number];
36
- export const DEFAULT_CODING_DISCIPLINE_STRICTNESS: CodingDisciplineStrictness = "lenient";
37
25
  const TODO_THINKING_OVERRIDE_LEVELS = ["off", "minimal", "low", "medium", "high", "xhigh", "max"] as const;
38
26
  export type TodoThinkingLevel = (typeof TODO_THINKING_OVERRIDE_LEVELS)[number];
39
27
 
@@ -80,10 +68,6 @@ function normalizeLookupModel(raw: unknown): string | undefined {
80
68
  return trimmed ? trimmed : undefined;
81
69
  }
82
70
 
83
- function normalizeCodingDisciplineStrictness(raw: unknown): CodingDisciplineStrictness {
84
- return raw === "strict" ? "strict" : "lenient";
85
- }
86
-
87
71
  function isTodoThinkingLevel(raw: unknown): raw is TodoThinkingLevel {
88
72
  return TODO_THINKING_OVERRIDE_LEVELS.includes(raw as TodoThinkingLevel);
89
73
  }
@@ -161,9 +145,6 @@ function mergeConfigLayer(config: MutableConfig, raw: Record<string, unknown>, k
161
145
  if (typeof raw.todoThinking === "boolean") config.todoThinking = raw.todoThinking;
162
146
  mergeTodoThinkingOverrides(config, raw.todoThinkingOverrides);
163
147
  if (Object.prototype.hasOwnProperty.call(raw, "lookupModel")) config.lookupModel = normalizeLookupModel(raw.lookupModel);
164
- if (Object.prototype.hasOwnProperty.call(raw, "codingDisciplineStrictness")) {
165
- config.codingDisciplineStrictness = normalizeCodingDisciplineStrictness(raw.codingDisciplineStrictness);
166
- }
167
148
 
168
149
  for (const key of DISABLED_LIST_KEYS) addDisabled(config, raw[key], knownModules);
169
150
  for (const key of ENABLED_LIST_KEYS) removeDisabled(config, raw[key], knownModules);
@@ -222,7 +203,6 @@ export function loadPiToolsSuiteConfig(moduleNames: readonly string[], options:
222
203
  todoThinking: false,
223
204
  todoThinkingOverrides: new Map(DEFAULT_TODO_THINKING_OVERRIDES),
224
205
  lookupModel: undefined,
225
- codingDisciplineStrictness: DEFAULT_CODING_DISCIPLINE_STRICTNESS,
226
206
  };
227
207
  const userConfigPath = getPiToolsSuiteUserConfigPath(options.homeDir);
228
208
 
@@ -243,6 +223,5 @@ export function loadPiToolsSuiteConfig(moduleNames: readonly string[], options:
243
223
  todoThinking: config.todoThinking,
244
224
  todoThinkingOverrides: Object.fromEntries(config.todoThinkingOverrides),
245
225
  ...(config.lookupModel ? { lookupModel: config.lookupModel } : {}),
246
- codingDisciplineStrictness: config.codingDisciplineStrictness,
247
226
  };
248
227
  }
@@ -24,12 +24,6 @@ export const DEFAULT_PI_TOOLS_SUITE_CONFIG_JSONC = String.raw`{
24
24
  // Vision-capable model used by the coding-discipline lookup tool for blind-model
25
25
  // screenshot/image questions. Remove or set to null to disable lookup.
26
26
  "lookupModel": "zai/glm-5.3-flash",
27
- // coding-discipline working-state strictness.
28
- // "lenient" (default): batch independent read-only tool calls; brief reasoning
29
- // text is acceptable when thinking is off. Text only counts as chatter when a
30
- // thinking/reasoning block already captured the reasoning.
31
- // "strict": one tool call per turn, no assistant text at all (Opus-like).
32
- "codingDisciplineStrictness": "lenient",
33
27
  "terminalBell": { "sound": true },
34
28
  // comment-checker: nudges the agent to remove AI-slop code comments it just
35
29
  // added via write/edit/apply_patch. Net-new comments are classified and a
@@ -398,6 +392,29 @@ export const DEFAULT_PI_TOOLS_SUITE_CONFIG_JSONC = String.raw`{
398
392
  }
399
393
  // ,
400
394
  // {
395
+ // "id": "svelte",
396
+ // "include": [
397
+ // "**/*.svelte"
398
+ // ],
399
+ // "exclude": [
400
+ // "**/node_modules/**"
401
+ // ],
402
+ // "rootMarkers": [
403
+ // "svelte.config.js",
404
+ // "package.json"
405
+ // ],
406
+ // "bin": "svelteserver",
407
+ // "args": [
408
+ // "--stdio"
409
+ // ],
410
+ // "startupTimeoutMs": 30000,
411
+ // "diagnosticsWaitMs": 8000,
412
+ // "languageIdByExtension": {
413
+ // ".svelte": "svelte"
414
+ // }
415
+ // }
416
+ // ,
417
+ // {
401
418
  // "id": "python",
402
419
  // "include": [
403
420
  // "**/*.py",
@@ -39,10 +39,11 @@ export function astGrepToolDescriptions(maxLines: number, maxBytesLabel: string)
39
39
  astGrep: {
40
40
  name: "ast_grep",
41
41
  label: "ast-grep",
42
- description: `Read-only AST structural search/scan. Use for language-aware patterns, sgconfig/rule scans, JSON matches, and rewrite previews. Use text search for plain strings and ast_apply for mutations. Output truncates at ${maxLines} lines or ${maxBytesLabel} with full output saved to a temp file.`,
43
- promptSnippet: "Use ast_grep for AST/structural code search, not plain text search. It previews rewrites only; use ast_apply to mutate files.",
42
+ description: `Read-only AST structural search/scan. MANDATORY ROUTING: for structural, syntax-aware, AST, language-aware, or code-shape matching, ast_grep must be the FIRST tool call. Never preflight with Glob, Grep, Read, or shell even when files are unknown; omit paths to scan the current project. Use for sgconfig/rule scans, JSON matches, and rewrite previews. Use Grep for exact literals/regex, Glob only for filename/path-only requests, and ast_apply for mutations. Output truncates at ${maxLines} lines or ${maxBytesLabel} with full output saved to a temp file.`,
43
+ promptSnippet: "MANDATORY: structural/syntax-aware/AST/code-shape matching => call ast_grep FIRST. Do not call Glob, Grep, Read, or shell before it; unknown files are not a reason to pre-search because ast_grep scans the project by default. Exact literal/regex only => Grep; filename/path only => Glob. Use ast_apply for mutations.",
44
44
  promptGuidelines: [
45
- "Use ast_grep when syntax/AST structure matters; use text search for exact strings/regex. Keep paths/globs narrow and set lang for ambiguous snippets.",
45
+ "The first tool for syntax relationships or code-shape matching must be ast_grep, even when the file or language is unknown. Do not make a preliminary Glob/Grep/Read/shell call; start at the current project and narrow within ast_grep when needed.",
46
+ "Use Grep/Read directly for exact literal or regex lookups and Glob only for filename/path-only discovery; those text-only tasks must not trigger ast_grep.",
46
47
  "ast_grep is read-only: use rewrite to preview only; use ast_apply for mutations or command=scan fixes.",
47
48
  ],
48
49
  },
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pi-ui-extend",
3
- "version": "1.0.39",
3
+ "version": "1.0.40",
4
4
  "description": "Pix: a workspace-first terminal UI for Pi with tabs, readable tool activity, voice input, and bundled agent tools.",
5
5
  "private": false,
6
6
  "repository": {
@@ -83,10 +83,9 @@
83
83
  "prepublishOnly": "npm run check && npm run build:pix && npm run generate-schemas"
84
84
  },
85
85
  "dependencies": {
86
- "@earendil-works/pi-ai": "0.85.0",
87
- "@earendil-works/pi-coding-agent": "0.85.0",
88
- "@earendil-works/pi-server": "0.85.0",
89
- "@earendil-works/pi-tui": "0.85.0",
86
+ "@earendil-works/pi-ai": "0.85.1",
87
+ "@earendil-works/pi-coding-agent": "0.85.1",
88
+ "@earendil-works/pi-tui": "0.85.1",
90
89
  "@mariozechner/clipboard": "^0.3.9",
91
90
  "grok-mermaid": "0.2.2",
92
91
  "jsonc-parser": "3.3.1",