@ahpd/server 0.1.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/README.md +88 -81
- package/dist/config.d.ts +72 -0
- package/dist/config.js +75 -0
- package/dist/daemon.d.ts +31 -0
- package/dist/daemon.js +162 -0
- package/dist/main.d.ts +2 -0
- package/dist/main.js +335 -0
- package/dist/pty.d.ts +12 -0
- package/dist/pty.js +56 -0
- package/package.json +15 -25
- package/dist/automations.d.ts +0 -4
- package/dist/automations.d.ts.map +0 -1
- package/dist/automations.js +0 -191
- package/dist/automations.js.map +0 -1
- package/dist/catalog.d.ts +0 -48
- package/dist/catalog.d.ts.map +0 -1
- package/dist/catalog.js +0 -51
- package/dist/catalog.js.map +0 -1
- package/dist/changes.d.ts +0 -4
- package/dist/changes.d.ts.map +0 -1
- package/dist/changes.js +0 -601
- package/dist/changes.js.map +0 -1
- package/dist/cron.d.ts +0 -43
- package/dist/cron.d.ts.map +0 -1
- package/dist/cron.js +0 -211
- package/dist/cron.js.map +0 -1
- package/dist/git.d.ts +0 -16
- package/dist/git.d.ts.map +0 -1
- package/dist/git.js +0 -126
- package/dist/git.js.map +0 -1
- package/dist/host.d.ts +0 -24
- package/dist/host.d.ts.map +0 -1
- package/dist/host.js +0 -5850
- package/dist/host.js.map +0 -1
- package/dist/index.d.ts +0 -36
- package/dist/index.d.ts.map +0 -1
- package/dist/index.js +0 -34
- package/dist/index.js.map +0 -1
- package/dist/listen.d.ts +0 -3
- package/dist/listen.d.ts.map +0 -1
- package/dist/listen.js +0 -183
- package/dist/listen.js.map +0 -1
- package/dist/paging.d.ts +0 -38
- package/dist/paging.d.ts.map +0 -1
- package/dist/paging.js +0 -53
- package/dist/paging.js.map +0 -1
- package/dist/paths.d.ts +0 -15
- package/dist/paths.d.ts.map +0 -1
- package/dist/paths.js +0 -19
- package/dist/paths.js.map +0 -1
- package/dist/resources.d.ts +0 -122
- package/dist/resources.d.ts.map +0 -1
- package/dist/resources.js +0 -494
- package/dist/resources.js.map +0 -1
- package/dist/rpc.d.ts +0 -63
- package/dist/rpc.d.ts.map +0 -1
- package/dist/rpc.js +0 -208
- package/dist/rpc.js.map +0 -1
- package/dist/scheduled.d.ts +0 -48
- package/dist/scheduled.d.ts.map +0 -1
- package/dist/scheduled.js +0 -325
- package/dist/scheduled.js.map +0 -1
- package/dist/terminals.d.ts +0 -29
- package/dist/terminals.d.ts.map +0 -1
- package/dist/terminals.js +0 -346
- package/dist/terminals.js.map +0 -1
- package/dist/tools.d.ts +0 -18
- package/dist/tools.d.ts.map +0 -1
- package/dist/tools.js +0 -65
- package/dist/tools.js.map +0 -1
- package/dist/types/agent.d.ts +0 -245
- package/dist/types/agent.d.ts.map +0 -1
- package/dist/types/agent.js +0 -3
- package/dist/types/agent.js.map +0 -1
- package/dist/types/automations.d.ts +0 -164
- package/dist/types/automations.d.ts.map +0 -1
- package/dist/types/automations.js +0 -3
- package/dist/types/automations.js.map +0 -1
- package/dist/types/catalog.d.ts +0 -30
- package/dist/types/catalog.d.ts.map +0 -1
- package/dist/types/catalog.js +0 -3
- package/dist/types/catalog.js.map +0 -1
- package/dist/types/changes.d.ts +0 -272
- package/dist/types/changes.d.ts.map +0 -1
- package/dist/types/changes.js +0 -3
- package/dist/types/changes.js.map +0 -1
- package/dist/types/common.d.ts +0 -9
- package/dist/types/common.d.ts.map +0 -1
- package/dist/types/common.js +0 -3
- package/dist/types/common.js.map +0 -1
- package/dist/types/host.d.ts +0 -372
- package/dist/types/host.d.ts.map +0 -1
- package/dist/types/host.js +0 -3
- package/dist/types/host.js.map +0 -1
- package/dist/types/index.d.ts +0 -20
- package/dist/types/index.d.ts.map +0 -1
- package/dist/types/index.js +0 -8
- package/dist/types/index.js.map +0 -1
- package/dist/types/listen.d.ts +0 -48
- package/dist/types/listen.d.ts.map +0 -1
- package/dist/types/listen.js +0 -3
- package/dist/types/listen.js.map +0 -1
- package/dist/types/paging.d.ts +0 -10
- package/dist/types/paging.d.ts.map +0 -1
- package/dist/types/paging.js +0 -3
- package/dist/types/paging.js.map +0 -1
- package/dist/types/probe.d.ts +0 -46
- package/dist/types/probe.d.ts.map +0 -1
- package/dist/types/probe.js +0 -3
- package/dist/types/probe.js.map +0 -1
- package/dist/types/resources.d.ts +0 -83
- package/dist/types/resources.d.ts.map +0 -1
- package/dist/types/resources.js +0 -3
- package/dist/types/resources.js.map +0 -1
- package/dist/types/rpc.d.ts +0 -65
- package/dist/types/rpc.d.ts.map +0 -1
- package/dist/types/rpc.js +0 -3
- package/dist/types/rpc.js.map +0 -1
- package/dist/types/session.d.ts +0 -395
- package/dist/types/session.d.ts.map +0 -1
- package/dist/types/session.js +0 -3
- package/dist/types/session.js.map +0 -1
- package/dist/types/terminals.d.ts +0 -131
- package/dist/types/terminals.d.ts.map +0 -1
- package/dist/types/terminals.js +0 -3
- package/dist/types/terminals.js.map +0 -1
- package/dist/types/wire.d.ts +0 -62
- package/dist/types/wire.d.ts.map +0 -1
- package/dist/types/wire.js +0 -13
- package/dist/types/wire.js.map +0 -1
- package/dist/types/worktrees.d.ts +0 -86
- package/dist/types/worktrees.d.ts.map +0 -1
- package/dist/types/worktrees.js +0 -3
- package/dist/types/worktrees.js.map +0 -1
- package/dist/worktrees.d.ts +0 -27
- package/dist/worktrees.d.ts.map +0 -1
- package/dist/worktrees.js +0 -152
- package/dist/worktrees.js.map +0 -1
- package/src/automations.ts +0 -204
- package/src/catalog.ts +0 -53
- package/src/changes.ts +0 -629
- package/src/cron.ts +0 -251
- package/src/git.ts +0 -132
- package/src/host.ts +0 -5947
- package/src/index.ts +0 -40
- package/src/listen.ts +0 -240
- package/src/paging.ts +0 -56
- package/src/paths.ts +0 -19
- package/src/resources.ts +0 -513
- package/src/rpc.ts +0 -222
- package/src/scheduled.ts +0 -369
- package/src/terminals.ts +0 -353
- package/src/tools.ts +0 -64
- package/src/types/agent.ts +0 -255
- package/src/types/automations.ts +0 -164
- package/src/types/catalog.ts +0 -26
- package/src/types/changes.ts +0 -266
- package/src/types/common.ts +0 -9
- package/src/types/host.ts +0 -386
- package/src/types/index.ts +0 -27
- package/src/types/listen.ts +0 -53
- package/src/types/paging.ts +0 -11
- package/src/types/probe.ts +0 -42
- package/src/types/resources.ts +0 -107
- package/src/types/rpc.ts +0 -68
- package/src/types/session.ts +0 -415
- package/src/types/terminals.ts +0 -133
- package/src/types/wire.ts +0 -69
- package/src/types/worktrees.ts +0 -91
- package/src/worktrees.ts +0 -162
package/src/types/host.ts
DELETED
|
@@ -1,386 +0,0 @@
|
|
|
1
|
-
/** The protocol server: channels, subscriptions and requests. */
|
|
2
|
-
|
|
3
|
-
import type { ToolDefinition } from '@microsoft/agent-host-protocol';
|
|
4
|
-
import type { Agent } from './agent.js';
|
|
5
|
-
import type { Entry, Metadata, Read, ResourceChange, WatchOptions, Watcher, Write as WriteContent } from './resources.js';
|
|
6
|
-
import type { Terminal, TerminalOptions } from './terminals.js';
|
|
7
|
-
import type { ChangesetSource } from './changes.js';
|
|
8
|
-
import type { Worktrees } from './worktrees.js';
|
|
9
|
-
import type { AutomationStore } from './automations.js';
|
|
10
|
-
import type { Peer, Request } from './rpc.js';
|
|
11
|
-
|
|
12
|
-
/**
|
|
13
|
-
* What a host can say about a directory beyond its path.
|
|
14
|
-
*
|
|
15
|
-
* Injected rather than built in. The interesting answers come from outside the
|
|
16
|
-
* protocol - a branch is a `git` subprocess, and `git` is a binary that may
|
|
17
|
-
* not be installed - and a host embedded in something that already knows them
|
|
18
|
-
* should not have them read a second time. A host given none says only what a
|
|
19
|
-
* path alone can tell it, which is the project's name.
|
|
20
|
-
*/
|
|
21
|
-
export interface DirectoryFacts {
|
|
22
|
-
/**
|
|
23
|
-
* What is known about a directory now, as the session's `_meta`.
|
|
24
|
-
*
|
|
25
|
-
* Synchronous and cheap, because it is asked for every description of every
|
|
26
|
-
* session - a catalogue of a hundred rows asks a hundred times. Anything
|
|
27
|
-
* that has to be fetched is fetched by `refresh` and cached here.
|
|
28
|
-
*
|
|
29
|
-
* The keys are the protocol's: `git` is the well-known one, and anything of
|
|
30
|
-
* an implementation's own belongs under a namespace.
|
|
31
|
-
*/
|
|
32
|
-
meta(dir: string): Record<string, unknown> | undefined;
|
|
33
|
-
/**
|
|
34
|
-
* Look again, answering whether anything actually moved.
|
|
35
|
-
*
|
|
36
|
-
* Asked once per served directory at startup and again whenever a turn
|
|
37
|
-
* ends. Only a true answer reaches a client, so a directory that has not
|
|
38
|
-
* changed costs nothing but the look.
|
|
39
|
-
*/
|
|
40
|
-
refresh?(dir: string): Promise<boolean>;
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
/**
|
|
44
|
-
* The files a client may read through this host.
|
|
45
|
-
*
|
|
46
|
-
* A port, for the same reason `DirectoryFacts` is one: reading a directory is
|
|
47
|
-
* `node:fs` on one runtime and something else on another, and a host embedded
|
|
48
|
-
* in an editor may already have the file open. `roots` arrives per call rather
|
|
49
|
-
* than being captured, because a backend may learn of a directory after the
|
|
50
|
-
* host started and the answer has to move with it.
|
|
51
|
-
*
|
|
52
|
-
* A host given none serves no `resource*` command at all - `-32601`, the same
|
|
53
|
-
* answer it gives for anything else it does not have - and completes no `@`.
|
|
54
|
-
*/
|
|
55
|
-
export interface ResourceStore {
|
|
56
|
-
/** One directory's entries. */
|
|
57
|
-
list(uri: string, roots: string[], ): Promise<Entry[]>;
|
|
58
|
-
/** One file's bytes, or the range of them that was asked for. */
|
|
59
|
-
read(uri: string, roots: string[], wanted?: string): Promise<Read>;
|
|
60
|
-
/** What a URI is, without reading it. */
|
|
61
|
-
resolve(uri: string, roots: string[], followSymlinks?: boolean): Promise<Metadata>;
|
|
62
|
-
/** Paths under `base` that start with what is typed. */
|
|
63
|
-
complete(typed: string, base: string, roots: string[], limit?: number): Promise<string[]>;
|
|
64
|
-
|
|
65
|
-
/*
|
|
66
|
-
* The half that writes.
|
|
67
|
-
*
|
|
68
|
-
* Every one is optional and they are optional together: a store that has
|
|
69
|
-
* none is a read-only filesystem, and the host answers `-32601` for each,
|
|
70
|
-
* which is a different thing from refusing a particular path. `fileResources()`
|
|
71
|
-
* has them all; a store over something that cannot be written - an archive,
|
|
72
|
-
* a read-only mount, a fixture - simply leaves them out and says so by
|
|
73
|
-
* omission rather than by throwing on every call.
|
|
74
|
-
*
|
|
75
|
-
* The host has already checked the client's `resourceRequest` grant before
|
|
76
|
-
* any of these is reached. What is left to each is the path check, which is
|
|
77
|
-
* a store's own business because only it knows what a path means.
|
|
78
|
-
*/
|
|
79
|
-
|
|
80
|
-
/** Write, create or splice one file. */
|
|
81
|
-
write?(uri: string, roots: string[], content: WriteContent): Promise<void>;
|
|
82
|
-
/** Remove a file, or a directory when `recursive`. */
|
|
83
|
-
remove?(uri: string, roots: string[], recursive?: boolean): Promise<void>;
|
|
84
|
-
/** Make a directory, and the parents it needs. */
|
|
85
|
-
mkdir?(uri: string, roots: string[]): Promise<void>;
|
|
86
|
-
/** Rename, within the served directories on both ends. */
|
|
87
|
-
move?(source: string, destination: string, roots: string[], failIfExists?: boolean): Promise<void>;
|
|
88
|
-
/** Copy, within the served directories on both ends. */
|
|
89
|
-
copy?(source: string, destination: string, roots: string[], failIfExists?: boolean): Promise<void>;
|
|
90
|
-
|
|
91
|
-
/**
|
|
92
|
-
* Tell me when that changes.
|
|
93
|
-
*
|
|
94
|
-
* Optional on its own rather than with the write half: watching is a read,
|
|
95
|
-
* and a store may perfectly well serve bytes it cannot subscribe to - a
|
|
96
|
-
* remote filesystem, an archive, a fixture. A host whose store has none
|
|
97
|
-
* answers `-32601` for `createResourceWatch`, and the protocol's own client
|
|
98
|
-
* treats that as a reason to degrade rather than to fail.
|
|
99
|
-
*
|
|
100
|
-
* `onChange` is called with a *batch*, because the filesystem reports one
|
|
101
|
-
* event per file and a save is several: the protocol says a server coalesces
|
|
102
|
-
* them, and an empty batch MUST NOT be dispatched. Closing the returned
|
|
103
|
-
* handle is the only way to stop it - there is no dispose command, and
|
|
104
|
-
* `unsubscribe` is what the host turns into this call.
|
|
105
|
-
*/
|
|
106
|
-
watch?(
|
|
107
|
-
uri: string,
|
|
108
|
-
roots: string[],
|
|
109
|
-
options: WatchOptions,
|
|
110
|
-
onChange: (changes: ResourceChange[]) => void,
|
|
111
|
-
): Promise<Watcher>;
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
/**
|
|
115
|
-
* The shells this host can open.
|
|
116
|
-
*
|
|
117
|
-
* A port, because a terminal is a subprocess: which one, and how it is
|
|
118
|
-
* spawned, is the runtime's business rather than the protocol's. A host given
|
|
119
|
-
* none serves neither `createTerminal` nor `disposeTerminal`, and says so with
|
|
120
|
-
* `-32601` rather than opening nothing and reporting success.
|
|
121
|
-
*/
|
|
122
|
-
export interface TerminalStore {
|
|
123
|
-
/** Open one, in a directory the host has already checked. */
|
|
124
|
-
create(options: TerminalOptions): Terminal;
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
/** How to construct a host. */
|
|
128
|
-
export interface HostOptions {
|
|
129
|
-
/**
|
|
130
|
-
* The directory whose sessions this host serves, on the machine it runs on.
|
|
131
|
-
*
|
|
132
|
-
* Also the catalogue's scope: sessions outside it are neither listed nor
|
|
133
|
-
* openable.
|
|
134
|
-
*/
|
|
135
|
-
path: string;
|
|
136
|
-
/**
|
|
137
|
-
* The backends this host serves.
|
|
138
|
-
*
|
|
139
|
-
* At least one, and each with a `provider` no other has. The first is what
|
|
140
|
-
* a client gets when it names none - which is the ordinary case, since a
|
|
141
|
-
* client that has read the root channel names one and one that has not
|
|
142
|
-
* cannot.
|
|
143
|
-
*
|
|
144
|
-
* Nothing in the host knows what any of them are. `claude()` is one that
|
|
145
|
-
* ships with it; anything satisfying `Agent` is another.
|
|
146
|
-
*/
|
|
147
|
-
agents: Agent[];
|
|
148
|
-
/**
|
|
149
|
-
* The files a client may read, and complete an `@` into.
|
|
150
|
-
*
|
|
151
|
-
* Left out, no `resource*` command is served. `fileResources()` is the one
|
|
152
|
-
* that ships with this package, and the daemon uses it.
|
|
153
|
-
*/
|
|
154
|
-
resources?: ResourceStore;
|
|
155
|
-
/**
|
|
156
|
-
* How to open a shell.
|
|
157
|
-
*
|
|
158
|
-
* Left out, no terminal can be created. `shellTerminals()` is the one that
|
|
159
|
-
* ships with this package, and the daemon uses it.
|
|
160
|
-
*/
|
|
161
|
-
terminals?: TerminalStore;
|
|
162
|
-
/**
|
|
163
|
-
* Where the file changes a session made come from.
|
|
164
|
-
*
|
|
165
|
-
* Left out, no session advertises a changeset and the changes screen is
|
|
166
|
-
* honestly empty rather than emptily wrong. `gitChanges()` is the one that
|
|
167
|
-
* ships with this package, and the daemon uses it.
|
|
168
|
-
*/
|
|
169
|
-
changes?: ChangesetSource;
|
|
170
|
-
/**
|
|
171
|
-
* What this host can say about the directories it serves.
|
|
172
|
-
*
|
|
173
|
-
* Left out, sessions carry their project and nothing more. `gitBranches()`
|
|
174
|
-
* is the one that ships with this package, and the daemon uses it.
|
|
175
|
-
*/
|
|
176
|
-
directories?: DirectoryFacts;
|
|
177
|
-
/**
|
|
178
|
-
* Whether a session can be given a working tree of its own.
|
|
179
|
-
*
|
|
180
|
-
* Left out, every session runs in the folder it was pointed at and this host
|
|
181
|
-
* advertises no `isolation` - so a client draws no control for it, which is
|
|
182
|
-
* the honest form of "not offered". `gitWorktrees()` is the one that ships
|
|
183
|
-
* with this package, and the daemon uses it.
|
|
184
|
-
*
|
|
185
|
-
* The reason to wire it in: two agents in one repository is the ordinary
|
|
186
|
-
* case for a sessions server, and without this they share a working tree.
|
|
187
|
-
* The second turn's changeset then contains the first turn's edits, and
|
|
188
|
-
* discarding a file discards somebody else's work.
|
|
189
|
-
*/
|
|
190
|
-
worktrees?: Worktrees;
|
|
191
|
-
/**
|
|
192
|
-
* The automations this host offers.
|
|
193
|
-
*
|
|
194
|
-
* Left out, no `ahp-automations://` channel is advertised and all three
|
|
195
|
-
* automation commands answer `-32601` - which is the right answer for a
|
|
196
|
-
* daemon that runs the sessions somebody asks for and schedules nothing.
|
|
197
|
-
* `memoryAutomations()` is the one that ships with this package: it holds
|
|
198
|
-
* definitions, runs them when asked, and holds no clock.
|
|
199
|
-
*/
|
|
200
|
-
automations?: AutomationStore;
|
|
201
|
-
/**
|
|
202
|
-
* Tools this host contributes to every session it runs.
|
|
203
|
-
*
|
|
204
|
-
* The protocol's `serverTools`: tools that are the *host's* rather than a
|
|
205
|
-
* backend's or a client's, reported on `SessionState.serverTools` and given
|
|
206
|
-
* to the backend to offer the model. What they are is the host's to decide
|
|
207
|
-
* - `hostTools()` is the set that ships with this package - and a host that
|
|
208
|
-
* passes none contributes none, which is what an absent `serverTools` says.
|
|
209
|
-
*/
|
|
210
|
-
tools?: HostTool[];
|
|
211
|
-
/** Called with one line per notable event, for a log. */
|
|
212
|
-
onEvent?(message: string): void;
|
|
213
|
-
}
|
|
214
|
-
|
|
215
|
-
/**
|
|
216
|
-
* One tool the host contributes, and what running it does.
|
|
217
|
-
*
|
|
218
|
-
* `definition` is what a client draws and what the model is offered;
|
|
219
|
-
* `run` is called when the model calls it, with the arguments it passed and
|
|
220
|
-
* the chat it called from. Returning a string is the answer; throwing is a
|
|
221
|
-
* tool that failed, and the message reaches the model.
|
|
222
|
-
*/
|
|
223
|
-
export interface HostTool {
|
|
224
|
-
/** What the model is offered. `name` is the id it calls. */
|
|
225
|
-
definition: ToolDefinition;
|
|
226
|
-
/** What running it does. */
|
|
227
|
-
run(input: Record<string, unknown>, at: ToolCall): Promise<string> | string;
|
|
228
|
-
}
|
|
229
|
-
|
|
230
|
-
/**
|
|
231
|
-
* Where a host tool was called from, and what the host knows.
|
|
232
|
-
*
|
|
233
|
-
* The reason a tool is the host's rather than the backend's: an agent inside
|
|
234
|
-
* a session cannot see the sessions beside it or the terminals a person is
|
|
235
|
-
* watching, and the host can. A tool that wants neither ignores both.
|
|
236
|
-
*/
|
|
237
|
-
export interface ToolCall {
|
|
238
|
-
/** The session channel URI the call was made in. */
|
|
239
|
-
session: string;
|
|
240
|
-
/** The chat channel URI it was made from. */
|
|
241
|
-
chat: string;
|
|
242
|
-
/** Every session this host is running, including the calling one. */
|
|
243
|
-
sessions(): { uri: string; provider: string; title: string; workingDirectories: string[] }[];
|
|
244
|
-
/** Every terminal this host has open. */
|
|
245
|
-
terminals(): { uri: string; title: string; cwd: string; running: boolean }[];
|
|
246
|
-
/**
|
|
247
|
-
* Read a resource this host serves, as text.
|
|
248
|
-
*
|
|
249
|
-
* Including one it does not have: a URI a connected client published is
|
|
250
|
-
* fetched from that client, which is the only way an agent reaches a
|
|
251
|
-
* plugin's virtual files or an editor's unsaved buffers. Rejects when
|
|
252
|
-
* nothing serves it, in the words of whatever refused.
|
|
253
|
-
*/
|
|
254
|
-
read(uri: string): Promise<string>;
|
|
255
|
-
}
|
|
256
|
-
|
|
257
|
-
/** One connected client and what it is watching. */
|
|
258
|
-
export interface Connection {
|
|
259
|
-
/** Where to write messages for this client. */
|
|
260
|
-
peer: Peer;
|
|
261
|
-
/** The identifier the client gave at `initialize`. */
|
|
262
|
-
clientId: string;
|
|
263
|
-
/**
|
|
264
|
-
* Channel URIs this client subscribed to.
|
|
265
|
-
*
|
|
266
|
-
* Per connection: two clients can watch one channel, and dropping one must
|
|
267
|
-
* not stop the other's stream.
|
|
268
|
-
*/
|
|
269
|
-
watching: Set<string>;
|
|
270
|
-
/**
|
|
271
|
-
* Resource access this client has been granted, as `read:<uri>` / `write:<uri>`.
|
|
272
|
-
*
|
|
273
|
-
* Per connection and never per host: `resourceRequest` is a negotiation
|
|
274
|
-
* between two peers, and a grant one client talked its way into is not one
|
|
275
|
-
* every other client on the port inherits. Emptied when the connection goes,
|
|
276
|
-
* because it goes with the set.
|
|
277
|
-
*/
|
|
278
|
-
grants: Set<string>;
|
|
279
|
-
/**
|
|
280
|
-
* Tokens this client pushed, by protected resource identifier.
|
|
281
|
-
*
|
|
282
|
-
* Per connection for the same reason grants are, and the specification says
|
|
283
|
-
* so outright: authentication status is per connection, each client
|
|
284
|
-
* authenticating independently. A token one client offered is theirs, spent
|
|
285
|
-
* only on sessions they ask for, and gone when they hang up.
|
|
286
|
-
*
|
|
287
|
-
* Which is also why an automation that fires with nobody connected has
|
|
288
|
-
* none: it is the host's own work rather than any client's, and it runs on
|
|
289
|
-
* the credentials the daemon was started with.
|
|
290
|
-
*/
|
|
291
|
-
tokens: Map<string, string>;
|
|
292
|
-
/**
|
|
293
|
-
* Channels this client named in a shape of its own, by the channel they mean.
|
|
294
|
-
*
|
|
295
|
-
* A client may address a chat by a URI this host did not mint - see
|
|
296
|
-
* `chatFor` - and it then expects to be answered about *that* URI: its
|
|
297
|
-
* subscription is keyed by the string it sent, and an action arriving under
|
|
298
|
-
* any other name belongs to a channel it is not watching. So the spelling is
|
|
299
|
-
* remembered per connection and every notification is addressed back the way
|
|
300
|
-
* it was asked for.
|
|
301
|
-
*/
|
|
302
|
-
aliases: Map<string, string>;
|
|
303
|
-
}
|
|
304
|
-
|
|
305
|
-
/**
|
|
306
|
-
* The clients connected to this host, as places a resource can come from.
|
|
307
|
-
*
|
|
308
|
-
* The protocol is symmetrical about `resource*`: the ten methods a client
|
|
309
|
-
* calls on a host are the ten a host may call on a client, with the same
|
|
310
|
-
* params and the same results, and the receiver decides whether to allow the
|
|
311
|
-
* operation whichever way round it went. What that is *for* is a client that
|
|
312
|
-
* publishes something the host has no way to reach - a plugin's virtual
|
|
313
|
-
* files, an editor's unsaved buffers, a filesystem provider - and addresses
|
|
314
|
-
* it as `<scheme>://<clientId>/…`.
|
|
315
|
-
*
|
|
316
|
-
* So this is not a port handed in: it is built out of the connections a host
|
|
317
|
-
* already has, and a URI naming one of them is answered by that client rather
|
|
318
|
-
* than by the host's own filesystem.
|
|
319
|
-
*/
|
|
320
|
-
export interface Clients {
|
|
321
|
-
/** Every client currently connected, by the id it gave at `initialize`. */
|
|
322
|
-
ids(): string[];
|
|
323
|
-
/**
|
|
324
|
-
* The client a URI belongs to, if a connected one publishes it.
|
|
325
|
-
*
|
|
326
|
-
* `<scheme>://<clientId>/…`, which is how the reference host addresses one.
|
|
327
|
-
* `file:` is never a client's, and neither is any `ahp-` channel scheme -
|
|
328
|
-
* those are this protocol's own and their authority is not a client id.
|
|
329
|
-
*/
|
|
330
|
-
owner(uri: string): string | undefined;
|
|
331
|
-
|
|
332
|
-
/** Read a file the client serves. */
|
|
333
|
-
read(client: string, uri: string, encoding?: string): Promise<unknown>;
|
|
334
|
-
/** List a directory the client serves. */
|
|
335
|
-
list(client: string, uri: string): Promise<unknown>;
|
|
336
|
-
/** Ask the client what a URI actually is. */
|
|
337
|
-
resolve(client: string, uri: string): Promise<unknown>;
|
|
338
|
-
/** Write a file the client serves. */
|
|
339
|
-
write(client: string, uri: string, content: { data: string; encoding?: string; create?: boolean; overwrite?: boolean }): Promise<unknown>;
|
|
340
|
-
/** Remove one. */
|
|
341
|
-
remove(client: string, uri: string, recursive?: boolean): Promise<unknown>;
|
|
342
|
-
/** Move one. Both URIs must be the same client's. */
|
|
343
|
-
move(client: string, source: string, destination: string, failIfExists?: boolean): Promise<unknown>;
|
|
344
|
-
/** Copy one. Both URIs must be the same client's. */
|
|
345
|
-
copy(client: string, source: string, destination: string, failIfExists?: boolean): Promise<unknown>;
|
|
346
|
-
/** Make a directory. */
|
|
347
|
-
mkdir(client: string, uri: string): Promise<unknown>;
|
|
348
|
-
/** Ask to watch one, and get back the channel the client will report on. */
|
|
349
|
-
watch(client: string, uri: string, options?: Record<string, unknown>): Promise<unknown>;
|
|
350
|
-
/** Ask the client for access to one of its resources. */
|
|
351
|
-
request(client: string, uri: string, access: { read?: boolean; write?: boolean }): Promise<unknown>;
|
|
352
|
-
}
|
|
353
|
-
|
|
354
|
-
/** A protocol server. One host serves many connections. */
|
|
355
|
-
export interface Host {
|
|
356
|
-
/**
|
|
357
|
-
* Take a new client and return what answers it.
|
|
358
|
-
*
|
|
359
|
-
* The result's `handle` answers requests; its `close` must be called when
|
|
360
|
-
* the connection drops, or the client's subscriptions leak.
|
|
361
|
-
*/
|
|
362
|
-
accept(peer: Peer): {
|
|
363
|
-
/** Answer one request from this client. */
|
|
364
|
-
handle(request: Request): Promise<unknown>;
|
|
365
|
-
/** Drop this client's subscriptions and state. */
|
|
366
|
-
close(): void;
|
|
367
|
-
};
|
|
368
|
-
/** How many clients are currently connected. */
|
|
369
|
-
connections(): number;
|
|
370
|
-
/**
|
|
371
|
-
* The connected clients, as places a resource can come from.
|
|
372
|
-
*
|
|
373
|
-
* Used by this host to answer a `resource*` command naming a URI a client
|
|
374
|
-
* published, and exposed so an embedder can read one directly.
|
|
375
|
-
*/
|
|
376
|
-
clients: Clients;
|
|
377
|
-
/**
|
|
378
|
-
* Replace the tools this host contributes.
|
|
379
|
-
*
|
|
380
|
-
* Full replacement, which is what `session/serverToolsChanged` means, and
|
|
381
|
-
* every running session is told. Sessions started after this get the new
|
|
382
|
-
* set; the ones already running get it on their next turn, because a
|
|
383
|
-
* backend is offered its tools when its process starts.
|
|
384
|
-
*/
|
|
385
|
-
setTools(tools: HostTool[]): void;
|
|
386
|
-
}
|
package/src/types/index.ts
DELETED
|
@@ -1,27 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Every shape this daemon speaks.
|
|
3
|
-
*
|
|
4
|
-
* Nothing under `types/` imports a runtime value, so the contract can be read
|
|
5
|
-
* without loading the server, a socket or the agent SDK.
|
|
6
|
-
*/
|
|
7
|
-
|
|
8
|
-
export type { Bag } from './common.js';
|
|
9
|
-
/*
|
|
10
|
-
* The protocol's own shapes, as this host builds them.
|
|
11
|
-
*
|
|
12
|
-
* On the public surface because the port names them: `Agent.transcript`
|
|
13
|
-
* answers with `WireTurn<Turn>[]`, and a backend written against this library
|
|
14
|
-
* cannot implement that without being able to say it.
|
|
15
|
-
*/
|
|
16
|
-
export type { OnWire, WireTurn } from './wire.js';
|
|
17
|
-
export type { Request, Wire, Peer, Handler } from './rpc.js';
|
|
18
|
-
export type { Summary } from './catalog.js';
|
|
19
|
-
export type { Emit, SessionOptions, Session, Ran, Chosen } from './session.js';
|
|
20
|
-
export type { HostOptions, Connection, Host } from './host.js';
|
|
21
|
-
export type { Page } from './paging.js';
|
|
22
|
-
export type { Connected, OnConnect, Runtime, Listener } from './listen.js';
|
|
23
|
-
export type { Offered } from './probe.js';
|
|
24
|
-
export type { Agent, Listed, Start, BoundTool } from './agent.js';
|
|
25
|
-
export type { Entry, Metadata, Read } from './resources.js';
|
|
26
|
-
export type { Claim, Terminal, TerminalOptions, SpawnPty } from './terminals.js';
|
|
27
|
-
export type { Worktree, Worktrees } from './worktrees.js';
|
package/src/types/listen.ts
DELETED
|
@@ -1,53 +0,0 @@
|
|
|
1
|
-
/** Accepting connections, on whichever JavaScript runtime is running. */
|
|
2
|
-
|
|
3
|
-
import type { Peer, Request } from './rpc.js';
|
|
4
|
-
|
|
5
|
-
/** One accepted client, for as long as its connection lasts. */
|
|
6
|
-
export interface Connected {
|
|
7
|
-
/** Answer one request from this client. */
|
|
8
|
-
handle(request: Request): Promise<unknown>;
|
|
9
|
-
/** Release what the connection held. Called once, when it drops. */
|
|
10
|
-
close(): void;
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
/** Called per connection, to hand it to whatever will answer it. */
|
|
14
|
-
export type OnConnect = (peer: Peer) => Connected;
|
|
15
|
-
|
|
16
|
-
/** The runtimes a listener can be running on. */
|
|
17
|
-
export type Runtime = 'node' | 'bun' | 'deno';
|
|
18
|
-
|
|
19
|
-
/** A running server. */
|
|
20
|
-
export interface Listener {
|
|
21
|
-
/** Which runtime was detected. */
|
|
22
|
-
readonly runtime: Runtime;
|
|
23
|
-
/** The address it bound. */
|
|
24
|
-
readonly host: string;
|
|
25
|
-
/** The port it accepted. */
|
|
26
|
-
readonly port: number;
|
|
27
|
-
/** Whether a connection token is required. */
|
|
28
|
-
readonly guarded: boolean;
|
|
29
|
-
/** Stop accepting and drop open connections. */
|
|
30
|
-
close(): void | Promise<void>;
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
/** Where to accept connections, and who may open one. */
|
|
34
|
-
export interface ListenOptions {
|
|
35
|
-
/** TCP port to bind. */
|
|
36
|
-
port: number;
|
|
37
|
-
/**
|
|
38
|
-
* Address to bind.
|
|
39
|
-
*
|
|
40
|
-
* Loopback by default, which is the only address that needs no secret:
|
|
41
|
-
* anything reaching it is already on this machine. `0.0.0.0` is every
|
|
42
|
-
* interface, and is what a connection token is for.
|
|
43
|
-
*/
|
|
44
|
-
host?: string;
|
|
45
|
-
/**
|
|
46
|
-
* A secret every connection must present, or nothing to accept any.
|
|
47
|
-
*
|
|
48
|
-
* Given as `?tkn=<token>` on the WebSocket URL or as an
|
|
49
|
-
* `Authorization: Bearer <token>` header. Browsers cannot set headers on a
|
|
50
|
-
* WebSocket, which is why the query string is the one that always works.
|
|
51
|
-
*/
|
|
52
|
-
token?: string;
|
|
53
|
-
}
|
package/src/types/paging.ts
DELETED
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
/** Serving a long list of turns a page at a time, walking backwards. */
|
|
2
|
-
|
|
3
|
-
import type { Bag } from './common.js';
|
|
4
|
-
|
|
5
|
-
/** One page of turns, newest page first, walking backwards. */
|
|
6
|
-
export interface Page {
|
|
7
|
-
/** The turns in this page, oldest first. */
|
|
8
|
-
turns: Bag[];
|
|
9
|
-
/** Cursor for the next older page. Absent when the page reaches the start. */
|
|
10
|
-
turnsNextCursor?: string;
|
|
11
|
-
}
|
package/src/types/probe.ts
DELETED
|
@@ -1,42 +0,0 @@
|
|
|
1
|
-
/** What the agent backend offers, read once before any session exists. */
|
|
2
|
-
|
|
3
|
-
/** The harness-wide capabilities, used until a session reports its own. */
|
|
4
|
-
export interface Offered {
|
|
5
|
-
/**
|
|
6
|
-
* Models a turn can run on.
|
|
7
|
-
*
|
|
8
|
-
* `id` is what the wire carries and `name` what a person reads.
|
|
9
|
-
* `configSchema` is what the *model* can be told to do differently, as
|
|
10
|
-
* `SessionModelInfo.configSchema`: a client draws it as a form beside the
|
|
11
|
-
* model rather than as a session-wide control, which matters because
|
|
12
|
-
* different models take different options. A model that takes none omits
|
|
13
|
-
* it, and a client then draws no form for that one.
|
|
14
|
-
*/
|
|
15
|
-
models: { id: string; name: string; configSchema?: Record<string, unknown> }[];
|
|
16
|
-
/**
|
|
17
|
-
* Skills, commands, subagents and MCP servers the harness offers here.
|
|
18
|
-
*
|
|
19
|
-
* What a new session starts out reporting, so its info pane is answered at
|
|
20
|
-
* once rather than several seconds later when its own agent replies.
|
|
21
|
-
*/
|
|
22
|
-
customizations: Record<string, unknown>[];
|
|
23
|
-
/**
|
|
24
|
-
* Output styles this harness has, and the one in force.
|
|
25
|
-
*
|
|
26
|
-
* Optional because it is a real answer for a backend to have no such
|
|
27
|
-
* notion: left out, no output-style control is drawn at all rather than an
|
|
28
|
-
* empty picker being offered.
|
|
29
|
-
*/
|
|
30
|
-
outputStyles?: string[];
|
|
31
|
-
/** The style the harness starts on, when it has them. */
|
|
32
|
-
outputStyle?: string;
|
|
33
|
-
/** Commands available after a slash. */
|
|
34
|
-
commands: {
|
|
35
|
-
/** The command name, without its leading slash. */
|
|
36
|
-
name: string;
|
|
37
|
-
/** One line describing what it does. */
|
|
38
|
-
description?: string;
|
|
39
|
-
/** What its argument is, e.g. `<id>`, when it takes one. */
|
|
40
|
-
argumentHint?: string;
|
|
41
|
-
}[];
|
|
42
|
-
}
|
package/src/types/resources.ts
DELETED
|
@@ -1,107 +0,0 @@
|
|
|
1
|
-
/** The host's filesystem, as far as a client is allowed to see it. */
|
|
2
|
-
|
|
3
|
-
import type {
|
|
4
|
-
ContentEncoding, ResourceChangeType, ResourceType, ResourceWriteMode,
|
|
5
|
-
} from '@microsoft/agent-host-protocol';
|
|
6
|
-
|
|
7
|
-
/*
|
|
8
|
-
* The vocabularies below are the protocol's own, taken as `${Enum}` rather
|
|
9
|
-
* than written out.
|
|
10
|
-
*
|
|
11
|
-
* A template literal over a string enum is the string union it declares, so
|
|
12
|
-
* `'ready'` still assigns and `'complete'` is a compile error - and the words
|
|
13
|
-
* come from the installed package rather than from a copy somebody made once.
|
|
14
|
-
* A copy is what let a changeset report `status: 'complete'` for the life of
|
|
15
|
-
* this host: the protocol says `ready`, nothing checked the difference, and a
|
|
16
|
-
* conformant client read a changeset that never finished computing.
|
|
17
|
-
*
|
|
18
|
-
* Type-only, so nothing here imports a runtime value.
|
|
19
|
-
*/
|
|
20
|
-
|
|
21
|
-
/** One entry in a directory listing. */
|
|
22
|
-
export interface Entry {
|
|
23
|
-
/** Base name, not a path. */
|
|
24
|
-
name: string;
|
|
25
|
-
/** Which of the two it is. A symlink is reported as what it points at. */
|
|
26
|
-
type: Exclude<`${ResourceType}`, 'symlink'>;
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
/** What a path is, without opening it. */
|
|
30
|
-
export interface Metadata {
|
|
31
|
-
/** The canonical URI, after symlinks unless they were not followed. */
|
|
32
|
-
uri: string;
|
|
33
|
-
/** Resource kind. */
|
|
34
|
-
type: `${ResourceType}`;
|
|
35
|
-
/** Size in bytes. Omitted for directories. */
|
|
36
|
-
size?: number;
|
|
37
|
-
/** ISO 8601 last-modified time. */
|
|
38
|
-
mtime: string;
|
|
39
|
-
/** ISO 8601 creation time. */
|
|
40
|
-
ctime: string;
|
|
41
|
-
/**
|
|
42
|
-
* A weak validator for the bytes, as `resourceWrite`'s `ifMatch` reads it.
|
|
43
|
-
*
|
|
44
|
-
* Derived from size and modification time rather than from a hash of the
|
|
45
|
-
* content: it exists to catch a lost update, so it has to be cheap enough to
|
|
46
|
-
* produce on every stat, and two writes a millisecond apart that leave the
|
|
47
|
-
* file the same length are not the case anybody is guarding against.
|
|
48
|
-
*/
|
|
49
|
-
etag?: string;
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
/**
|
|
53
|
-
* Where `data` goes in the file, as `ResourceWriteMode` has it.
|
|
54
|
-
*
|
|
55
|
-
* All three read `position` differently, which is the part worth stating: two
|
|
56
|
-
* of them are rooted at the start of the file and `append` is rooted at its
|
|
57
|
-
* end, so `position: 5` means "five bytes in" for the first two and "five
|
|
58
|
-
* bytes before EOF" for the third.
|
|
59
|
-
*/
|
|
60
|
-
export type WriteMode = `${ResourceWriteMode}`;
|
|
61
|
-
|
|
62
|
-
/** One write, with everything the protocol lets a client ask for. */
|
|
63
|
-
export interface Write {
|
|
64
|
-
/** The content, encoded as `encoding` says. */
|
|
65
|
-
data: string;
|
|
66
|
-
/** How to read `data`. Binary content MUST arrive base64. */
|
|
67
|
-
encoding: `${ContentEncoding}`;
|
|
68
|
-
/** How `data` is placed. `truncate` when the client says nothing. */
|
|
69
|
-
mode?: WriteMode;
|
|
70
|
-
/** The offset, read as `mode` says. Zero when the client says nothing. */
|
|
71
|
-
position?: number;
|
|
72
|
-
/** Refuse with `-32010` if the file is already there. */
|
|
73
|
-
createOnly?: boolean;
|
|
74
|
-
/** Refuse with `-32011` unless the file's current `etag` is this one. */
|
|
75
|
-
ifMatch?: string;
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
/** One file's bytes, in whichever encoding was meaningful. */
|
|
79
|
-
export interface Read {
|
|
80
|
-
/** The content, encoded as `encoding` says. */
|
|
81
|
-
data: string;
|
|
82
|
-
/** How `data` is encoded. Reported rather than assumed. */
|
|
83
|
-
encoding: `${ContentEncoding}`;
|
|
84
|
-
/** Sniffed MIME type, where there is one worth reporting. */
|
|
85
|
-
contentType?: string;
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
/** What happened to one path, in the protocol's three words. */
|
|
89
|
-
export interface ResourceChange {
|
|
90
|
-
uri: string;
|
|
91
|
-
type: `${ResourceChangeType}`;
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
/** What a watch was asked to report. */
|
|
95
|
-
export interface WatchOptions {
|
|
96
|
-
/** Report descendants too. Without it, the path itself and its direct children. */
|
|
97
|
-
recursive?: boolean;
|
|
98
|
-
/** Globs, relative to the watched root, whose matches are not reported. */
|
|
99
|
-
excludes?: string[];
|
|
100
|
-
/** Globs the reported set is restricted to. Absent reports everything not excluded. */
|
|
101
|
-
includes?: string[];
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
/** A watch, for as long as somebody wants it. */
|
|
105
|
-
export interface Watcher {
|
|
106
|
-
close(): void;
|
|
107
|
-
}
|