opennote-cli 1.3.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 (50) hide show
  1. package/LICENSE +22 -0
  2. package/README.md +272 -0
  3. package/package.json +30 -0
  4. package/src/arrangement.js +282 -0
  5. package/src/arrangement.ts +317 -0
  6. package/src/assets/cover.png +0 -0
  7. package/src/cli.js +1398 -0
  8. package/src/cli.ts +1709 -0
  9. package/src/exportAudio.js +459 -0
  10. package/src/exportAudio.ts +499 -0
  11. package/src/exportMidi.js +85 -0
  12. package/src/exportMidi.ts +103 -0
  13. package/src/ffmpeg-static.d.ts +5 -0
  14. package/src/fx.js +28 -0
  15. package/src/fx.ts +49 -0
  16. package/src/generator.js +15 -0
  17. package/src/generator.ts +29 -0
  18. package/src/index.js +511 -0
  19. package/src/index.ts +642 -0
  20. package/src/instrument.js +35 -0
  21. package/src/instrument.ts +51 -0
  22. package/src/midi.js +167 -0
  23. package/src/midi.ts +218 -0
  24. package/src/openExport.js +22 -0
  25. package/src/openExport.ts +24 -0
  26. package/src/prompt.js +22 -0
  27. package/src/prompt.ts +25 -0
  28. package/src/providers/auth.js +23 -0
  29. package/src/providers/auth.ts +30 -0
  30. package/src/providers/claudeProvider.js +46 -0
  31. package/src/providers/claudeProvider.ts +50 -0
  32. package/src/providers/factory.js +39 -0
  33. package/src/providers/factory.ts +43 -0
  34. package/src/providers/geminiProvider.js +55 -0
  35. package/src/providers/geminiProvider.ts +71 -0
  36. package/src/providers/grokProvider.js +57 -0
  37. package/src/providers/grokProvider.ts +69 -0
  38. package/src/providers/groqProvider.js +57 -0
  39. package/src/providers/groqProvider.ts +69 -0
  40. package/src/providers/mockProvider.js +13 -0
  41. package/src/providers/mockProvider.ts +15 -0
  42. package/src/providers/openaiProvider.js +45 -0
  43. package/src/providers/openaiProvider.ts +49 -0
  44. package/src/providers/retry.js +46 -0
  45. package/src/providers/retry.ts +54 -0
  46. package/src/types.js +1 -0
  47. package/src/types.ts +17 -0
  48. package/src/validate.js +10 -0
  49. package/src/validate.ts +13 -0
  50. package/tsconfig.json +13 -0
@@ -0,0 +1,54 @@
1
+ const RETRYABLE_STATUS = new Set([408, 409, 425, 429, 500, 502, 503, 504]);
2
+
3
+ function sleep(ms: number): Promise<void> {
4
+ return new Promise((resolve) => setTimeout(resolve, ms));
5
+ }
6
+
7
+ function parseRetryAfterMs(value: string | null): number | null {
8
+ if (!value) return null;
9
+ const sec = Number.parseFloat(value);
10
+ if (Number.isFinite(sec) && sec >= 0) return Math.round(sec * 1000);
11
+ const date = Date.parse(value);
12
+ if (!Number.isNaN(date)) {
13
+ const diff = date - Date.now();
14
+ return diff > 0 ? diff : 0;
15
+ }
16
+ return null;
17
+ }
18
+
19
+ function parseTryAgainMs(text: string): number | null {
20
+ const match = text.match(/try again in\s+(\d+(?:\.\d+)?)s/i);
21
+ if (!match) return null;
22
+ const sec = Number.parseFloat(match[1]);
23
+ if (!Number.isFinite(sec) || sec < 0) return null;
24
+ return Math.round(sec * 1000);
25
+ }
26
+
27
+ function backoffMs(attempt: number): number {
28
+ const base = 500 * Math.pow(2, attempt);
29
+ const jitter = Math.floor(Math.random() * 250);
30
+ return base + jitter;
31
+ }
32
+
33
+ export function shouldRetryStatus(status: number): boolean {
34
+ return RETRYABLE_STATUS.has(status);
35
+ }
36
+
37
+ export function computeRetryDelayMs(
38
+ headersRetryAfter: string | null,
39
+ responseText: string,
40
+ attempt: number,
41
+ ): number {
42
+ const fromHeader = parseRetryAfterMs(headersRetryAfter);
43
+ if (fromHeader != null) return Math.min(10_000, Math.max(250, fromHeader));
44
+
45
+ const fromBody = parseTryAgainMs(responseText);
46
+ if (fromBody != null) return Math.min(10_000, Math.max(250, fromBody));
47
+
48
+ return Math.min(10_000, backoffMs(attempt));
49
+ }
50
+
51
+ export async function waitForRetry(ms: number): Promise<void> {
52
+ await sleep(ms);
53
+ }
54
+
package/src/types.js ADDED
@@ -0,0 +1 @@
1
+ export {};
package/src/types.ts ADDED
@@ -0,0 +1,17 @@
1
+ export type GeneratedNote = {
2
+ pitch: number; // 0..127
3
+ velocity: number; // 1..127
4
+ durationMs: number; // >= 1
5
+ };
6
+
7
+ export type NextNoteRequest = {
8
+ theme: string;
9
+ targetLength: number;
10
+ seedPitch: number;
11
+ history: GeneratedNote[];
12
+ bpm: number;
13
+ };
14
+
15
+ export interface LLMProvider {
16
+ nextNote(input: NextNoteRequest): Promise<GeneratedNote>;
17
+ }
@@ -0,0 +1,10 @@
1
+ function clamp(n, min, max) {
2
+ return Math.max(min, Math.min(max, n));
3
+ }
4
+ export function sanitizeNote(note) {
5
+ return {
6
+ pitch: clamp(Math.round(note.pitch), 0, 127),
7
+ velocity: clamp(Math.round(note.velocity), 1, 127),
8
+ durationMs: Math.max(1, Math.round(note.durationMs)),
9
+ };
10
+ }
@@ -0,0 +1,13 @@
1
+ import type { GeneratedNote } from './types';
2
+
3
+ function clamp(n: number, min: number, max: number): number {
4
+ return Math.max(min, Math.min(max, n));
5
+ }
6
+
7
+ export function sanitizeNote(note: GeneratedNote): GeneratedNote {
8
+ return {
9
+ pitch: clamp(Math.round(note.pitch), 0, 127),
10
+ velocity: clamp(Math.round(note.velocity), 1, 127),
11
+ durationMs: Math.max(1, Math.round(note.durationMs)),
12
+ };
13
+ }
package/tsconfig.json ADDED
@@ -0,0 +1,13 @@
1
+ {
2
+ "compilerOptions": {
3
+ "target": "ES2022",
4
+ "module": "ESNext",
5
+ "moduleResolution": "Bundler",
6
+ "strict": true,
7
+ "skipLibCheck": true,
8
+ "esModuleInterop": true,
9
+ "forceConsistentCasingInFileNames": true,
10
+ "types": ["node"]
11
+ },
12
+ "include": ["src"]
13
+ }