pi-ui-extend 0.1.9 → 0.1.13

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.
Files changed (121) hide show
  1. package/README.md +23 -2
  2. package/dist/app/app.d.ts +4 -0
  3. package/dist/app/app.js +76 -7
  4. package/dist/app/cli/install.d.ts +16 -0
  5. package/dist/app/cli/install.js +34 -7
  6. package/dist/app/cli/startup-info.js +5 -2
  7. package/dist/app/cli/update.d.ts +7 -0
  8. package/dist/app/cli/update.js +11 -3
  9. package/dist/app/commands/command-controller.js +4 -0
  10. package/dist/app/commands/command-host.d.ts +4 -0
  11. package/dist/app/commands/command-model-actions.d.ts +5 -0
  12. package/dist/app/commands/command-model-actions.js +104 -0
  13. package/dist/app/commands/command-navigation-actions.d.ts +6 -1
  14. package/dist/app/commands/command-navigation-actions.js +37 -14
  15. package/dist/app/commands/command-registry.d.ts +4 -0
  16. package/dist/app/commands/command-registry.js +32 -0
  17. package/dist/app/commands/command-session-actions.d.ts +1 -0
  18. package/dist/app/commands/command-session-actions.js +15 -5
  19. package/dist/app/commands/shell-command.d.ts +7 -0
  20. package/dist/app/commands/shell-command.js +12 -4
  21. package/dist/app/commands/shell-controller.d.ts +1 -0
  22. package/dist/app/commands/shell-controller.js +1 -1
  23. package/dist/app/constants.d.ts +1 -1
  24. package/dist/app/constants.js +1 -1
  25. package/dist/app/icons.d.ts +1 -0
  26. package/dist/app/icons.js +3 -1
  27. package/dist/app/input/autocomplete-controller.d.ts +52 -0
  28. package/dist/app/input/autocomplete-controller.js +352 -0
  29. package/dist/app/input/input-action-controller.d.ts +1 -0
  30. package/dist/app/input/input-action-controller.js +21 -0
  31. package/dist/app/input/input-controller.d.ts +1 -0
  32. package/dist/app/input/input-controller.js +2 -0
  33. package/dist/app/input/input-paste-handler.d.ts +1 -0
  34. package/dist/app/input/input-paste-handler.js +22 -18
  35. package/dist/app/input/prompt-enhancer-controller.d.ts +7 -1
  36. package/dist/app/input/prompt-enhancer-controller.js +12 -3
  37. package/dist/app/input/voice-controller.d.ts +51 -1
  38. package/dist/app/input/voice-controller.js +42 -19
  39. package/dist/app/model/model-usage-status.d.ts +9 -0
  40. package/dist/app/model/model-usage-status.js +124 -34
  41. package/dist/app/popup/popup-action-controller.js +1 -1
  42. package/dist/app/process.d.ts +17 -0
  43. package/dist/app/process.js +68 -0
  44. package/dist/app/rendering/conversation-entry-renderer.js +8 -6
  45. package/dist/app/rendering/conversation-tool-renderer.js +3 -2
  46. package/dist/app/rendering/editor-layout-renderer.d.ts +1 -0
  47. package/dist/app/rendering/editor-layout-renderer.js +11 -1
  48. package/dist/app/rendering/message-content.js +65 -7
  49. package/dist/app/rendering/render-controller.js +6 -1
  50. package/dist/app/rendering/render-text.d.ts +3 -0
  51. package/dist/app/rendering/render-text.js +51 -3
  52. package/dist/app/rendering/status-line-renderer.d.ts +5 -1
  53. package/dist/app/rendering/status-line-renderer.js +61 -25
  54. package/dist/app/rendering/toast-renderer.js +10 -13
  55. package/dist/app/rendering/tool-block-renderer.d.ts +1 -0
  56. package/dist/app/rendering/tool-block-renderer.js +16 -33
  57. package/dist/app/runtime.d.ts +6 -1
  58. package/dist/app/runtime.js +35 -2
  59. package/dist/app/screen/clipboard.d.ts +11 -2
  60. package/dist/app/screen/clipboard.js +29 -21
  61. package/dist/app/screen/file-link-opener.d.ts +8 -0
  62. package/dist/app/screen/file-link-opener.js +11 -3
  63. package/dist/app/screen/file-links.js +3 -3
  64. package/dist/app/screen/image-opener.d.ts +12 -0
  65. package/dist/app/screen/image-opener.js +13 -5
  66. package/dist/app/screen/mouse-controller.d.ts +5 -2
  67. package/dist/app/screen/mouse-controller.js +16 -1
  68. package/dist/app/screen/screen-styler.d.ts +4 -1
  69. package/dist/app/screen/screen-styler.js +3 -2
  70. package/dist/app/screen/status-controller.d.ts +3 -0
  71. package/dist/app/screen/status-controller.js +23 -8
  72. package/dist/app/session/queued-message-controller.d.ts +7 -1
  73. package/dist/app/session/queued-message-controller.js +36 -21
  74. package/dist/app/session/resume-session-loader.d.ts +15 -0
  75. package/dist/app/session/resume-session-loader.js +204 -0
  76. package/dist/app/session/session-event-controller.d.ts +5 -1
  77. package/dist/app/session/session-event-controller.js +72 -5
  78. package/dist/app/session/session-history.js +4 -3
  79. package/dist/app/session/session-lifecycle-controller.d.ts +5 -0
  80. package/dist/app/session/session-lifecycle-controller.js +9 -1
  81. package/dist/app/session/tabs-controller.d.ts +10 -1
  82. package/dist/app/session/tabs-controller.js +101 -5
  83. package/dist/app/terminal/nerd-font-controller.d.ts +16 -0
  84. package/dist/app/terminal/nerd-font-controller.js +30 -23
  85. package/dist/app/terminal/terminal-controller.d.ts +1 -0
  86. package/dist/app/terminal/terminal-controller.js +1 -0
  87. package/dist/app/types.d.ts +14 -0
  88. package/dist/app/workspace/workspace-actions-controller.d.ts +1 -1
  89. package/dist/app/workspace/workspace-actions-controller.js +3 -3
  90. package/dist/app/workspace/workspace-undo.d.ts +1 -1
  91. package/dist/app/workspace/workspace-undo.js +22 -20
  92. package/dist/config.d.ts +27 -0
  93. package/dist/config.js +174 -1
  94. package/dist/default-pix-config.js +39 -353
  95. package/dist/input-editor.d.ts +7 -1
  96. package/dist/input-editor.js +47 -6
  97. package/dist/markdown-format.d.ts +1 -0
  98. package/dist/markdown-format.js +26 -1
  99. package/dist/schemas/index.d.ts +5 -0
  100. package/dist/schemas/index.js +5 -0
  101. package/dist/schemas/pi-tools-suite-schema.d.ts +177 -0
  102. package/dist/schemas/pi-tools-suite-schema.js +218 -0
  103. package/dist/schemas/pix-schema.d.ts +65 -0
  104. package/dist/schemas/pix-schema.js +91 -0
  105. package/dist/terminal-width.js +73 -56
  106. package/external/pi-tools-suite/src/async-subagents/async-subagents.sample.jsonc +3 -0
  107. package/external/pi-tools-suite/src/dcp/compression-blocks.ts +1 -0
  108. package/external/pi-tools-suite/src/dcp/prompts.ts +1 -0
  109. package/external/pi-tools-suite/src/default-pi-tools-suite-config.ts +46 -195
  110. package/external/pi-tools-suite/src/lib/lsp.ts +2 -1
  111. package/external/pi-tools-suite/src/lsp/_shared/output.ts +8 -7
  112. package/external/pi-tools-suite/src/lsp/manager.ts +4 -4
  113. package/external/pi-tools-suite/src/repo-discovery/index.ts +49 -2
  114. package/external/pi-tools-suite/src/todo/index.ts +4 -2
  115. package/external/pi-tools-suite/src/todo/state/selectors.ts +4 -0
  116. package/external/pi-tools-suite/src/todo/todo.ts +2 -6
  117. package/external/pi-tools-suite/src/todo/tool/response-envelope.ts +9 -1
  118. package/external/pi-tools-suite/src/tool-descriptions.ts +1 -1
  119. package/package.json +12 -3
  120. package/schemas/pi-tools-suite.json +881 -0
  121. package/schemas/pix.json +298 -0
