@airterm/protocol 0.4.0 → 0.6.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 +22 -2
- package/dist/acp-agents.d.ts +66 -0
- package/dist/acp-agents.d.ts.map +1 -0
- package/dist/acp-agents.js +141 -0
- package/dist/acp-agents.js.map +1 -0
- package/dist/acp-middleware.d.ts +426 -0
- package/dist/acp-middleware.d.ts.map +1 -0
- package/dist/acp-middleware.js +626 -0
- package/dist/acp-middleware.js.map +1 -0
- package/dist/framing.d.ts +24 -1
- package/dist/framing.d.ts.map +1 -1
- package/dist/framing.js +23 -0
- package/dist/framing.js.map +1 -1
- package/dist/index.d.ts +6 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +5 -1
- package/dist/index.js.map +1 -1
- package/dist/messages.d.ts +131 -1
- package/dist/messages.d.ts.map +1 -1
- package/dist/messages.js +272 -0
- package/dist/messages.js.map +1 -1
- package/dist/relay-usage.d.ts.map +1 -1
- package/dist/relay-usage.js +4 -1
- package/dist/relay-usage.js.map +1 -1
- package/dist/sharing.d.ts +42 -0
- package/dist/sharing.d.ts.map +1 -0
- package/dist/sharing.js +87 -0
- package/dist/sharing.js.map +1 -0
- package/dist/shellIntegration.d.ts +116 -0
- package/dist/shellIntegration.d.ts.map +1 -0
- package/dist/shellIntegration.js +243 -0
- package/dist/shellIntegration.js.map +1 -0
- package/package.json +1 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"acp-middleware.d.ts","sourceRoot":"","sources":["../src/acp-middleware.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,626 @@
|
|
|
1
|
+
/** Provider-neutral ACP messages exchanged across AirTerm's encrypted transport. */
|
|
2
|
+
export const ACP_MIDDLEWARE_VERSION = 4;
|
|
3
|
+
export const ACP_MIDDLEWARE_FEATURE = 'acp-middleware-v4';
|
|
4
|
+
export const ACP_MIDDLEWARE_MAX_COMMAND_BYTES = 48 * 1024;
|
|
5
|
+
export const ACP_MIDDLEWARE_MAX_EVENT_BYTES = 48 * 1024;
|
|
6
|
+
export const ACP_MIDDLEWARE_MAX_MUTATIONS = 64;
|
|
7
|
+
export const ACP_MIDDLEWARE_MAX_SNAPSHOT_BYTES = 2 * 1024 * 1024;
|
|
8
|
+
export const ACP_MIDDLEWARE_MAX_SNAPSHOT_CHUNKS = 128;
|
|
9
|
+
export const ACP_MIDDLEWARE_MAX_SNAPSHOT_MUTATIONS = 4096;
|
|
10
|
+
export const ACP_MIDDLEWARE_MAX_TEXT_BYTES = 256 * 1024;
|
|
11
|
+
/** How many attachment paths one prompt may carry. */
|
|
12
|
+
export const ACP_MIDDLEWARE_MAX_PROMPT_FILES = 10;
|
|
13
|
+
/** A path is a host path, bounded the same way every other one is. */
|
|
14
|
+
export const ACP_MIDDLEWARE_MAX_PATH_BYTES = 4096;
|
|
15
|
+
export const ACP_MIDDLEWARE_MAX_TURNS = 50;
|
|
16
|
+
export const ACP_MIDDLEWARE_MAX_HISTORY_BYTES = 1 * 1024 * 1024;
|
|
17
|
+
export const ACP_MIDDLEWARE_MAX_ACTIVE_TURN_BYTES = 1 * 1024 * 1024;
|
|
18
|
+
export const ACP_MIDDLEWARE_MAX_PENDING_REQUESTS = 16;
|
|
19
|
+
export const ACP_MIDDLEWARE_MAX_PENDING_BYTES = 512 * 1024;
|
|
20
|
+
export const ACP_MIDDLEWARE_MAX_REASONING_BYTES = 256 * 1024;
|
|
21
|
+
export const ACP_MIDDLEWARE_MAX_CONFIG_OPTIONS = 64;
|
|
22
|
+
export const ACP_MIDDLEWARE_MAX_CONFIG_CHOICES = 255;
|
|
23
|
+
export const ACP_MIDDLEWARE_MAX_COMMANDS = 128;
|
|
24
|
+
export const ACP_MIDDLEWARE_MAX_COMMAND_NAME_BYTES = 128;
|
|
25
|
+
export const ACP_MIDDLEWARE_MAX_COMMAND_DESCRIPTION_BYTES = 256;
|
|
26
|
+
export const ACP_MIDDLEWARE_MAX_COMMAND_HINT_BYTES = 128;
|
|
27
|
+
/**
|
|
28
|
+
* Bounds on an agent's plan.
|
|
29
|
+
*
|
|
30
|
+
* A plan is display-only content an agent may rewrite as often as it likes, so
|
|
31
|
+
* every part of it is bounded here rather than at the point a pane happens to
|
|
32
|
+
* render it: the identifier an update is correlated by, how many entries an item
|
|
33
|
+
* plan may show, how long each entry may be, and how much markdown a markdown
|
|
34
|
+
* plan may carry. A plan that exceeds a bound is truncated by its producer with a
|
|
35
|
+
* marker saying so, never silently cut.
|
|
36
|
+
*/
|
|
37
|
+
export const ACP_MIDDLEWARE_MAX_PLAN_ID_BYTES = 128;
|
|
38
|
+
export const ACP_MIDDLEWARE_MAX_PLAN_ITEMS = 32;
|
|
39
|
+
export const ACP_MIDDLEWARE_MAX_PLAN_ITEM_BYTES = 512;
|
|
40
|
+
export const ACP_MIDDLEWARE_MAX_PLAN_MARKDOWN_BYTES = 24 * 1024;
|
|
41
|
+
/** How many plans one turn may carry at once, newest kept. */
|
|
42
|
+
export const ACP_MIDDLEWARE_MAX_PLANS_PER_TURN = 8;
|
|
43
|
+
const encoder = new TextEncoder();
|
|
44
|
+
const decoder = new TextDecoder();
|
|
45
|
+
export function createAcpCanonicalState(agent = '', capabilities = {}) {
|
|
46
|
+
return {
|
|
47
|
+
version: ACP_MIDDLEWARE_VERSION,
|
|
48
|
+
phase: 'starting',
|
|
49
|
+
agent,
|
|
50
|
+
capabilities: {
|
|
51
|
+
resume: capabilities.resume === true,
|
|
52
|
+
load: capabilities.load === true,
|
|
53
|
+
cancel: capabilities.cancel !== false,
|
|
54
|
+
configuration: capabilities.configuration === true,
|
|
55
|
+
permissions: capabilities.permissions === true,
|
|
56
|
+
elicitation: capabilities.elicitation === true,
|
|
57
|
+
},
|
|
58
|
+
configOptions: [],
|
|
59
|
+
commands: [],
|
|
60
|
+
turns: [],
|
|
61
|
+
interactions: [],
|
|
62
|
+
notices: [],
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
export function isAcpGenerating(state) {
|
|
66
|
+
return state.activeTurnId !== undefined && state.turns.some((turn) => turn.id === state.activeTurnId && turn.status === 'active');
|
|
67
|
+
}
|
|
68
|
+
/** Pure reducer used by the CLI authority and the browser projection. */
|
|
69
|
+
export function reduceAcpCanonicalState(state, mutation) {
|
|
70
|
+
const next = { ...state };
|
|
71
|
+
switch (mutation.type) {
|
|
72
|
+
case 'session':
|
|
73
|
+
next.phase = mutation.phase;
|
|
74
|
+
if (mutation.sessionId !== undefined)
|
|
75
|
+
next.sessionId = mutation.sessionId;
|
|
76
|
+
if (mutation.title !== undefined)
|
|
77
|
+
next.title = mutation.title;
|
|
78
|
+
if (mutation.error === undefined)
|
|
79
|
+
delete next.error;
|
|
80
|
+
else
|
|
81
|
+
next.error = mutation.error;
|
|
82
|
+
return next;
|
|
83
|
+
case 'history-boundary':
|
|
84
|
+
next.historyBoundary = mutation.boundary;
|
|
85
|
+
return next;
|
|
86
|
+
case 'turn-start':
|
|
87
|
+
{
|
|
88
|
+
const existing = state.turns.find((turn) => turn.id === mutation.turnId);
|
|
89
|
+
if (existing !== undefined) {
|
|
90
|
+
if (existing.origin !== mutation.origin)
|
|
91
|
+
return state;
|
|
92
|
+
next.turns = state.turns.map((turn) => turn.id === mutation.turnId && turn.userText === undefined && mutation.userText !== undefined
|
|
93
|
+
? { ...turn, userText: mutation.userText }
|
|
94
|
+
: turn);
|
|
95
|
+
}
|
|
96
|
+
else {
|
|
97
|
+
next.turns = [...state.turns, {
|
|
98
|
+
id: mutation.turnId,
|
|
99
|
+
origin: mutation.origin,
|
|
100
|
+
...(mutation.userText === undefined ? {} : { userText: mutation.userText }),
|
|
101
|
+
items: [],
|
|
102
|
+
status: mutation.origin === 'user' ? 'active' : 'complete',
|
|
103
|
+
}];
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
if (mutation.origin === 'user')
|
|
107
|
+
next.activeTurnId = mutation.turnId;
|
|
108
|
+
return next;
|
|
109
|
+
case 'turn-user-append': {
|
|
110
|
+
const turn = state.turns.find((item) => item.id === mutation.turnId);
|
|
111
|
+
if (turn === undefined || turn.status !== 'active' || turn.origin !== 'user')
|
|
112
|
+
return state;
|
|
113
|
+
next.turns = state.turns.map((item) => item.id === turn.id ? { ...item, userText: (item.userText ?? '') + mutation.text } : item);
|
|
114
|
+
return next;
|
|
115
|
+
}
|
|
116
|
+
case 'message-append': {
|
|
117
|
+
const turn = state.turns.find((item) => item.id === mutation.turnId);
|
|
118
|
+
if (turn === undefined)
|
|
119
|
+
return state;
|
|
120
|
+
const found = turn.items.find((item) => item.kind === 'message' && item.id === mutation.messageId);
|
|
121
|
+
const items = found === undefined
|
|
122
|
+
? [...turn.items, { kind: 'message', id: mutation.messageId, role: mutation.role, text: mutation.text }]
|
|
123
|
+
: turn.items.map((item) => item.kind === 'message' && item.id === mutation.messageId ? { ...item, text: item.text + mutation.text } : item);
|
|
124
|
+
next.turns = state.turns.map((item) => item.id === turn.id ? { ...item, items } : item);
|
|
125
|
+
return next;
|
|
126
|
+
}
|
|
127
|
+
case 'tool-upsert': {
|
|
128
|
+
const turn = state.turns.find((item) => item.id === mutation.turnId);
|
|
129
|
+
if (turn === undefined)
|
|
130
|
+
return state;
|
|
131
|
+
const found = turn.items.some((item) => item.kind === 'tool' && item.tool.id === mutation.tool.id);
|
|
132
|
+
const items = found
|
|
133
|
+
? turn.items.map((item) => item.kind === 'tool' && item.tool.id === mutation.tool.id ? { kind: 'tool', tool: mutation.tool } : item)
|
|
134
|
+
: [...turn.items, { kind: 'tool', tool: mutation.tool }];
|
|
135
|
+
next.turns = state.turns.map((item) => item.id === turn.id ? { ...item, items } : item);
|
|
136
|
+
return next;
|
|
137
|
+
}
|
|
138
|
+
case 'omission-append': {
|
|
139
|
+
const turn = state.turns.find((item) => item.id === mutation.turnId);
|
|
140
|
+
if (turn === undefined)
|
|
141
|
+
return state;
|
|
142
|
+
if (turn.items.some((item) => item.kind === 'omission' && item.id === mutation.omissionId))
|
|
143
|
+
return state;
|
|
144
|
+
const items = [...turn.items, { kind: 'omission', id: mutation.omissionId, reason: mutation.reason }];
|
|
145
|
+
next.turns = state.turns.map((item) => item.id === turn.id ? { ...item, items } : item);
|
|
146
|
+
return next;
|
|
147
|
+
}
|
|
148
|
+
case 'plan-upsert': {
|
|
149
|
+
const turn = state.turns.find((item) => item.id === mutation.turnId);
|
|
150
|
+
if (turn === undefined)
|
|
151
|
+
return state;
|
|
152
|
+
const plans = turn.plans ?? [];
|
|
153
|
+
// An update to a plan already held replaces it where it sits, so a
|
|
154
|
+
// revision cannot reshuffle the cards the reader is looking at. A new
|
|
155
|
+
// plan goes on the end, and the oldest is dropped past the bound.
|
|
156
|
+
const merged = plans.some((plan) => plan.id === mutation.plan.id)
|
|
157
|
+
? plans.map((plan) => (plan.id === mutation.plan.id ? mutation.plan : plan))
|
|
158
|
+
: [...plans, mutation.plan].slice(-ACP_MIDDLEWARE_MAX_PLANS_PER_TURN);
|
|
159
|
+
next.turns = state.turns.map((item) => item.id === turn.id ? { ...item, plans: merged } : item);
|
|
160
|
+
return next;
|
|
161
|
+
}
|
|
162
|
+
case 'plan-remove': {
|
|
163
|
+
const turn = state.turns.find((item) => item.id === mutation.turnId);
|
|
164
|
+
if (turn === undefined || turn.plans === undefined)
|
|
165
|
+
return state;
|
|
166
|
+
const plans = turn.plans.filter((plan) => plan.id !== mutation.planId);
|
|
167
|
+
if (plans.length === turn.plans.length)
|
|
168
|
+
return state;
|
|
169
|
+
next.turns = state.turns.map((item) => item.id === turn.id ? { ...item, plans } : item);
|
|
170
|
+
return next;
|
|
171
|
+
}
|
|
172
|
+
case 'turn-finish':
|
|
173
|
+
next.turns = state.turns.map((turn) => {
|
|
174
|
+
if (turn.id !== mutation.turnId)
|
|
175
|
+
return turn;
|
|
176
|
+
return mutation.stopReason === undefined
|
|
177
|
+
? { ...turn, status: mutation.status }
|
|
178
|
+
: { ...turn, status: mutation.status, stopReason: mutation.stopReason };
|
|
179
|
+
});
|
|
180
|
+
if (next.activeTurnId === mutation.turnId)
|
|
181
|
+
delete next.activeTurnId;
|
|
182
|
+
return next;
|
|
183
|
+
case 'config':
|
|
184
|
+
next.configOptions = mutation.options;
|
|
185
|
+
if (mutation.model === undefined)
|
|
186
|
+
delete next.currentModel;
|
|
187
|
+
else
|
|
188
|
+
next.currentModel = mutation.model;
|
|
189
|
+
return next;
|
|
190
|
+
case 'mode':
|
|
191
|
+
if (mutation.mode === undefined)
|
|
192
|
+
delete next.mode;
|
|
193
|
+
else
|
|
194
|
+
next.mode = mutation.mode;
|
|
195
|
+
return next;
|
|
196
|
+
case 'commands':
|
|
197
|
+
next.commands = mutation.commands;
|
|
198
|
+
return next;
|
|
199
|
+
case 'usage':
|
|
200
|
+
next.usage = { used: mutation.used, size: mutation.size, ...(mutation.cost === undefined ? {} : { cost: mutation.cost }), ...(mutation.currency === undefined ? {} : { currency: mutation.currency }) };
|
|
201
|
+
return next;
|
|
202
|
+
case 'interaction-upsert':
|
|
203
|
+
next.interactions = state.interactions.some((item) => item.id === mutation.interaction.id) ? state.interactions.map((item) => item.id === mutation.interaction.id ? mutation.interaction : item) : [...state.interactions, mutation.interaction];
|
|
204
|
+
return next;
|
|
205
|
+
case 'interaction-remove':
|
|
206
|
+
next.interactions = state.interactions.filter((item) => item.id !== mutation.interactionId);
|
|
207
|
+
return next;
|
|
208
|
+
case 'notice':
|
|
209
|
+
next.notices = state.notices.some((item) => item.id === mutation.notice.id) ? state.notices.map((item) => item.id === mutation.notice.id ? mutation.notice : item) : [...state.notices, mutation.notice];
|
|
210
|
+
return next;
|
|
211
|
+
case 'notice-remove':
|
|
212
|
+
next.notices = state.notices.filter((item) => item.id !== mutation.noticeId);
|
|
213
|
+
return next;
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
function record(value) {
|
|
217
|
+
return typeof value === 'object' && value !== null && !Array.isArray(value);
|
|
218
|
+
}
|
|
219
|
+
/**
|
|
220
|
+
* Cuts text to a byte budget without splitting a character.
|
|
221
|
+
*
|
|
222
|
+
* Every bound in this file is a UTF-8 byte count, but a JavaScript `slice`
|
|
223
|
+
* counts UTF-16 code units - so a producer that truncated by character count
|
|
224
|
+
* could emit a title or a message whose bytes exceed the bound the decoder
|
|
225
|
+
* enforces. The decoder would then reject the whole mutation, and because a
|
|
226
|
+
* mutation is validated as a unit, one over-long field would take the entire
|
|
227
|
+
* state restore with it. Truncating by bytes is what keeps a producer's own
|
|
228
|
+
* bound and the decoder's bound the same number.
|
|
229
|
+
*/
|
|
230
|
+
export function truncateUtf8(text, maximum) {
|
|
231
|
+
if (maximum <= 0)
|
|
232
|
+
return '';
|
|
233
|
+
// Every UTF-16 code unit encodes to at least one UTF-8 byte, so nothing
|
|
234
|
+
// beyond `maximum` code units can fit. Slicing first keeps a large string
|
|
235
|
+
// from being encoded in full only to keep a short prefix of it.
|
|
236
|
+
const candidate = text.length > maximum ? text.slice(0, maximum) : text;
|
|
237
|
+
const bytes = encoder.encode(candidate);
|
|
238
|
+
if (bytes.byteLength <= maximum)
|
|
239
|
+
return candidate;
|
|
240
|
+
// Walk back to a character boundary: decoding a sequence cut mid-character
|
|
241
|
+
// would yield U+FFFD, whose own byte length is not the one that was cut.
|
|
242
|
+
let end = maximum;
|
|
243
|
+
while (end > 0 && (bytes[end] & 0xc0) === 0x80)
|
|
244
|
+
end -= 1;
|
|
245
|
+
return decoder.decode(bytes.subarray(0, end));
|
|
246
|
+
}
|
|
247
|
+
/** Reads text a byte-bounded field can hold, or nothing when it holds none. */
|
|
248
|
+
export function boundedUtf8Text(value, maximum) {
|
|
249
|
+
if (typeof value !== 'string' || value.length === 0)
|
|
250
|
+
return undefined;
|
|
251
|
+
const text = truncateUtf8(value, maximum);
|
|
252
|
+
return text.length > 0 ? text : undefined;
|
|
253
|
+
}
|
|
254
|
+
function stringValue(value, maximum, required = true) {
|
|
255
|
+
if (typeof value !== 'string' || value.length === 0 && required || encoder.encode(value).byteLength > maximum)
|
|
256
|
+
return undefined;
|
|
257
|
+
return value;
|
|
258
|
+
}
|
|
259
|
+
function integer(value, minimum = 0) {
|
|
260
|
+
return typeof value === 'number' && Number.isSafeInteger(value) && value >= minimum;
|
|
261
|
+
}
|
|
262
|
+
function readJson(payload) {
|
|
263
|
+
if (payload.byteLength > ACP_MIDDLEWARE_MAX_EVENT_BYTES)
|
|
264
|
+
throw new Error('ACP middleware message is too large.');
|
|
265
|
+
try {
|
|
266
|
+
return JSON.parse(new TextDecoder().decode(payload));
|
|
267
|
+
}
|
|
268
|
+
catch {
|
|
269
|
+
throw new Error('Invalid ACP middleware JSON.');
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
function readMutation(value) {
|
|
273
|
+
if (!record(value) || typeof value.type !== 'string')
|
|
274
|
+
return undefined;
|
|
275
|
+
switch (value.type) {
|
|
276
|
+
case 'session':
|
|
277
|
+
if (!['starting', 'loading', 'ready', 'error', 'closed'].includes(value.phase))
|
|
278
|
+
return undefined;
|
|
279
|
+
const sessionId = value.sessionId === undefined ? undefined : stringValue(value.sessionId, 256);
|
|
280
|
+
const title = value.title === undefined ? undefined : stringValue(value.title, 256);
|
|
281
|
+
const error = value.error === undefined ? undefined : stringValue(value.error, 2048);
|
|
282
|
+
if ((value.sessionId !== undefined && sessionId === undefined) || (value.title !== undefined && title === undefined) || (value.error !== undefined && error === undefined))
|
|
283
|
+
return undefined;
|
|
284
|
+
return { type: 'session', phase: value.phase, ...(sessionId === undefined ? {} : { sessionId }), ...(title === undefined ? {} : { title }), ...(error === undefined ? {} : { error }) };
|
|
285
|
+
case 'history-boundary': return value.boundary === 'complete' || value.boundary === 'omitted' ? { type: 'history-boundary', boundary: value.boundary } : undefined;
|
|
286
|
+
case 'turn-start': {
|
|
287
|
+
const turnId = stringValue(value.turnId, 128);
|
|
288
|
+
const userText = value.userText === undefined ? undefined : stringValue(value.userText, ACP_MIDDLEWARE_MAX_TEXT_BYTES);
|
|
289
|
+
return turnId === undefined || (value.userText !== undefined && userText === undefined) || (value.origin !== 'user' && value.origin !== 'agent')
|
|
290
|
+
? undefined
|
|
291
|
+
: { type: 'turn-start', turnId, origin: value.origin, ...(userText === undefined ? {} : { userText }) };
|
|
292
|
+
}
|
|
293
|
+
case 'turn-user-append': {
|
|
294
|
+
const turnId = stringValue(value.turnId, 128);
|
|
295
|
+
const text = stringValue(value.text, ACP_MIDDLEWARE_MAX_TEXT_BYTES);
|
|
296
|
+
return turnId === undefined || text === undefined ? undefined : { type: 'turn-user-append', turnId, text };
|
|
297
|
+
}
|
|
298
|
+
case 'message-append': {
|
|
299
|
+
const turnId = stringValue(value.turnId, 128);
|
|
300
|
+
const messageId = stringValue(value.messageId, 128);
|
|
301
|
+
const text = stringValue(value.text, ACP_MIDDLEWARE_MAX_TEXT_BYTES);
|
|
302
|
+
return turnId === undefined || messageId === undefined || text === undefined || (value.role !== 'assistant' && value.role !== 'thought') ? undefined : { type: 'message-append', turnId, messageId, role: value.role, text };
|
|
303
|
+
}
|
|
304
|
+
case 'omission-append': {
|
|
305
|
+
const turnId = stringValue(value.turnId, 128);
|
|
306
|
+
const omissionId = stringValue(value.omissionId, 128);
|
|
307
|
+
const reason = stringValue(value.reason, 1024);
|
|
308
|
+
return turnId === undefined || omissionId === undefined || reason === undefined ? undefined : { type: 'omission-append', turnId, omissionId, reason };
|
|
309
|
+
}
|
|
310
|
+
case 'turn-finish': {
|
|
311
|
+
const turnId = stringValue(value.turnId, 128);
|
|
312
|
+
const stopReason = value.stopReason === undefined ? undefined : stringValue(value.stopReason, 128);
|
|
313
|
+
return turnId === undefined || (value.status !== 'complete' && value.status !== 'interrupted') || (value.stopReason !== undefined && stopReason === undefined) ? undefined : { type: 'turn-finish', turnId, status: value.status, ...(stopReason === undefined ? {} : { stopReason }) };
|
|
314
|
+
}
|
|
315
|
+
case 'tool-upsert': {
|
|
316
|
+
if (!record(value.tool))
|
|
317
|
+
return undefined;
|
|
318
|
+
const turnId = stringValue(value.turnId, 128);
|
|
319
|
+
const tool = value.tool;
|
|
320
|
+
const id = stringValue(tool.id, 128);
|
|
321
|
+
const title = stringValue(tool.title, 256);
|
|
322
|
+
const statuses = ['pending', 'in_progress', 'completed', 'failed', 'cancelled'];
|
|
323
|
+
if (turnId === undefined || id === undefined || title === undefined || !statuses.includes(tool.status))
|
|
324
|
+
return undefined;
|
|
325
|
+
const kind = tool.kind === undefined ? undefined : stringValue(tool.kind, 64);
|
|
326
|
+
const detail = tool.detail === undefined ? undefined : stringValue(tool.detail, 2048);
|
|
327
|
+
const failureReason = tool.failureReason === undefined ? undefined : stringValue(tool.failureReason, 1024);
|
|
328
|
+
if ((tool.kind !== undefined && kind === undefined) || (tool.detail !== undefined && detail === undefined) || (tool.failureReason !== undefined && failureReason === undefined))
|
|
329
|
+
return undefined;
|
|
330
|
+
if (tool.locations !== undefined && (!Array.isArray(tool.locations) || tool.locations.length > 16 || tool.locations.some((item) => stringValue(item, 4096) === undefined)))
|
|
331
|
+
return undefined;
|
|
332
|
+
return { type: 'tool-upsert', turnId, tool: { id, title, status: tool.status, ...(kind === undefined ? {} : { kind }), ...(detail === undefined ? {} : { detail }), ...(failureReason === undefined ? {} : { failureReason }), ...(tool.locations === undefined ? {} : { locations: tool.locations }) } };
|
|
333
|
+
}
|
|
334
|
+
case 'config': {
|
|
335
|
+
if (!Array.isArray(value.options) || value.options.length > ACP_MIDDLEWARE_MAX_CONFIG_OPTIONS)
|
|
336
|
+
return undefined;
|
|
337
|
+
const options = value.options.map((option) => {
|
|
338
|
+
if (!record(option))
|
|
339
|
+
return undefined;
|
|
340
|
+
const id = stringValue(option.id, 256);
|
|
341
|
+
const category = option.category === undefined ? undefined : stringValue(option.category, 64);
|
|
342
|
+
const type = option.type === undefined ? undefined : stringValue(option.type, 64);
|
|
343
|
+
const currentValue = option.currentValue === undefined ? undefined : stringValue(option.currentValue, 4096);
|
|
344
|
+
if (id === undefined || (option.category !== undefined && category === undefined) || (option.type !== undefined && type === undefined) || (option.currentValue !== undefined && currentValue === undefined))
|
|
345
|
+
return undefined;
|
|
346
|
+
if (option.options !== undefined && (!Array.isArray(option.options) || option.options.length > ACP_MIDDLEWARE_MAX_CONFIG_CHOICES))
|
|
347
|
+
return undefined;
|
|
348
|
+
const choices = option.options?.map((choice) => {
|
|
349
|
+
if (!record(choice))
|
|
350
|
+
return undefined;
|
|
351
|
+
const choiceValue = stringValue(choice.value, 4096);
|
|
352
|
+
const label = choice.label === undefined ? undefined : stringValue(choice.label, 256);
|
|
353
|
+
return choiceValue === undefined || (choice.label !== undefined && label === undefined) ? undefined : { value: choiceValue, ...(label === undefined ? {} : { label }) };
|
|
354
|
+
});
|
|
355
|
+
if (choices?.some((choice) => choice === undefined))
|
|
356
|
+
return undefined;
|
|
357
|
+
const values = choices?.map((choice) => choice?.value);
|
|
358
|
+
if (values !== undefined && new Set(values).size !== values.length)
|
|
359
|
+
return undefined;
|
|
360
|
+
return { id, ...(category === undefined ? {} : { category }), ...(type === undefined ? {} : { type }), ...(currentValue === undefined ? {} : { currentValue }), ...(choices === undefined ? {} : { options: choices }) };
|
|
361
|
+
});
|
|
362
|
+
if (options.some((option) => option === undefined))
|
|
363
|
+
return undefined;
|
|
364
|
+
const model = value.model === undefined ? undefined : stringValue(value.model, 4096);
|
|
365
|
+
if (value.model !== undefined && model === undefined)
|
|
366
|
+
return undefined;
|
|
367
|
+
return { type: 'config', options: options, ...(model === undefined ? {} : { model }) };
|
|
368
|
+
}
|
|
369
|
+
case 'mode': return value.mode === undefined || stringValue(value.mode, 128) !== undefined ? { type: 'mode', ...(value.mode === undefined ? {} : { mode: value.mode }) } : undefined;
|
|
370
|
+
case 'commands': {
|
|
371
|
+
if (!Array.isArray(value.commands) || value.commands.length > ACP_MIDDLEWARE_MAX_COMMANDS)
|
|
372
|
+
return undefined;
|
|
373
|
+
const commands = value.commands.map((item) => {
|
|
374
|
+
if (!record(item))
|
|
375
|
+
return undefined;
|
|
376
|
+
const name = stringValue(item.name, ACP_MIDDLEWARE_MAX_COMMAND_NAME_BYTES);
|
|
377
|
+
const description = stringValue(item.description, ACP_MIDDLEWARE_MAX_COMMAND_DESCRIPTION_BYTES);
|
|
378
|
+
const inputHint = item.inputHint === undefined ? undefined : stringValue(item.inputHint, ACP_MIDDLEWARE_MAX_COMMAND_HINT_BYTES);
|
|
379
|
+
if (name === undefined || description === undefined || (item.inputHint !== undefined && inputHint === undefined))
|
|
380
|
+
return undefined;
|
|
381
|
+
return { name, description, ...(inputHint === undefined ? {} : { inputHint }) };
|
|
382
|
+
});
|
|
383
|
+
if (commands.some((item) => item === undefined))
|
|
384
|
+
return undefined;
|
|
385
|
+
return { type: 'commands', commands: commands };
|
|
386
|
+
}
|
|
387
|
+
case 'usage': return integer(value.used) && integer(value.size, 1) && (value.cost === undefined || typeof value.cost === 'number' && Number.isFinite(value.cost)) && (value.currency === undefined || stringValue(value.currency, 16) !== undefined) ? { type: 'usage', used: value.used, size: value.size, ...(value.cost === undefined ? {} : { cost: value.cost }), ...(value.currency === undefined ? {} : { currency: value.currency }) } : undefined;
|
|
388
|
+
case 'interaction-remove': return stringValue(value.interactionId, 128) === undefined ? undefined : { type: 'interaction-remove', interactionId: value.interactionId };
|
|
389
|
+
case 'notice-remove': return stringValue(value.noticeId, 128) === undefined ? undefined : { type: 'notice-remove', noticeId: value.noticeId };
|
|
390
|
+
case 'plan-remove': return stringValue(value.turnId, 128) !== undefined && stringValue(value.planId, ACP_MIDDLEWARE_MAX_PLAN_ID_BYTES) !== undefined ? { type: 'plan-remove', turnId: value.turnId, planId: value.planId } : undefined;
|
|
391
|
+
case 'plan-upsert': {
|
|
392
|
+
const turnId = stringValue(value.turnId, 128);
|
|
393
|
+
const plan = readPlan(value.plan);
|
|
394
|
+
return turnId === undefined || plan === undefined ? undefined : { type: 'plan-upsert', turnId, plan };
|
|
395
|
+
}
|
|
396
|
+
case 'interaction-upsert': {
|
|
397
|
+
if (!record(value.interaction))
|
|
398
|
+
return undefined;
|
|
399
|
+
const interaction = value.interaction;
|
|
400
|
+
const id = stringValue(interaction.id, 128);
|
|
401
|
+
const message = stringValue(interaction.message, 4096);
|
|
402
|
+
if (id === undefined || message === undefined || (interaction.kind !== 'permission' && interaction.kind !== 'elicitation'))
|
|
403
|
+
return undefined;
|
|
404
|
+
if (interaction.options !== undefined && (!Array.isArray(interaction.options) || interaction.options.length > 16))
|
|
405
|
+
return undefined;
|
|
406
|
+
const options = interaction.options?.map((option) => {
|
|
407
|
+
if (!record(option))
|
|
408
|
+
return undefined;
|
|
409
|
+
const optionId = stringValue(option.id, 128);
|
|
410
|
+
const label = stringValue(option.label, 256);
|
|
411
|
+
const kind = option.kind === undefined ? undefined : stringValue(option.kind, 64);
|
|
412
|
+
return optionId === undefined || label === undefined || (option.kind !== undefined && kind === undefined) ? undefined : { id: optionId, label, ...(kind === undefined ? {} : { kind }) };
|
|
413
|
+
});
|
|
414
|
+
if (options?.some((option) => option === undefined) || (options !== undefined && new Set(options.map((option) => option?.id)).size !== options.length))
|
|
415
|
+
return undefined;
|
|
416
|
+
if (interaction.schema !== undefined && (!record(interaction.schema) || encoder.encode(JSON.stringify(interaction.schema)).byteLength > 16 * 1024))
|
|
417
|
+
return undefined;
|
|
418
|
+
return { type: 'interaction-upsert', interaction: { id, message, kind: interaction.kind, ...(options === undefined ? {} : { options: options }), ...(interaction.schema === undefined ? {} : { schema: interaction.schema }) } };
|
|
419
|
+
}
|
|
420
|
+
case 'notice': {
|
|
421
|
+
if (!record(value.notice))
|
|
422
|
+
return undefined;
|
|
423
|
+
const notice = value.notice;
|
|
424
|
+
const id = stringValue(notice.id, 128);
|
|
425
|
+
const message = stringValue(notice.message, 4096);
|
|
426
|
+
if (id === undefined || message === undefined || !['info', 'warning', 'error'].includes(notice.level))
|
|
427
|
+
return undefined;
|
|
428
|
+
return { type: 'notice', notice: { id, message, level: notice.level } };
|
|
429
|
+
}
|
|
430
|
+
default: return undefined;
|
|
431
|
+
}
|
|
432
|
+
}
|
|
433
|
+
/**
|
|
434
|
+
* Reads a plan an agent published, or undefined when it is malformed.
|
|
435
|
+
*
|
|
436
|
+
* Malformed and oversized parts are refused rather than trimmed here: a producer
|
|
437
|
+
* that wants to publish a plan larger than this contract allows truncates it
|
|
438
|
+
* itself and says so, so that a pane never shows a partial plan as if it were the
|
|
439
|
+
* whole thing. The one exception is a file plan's URI, which is not read at all -
|
|
440
|
+
* it names a path on the agent's machine, which this client cannot open.
|
|
441
|
+
*/
|
|
442
|
+
function readPlan(value) {
|
|
443
|
+
if (!record(value))
|
|
444
|
+
return undefined;
|
|
445
|
+
const id = stringValue(value.id, ACP_MIDDLEWARE_MAX_PLAN_ID_BYTES);
|
|
446
|
+
if (id === undefined)
|
|
447
|
+
return undefined;
|
|
448
|
+
if (value.type === 'items') {
|
|
449
|
+
if (!Array.isArray(value.entries) || value.entries.length > ACP_MIDDLEWARE_MAX_PLAN_ITEMS)
|
|
450
|
+
return undefined;
|
|
451
|
+
const entries = value.entries.map((entry) => {
|
|
452
|
+
if (!record(entry))
|
|
453
|
+
return undefined;
|
|
454
|
+
const content = stringValue(entry.content, ACP_MIDDLEWARE_MAX_PLAN_ITEM_BYTES);
|
|
455
|
+
const status = stringValue(entry.status, 64);
|
|
456
|
+
const priority = entry.priority === undefined ? undefined : stringValue(entry.priority, 64);
|
|
457
|
+
if (content === undefined || status === undefined || (entry.priority !== undefined && priority === undefined))
|
|
458
|
+
return undefined;
|
|
459
|
+
return { content, status, ...(priority === undefined ? {} : { priority }) };
|
|
460
|
+
});
|
|
461
|
+
if (entries.some((entry) => entry === undefined))
|
|
462
|
+
return undefined;
|
|
463
|
+
const totalEntries = value.totalEntries === undefined ? undefined : integer(value.totalEntries, 1) ? value.totalEntries : undefined;
|
|
464
|
+
if (value.totalEntries !== undefined && totalEntries === undefined)
|
|
465
|
+
return undefined;
|
|
466
|
+
return { id, type: 'items', entries: entries, ...(totalEntries === undefined ? {} : { totalEntries }) };
|
|
467
|
+
}
|
|
468
|
+
if (value.type === 'markdown') {
|
|
469
|
+
const content = stringValue(value.content, ACP_MIDDLEWARE_MAX_PLAN_MARKDOWN_BYTES);
|
|
470
|
+
if (content === undefined)
|
|
471
|
+
return undefined;
|
|
472
|
+
return { id, type: 'markdown', content, ...(value.truncated === true ? { truncated: true } : {}) };
|
|
473
|
+
}
|
|
474
|
+
if (value.type === 'file') {
|
|
475
|
+
return { id, type: 'file' };
|
|
476
|
+
}
|
|
477
|
+
return undefined;
|
|
478
|
+
}
|
|
479
|
+
function readMutations(value, maximum = ACP_MIDDLEWARE_MAX_MUTATIONS) {
|
|
480
|
+
if (!Array.isArray(value) || value.length > maximum)
|
|
481
|
+
throw new Error('Invalid ACP middleware mutations.');
|
|
482
|
+
const result = value.map(readMutation);
|
|
483
|
+
if (result.some((item) => item === undefined))
|
|
484
|
+
throw new Error('Invalid ACP middleware mutation.');
|
|
485
|
+
return result;
|
|
486
|
+
}
|
|
487
|
+
export function encodeAcpCommand(commandIdValue, command) {
|
|
488
|
+
if (stringValue(commandIdValue, 128) === undefined)
|
|
489
|
+
throw new Error('Invalid ACP middleware command id.');
|
|
490
|
+
const bytes = encoder.encode(JSON.stringify({ version: ACP_MIDDLEWARE_VERSION, type: 'command', commandId: commandIdValue, command }));
|
|
491
|
+
if (bytes.byteLength > ACP_MIDDLEWARE_MAX_COMMAND_BYTES)
|
|
492
|
+
throw new RangeError('ACP middleware command is too large.');
|
|
493
|
+
return bytes;
|
|
494
|
+
}
|
|
495
|
+
export function decodeAcpCommand(payload) {
|
|
496
|
+
const value = readJson(payload);
|
|
497
|
+
if (!record(value) || value.version !== ACP_MIDDLEWARE_VERSION || value.type !== 'command' || stringValue(value.commandId, 128) === undefined || !record(value.command))
|
|
498
|
+
throw new Error('Invalid ACP middleware command envelope.');
|
|
499
|
+
const command = value.command;
|
|
500
|
+
switch (command.kind) {
|
|
501
|
+
case 'sync':
|
|
502
|
+
if ((command.epoch !== undefined && stringValue(command.epoch, 128) === undefined) || (command.afterSequence !== undefined && !integer(command.afterSequence)))
|
|
503
|
+
throw new Error('Invalid ACP middleware sync command.');
|
|
504
|
+
break;
|
|
505
|
+
case 'prompt': {
|
|
506
|
+
if (stringValue(command.text, ACP_MIDDLEWARE_MAX_TEXT_BYTES) === undefined)
|
|
507
|
+
throw new Error('Invalid ACP prompt.');
|
|
508
|
+
if (command.files !== undefined) {
|
|
509
|
+
if (!Array.isArray(command.files) || command.files.length > ACP_MIDDLEWARE_MAX_PROMPT_FILES)
|
|
510
|
+
throw new Error('Invalid ACP prompt attachments.');
|
|
511
|
+
for (const path of command.files) {
|
|
512
|
+
if (stringValue(path, ACP_MIDDLEWARE_MAX_PATH_BYTES) === undefined)
|
|
513
|
+
throw new Error('Invalid ACP prompt attachment.');
|
|
514
|
+
}
|
|
515
|
+
}
|
|
516
|
+
break;
|
|
517
|
+
}
|
|
518
|
+
case 'cancel': break;
|
|
519
|
+
case 'set-config':
|
|
520
|
+
if (stringValue(command.id, 256) === undefined || stringValue(command.value, 4096) === undefined)
|
|
521
|
+
throw new Error('Invalid ACP configuration command.');
|
|
522
|
+
break;
|
|
523
|
+
case 'respond-interaction':
|
|
524
|
+
if (stringValue(command.interactionId, 128) === undefined || !['accept', 'decline', 'cancel'].includes(command.action) || (command.values !== undefined && !record(command.values)))
|
|
525
|
+
throw new Error('Invalid ACP interaction command.');
|
|
526
|
+
break;
|
|
527
|
+
case 'history':
|
|
528
|
+
if (command.action !== 'retry' && command.action !== 'continue')
|
|
529
|
+
throw new Error('Invalid ACP history command.');
|
|
530
|
+
break;
|
|
531
|
+
case 'catalog-workspaces':
|
|
532
|
+
if (stringValue(command.agent, 64) === undefined)
|
|
533
|
+
throw new Error('Invalid ACP workspace query.');
|
|
534
|
+
break;
|
|
535
|
+
case 'catalog-sessions':
|
|
536
|
+
if (stringValue(command.agent, 64) === undefined || stringValue(command.cwd, 4096) === undefined)
|
|
537
|
+
throw new Error('Invalid ACP session query.');
|
|
538
|
+
break;
|
|
539
|
+
case 'catalog-directories':
|
|
540
|
+
if (command.path !== undefined && stringValue(command.path, 4096) === undefined)
|
|
541
|
+
throw new Error('Invalid ACP directory query.');
|
|
542
|
+
break;
|
|
543
|
+
case 'read-file':
|
|
544
|
+
if (stringValue(command.path, 4096) === undefined || (command.cwd !== undefined && stringValue(command.cwd, 4096) === undefined))
|
|
545
|
+
throw new Error('Invalid ACP file query.');
|
|
546
|
+
break;
|
|
547
|
+
case 'file-diff':
|
|
548
|
+
if (stringValue(command.path, 4096) === undefined || (command.cwd !== undefined && stringValue(command.cwd, 4096) === undefined))
|
|
549
|
+
throw new Error('Invalid ACP diff query.');
|
|
550
|
+
break;
|
|
551
|
+
default: throw new Error('Unknown ACP middleware command.');
|
|
552
|
+
}
|
|
553
|
+
return { version: ACP_MIDDLEWARE_VERSION, type: 'command', commandId: value.commandId, command: command };
|
|
554
|
+
}
|
|
555
|
+
export function encodeAcpEvent(event) {
|
|
556
|
+
const bytes = encoder.encode(JSON.stringify(event));
|
|
557
|
+
if (bytes.byteLength > ACP_MIDDLEWARE_MAX_EVENT_BYTES)
|
|
558
|
+
throw new RangeError('ACP middleware event is too large.');
|
|
559
|
+
return bytes;
|
|
560
|
+
}
|
|
561
|
+
export function decodeAcpEvent(payload) {
|
|
562
|
+
const value = readJson(payload);
|
|
563
|
+
if (!record(value) || value.version !== ACP_MIDDLEWARE_VERSION || typeof value.type !== 'string')
|
|
564
|
+
throw new Error('Invalid ACP middleware event envelope.');
|
|
565
|
+
if (value.type === 'delta') {
|
|
566
|
+
if (stringValue(value.epoch, 128) === undefined || !integer(value.firstSequence, 1))
|
|
567
|
+
throw new Error('Invalid ACP middleware delta.');
|
|
568
|
+
return { version: ACP_MIDDLEWARE_VERSION, type: 'delta', epoch: value.epoch, firstSequence: value.firstSequence, mutations: readMutations(value.mutations) };
|
|
569
|
+
}
|
|
570
|
+
if (value.type === 'snapshot-start') {
|
|
571
|
+
if (stringValue(value.snapshotId, 128) === undefined || stringValue(value.epoch, 128) === undefined || !integer(value.throughSequence) || !integer(value.chunkCount, 1) || value.chunkCount > ACP_MIDDLEWARE_MAX_SNAPSHOT_CHUNKS || !integer(value.mutationCount) || value.mutationCount > ACP_MIDDLEWARE_MAX_SNAPSHOT_MUTATIONS || typeof value.digest !== 'string' || !/^[a-f0-9]{64}$/.test(value.digest))
|
|
572
|
+
throw new Error('Invalid ACP middleware snapshot start.');
|
|
573
|
+
return { version: ACP_MIDDLEWARE_VERSION, type: 'snapshot-start', snapshotId: value.snapshotId, epoch: value.epoch, throughSequence: value.throughSequence, chunkCount: value.chunkCount, mutationCount: value.mutationCount, digest: value.digest };
|
|
574
|
+
}
|
|
575
|
+
if (value.type === 'snapshot-chunk') {
|
|
576
|
+
if (stringValue(value.snapshotId, 128) === undefined || !integer(value.index) || value.index >= ACP_MIDDLEWARE_MAX_SNAPSHOT_CHUNKS)
|
|
577
|
+
throw new Error('Invalid ACP middleware snapshot chunk.');
|
|
578
|
+
return { version: ACP_MIDDLEWARE_VERSION, type: 'snapshot-chunk', snapshotId: value.snapshotId, index: value.index, mutations: readMutations(value.mutations) };
|
|
579
|
+
}
|
|
580
|
+
if (value.type === 'snapshot-complete') {
|
|
581
|
+
if (stringValue(value.snapshotId, 128) === undefined || !integer(value.chunkCount) || !integer(value.mutationCount))
|
|
582
|
+
throw new Error('Invalid ACP middleware snapshot complete.');
|
|
583
|
+
return { version: ACP_MIDDLEWARE_VERSION, type: 'snapshot-complete', snapshotId: value.snapshotId, chunkCount: value.chunkCount, mutationCount: value.mutationCount };
|
|
584
|
+
}
|
|
585
|
+
if (value.type === 'command-result') {
|
|
586
|
+
if (stringValue(value.commandId, 128) === undefined || typeof value.accepted !== 'boolean' || (value.error !== undefined && stringValue(value.error, 2048) === undefined))
|
|
587
|
+
throw new Error('Invalid ACP middleware command result.');
|
|
588
|
+
return { version: ACP_MIDDLEWARE_VERSION, type: 'command-result', commandId: value.commandId, accepted: value.accepted, ...(value.error === undefined ? {} : { error: value.error }) };
|
|
589
|
+
}
|
|
590
|
+
if (value.type === 'catalog-result' && stringValue(value.commandId, 128) !== undefined)
|
|
591
|
+
return { version: ACP_MIDDLEWARE_VERSION, type: 'catalog-result', commandId: value.commandId, value: value.value };
|
|
592
|
+
throw new Error('Unknown ACP middleware event.');
|
|
593
|
+
}
|
|
594
|
+
/**
|
|
595
|
+
* Deterministic JSON serialization where object keys are recursively sorted.
|
|
596
|
+
*
|
|
597
|
+
* Arrays preserve their order; primitive values, null, and booleans match
|
|
598
|
+
* standard JSON.stringify; object keys whose values are undefined, functions,
|
|
599
|
+
* or symbols are omitted, matching standard JSON object serialization.
|
|
600
|
+
*/
|
|
601
|
+
export function canonicalJsonStringify(value) {
|
|
602
|
+
if (value === null || typeof value !== 'object') {
|
|
603
|
+
return JSON.stringify(value);
|
|
604
|
+
}
|
|
605
|
+
let target = value;
|
|
606
|
+
if (typeof target.toJSON === 'function') {
|
|
607
|
+
target = target.toJSON();
|
|
608
|
+
if (target === null || typeof target !== 'object') {
|
|
609
|
+
return JSON.stringify(target);
|
|
610
|
+
}
|
|
611
|
+
}
|
|
612
|
+
if (Array.isArray(target)) {
|
|
613
|
+
return `[${target.map((item) => (item === undefined ? 'null' : canonicalJsonStringify(item))).join(',')}]`;
|
|
614
|
+
}
|
|
615
|
+
const recordValue = target;
|
|
616
|
+
const keys = Object.keys(recordValue).sort();
|
|
617
|
+
const parts = [];
|
|
618
|
+
for (const key of keys) {
|
|
619
|
+
const val = recordValue[key];
|
|
620
|
+
if (val !== undefined && typeof val !== 'function' && typeof val !== 'symbol') {
|
|
621
|
+
parts.push(`${JSON.stringify(key)}:${canonicalJsonStringify(val)}`);
|
|
622
|
+
}
|
|
623
|
+
}
|
|
624
|
+
return `{${parts.join(',')}}`;
|
|
625
|
+
}
|
|
626
|
+
//# sourceMappingURL=acp-middleware.js.map
|