@hraness/dawg 0.2.0 → 0.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 (94) hide show
  1. package/CHANGELOG.md +79 -0
  2. package/DAWG.md +196 -11
  3. package/README.md +79 -30
  4. package/core/diff.ts +249 -0
  5. package/core/key.ts +43 -0
  6. package/core/pitch.ts +60 -0
  7. package/core/score.ts +324 -1
  8. package/core/sdk/eval-child.ts +113 -0
  9. package/core/sdk/eval.ts +257 -0
  10. package/core/sdk/print.ts +393 -0
  11. package/core/sdk/v1.ts +954 -0
  12. package/core/slug.ts +19 -0
  13. package/package.json +8 -5
  14. package/src/agent/agent.ts +280 -14
  15. package/src/agent/brief.ts +23 -3
  16. package/src/agent/gateway.ts +215 -41
  17. package/src/agent/models.ts +633 -0
  18. package/src/agent/ops.ts +3 -18
  19. package/src/agent/planner.ts +38 -0
  20. package/src/agent/provider.ts +234 -106
  21. package/src/agent/sse.ts +31 -7
  22. package/src/agent/tools.ts +398 -1
  23. package/src/agent/usage.ts +296 -0
  24. package/src/agent/workspace.ts +683 -0
  25. package/src/agent/xcb-agent.ts +27 -12
  26. package/src/agent/xcb.ts +233 -21
  27. package/src/audio/click.ts +125 -0
  28. package/src/audio/engine.ts +407 -33
  29. package/src/audio/live.ts +152 -0
  30. package/src/audio/player.ts +19 -4
  31. package/src/audio/render-worker.ts +68 -0
  32. package/src/audio/renderer.ts +174 -0
  33. package/src/audio/sampler.ts +292 -0
  34. package/src/audio/samples.ts +683 -0
  35. package/src/audio/wav.ts +290 -76
  36. package/src/auth/cli.ts +146 -27
  37. package/src/auth/credentials.ts +167 -41
  38. package/src/auth/discover.ts +481 -0
  39. package/src/auth/login.ts +885 -128
  40. package/src/auth/openrouter.ts +206 -0
  41. package/src/auth/picker.ts +282 -0
  42. package/src/auth/runner.ts +25 -2
  43. package/src/auth/tui.ts +60 -43
  44. package/src/commands/edit.ts +170 -0
  45. package/src/commands/help.ts +247 -0
  46. package/src/commands/history.ts +32 -19
  47. package/src/commands/music.ts +24 -7
  48. package/src/commands/sample.ts +302 -0
  49. package/src/main.ts +1043 -166
  50. package/src/media/analyze.ts +364 -0
  51. package/src/media/backend.ts +253 -0
  52. package/src/media/cli.ts +173 -0
  53. package/src/media/download.ts +281 -0
  54. package/src/media/dsp.ts +281 -0
  55. package/src/media/import.ts +130 -0
  56. package/src/media/lyrics.ts +201 -0
  57. package/src/media/notes.ts +363 -0
  58. package/src/media/paths.ts +168 -0
  59. package/src/media/process.ts +226 -0
  60. package/src/media/registry.ts +9 -0
  61. package/src/media/sidecar.ts +72 -0
  62. package/src/media/stemdeck.ts +254 -0
  63. package/src/media/stems.ts +173 -0
  64. package/src/media/tools.ts +292 -0
  65. package/src/media/types.ts +92 -0
  66. package/src/media/vendor/basic-pitch.ts +261 -0
  67. package/src/media/vendor/drums.ts +817 -0
  68. package/src/media/vendor/grid.ts +203 -0
  69. package/src/media/vendor/util.ts +139 -0
  70. package/src/media/vendor/wav.ts +233 -0
  71. package/src/project/check.ts +80 -0
  72. package/src/project/init.ts +253 -0
  73. package/src/project/sync.ts +432 -0
  74. package/src/project/typecheck.ts +149 -0
  75. package/src/render.ts +28 -6
  76. package/src/session/attach.ts +3 -4
  77. package/src/session/daemon.ts +25 -8
  78. package/src/session/delta.ts +249 -0
  79. package/src/session/naming.ts +3 -37
  80. package/src/session/port.ts +26 -6
  81. package/src/session/rebase.ts +38 -8
  82. package/src/session/store.ts +116 -21
  83. package/src/tui/menu.ts +1083 -0
  84. package/src/tui/play-mode.ts +442 -0
  85. package/src/tui/play-session.ts +636 -0
  86. package/src/web/fetch.ts +340 -0
  87. package/src/web/http.ts +137 -0
  88. package/src/web/search.ts +681 -0
  89. package/tui/activity.ts +42 -3
  90. package/tui/app.ts +261 -18
  91. package/tui/drums.ts +44 -0
  92. package/tui/highway.ts +18 -2
  93. package/tui/layers.ts +14 -2
  94. package/tui/play-strip.ts +143 -0
