@ahpd/server 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (163) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +129 -0
  3. package/dist/automations.d.ts +4 -0
  4. package/dist/automations.d.ts.map +1 -0
  5. package/dist/automations.js +191 -0
  6. package/dist/automations.js.map +1 -0
  7. package/dist/catalog.d.ts +48 -0
  8. package/dist/catalog.d.ts.map +1 -0
  9. package/dist/catalog.js +51 -0
  10. package/dist/catalog.js.map +1 -0
  11. package/dist/changes.d.ts +4 -0
  12. package/dist/changes.d.ts.map +1 -0
  13. package/dist/changes.js +601 -0
  14. package/dist/changes.js.map +1 -0
  15. package/dist/cron.d.ts +43 -0
  16. package/dist/cron.d.ts.map +1 -0
  17. package/dist/cron.js +211 -0
  18. package/dist/cron.js.map +1 -0
  19. package/dist/git.d.ts +16 -0
  20. package/dist/git.d.ts.map +1 -0
  21. package/dist/git.js +126 -0
  22. package/dist/git.js.map +1 -0
  23. package/dist/host.d.ts +24 -0
  24. package/dist/host.d.ts.map +1 -0
  25. package/dist/host.js +5850 -0
  26. package/dist/host.js.map +1 -0
  27. package/dist/index.d.ts +36 -0
  28. package/dist/index.d.ts.map +1 -0
  29. package/dist/index.js +34 -0
  30. package/dist/index.js.map +1 -0
  31. package/dist/listen.d.ts +3 -0
  32. package/dist/listen.d.ts.map +1 -0
  33. package/dist/listen.js +183 -0
  34. package/dist/listen.js.map +1 -0
  35. package/dist/paging.d.ts +38 -0
  36. package/dist/paging.d.ts.map +1 -0
  37. package/dist/paging.js +53 -0
  38. package/dist/paging.js.map +1 -0
  39. package/dist/paths.d.ts +15 -0
  40. package/dist/paths.d.ts.map +1 -0
  41. package/dist/paths.js +19 -0
  42. package/dist/paths.js.map +1 -0
  43. package/dist/resources.d.ts +122 -0
  44. package/dist/resources.d.ts.map +1 -0
  45. package/dist/resources.js +494 -0
  46. package/dist/resources.js.map +1 -0
  47. package/dist/rpc.d.ts +63 -0
  48. package/dist/rpc.d.ts.map +1 -0
  49. package/dist/rpc.js +208 -0
  50. package/dist/rpc.js.map +1 -0
  51. package/dist/scheduled.d.ts +48 -0
  52. package/dist/scheduled.d.ts.map +1 -0
  53. package/dist/scheduled.js +325 -0
  54. package/dist/scheduled.js.map +1 -0
  55. package/dist/terminals.d.ts +29 -0
  56. package/dist/terminals.d.ts.map +1 -0
  57. package/dist/terminals.js +346 -0
  58. package/dist/terminals.js.map +1 -0
  59. package/dist/tools.d.ts +18 -0
  60. package/dist/tools.d.ts.map +1 -0
  61. package/dist/tools.js +65 -0
  62. package/dist/tools.js.map +1 -0
  63. package/dist/types/agent.d.ts +245 -0
  64. package/dist/types/agent.d.ts.map +1 -0
  65. package/dist/types/agent.js +3 -0
  66. package/dist/types/agent.js.map +1 -0
  67. package/dist/types/automations.d.ts +164 -0
  68. package/dist/types/automations.d.ts.map +1 -0
  69. package/dist/types/automations.js +3 -0
  70. package/dist/types/automations.js.map +1 -0
  71. package/dist/types/catalog.d.ts +30 -0
  72. package/dist/types/catalog.d.ts.map +1 -0
  73. package/dist/types/catalog.js +3 -0
  74. package/dist/types/catalog.js.map +1 -0
  75. package/dist/types/changes.d.ts +272 -0
  76. package/dist/types/changes.d.ts.map +1 -0
  77. package/dist/types/changes.js +3 -0
  78. package/dist/types/changes.js.map +1 -0
  79. package/dist/types/common.d.ts +9 -0
  80. package/dist/types/common.d.ts.map +1 -0
  81. package/dist/types/common.js +3 -0
  82. package/dist/types/common.js.map +1 -0
  83. package/dist/types/host.d.ts +372 -0
  84. package/dist/types/host.d.ts.map +1 -0
  85. package/dist/types/host.js +3 -0
  86. package/dist/types/host.js.map +1 -0
  87. package/dist/types/index.d.ts +20 -0
  88. package/dist/types/index.d.ts.map +1 -0
  89. package/dist/types/index.js +8 -0
  90. package/dist/types/index.js.map +1 -0
  91. package/dist/types/listen.d.ts +48 -0
  92. package/dist/types/listen.d.ts.map +1 -0
  93. package/dist/types/listen.js +3 -0
  94. package/dist/types/listen.js.map +1 -0
  95. package/dist/types/paging.d.ts +10 -0
  96. package/dist/types/paging.d.ts.map +1 -0
  97. package/dist/types/paging.js +3 -0
  98. package/dist/types/paging.js.map +1 -0
  99. package/dist/types/probe.d.ts +46 -0
  100. package/dist/types/probe.d.ts.map +1 -0
  101. package/dist/types/probe.js +3 -0
  102. package/dist/types/probe.js.map +1 -0
  103. package/dist/types/resources.d.ts +83 -0
  104. package/dist/types/resources.d.ts.map +1 -0
  105. package/dist/types/resources.js +3 -0
  106. package/dist/types/resources.js.map +1 -0
  107. package/dist/types/rpc.d.ts +65 -0
  108. package/dist/types/rpc.d.ts.map +1 -0
  109. package/dist/types/rpc.js +3 -0
  110. package/dist/types/rpc.js.map +1 -0
  111. package/dist/types/session.d.ts +395 -0
  112. package/dist/types/session.d.ts.map +1 -0
  113. package/dist/types/session.js +3 -0
  114. package/dist/types/session.js.map +1 -0
  115. package/dist/types/terminals.d.ts +131 -0
  116. package/dist/types/terminals.d.ts.map +1 -0
  117. package/dist/types/terminals.js +3 -0
  118. package/dist/types/terminals.js.map +1 -0
  119. package/dist/types/wire.d.ts +62 -0
  120. package/dist/types/wire.d.ts.map +1 -0
  121. package/dist/types/wire.js +13 -0
  122. package/dist/types/wire.js.map +1 -0
  123. package/dist/types/worktrees.d.ts +86 -0
  124. package/dist/types/worktrees.d.ts.map +1 -0
  125. package/dist/types/worktrees.js +3 -0
  126. package/dist/types/worktrees.js.map +1 -0
  127. package/dist/worktrees.d.ts +27 -0
  128. package/dist/worktrees.d.ts.map +1 -0
  129. package/dist/worktrees.js +152 -0
  130. package/dist/worktrees.js.map +1 -0
  131. package/package.json +61 -0
  132. package/src/automations.ts +204 -0
  133. package/src/catalog.ts +53 -0
  134. package/src/changes.ts +629 -0
  135. package/src/cron.ts +251 -0
  136. package/src/git.ts +132 -0
  137. package/src/host.ts +5947 -0
  138. package/src/index.ts +40 -0
  139. package/src/listen.ts +240 -0
  140. package/src/paging.ts +56 -0
  141. package/src/paths.ts +19 -0
  142. package/src/resources.ts +513 -0
  143. package/src/rpc.ts +222 -0
  144. package/src/scheduled.ts +369 -0
  145. package/src/terminals.ts +353 -0
  146. package/src/tools.ts +64 -0
  147. package/src/types/agent.ts +255 -0
  148. package/src/types/automations.ts +164 -0
  149. package/src/types/catalog.ts +26 -0
  150. package/src/types/changes.ts +266 -0
  151. package/src/types/common.ts +9 -0
  152. package/src/types/host.ts +386 -0
  153. package/src/types/index.ts +27 -0
  154. package/src/types/listen.ts +53 -0
  155. package/src/types/paging.ts +11 -0
  156. package/src/types/probe.ts +42 -0
  157. package/src/types/resources.ts +107 -0
  158. package/src/types/rpc.ts +68 -0
  159. package/src/types/session.ts +415 -0
  160. package/src/types/terminals.ts +133 -0
  161. package/src/types/wire.ts +69 -0
  162. package/src/types/worktrees.ts +91 -0
  163. package/src/worktrees.ts +162 -0
