gentle-pi 4.3.0 → 4.5.0

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 (218) hide show
  1. package/README.md +10 -7
  2. package/assets/agents/gentle-ai-worker.md +1 -1
  3. package/assets/design-canvas/canvas.css +648 -0
  4. package/assets/design-canvas/canvas.js +1497 -0
  5. package/assets/design-canvas/index.html +88 -0
  6. package/assets/design-canvas/inspector.js +290 -0
  7. package/assets/orchestrator-delegation-reference.md +2 -2
  8. package/assets/orchestrator-verification.md +1 -1
  9. package/assets/orchestrator.md +2 -2
  10. package/bin/engram-guard +1 -1
  11. package/bin/gentle-shell.mjs +138 -155
  12. package/docs/bundled-install.md +47 -42
  13. package/docs/delegated-verification.md +6 -0
  14. package/docs/gentle-agents-activity.md +5 -1
  15. package/docs/gentle-music.md +82 -0
  16. package/docs/gentle-shell.md +80 -10
  17. package/docs/install-wizard.md +30 -6
  18. package/docs/permission-modes.md +7 -2
  19. package/docs/readme-reference.md +72 -55
  20. package/docs/session-profile-format.md +26 -0
  21. package/docs/voice.md +259 -0
  22. package/docs/yolo-mode.md +17 -2
  23. package/extensions/ask-user-choice.ts +4 -1
  24. package/extensions/gentle-agents.ts +187 -40
  25. package/extensions/gentle-ai.ts +1765 -1185
  26. package/extensions/gentle-design.ts +158 -0
  27. package/extensions/gentle-music.ts +354 -0
  28. package/extensions/gentle-shell.ts +418 -79
  29. package/extensions/gentle-voice.ts +11 -0
  30. package/extensions/session-scratch.ts +41 -22
  31. package/extensions/skill-registry.ts +63 -8
  32. package/lib/agent-profiles.ts +26 -0
  33. package/lib/agents-config.ts +35 -0
  34. package/lib/agents-protocol.ts +57 -1
  35. package/lib/agents-runner.ts +52 -3
  36. package/lib/agents-session-transport.ts +101 -6
  37. package/lib/agents-widget.ts +14 -1
  38. package/lib/auto-permission-memory.ts +48 -18
  39. package/lib/auto-permission-runtime.ts +21 -6
  40. package/lib/clipboard-image.ts +147 -0
  41. package/lib/command-palette-catalog.ts +3 -2
  42. package/lib/commit-slice-signal.ts +1 -1
  43. package/lib/context-backstop.ts +36 -0
  44. package/lib/design-canvas-server.ts +947 -0
  45. package/lib/design-comments.ts +437 -0
  46. package/lib/design-handoffs.ts +313 -0
  47. package/lib/design-open-browser.ts +58 -0
  48. package/lib/design-sources.ts +120 -0
  49. package/lib/external-editor.ts +31 -0
  50. package/lib/gentle-design.ts +513 -0
  51. package/lib/gentle-shell-bundled.ts +141 -57
  52. package/lib/gentle-shell-launcher.ts +11 -4
  53. package/lib/gentle-shell-startup-update.ts +61 -9
  54. package/lib/gentle-shell-uninstall.ts +33 -1
  55. package/lib/image-attachments.ts +150 -0
  56. package/lib/inprocess-reviewer.ts +33 -2
  57. package/lib/jobs-sidebar-state.ts +22 -3
  58. package/lib/jobs-widget.ts +112 -0
  59. package/lib/nan-provider.ts +3 -0
  60. package/lib/native-review-cli.ts +11 -4
  61. package/lib/notification-audio-native.ts +149 -13
  62. package/lib/notification-audio.ts +4 -0
  63. package/lib/notification-pulse-worker.ts +82 -18
  64. package/lib/notification-service.ts +5 -1
  65. package/lib/orchestrator-presence.ts +78 -8
  66. package/lib/orchestrator-scope.ts +10 -0
  67. package/lib/orchestrator-state.ts +11 -3
  68. package/lib/permission-mode-policy.ts +2 -2
  69. package/lib/review-host-relay.ts +11 -2
  70. package/lib/review-reminder-receipt.ts +24 -1
  71. package/lib/session-profile-append-controller.ts +713 -0
  72. package/lib/session-profile-disk-reader.ts +182 -0
  73. package/lib/session-profile-freeze.ts +2 -2
  74. package/lib/session-profile-persistence.ts +15 -7
  75. package/lib/session-scratch.ts +52 -3
  76. package/lib/session-worktree-registry.ts +7 -0
  77. package/lib/shell-bar.ts +6 -7
  78. package/lib/shell-changes.ts +81 -5
  79. package/lib/shell-prompt.ts +4 -4
  80. package/lib/shell-sidebar-layout.ts +27 -7
  81. package/lib/shell-todo.ts +1 -1
  82. package/lib/verifier-admission.ts +5 -4
  83. package/lib/vim-editor-adapter.ts +14 -10
  84. package/lib/voice-artifacts.ts +188 -0
  85. package/lib/voice-command.ts +576 -0
  86. package/lib/voice-install.ts +455 -0
  87. package/lib/voice-platform.ts +99 -0
  88. package/lib/voice-push-to-talk.ts +262 -0
  89. package/lib/voice-session.ts +460 -0
  90. package/lib/voice-settings.ts +50 -0
  91. package/lib/voice-ui.ts +158 -0
  92. package/lib/yolo-session-policy.ts +58 -22
  93. package/package.json +1 -1
  94. package/runtime/gentle-shell-bundled.mjs +140 -56
  95. package/runtime/gentle-shell-launcher.mjs +11 -4
  96. package/runtime/gentle-shell-startup-update.mjs +61 -9
  97. package/runtime/gentle-shell-uninstall.mjs +33 -1
  98. package/runtime/native-review-cli.mjs +11 -4
  99. package/scripts/bundled-engram-migration.mjs +0 -6
  100. package/scripts/bundled-install.mjs +209 -13
  101. package/scripts/gentle-ai-installer.mjs +10 -10
  102. package/scripts/installer-downloads.mjs +31 -7
  103. package/scripts/installer-preflight.mjs +6 -4
  104. package/scripts/installer-windows.mjs +37 -7
  105. package/scripts/main-channel.mjs +91 -17
  106. package/scripts/pi-update.mjs +37 -7
  107. package/scripts/verify-package-files.mjs +26 -2
  108. package/scripts/voice-worker.cjs +476 -0
  109. package/skills/design/SKILL.md +110 -0
  110. package/tests/agent-profiles.test.ts +24 -0
  111. package/tests/agents-config.test.ts +61 -0
  112. package/tests/agents-fake-child.ts +8 -1
  113. package/tests/agents-protocol.test.ts +32 -0
  114. package/tests/agents-runner.test.ts +226 -5
  115. package/tests/agents-session-transport.test.ts +53 -3
  116. package/tests/ask-user-choice.test.ts +30 -0
  117. package/tests/auto-mode.test.ts +17 -0
  118. package/tests/auto-permission-memory-diagnostics.test.ts +56 -0
  119. package/tests/auto-permission-runtime.test.ts +85 -1
  120. package/tests/autonomous-guard.test.ts +20 -0
  121. package/tests/bundled-install.test.ts +276 -5
  122. package/tests/clipboard-image.test.ts +114 -0
  123. package/tests/command-palette.test.ts +4 -4
  124. package/tests/context-backstop.test.ts +70 -4
  125. package/tests/delegate-for-reason-contract.test.ts +2 -1
  126. package/tests/design-canvas-assets.test.ts +710 -0
  127. package/tests/design-canvas-server.test.ts +1096 -0
  128. package/tests/design-comments.test.ts +201 -0
  129. package/tests/design-handoffs.test.ts +282 -0
  130. package/tests/design-open-browser.test.ts +70 -0
  131. package/tests/design-sources.test.ts +132 -0
  132. package/tests/engram-safety.test.ts +132 -57
  133. package/tests/external-editor.test.ts +84 -0
  134. package/tests/fixtures/primary-session-prompt/gentleman.golden.md +3 -3
  135. package/tests/gentle-agents.test.ts +369 -24
  136. package/tests/gentle-ai-binary.test.ts +1 -1
  137. package/tests/gentle-ai-installer.test.ts +51 -51
  138. package/tests/gentle-ai.test.ts +928 -448
  139. package/tests/gentle-design.test.ts +1313 -0
  140. package/tests/gentle-music.test.ts +452 -0
  141. package/tests/gentle-shell-bundled.test.ts +321 -248
  142. package/tests/gentle-shell-launcher.test.ts +29 -2
  143. package/tests/gentle-shell-startup-update.test.ts +77 -1
  144. package/tests/gentle-shell-uninstall.test.ts +59 -0
  145. package/tests/gentle-shell.test.ts +227 -27
  146. package/tests/gentle-todo.test.ts +11 -0
  147. package/tests/image-attachments.test.ts +119 -0
  148. package/tests/image-paste-chips.test.ts +236 -0
  149. package/tests/inprocess-reviewer.test.ts +55 -2
  150. package/tests/installer-bundles.test.ts +12 -6
  151. package/tests/installer-downloads.test.ts +32 -0
  152. package/tests/installer-posix-bootstrap.test.ts +8 -8
  153. package/tests/installer-preflight.test.ts +16 -0
  154. package/tests/installer-server.test.ts +2 -2
  155. package/tests/installer-windows-bootstrap.test.ts +61 -3
  156. package/tests/installer-windows-diagnostics.test.ts +111 -0
  157. package/tests/jobs-widget.test.ts +138 -0
  158. package/tests/main-channel-upgrade.test.ts +232 -2
  159. package/tests/main-channel.test.ts +140 -21
  160. package/tests/model-profiles-preservation.test.ts +2 -2
  161. package/tests/nan-provider.test.ts +36 -0
  162. package/tests/native-review-capability-contract.test.ts +11 -4
  163. package/tests/native-review-parity.test.ts +1 -1
  164. package/tests/notification-audio-native.test.ts +128 -9
  165. package/tests/notification-customize.test.ts +17 -5
  166. package/tests/odd-routing-canonical-ratchet.test.ts +2 -1
  167. package/tests/orchestrator-budget.test.ts +5 -2
  168. package/tests/orchestrator-presence.test.ts +100 -2
  169. package/tests/orchestrator-rdd-ownership.test.ts +2 -2
  170. package/tests/orchestrator-scope.test.ts +14 -0
  171. package/tests/orchestrator-state.test.ts +29 -0
  172. package/tests/package-files.test.ts +34 -0
  173. package/tests/package-manifest.test.ts +6 -6
  174. package/tests/permission-mode-policy.test.ts +10 -1
  175. package/tests/pi-update.test.ts +104 -4
  176. package/tests/rdd-aware-verification-contract.test.ts +1 -1
  177. package/tests/review-host-relay-routing.test.ts +88 -1
  178. package/tests/review-host-relay.test.ts +9 -2
  179. package/tests/review-json-arguments.test.ts +20 -3
  180. package/tests/review-loadout-rdd-off-sdk.test.ts +23 -2
  181. package/tests/review-relay-transport-agent.test.ts +26 -0
  182. package/tests/review-reminder-receipt.test.ts +31 -1
  183. package/tests/runtime-harness.mjs +188 -211
  184. package/tests/session-changes.test.ts +2 -1
  185. package/tests/session-profile-append-controller-fork.test.ts +458 -0
  186. package/tests/session-profile-append-controller-pi.test.ts +290 -0
  187. package/tests/session-profile-append-controller.test.ts +731 -0
  188. package/tests/session-profile-disk-reader-pi.test.ts +183 -0
  189. package/tests/session-profile-disk-reader.test.ts +311 -0
  190. package/tests/session-profile-freeze.test.ts +6 -4
  191. package/tests/session-scratch.test.ts +68 -2
  192. package/tests/session-worktree-registry.test.ts +13 -1
  193. package/tests/shell-bar.test.ts +18 -6
  194. package/tests/shell-changes.test.ts +148 -1
  195. package/tests/shell-prompt.test.ts +3 -3
  196. package/tests/shell-render-cache.test.ts +134 -1
  197. package/tests/shell-sidebar-layout.test.ts +67 -0
  198. package/tests/short-check-routing-contract.test.ts +1 -1
  199. package/tests/skill-collision-prefixes.test.ts +3 -1
  200. package/tests/skill-registry-watcher.test.ts +17 -5
  201. package/tests/skill-registry.test.ts +47 -3
  202. package/tests/task-size-routing-contract.test.ts +1 -1
  203. package/tests/test-strength-contract.test.ts +1 -1
  204. package/tests/verifier-admission.test.ts +18 -1
  205. package/tests/vim-editor-adapter.test.ts +2 -2
  206. package/tests/voice-command.test.ts +773 -0
  207. package/tests/voice-install.test.ts +323 -0
  208. package/tests/voice-platform.test.ts +176 -0
  209. package/tests/voice-push-to-talk.test.ts +444 -0
  210. package/tests/voice-session.test.ts +434 -0
  211. package/tests/voice-settings.test.ts +49 -0
  212. package/tests/voice-ui.test.ts +97 -0
  213. package/tests/voice-worker.test.ts +445 -0
  214. package/tests/weak-model-economy-prompt.test.ts +32 -0
  215. package/tests/windows-hidden-processes.test.ts +25 -2
  216. package/tests/yolo-customize.test.ts +5 -1
  217. package/tests/yolo-mode.test.ts +1 -1
  218. package/tests/yolo-session-policy-capture.test.ts +104 -0
