@stringsync/splates 0.0.53 → 0.0.54
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/artifact.d.ts +3 -0
- package/budget.d.ts +3 -0
- package/creds.d.ts +3 -0
- package/flags.d.ts +37 -0
- package/hook.d.ts +3 -0
- package/index.d.ts +2 -0
- package/index.js +1802 -0
- package/infra.d.ts +3 -0
- package/lane.d.ts +3 -0
- package/notes.d.ts +4 -0
- package/package.json +12 -14
- package/projects.d.ts +3 -0
- package/queue.d.ts +3 -0
- package/server.d.ts +7 -0
- package/setup.d.ts +22 -0
- package/slots.d.ts +3 -0
- package/splates.d.ts +10 -0
- package/task.d.ts +3 -0
- package/tunnel.d.ts +3 -0
- package/waiting.d.ts +3 -0
- package/worker.d.ts +3 -0
- package/artifact.ts +0 -120
- package/budget.ts +0 -117
- package/checkout.ts +0 -8
- package/creds.test.ts +0 -336
- package/creds.ts +0 -144
- package/dev/dev.ts +0 -86
- package/dev/eval.ts +0 -21
- package/dev/fix.ts +0 -63
- package/dev/index.ts +0 -1
- package/dev/prove.ts +0 -38
- package/dev/root.ts +0 -7
- package/dev/ship.ts +0 -46
- package/dev/test.ts +0 -154
- package/e2e.test.ts +0 -472
- package/flags.ts +0 -157
- package/hook.ts +0 -328
- package/index.ts +0 -18
- package/infra.ts +0 -107
- package/lane.test.ts +0 -29
- package/lane.ts +0 -172
- package/notes.ts +0 -19
- package/projects.test.ts +0 -191
- package/projects.ts +0 -37
- package/queue.ts +0 -82
- package/screenshots/annotate.png +0 -0
- package/screenshots/demo.png +0 -0
- package/screenshots/parallel.png +0 -0
- package/screenshots/questions.png +0 -0
- package/server.ts +0 -287
- package/setup.ts +0 -233
- package/slots.ts +0 -65
- package/splates.test.ts +0 -338
- package/splates.ts +0 -567
- package/task.ts +0 -354
- package/tunnel.ts +0 -106
- package/wait-journal.test.ts +0 -96
- package/waiting.ts +0 -59
- package/worker-relay.test.ts +0 -233
- package/worker.ts +0 -300
package/lane.ts
DELETED
|
@@ -1,172 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
APPROVAL,
|
|
3
|
-
BACKLOG_LANE,
|
|
4
|
-
laneAdd,
|
|
5
|
-
laneList,
|
|
6
|
-
laneRemove,
|
|
7
|
-
laneShow,
|
|
8
|
-
laneUpdate,
|
|
9
|
-
laneUpdated,
|
|
10
|
-
recordLaneRemove,
|
|
11
|
-
} from "@stringsync/splates-server/board";
|
|
12
|
-
import { refuseGroomer } from "@stringsync/splates-server/conversations";
|
|
13
|
-
import { UNTRIAGED } from "@stringsync/splates-server/plans";
|
|
14
|
-
import { refuseAgentQueue } from "@stringsync/splates-server/queue";
|
|
15
|
-
import { repository } from "@stringsync/splates-server/records";
|
|
16
|
-
import type { SplatesDeps } from "@stringsync/splates-server/server";
|
|
17
|
-
import { cli } from "webappwiz/cmd";
|
|
18
|
-
import { z } from "zod";
|
|
19
|
-
import { position } from "./flags";
|
|
20
|
-
|
|
21
|
-
/** Backlog is lane zero, also addressable by its permanent name. */
|
|
22
|
-
const laneNumber = z.union([
|
|
23
|
-
z.literal("backlog").transform(() => BACKLOG_LANE),
|
|
24
|
-
z.coerce.number().int().nonnegative(),
|
|
25
|
-
]);
|
|
26
|
-
|
|
27
|
-
/** `splates lane`, which the root cli mounts after `splates task`. */
|
|
28
|
-
export const splatesLane = cli<SplatesDeps>("lane").description(
|
|
29
|
-
"lanes: named groups of tasks, for you to see related work together on the board; queue one whole with `splates lane queue`. Backlog (lane 0) is permanent and holds unmatched deferred work. Untriaged is groomed into lanes and cannot be queued whole",
|
|
30
|
-
);
|
|
31
|
-
|
|
32
|
-
splatesLane
|
|
33
|
-
.command("list")
|
|
34
|
-
.use(repository({ needs: "read" }))
|
|
35
|
-
.description(
|
|
36
|
-
"every lane: its name, its queued tasks in order, the started tasks on it, its next task, and what blocks that in other lanes",
|
|
37
|
-
)
|
|
38
|
-
.option("json", z.boolean(), { default: false, description: "emit JSON" })
|
|
39
|
-
.action((opts, ctx) => laneList(ctx, { json: opts.json }));
|
|
40
|
-
|
|
41
|
-
splatesLane
|
|
42
|
-
.command("show")
|
|
43
|
-
.use(repository({ needs: "read" }))
|
|
44
|
-
.description(
|
|
45
|
-
"one lane step by step, and what its agent does next: start the next task, or wait for the one blocking it in another lane to land first; `untriaged` lists the tasks in no lane, to place in lanes",
|
|
46
|
-
)
|
|
47
|
-
.arg(
|
|
48
|
-
"lane",
|
|
49
|
-
z.union([z.literal(UNTRIAGED).transform(() => null), laneNumber], {
|
|
50
|
-
error: "pass a lane's number, backlog, or untriaged",
|
|
51
|
-
}),
|
|
52
|
-
{ description: "lane number, `backlog`, or `untriaged`" },
|
|
53
|
-
)
|
|
54
|
-
.option("json", z.boolean(), { default: false, description: "emit JSON" })
|
|
55
|
-
.action((opts, ctx) => laneShow(ctx, opts.lane, { json: opts.json }));
|
|
56
|
-
|
|
57
|
-
splatesLane
|
|
58
|
-
.command("add")
|
|
59
|
-
.use(repository({ needs: "tasks" }))
|
|
60
|
-
.description("start an empty lane, after the others")
|
|
61
|
-
.arg("name", z.string(), {
|
|
62
|
-
description: "what its tasks are for, like `Licensing`",
|
|
63
|
-
})
|
|
64
|
-
.action(async (opts, ctx) => {
|
|
65
|
-
await ctx.journal.record(
|
|
66
|
-
"lane add",
|
|
67
|
-
null,
|
|
68
|
-
() => laneAdd(ctx, opts.name),
|
|
69
|
-
(lane) => ({ lane: lane.id, name: lane.name }),
|
|
70
|
-
);
|
|
71
|
-
});
|
|
72
|
-
|
|
73
|
-
splatesLane
|
|
74
|
-
.command("update")
|
|
75
|
-
.use(repository({ needs: "tasks" }))
|
|
76
|
-
.description("rename a lane, or move it among the others")
|
|
77
|
-
.arg("lane", laneNumber, {
|
|
78
|
-
description: "lane number",
|
|
79
|
-
})
|
|
80
|
-
.option("name", z.string().optional(), {
|
|
81
|
-
description: "what it is called from now on",
|
|
82
|
-
})
|
|
83
|
-
.option("position", position, {
|
|
84
|
-
description:
|
|
85
|
-
"where to move it among the lanes, 1 the first column on the board; the others close up around it",
|
|
86
|
-
})
|
|
87
|
-
.action(async (opts, ctx) => {
|
|
88
|
-
const change = { name: opts.name, position: opts.position };
|
|
89
|
-
await ctx.journal.record(
|
|
90
|
-
"lane update",
|
|
91
|
-
null,
|
|
92
|
-
() => laneUpdate(ctx, opts.lane, change),
|
|
93
|
-
(record) => laneUpdated(opts.lane, record, change),
|
|
94
|
-
);
|
|
95
|
-
});
|
|
96
|
-
|
|
97
|
-
splatesLane
|
|
98
|
-
.command("queue")
|
|
99
|
-
.use(repository({ needs: "tasks" }))
|
|
100
|
-
.description(
|
|
101
|
-
"queue a lane whole: each of its tasks is queued as soon as nothing blocks it, now and as tasks land, until the lane is empty; a task you take out with `splates queue remove` stays out until you queue it again. Untriaged cannot be queued whole",
|
|
102
|
-
)
|
|
103
|
-
.arg("lane", laneNumber, {
|
|
104
|
-
description: "lane number",
|
|
105
|
-
})
|
|
106
|
-
.action(async (opts, ctx) => {
|
|
107
|
-
refuseAgentQueue(ctx.service, "lane queue");
|
|
108
|
-
await refuseGroomer(ctx.service, "lane queue");
|
|
109
|
-
const change = { queued: true };
|
|
110
|
-
await ctx.journal.record(
|
|
111
|
-
"lane update",
|
|
112
|
-
null,
|
|
113
|
-
() => laneUpdate(ctx, opts.lane, change),
|
|
114
|
-
(record) => laneUpdated(opts.lane, record, change),
|
|
115
|
-
);
|
|
116
|
-
});
|
|
117
|
-
|
|
118
|
-
splatesLane
|
|
119
|
-
.command("approve")
|
|
120
|
-
.use(repository({ needs: "tasks" }))
|
|
121
|
-
.description(
|
|
122
|
-
"let a queued lane queue more tasks on its own: it stops when its budget is spent, which starts at its tasks then plus 5, and this adds 10 to what is left; refused from an agent",
|
|
123
|
-
)
|
|
124
|
-
.arg("lane", laneNumber, {
|
|
125
|
-
description: "lane number",
|
|
126
|
-
})
|
|
127
|
-
.action(async (opts, ctx) => {
|
|
128
|
-
refuseAgentQueue(ctx.service, "lane approve");
|
|
129
|
-
const change = { approve: APPROVAL };
|
|
130
|
-
await ctx.journal.record(
|
|
131
|
-
"lane update",
|
|
132
|
-
null,
|
|
133
|
-
() => laneUpdate(ctx, opts.lane, change),
|
|
134
|
-
(record) => laneUpdated(opts.lane, record, change),
|
|
135
|
-
);
|
|
136
|
-
});
|
|
137
|
-
|
|
138
|
-
splatesLane
|
|
139
|
-
.command("unqueue")
|
|
140
|
-
.use(repository({ needs: "tasks" }))
|
|
141
|
-
.description(
|
|
142
|
-
"stop queueing a lane whole, taking out of the queue each of its tasks that has yet to start; those under way go on",
|
|
143
|
-
)
|
|
144
|
-
.arg("lane", laneNumber, {
|
|
145
|
-
description: "lane number",
|
|
146
|
-
})
|
|
147
|
-
.action(async (opts, ctx) => {
|
|
148
|
-
refuseAgentQueue(ctx.service, "lane unqueue");
|
|
149
|
-
const change = { queued: false };
|
|
150
|
-
await ctx.journal.record(
|
|
151
|
-
"lane update",
|
|
152
|
-
null,
|
|
153
|
-
() => laneUpdate(ctx, opts.lane, change),
|
|
154
|
-
(record) => laneUpdated(opts.lane, record, change),
|
|
155
|
-
);
|
|
156
|
-
});
|
|
157
|
-
|
|
158
|
-
splatesLane
|
|
159
|
-
.command("remove")
|
|
160
|
-
.use(repository({ needs: "tasks" }))
|
|
161
|
-
.description(
|
|
162
|
-
"remove a lane and its tasks, kept to restore; a lane whose last task merges goes on its own; refused from an agent, which asks with a permission card",
|
|
163
|
-
)
|
|
164
|
-
.arg("lane", laneNumber, {
|
|
165
|
-
description: "lane number",
|
|
166
|
-
})
|
|
167
|
-
.action((opts, ctx) => {
|
|
168
|
-
refuseAgentQueue(ctx.service, "lane remove");
|
|
169
|
-
return recordLaneRemove(ctx.journal, ctx.tasks, opts.lane, () =>
|
|
170
|
-
laneRemove(ctx, opts.lane),
|
|
171
|
-
);
|
|
172
|
-
});
|
package/notes.ts
DELETED
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
import { loadConfig } from "@stringsync/splates-server/config";
|
|
2
|
-
import { Notes } from "@stringsync/splates-server/notes";
|
|
3
|
-
import type { Repository } from "@stringsync/splates-server/records";
|
|
4
|
-
import type { SplatesDeps } from "@stringsync/splates-server/server";
|
|
5
|
-
|
|
6
|
-
/** Prints the descriptions in this checkout, or the project explicitly named. */
|
|
7
|
-
export async function notes(ctx: SplatesDeps & Repository): Promise<void> {
|
|
8
|
-
const root =
|
|
9
|
-
ctx.project === undefined
|
|
10
|
-
? (
|
|
11
|
-
await ctx.git.run(ctx.ps.cwd(), "rev-parse", "--show-toplevel")
|
|
12
|
-
).stdout.trim()
|
|
13
|
-
: ctx.git.root;
|
|
14
|
-
const config = await loadConfig(root, { fs: ctx.fs, git: ctx.git });
|
|
15
|
-
const found = await new Notes(ctx.fs).list(root, config);
|
|
16
|
-
for (const note of found) {
|
|
17
|
-
ctx.log.info(note.description);
|
|
18
|
-
}
|
|
19
|
-
}
|
package/projects.test.ts
DELETED
|
@@ -1,191 +0,0 @@
|
|
|
1
|
-
import { afterEach, beforeEach, describe, expect, it } from "bun:test";
|
|
2
|
-
import { basename, join } from "node:path";
|
|
3
|
-
import { Testing } from "@stringsync/splates-server/testing";
|
|
4
|
-
import { projectArgs, splates } from "./splates";
|
|
5
|
-
|
|
6
|
-
/**
|
|
7
|
-
* Two projects on one machine, the first's registry naming both, its agent
|
|
8
|
-
* running `splates` on the second with `--project`.
|
|
9
|
-
*/
|
|
10
|
-
describe("splates across projects", () => {
|
|
11
|
-
let here: Testing;
|
|
12
|
-
let there: Testing;
|
|
13
|
-
let deps: Parameters<typeof splates.run>[0];
|
|
14
|
-
let hereSlug: string;
|
|
15
|
-
let thereSlug: string;
|
|
16
|
-
|
|
17
|
-
beforeEach(async () => {
|
|
18
|
-
here = await Testing.open();
|
|
19
|
-
there = await Testing.open();
|
|
20
|
-
await here.projects.register(there.root);
|
|
21
|
-
const listed = await here.projects.list();
|
|
22
|
-
const slug = (root: string) =>
|
|
23
|
-
listed.find((each) => each.root === root)?.slug ?? "";
|
|
24
|
-
hereSlug = slug(here.root);
|
|
25
|
-
thereSlug = slug(there.root);
|
|
26
|
-
here.ps.cd(here.root);
|
|
27
|
-
deps = {
|
|
28
|
-
log: here.log,
|
|
29
|
-
fs: here.fs,
|
|
30
|
-
ps: here.ps,
|
|
31
|
-
assets: here.assets,
|
|
32
|
-
secrets: here.secrets,
|
|
33
|
-
};
|
|
34
|
-
});
|
|
35
|
-
|
|
36
|
-
afterEach(async () => {
|
|
37
|
-
await here.disposeAsync();
|
|
38
|
-
await there.disposeAsync();
|
|
39
|
-
});
|
|
40
|
-
|
|
41
|
-
/** Runs `splates --project <there> ...args` from here. */
|
|
42
|
-
const onThere = (...args: string[]) =>
|
|
43
|
-
splates.run({ ...deps, project: thereSlug }, args);
|
|
44
|
-
|
|
45
|
-
it("splits a leading --project off the arguments", () => {
|
|
46
|
-
expect(projectArgs(["--project", "shop", "list"])).toEqual({
|
|
47
|
-
project: "shop",
|
|
48
|
-
argv: ["list"],
|
|
49
|
-
});
|
|
50
|
-
expect(projectArgs(["--project=shop", "list"])).toEqual({
|
|
51
|
-
project: "shop",
|
|
52
|
-
argv: ["list"],
|
|
53
|
-
});
|
|
54
|
-
expect(projectArgs(["list", "--project", "shop"])).toEqual({
|
|
55
|
-
argv: ["list", "--project", "shop"],
|
|
56
|
-
});
|
|
57
|
-
});
|
|
58
|
-
|
|
59
|
-
it("queues a task in its untriaged lane, saying where it came from", async () => {
|
|
60
|
-
await splates.run(deps, ["add", "alpha", "--goal", "Land it."]);
|
|
61
|
-
here.ps.cd((await here.service.find("alpha")).path);
|
|
62
|
-
|
|
63
|
-
await onThere(
|
|
64
|
-
"task",
|
|
65
|
-
"add",
|
|
66
|
-
"Export the parser",
|
|
67
|
-
"--slug",
|
|
68
|
-
"parser-export",
|
|
69
|
-
);
|
|
70
|
-
|
|
71
|
-
const thereSlug = (await here.projects.list()).find(
|
|
72
|
-
(each) => each.root === there.root,
|
|
73
|
-
)?.slug;
|
|
74
|
-
expect(String(here.log.entries.at(-1)?.message)).toContain(
|
|
75
|
-
`${thereSlug} #1 at`,
|
|
76
|
-
);
|
|
77
|
-
|
|
78
|
-
const [queued] = await there.tasks.all();
|
|
79
|
-
expect(queued?.state).toMatchObject({
|
|
80
|
-
subject: "Export the parser",
|
|
81
|
-
from: null,
|
|
82
|
-
lane: null,
|
|
83
|
-
origin: { project: here.root, task: "alpha" },
|
|
84
|
-
});
|
|
85
|
-
expect(await here.tasks.all()).toEqual([]);
|
|
86
|
-
|
|
87
|
-
await onThere("task", "show", String(queued?.id));
|
|
88
|
-
expect(String(here.log.entries.at(-1)?.message)).toContain(
|
|
89
|
-
`${thereSlug} #${queued?.id}`,
|
|
90
|
-
);
|
|
91
|
-
expect(String(here.log.entries.at(-1)?.message)).toContain(
|
|
92
|
-
`from: ${basename(here.root)}/alpha`,
|
|
93
|
-
);
|
|
94
|
-
});
|
|
95
|
-
|
|
96
|
-
it("refuses a lane for a queued task from another project", async () => {
|
|
97
|
-
await onThere(
|
|
98
|
-
"task",
|
|
99
|
-
"add",
|
|
100
|
-
"Export the parser",
|
|
101
|
-
"--slug",
|
|
102
|
-
"parser-export",
|
|
103
|
-
"--lane",
|
|
104
|
-
"new",
|
|
105
|
-
);
|
|
106
|
-
|
|
107
|
-
expect(here.out()).toContain('"reason":"not_granted"');
|
|
108
|
-
expect(await there.tasks.all()).toEqual([]);
|
|
109
|
-
});
|
|
110
|
-
|
|
111
|
-
it("refuses what the other project has not granted, until it does", async () => {
|
|
112
|
-
await onThere(
|
|
113
|
-
"task",
|
|
114
|
-
"add",
|
|
115
|
-
"Export the parser",
|
|
116
|
-
"--slug",
|
|
117
|
-
"parser-export",
|
|
118
|
-
);
|
|
119
|
-
await onThere("task", "remove", "1");
|
|
120
|
-
expect(here.out()).toContain('"reason":"not_granted"');
|
|
121
|
-
expect(here.out()).toContain(`splates projects grant ${hereSlug} tasks`);
|
|
122
|
-
expect(await there.tasks.all()).toHaveLength(1);
|
|
123
|
-
|
|
124
|
-
// The person, in the other project's main tree.
|
|
125
|
-
here.ps.cd(there.root);
|
|
126
|
-
await splates.run(deps, ["projects", "grant", hereSlug, "tasks"]);
|
|
127
|
-
expect(await here.projects.reach(here.root, there.root)).toBe("tasks");
|
|
128
|
-
|
|
129
|
-
here.ps.cd(here.root);
|
|
130
|
-
await onThere("task", "remove", "1");
|
|
131
|
-
expect(await there.tasks.all()).toEqual([]);
|
|
132
|
-
});
|
|
133
|
-
|
|
134
|
-
it("starts no task in another project, granted or not, so it is queued there", async () => {
|
|
135
|
-
await here.projects.grant(there.root, here.root, "tasks");
|
|
136
|
-
|
|
137
|
-
await onThere("add", "beta", "--goal", "Do it.", "--agent", "claude");
|
|
138
|
-
|
|
139
|
-
expect(here.out()).toContain('"reason":"not_granted"');
|
|
140
|
-
expect(here.out()).toContain("task add");
|
|
141
|
-
expect((await there.service.find("beta")).gone).toBe(true);
|
|
142
|
-
});
|
|
143
|
-
|
|
144
|
-
it("refuses a command only a project runs on itself", async () => {
|
|
145
|
-
await here.projects.grant(there.root, here.root, "tasks");
|
|
146
|
-
|
|
147
|
-
await onThere("projects", "grant", hereSlug, "tasks");
|
|
148
|
-
|
|
149
|
-
expect(here.out()).toContain('"reason":"not_granted"');
|
|
150
|
-
});
|
|
151
|
-
|
|
152
|
-
it("checks an agent of this project's page that changes into the other", async () => {
|
|
153
|
-
await here.projects.grant(there.root, here.root, "read");
|
|
154
|
-
await here.fs.mkdir(join(here.root, ".git/splates/conversations"));
|
|
155
|
-
await here.fs.write(
|
|
156
|
-
join(here.root, ".git/splates/conversations/c1.jsonl"),
|
|
157
|
-
"",
|
|
158
|
-
);
|
|
159
|
-
here.proc.env.SPLATES_CONVERSATION = "c1";
|
|
160
|
-
here.ps.cd(there.root);
|
|
161
|
-
|
|
162
|
-
await splates.run(deps, [
|
|
163
|
-
"task",
|
|
164
|
-
"add",
|
|
165
|
-
"Export the parser",
|
|
166
|
-
"--slug",
|
|
167
|
-
"parser-export",
|
|
168
|
-
]);
|
|
169
|
-
expect(here.out()).toContain('"reason":"not_granted"');
|
|
170
|
-
expect(await there.tasks.all()).toEqual([]);
|
|
171
|
-
|
|
172
|
-
await splates.run(deps, ["task", "list", "--json"]);
|
|
173
|
-
expect(JSON.parse(String(here.log.entries.at(-1)?.message))).toEqual([]);
|
|
174
|
-
});
|
|
175
|
-
|
|
176
|
-
it("lists what each project may do in the other", async () => {
|
|
177
|
-
await here.projects.grant(there.root, here.root, "tasks");
|
|
178
|
-
|
|
179
|
-
await splates.run(deps, ["projects", "list", "--json"]);
|
|
180
|
-
|
|
181
|
-
expect(JSON.parse(String(here.log.entries.at(-1)?.message))).toEqual([
|
|
182
|
-
{
|
|
183
|
-
slug: thereSlug,
|
|
184
|
-
root: there.root,
|
|
185
|
-
gone: false,
|
|
186
|
-
here: "queue",
|
|
187
|
-
there: "tasks",
|
|
188
|
-
},
|
|
189
|
-
]);
|
|
190
|
-
});
|
|
191
|
-
});
|
package/projects.ts
DELETED
|
@@ -1,37 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
grantReach,
|
|
3
|
-
listReaches,
|
|
4
|
-
REACHES,
|
|
5
|
-
} from "@stringsync/splates-server/projects";
|
|
6
|
-
import { repository } from "@stringsync/splates-server/records";
|
|
7
|
-
import type { SplatesDeps } from "@stringsync/splates-server/server";
|
|
8
|
-
import { cli } from "webappwiz/cmd";
|
|
9
|
-
import { z } from "zod";
|
|
10
|
-
|
|
11
|
-
/** `splates projects`, which the root cli mounts after `splates lane`. */
|
|
12
|
-
export const splatesProjects = cli<SplatesDeps>("projects")
|
|
13
|
-
.description(
|
|
14
|
-
"the other splates projects on this machine, and what agents of each may do in the others through splates: `read` their tasks and lanes; add tasks to their untriaged lane with `queue`, as every project may until granted otherwise; or run their queue, lanes and hooks with `tasks`. Any repo command runs on another project as `splates --project <slug> <command>`, refused where it needs more than that project granted",
|
|
15
|
-
)
|
|
16
|
-
.fallback("list");
|
|
17
|
-
|
|
18
|
-
splatesProjects
|
|
19
|
-
.command("list")
|
|
20
|
-
.use(repository({ needs: "read" }))
|
|
21
|
-
.description(
|
|
22
|
-
"print each other project: its slug, its root, what it may do here, and what this one may do there",
|
|
23
|
-
)
|
|
24
|
-
.option("json", z.boolean(), { default: false, description: "emit JSON" })
|
|
25
|
-
.action((opts, ctx) => listReaches(ctx, { json: opts.json }));
|
|
26
|
-
|
|
27
|
-
splatesProjects
|
|
28
|
-
.command("grant")
|
|
29
|
-
.use(repository({ needs: "own" }))
|
|
30
|
-
.description(
|
|
31
|
-
"let agents of another project do as much as `read`, `queue` or `tasks` here, each including those before it; the user's call, so an agent runs it only when the user asks it to",
|
|
32
|
-
)
|
|
33
|
-
.arg("project", z.string(), { description: "the other project's slug" })
|
|
34
|
-
.arg("reach", z.enum(REACHES), {
|
|
35
|
-
description: "read, queue or tasks",
|
|
36
|
-
})
|
|
37
|
-
.action((opts, ctx) => grantReach(ctx, opts.project, opts.reach));
|
package/queue.ts
DELETED
|
@@ -1,82 +0,0 @@
|
|
|
1
|
-
import { tasksNamed } from "@stringsync/splates-server/board";
|
|
2
|
-
import { refuseGroomer } from "@stringsync/splates-server/conversations";
|
|
3
|
-
import {
|
|
4
|
-
queueAdd,
|
|
5
|
-
queueList,
|
|
6
|
-
queueMove,
|
|
7
|
-
queueRemove,
|
|
8
|
-
refuseAgentQueue,
|
|
9
|
-
} from "@stringsync/splates-server/queue";
|
|
10
|
-
import { repository } from "@stringsync/splates-server/records";
|
|
11
|
-
import type { SplatesDeps } from "@stringsync/splates-server/server";
|
|
12
|
-
import { cli } from "webappwiz/cmd";
|
|
13
|
-
import { z } from "zod";
|
|
14
|
-
import { here } from "./flags";
|
|
15
|
-
|
|
16
|
-
/** `splates queue`, which the root cli mounts beside `splates task`. */
|
|
17
|
-
export const splatesQueue = cli<SplatesDeps>("queue").description(
|
|
18
|
-
"the queue: the tasks a worker of `splates server` starts as soon as it has a slot free, each after every task it is blocked by, otherwise in the order you set. Only you queue a task, from the backlog or groomed, and an agent asks you to with a queue card; one that names no model runs on the roster's first agent",
|
|
19
|
-
);
|
|
20
|
-
|
|
21
|
-
splatesQueue
|
|
22
|
-
.command("list")
|
|
23
|
-
.use(repository({ needs: "read" }))
|
|
24
|
-
.description(
|
|
25
|
-
"the queue in the order workers start it, with each task's model and what it waits on: the open tasks it is blocked by, or those removed without merging",
|
|
26
|
-
)
|
|
27
|
-
.option("json", z.boolean(), { default: false, description: "emit JSON" })
|
|
28
|
-
.action((opts, ctx) => queueList(ctx, { json: opts.json }));
|
|
29
|
-
|
|
30
|
-
splatesQueue
|
|
31
|
-
.command("add")
|
|
32
|
-
.use(repository({ needs: "tasks" }))
|
|
33
|
-
.description(
|
|
34
|
-
"queue tasks for a worker to start once nothing they are blocked by is open; refused for one already under way",
|
|
35
|
-
)
|
|
36
|
-
.rest("ids", z.coerce.number().int().positive(), {
|
|
37
|
-
description: "task numbers",
|
|
38
|
-
})
|
|
39
|
-
.action(async (opts, ctx) => {
|
|
40
|
-
refuseAgentQueue(ctx.service, "queue add");
|
|
41
|
-
await refuseGroomer(ctx.service, "queue add");
|
|
42
|
-
await ctx.journal.record(
|
|
43
|
-
"queue add",
|
|
44
|
-
await here(ctx),
|
|
45
|
-
() => queueAdd(ctx, opts.ids),
|
|
46
|
-
(queued) => ({ tasks: tasksNamed(queued) }),
|
|
47
|
-
);
|
|
48
|
-
});
|
|
49
|
-
|
|
50
|
-
splatesQueue
|
|
51
|
-
.command("remove")
|
|
52
|
-
.use(repository({ needs: "tasks" }))
|
|
53
|
-
.description(
|
|
54
|
-
"take tasks out of the queue, back to ready when they name a model, else the backlog; the tasks stay",
|
|
55
|
-
)
|
|
56
|
-
.rest("ids", z.coerce.number().int().positive(), {
|
|
57
|
-
description: "task numbers",
|
|
58
|
-
})
|
|
59
|
-
.action(async (opts, ctx) => {
|
|
60
|
-
refuseAgentQueue(ctx.service, "queue remove");
|
|
61
|
-
await ctx.journal.record(
|
|
62
|
-
"queue remove",
|
|
63
|
-
await here(ctx),
|
|
64
|
-
() => queueRemove(ctx, opts.ids),
|
|
65
|
-
(removed) => ({ tasks: tasksNamed(removed) }),
|
|
66
|
-
);
|
|
67
|
-
});
|
|
68
|
-
|
|
69
|
-
splatesQueue
|
|
70
|
-
.command("move")
|
|
71
|
-
.use(repository({ needs: "tasks" }))
|
|
72
|
-
.description(
|
|
73
|
-
"move a queued task to another place in the queue, from 1 for the next to start; what it is blocked by still goes first. Then lists the queue",
|
|
74
|
-
)
|
|
75
|
-
.arg("id", z.coerce.number().int().positive(), { description: "task number" })
|
|
76
|
-
.arg("position", z.coerce.number().int().positive(), {
|
|
77
|
-
description: "where in the queue to put it, from 1",
|
|
78
|
-
})
|
|
79
|
-
.action(async (opts, ctx) => {
|
|
80
|
-
refuseAgentQueue(ctx.service, "queue move");
|
|
81
|
-
return queueMove(ctx, opts.id, opts.position);
|
|
82
|
-
});
|
package/screenshots/annotate.png
DELETED
|
Binary file
|
package/screenshots/demo.png
DELETED
|
Binary file
|
package/screenshots/parallel.png
DELETED
|
Binary file
|
|
Binary file
|