@stringsync/splates 0.0.53 → 0.0.55

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 (63) hide show
  1. package/README.md +7 -24
  2. package/artifact.d.ts +3 -0
  3. package/budget.d.ts +3 -0
  4. package/creds.d.ts +3 -0
  5. package/flags.d.ts +37 -0
  6. package/handoff.d.ts +13 -0
  7. package/hook.d.ts +3 -0
  8. package/index.d.ts +2 -0
  9. package/index.js +1844 -0
  10. package/lane.d.ts +3 -0
  11. package/notes.d.ts +4 -0
  12. package/package.json +12 -14
  13. package/projects.d.ts +3 -0
  14. package/queue.d.ts +3 -0
  15. package/replica.d.ts +3 -0
  16. package/runners.d.ts +3 -0
  17. package/server.d.ts +6 -0
  18. package/setup.d.ts +22 -0
  19. package/slots.d.ts +3 -0
  20. package/splates.d.ts +10 -0
  21. package/task.d.ts +3 -0
  22. package/tunnel.d.ts +3 -0
  23. package/waiting.d.ts +3 -0
  24. package/worker.d.ts +3 -0
  25. package/artifact.ts +0 -120
  26. package/budget.ts +0 -117
  27. package/checkout.ts +0 -8
  28. package/creds.test.ts +0 -336
  29. package/creds.ts +0 -144
  30. package/dev/dev.ts +0 -86
  31. package/dev/eval.ts +0 -21
  32. package/dev/fix.ts +0 -63
  33. package/dev/index.ts +0 -1
  34. package/dev/prove.ts +0 -38
  35. package/dev/root.ts +0 -7
  36. package/dev/ship.ts +0 -46
  37. package/dev/test.ts +0 -154
  38. package/e2e.test.ts +0 -472
  39. package/flags.ts +0 -157
  40. package/hook.ts +0 -328
  41. package/index.ts +0 -18
  42. package/infra.ts +0 -107
  43. package/lane.test.ts +0 -29
  44. package/lane.ts +0 -172
  45. package/notes.ts +0 -19
  46. package/projects.test.ts +0 -191
  47. package/projects.ts +0 -37
  48. package/queue.ts +0 -82
  49. package/screenshots/annotate.png +0 -0
  50. package/screenshots/demo.png +0 -0
  51. package/screenshots/parallel.png +0 -0
  52. package/screenshots/questions.png +0 -0
  53. package/server.ts +0 -287
  54. package/setup.ts +0 -233
  55. package/slots.ts +0 -65
  56. package/splates.test.ts +0 -338
  57. package/splates.ts +0 -567
  58. package/task.ts +0 -354
  59. package/tunnel.ts +0 -106
  60. package/wait-journal.test.ts +0 -96
  61. package/waiting.ts +0 -59
  62. package/worker-relay.test.ts +0 -233
  63. package/worker.ts +0 -300