@@ -7,10 +7,11 @@ import { contextBackstopReached, type MeasuredContext } from "./context-backstop
7
7
  // existing feature document (the same lines writer admission accepts), or the parent's measured context reaches the
8
8
  // context backstop. The agent catalog has no generic verifier alias, so only `gentle-ai-verify` is gated.
9
9
  const VERIFIER_NAMES = ["gentle-ai-verify"];
10
- // A line that starts with `Risk:` (optionally as a list item) whose first entry is `item N` with N in 1-6, for
11
- // example `Risk: item 3 (shared parser)` or `- Risk: item 2, item 3 (reason)`. `Risk: none` and prose mentions
12
- // do not start such a line.
13
- const HIGH_RISK_ITEM_LINE = /^[ \t]*(?:[-*+][ \t]+)?Risk:[ \t]*item[ \t]+[1-6](?!\d)/m;
10
+ // A declaration that starts a line (optionally as a list item) or a sentence (after `.`, `!` or `?` and a space) with
11
+ // `Risk:` whose first entry is `item N` with N in 1-6, for example `Risk: item 3 (shared parser)`, `- Risk: item 2,
12
+ // item 3 (reason)` or `... on top of ebf3f35. Risk: item 1 (migration)`. `Risk: none` and a mention inside a
13
+ // sentence ("Do not write Risk: item 3") do not start one.
14
+ const HIGH_RISK_ITEM_LINE = /(?:^[ \t]*(?:[-*+][ \t]+)?|[.!?][ \t]+)Risk:[ \t]*item[ \t]+[1-6](?!\d)/m;
14
15
  export const VERIFIER_RISK_REJECTION =