package/dist/config.d.ts CHANGED
@@ -25,6 +25,24 @@ export type OutputFiltersConfig = {
25
25
  export type PromptEnhancerConfig = {
26
26
  modelRef: string;
27
27
  };
28
+ export type AutocompleteConfig = {
29
+ /** Empty string disables inline LLM autocomplete. */
30
+ modelRef: string;
31
+ /** Delay after typing before asking the model. */
32
+ debounceMs: number;
33
+ /** Hard timeout for a best-effort completion request. */
34
+ timeoutMs: number;
35
+ /** Maximum output tokens requested from the provider. */
36
+ maxTokens: number;
37
+ /** Approximate maximum input prompt tokens, including system prompt and optional history. */
38
+ maxPromptTokens: number;
39
+ /** Number of recent active-session user/assistant messages to include as context. */
40
+ includeRecentMessages: number;
41
+ };
42
+ export type DefaultModelConfig = {
43
+ modelRef: string;
44
+ thinking?: "off" | "minimal" | "low" | "medium" | "high" | "xhigh";
45
+ };
28
46
  export type ModelColorsConfig = {
29
47
  rules: Record<string, string>;
30
48
  };
@@ -43,12 +61,21 @@ export type DictationConfig = {
43
61
  export type PixConfig = {
44
62
  toolRenderer: ToolRendererConfig;
45
63
  outputFilters: OutputFiltersConfig;
64
+ defaultModel?: DefaultModelConfig;
46
65
  promptEnhancer: PromptEnhancerConfig;
66
+ autocomplete: AutocompleteConfig;
47
67
  modelColors: ModelColorsConfig;
48
68
  iconTheme: IconThemeConfig;
49
69
  dictation: DictationConfig;
50
70
  };
51
71
  export declare function getPixConfigPath(homeDir?: string): string;
72
+ export declare function resolveDefaultModelRef(config: PixConfig): string | undefined;
73
+ export declare function savePixDefaultModel(modelRef: string): DefaultModelConfig | undefined;
74
+ export declare function savePixDefaultThinking(thinking: string, fallbackModelRef?: string): DefaultModelConfig | undefined;
75
+ export declare function savePixAutocompleteModel(modelRef: string): AutocompleteConfig;
76
+ export declare function upsertPixDefaultModelInJsonc(source: string, modelRef: string): string;
77
+ export declare function upsertPixDefaultThinkingInJsonc(source: string, thinking: string, fallbackModelRef?: string): string;
78
+ export declare function upsertPixAutocompleteModelInJsonc(source: string, modelRef: string): string;
52
79
  export declare function loadPixConfig(): PixConfig;
53
80
  export declare function savePixDictationLanguage(language: string): void;
54
81
  export declare function upsertPixDictationLanguageInJsonc(source: string, language: string): string;
package/dist/config.js CHANGED
@@ -48,9 +48,18 @@ const DEFAULT_TOOL_RENDERER = {
48
48
  const DEFAULT_OUTPUT_FILTERS = {
49
49
  patterns: [],
50
50
  };
51
+ const THINKING_LEVELS = ["off", "minimal", "low", "medium", "high", "xhigh"];
51
52
  const DEFAULT_PROMPT_ENHANCER = {
52
53
  modelRef: "zai/glm-5-turbo",
53
54
  };
55
+ const DEFAULT_AUTOCOMPLETE = {
56
+ modelRef: "zai/glm-5-turbo",
57
+ debounceMs: 350,
58
+ timeoutMs: 3000,
59
+ maxTokens: 48,
60
+ maxPromptTokens: 1200,
61
+ includeRecentMessages: 0,
62
+ };
54
63
  const DEFAULT_MODEL_COLORS = {
55
64
  rules: {
56
65
  "zai/*": "success",
@@ -124,6 +133,51 @@ function extractPromptEnhancerConfig(raw) {
124
133
  const modelRef = nonEmptyString(enhancer.modelRef) ?? nonEmptyString(enhancer.model);
125
134
  return modelRef ? { modelRef } : undefined;
126
135
  }
136
+ function extractAutocompleteConfig(raw) {
137
+ if (!isPlainObject(raw))
138
+ return undefined;
139
+ const autocomplete = raw.autocomplete ?? raw.autoComplete;
140
+ if (typeof autocomplete === "string")
141
+ return { ...DEFAULT_AUTOCOMPLETE, modelRef: autocomplete.trim() };
142
+ if (!isPlainObject(autocomplete))
143
+ return undefined;
144
+ const modelRef = autocompleteModelRef(autocomplete);
145
+ return {
146
+ ...DEFAULT_AUTOCOMPLETE,
147
+ ...(modelRef === undefined ? {} : { modelRef }),
148
+ debounceMs: numberInRange(autocomplete.debounceMs, DEFAULT_AUTOCOMPLETE.debounceMs, 100, 2_000),
149
+ timeoutMs: numberInRange(autocomplete.timeoutMs, DEFAULT_AUTOCOMPLETE.timeoutMs, 250, 10_000),
150
+ maxTokens: numberInRange(autocomplete.maxTokens, DEFAULT_AUTOCOMPLETE.maxTokens, 8, 256),
151
+ maxPromptTokens: numberInRange(autocomplete.maxPromptTokens, DEFAULT_AUTOCOMPLETE.maxPromptTokens, 256, 16_000),
152
+ includeRecentMessages: numberInRange(autocomplete.includeRecentMessages ?? autocomplete.recentMessages, DEFAULT_AUTOCOMPLETE.includeRecentMessages, 0, 20),
153
+ };
154
+ }
155
+ function autocompleteModelRef(autocomplete) {
156
+ if (typeof autocomplete.modelRef === "string")
157
+ return autocomplete.modelRef.trim();
158
+ if (typeof autocomplete.model === "string")
159
+ return autocomplete.model.trim();
160
+ return undefined;
161
+ }
162
+ function extractDefaultModelConfig(raw) {
163
+ if (!isPlainObject(raw))
164
+ return undefined;
165
+ const configured = raw.defaultModel ?? raw.modelDefault;
166
+ if (typeof configured === "string") {
167
+ const modelRef = configured.trim();
168
+ return modelRef ? { modelRef } : undefined;
169
+ }
170
+ if (!isPlainObject(configured))
171
+ return undefined;
172
+ const modelRef = nonEmptyString(configured.modelRef) ?? nonEmptyString(configured.model);
173
+ if (!modelRef)
174
+ return undefined;
175
+ const thinking = normalizeThinkingLevel(configured.thinking) ?? normalizeThinkingLevel(configured.thinkingLevel);
176
+ return {
177
+ modelRef,
178
+ ...(thinking === undefined ? {} : { thinking }),
179
+ };
180
+ }
127
181
  function extractModelColorsConfig(raw) {
128
182
  if (!isPlainObject(raw))
129
183
  return undefined;
@@ -193,22 +247,139 @@ function normalizeDictationLanguage(value) {
193
247
  const normalized = value.trim().toLowerCase();
194
248
  return normalized.length > 0 ? normalized : undefined;
195
249
  }
250
+ function normalizeThinkingLevel(value) {
251
+ if (typeof value !== "string")
252
+ return undefined;
253
+ const normalized = value.trim().toLowerCase();
254
+ return THINKING_LEVELS.includes(normalized) ? normalized : undefined;
255
+ }
196
256
  function nonEmptyString(value) {
197
257
  if (typeof value !== "string")
198
258
  return undefined;
199
259
  const trimmed = value.trim();
200
260
  return trimmed.length > 0 ? trimmed : undefined;
201
261
  }
262
+ function numberInRange(value, fallback, min, max) {
263
+ if (typeof value !== "number" || !Number.isFinite(value))
264
+ return fallback;
265
+ const rounded = Math.round(value);
266
+ return Math.min(max, Math.max(min, rounded));
267
+ }
202
268
  function defaultPixConfig() {
203
269
  return {
204
270
  toolRenderer: DEFAULT_TOOL_RENDERER,
205
271
  outputFilters: DEFAULT_OUTPUT_FILTERS,
206
272
  promptEnhancer: DEFAULT_PROMPT_ENHANCER,
273
+ autocomplete: DEFAULT_AUTOCOMPLETE,
207
274
  modelColors: DEFAULT_MODEL_COLORS,
208
275
  iconTheme: { name: resolveAppIconThemeNameFromEnv() },
209
276
  dictation: DEFAULT_DICTATION,
210
277
  };
211
278
  }
279
+ export function resolveDefaultModelRef(config) {
280
+ const modelRef = config.defaultModel?.modelRef.trim();
281
+ if (!modelRef)
282
+ return undefined;
283
+ const thinking = config.defaultModel?.thinking;
284
+ if (!thinking)
285
+ return modelRef;
286
+ return `${stripThinkingSuffix(modelRef)}:${thinking}`;
287
+ }
288
+ export function savePixDefaultModel(modelRef) {
289
+ const normalized = normalizeDefaultModelRef(modelRef);
290
+ if (!normalized)
291
+ return undefined;
292
+ const configPath = PIX_CONFIG_PATH;
293
+ const source = existsSync(configPath) ? readFileSync(configPath, "utf8") : "{\n}\n";
294
+ const updated = upsertPixDefaultModelInJsonc(source, modelRef);
295
+ mkdirSync(dirname(configPath), { recursive: true });
296
+ writeFileSync(configPath, updated);
297
+ return extractDefaultModelConfig(parseJsonc(updated));
298
+ }
299
+ export function savePixDefaultThinking(thinking, fallbackModelRef) {
300
+ const normalizedThinking = normalizeThinkingLevel(thinking);
301
+ if (!normalizedThinking)
302
+ return undefined;
303
+ const configPath = PIX_CONFIG_PATH;
304
+ const source = existsSync(configPath) ? readFileSync(configPath, "utf8") : "{\n}\n";
305
+ const updated = upsertPixDefaultThinkingInJsonc(source, normalizedThinking, fallbackModelRef);
306
+ const defaultModel = extractDefaultModelConfig(parseJsonc(updated));
307
+ if (!defaultModel)
308
+ return undefined;
309
+ mkdirSync(dirname(configPath), { recursive: true });
310
+ writeFileSync(configPath, updated);
311
+ return defaultModel;
312
+ }
313
+ export function savePixAutocompleteModel(modelRef) {
314
+ const configPath = PIX_CONFIG_PATH;
315
+ const source = existsSync(configPath) ? readFileSync(configPath, "utf8") : "{\n}\n";
316
+ const updated = upsertPixAutocompleteModelInJsonc(source, modelRef);
317
+ mkdirSync(dirname(configPath), { recursive: true });
318
+ writeFileSync(configPath, updated);
319
+ return extractAutocompleteConfig(parseJsonc(updated)) ?? { ...DEFAULT_AUTOCOMPLETE, modelRef: modelRef.trim() };
320
+ }
321
+ export function upsertPixDefaultModelInJsonc(source, modelRef) {
322
+ const normalized = normalizeDefaultModelRef(modelRef);
323
+ if (!normalized)
324
+ return source;
325
+ const parsed = parseJsonc(source);
326
+ const current = extractDefaultModelConfig(parsed);
327
+ const thinking = normalized.thinking ?? current?.thinking;
328
+ const next = {
329
+ modelRef: normalized.modelRef,
330
+ ...(thinking === undefined ? {} : { thinking }),
331
+ };
332
+ return upsertPixDefaultModelObjectInJsonc(source, parsed, next);
333
+ }
334
+ export function upsertPixDefaultThinkingInJsonc(source, thinking, fallbackModelRef) {
335
+ const normalizedThinking = normalizeThinkingLevel(thinking);
336
+ if (!normalizedThinking)
337
+ return source;
338
+ const parsed = parseJsonc(source);
339
+ const current = extractDefaultModelConfig(parsed);
340
+ const fallback = fallbackModelRef ? normalizeDefaultModelRef(fallbackModelRef) : undefined;
341
+ const modelRef = current?.modelRef ?? fallback?.modelRef;
342
+ if (!modelRef)
343
+ return source;
344
+ const next = {
345
+ modelRef: stripThinkingSuffix(modelRef),
346
+ thinking: normalizedThinking,
347
+ };
348
+ return upsertPixDefaultModelObjectInJsonc(source, parsed, next);
349
+ }
350
+ function upsertPixDefaultModelObjectInJsonc(source, parsed, config) {
351
+ const formattingOptions = { insertSpaces: true, tabSize: 2 };
352
+ if (!isPlainObject(parsed) || !isPlainObject(parsed.defaultModel)) {
353
+ return applyEdits(source, modify(source, ["defaultModel"], config, { formattingOptions, getInsertionIndex: () => 0 }));
354
+ }
355
+ let updated = applyEdits(source, modify(source, ["defaultModel", "modelRef"], config.modelRef, { formattingOptions }));
356
+ if (config.thinking !== undefined) {
357
+ updated = applyEdits(updated, modify(updated, ["defaultModel", "thinking"], config.thinking, { formattingOptions }));
358
+ }
359
+ return updated;
360
+ }
361
+ export function upsertPixAutocompleteModelInJsonc(source, modelRef) {
362
+ const formattingOptions = { insertSpaces: true, tabSize: 2 };
363
+ return applyEdits(source, modify(source, ["autocomplete", "modelRef"], modelRef.trim(), { formattingOptions }));
364
+ }
365
+ function normalizeDefaultModelRef(modelRef) {
366
+ const trimmed = modelRef.trim();
367
+ if (!trimmed)
368
+ return undefined;
369
+ const colonIndex = trimmed.lastIndexOf(":");
370
+ if (colonIndex <= 0)
371
+ return { modelRef: trimmed };
372
+ const suffix = trimmed.slice(colonIndex + 1);
373
+ const thinking = normalizeThinkingLevel(suffix);
374
+ return thinking ? { modelRef: trimmed.slice(0, colonIndex), thinking } : { modelRef: trimmed };
375
+ }
376
+ function stripThinkingSuffix(modelRef) {
377
+ const colonIndex = modelRef.lastIndexOf(":");
378
+ if (colonIndex <= 0)
379
+ return modelRef;
380
+ const suffix = modelRef.slice(colonIndex + 1);
381
+ return normalizeThinkingLevel(suffix) ? modelRef.slice(0, colonIndex) : modelRef;
382
+ }
212
383
  function extractToolRendererRule(value) {
213
384
  if (!isPlainObject(value))
214
385
  return undefined;
@@ -258,12 +429,14 @@ export function loadPixConfig() {
258
429
  const parsed = parseJsonc(raw);
259
430
  const toolRenderer = extractToolRendererConfig(parsed) ?? DEFAULT_TOOL_RENDERER;
260
431
  const outputFilters = extractOutputFiltersConfig(parsed) ?? DEFAULT_OUTPUT_FILTERS;
432
+ const defaultModel = extractDefaultModelConfig(parsed);
261
433
  const promptEnhancer = extractPromptEnhancerConfig(parsed) ?? DEFAULT_PROMPT_ENHANCER;
434
+ const autocomplete = extractAutocompleteConfig(parsed) ?? DEFAULT_AUTOCOMPLETE;
262
435
  const modelColors = extractModelColorsConfig(parsed) ?? DEFAULT_MODEL_COLORS;
263
436
  const configuredIconTheme = extractIconThemeConfig(parsed) ?? DEFAULT_ICON_THEME;
264
437
  const iconTheme = { name: appIconThemeOverrideFromEnv() ?? configuredIconTheme.name };
265
438
  const dictation = extractDictationConfig(parsed) ?? DEFAULT_DICTATION;
266
- return { toolRenderer, outputFilters, promptEnhancer, modelColors, iconTheme, dictation };
439
+ return { toolRenderer, outputFilters, ...(defaultModel === undefined ? {} : { defaultModel }), promptEnhancer, autocomplete, modelColors, iconTheme, dictation };
267
440
  }
268
441
  catch (error) {
269
442
  process.stderr.write(`[pix] Failed to load ${configPath}: ${error instanceof Error ? error.message : String(error)}\n`);