@@ -0,0 +1,395 @@
1
+ /** One agent session: its lifecycle, its turns, and what it is waiting for. */
2
+ import type { Bag } from './common.js';
3
+ import type { BoundTool } from './agent.js';
4
+ /**
5
+ * Emits one state action on a session's channel.
6
+ *
7
+ * `session` addresses the session channel, `chat` the chat channel beneath it,
8
+ * and `terminal` a terminal's own - the emitter knows which of its channels it
9
+ * is talking about and the host knows what each is called.
10
+ */
11
+ export type Emit = (channel: 'session' | 'chat' | 'terminal', action: Bag) => void;
12
+ /**
13
+ * The model a turn runs on.
14
+ *
15
+ * An object rather than a name, because a model that carries a `configSchema`
16
+ * is chosen by picking a row *and* answering its form: the protocol's
17
+ * `ModelSelection` is `{ id, config }`, and a host that read only the id would
18
+ * accept a form it then ignored.
19
+ */
20
+ export interface Chosen {
21
+ /** The model, spelled as `RootState.agents[].models[].id` spells it. */
22
+ id: string;
23
+ /**
24
+ * What the client filled that model's own `configSchema` in with.
25
+ *
26
+ * JSON primitives, which is what the protocol carries here: most pickers
27
+ * produce strings and a numeric one produces a number.
28
+ */
29
+ config?: Record<string, string | number | boolean | null>;
30
+ }
31
+ /** How to construct a session. */
32
+ export interface SessionOptions {
33
+ /** The session channel URI, `ahp-session:/<id>`. */
34
+ uri: string;
35
+ /** The chat channel URI beneath it, `ahp-chat:/<id>`. */
36
+ chatUri: string;
37
+ /**
38
+ * Directories beside the first the agent may also read and write.
39
+ *
40
+ * The first is `cwd` and is the process root; these are its peers. The
41
+ * protocol calls the whole set `workingDirectories` and fixes index 0 for
42
+ * the session's lifetime, which is what `immutablePrimary` means.
43
+ */
44
+ additional?: string[];
45
+ /** The directory the agent works in. */
46
+ cwd: string;
47
+ /** Config values chosen at creation, by key. */
48
+ settings?: Record<string, unknown>;
49
+ /** The config schema this session reports, shared with the root channel. */
50
+ schema?: () => Bag;
51
+ /** Customizations to report until the agent reports its own. */
52
+ seedCustomizations?: Bag[];
53
+ /** Where state actions go. */
54
+ emit: Emit;
55
+ /**
56
+ * Environment for the agent's own process.
57
+ *
58
+ * Merged over `process.env` by the session, never handed to the SDK alone:
59
+ * the SDK's `env` *replaces* the subprocess environment rather than adding
60
+ * to it, so passing only a credential is a subprocess with no `PATH`.
61
+ */
62
+ env?: Record<string, string>;
63
+ /** An existing agent session to continue, rather than starting a new one. */
64
+ resume?: string;
65
+ /**
66
+ * The prompt this session is resumed *at*, so the rest is left behind.
67
+ *
68
+ * A fork: the conversation continues from that turn as though the ones
69
+ * after it had not happened, under a new id of its own so the original is
70
+ * untouched. Meaningless without `resume`, which names what is being forked.
71
+ */
72
+ forkAt?: string;
73
+ /**
74
+ * The chain entry this session is resumed *at*, keeping it and everything
75
+ * before it.
76
+ *
77
+ * A rewind rather than a fork: the conversation carries on under the id it
78
+ * already had, with the turns after that point dropped. What
79
+ * `chat/truncated` asks for, and the id is the difference - a fork leaves
80
+ * the original for somebody else to find, a truncation means there is
81
+ * nothing left to find. Meaningless without `resume`, and ignored beside
82
+ * `forkAt`, which asks for the other thing.
83
+ */
84
+ rewindAt?: string;
85
+ /**
86
+ * Context the first turn carries without showing it.
87
+ *
88
+ * A side chat is started from a turn somewhere else and needs to know what
89
+ * that turn said, but the protocol is explicit that the source transcript is
90
+ * not copied into this chat's visible history - so this reaches the model
91
+ * and never the wire.
92
+ */
93
+ context?: string;
94
+ /**
95
+ * MCP servers this session declares, by name.
96
+ *
97
+ * Declared by the host rather than left to the backend's own discovery,
98
+ * because a server the SDK was given is one it can be told about again -
99
+ * which is what applying a token a client signed in with requires.
100
+ */
101
+ mcpServers?: Record<string, Bag>;
102
+ /**
103
+ * Tools the host contributes to this session.
104
+ *
105
+ * Offered to the model as an MCP server that runs in this process, so a
106
+ * call is a function call rather than a subprocess. What they are is the
107
+ * host's business; this only runs them.
108
+ */
109
+ tools?: BoundTool[];
110
+ /** Turns already known, so a resumed session does not open empty. */
111
+ seed?: Bag[];
112
+ /**
113
+ * A file a tool is about to change, and the same file once it has.
114
+ *
115
+ * Off the agent's own message stream rather than out of a hook: the SDK's
116
+ * `PreToolUse` and `PostToolUse` are bypassable from a person's settings,
117
+ * and the stream is the signal that cannot be turned off. Called with
118
+ * `before` as the tool is announced and `after` when its result arrives,
119
+ * which is what makes a turn's changeset the turn's rather than the
120
+ * working tree's at the time somebody asked.
121
+ *
122
+ * The path only. Reading it is the host's business, because reading a file
123
+ * is a filesystem and a session has none.
124
+ */
125
+ onFileEdit?(turnId: string, path: string, phase: 'before' | 'after'): void;
126
+ /** Called once the agent has reported what it can do. */
127
+ onHandshake?(): void;
128
+ }
129
+ /** What a host-run command did, once it has finished doing it. */
130
+ export interface Ran {
131
+ /** Whether it exited cleanly. */
132
+ success: boolean;
133
+ /** One line about how it went, in the past tense, for the finished call. */
134
+ said: string;
135
+ /** Everything it printed. Empty when it printed nothing. */
136
+ output: string;
137
+ /** The terminal it ran in, so a client can watch it while it runs. */
138
+ terminal?: string;
139
+ /** What it exited with, where the runtime reported one. */
140
+ code?: number;
141
+ }
142
+ /** A live session. */
143
+ export interface Session {
144
+ /** The session channel URI. */
145
+ readonly uri: string;
146
+ /** The chat channel URI. */
147
+ readonly chatUri: string;
148
+ /** Models this session can run a turn on. Empty until the agent has answered. */
149
+ models(): {
150
+ id: string;
151
+ name: string;
152
+ }[];
153
+ /**
154
+ * The id the agent gave this session, if it has said one yet.
155
+ *
156
+ * Not the same as `uri`: the client names the channel, the agent names the
157
+ * transcript it writes. The catalogue needs both to tell that the row on
158
+ * disk and this session are one conversation.
159
+ */
160
+ agentId(): string | undefined;
161
+ /**
162
+ * The backend's own name for the prompt that began a turn, if it has one.
163
+ *
164
+ * What a fork is cut at. A turn has an id this host chose and the backend
165
+ * has an id of its own for the same prompt, and only the backend's means
166
+ * anything when it is asked to resume at one.
167
+ *
168
+ * Optional, and its absence is what makes forking unavailable: a backend
169
+ * that cannot name a prompt cannot be asked to continue from one, and the
170
+ * host advertises no `fork` capability for it rather than offering a control
171
+ * that fails when it is used.
172
+ */
173
+ forkPoint?(turnId: string): string | undefined;
174
+ /**
175
+ * The backend's own name for the *last* thing a turn did, if it has one.
176
+ *
177
+ * Where a rewind cuts. `forkPoint` names the prompt a turn began with and
178
+ * `endPoint` names the last entry it left behind, and the two are different
179
+ * questions: a fork re-asks the turn, a truncation keeps it whole and drops
180
+ * what came after.
181
+ *
182
+ * Optional and, like `forkPoint`, only ever answered for a turn this process
183
+ * watched run: the backend's names for a turn read back off a transcript are
184
+ * not recorded, so a session resumed from disk can be truncated no further
185
+ * back than its own first turn.
186
+ */
187
+ endPoint?(turnId: string): string | undefined;
188
+ /** Skills, commands, subagents and MCP servers this session was given. */
189
+ customizations(): Bag[];
190
+ /** Every completed turn. Snapshots carry only the newest page of these. */
191
+ allTurns(): Bag[];
192
+ /** `SessionStatus` bitset, derived from what the session is doing now. */
193
+ status(): number;
194
+ /** What it is doing now, in one line, or nothing when it is idle. */
195
+ activity(): string | undefined;
196
+ /** Display title. */
197
+ title(): string;
198
+ /** ISO 8601 timestamp of the last change. */
199
+ modifiedAt(): string;
200
+ /**
201
+ * Where the agent is actually working, as `file://` URIs.
202
+ *
203
+ * Asked rather than assumed: the host knows what directory it was started
204
+ * in and a session may have been created in another, so a host that
205
+ * answered with its own reported the wrong one for exactly the sessions
206
+ * somebody chose a directory for.
207
+ */
208
+ workingDirectories(): string[];
209
+ /** The session channel's state, for a subscription snapshot. */
210
+ sessionState(): Bag;
211
+ /** The chat channel's state, for a subscription snapshot. */
212
+ chatState(): Bag;
213
+ /**
214
+ * Run one command as a turn of this chat's, without asking the agent.
215
+ *
216
+ * What the composer's `!` prefix means: the person typed a command rather
217
+ * than a question, and the answer is a shell's. The turn is still the
218
+ * chat's - a host that emitted one this session did not know about would
219
+ * serve a snapshot without it the moment anybody re-subscribed - so the
220
+ * session opens it, reports the tool call, and closes it when `run`
221
+ * settles.
222
+ *
223
+ * `run` is the host's half: it is handed the id of the tool call this turn
224
+ * is about and answers with what happened. The terminal is the host's
225
+ * because the shell is - a session has no port to spawn one through - and
226
+ * naming it back is what lets a client watch the output arrive rather than
227
+ * only read it afterwards.
228
+ *
229
+ * Optional. A backend that leaves it out is one this host advertises no
230
+ * `terminalCommandPrefix` for, which is the protocol's own way of saying the
231
+ * shorthand is unavailable.
232
+ */
233
+ ran?(turnId: string, command: string, run: (toolCallId: string) => Promise<Ran>): void;
234
+ /**
235
+ * Put a message into the turn that is already running.
236
+ *
237
+ * Steering, in the protocol's word: somebody correcting an agent halfway
238
+ * rather than waiting for it to finish doing the thing they are trying to
239
+ * stop. Answers whether there was a turn to steer - a chat with nothing
240
+ * running has nothing to inject into, and the caller says so rather than
241
+ * quietly turning it into an ordinary message.
242
+ *
243
+ * Optional. A backend that cannot take a message mid-turn leaves it out,
244
+ * and this host refuses steering for that backend with that as the reason.
245
+ */
246
+ steer?(id: string, text: string): boolean;
247
+ /** Start a turn with what the person said, optionally naming a model. */
248
+ begin(turnId: string, text: string, model?: Chosen): void;
249
+ /**
250
+ * Run the latest turn again, without adding a message.
251
+ *
252
+ * What `chat/turnResume` asks for: the turn errored, its message and its
253
+ * parts are intact, and the client wants the same prompt tried again rather
254
+ * than typed again. Answers whether there was such a turn to resume.
255
+ *
256
+ * Optional. A backend that cannot re-run a turn leaves it out, and the host
257
+ * refuses the action with that as the reason.
258
+ */
259
+ resume?(turnId: string): boolean;
260
+ /** Stop the running turn, and answer anything it was blocked on. */
261
+ cancel(turnId: string): void;
262
+ /**
263
+ * Hold a message, and make it the next turn when the running one ends.
264
+ *
265
+ * The queue is the session's, not a client's: a client that held a message
266
+ * would be the only thing that could ever send it, and nothing in a client
267
+ * watches for a turn to end. The same `id` twice edits what is waiting.
268
+ */
269
+ queue(id: string, text: string, model?: Chosen): void;
270
+ /** Take one back, while it is still waiting. */
271
+ unqueue(id: string): void;
272
+ /**
273
+ * What somebody is part-way through typing.
274
+ *
275
+ * Held by the session so two people on one chat see each other's - a client
276
+ * that kept its own would need nothing from a host for this.
277
+ */
278
+ setDraft(draft: Bag | undefined): void;
279
+ /** Reorder what is waiting. Anything not named keeps its place behind what is. */
280
+ reorder(order: string[]): void;
281
+ /** Answer a tool call the agent is waiting on. */
282
+ confirm(toolCallId: string, approved: boolean): void;
283
+ /**
284
+ * Replace the tools this session offers the model.
285
+ *
286
+ * The host's own are fixed at creation; a client's come and go with the
287
+ * client, which is what this is for. Replaces rather than merges, because
288
+ * a tool taken away has to be able to go.
289
+ *
290
+ * False when the backend could not re-declare them - a session whose agent
291
+ * has gone, or one whose backend cannot change its tools once it is running.
292
+ *
293
+ * Optional. A backend that leaves it out is one this host offers no
294
+ * client-provided tools through, and it says so rather than accepting an
295
+ * announcement it will not act on.
296
+ */
297
+ setTools?(tools: BoundTool[]): Promise<boolean>;
298
+ /**
299
+ * The client running a tool call, for a call that is one client's to run.
300
+ *
301
+ * Nothing for a call the agent is running itself, which is what makes this
302
+ * the check for whether a client may write into one: the protocol says a
303
+ * host should refuse `chat/toolCallContentChanged` from anybody but the
304
+ * call's own contributor.
305
+ */
306
+ toolCallOwner?(toolCallId: string): string | undefined;
307
+ /**
308
+ * What a client says one of its own tool calls did.
309
+ *
310
+ * False when no call by that id is waiting, or when it is waiting on a
311
+ * different client - both are a client out of step rather than a no-op, and
312
+ * the host refuses rather than dropping it.
313
+ */
314
+ completeToolCall?(toolCallId: string, clientId: string, result: {
315
+ text: string;
316
+ ok: boolean;
317
+ }): boolean;
318
+ /**
319
+ * A client that was running tool calls here has gone.
320
+ *
321
+ * Its outstanding calls are failed rather than left open: the agent is
322
+ * waiting on a promise that nothing can settle any more, and a turn that
323
+ * hangs for ever is worse than a tool that says it could not run.
324
+ */
325
+ clientGone?(clientId: string): void;
326
+ /** Answer a question the agent asked, keyed by question id. */
327
+ answer(requestId: string, accepted: boolean, answers: Bag): void;
328
+ /**
329
+ * One question of an open request, as somebody types the answer.
330
+ *
331
+ * The protocol calls the result the request's synced answer state, and it is
332
+ * what a `chat/inputCompleted` carrying no answers of its own is completed
333
+ * with. Held by the session for the same reason a draft message is: two
334
+ * people on one chat are answering one form.
335
+ *
336
+ * False when nothing here is waiting on that request, or when what is
337
+ * waiting is a tool confirmation rather than a question.
338
+ *
339
+ * Optional. A backend that keeps no drafts leaves it out, and the host
340
+ * refuses the action with that as the reason.
341
+ */
342
+ setAnswer?(requestId: string, questionId: string, answer: Bag | undefined): boolean;
343
+ /**
344
+ * Take one config value, or say why not.
345
+ *
346
+ * Every key a client sets goes through here, including the ones a backend
347
+ * advertises in its own schema: the host reads that schema for how a key
348
+ * behaves - whether it can move on a running session, whether it belongs to
349
+ * the session or to one chat - and knows nothing about what any key means.
350
+ *
351
+ * `true` when it was taken. A string is the refusal, in the backend's own
352
+ * words, and it is a string rather than `false` because only the backend
353
+ * knows which of the two things went wrong: a key it does not serve, or a
354
+ * value it will not take for a key it does. A host that answered both with
355
+ * one sentence would be telling a client its control does not exist when
356
+ * the truth is that the value was wrong.
357
+ */
358
+ setConfig?(key: string, value: unknown): true | string | Promise<true | string>;
359
+ /** The config in force, by key. */
360
+ settings(): Record<string, unknown>;
361
+ /**
362
+ * Turn a customization on or off. False when this backend cannot.
363
+ *
364
+ * False is a real answer and the one to give for anything with no runtime
365
+ * switch: a control that reports success and changes nothing is worse than
366
+ * one that refuses.
367
+ */
368
+ setCustomizationEnabled(id: string, enabled: boolean): Promise<boolean>;
369
+ /** Start an MCP server, which is also how one that needs signing into is. */
370
+ startMcpServer(id: string): Promise<boolean>;
371
+ /** Stop one. */
372
+ stopMcpServer(id: string): Promise<boolean>;
373
+ /**
374
+ * A token for one of this session's MCP servers, as the client signed in.
375
+ *
376
+ * Answers whether the server it names is one of this session's. The token
377
+ * becomes that server's `Authorization` header and the server is asked to
378
+ * connect again; nothing else in the session is told.
379
+ *
380
+ * Optional: a backend that cannot re-declare a server leaves it out, and the
381
+ * host then advertises no resource for one to be signed into.
382
+ */
383
+ authenticated?(resource: string, token: string): Promise<boolean>;
384
+ /**
385
+ * The OAuth resources this session's MCP servers need signing into.
386
+ *
387
+ * What `authenticate` is checked against: the protocol says a client's
388
+ * `resource` MUST match one the server advertised, and these are advertised
389
+ * on the servers' own `authRequired` states.
390
+ */
391
+ awaiting?(): string[];
392
+ /** End the session and stop its agent. */
393
+ close(): void;
394
+ }
395
+ //# sourceMappingURL=session.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"session.d.ts","sourceRoot":"","sources":["../../src/types/session.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ /** One agent session: its lifecycle, its turns, and what it is waiting for. */
2
+ export {};
3
+ //# sourceMappingURL=session.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"session.js","sourceRoot":"","sources":["../../src/types/session.ts"],"names":[],"mappings":"AAAA,+EAA+E"}
@@ -0,0 +1,131 @@
1
+ /** A shell on the host machine, as a terminal channel. */
2
+ import type { TerminalClaim, TerminalLifecycleState, TerminalState } from '@microsoft/agent-host-protocol';
3
+ import type { OnWire } from './wire.js';
4
+ import type { Emit } from './session.js';
5
+ /** Who currently holds a terminal: a connected client, or a session. */
6
+ /**
7
+ * Who is holding a terminal, in the protocol's own type.
8
+ *
9
+ * A client, or a session and the chat inside it. Was `Bag`, which meant a
10
+ * claim missing the fields its own kind requires compiled perfectly.
11
+ */
12
+ export type Claim = OnWire<TerminalClaim>;
13
+ /** How to start one. */
14
+ export interface TerminalOptions {
15
+ /** The terminal channel URI, chosen by the client that asked for it. */
16
+ uri: string;
17
+ /** The directory it starts in. Already checked against what the host serves. */
18
+ cwd: string;
19
+ /** Who is holding it. */
20
+ claim: Claim;
21
+ /** Display name. The shell's own if none is given. */
22
+ name?: string;
23
+ /**
24
+ * The shell to run, absolute. The store's own choice if none is given.
25
+ *
26
+ * A connected client pushes this: VS Code sends `defaultShell` on the root
27
+ * channel out of `terminal.integrated.agentHostProfile.<os>`, because the
28
+ * shell somebody wants a host-managed terminal to open is a preference of
29
+ * theirs rather than a fact about the machine.
30
+ */
31
+ shell?: string;
32
+ /**
33
+ * One command to run instead of a shell to sit in.
34
+ *
35
+ * The terminal runs it and exits, so `terminal/exited` is what says the
36
+ * command finished and its code is what says how. Without this the shell
37
+ * reads from a pipe and stays open, which is right for a terminal somebody
38
+ * is typing into and wrong for one opened to answer a single question -
39
+ * there is no shell integration here to tell where one command ends.
40
+ */
41
+ command?: string;
42
+ /** Width in columns, as the client draws it. */
43
+ cols?: number;
44
+ /** Height in rows. */
45
+ rows?: number;
46
+ /** Where state actions go. The host routes them to the terminal's channel. */
47
+ emit: Emit;
48
+ }
49
+ /** A running terminal. */
50
+ export interface Terminal {
51
+ /** Its channel URI. */
52
+ readonly uri: string;
53
+ /** Display title. */
54
+ title(): string;
55
+ /** Who is holding it. */
56
+ claim(): Claim;
57
+ /** The process's exit code, once it has one. Undefined while it runs. */
58
+ exitCode(): number | undefined;
59
+ /**
60
+ * Running, or exited and with what.
61
+ *
62
+ * 0.9.0 moved the exit code in here and made this required, so a terminal
63
+ * described without it is a terminal a client cannot ask about. `exitCode`
64
+ * above stays for the versions this host still negotiates down to.
65
+ */
66
+ lifecycle(): OnWire<TerminalLifecycleState>;
67
+ /** The channel's state, for a subscription snapshot. */
68
+ /**
69
+ * The terminal channel's snapshot, in the protocol's own type.
70
+ *
71
+ * Typed against the package rather than as a `Bag`, which is the point:
72
+ * `Bag` is why 0.9.0 moved the exit code inside `lifecycle` and this host
73
+ * went on sending the old shape with a clean compile. A field removed or
74
+ * renamed upstream is a type error here now, at the one place the payload
75
+ * is built.
76
+ *
77
+ * The intersection is the deliberate part. This host negotiates down to
78
+ * 0.5.1 and every version before 0.9.0 reads a flat `exitCode`, so it sends
79
+ * both - and saying so in the type is the difference between a divergence
80
+ * somebody chose and one nobody noticed.
81
+ */
82
+ state(): OnWire<TerminalState> & {
83
+ exitCode?: number;
84
+ };
85
+ /** Send input. Ignored once the process has exited. */
86
+ write(data: string): void;
87
+ /** Record a new size. Nothing is signalled: there is no pseudoterminal. */
88
+ resize(cols: number, rows: number): void;
89
+ /**
90
+ * Throw away the scrollback, keeping everything else.
91
+ *
92
+ * The size, the title and the claim survive: a client clears a terminal to
93
+ * stop reading what is already there, not to give it up. Nothing reaches
94
+ * the process - there is no pseudoterminal to send anything to, and a shell
95
+ * has no notion of its own output having been discarded.
96
+ */
97
+ clear(): void;
98
+ /** Rename it. */
99
+ setTitle(title: string): void;
100
+ /** Hand it to somebody else. */
101
+ setClaim(claim: Claim): void;
102
+ /** Kill the process and let go. */
103
+ close(): void;
104
+ }
105
+ /**
106
+ * A pseudoterminal, as this host needs one.
107
+ *
108
+ * Handed in rather than imported: a PTY is a native binding, and a library
109
+ * that depended on one would not load under a runtime it was not built for.
110
+ * The daemon passes `node-pty` when it has it; a host on another runtime
111
+ * passes its own, and one that passes none keeps pipes and says `isPty: false`.
112
+ */
113
+ export interface Pty {
114
+ /** Everything the terminal writes, VT sequences included. */
115
+ onData(listen: (data: string) => void): void;
116
+ /** Called once, when the process goes. */
117
+ onExit(listen: (exit: {
118
+ exitCode: number;
119
+ }) => void): void;
120
+ write(data: string): void;
121
+ resize(cols: number, rows: number): void;
122
+ kill(signal?: string): void;
123
+ }
124
+ /** Start one. The shape `node-pty`'s own `spawn` already has. */
125
+ export type SpawnPty = (file: string, args: string[], options: {
126
+ cwd?: string;
127
+ cols: number;
128
+ rows: number;
129
+ env: Record<string, string | undefined>;
130
+ }) => Pty;
131
+ //# sourceMappingURL=terminals.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"terminals.d.ts","sourceRoot":"","sources":["../../src/types/terminals.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ /** A shell on the host machine, as a terminal channel. */
2
+ export {};
3
+ //# sourceMappingURL=terminals.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"terminals.js","sourceRoot":"","sources":["../../src/types/terminals.ts"],"names":[],"mappings":"AAAA,0DAA0D"}
@@ -0,0 +1,62 @@
1
+ /** The protocol's own shapes, as they actually go down the socket. */
2
+ import type { Bag } from './common.js';
3
+ /**
4
+ * Why this exists at all.
5
+ *
6
+ * Every payload this host builds used to be a `Bag`, and that is how 0.9.0
7
+ * moved a terminal's exit code inside `lifecycle`, removed `Turn.error` and
8
+ * required an `ErrorInfo` on a failed MCP server without a single compile
9
+ * error here. Three shape defects in one afternoon's audit, each one a client
10
+ * behaving correctly and getting it wrong. Typing the construction sites
11
+ * against the package turns the next one into a build failure.
12
+ *
13
+ * The conversion is needed because the protocol types its discriminants as
14
+ * `const enum`, and this project compiles with `verbatimModuleSyntax`, which
15
+ * refuses to import an ambient const enum as a value. That is not a problem
16
+ * worth casting past: what travels on the wire *is* the string, and
17
+ * `` `${SomeEnum}` `` is the set of strings that enum can be - checked, so a
18
+ * value renamed upstream stops matching here exactly as a field would.
19
+ */
20
+ /** One value, with string enums widened to the strings they are. */
21
+ type WireValue<V> = V extends (...args: never[]) => unknown ? V : V extends string ? `${V}` : V extends readonly (infer E)[] ? WireValue<E>[] : V extends object ? OnWire<V> : V;
22
+ /**
23
+ * A protocol shape as this host builds it.
24
+ *
25
+ * Optional keys stay optional, which matters under `exactOptionalPropertyTypes`:
26
+ * a field the protocol allows to be absent must not become one that has to be
27
+ * present and `undefined`.
28
+ */
29
+ export type OnWire<T> = {
30
+ [K in keyof T]: WireValue<T[K]>;
31
+ };
32
+ /**
33
+ * A turn, whose parts are checked where they are built rather than here.
34
+ *
35
+ * `responseParts` is seven kinds and an eight-state tool call, assembled piece
36
+ * by piece as an agent talks - so the array cannot carry a union the way a
37
+ * finished value can: a call is `running` when it is pushed and `completed`
38
+ * three frames later, and a variable declared as either fights the other.
39
+ *
40
+ * The gap this used to leave is where the worst of it hid. A rebuilt
41
+ * transcript wrote a tool-call `status` that is not one of the seven, left off
42
+ * three fields the completed state requires, and gave its content blocks no
43
+ * `type` - four defects in one object, none of them a compile error, and every
44
+ * one of them a conversation that would not draw. So each part is now checked
45
+ * against the state it claims, at the moment it is built, with `satisfies` on
46
+ * the literal; what stays loose here is only the mutation that follows.
47
+ */
48
+ export type WireTurn<T> = Omit<OnWire<T>, 'responseParts'> & {
49
+ responseParts: Bag[];
50
+ };
51
+ export {};
52
+ /**
53
+ * On `satisfies` rather than annotation, where you see it.
54
+ *
55
+ * A turn is built as an `ActiveTurn` and then *mutated* into a `Turn` - a
56
+ * state and a duration are set on the same object when it ends. Declaring the
57
+ * variable as either one fights the other, so the literal is checked with
58
+ * `satisfies` at the moment it is built and the variable stays a `Bag` for the
59
+ * mutation that follows. The construction is what the protocol changes under,
60
+ * and the construction is what is checked.
61
+ */
62
+ //# sourceMappingURL=wire.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"wire.d.ts","sourceRoot":"","sources":["../../src/types/wire.ts"],"names":[],"mappings":"AAAA,sEAAsE;AAEtE,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,aAAa,CAAC;AAEvC;;;;;;;;;;;;;;;;GAgBG;AAEH,oEAAoE;AACpE,KAAK,SAAS,CAAC,CAAC,IAGd,CAAC,SAAS,CAAC,GAAG,IAAI,EAAE,KAAK,EAAE,KAAK,OAAO,GAAG,CAAC,GACvC,CAAC,SAAS,MAAM,GAAG,GAAG,CAAC,EAAE,GACvB,CAAC,SAAS,SAAS,CAAC,MAAM,CAAC,CAAC,EAAE,GAAG,SAAS,CAAC,CAAC,CAAC,EAAE,GAC7C,CAAC,SAAS,MAAM,GAAG,MAAM,CAAC,CAAC,CAAC,GAC1B,CAAC,CAAC;AAEd;;;;;;GAMG;AACH,MAAM,MAAM,MAAM,CAAC,CAAC,IAAI;KAAG,CAAC,IAAI,MAAM,CAAC,GAAG,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;CAAE,CAAC;AAE5D;;;;;;;;;;;;;;;GAeG;AACH,MAAM,MAAM,QAAQ,CAAC,CAAC,IAAI,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,eAAe,CAAC,GAAG;IAAE,aAAa,EAAE,GAAG,EAAE,CAAA;CAAE,CAAC;;AAEtF;;;;;;;;;GASG"}
@@ -0,0 +1,13 @@
1
+ /** The protocol's own shapes, as they actually go down the socket. */
2
+ export {};
3
+ /**
4
+ * On `satisfies` rather than annotation, where you see it.
5
+ *
6
+ * A turn is built as an `ActiveTurn` and then *mutated* into a `Turn` - a
7
+ * state and a duration are set on the same object when it ends. Declaring the
8
+ * variable as either one fights the other, so the literal is checked with
9
+ * `satisfies` at the moment it is built and the variable stays a `Bag` for the
10
+ * mutation that follows. The construction is what the protocol changes under,
11
+ * and the construction is what is checked.
12
+ */
13
+ //# sourceMappingURL=wire.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"wire.js","sourceRoot":"","sources":["../../src/types/wire.ts"],"names":[],"mappings":"AAAA,sEAAsE;;AA2DtE;;;;;;;;;GASG"}