15
16
  "An independent verifier runs only for a change that declares a named high-risk item (`Risk: item N` from the Task Size list in the task). This change declares none: run its focused test and suite inline yourself now; do not retry the launch, and never add a Risk line or create a feature document only to get a verifier admitted.";
16
17
 
@@ -1,7 +1,7 @@
1
1
  import { CURSOR_MARKER, Editor, visibleWidth } from "@earendil-works/pi-tui";
2
2
  import { createRequire } from "node:module";
3
3
 
4
- // Private shape audited against @earendil-works/pi-tui 0.99.1, 0.99.2, 1.0.0, 1.1.0 and 1.2.0:
4
+ // Private shape audited against @earendil-works/pi-tui 0.99.1, 0.99.2, 1.0.0, 1.1.0, 1.2.0, 1.3.0 and 1.4.0:
5
5
  // editor.js state/pastes/history, sticky cursor reset, layoutText/render geometry,
6
6
  // autocomplete cancellation and { state, pastes, pasteCounter } undo restoration;
7
7
  // undo-stack.js clone-on-push/pop snapshots. The two 0.99 releases ship identical
@@ -17,6 +17,7 @@ import { createRequire } from "node:module";
17
17
  // markers resolved by the host TUI (including hardware-cursor suppression).
18
18
  // Keep these markers intact and rearm selection after their reverse-off;
