@stringsync/splates 0.0.0-stage → 0.0.45
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/LICENSE +21 -0
- package/README.md +308 -2
- package/acp-extensions.d.ts +82 -0
- package/add.d.ts +53 -0
- package/adherence.d.ts +49 -0
- package/age.d.ts +2 -0
- package/agent-connection.d.ts +171 -0
- package/agent-errors.d.ts +2 -0
- package/agent-process.d.ts +65 -0
- package/agent-stream.d.ts +91 -0
- package/agents.d.ts +15 -0
- package/artifact-room.d.ts +47 -0
- package/artifact-viewers.d.ts +6 -0
- package/artifact.d.ts +30 -0
- package/artifacts.d.ts +161 -0
- package/asked.d.ts +146 -0
- package/asked.js +7 -0
- package/assumed.d.ts +34 -0
- package/attach.d.ts +30 -0
- package/attachments.d.ts +43 -0
- package/baselines.d.ts +55 -0
- package/claim.d.ts +17 -0
- package/cloudflare-api.d.ts +25 -0
- package/cloudflare-error.d.ts +5 -0
- package/cloudflared-tunnel-provider.d.ts +27 -0
- package/codex-limits.d.ts +19 -0
- package/compaction.d.ts +17 -0
- package/config-source.d.ts +13 -0
- package/config.d.ts +98 -0
- package/config.js +7 -0
- package/conversation-archive.d.ts +6 -0
- package/conversation-background.d.ts +21 -0
- package/conversation-choice.d.ts +4 -0
- package/conversation-files.d.ts +51 -0
- package/conversation-given.d.ts +8 -0
- package/conversation-host.d.ts +102 -0
- package/conversation-listing.d.ts +15 -0
- package/conversation-log.d.ts +301 -0
- package/conversation-messages.d.ts +18 -0
- package/conversation-name.d.ts +28 -0
- package/conversation-options.d.ts +73 -0
- package/conversation-reference.d.ts +2 -0
- package/conversation-state.d.ts +472 -0
- package/conversation-turns.d.ts +115 -0
- package/conversation.d.ts +209 -0
- package/conversations.d.ts +140 -0
- package/coordinator-state.d.ts +28 -0
- package/creds.d.ts +123 -0
- package/darwin-temperature.d.ts +7 -0
- package/decided.d.ts +18 -0
- package/demo.d.ts +29 -0
- package/dev/api.d.ts +209 -0
- package/dev/assets.d.ts +24 -0
- package/dev/conversation-address.d.ts +47 -0
- package/dev/conversation-feed.d.ts +166 -0
- package/dev/live-stream.d.ts +29 -0
- package/dev/worker.d.ts +33 -0
- package/dev-access.d.ts +61 -0
- package/dev-artifacts.d.ts +22 -0
- package/dev-budgets.d.ts +18 -0
- package/dev-conversation-events.d.ts +39 -0
- package/dev-conversation-routes.d.ts +90 -0
- package/dev-creds.d.ts +17 -0
- package/dev-dictation-connection.d.ts +18 -0
- package/dev-dictation.d.ts +17 -0
- package/dev-http.d.ts +76 -0
- package/dev-open.d.ts +15 -0
- package/dev-options.d.ts +133 -0
- package/dev-outcomes.d.ts +21 -0
- package/dev-pages.d.ts +16 -0
- package/dev-picker.d.ts +57 -0
- package/dev-port-socket.d.ts +26 -0
- package/dev-ports.d.ts +11 -0
- package/dev-project-watch.d.ts +44 -0
- package/dev-project.d.ts +168 -0
- package/dev-push.d.ts +59 -0
- package/dev-restart.d.ts +141 -0
- package/dev-servers.d.ts +30 -0
- package/dev-setup-native.d.ts +23 -0
- package/dev-setup-opencode.d.ts +29 -0
- package/dev-setup.d.ts +16 -0
- package/dev-shell.d.ts +70 -0
- package/dev-slot.d.ts +28 -0
- package/dev-sockets.d.ts +13 -0
- package/dev-task-ports.d.ts +73 -0
- package/dev-tasks.d.ts +20 -0
- package/dev-terminal-connection.d.ts +19 -0
- package/dev-terminal.d.ts +42 -0
- package/dev-todos.d.ts +35 -0
- package/dev-transcriber.d.ts +15 -0
- package/dev-tunnel.d.ts +38 -0
- package/dev-versions.d.ts +53 -0
- package/dev-workers.d.ts +55 -0
- package/dev.d.ts +24 -0
- package/diff.d.ts +29 -0
- package/dispatched.d.ts +16 -0
- package/editors.d.ts +22 -0
- package/escalate.d.ts +27 -0
- package/events.d.ts +311 -0
- package/everywhere.d.ts +41 -0
- package/exhibit.d.ts +21 -0
- package/exit.d.ts +54 -0
- package/fact-todos.d.ts +18 -0
- package/fake-agent.d.ts +107 -0
- package/fake-agent.js +284 -0
- package/finding-facts.d.ts +38 -0
- package/findings.d.ts +84 -0
- package/fold.d.ts +43 -0
- package/follow.d.ts +41 -0
- package/format.d.ts +68 -0
- package/git.d.ts +112 -0
- package/handed-out.d.ts +79 -0
- package/handoff.d.ts +23 -0
- package/heavy-run.d.ts +12 -0
- package/heavy.d.ts +28 -0
- package/heavy.js +16 -0
- package/held.d.ts +22 -0
- package/index-0tfvy823.js +272 -0
- package/index-43pq33n4.js +157 -0
- package/index-4776671w.js +698 -0
- package/index-d4hjrzaq.js +464 -0
- package/index-gcfq7awr.js +740 -0
- package/index-k73tsw5g.js +101 -0
- package/index-kaa44k7q.js +59 -0
- package/index-vcv9m93e.js +1265 -0
- package/index-xmfmy729.js +249 -0
- package/index.d.ts +2 -0
- package/index.js +26928 -0
- package/init.d.ts +28 -0
- package/journal.d.ts +57 -0
- package/landed.d.ts +14 -0
- package/lane-todos.d.ts +44 -0
- package/lane.d.ts +55 -0
- package/lanes-from-tags.d.ts +17 -0
- package/lanes.d.ts +96 -0
- package/legacy-names.d.ts +70 -0
- package/legacy-ps.d.ts +31 -0
- package/limits.d.ts +32 -0
- package/list.d.ts +18 -0
- package/load-config.d.ts +44 -0
- package/log.d.ts +14 -0
- package/machine.d.ts +42 -0
- package/merge.d.ts +35 -0
- package/migrate-config.d.ts +31 -0
- package/models.d.ts +24 -0
- package/needs.d.ts +115 -0
- package/notices.d.ts +39 -0
- package/offered.d.ts +39 -0
- package/opencode-usage.d.ts +37 -0
- package/outcomes.d.ts +114 -0
- package/package.json +74 -5
- package/path.d.ts +13 -0
- package/plan.d.ts +236 -0
- package/port-forward.d.ts +22 -0
- package/port-pipe.d.ts +36 -0
- package/ports-list.d.ts +19 -0
- package/probe-runtime.d.ts +5 -0
- package/probe-runtime.js +13 -0
- package/project-reaches.d.ts +23 -0
- package/projects.d.ts +136 -0
- package/prompts.d.ts +128 -0
- package/pty.d.ts +39 -0
- package/pulse.d.ts +8 -0
- package/recommend.d.ts +31 -0
- package/release.d.ts +41 -0
- package/remote-process.d.ts +26 -0
- package/remote-pty.d.ts +29 -0
- package/remote-worker.d.ts +77 -0
- package/remove.d.ts +31 -0
- package/repository.d.ts +91 -0
- package/retry.d.ts +34 -0
- package/roster.d.ts +63 -0
- package/saved-ports-host.d.ts +25 -0
- package/saved-tunnel.d.ts +44 -0
- package/server-worker-socket.d.ts +21 -0
- package/setup-areas.d.ts +7 -0
- package/setup-opencode-model-error.d.ts +3 -0
- package/setup-opencode-models.d.ts +54 -0
- package/setup-opencode-recipe.d.ts +26 -0
- package/setup-opencode.d.ts +46 -0
- package/setup.d.ts +102 -0
- package/shared-browser.d.ts +50 -0
- package/shell.d.ts +17 -0
- package/show.d.ts +106 -0
- package/skill-checks.d.ts +73 -0
- package/skill-checks.js +10 -0
- package/skills.d.ts +16 -0
- package/slot-tunnel.d.ts +27 -0
- package/slots.d.ts +135 -0
- package/snapshot.d.ts +75 -0
- package/splates-artifact.d.ts +3 -0
- package/splates-creds.d.ts +3 -0
- package/splates-dev.d.ts +22 -0
- package/splates-flags.d.ts +34 -0
- package/splates-lane.d.ts +3 -0
- package/splates-projects.d.ts +3 -0
- package/splates-setup.d.ts +17 -0
- package/splates-slots.d.ts +3 -0
- package/splates-todo.d.ts +3 -0
- package/splates-tunnel.d.ts +3 -0
- package/splates-worker.d.ts +3 -0
- package/splates.d.ts +28 -0
- package/stats.d.ts +186 -0
- package/supervise.d.ts +50 -0
- package/system-changes.d.ts +67 -0
- package/system.d.ts +28 -0
- package/systems.d.ts +119 -0
- package/systems.js +21 -0
- package/table.d.ts +5 -0
- package/task-log.d.ts +35 -0
- package/task-ports.d.ts +25 -0
- package/tell.d.ts +47 -0
- package/todo-edit.d.ts +60 -0
- package/todo-file.d.ts +6 -0
- package/todo-lanes.d.ts +82 -0
- package/todo-list.d.ts +26 -0
- package/todo-take.d.ts +27 -0
- package/todo.d.ts +146 -0
- package/todos.d.ts +157 -0
- package/tool-calls.d.ts +18 -0
- package/tunnel-provider.d.ts +37 -0
- package/tunnel-provider.js +0 -0
- package/tunnel-remove.d.ts +28 -0
- package/tunnel-setup.d.ts +104 -0
- package/unix-worker-listener.d.ts +23 -0
- package/unix-worker-socket.d.ts +30 -0
- package/update.d.ts +29 -0
- package/update.js +10 -0
- package/vocabulary.d.ts +9 -0
- package/wait.d.ts +36 -0
- package/watch.d.ts +46 -0
- package/watched.d.ts +43 -0
- package/websocket-worker-socket.d.ts +18 -0
- package/worker-call-host.d.ts +51 -0
- package/worker-channel.d.ts +83 -0
- package/worker-connection.d.ts +24 -0
- package/worker-daemon.d.ts +64 -0
- package/worker-git.d.ts +18 -0
- package/worker-list.d.ts +49 -0
- package/worker-machine.d.ts +34 -0
- package/worker-port-host.d.ts +21 -0
- package/worker-process-host.d.ts +29 -0
- package/worker-protocol.d.ts +104 -0
- package/worker-pty-host.d.ts +34 -0
- package/worker-registry.d.ts +68 -0
- package/worker-replay.d.ts +25 -0
- package/worker-run.d.ts +20 -0
- package/worker-session.d.ts +189 -0
- package/worker-socket.d.ts +15 -0
- package/worktree-service.d.ts +113 -0
- package/worktree.d.ts +232 -0
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import type { WorkerSocket, WorkerSocketEvents } from "./worker-socket.js";
|
|
2
|
+
/** Bun's socket, whose handlers hand each event to the `UnixWorkerSocket` it carries. */
|
|
3
|
+
export type UnixSocket = Bun.Socket<UnixWorkerSocket>;
|
|
4
|
+
/** The handlers `Bun.listen` and `Bun.connect` take, the same at both ends. */
|
|
5
|
+
export declare const UNIX_HANDLERS: Bun.SocketHandler<UnixWorkerSocket>;
|
|
6
|
+
/**
|
|
7
|
+
* A `WorkerSocket` over a Unix socket, how the local worker speaks to the
|
|
8
|
+
* coordinator on its machine. Dial one with `connect`; a `UnixWorkerListener`
|
|
9
|
+
* hands over the other end.
|
|
10
|
+
*/
|
|
11
|
+
export declare class UnixWorkerSocket implements WorkerSocket {
|
|
12
|
+
private readonly dispatcher;
|
|
13
|
+
readonly events: import("webappwiz/events").Events<WorkerSocketEvents>;
|
|
14
|
+
private socket;
|
|
15
|
+
private pending;
|
|
16
|
+
/** What the kernel would not take yet, sent on the next drain. */
|
|
17
|
+
private unsent;
|
|
18
|
+
private open;
|
|
19
|
+
/** Dials the coordinator listening at `path`. */
|
|
20
|
+
static connect(path: string): Promise<UnixWorkerSocket>;
|
|
21
|
+
/** Takes the Bun socket it speaks over, as a listener or `connect` hands it. */
|
|
22
|
+
attach(socket: UnixSocket): void;
|
|
23
|
+
send(frame: string | Uint8Array): void;
|
|
24
|
+
dispose(): void;
|
|
25
|
+
/** Bun's `data` handler calls this with each chunk it read. */
|
|
26
|
+
received(chunk: Uint8Array): void;
|
|
27
|
+
/** Sends what the kernel has room for now. */
|
|
28
|
+
flush(): void;
|
|
29
|
+
closed(): void;
|
|
30
|
+
}
|
package/update.d.ts
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { type Logger } from "webappwiz/log";
|
|
2
|
+
import type { Fs, Ps } from "webappwiz/system";
|
|
3
|
+
/**
|
|
4
|
+
* Set in the environment of the splates `update` hands itself to, so that one
|
|
5
|
+
* refreshes rather than looking for a newer one again: npm can name a version
|
|
6
|
+
* a moment before `bunx` can fetch it.
|
|
7
|
+
*/
|
|
8
|
+
export declare const UPDATING = "SPLATES_UPDATING";
|
|
9
|
+
/**
|
|
10
|
+
* Brings this repository up to the newest splates: when npm has a newer release
|
|
11
|
+
* than the one running, runs `update` again on that one, which does the rest
|
|
12
|
+
* itself; otherwise moves todos saved with tags into lanes, installs this
|
|
13
|
+
* one's skill over whatever copy is there, through `bunx skills add` from
|
|
14
|
+
* this release's tag, and moves what an older config holds to where this
|
|
15
|
+
* one reads it. Offline, the running release is the newest there is to
|
|
16
|
+
* have. `wiz update` names the release instead, as it pins every webappwiz
|
|
17
|
+
* package to one. Answers with the exit code to end on.
|
|
18
|
+
*/
|
|
19
|
+
export declare function update({ root, fs, ps, log, newest, release, }: {
|
|
20
|
+
/** The repository's main tree. */
|
|
21
|
+
root: string;
|
|
22
|
+
fs: Fs;
|
|
23
|
+
ps: Ps;
|
|
24
|
+
log: Logger;
|
|
25
|
+
/** The latest splates on npm, or null when it cannot say; unasked given `release`. */
|
|
26
|
+
newest?: () => Promise<string | null>;
|
|
27
|
+
/** The release whose skill to install, rather than the newest. */
|
|
28
|
+
release?: string;
|
|
29
|
+
}): Promise<number>;
|
package/update.js
ADDED
package/vocabulary.d.ts
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { System } from "./systems.js";
|
|
2
|
+
/**
|
|
3
|
+
* Every word a prompt to an agent in `project` may use that a speech model
|
|
4
|
+
* would spell its own way: splates, the project's name, and each system's name
|
|
5
|
+
* and aliases.
|
|
6
|
+
*/
|
|
7
|
+
export declare function words(project: string, systems: Record<string, System>): string[];
|
|
8
|
+
/** The prompt that gets the project's own words spelled its way. */
|
|
9
|
+
export declare function vocabulary(project: string, systems: Record<string, System>): string;
|
package/wait.d.ts
ADDED
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { type Logger } from "webappwiz/log";
|
|
2
|
+
import { Duration } from "webappwiz/time";
|
|
3
|
+
import type { Todos } from "./todos.js";
|
|
4
|
+
import type { WorktreeService } from "./worktree-service.js";
|
|
5
|
+
/** How long `wait` gives a task before handing the wait back to its caller. */
|
|
6
|
+
export declare const DEFAULT_TIMEOUT: Duration;
|
|
7
|
+
/** When a wait begun now gives up after `timeout`, as an ISO time. */
|
|
8
|
+
export declare function untilAfter(timeout: Duration): string;
|
|
9
|
+
export interface WaitOptions {
|
|
10
|
+
/** How long to wait before giving up. */
|
|
11
|
+
timeout?: Duration;
|
|
12
|
+
/** How long between reads of the record; the default suits a human's patience. */
|
|
13
|
+
poll?: Duration;
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Blocks until a task stops moving: merged or removed (both leave the name
|
|
17
|
+
* `removed`), escalated to a human, or broken. Waiting is for the agent whose
|
|
18
|
+
* own work overlaps this one's and would rather rebase onto the result than
|
|
19
|
+
* against it, which is why the timeout is short enough to come back and think
|
|
20
|
+
* again rather than block a session for an afternoon.
|
|
21
|
+
*/
|
|
22
|
+
export declare function wait({ service, log }: {
|
|
23
|
+
service: WorktreeService;
|
|
24
|
+
log: Logger;
|
|
25
|
+
}, task: string, { timeout, poll }?: WaitOptions): Promise<void>;
|
|
26
|
+
/**
|
|
27
|
+
* Blocks until todo `id` leaves the list, which it does when the task that
|
|
28
|
+
* took it merges (or it is removed): what an agent whose next todo comes
|
|
29
|
+
* after it waits for, not knowing which task will take it. Ends early when
|
|
30
|
+
* the task that has it is escalated, since that wait is on a person.
|
|
31
|
+
*/
|
|
32
|
+
export declare function todoWait({ service, todos, log, }: {
|
|
33
|
+
service: WorktreeService;
|
|
34
|
+
todos: Todos;
|
|
35
|
+
log: Logger;
|
|
36
|
+
}, id: number, { timeout, poll }?: WaitOptions): Promise<void>;
|
package/watch.d.ts
ADDED
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import type { Git } from "./git.js";
|
|
2
|
+
import { Watched } from "./watched.js";
|
|
3
|
+
/** The git `Watch` runs, on whichever machine the agent works: `Git` here, or a worker's. */
|
|
4
|
+
export type WatchGit = Pick<Git, "root" | "run" | "interruptedOps">;
|
|
5
|
+
/**
|
|
6
|
+
* Something a command did to git that an agent should not have, judged by
|
|
7
|
+
* what it did rather than what it said: one that stashes and pops again, or
|
|
8
|
+
* commits and squashes, did nothing worth a flag.
|
|
9
|
+
*/
|
|
10
|
+
export type Flag =
|
|
11
|
+
/** Stashed `count` changes and left them there. */
|
|
12
|
+
{
|
|
13
|
+
type: "stashed";
|
|
14
|
+
count: number;
|
|
15
|
+
}
|
|
16
|
+
/** Took commits off `branch` that its tree no longer holds. */
|
|
17
|
+
| {
|
|
18
|
+
type: "dropped";
|
|
19
|
+
branch: string;
|
|
20
|
+
}
|
|
21
|
+
/** Checked out `now`, a branch or null for a detached HEAD, off `branch`. */
|
|
22
|
+
| {
|
|
23
|
+
type: "left";
|
|
24
|
+
branch: string;
|
|
25
|
+
now: string | null;
|
|
26
|
+
}
|
|
27
|
+
/** Pushed, updating these remote branches, in a command that says `push`. */
|
|
28
|
+
| {
|
|
29
|
+
type: "pushed";
|
|
30
|
+
refs: string[];
|
|
31
|
+
}
|
|
32
|
+
/** Changed these files in the main tree, from a task's worktree. */
|
|
33
|
+
| {
|
|
34
|
+
type: "outside";
|
|
35
|
+
paths: string[];
|
|
36
|
+
};
|
|
37
|
+
/**
|
|
38
|
+
* Watches the commands agents run in one repository, `git.root` its main
|
|
39
|
+
* tree, for what they did to git.
|
|
40
|
+
*/
|
|
41
|
+
export declare class Watch {
|
|
42
|
+
private readonly git;
|
|
43
|
+
constructor(git: WatchGit);
|
|
44
|
+
/** Starts watching a command run in `cwd`, looking at git as it stands. */
|
|
45
|
+
command(cwd: string): Watched;
|
|
46
|
+
}
|
package/watched.d.ts
ADDED
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import type { Flag, WatchGit } from "./watch.js";
|
|
2
|
+
/** A command being watched, from the look before it ran. */
|
|
3
|
+
export declare class Watched {
|
|
4
|
+
private readonly git;
|
|
5
|
+
private readonly cwd;
|
|
6
|
+
private readonly before;
|
|
7
|
+
constructor(git: WatchGit, cwd: string, before: Promise<Look>);
|
|
8
|
+
/** Starts watching a command run in `cwd`, looking at git as it stands. */
|
|
9
|
+
static start(git: WatchGit, cwd: string): Watched;
|
|
10
|
+
/** Settles once the look before the command is taken. */
|
|
11
|
+
looked(): Promise<void>;
|
|
12
|
+
/**
|
|
13
|
+
* Looks at git again, now that `command` is over, and says what it did.
|
|
14
|
+
* A push counts only in a command that says `push`.
|
|
15
|
+
*/
|
|
16
|
+
done(command: string | null): Promise<Flag[]>;
|
|
17
|
+
/**
|
|
18
|
+
* Whether `branch` lost what it held at `tip`: merging that commit into
|
|
19
|
+
* what the branch is now changes nothing in its commit or its tree, as it
|
|
20
|
+
* would not after a squash or a rebase onto trunk.
|
|
21
|
+
*/
|
|
22
|
+
private dropped;
|
|
23
|
+
/** A rebase detaches HEAD until it is done, as `splates merge` leaves one. */
|
|
24
|
+
private rebasing;
|
|
25
|
+
/** The remote branches a push moved, as their reflogs say. */
|
|
26
|
+
private pushed;
|
|
27
|
+
}
|
|
28
|
+
/** What git looked like around a command. */
|
|
29
|
+
interface Look {
|
|
30
|
+
/** The stash's entries, by commit. */
|
|
31
|
+
stash: string[];
|
|
32
|
+
/** The branch HEAD is on in the command's tree, null when detached. */
|
|
33
|
+
branch: string | null;
|
|
34
|
+
/** That branch's commit; null when detached or the tree is gone. */
|
|
35
|
+
tip: string | null;
|
|
36
|
+
/** Whether the tree is gone, as a merged task's is. */
|
|
37
|
+
gone: boolean;
|
|
38
|
+
/** Every remote branch but a symbolic one like `origin/HEAD`, with its commit. */
|
|
39
|
+
remotes: Map<string, string>;
|
|
40
|
+
/** The main tree's uncommitted paths; null for a command run in it. */
|
|
41
|
+
dirty: Set<string> | null;
|
|
42
|
+
}
|
|
43
|
+
export {};
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import type { WorkerSocket, WorkerSocketEvents } from "./worker-socket.js";
|
|
2
|
+
/**
|
|
3
|
+
* A `WorkerSocket` over a WebSocket the worker dials, as a remote worker
|
|
4
|
+
* reaches its coordinator's `/api/workers`: each frame is one message, text
|
|
5
|
+
* or binary as the protocol has it.
|
|
6
|
+
*/
|
|
7
|
+
export declare class WebSocketWorkerSocket implements WorkerSocket {
|
|
8
|
+
private readonly socket;
|
|
9
|
+
private readonly dispatcher;
|
|
10
|
+
readonly events: import("webappwiz/events").Events<WorkerSocketEvents>;
|
|
11
|
+
private open;
|
|
12
|
+
private constructor();
|
|
13
|
+
/** Dials `url`, settling once the socket is open. */
|
|
14
|
+
static connect(url: string): Promise<WebSocketWorkerSocket>;
|
|
15
|
+
send(frame: string | Uint8Array): void;
|
|
16
|
+
dispose(): void;
|
|
17
|
+
private closed;
|
|
18
|
+
}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import type { Resource } from "webappwiz/disposable";
|
|
2
|
+
import { z } from "zod";
|
|
3
|
+
import type { WorkerChannel } from "./worker-channel.js";
|
|
4
|
+
import type { WorkerMachine } from "./worker-machine.js";
|
|
5
|
+
/** A question a coordinator asks on a `calls` channel, answered by its id. */
|
|
6
|
+
export declare const CallRequest: z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
7
|
+
id: z.ZodNumber;
|
|
8
|
+
method: z.ZodLiteral<"git">;
|
|
9
|
+
cwd: z.ZodString;
|
|
10
|
+
args: z.ZodArray<z.ZodString>;
|
|
11
|
+
}, z.core.$strip>, z.ZodObject<{
|
|
12
|
+
id: z.ZodNumber;
|
|
13
|
+
method: z.ZodLiteral<"processes">;
|
|
14
|
+
}, z.core.$strip>, z.ZodObject<{
|
|
15
|
+
id: z.ZodNumber;
|
|
16
|
+
method: z.ZodLiteral<"listening">;
|
|
17
|
+
}, z.core.$strip>, z.ZodObject<{
|
|
18
|
+
id: z.ZodNumber;
|
|
19
|
+
method: z.ZodLiteral<"exists">;
|
|
20
|
+
path: z.ZodString;
|
|
21
|
+
}, z.core.$strip>, z.ZodObject<{
|
|
22
|
+
id: z.ZodNumber;
|
|
23
|
+
method: z.ZodLiteral<"read">;
|
|
24
|
+
path: z.ZodString;
|
|
25
|
+
from: z.ZodNumber;
|
|
26
|
+
}, z.core.$strip>], "method">;
|
|
27
|
+
export type CallRequest = z.infer<typeof CallRequest>;
|
|
28
|
+
/** How a worker answers: `{ id, result }`, or `{ id, error }` saying what went wrong. */
|
|
29
|
+
export declare const CallAnswer: z.ZodUnion<readonly [z.ZodObject<{
|
|
30
|
+
id: z.ZodNumber;
|
|
31
|
+
result: z.ZodUnknown;
|
|
32
|
+
}, z.core.$strip>, z.ZodObject<{
|
|
33
|
+
id: z.ZodNumber;
|
|
34
|
+
error: z.ZodString;
|
|
35
|
+
}, z.core.$strip>]>;
|
|
36
|
+
/**
|
|
37
|
+
* Answers a coordinator's calls on the machine a task runs on, each request
|
|
38
|
+
* a message on a `calls` channel and each answer one back, in whatever order
|
|
39
|
+
* they finish. A read's bytes go as base64.
|
|
40
|
+
*/
|
|
41
|
+
export declare class WorkerCallHost implements Resource {
|
|
42
|
+
private readonly channel;
|
|
43
|
+
private readonly machine;
|
|
44
|
+
private readonly unlisten;
|
|
45
|
+
constructor(channel: WorkerChannel, machine: WorkerMachine);
|
|
46
|
+
/** Stops answering, leaving the channel to whoever closes it. */
|
|
47
|
+
dispose(): void;
|
|
48
|
+
private answer;
|
|
49
|
+
private call;
|
|
50
|
+
private reply;
|
|
51
|
+
}
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
import type { Resource } from "webappwiz/disposable";
|
|
2
|
+
import { type Eventful } from "webappwiz/events";
|
|
3
|
+
import type { Json } from "./worker-protocol.js";
|
|
4
|
+
/** What a `WorkerChannel` hears from the other end, each with its seq. */
|
|
5
|
+
export interface WorkerChannelEvents extends Record<string, unknown> {
|
|
6
|
+
data: {
|
|
7
|
+
bytes: Uint8Array;
|
|
8
|
+
seq: number;
|
|
9
|
+
};
|
|
10
|
+
message: {
|
|
11
|
+
body: Json;
|
|
12
|
+
seq: number;
|
|
13
|
+
};
|
|
14
|
+
/** Both ends have closed it, whichever closed first. */
|
|
15
|
+
close: undefined;
|
|
16
|
+
}
|
|
17
|
+
/** What a channel needs of the session it runs over. */
|
|
18
|
+
export interface WorkerChannelLink {
|
|
19
|
+
/** Sends a frame in the channel's next seq, and says whether there is room for more. */
|
|
20
|
+
send(channel: number, frame: {
|
|
21
|
+
type: "message";
|
|
22
|
+
body: Json;
|
|
23
|
+
} | {
|
|
24
|
+
type: "data";
|
|
25
|
+
bytes: Uint8Array;
|
|
26
|
+
} | {
|
|
27
|
+
type: "close";
|
|
28
|
+
}): boolean;
|
|
29
|
+
ack(channel: number, seq: number): void;
|
|
30
|
+
/** Both ends have said close, so the session can forget the channel. */
|
|
31
|
+
done(channel: number): void;
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* One stream between a coordinator and a worker, such as an agent's stdio or
|
|
35
|
+
* a PTY: bytes as `data`, and JSON as `message` for what is not bytes (a
|
|
36
|
+
* resize, an exit code). Its frames survive a reconnect. Disposing it closes
|
|
37
|
+
* it at both ends, and each hears `close` once both have.
|
|
38
|
+
*/
|
|
39
|
+
export declare class WorkerChannel implements Eventful<WorkerChannelEvents>, Resource {
|
|
40
|
+
readonly id: number;
|
|
41
|
+
readonly kind: string;
|
|
42
|
+
readonly params: Json;
|
|
43
|
+
private readonly link;
|
|
44
|
+
private readonly dispatcher;
|
|
45
|
+
readonly events: import("webappwiz/events").Events<WorkerChannelEvents>;
|
|
46
|
+
private sentClose;
|
|
47
|
+
private heardClose;
|
|
48
|
+
constructor(id: number, kind: string, params: Json, link: WorkerChannelLink);
|
|
49
|
+
get closed(): boolean;
|
|
50
|
+
/**
|
|
51
|
+
* Returns `false` once the session holds as many unacked bytes as it is
|
|
52
|
+
* allowed: stop reading whatever feeds this until the session's `drain`.
|
|
53
|
+
*/
|
|
54
|
+
write(bytes: Uint8Array): boolean;
|
|
55
|
+
/** As `write`, for JSON. */
|
|
56
|
+
send(body: Json): boolean;
|
|
57
|
+
/** Says this end holds everything up to `seq`, for a session that acks by hand. */
|
|
58
|
+
ack(seq: number): void;
|
|
59
|
+
dispose(): void;
|
|
60
|
+
/**
|
|
61
|
+
* Ends it here without a word to the other end, which no longer knows it,
|
|
62
|
+
* as a coordinator started again does not; this end hears `close`.
|
|
63
|
+
*/
|
|
64
|
+
drop(): void;
|
|
65
|
+
/**
|
|
66
|
+
* Hands the channel what the other end sent; the session calls it. Says
|
|
67
|
+
* whether anyone heard it, since a frame nobody heard is the session's to ack.
|
|
68
|
+
*/
|
|
69
|
+
receive(frame: {
|
|
70
|
+
type: "message";
|
|
71
|
+
body: Json;
|
|
72
|
+
seq: number;
|
|
73
|
+
} | {
|
|
74
|
+
type: "data";
|
|
75
|
+
bytes: Uint8Array;
|
|
76
|
+
seq: number;
|
|
77
|
+
} | {
|
|
78
|
+
type: "close";
|
|
79
|
+
seq: number;
|
|
80
|
+
}): boolean;
|
|
81
|
+
private finishIfDone;
|
|
82
|
+
private assertOpen;
|
|
83
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { Disposer, type Resource } from "webappwiz/disposable";
|
|
2
|
+
import type { Duration } from "webappwiz/time";
|
|
3
|
+
import type { Negotiated } from "./worker-protocol.js";
|
|
4
|
+
import type { WorkerSocket } from "./worker-socket.js";
|
|
5
|
+
/**
|
|
6
|
+
* One socket's worth of a `WorkerSession`: what goes when the socket does,
|
|
7
|
+
* while the session's channels and unacked frames stay for the next one.
|
|
8
|
+
*/
|
|
9
|
+
export declare class WorkerConnection implements Resource {
|
|
10
|
+
readonly socket: WorkerSocket;
|
|
11
|
+
heard: Duration;
|
|
12
|
+
readonly resources: Disposer;
|
|
13
|
+
/** Settles with the handshake, or with why the socket went first. */
|
|
14
|
+
readonly settled: {
|
|
15
|
+
promise: Promise<Negotiated>;
|
|
16
|
+
resolve: (value?: PromiseLike<Negotiated> | Negotiated | undefined) => void;
|
|
17
|
+
reject: (reason?: any) => void;
|
|
18
|
+
};
|
|
19
|
+
/** Past the handshake, so channel frames flow. */
|
|
20
|
+
live: boolean;
|
|
21
|
+
ackFlush: Resource | undefined;
|
|
22
|
+
constructor(socket: WorkerSocket, heard: Duration);
|
|
23
|
+
dispose(): void;
|
|
24
|
+
}
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import type { AsyncResource } from "webappwiz/disposable";
|
|
2
|
+
import type { Logger } from "webappwiz/log";
|
|
3
|
+
import type { Fs, Ps } from "webappwiz/system";
|
|
4
|
+
import { type Clock, Duration, type Timer } from "webappwiz/time";
|
|
5
|
+
import { WorkerSession, type WorkerSessionOptions } from "./worker-session.js";
|
|
6
|
+
import type { WorkerSocket } from "./worker-socket.js";
|
|
7
|
+
/** How a worker reaches its coordinator, dialed afresh after each drop. */
|
|
8
|
+
export interface WorkerDialer {
|
|
9
|
+
/** Where it dials, for the log. */
|
|
10
|
+
readonly where: string;
|
|
11
|
+
dial(): Promise<WorkerSocket>;
|
|
12
|
+
}
|
|
13
|
+
/** The channels a worker serves, which it says it can in its hello. */
|
|
14
|
+
export declare const WORKER_CAPABILITIES: string[];
|
|
15
|
+
/** Who a `WorkerDaemon` is and what it runs on. */
|
|
16
|
+
export interface WorkerDaemonOptions {
|
|
17
|
+
/** Stays the same across restarts, so the coordinator resumes its session. */
|
|
18
|
+
id: string;
|
|
19
|
+
slots: number;
|
|
20
|
+
ps: Ps;
|
|
21
|
+
fs: Fs;
|
|
22
|
+
log: Logger;
|
|
23
|
+
/** The shortest and longest wait between dials. */
|
|
24
|
+
backoff?: {
|
|
25
|
+
min: Duration;
|
|
26
|
+
max: Duration;
|
|
27
|
+
};
|
|
28
|
+
/** Paces the session, as `WorkerSession` takes it. */
|
|
29
|
+
session?: Omit<WorkerSessionOptions, "timer" | "clock" | "capabilities">;
|
|
30
|
+
timer?: Timer;
|
|
31
|
+
clock?: Clock;
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* `splates worker run`: a worker that dials out to its coordinator and keeps
|
|
35
|
+
* dialing, waiting longer after each failure, and runs what it is asked to
|
|
36
|
+
* on this machine: processes, PTYs, calls, and connections to the ports its
|
|
37
|
+
* tasks serve. What it runs outlives a
|
|
38
|
+
* dropped link, since the session replays what the coordinator missed.
|
|
39
|
+
*/
|
|
40
|
+
export declare class WorkerDaemon implements AsyncResource {
|
|
41
|
+
private readonly dialer;
|
|
42
|
+
private readonly opts;
|
|
43
|
+
readonly session: WorkerSession;
|
|
44
|
+
private readonly hosts;
|
|
45
|
+
private readonly timer;
|
|
46
|
+
private readonly backoff;
|
|
47
|
+
private readonly machine;
|
|
48
|
+
private waiting;
|
|
49
|
+
private stopped;
|
|
50
|
+
constructor(dialer: WorkerDialer, opts: WorkerDaemonOptions);
|
|
51
|
+
/**
|
|
52
|
+
* Dials and serves until disposed, or until the coordinator refuses this
|
|
53
|
+
* worker, resolving with why it stopped.
|
|
54
|
+
*/
|
|
55
|
+
run(): Promise<{
|
|
56
|
+
refused: string;
|
|
57
|
+
} | {
|
|
58
|
+
stopped: true;
|
|
59
|
+
}>;
|
|
60
|
+
/** Stops dialing and everything this worker runs, and hangs up. */
|
|
61
|
+
disposeAsync(): Promise<void>;
|
|
62
|
+
private serve;
|
|
63
|
+
private sleep;
|
|
64
|
+
}
|
package/worker-git.d.ts
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import type { GitResult } from "./git.js";
|
|
2
|
+
import type { WatchGit } from "./watch.js";
|
|
3
|
+
import type { WorkerMachine } from "./worker-machine.js";
|
|
4
|
+
/**
|
|
5
|
+
* The git `Watch` runs around an agent's commands, run on the worker the
|
|
6
|
+
* agent works on, since its worktree is there.
|
|
7
|
+
*/
|
|
8
|
+
export declare class WorkerGit implements WatchGit {
|
|
9
|
+
/** The main worktree, where trunk lives. */
|
|
10
|
+
readonly root: string;
|
|
11
|
+
private readonly machine;
|
|
12
|
+
constructor(
|
|
13
|
+
/** The main worktree, where trunk lives. */
|
|
14
|
+
root: string, machine: WorkerMachine);
|
|
15
|
+
run(cwd: string, ...args: string[]): Promise<GitResult>;
|
|
16
|
+
/** As `Git.interruptedOps`, read on the worker: a worktree's half-finished merges and rebases. */
|
|
17
|
+
interruptedOps(worktree: string): Promise<string[]>;
|
|
18
|
+
}
|
package/worker-list.d.ts
ADDED
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import type { Logger } from "webappwiz/log";
|
|
2
|
+
import type { Ps } from "webappwiz/system";
|
|
3
|
+
import { type WallClock } from "webappwiz/time";
|
|
4
|
+
import type { WorkerKind } from "./remote-worker.js";
|
|
5
|
+
import type { WorkerRegistry } from "./worker-registry.js";
|
|
6
|
+
/** One worker as `GET /api/workers` and `splates worker list` give it. */
|
|
7
|
+
export interface WorkerListing {
|
|
8
|
+
id: string;
|
|
9
|
+
/** `provisioned` is for workers splates makes itself, which do not exist yet. */
|
|
10
|
+
kind: WorkerKind | "provisioned";
|
|
11
|
+
platform: string | null;
|
|
12
|
+
build: string | null;
|
|
13
|
+
/** What its link settled on; null before any handshake. */
|
|
14
|
+
protocol: string | null;
|
|
15
|
+
slots: {
|
|
16
|
+
used: number;
|
|
17
|
+
total: number | null;
|
|
18
|
+
};
|
|
19
|
+
/** `connected` while the link is up, else `away`. */
|
|
20
|
+
health: "connected" | "away";
|
|
21
|
+
/** When anything last came from it, epoch milliseconds; null before the first. */
|
|
22
|
+
lastHeard: number | null;
|
|
23
|
+
/** The tasks placed on it; none until tasks are placed on workers. */
|
|
24
|
+
tasks: string[];
|
|
25
|
+
dollarsPerHour: number;
|
|
26
|
+
}
|
|
27
|
+
/** What `GET /api/workers` answers. */
|
|
28
|
+
export interface WorkerListings {
|
|
29
|
+
workers: WorkerListing[];
|
|
30
|
+
refused: {
|
|
31
|
+
id: string;
|
|
32
|
+
protocol: string;
|
|
33
|
+
reason: string;
|
|
34
|
+
}[];
|
|
35
|
+
}
|
|
36
|
+
/** The workers a registry keeps and the ones it turned away. */
|
|
37
|
+
export declare function workerList(registry: WorkerRegistry): WorkerListings;
|
|
38
|
+
/** What `splates worker list` is run with. */
|
|
39
|
+
export interface ListWorkersOptions {
|
|
40
|
+
/** The `splates server` to ask; empty for the one this agent runs under. */
|
|
41
|
+
dev: string;
|
|
42
|
+
json: boolean;
|
|
43
|
+
log: Logger;
|
|
44
|
+
ps: Ps;
|
|
45
|
+
send?: typeof fetch;
|
|
46
|
+
wall?: WallClock;
|
|
47
|
+
}
|
|
48
|
+
/** `splates worker list`: asks the running `splates server` which workers it has. */
|
|
49
|
+
export declare function listWorkers(opts: ListWorkersOptions): Promise<void>;
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import type { Fs, ListeningEntry, ProcessEntry, Ps } from "webappwiz/system";
|
|
2
|
+
import { type GitResult } from "./git.js";
|
|
3
|
+
/** A file's size, and its bytes from where the caller last read up to. */
|
|
4
|
+
export interface WorkerRead {
|
|
5
|
+
size: number;
|
|
6
|
+
bytes: Uint8Array;
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* What the coordinator asks of the machine a task runs on: git in its
|
|
10
|
+
* worktree around each tool call (`Watch`), a background command's output
|
|
11
|
+
* (`ConversationBackground`), the process table (`heldBy`), and the ports
|
|
12
|
+
* its processes listen on (`TaskPorts`).
|
|
13
|
+
*/
|
|
14
|
+
export interface WorkerMachine {
|
|
15
|
+
git(cwd: string, args: string[]): Promise<GitResult>;
|
|
16
|
+
processes(): Promise<ProcessEntry[]>;
|
|
17
|
+
listening(): Promise<ListeningEntry[]>;
|
|
18
|
+
/** `path` from byte `from` on; a missing file reads as empty. */
|
|
19
|
+
read(path: string, from: number): Promise<WorkerRead>;
|
|
20
|
+
/** Whether anything is at `path`, a file or a directory. */
|
|
21
|
+
exists(path: string): Promise<boolean>;
|
|
22
|
+
}
|
|
23
|
+
/** The machine this process runs on, as a worker answers for it. */
|
|
24
|
+
export declare class LocalWorkerMachine implements WorkerMachine {
|
|
25
|
+
private readonly ps;
|
|
26
|
+
private readonly fs;
|
|
27
|
+
private readonly runner;
|
|
28
|
+
constructor(ps: Ps, fs: Fs);
|
|
29
|
+
git(cwd: string, args: string[]): Promise<GitResult>;
|
|
30
|
+
processes(): Promise<ProcessEntry[]>;
|
|
31
|
+
listening(): Promise<ListeningEntry[]>;
|
|
32
|
+
exists(path: string): Promise<boolean>;
|
|
33
|
+
read(path: string, from: number): Promise<WorkerRead>;
|
|
34
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type { Resource } from "webappwiz/disposable";
|
|
2
|
+
import { z } from "zod";
|
|
3
|
+
import type { WorkerChannel } from "./worker-channel.js";
|
|
4
|
+
import type { WorkerSession } from "./worker-session.js";
|
|
5
|
+
/** What a coordinator opens a `port` channel with. */
|
|
6
|
+
export declare const PortParams: z.ZodObject<{
|
|
7
|
+
port: z.ZodNumber;
|
|
8
|
+
}, z.core.$strip>;
|
|
9
|
+
/**
|
|
10
|
+
* One TCP connection a `port` channel opened to a port on the worker's
|
|
11
|
+
* loopback, such as a task's dev server: its bytes both ways as the
|
|
12
|
+
* channel's, `connected` once it is open, or `failed` with why before the
|
|
13
|
+
* channel closes. Closing the channel ends the connection.
|
|
14
|
+
*/
|
|
15
|
+
export declare class WorkerPortHost implements Resource {
|
|
16
|
+
private readonly channel;
|
|
17
|
+
private readonly pipe;
|
|
18
|
+
constructor(channel: WorkerChannel, session: WorkerSession);
|
|
19
|
+
dispose(): void;
|
|
20
|
+
private connect;
|
|
21
|
+
}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import type { Resource } from "webappwiz/disposable";
|
|
2
|
+
import type { Ps } from "webappwiz/system";
|
|
3
|
+
import { z } from "zod";
|
|
4
|
+
import type { WorkerChannel } from "./worker-channel.js";
|
|
5
|
+
import type { WorkerSession } from "./worker-session.js";
|
|
6
|
+
/** What a coordinator opens a `process` channel with. */
|
|
7
|
+
export declare const ProcessParams: z.ZodObject<{
|
|
8
|
+
argv: z.ZodArray<z.ZodString>;
|
|
9
|
+
cwd: z.ZodString;
|
|
10
|
+
env: z.ZodDefault<z.ZodRecord<z.ZodString, z.ZodString>>;
|
|
11
|
+
}, z.core.$strip>;
|
|
12
|
+
/**
|
|
13
|
+
* One process a `process` channel started on the worker, such as an agent:
|
|
14
|
+
* its stdout as the channel's bytes, its stdin from them, and its pid,
|
|
15
|
+
* stderr and exit code as messages. Its stdout is read only while the
|
|
16
|
+
* session has room, so a coordinator away for long stalls the process
|
|
17
|
+
* rather than losing what it says. Closing the channel kills it.
|
|
18
|
+
*/
|
|
19
|
+
export declare class WorkerProcessHost implements Resource {
|
|
20
|
+
private readonly channel;
|
|
21
|
+
private readonly session;
|
|
22
|
+
private readonly child;
|
|
23
|
+
private readonly stdin;
|
|
24
|
+
constructor(channel: WorkerChannel, session: WorkerSession, ps: Ps);
|
|
25
|
+
dispose(): void;
|
|
26
|
+
private told;
|
|
27
|
+
private run;
|
|
28
|
+
private pump;
|
|
29
|
+
}
|