@@ -0,0 +1,143 @@
1
+ /**
2
+ * Play mode's two fixed rows: the header (`PLAY C3–F4 vel 100 ● REC
3
+ * click ✓` plus a beat flash) and a one-line keyboard strip with the keys
4
+ * that are sounding lit. Both repaint in place every frame, so playing never
5
+ * scrolls the transcript.
6
+ */
7
+ import type { CellBuffer } from "./screen.ts";
8
+ import { displayWidth, truncate } from "./text.ts";
9
+ import { onBackground, type Theme } from "./theme.ts";
10
+
11
+ export type PlayStripKey = Readonly<{
12
+ key: string;
13
+ label: string;
14
+ black: boolean;
15
+ lit: boolean;
16
+ }>;
17
+
18
+ export type PlayHeaderView = Readonly<{
19
+ /** `C3–F4`. */
20
+ range: string;
21
+ velocity: number;
22
+ /** Record armed. */
23
+ armed: boolean;
24
+ /** Recording right now (armed and the transport is running). */
25
+ recording: boolean;
26
+ replace: boolean;
27
+ click: boolean;
28
+ sustain: boolean;
29
+ /** `count-in 3` while counting in. */
30
+ countIn?: string | undefined;
31
+ /** Beat within the bar (1-based) and whether it is the flash window. */
32
+ beat?: Readonly<{ index: number; of: number; flash: boolean }> | undefined;
33
+ /** `grid 1/16`. */
34
+ grid: string;
35
+ /** Short status (`octave C2`, `no audio`). */
36
+ status?: string | undefined;
37
+ keys: readonly PlayStripKey[];
38
+ }>;
39
+
40
+ /** Text of the header row, for tests and narrow terminals. */
41
+ export function playHeaderText(view: PlayHeaderView, unicode = true): string {
42
+ const parts = [
43
+ "PLAY",
44
+ view.range,
45
+ `vel ${view.velocity}`,
46
+ view.armed
47
+ ? `${unicode ? "●" : "*"} ${view.recording ? "REC" : "rec armed"}${view.replace ? " replace" : ""}`
48
+ : "",
49
+ `click ${view.click ? (unicode ? "✓" : "on") : "off"}`,
50
+ view.sustain ? "SUSTAIN" : "",
51
+ view.grid,
52
+ view.countIn ?? "",
53
+ ].filter(Boolean);
54
+ return parts.join(" ");
55
+ }
56
+
57
+ export function paintPlayHeader(
58
+ buffer: CellBuffer,
59
+ y: number,
60
+ width: number,
61
+ view: PlayHeaderView,
62
+ theme: Theme,
63
+ unicode: boolean,
64
+ ): void {
65
+ const roles = theme.roles;
66
+ const panel = roles.panel;
67
+ buffer.fill(0, y, width, 1, panel);
68
+ let x = 1;
69
+ const put = (text: string, style = roles.text) => {
70
+ if (x >= width - 1) return;
71
+ x += buffer.text(
72
+ x,
73
+ y,
74
+ truncate(text, Math.max(1, width - x - 1)),
75
+ onBackground(style, panel),
76
+ );
77
+ x += buffer.text(x, y, " ", panel);
78
+ };
79
+ put(" PLAY ", roles.pillSteer);
80
+ put(view.range, { ...roles.text, bold: true });
81
+ put(`vel ${view.velocity}`);
82
+ if (view.armed)
83
+ put(
84
+ `${unicode ? "●" : "*"} ${view.recording ? "REC" : "rec armed"}${view.replace ? " replace" : ""}`,
85
+ view.recording ? roles.error : roles.warning,
86
+ );
87
+ put(
88
+ `click ${view.click ? (unicode ? "✓" : "on") : "off"}`,
89
+ view.click ? roles.success : roles.muted,
90
+ );
91
+ if (view.sustain) put("SUSTAIN", roles.pillQueue);
92
+ if (view.countIn) put(view.countIn, roles.warning);
93
+ if (view.beat) {
94
+ const cells = Array.from({ length: view.beat.of }, (_, index) =>
95
+ index + 1 === view.beat!.index
96
+ ? unicode
97
+ ? "●"
98
+ : "o"
99
+ : unicode
100
+ ? "·"
101
+ : ".",
102
+ ).join("");
103
+ put(
104
+ cells,
105
+ view.beat.flash
106
+ ? view.beat.index === 1
107
+ ? roles.error
108
+ : roles.hit
109
+ : roles.muted,
110
+ );
111
+ }
112
+ put(view.grid, roles.muted);
113
+ if (view.status) put(view.status, roles.muted);
114
+ // Mode keys at the right edge while there is room.
115
+ const hint = "z/x oct · c/v vel · r rec · m click · esc exit";
116
+ const room = width - 1 - displayWidth(hint);
117
+ if (room > x) buffer.text(room, y, hint, onBackground(roles.faint, panel));
118
+ }
119
+
120
+ /** `a C3 │ w C#3 …`: each key with its note; lit keys reversed. */
121
+ export function paintPlayStrip(
122
+ buffer: CellBuffer,
123
+ y: number,
124
+ width: number,
125
+ keys: readonly PlayStripKey[],
126
+ theme: Theme,
127
+ ): void {
128
+ const roles = theme.roles;
129
+ buffer.fill(0, y, width, 1, roles.canvas);
130
+ let x = 1;
131
+ for (const key of keys) {
132
+ const cell = `${key.key.toUpperCase()} ${key.label}`;
133
+ const cellWidth = displayWidth(cell) + 1;
134
+ if (x + cellWidth > width - 1) break;
135
+ const style = key.lit
136
+ ? { ...(key.black ? roles.selected : roles.hit), reverse: true }
137
+ : key.black
138
+ ? roles.muted
139
+ : roles.text;
140
+ buffer.text(x, y, cell, style);
141
+ x += cellWidth;
142
+ }
143
+ }