19
19
  // state, undo, paste, layout and autocomplete contracts remain unchanged.
20
+ // 1.3.0 and 1.4.0 ship editor.js, undo-stack.js and keys.js byte-identical to 1.2.0.
20
21
  // Never silently adapt another build: undo also owns the paste registry.
21
22
  interface Position { line: number; col: number }
22
23
  interface State { lines: string[]; cursorLine: number; cursorCol: number }
@@ -32,6 +33,8 @@ interface PrivateEditor {
32
33
  onChange?: (text: string) => void;
33
34
  pastes: Map<number, string>;
34
35
  pasteCounter: number;
36
+ /** Host-owned atomic spans (gentle-shell#2464 image chips) that NORMAL motions must not split. */
37
+ atomicSpans?(line: string): Array<{ start: number; end: number }>;
35
38
  undoStack: Stack;
36
39
  history: string[];
37
40
  historyIndex: number;
@@ -55,7 +58,7 @@ interface PrivateEditor {
55
58
 
56
59
  // The single audited-release source for the adapter and Gentle Shell's runtime
57
60
  // identity gates. Add a release only after re-auditing the files named above.
58
- export const AUDITED_PI_EDITOR_VERSIONS = Object.freeze(["0.99.1", "0.99.2", "1.0.0", "1.1.0", "1.2.0"] as const);
61
+ export const AUDITED_PI_EDITOR_VERSIONS = Object.freeze(["0.99.1", "0.99.2", "1.0.0", "1.1.0", "1.2.0", "1.3.0", "1.4.0"] as const);
59
62
  export type AuditedPiEditorVersion = (typeof AUDITED_PI_EDITOR_VERSIONS)[number];
60
63
 
61
64
  export function isAuditedPiEditorVersion(version: unknown): version is AuditedPiEditorVersion {
@@ -151,12 +154,13 @@ function highlightRenderedRow(row: string, chunk: LayoutLine, left: number, righ
151
154
  return result;
152
155
  }
153
156
 
154
- function boundaries(line: string, pastes: Map<number, string>): number[] {
157
+ function boundaries(line: string, editor: Pick<PrivateEditor, "pastes" | "atomicSpans">): number[] {
155
158
  const units = [...segmenter.segment(line)].map((part) => part.index);
156
- for (const match of line.matchAll(marker)) {
157
- if (!pastes.has(Number(match[1]))) continue;
158
- const start = match.index;
159
- const end = start + match[0].length;
159
+ const spans = [...line.matchAll(marker)]
160
+ .filter((match) => editor.pastes.has(Number(match[1])))
161
+ .map((match) => ({ start: match.index, end: match.index + match[0].length }));
162
+ if (typeof editor.atomicSpans === "function") spans.push(...editor.atomicSpans(line));
163
+ for (const { start, end } of spans) {
160
164
  for (let i = units.length - 1; i >= 0; i--) {
161
165
  if (units[i]! > start && units[i]! < end) units.splice(i, 1);
162
166
  }
@@ -177,7 +181,7 @@ function assertUniquePastes(editor: PrivateEditor): void {
177
181
  function assertPosition(editor: PrivateEditor, pos: Position): void {
178
182
  assertUniquePastes(editor);
179
183
  const line = editor.state.lines[pos.line];
180
- if (line === undefined || !Number.isInteger(pos.col) || !boundaries(line, editor.pastes).includes(pos.col)) {
184
+ if (line === undefined || !Number.isInteger(pos.col) || !boundaries(line, editor).includes(pos.col)) {
181
185
  throw new Error("Cursor must be on a valid grapheme or paste boundary");
182
186
  }
183
187
  }
@@ -265,7 +269,7 @@ export function createVimEditorAdapter(value: unknown, version: string, editorCl
265
269
  },
266
270
  motionBoundaries(): number[][] {
267
271
  assertUniquePastes(editor);
268
- return editor.state.lines.map((line) => boundaries(line, editor.pastes));
272
+ return editor.state.lines.map((line) => boundaries(line, editor));
269
273
  },
270
274
  move(pos: Position): void {
271
275
  assertPosition(editor, pos);
@@ -277,7 +281,7 @@ export function createVimEditorAdapter(value: unknown, version: string, editorCl
277
281
  moveByGraphemes(delta: number): void {
278
282
  if (!Number.isInteger(delta)) throw new Error("Invalid motion");
279
283
  const positions = editor.state.lines.flatMap((line, index) =>
280
- boundaries(line, editor.pastes).map((col) => ({ line: index, col })));
284
+ boundaries(line, editor).map((col) => ({ line: index, col })));
281
285
  const current = editor.getCursor();
282
286
  const at = positions.findIndex((p) => p.line === current.line && p.col === current.col);
283
287
  if (at < 0) throw new Error("Invalid cursor boundary");
@@ -0,0 +1,188 @@
1
+ // Pinned artifacts for the optional local voice dictation (S1-S3). Nothing here is
2
+ // fetched or resolved at runtime: every version, size and digest below was read
3
+ // from the public npm registry and Hugging Face metadata for the exact versions,
4
+ // and the tarball layouts were inspected for the facts the comments state.
5
+ // Installation lives in voice-install.ts; this module is data only.
6
+
7
+ export type VoiceTarget = "darwin-x64" | "darwin-arm64" | "linux-x64" | "linux-arm64" | "win32-x64";
8
+
9
+ export const VOICE_TARGETS: readonly VoiceTarget[] = ["darwin-x64", "darwin-arm64", "linux-x64", "linux-arm64", "win32-x64"];
10
+
11
+ // A redirect hop is followed only when its URL is HTTPS on this origin and its
12
+ // path starts with the prefix. Anything else ends the download.
13
+ export interface VoiceRedirectRule {
14
+ origin: string;
15
+ pathPrefix: string;
16
+ }
17
+
18
+ export interface VoiceNpmPackage {
19
+ name: string;
20
+ version: string;
21
+ license: string;
22
+ tarball: string;
23
+ // The packed tarball size in bytes and its registry `dist.integrity`.
24
+ size: number;
25
+ integrity: string;
26
+ // Registry `dist.unpackedSize` and `dist.fileCount`: hard limits for extraction.
27
+ unpackedSize: number;
28
+ fileCount: number;
29
+ // Paths relative to the package root that must be present after extraction.
30
+ requiredFiles: string[];
31
+ }
32
+
33
+ export interface VoiceRuntimeManifest {
34
+ // The installed directory name; also part of the install marker.
35
+ id: string;
36
+ target: VoiceTarget;
37
+ packages: VoiceNpmPackage[];
38
+ redirects: VoiceRedirectRule[];
39
+ }
40
+
41
+ export interface VoiceModelFile {
42
+ name: string;
43
+ size: number;
44
+ sha256: string;
45
+ }
46
+
47
+ export interface VoiceModelManifest {
48
+ id: string;
49
+ revision: string;
50
+ // Files are fetched from `${baseUrl}/${name}`.
51
+ baseUrl: string;
52
+ files: VoiceModelFile[];
53
+ redirects: VoiceRedirectRule[];
54
+ }
55
+
56
+ const SHERPA_VERSION = "1.13.8";
57
+
58
+ const npmTarball = (name: string, version: string) => `https://registry.npmjs.org/${name}/-/${name}-${version}.tgz`;
59
+
60
+ // sherpa-onnx-node holds only JavaScript. Its addon-static-import.js loads
61
+ // `../sherpa-onnx-<platform>-<arch>/sherpa-onnx.node` (Windows spelled `win`), so the
62
+ // platform package must be installed as a sibling directory under node_modules.
63
+ export const SHERPA_ONNX_NODE: VoiceNpmPackage = {
64
+ name: "sherpa-onnx-node",
65
+ version: SHERPA_VERSION,
66
+ license: "Apache-2.0",
67
+ tarball: npmTarball("sherpa-onnx-node", SHERPA_VERSION),
68
+ size: 11954,
69
+ integrity: "sha512-MsDMBdhLFTZ1GwvcGSSQhnS7g/EA8OMH6IYysCVUOM7j8Icty9KRc0E6YT1A5fWBsZwRfKOeh88QC95aRvS8ag==",
70
+ unpackedSize: 61221,
71
+ fileCount: 19,
72
+ requiredFiles: ["package.json", "sherpa-onnx.js", "addon.js", "addon-static-import.js", "non-streaming-asr.js"],
73
+ };
74
+
75
+ function sherpaPlatform(target: VoiceTarget, size: number, integrity: string, unpackedSize: number, fileCount: number): VoiceNpmPackage {
76
+ const name = `sherpa-onnx-${target.replace(/^win32-/, "win-")}`;
77
+ return {
78
+ name,
79
+ version: SHERPA_VERSION,
80
+ license: "Apache-2.0",
81
+ tarball: npmTarball(name, SHERPA_VERSION),
82
+ size,
83
+ integrity,
84
+ unpackedSize,
85
+ fileCount,
86
+ requiredFiles: ["package.json", "sherpa-onnx.node"],
87
+ };
88
+ }
89
+
90
+ // Each platform package bundles sherpa-onnx.node, the sherpa-onnx C/C++ API
91
+ // libraries and onnxruntime, all built for the named architecture.
92
+ export const SHERPA_ONNX_PLATFORM_PACKAGES: Readonly<Record<VoiceTarget, VoiceNpmPackage>> = {
93
+ "darwin-x64": sherpaPlatform("darwin-x64", 11191481, "sha512-7BLRpjM6w4f9W46/nmkmq8lEKUayhebvcpslCVQ+6QN2uReYlZEMDZlSpXMjme+hUFrPfRz8P3UNq8ep/4d19g==", 37678686, 7),
94
+ "darwin-arm64": sherpaPlatform("darwin-arm64", 10047754, "sha512-FPNgJMgnWVl/KhRTIhG3KL3A4Om63Rn4YKXc9/uHY7SzLcvqLJLc/h7UBWJwduXvv7K18t5NpxHR6XgXn4sjWw==", 34089738, 7),
95
+ "linux-x64": sherpaPlatform("linux-x64", 11089653, "sha512-6plnhjagsSeTntCgnlag86hWbs/uZE9Crms1LgOb68/1nKsIQjMd+WG519m+aPwT6TrsBOiEMzrx41t8sL5L5g==", 33381117, 7),
96
+ "linux-arm64": sherpaPlatform("linux-arm64", 13910679, "sha512-Tlg7a70b/Wge3OF8IgTHF9jhSVCsLyKQKhwc4BsJ5A+dL/SrFtGBjzuHp4XeLhiiOT7afCxX5PdSn/D4c8Lnuw==", 40306856, 7),
97
+ "win32-x64": sherpaPlatform("win32-x64", 8894875, "sha512-oZF1c9VPOKtMwn83Bboc5XSWL+76BRoyB3eUuVnCknBKxwSULZU2Foia9VHWzU+n4I12rPsP6z6H9Rp1hD9o8g==", 23453246, 8),
98
+ };
99
+
100
+ // node-cpal has no dependencies or install scripts and needs Node >= 22. Its
101
+ // tarball ships every prebuilt binary; the default backend loads
102
+ // bin/<platform>-<arch>/index.node through facade.js. The five binary headers were
103
+ // inspected (not loaded) and each is built for its own architecture. Published
104
+ // from saeta-eth/node-cpal tag v1.0.0, commit 20e2ac8d1922de7c4af50431e2ddc21a421cf764.
105
+ // 0.1.1 is not used: its darwin-x64 and linux-arm64 binaries were built for the
106
+ // other architecture.
107
+ const NODE_CPAL_VERSION = "1.0.0";
108
+
109
+ export const NODE_CPAL: VoiceNpmPackage = {
110
+ name: "node-cpal",
111
+ version: NODE_CPAL_VERSION,
112
+ license: "ISC",
113
+ tarball: npmTarball("node-cpal", NODE_CPAL_VERSION),
114
+ size: 7723259,
115
+ integrity: "sha512-d71jIzKDjw1HepqaJQMPd+/k3ZLqYZWhLAv6a8aafIGnYoA1QWlShA5iB5CgijIJtQxq9PdQAk99JQKspqlnTA==",
116
+ unpackedSize: 20363834,
117
+ fileCount: 40,
118
+ requiredFiles: ["package.json", "index.js", "facade.js", "cpal-values.js"],
119
+ };
120
+
121
+ // The oldest glibc the pinned Linux native binaries accept.
122
+ export const VOICE_LINUX_MIN_GLIBC = "2.34";
123
+
124
+ export function voiceRuntimeManifest(target: VoiceTarget): VoiceRuntimeManifest {
125
+ const packages = [
126
+ SHERPA_ONNX_NODE,
127
+ SHERPA_ONNX_PLATFORM_PACKAGES[target],
128
+ { ...NODE_CPAL, requiredFiles: [...NODE_CPAL.requiredFiles, `bin/${target}/index.node`] },
129
+ ];
130
+ // The id names both native versions, so a runtime installed with other pins
131
+ // lives in another directory and is never reported as this one.
132
+ // npm serves these tarballs directly; no redirect is expected or followed.
133
+ return { id: `sherpa-onnx-${SHERPA_VERSION}-node-cpal-${NODE_CPAL_VERSION}-${target}`, target, packages, redirects: [] };
134
+ }
135
+
136
+ const PARAKEET_REPO = "csukuangfj/sherpa-onnx-nemo-parakeet-tdt-0.6b-v3-int8";
137
+ const PARAKEET_REVISION = "2bda32ec70b097a55adaa07d9a7173915b43cc78";
138
+
139
+ // The int8 sherpa-onnx export of NVIDIA Parakeet TDT 0.6B v3 at a fixed commit.
140
+ // Observed redirects: tokens.txt answers 307 with a same-origin resolve-cache path,
141
+ // the LFS/Xet files answer 302 to us.aws.cdn.hf.co/xet-bridge-us/. Other CDN
142
+ // regions were not observed, so they are refused rather than guessed.
143
+ export const PARAKEET_MODEL_MANIFEST: VoiceModelManifest = {
144
+ id: `parakeet-tdt-0.6b-v3-int8-${PARAKEET_REVISION.slice(0, 12)}`,
145
+ revision: PARAKEET_REVISION,
146
+ baseUrl: `https://huggingface.co/${PARAKEET_REPO}/resolve/${PARAKEET_REVISION}`,
147
+ files: [
148
+ { name: "encoder.int8.onnx", size: 652184281, sha256: "acfc2b4456377e15d04f0243af540b7fe7c992f8d898d751cf134c3a55fd2247" },
149
+ { name: "decoder.int8.onnx", size: 11845275, sha256: "179e50c43d1a9de79c8a24149a2f9bac6eb5981823f2a2ed88d655b24248db4e" },
150
+ { name: "joiner.int8.onnx", size: 6355277, sha256: "3164c13fc2821009440d20fcb5fdc78bff28b4db2f8d0f0b329101719c0948b3" },
151
+ { name: "tokens.txt", size: 93939, sha256: "d58544679ea4bc6ac563d1f545eb7d474bd6cfa467f0a6e2c1dc1c7d37e3c35d" },
152
+ ],
153
+ redirects: [
154
+ { origin: "https://huggingface.co", pathPrefix: `/api/resolve-cache/models/${PARAKEET_REPO}/${PARAKEET_REVISION}/` },
155
+ { origin: "https://us.aws.cdn.hf.co", pathPrefix: "/xet-bridge-us/" },
156
+ ],
157
+ };
158
+
159
+ export interface VoiceNotice {
160
+ component: string;
161
+ license: string;
162
+ source: string;
163
+ attribution?: string;
164
+ // What is known to be missing from the distributed artifact, stated plainly.
165
+ unresolved?: string;
166
+ }
167
+
168
+ export const VOICE_NOTICES: readonly VoiceNotice[] = [
169
+ {
170
+ component: "parakeet-tdt-0.6b-v3",
171
+ license: "CC-BY-4.0",
172
+ source: "https://huggingface.co/nvidia/parakeet-tdt-0.6b-v3",
173
+ attribution: "Parakeet TDT 0.6B v3 by NVIDIA, licensed under CC-BY-4.0; int8 sherpa-onnx export by csukuangfj.",
174
+ unresolved: `The ${PARAKEET_REPO} export has no license file or model card license of its own; the license is taken from the upstream NVIDIA model.`,
175
+ },
176
+ {
177
+ component: "sherpa-onnx-node",
178
+ license: "Apache-2.0",
179
+ source: "https://github.com/k2-fsa/sherpa-onnx",
180
+ unresolved: "The sherpa-onnx npm tarballs ship no LICENSE or NOTICE file, and the platform packages bundle onnxruntime (MIT) without its license text.",
181
+ },
182
+ {
183
+ component: "node-cpal",
184
+ license: "ISC",
185
+ source: "https://github.com/saeta-eth/node-cpal",
186
+ unresolved: "The node-cpal@1.0.0 tarball ships no LICENSE or NOTICE file, and its prebuilt binaries link Rust crates whose notices are not included.",
187
+ },
188
+ ];