veodl 1.12.1 → 2.0.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 (60) hide show
  1. package/CHANGELOG.md +15 -0
  2. package/LICENSE +21 -21
  3. package/README.md +178 -97
  4. package/bin/veo.js +47 -2
  5. package/docs/AGENT_GUIDE.md +1 -1
  6. package/native/android-arm64/veo +0 -0
  7. package/native/darwin-arm64/veo +0 -0
  8. package/native/darwin-x64/veo +0 -0
  9. package/native/linux-arm64/veo +0 -0
  10. package/native/linux-x64/veo +0 -0
  11. package/native/win32-arm64/veo.exe +0 -0
  12. package/native/win32-x64/veo.exe +0 -0
  13. package/package.json +53 -57
  14. package/src/alias.js +0 -258
  15. package/src/backend-update.js +0 -191
  16. package/src/backend.js +0 -572
  17. package/src/changes.js +0 -278
  18. package/src/cli.js +0 -785
  19. package/src/compatibility.js +0 -39
  20. package/src/config-clipboard.js +0 -67
  21. package/src/config-diagnostics.js +0 -155
  22. package/src/config-editor.js +0 -404
  23. package/src/config-errors.js +0 -64
  24. package/src/config-reset.js +0 -39
  25. package/src/config-template.js +0 -227
  26. package/src/config.js +0 -307
  27. package/src/disk-space.js +0 -68
  28. package/src/doctor.js +0 -306
  29. package/src/download-cache.js +0 -31
  30. package/src/downloader.js +0 -704
  31. package/src/execution.js +0 -68
  32. package/src/experimental-fragments.js +0 -29
  33. package/src/flush.js +0 -66
  34. package/src/history.js +0 -173
  35. package/src/inline-region.js +0 -72
  36. package/src/inspect-media.js +0 -179
  37. package/src/interactive.js +0 -120
  38. package/src/jobs.js +0 -218
  39. package/src/legacy-config-comments.js +0 -106
  40. package/src/media-assets.js +0 -272
  41. package/src/naming.js +0 -54
  42. package/src/open-file.js +0 -15
  43. package/src/option-suggestions.js +0 -43
  44. package/src/output.js +0 -81
  45. package/src/path-links.js +0 -53
  46. package/src/paths.js +0 -26
  47. package/src/playlist.js +0 -31
  48. package/src/progress.js +0 -341
  49. package/src/run-archive.js +0 -148
  50. package/src/runs.js +0 -346
  51. package/src/source-discovery.js +0 -305
  52. package/src/state.js +0 -27
  53. package/src/stats.js +0 -63
  54. package/src/terminal-size.js +0 -8
  55. package/src/terminal-title.js +0 -19
  56. package/src/tool-setup.js +0 -289
  57. package/src/uninstall.js +0 -222
  58. package/src/updater.js +0 -229
  59. package/src/utils.js +0 -208
  60. package/src/version.js +0 -38
