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
@@ -4,6 +4,7 @@ import type { CommandRunResult } from "./types";
4
4
  import { normalizeRelativePath, uriToFilePath } from "./paths";
5
5
 
6
6
  const DEFAULT_OUTPUT_LIMIT = 4000;
7
+ export const LSP_DIAGNOSTIC_ICON = "\u{f0026}";
7
8
 
8
9
  export function textFromContent(content: Array<{ type: string; text?: string }>): string {
9
10
  return content
@@ -29,20 +30,20 @@ export function commandOutput(result: Pick<CommandRunResult, "stdout" | "stderr"
29
30
 
30
31
  export function formatWarnings(title: string, warnings: string[]): string {
31
32
  if (warnings.length === 0) return "";
32
- return `${title}:\n\n${warnings.map((warning) => `⚠️ ${warning}`).join("\n")}`;
33
+ return `${title}:\n\n${warnings.map((warning) => `${LSP_DIAGNOSTIC_ICON} ${warning}`).join("\n")}`;
33
34
  }
34
35
 
35
36
  export function formatCommandIssue(toolId: string, action: string, result: CommandRunResult): string {
36
37
  const output = commandOutput(result);
37
38
  const suffix = result.killed ? " (killed/timeout)" : "";
38
- if (!output) return `⚠️ ${toolId} ${action} failed with exit code ${result.code}${suffix}`;
39
- return `⚠️ ${toolId} ${action} failed with exit code ${result.code}${suffix}:\n${output}`;
39
+ if (!output) return `${LSP_DIAGNOSTIC_ICON} ${toolId} ${action} failed with exit code ${result.code}${suffix}`;
40
+ return `${LSP_DIAGNOSTIC_ICON} ${toolId} ${action} failed with exit code ${result.code}${suffix}:\n${output}`;
40
41
  }
41
42
 
42
43
  export function formatDiagnosticOutput(toolId: string, output: string): string {
43
44
  const compact = truncateOutput(output);
44
- if (!compact) return `⚠️ ${toolId} found issues`;
45
- return `⚠️ ${toolId} found issues:\n${compact}`;
45
+ if (!compact) return `${LSP_DIAGNOSTIC_ICON} ${toolId} found issues`;
46
+ return `${LSP_DIAGNOSTIC_ICON} ${toolId} found issues:\n${compact}`;
46
47
  }
47
48
 
48
49
  function severityLabel(severity: number | undefined): string {
@@ -88,11 +89,11 @@ export function formatLspDiagnostics(serverId: string, file: string, diagnostics
88
89
  if (diagnostics.length === 0) return "";
89
90
  const rendered = diagnostics.slice(0, 20).map((diagnostic) => formatDiagnostic(file, diagnostic, root));
90
91
  if (diagnostics.length > 20) rendered.push(`… ${diagnostics.length - 20} more diagnostics`);
91
- return `⚠️ ${serverId}:\n${rendered.join("\n")}`;
92
+ return `${LSP_DIAGNOSTIC_ICON} ${serverId}:\n${rendered.join("\n")}`;
92
93
  }
93
94
 
94
95
  export function hasIssueOutput(output: string): boolean {
95
- return output.includes("⚠️");
96
+ return output.includes(LSP_DIAGNOSTIC_ICON) || output.includes("⚠️") || output.includes("⚠");
96
97
  }
97
98
 
98
99
  export function joinSections(title: string, lines: string[]): string {
@@ -6,7 +6,7 @@ import { LspClient } from "./client";
6
6
  import { loadLspConfig } from "./_shared/config";
7
7
  import { isPathIncluded } from "./_shared/glob";
8
8
  import { filePathToUri, findProjectRoot, normalizeRelativePath, resolveCommand, toAbsolutePath } from "./_shared/paths";
9
- import { formatLspDiagnostics, formatWarnings, joinSections } from "./_shared/output";
9
+ import { formatLspDiagnostics, formatWarnings, joinSections, LSP_DIAGNOSTIC_ICON } from "./_shared/output";
10
10
  import type { LspServerConfig, StoredDiagnostics } from "./_shared/types";
11
11
  import { clientKey, couldMatchBeforeRoot, fileSizeAllowed, languageIdForFile, readTextFile } from "./lsp-utils";
12
12
  import { localMarkdownDiagnostics } from "./markdown-diagnostics";
@@ -112,7 +112,7 @@ export class LspManager {
112
112
  try {
113
113
  const maxFileSizeBytes = match.server.maxFileSizeBytes ?? DEFAULT_MAX_FILE_SIZE_BYTES;
114
114
  if (!(await fileSizeAllowed(file, maxFileSizeBytes))) {
115
- lines.push(`⚠️ ${match.server.id}: skipped ${match.relFile}; file exceeds maxFileSizeBytes (${maxFileSizeBytes})`);
115
+ lines.push(`${LSP_DIAGNOSTIC_ICON} ${match.server.id}: skipped ${match.relFile}; file exceeds maxFileSizeBytes (${maxFileSizeBytes})`);
116
116
  continue;
117
117
  }
118
118
 
@@ -173,14 +173,14 @@ export class LspManager {
173
173
  if (!isFreshDiagnosticsEntry(entry, startedAt, doc.version)) {
174
174
  const fallbackSuffix = tsserverFallbackError ? `; tsserver fallback failed: ${tsserverFallbackError}` : "";
175
175
  const pullSuffix = pullDiagnosticsError ? `; pull diagnostics failed: ${pullDiagnosticsError}` : "";
176
- lines.push(`⚠️ ${match.server.id}: timed out after ${diagnosticsWaitMs}ms waiting for fresh diagnostics for ${match.relFile}${fallbackSuffix}${pullSuffix}`);
176
+ lines.push(`${LSP_DIAGNOSTIC_ICON} ${match.server.id}: timed out after ${diagnosticsWaitMs}ms waiting for fresh diagnostics for ${match.relFile}${fallbackSuffix}${pullSuffix}`);
177
177
  continue;
178
178
  }
179
179
  const diagnostics = diagnosticsWithLocalFallback(match.server.id, file, text, entry.diagnostics);
180
180
  if (diagnostics !== entry.diagnostics) this.diagnostics.set(match.server.id, match.root, filePathToUri(file), diagnostics, doc.version);
181
181
  lines.push(formatLspDiagnostics(match.server.id, file, diagnostics, match.root));
182
182
  } catch (error) {
183
- lines.push(`⚠️ ${match.server.id}: ${(error as Error).message}`);
183
+ lines.push(`${LSP_DIAGNOSTIC_ICON} ${match.server.id}: ${(error as Error).message}`);
184
184
  }
185
185
  }
186
186
 
@@ -112,9 +112,56 @@ async function initializeIndexedProject(pi: ExtensionAPI, cwd: string, signal: A
112
112
  const indexerDir = path.join(projectRoot, ".indexer-cli");
113
113
  if (directoryExists(indexerDir)) return { projectRoot, initialized: false, alreadyIndexed: true, output: "Project is already indexed." };
114
114
 
115
+ const idxCli = await ensureIdxCliAvailable(pi, projectRoot, signal);
116
+ if (!idxCli.available) {
117
+ return {
118
+ projectRoot,
119
+ initialized: false,
120
+ alreadyIndexed: false,
121
+ output: idxCli.output,
122
+ exitCode: idxCli.exitCode,
123
+ installedIdx: idxCli.installed,
124
+ };
125
+ }
126
+
115
127
  const init = await pi.exec("idx", ["init"], { cwd: projectRoot, signal, timeout: 600_000 });
116
- const output = [init.stdout, init.stderr].filter(Boolean).join(init.stdout && init.stderr ? "\n" : "").trim() || "No output";
117
- return { projectRoot, initialized: (init.code ?? 0) === 0, alreadyIndexed: false, output, exitCode: init.code ?? 0 };
128
+ const initOutput = [init.stdout, init.stderr].filter(Boolean).join(init.stdout && init.stderr ? "\n" : "").trim() || "No output";
129
+ const output = idxCli.installed
130
+ ? [`idx was not available; installed with npm install -g indexer-cli@latest:`, idxCli.output, `idx init output:`, initOutput].join("\n\n")
131
+ : initOutput;
132
+ return { projectRoot, initialized: (init.code ?? 0) === 0, alreadyIndexed: false, output, exitCode: init.code ?? 0, installedIdx: idxCli.installed };
133
+ }
134
+
135
+ async function ensureIdxCliAvailable(pi: ExtensionAPI, cwd: string, signal: AbortSignal | undefined) {
136
+ const check = await runCommandSafely(pi, "sh", ["-lc", "command -v idx"], { cwd, signal, timeout: 30_000 });
137
+ if ((check.code ?? 0) === 0) return { available: true, installed: false, output: "idx is available.", exitCode: 0 };
138
+
139
+ const install = await runCommandSafely(pi, "npm", ["install", "-g", "indexer-cli@latest"], { cwd, signal, timeout: 600_000 });
140
+ const installOutput = [install.stdout, install.stderr].filter(Boolean).join(install.stdout && install.stderr ? "\n" : "").trim() || "No output";
141
+ const exitCode = install.code ?? 0;
142
+ if (exitCode !== 0) {
143
+ return {
144
+ available: false,
145
+ installed: false,
146
+ output: [`idx is not available and npm install -g indexer-cli@latest failed:`, installOutput].join("\n\n"),
147
+ exitCode,
148
+ };
149
+ }
150
+
151
+ return { available: true, installed: true, output: installOutput, exitCode };
152
+ }
153
+
154
+ async function runCommandSafely(
155
+ pi: ExtensionAPI,
156
+ command: string,
157
+ args: string[],
158
+ options: { cwd?: string; signal?: AbortSignal; timeout?: number },
159
+ ): Promise<ExecResult> {
160
+ try {
161
+ return await pi.exec(command, args, options);
162
+ } catch (error) {
163
+ return { stdout: "", stderr: error instanceof Error ? error.message : String(error), code: 1 };
164
+ }
118
165
  }
119
166
 
120
167
  async function updateIndexerCli(pi: ExtensionAPI, cwd: string, signal: AbortSignal | undefined) {
@@ -2,7 +2,7 @@ import type { ExtensionAPI, ExtensionContext } from "@earendil-works/pi-coding-a
2
2
  import { autoClearCompletedTodos } from "./state/auto-clear.js";
3
3
  import { loadPersistedPlan, syncPersistedPlan } from "./state/persistence.js";
4
4
  import { replayFromBranch } from "./state/replay.js";
5
- import { ACTIVE_STATUSES, selectVisibleTasks } from "./state/selectors.js";
5
+ import { ACTIVE_STATUSES, isTaskBlocked, selectVisibleTasks } from "./state/selectors.js";
6
6
  import { getState, replaceState } from "./state/store.js";
7
7
  import { publishTodoState, registerTodosCommand, registerTodoTool } from "./todo.js";
8
8
 
@@ -17,7 +17,9 @@ function isAskUserToolName(toolName: string): boolean {
17
17
  }
18
18
 
19
19
  function getUnfinishedTodoNudge(): { signature: string; message: string } | undefined {
20
- const unfinished = selectVisibleTasks(getState()).filter((task) => ACTIVE_STATUSES.has(task.status));
20
+ const visible = selectVisibleTasks(getState());
21
+ const byId = new Map(visible.map((task) => [task.id, task]));
22
+ const unfinished = visible.filter((task) => ACTIVE_STATUSES.has(task.status) && !isTaskBlocked(task, byId));
21
23
  if (unfinished.length === 0) return undefined;
22
24
 
23
25
  const signature = JSON.stringify(
@@ -47,3 +47,7 @@ export function selectTodoCounts(state: TaskState): TodoCounts {
47
47
  }
48
48
 
49
49
  export const ACTIVE_STATUSES: ReadonlySet<TaskStatus> = new Set(["pending", "in_progress"]);
50
+
51
+ export function isTaskBlocked(task: Task, byId: ReadonlyMap<number, Task>): boolean {
52
+ return (task.blockedBy ?? []).some((id) => byId.get(id)?.status !== "completed");
53
+ }
@@ -23,7 +23,7 @@ import {
23
23
  } from "./state/persistence.js";
24
24
  import { AUTO_CLEAR_COMPLETED_MESSAGE, autoClearCompletedTodos } from "./state/auto-clear.js";
25
25
  import { replayFromBranch } from "./state/replay.js";
26
- import { selectTasksByStatus, selectTodoCounts } from "./state/selectors.js";
26
+ import { isTaskBlocked, selectTasksByStatus, selectTodoCounts } from "./state/selectors.js";
27
27
  import { applyTaskMutation } from "./state/state-reducer.js";
28
28
  import { commitState, getState, replaceState } from "./state/store.js";
29
29
  import { buildToolResult, formatContent } from "./tool/response-envelope.js";
@@ -287,11 +287,7 @@ function filterCommandTasks(tasks: readonly Task[], options: TodosCommandOptions
287
287
  if (!options.includeDeleted) view = view.filter((task) => task.status !== "deleted");
288
288
  if (options.activeOnly) view = view.filter((task) => task.status === "pending" || task.status === "in_progress");
289
289
  if (options.readyOnly) {
290
- view = view.filter(
291
- (task) =>
292
- task.status === "pending" &&
293
- (task.blockedBy ?? []).every((id) => byId.get(id)?.status === "completed"),
294
- );
290
+ view = view.filter((task) => task.status === "pending" && !isTaskBlocked(task, byId));
295
291
  }
296
292
  if (options.status) view = view.filter((task) => task.status === options.status);
297
293
  if (options.priority) view = view.filter((task) => task.priority === options.priority);
@@ -131,7 +131,7 @@ export function buildToolResult(
131
131
  state: TaskState,
132
132
  op: Op,
133
133
  ): { content: Array<{ type: "text"; text: string }>; details: TaskDetails } {
134
- const text = formatContent(op, state);
134
+ const text = appendWorkflowReminder(formatContent(op, state), op, state);
135
135
  const details: TaskDetails = {
136
136
  action,
137
137
  params: params as Record<string, unknown>,
@@ -141,3 +141,11 @@ export function buildToolResult(
141
141
  };
142
142
  return { content: [{ type: "text", text }], details };
143
143
  }
144
+
145
+ function appendWorkflowReminder(text: string, op: Op, state: TaskState): string {
146
+ if (op.kind === "error" || op.kind === "export") return text;
147
+ const hasPending = state.tasks.some((task) => task.status === "pending");
148
+ const hasInProgress = state.tasks.some((task) => task.status === "in_progress");
149
+ if (!hasPending || hasInProgress) return text;
150
+ return `${text}\n\nReminder: pending todos exist but none is in_progress. Before starting work, call todo update on exactly one task with status in_progress and activeForm.`;
151
+ }
@@ -256,7 +256,7 @@ export const TODO_TOOL_DESCRIPTION: ToolDescription = {
256
256
  "When the user adds, removes, cancels, reprioritizes, or changes the goal, scope, requirements, constraints, or chosen approach, use `todo` before continuing to synchronize the plan: update still-relevant tasks, defer or delete obsolete tasks, add new required tasks, and adjust dependencies/order.",
257
257
  "When your own investigation or verification discovers new facts that make the current todo plan stale, incomplete, impossible, unsafe, or no longer the best approach, use `todo` to revise the plan immediately instead of following outdated tasks.",
258
258
  "Update todos as part of the workflow, not as end-of-task cleanup: whenever you start, finish, block, split, abandon, or materially change a step, call `todo` immediately before continuing.",
259
- "Before starting work, mark exactly one task in_progress with activeForm (present-continuous label). Mark it completed immediately after the required verification, never in batches.",
259
+ "Before any non-trivial read/edit/test/tool work on a planned task, mark exactly one task in_progress with activeForm (present-continuous label); do this immediately after creating a plan if no task is active. Mark it completed immediately after the required verification, never in batches.",
260
260
  "If implementation is partial, tests fail, or a blocker remains, keep the task in_progress and add/update a blocker task instead of completing it.",
261
261
  "Never use `clear`, `delete`, or batch deletion to hide unfinished, stale, or forgotten todos. Defer obsolete items or update them with the reason; only delete when the user explicitly asks or the item was created by mistake.",
262
262
  "Before giving a final response for work that used todos, ensure every visible todo is completed, deferred, or intentionally still in_progress with a blocker/explanation.",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pi-ui-extend",
3
- "version": "0.1.9",
3
+ "version": "0.1.13",
4
4
  "private": false,
5
5
  "type": "module",
6
6
  "bin": {
@@ -14,13 +14,16 @@
14
14
  "./sdk": {
15
15
  "types": "./dist/sdk.d.ts",
16
16
  "import": "./dist/sdk.js"
17
- }
17
+ },
18
+ "./schemas/pix.json": "./schemas/pix.json",
19
+ "./schemas/pi-tools-suite.json": "./schemas/pi-tools-suite.json"
18
20
  },
19
21
  "files": [
20
22
  "bin",
21
23
  "docs",
22
24
  "dist",
23
25
  "extensions",
26
+ "schemas",
24
27
  "skills",
25
28
  "external/pi-tools-suite/index.ts",
26
29
  "external/pi-tools-suite/package.json",
@@ -34,22 +37,28 @@
34
37
  "predev": "npm run link:pix --silent",
35
38
  "dev": "mise exec node@24.16.0 -- tsx src/main.ts",
36
39
  "start": "mise exec node@24.16.0 -- tsx src/main.ts",
40
+ "prebuild:pix": "npm run generate-schemas --silent",
37
41
  "build:pix": "mise exec node@24.16.0 -- tsc -p tsconfig.json",
38
42
  "prelink:pix": "npm run build:pix --silent",
39
43
  "link:pix": "mise exec node@24.16.0 -- npm link --silent",
40
44
  "watch:pix": "npm run link:pix --silent && mise exec node@24.16.0 -- tsc -p tsconfig.json --watch --preserveWatchOutput --noEmitOnError",
41
45
  "check": "mise exec node@24.16.0 -- npm run check:inner",
46
+ "precheck:inner": "npm run generate-schemas --silent",
42
47
  "check:inner": "tsc --noEmit && npm run test:inner",
43
48
  "test": "mise exec node@24.16.0 -- npm run test:inner",
44
49
  "test:inner": "node --import tsx --test \"tests/**/*.test.ts\"",
45
50
  "test:tools-suite": "npm --prefix external/pi-tools-suite test",
46
51
  "test:coverage": "mise exec node@24.16.0 -- node --import tsx --test --experimental-test-coverage --test-coverage-include=src/**/*.ts --test-coverage-exclude=src/main.ts --test-coverage-lines=95 --test-coverage-branches=80 --test-coverage-functions=95 \"tests/**/*.test.ts\"",
47
52
  "update-sdk-references": "mise exec node@24.16.0 -- node .pi/skills/pi-sdk/scripts/update-references.mjs",
53
+ "prepack": "npm run generate-schemas --silent",
48
54
  "pack:dry-run": "npm pack --dry-run",
49
55
  "smoke-test": "mise exec node@24.16.0 -- bash scripts/smoke-test-package.sh",
50
56
  "release:check": "npm run check && npm run build:pix && npm run pack:dry-run",
51
57
  "publish-npm": "bash scripts/publish.sh",
52
- "prepublishOnly": "npm run check && npm run build:pix"
58
+ "generate-schemas": "tsx scripts/generate-schemas.ts",
59
+ "generate-schemas:check": "tsx scripts/generate-schemas.ts --check",
60
+ "generate-schemas:watch": "tsx watch scripts/generate-schemas.ts",
61
+ "prepublishOnly": "npm run check && npm run build:pix && npm run generate-schemas"
53
62
  },
54
63
  "dependencies": {
55
64
  "@earendil-works/pi-tui": "0.77.0",