@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.
- package/CHANGELOG.md +79 -0
- package/DAWG.md +196 -11
- package/README.md +79 -30
- package/core/diff.ts +249 -0
- package/core/key.ts +43 -0
- package/core/pitch.ts +60 -0
- package/core/score.ts +324 -1
- package/core/sdk/eval-child.ts +113 -0
- package/core/sdk/eval.ts +257 -0
- package/core/sdk/print.ts +393 -0
- package/core/sdk/v1.ts +954 -0
- package/core/slug.ts +19 -0
- package/package.json +8 -5
- package/src/agent/agent.ts +280 -14
- package/src/agent/brief.ts +23 -3
- package/src/agent/gateway.ts +215 -41
- package/src/agent/models.ts +633 -0
- package/src/agent/ops.ts +3 -18
- package/src/agent/planner.ts +38 -0
- package/src/agent/provider.ts +234 -106
- package/src/agent/sse.ts +31 -7
- package/src/agent/tools.ts +398 -1
- package/src/agent/usage.ts +296 -0
- package/src/agent/workspace.ts +683 -0
- package/src/agent/xcb-agent.ts +27 -12
- package/src/agent/xcb.ts +233 -21
- package/src/audio/click.ts +125 -0
- package/src/audio/engine.ts +407 -33
- package/src/audio/live.ts +152 -0
- package/src/audio/player.ts +19 -4
- package/src/audio/render-worker.ts +68 -0
- package/src/audio/renderer.ts +174 -0
- package/src/audio/sampler.ts +292 -0
- package/src/audio/samples.ts +683 -0
- package/src/audio/wav.ts +290 -76
- package/src/auth/cli.ts +146 -27
- package/src/auth/credentials.ts +167 -41
- package/src/auth/discover.ts +481 -0
- package/src/auth/login.ts +885 -128
- package/src/auth/openrouter.ts +206 -0
- package/src/auth/picker.ts +282 -0
- package/src/auth/runner.ts +25 -2
- package/src/auth/tui.ts +60 -43
- package/src/commands/edit.ts +170 -0
- package/src/commands/help.ts +247 -0
- package/src/commands/history.ts +32 -19
- package/src/commands/music.ts +24 -7
- package/src/commands/sample.ts +302 -0
- package/src/main.ts +1043 -166
- package/src/media/analyze.ts +364 -0
- package/src/media/backend.ts +253 -0
- package/src/media/cli.ts +173 -0
- package/src/media/download.ts +281 -0
- package/src/media/dsp.ts +281 -0
- package/src/media/import.ts +130 -0
- package/src/media/lyrics.ts +201 -0
- package/src/media/notes.ts +363 -0
- package/src/media/paths.ts +168 -0
- package/src/media/process.ts +226 -0
- package/src/media/registry.ts +9 -0
- package/src/media/sidecar.ts +72 -0
- package/src/media/stemdeck.ts +254 -0
- package/src/media/stems.ts +173 -0
- package/src/media/tools.ts +292 -0
- package/src/media/types.ts +92 -0
- package/src/media/vendor/basic-pitch.ts +261 -0
- package/src/media/vendor/drums.ts +817 -0
- package/src/media/vendor/grid.ts +203 -0
- package/src/media/vendor/util.ts +139 -0
- package/src/media/vendor/wav.ts +233 -0
- package/src/project/check.ts +80 -0
- package/src/project/init.ts +253 -0
- package/src/project/sync.ts +432 -0
- package/src/project/typecheck.ts +149 -0
- package/src/render.ts +28 -6
- package/src/session/attach.ts +3 -4
- package/src/session/daemon.ts +25 -8
- package/src/session/delta.ts +249 -0
- package/src/session/naming.ts +3 -37
- package/src/session/port.ts +26 -6
- package/src/session/rebase.ts +38 -8
- package/src/session/store.ts +116 -21
- package/src/tui/menu.ts +1083 -0
- package/src/tui/play-mode.ts +442 -0
- package/src/tui/play-session.ts +636 -0
- package/src/web/fetch.ts +340 -0
- package/src/web/http.ts +137 -0
- package/src/web/search.ts +681 -0
- package/tui/activity.ts +42 -3
- package/tui/app.ts +261 -18
- package/tui/drums.ts +44 -0
- package/tui/highway.ts +18 -2
- package/tui/layers.ts +14 -2
- 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
|
+
}
|