package/src/changes.js DELETED
@@ -1,278 +0,0 @@
1
- import { commandOutput } from './output.js';
2
- import { readFile } from 'node:fs/promises';
3
- import { terminalColumns } from './terminal-size.js';
4
- import { wrap } from './progress.js';
5
- import { compareVersions } from './version.js';
6
- import { packageVersion } from './updater.js';
7
- import { suggestOption } from './option-suggestions.js';
8
- import { cleanText } from './utils.js';
9
-
10
- /**
11
- * `veo changes` reads the CHANGELOG.md that ships inside this package, so the
12
- * notes always belong to the installed code and work without network access. The
13
- * file is parsed into data instead of being printed: sections, bullets, nested
14
- * bullets and wrapped lines survive, and `--json` returns the same structure.
15
- */
16
- const RELEASE = /^##\s+v?(\d+\.\d+\.\d+(?:-[0-9A-Za-z.]+)?)(?:\s+[-–—]\s+(\d{4}-\d{2}-\d{2}))?\s*$/;
17
- const SECTION = /^###\s+(.+?)\s*$/;
18
- const BULLET = /^(\s*)-\s+(.*)$/;
19
- const VERSION = /^\d+(\.\d+)*$/;
20
- const MARKER = '(installed)';
21
- const SHOWN = 5;
22
- const USAGE = 'Usage: veo changes [<version>] [--json] [--latest] [--since <version>] [--to <version>] [--range <from>..<to>]';
23
-
24
- export const CHANGES_HELP = `veo changes [<version>] [--json] [--latest] [--since <version>]
25
- [--to <version>] [--range <from>..<to>]
26
-
27
- List every released version, newest first, and mark the installed one. With a version
28
- (or --version) show that release's notes; a partial version such as 1.10 selects the
29
- newest match. --since shows everything newer than a version, --to and --range set both
30
- ends of a range, and --latest shows only the newest release. Notes come from the
31
- CHANGELOG.md shipped with this veo version, so the command needs no network access and
32
- prints no automatic update hint. Use --json for scripting.
33
- `;
34
-
35
- /**
36
- * Keep a Changelog style document becomes releases, newest first. A heading of
37
- * second level that is not a version ends the notes, so an appended file list or
38
- * a second document cannot leak into the last release.
39
- */
40
- export function parseChangelog(markdown) {
41
- const releases = [];
42
- let release = null;
43
- let section = null;
44
- let item = null; // Current top-level bullet and parent of any nested ones.
45
- let last = null; // Most recent bullet, which a wrapped line continues.
46
- for (const raw of String(markdown).split(/\r?\n/)) {
47
- const line = raw.replace(/\s+$/, '');
48
- if (!line.trim()) { last = null; continue; }
49
- const heading = RELEASE.exec(line);
50
- if (heading) {
51
- release = { version: heading[1], date: heading[2] || null, sections: [] };
52
- releases.push(release);
53
- section = null; item = null; last = null;
54
- continue;
55
- }
56
- // A second-level heading that is not a version ends the notes; the document
57
- // title above the first release is preamble and ignored.
58
- if (/^##\s/.test(line)) break;
59
- if (!release) continue;
60
- const type = SECTION.exec(line);
61
- if (type) {
62
- section = { type: cleanText(type[1]), items: [] };
63
- release.sections.push(section);
64
- item = null; last = null;
65
- continue;
66
- }
67
- if (!section) continue;
68
- const bullet = BULLET.exec(line);
69
- if (bullet) {
70
- const text = cleanText(bullet[2]);
71
- if (!text) continue;
72
- if (!bullet[1].length || !item) {
73
- item = { text, items: [] };
74
- section.items.push(item);
75
- last = item;
76
- } else {
77
- last = { text, items: [] };
78
- item.items.push(last);
79
- }
80
- continue;
81
- }
82
- // Without a bullet the line continues the previous one; the changelog wraps prose.
83
- if (last) last.text = cleanText(`${last.text} ${line.trim()}`);
84
- }
85
- return releases.sort((left, right) => compareVersions(right.version, left.version));
86
- }
87
-
88
- /** Entry counts per section type, in the order the changelog lists them. */
89
- export function releaseCounts(release) {
90
- return Object.fromEntries(release.sections.filter(section => section.items.length)
91
- .map(section => [section.type, section.items.length]));
92
- }
93
-
94
- const summary = counts => Object.entries(counts).map(([type, count]) => `${type} ${count}`).join(', ');
95
-
96
- /** Exact match first, then the newest release starting with the given prefix. */
97
- export function resolveVersion(releases, requested, label = 'version') {
98
- const wanted = String(requested ?? '').trim().replace(/^v/i, '');
99
- if (!VERSION.test(wanted)) throw new Error(`${label} must be a version number such as 1.11.0.`);
100
- const exact = releases.find(release => release.version === wanted);
101
- if (exact) return exact;
102
- const partial = releases.filter(release => release.version.startsWith(`${wanted}.`) || release.version.startsWith(`${wanted}-`));
103
- if (partial.length) return partial.reduce((best, release) => compareVersions(release.version, best.version) > 0 ? release : best);
104
- const known = releases.map(release => release.version);
105
- if (!known.length) throw new Error(`${label} "${cleanText(requested)}" cannot be resolved: the changelog lists no releases.`);
106
- const guess = suggestOption(wanted, known);
107
- const list = known.slice(0, SHOWN).join(', ');
108
- throw new Error(`Unknown ${label} "${cleanText(requested)}".${guess ? ` Did you mean "${guess}"?` : ''} Known versions: ${list}${known.length > SHOWN ? ', …' : ''}.`);
109
- }
110
-
111
- /** Which releases a request selects, and under which heading they are shown. */
112
- export function selectReleases(releases, { version = null, latest = false, since = null, to = null } = {}) {
113
- const sorted = [...releases].sort((left, right) => compareVersions(right.version, left.version));
114
- const newest = sorted[0]?.version ?? null;
115
- if (version) {
116
- const release = resolveVersion(sorted, version);
117
- return { mode: 'version', from: release.version, to: release.version, versions: [release] };
118
- }
119
- if (latest) return { mode: 'latest', from: newest, to: newest, versions: sorted.slice(0, 1) };
120
- if (since || to) {
121
- const from = since ? resolveVersion(sorted, since, '--since').version : null;
122
- const upper = to ? resolveVersion(sorted, to, '--to').version : null;
123
- if (from && upper && compareVersions(upper, from) < 0) throw new Error(`--to ${upper} is older than --since ${from}.`);
124
- const versions = sorted.filter(release => (!from || compareVersions(release.version, from) > 0)
125
- && (!upper || compareVersions(release.version, upper) <= 0));
126
- if (!versions.length) {
127
- if (from && !upper) throw new Error(`This veo is already at ${from}; no newer changes are listed.`);
128
- throw new Error(`No changes listed between ${from ?? 'the first release'} and ${upper ?? newest}.`);
129
- }
130
- return { mode: 'range', from, to: upper ?? newest, versions };
131
- }
132
- return { mode: 'list', from: null, to: null, versions: sorted };
133
- }
134
-
135
- /** The shipped changelog, or a clear error when an installation lost the file. */
136
- export async function readChangelog(file = new URL('../CHANGELOG.md', import.meta.url)) {
137
- let markdown;
138
- try {
139
- markdown = await readFile(file, 'utf8');
140
- } catch (error) {
141
- if (error.code === 'ENOENT' || error.code === 'EISDIR') throw new Error(`No CHANGELOG.md found at ${file}.`);
142
- throw error;
143
- }
144
- return parseChangelog(markdown);
145
- }
146
-
147
- function bulletLines(entry, stream, depth) {
148
- const prefix = `${' '.repeat(depth)}- `;
149
- const hanging = ' '.repeat(prefix.length);
150
- // Notes are wrapped instead of shortened: a release note that loses its tail
151
- // because the terminal is narrow would be worse than useless.
152
- const columns = stream?.isTTY ? Math.max(24, terminalColumns(stream) - prefix.length - 1) : Infinity;
153
- return wrap(entry.text, columns).split('\n').map((line, index) => (index ? hanging : prefix) + line);
154
- }
155
-
156
- function releaseLines(release, stream, installed, header) {
157
- const lines = [];
158
- if (header) lines.push(release.version + (installed ? ` ${MARKER}` : ''));
159
- for (const section of release.sections) {
160
- if (!section.items.length) continue;
161
- lines.push(section.type);
162
- for (const entry of section.items) {
163
- lines.push(...bulletLines(entry, stream, 1));
164
- for (const nested of entry.items) lines.push(...bulletLines(nested, stream, 2));
165
- }
166
- lines.push('');
167
- }
168
- if (lines.at(-1) === '') lines.pop();
169
- return lines;
170
- }
171
-
172
- const plural = count => `${count} version${count === 1 ? '' : 's'}`;
173
-
174
- export function formatChanges(selection, { current, stream } = {}) {
175
- const { mode, versions } = selection;
176
- if (!versions.length) return 'veo changes\n\nNo release notes found in CHANGELOG.md.\n';
177
- if (mode === 'list') {
178
- const width = Math.max(...versions.map(release => release.version.length));
179
- const lines = [`veo changes (${plural(versions.length)}, newest first)`, ''];
180
- for (const release of versions) {
181
- const installed = release.version === current ? MARKER : '';
182
- const row = ` ${release.version.padEnd(width)} ${installed.padEnd(MARKER.length)}`;
183
- const counts = summary(releaseCounts(release));
184
- // A release without entries must not leave trailing spaces in the column.
185
- lines.push(counts ? `${row} ${counts}` : row);
186
- }
187
- lines.push('');
188
- lines.push('Use veo changes <version> for one version, veo changes --since <version> for');
189
- lines.push('everything newer than a given version, or --json for scripting.');
190
- return `${lines.join('\n')}\n`;
191
- }
192
- const title = mode === 'range'
193
- ? `veo changes ${selection.from ? `${selection.from} to ${selection.to}` : `up to ${selection.to}`} (${plural(versions.length)}, newest first)`
194
- : `veo changes ${selection.from}`;
195
- const lines = [title, ''];
196
- for (const release of versions) {
197
- lines.push(...releaseLines(release, stream, release.version === current, mode === 'range'));
198
- lines.push('');
199
- }
200
- lines.pop();
201
- return `${lines.join('\n')}\n`;
202
- }
203
-
204
- const sectionsJson = release => release.sections.filter(section => section.items.length)
205
- .map(section => ({ type: section.type, items: section.items }));
206
-
207
- function changesJson(selection, current) {
208
- if (selection.mode === 'list') {
209
- return {
210
- current,
211
- count: selection.versions.length,
212
- versions: selection.versions.map(release => {
213
- const counts = releaseCounts(release);
214
- return { version: release.version, date: release.date, installed: release.version === current, counts, summary: summary(counts) };
215
- }),
216
- };
217
- }
218
- if (selection.mode === 'range') {
219
- return {
220
- current,
221
- from: selection.from,
222
- to: selection.to,
223
- count: selection.versions.length,
224
- versions: selection.versions.map(release => ({
225
- version: release.version, date: release.date, installed: release.version === current, sections: sectionsJson(release),
226
- })),
227
- };
228
- }
229
- const [release] = selection.versions;
230
- return { current, version: release.version, date: release.date, installed: release.version === current, sections: sectionsJson(release) };
231
- }
232
-
233
- function versionValue(value, flag) {
234
- if (!value || value.startsWith('-')) throw new Error(`${flag} requires a version number such as 1.11.0.`);
235
- return value;
236
- }
237
-
238
- export function parseChangesArgs(args) {
239
- const options = { json: false, latest: false, version: null, since: null, to: null };
240
- for (let index = 0; index < args.length; index++) {
241
- let arg = args[index];
242
- let inline = null;
243
- const equals = arg.indexOf('=');
244
- if (arg.startsWith('--') && equals > 2) { inline = arg.slice(equals + 1); arg = arg.slice(0, equals); }
245
- const value = () => versionValue(inline ?? args[++index], arg);
246
- if (arg === '--json') options.json = true;
247
- else if (arg === '--latest') options.latest = true;
248
- else if (arg === '--version') options.version = value();
249
- else if (arg === '--since') options.since = value();
250
- else if (arg === '--to') options.to = value();
251
- else if (arg === '--range') {
252
- const [from, to] = value().split('..');
253
- if (!from || !to) throw new Error(`--range must look like 1.9.0..1.11.0. ${USAGE}`);
254
- options.since ??= from;
255
- options.to ??= to;
256
- } else if (arg.startsWith('-')) throw new Error(`Unknown option "${arg}". ${USAGE}`);
257
- else if (!options.version) options.version = arg;
258
- else throw new Error(USAGE);
259
- }
260
- const ranged = options.since || options.to;
261
- if (options.version && (ranged || options.latest)) throw new Error(`Use either a version or --latest/--since/--to, not both. ${USAGE}`);
262
- if (options.latest && ranged) throw new Error(`Use --latest on its own. ${USAGE}`);
263
- return options;
264
- }
265
-
266
- export async function changesMain(args = [], { stdout = process.stdout, current = null, file } = {}) {
267
- [args, stdout] = commandOutput(args, stdout);
268
- if (args.some(arg => ['--help', '-h'].includes(arg))) {
269
- stdout.write(CHANGES_HELP);
270
- return 0;
271
- }
272
- const options = parseChangesArgs(args);
273
- const installed = current ?? await packageVersion();
274
- const selection = selectReleases(await readChangelog(file), options);
275
- if (options.json) stdout.write(`${JSON.stringify(changesJson(selection, installed))}\n`);
276
- else stdout.write(formatChanges(selection, { current: installed, stream: stdout }));
277
- return 0;
278
- }