package/splates.test.ts DELETED
@@ -1,338 +0,0 @@
1
- import { afterEach, beforeEach, describe, expect, it } from "bun:test";
2
- import { basename, join } from "node:path";
3
- import { SERVING } from "@stringsync/splates-server/server";
4
- import { Testing } from "@stringsync/splates-server/testing";
5
- import { splates } from "./splates";
6
-
7
- /**
8
- * The cli in this process, run with fakes: the same commands `e2e.test.ts`
9
- * spawns, minus the subprocess. What it proves is the wiring, that every
10
- * dependency an action uses arrives through `run`.
11
- */
12
- describe("splates cli", () => {
13
- let env: Testing;
14
- let deps: Parameters<typeof splates.run>[0];
15
-
16
- beforeEach(async () => {
17
- env = await Testing.open();
18
- env.ps.cd(env.root);
19
- deps = {
20
- log: env.log,
21
- fs: env.fs,
22
- ps: env.ps,
23
- assets: env.assets,
24
- secrets: env.secrets,
25
- fetch: Object.assign(
26
- () => Promise.reject(new Error("no network in a test")),
27
- { preconnect: () => {} },
28
- ),
29
- };
30
- });
31
-
32
- afterEach(() => env.disposeAsync());
33
-
34
- it("prints nothing successfully when there is no notes directory", async () => {
35
- await splates.run(deps, ["notes"]);
36
- expect(env.out()).toBe("");
37
- expect(env.proc.lastExit()).toBeUndefined();
38
- });
39
-
40
- it("prints only note descriptions and does not record consulting them", async () => {
41
- await env.fs.mkdir(join(env.root, "notes"));
42
- await env.fs.write(
43
- join(env.root, "notes/a.md"),
44
- "---\ndescription: Project conventions\n---\nBody",
45
- );
46
- await env.fs.write(
47
- join(env.root, "notes/b.md"),
48
- "---\ndescription: Client agreement\n---\nBody",
49
- );
50
- const before = await env.journal.tail(10);
51
- await splates.run(deps, ["notes"]);
52
- expect(env.log.entries.map((entry) => entry.message)).toEqual([
53
- "Project conventions",
54
- "Client agreement",
55
- ]);
56
- expect(await env.journal.tail(10)).toEqual(before);
57
- });
58
-
59
- it("reads the current worktree's notes and configuration from a subdirectory", async () => {
60
- await splates.run(deps, ["add", "alpha", "--goal", "land it"]);
61
- const { path } = await env.service.find("alpha");
62
- await env.fs.mkdir(join(path, "context"));
63
- await env.fs.mkdir(join(env.root, "notes"));
64
- await env.fs.write(
65
- join(path, "splates.config.ts"),
66
- 'export default { notesDir: "context" };\n',
67
- );
68
- await env.fs.write(
69
- join(path, "context/a.md"),
70
- "---\ndescription: Worktree convention\n---\n",
71
- );
72
- await env.fs.write(
73
- join(env.root, "notes/a.md"),
74
- "---\ndescription: Main convention\n---\n",
75
- );
76
- env.ps.cd(join(path, "context"));
77
- const count = env.log.entries.length;
78
- await splates.run(deps, ["notes"]);
79
- expect(env.log.entries.slice(count).map((entry) => entry.message)).toEqual([
80
- "Worktree convention",
81
- ]);
82
- });
83
-
84
- it("runs its commands against the dependencies it is given", async () => {
85
- await splates.run(deps, ["add", "alpha", "--goal", "land it"]);
86
- await splates.run(deps, ["list", "--json"]);
87
-
88
- const rows = JSON.parse(String(env.log.entries.at(-1)?.message));
89
- expect(rows).toMatchObject([{ task: "alpha", status: "working" }]);
90
- expect(
91
- await env.fs.exists(join(`${env.root}-splates.noindex`, "alpha")),
92
- ).toBe(true);
93
- });
94
-
95
- it("prints the roster from outside any repository", async () => {
96
- const away = join(env.splatesHome, "..");
97
- await env.fs.mkdir(away);
98
- env.ps.cd(away);
99
- await splates.run(deps, ["agents", "--json"]);
100
-
101
- const roster = JSON.parse(String(env.log.entries.at(-1)?.message));
102
- expect(roster.map((agent: { id: string }) => agent.id)).toEqual([
103
- "claude",
104
- "codex",
105
- ]);
106
- expect(await env.fs.exists(join(env.splatesHome, "agents.json"))).toBe(
107
- true,
108
- );
109
- });
110
-
111
- it("prints setup's progress and skips a step from outside any repository", async () => {
112
- const away = join(env.splatesHome, "..");
113
- await env.fs.mkdir(away);
114
- env.ps.cd(away);
115
- await splates.run(deps, ["setup", "dictation", "--skip"]);
116
- await splates.run(deps, ["setup", "--json"]);
117
-
118
- const progress = JSON.parse(String(env.log.entries.at(-1)?.message));
119
- expect(progress.next).toBe("opencode-install");
120
- expect(
121
- progress.areas.find((area: { id: string }) => area.id === "dictation")
122
- .skipped,
123
- ).toBe(1);
124
- });
125
-
126
- it("prints what undoing an area would forget, and undoes nothing", async () => {
127
- await env.secrets.device.set("OPENAI_API_KEY", "sk-test");
128
-
129
- await splates.run(deps, ["setup", "dictation", "--undo", "--json"]);
130
-
131
- const plan = JSON.parse(String(env.log.entries.at(-1)?.message));
132
- expect(plan).toMatchObject({
133
- area: "dictation",
134
- creds: [{ name: "OPENAI_API_KEY", keptFor: null }],
135
- refused: null,
136
- });
137
- expect(await env.secrets.device.get("OPENAI_API_KEY")).toBe("sk-test");
138
- });
139
-
140
- // scry-ignore simple-test-setup: the started task is what numbers the queued task after it, which this case checks.
141
- it("edits the queued tasks added beside a started one", async () => {
142
- await splates.run(deps, ["add", "alpha", "--goal", "land it"]);
143
- await env.fs.write(join(env.root, "a.png"), "a");
144
- await splates.run(deps, [
145
- "task",
146
- "add",
147
- "write docs",
148
- "the CLI first",
149
- "--slug",
150
- "cli-docs",
151
- "--file",
152
- "a.png",
153
- ]);
154
- // Task alpha took number 1, so the queued task is numbered after it.
155
- const [queued] = await env.tasks.all();
156
- const id = queued?.id ?? 0;
157
- expect(id).toBe(2);
158
- const [attached = ""] = queued?.files ?? [];
159
- await splates.run(deps, [
160
- "task",
161
- "update",
162
- String(id),
163
- "--subject",
164
- "write the docs",
165
- "--slug",
166
- "docs",
167
- "--position",
168
- "1",
169
- "--remove-file",
170
- basename(attached),
171
- ]);
172
- expect((await env.tasks.find(id)).state).toMatchObject({
173
- subject: "write the docs",
174
- slug: "docs",
175
- text: "the CLI first",
176
- position: 1,
177
- files: [],
178
- });
179
-
180
- await splates.run(deps, ["log", "--json"]);
181
- const entries = JSON.parse(String(env.log.entries.at(-1)?.message));
182
- expect(entries.map((entry: { action: string }) => entry.action)).toContain(
183
- "task update",
184
- );
185
- });
186
-
187
- it("reports a refusal as a reason, a message and an exit code", async () => {
188
- await splates.run(deps, ["claim", "nope"]);
189
-
190
- expect(env.out()).toContain('"reason":"not_found"');
191
- expect(env.proc.lastExit()).toBe(8);
192
- });
193
-
194
- it("refuses a task with no Goal, and writes the one it is given into its plan", async () => {
195
- await splates.run(deps, ["add", "alpha"]);
196
-
197
- expect(env.out()).toContain('"reason":"usage"');
198
- expect(env.out()).toContain("--goal");
199
- expect((await env.service.find("alpha")).gone).toBe(true);
200
-
201
- await splates.run(deps, [
202
- "add",
203
- "alpha",
204
- "--goal",
205
- "Stop the 413 retries.",
206
- ]);
207
- const { path } = await env.service.find("alpha");
208
- expect(await env.fs.read(join(path, "SPLATES.md"))).toContain(
209
- "## Goal\n\nStop the 413 retries.",
210
- );
211
- expect((await env.journal.tail(1))[0]).toMatchObject({
212
- action: "add",
213
- goal: "Stop the 413 retries.",
214
- });
215
- });
216
-
217
- it("logs the task it queues, with where it went", async () => {
218
- await splates.run(deps, ["task", "add", "first", "--slug", "first"]);
219
- await splates.run(deps, [
220
- "task",
221
- "add",
222
- "Upload retries forever on a 413",
223
- "--slug",
224
- "upload-413",
225
- "--position",
226
- "1",
227
- "--lane",
228
- "new",
229
- ]);
230
-
231
- expect((await env.journal.tail(1))[0]).toMatchObject({
232
- action: "task add",
233
- reason: null,
234
- number: 2,
235
- subject: "Upload retries forever on a 413",
236
- lane: 1,
237
- position: 1,
238
- });
239
- });
240
-
241
- it("lists the thinking levels an agent offers, starts a task on one, and refuses any other", async () => {
242
- await env.fs.write(
243
- join(env.splatesHome, "offered.json"),
244
- JSON.stringify({
245
- format: 1,
246
- agents: {
247
- claude: [
248
- {
249
- id: "effort",
250
- name: "Effort",
251
- type: "select",
252
- category: "thought_level",
253
- current: "default",
254
- options: ["default", "low", "high"].map((value) => ({
255
- value,
256
- name: value,
257
- description: null,
258
- })),
259
- },
260
- ],
261
- },
262
- }),
263
- );
264
- await splates.run(deps, ["agents"]);
265
- expect(env.out()).toContain("THINKING default, low, high");
266
-
267
- await splates.run(deps, [
268
- "add",
269
- "alpha",
270
- "--goal",
271
- "Style it.",
272
- "--agent",
273
- "claude",
274
- "--effort",
275
- "max",
276
- ]);
277
- expect(env.proc.lastExit()).toBe(1);
278
- expect(env.out()).toContain("use one of default, low, high");
279
-
280
- await splates.run(deps, [
281
- "add",
282
- "alpha",
283
- "--goal",
284
- "Style it.",
285
- "--agent",
286
- "claude",
287
- "--effort",
288
- "High",
289
- ]);
290
- expect((await env.service.find("alpha")).state?.dispatch).toMatchObject({
291
- agent: "claude",
292
- effort: "high",
293
- });
294
-
295
- await splates.run(deps, [
296
- "task",
297
- "add",
298
- "Restyle the header",
299
- "--slug",
300
- "header-style",
301
- "--agent",
302
- "claude",
303
- "--effort",
304
- "low",
305
- ]);
306
- expect((await env.tasks.all()).at(-1)?.state.assignee).toEqual({
307
- agent: "claude",
308
- effort: "low",
309
- });
310
- });
311
-
312
- it("refuses a port that cannot exist rather than trying to listen", async () => {
313
- // As the supervisor runs it.
314
- env.proc.env[SERVING] = "1";
315
- await splates.run(deps, ["server", "--port", "99999"]);
316
-
317
- expect(env.out()).not.toContain(" reply ");
318
- expect(env.proc.lastExit()).toBe(1);
319
- });
320
-
321
- it("says no tunnel is saved, and requests the token a setup needs", async () => {
322
- await splates.run(deps, ["tunnel", "status"]);
323
- expect(env.out()).toContain("no tunnel saved");
324
-
325
- await splates.run(deps, [
326
- "tunnel",
327
- "setup",
328
- "splates.example.com",
329
- "--email",
330
- "me@example.com",
331
- ]);
332
- expect(env.out()).toContain("requested on the Creds page");
333
- expect(env.proc.lastExit()).toBe(25);
334
- expect(await env.creds.requests()).toMatchObject([
335
- { name: "SPLATES_CLOUDFLARE_API_TOKEN", scope: "device", status: "open" },
336
- ]);
337
- });
338
- });