@crowdedkingdoms/crowdyjs 11.1.0 → 12.0.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/MIGRATION.md +107 -0
- package/README.md +203 -0
- package/dist/crowdy-agent/browser-dispatcher.d.ts +41 -0
- package/dist/crowdy-agent/browser-dispatcher.d.ts.map +1 -0
- package/dist/crowdy-agent/browser-dispatcher.js +264 -0
- package/dist/crowdy-agent/controller.d.ts +144 -0
- package/dist/crowdy-agent/controller.d.ts.map +1 -0
- package/dist/crowdy-agent/controller.js +1239 -0
- package/dist/crowdy-agent/errors.d.ts +37 -0
- package/dist/crowdy-agent/errors.d.ts.map +1 -0
- package/dist/crowdy-agent/errors.js +107 -0
- package/dist/crowdy-agent/graphql-transport.d.ts +154 -0
- package/dist/crowdy-agent/graphql-transport.d.ts.map +1 -0
- package/dist/crowdy-agent/graphql-transport.js +854 -0
- package/dist/crowdy-agent/index.d.ts +16 -0
- package/dist/crowdy-agent/index.d.ts.map +1 -0
- package/dist/crowdy-agent/index.js +15 -0
- package/dist/crowdy-agent/registry.d.ts +29 -0
- package/dist/crowdy-agent/registry.d.ts.map +1 -0
- package/dist/crowdy-agent/registry.js +281 -0
- package/dist/crowdy-agent/schema.d.ts +72 -0
- package/dist/crowdy-agent/schema.d.ts.map +1 -0
- package/dist/crowdy-agent/schema.js +467 -0
- package/dist/crowdy-agent/studio-tools.d.ts +15 -0
- package/dist/crowdy-agent/studio-tools.d.ts.map +1 -0
- package/dist/crowdy-agent/studio-tools.js +280 -0
- package/dist/crowdy-agent/tool-descriptors.d.ts +4 -0
- package/dist/crowdy-agent/tool-descriptors.d.ts.map +1 -0
- package/dist/crowdy-agent/tool-descriptors.js +1049 -0
- package/dist/crowdy-agent/transport.d.ts +152 -0
- package/dist/crowdy-agent/transport.d.ts.map +1 -0
- package/dist/crowdy-agent/transport.js +27 -0
- package/dist/crowdy-agent/types.d.ts +328 -0
- package/dist/crowdy-agent/types.d.ts.map +1 -0
- package/dist/crowdy-agent/types.js +37 -0
- package/dist/crowdy-client.d.ts +3 -0
- package/dist/crowdy-client.d.ts.map +1 -1
- package/dist/crowdy-client.js +6 -0
- package/dist/crowdy-studio/agent-dom-shell.d.ts +40 -0
- package/dist/crowdy-studio/agent-dom-shell.d.ts.map +1 -0
- package/dist/crowdy-studio/agent-dom-shell.js +354 -0
- package/dist/crowdy-studio/controller.d.ts +74 -4
- package/dist/crowdy-studio/controller.d.ts.map +1 -1
- package/dist/crowdy-studio/controller.js +450 -17
- package/dist/crowdy-studio/dom-shell.d.ts +4 -1
- package/dist/crowdy-studio/dom-shell.d.ts.map +1 -1
- package/dist/crowdy-studio/dom-shell.js +6 -1
- package/dist/crowdy-studio/index.d.ts +6 -3
- package/dist/crowdy-studio/index.d.ts.map +1 -1
- package/dist/crowdy-studio/index.js +3 -0
- package/dist/crowdy-studio/models.d.ts +67 -0
- package/dist/crowdy-studio/models.d.ts.map +1 -1
- package/dist/crowdy-studio/mount.d.ts +15 -0
- package/dist/crowdy-studio/mount.d.ts.map +1 -1
- package/dist/crowdy-studio/mount.js +129 -2
- package/dist/crowdy-studio/styles.d.ts +1 -1
- package/dist/crowdy-studio/styles.d.ts.map +1 -1
- package/dist/crowdy-studio/styles.js +2 -0
- package/dist/generated/graphql.d.ts +3753 -1
- package/dist/generated/graphql.d.ts.map +1 -1
- package/dist/generated/graphql.js +296 -0
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/dist/kit/npcs.d.ts.map +1 -1
- package/dist/kit/social.d.ts.map +1 -1
- package/dist/player-host/index.d.ts +5 -0
- package/dist/player-host/index.d.ts.map +1 -0
- package/dist/player-host/index.js +3 -0
- package/dist/player-host/lease-manager.d.ts +66 -0
- package/dist/player-host/lease-manager.d.ts.map +1 -0
- package/dist/player-host/lease-manager.js +428 -0
- package/dist/player-host/schemas.d.ts +9 -0
- package/dist/player-host/schemas.d.ts.map +1 -0
- package/dist/player-host/schemas.js +347 -0
- package/dist/player-host/tools.d.ts +13 -0
- package/dist/player-host/tools.d.ts.map +1 -0
- package/dist/player-host/tools.js +79 -0
- package/dist/player-host/types.d.ts +203 -0
- package/dist/player-host/types.d.ts.map +1 -0
- package/dist/player-host/types.js +1 -0
- package/package.json +12 -2
|
@@ -0,0 +1,854 @@
|
|
|
1
|
+
import { createClient as createWsClient } from 'graphql-ws';
|
|
2
|
+
import { print } from 'graphql';
|
|
3
|
+
import { CrowdyGraphQLError, } from '../errors.js';
|
|
4
|
+
import { CrowdyStudioAgentAcknowledgeEventsDocument, CrowdyStudioAgentApproveToolDocument, CrowdyStudioAgentAttachClientDocument, CrowdyStudioAgentBudgetDocument, CrowdyStudioAgentCancelRunDocument, CrowdyStudioAgentCloseSessionDocument, CrowdyStudioAgentCreateSessionDocument, CrowdyStudioAgentEventsDocument, CrowdyStudioAgentGrantLeaseDocument, CrowdyStudioAgentHeartbeatDocument, CrowdyStudioAgentHistoryDocument, CrowdyStudioAgentPauseDocument, CrowdyStudioAgentRejectToolDocument, CrowdyStudioAgentResumeDocument, CrowdyStudioAgentRevokeLeaseDocument, CrowdyStudioAgentSendMessageDocument, CrowdyStudioAgentSessionDocument, CrowdyStudioAgentSessionsDocument, CrowdyStudioAgentSetModeDocument, CrowdyStudioAgentToolDescriptorsDocument, CrowdyStudioAgentToolResultDocument, } from '../generated/graphql.js';
|
|
5
|
+
import { CrowdyAgentError, } from './errors.js';
|
|
6
|
+
import { canonicalJson, digestCanonicalJson, } from './schema.js';
|
|
7
|
+
import { CrowdyAgentToolRegistry } from './registry.js';
|
|
8
|
+
/**
|
|
9
|
+
* Production generated-GraphQL adapter for `CrowdyStudioAgentTransportV1`.
|
|
10
|
+
* Every HTTP and subscription shape is selected by committed typed documents.
|
|
11
|
+
*/
|
|
12
|
+
export class CrowdyAgentGraphQLTransport {
|
|
13
|
+
constructor(graphql, options) {
|
|
14
|
+
this.graphql = graphql;
|
|
15
|
+
this.options = options;
|
|
16
|
+
this.activeSubscriptions = new Set();
|
|
17
|
+
}
|
|
18
|
+
async getSession(sessionId) {
|
|
19
|
+
const data = await this.request(CrowdyStudioAgentSessionDocument, {
|
|
20
|
+
sessionId,
|
|
21
|
+
});
|
|
22
|
+
return mapSession(data.crowdyStudioAgentSession);
|
|
23
|
+
}
|
|
24
|
+
async listSessions(input) {
|
|
25
|
+
const data = await this.request(CrowdyStudioAgentSessionsDocument, {
|
|
26
|
+
appId: input.appId,
|
|
27
|
+
after: input.after ?? null,
|
|
28
|
+
first: input.first,
|
|
29
|
+
});
|
|
30
|
+
const connection = data.crowdyStudioAgentSessions;
|
|
31
|
+
const edges = connection.edges.map((edge) => ({
|
|
32
|
+
cursor: edge.cursor,
|
|
33
|
+
node: mapSession(edge.node),
|
|
34
|
+
}));
|
|
35
|
+
return {
|
|
36
|
+
edges,
|
|
37
|
+
pageInfo: {
|
|
38
|
+
hasNextPage: connection.pageInfo.hasNextPage,
|
|
39
|
+
...(connection.pageInfo.endCursor
|
|
40
|
+
? { endCursor: connection.pageInfo.endCursor }
|
|
41
|
+
: {}),
|
|
42
|
+
},
|
|
43
|
+
nodes: edges.map((edge) => edge.node),
|
|
44
|
+
...(connection.endCursor ? { endCursor: connection.endCursor } : {}),
|
|
45
|
+
hasNextPage: connection.hasNextPage,
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
async history(input) {
|
|
49
|
+
const data = await this.request(CrowdyStudioAgentHistoryDocument, {
|
|
50
|
+
sessionId: input.sessionId,
|
|
51
|
+
afterSeq: input.afterSeq,
|
|
52
|
+
first: input.first,
|
|
53
|
+
});
|
|
54
|
+
const connection = data.crowdyStudioAgentHistory;
|
|
55
|
+
const edges = connection.edges.map((edge) => ({
|
|
56
|
+
cursor: edge.cursor,
|
|
57
|
+
node: mapEvent(edge.node),
|
|
58
|
+
}));
|
|
59
|
+
return {
|
|
60
|
+
edges,
|
|
61
|
+
pageInfo: {
|
|
62
|
+
hasNextPage: connection.pageInfo.hasNextPage,
|
|
63
|
+
...(connection.pageInfo.endCursor
|
|
64
|
+
? { endCursor: connection.pageInfo.endCursor }
|
|
65
|
+
: {}),
|
|
66
|
+
},
|
|
67
|
+
events: edges.map((edge) => edge.node),
|
|
68
|
+
hasMore: connection.hasMore,
|
|
69
|
+
};
|
|
70
|
+
}
|
|
71
|
+
async toolDescriptors(sessionId) {
|
|
72
|
+
const data = await this.request(CrowdyStudioAgentToolDescriptorsDocument, { sessionId });
|
|
73
|
+
const result = data.crowdyStudioAgentToolDescriptors;
|
|
74
|
+
const descriptors = result.tools.map(mapDescriptor);
|
|
75
|
+
const registry = new CrowdyAgentToolRegistry(descriptors);
|
|
76
|
+
if (registry.registryDigest !== result.registryDigest) {
|
|
77
|
+
throw new CrowdyAgentError('AGENT_CONTEXT_STALE', 'Game API descriptor registry digest does not match canonical descriptors');
|
|
78
|
+
}
|
|
79
|
+
return {
|
|
80
|
+
registryDigest: result.registryDigest,
|
|
81
|
+
tools: registry.list(),
|
|
82
|
+
};
|
|
83
|
+
}
|
|
84
|
+
async budget(sessionId) {
|
|
85
|
+
const data = await this.request(CrowdyStudioAgentBudgetDocument, {
|
|
86
|
+
sessionId,
|
|
87
|
+
});
|
|
88
|
+
return mapBudget(data.crowdyStudioAgentBudget);
|
|
89
|
+
}
|
|
90
|
+
async createSession(input) {
|
|
91
|
+
const data = await this.request(CrowdyStudioAgentCreateSessionDocument, {
|
|
92
|
+
input: {
|
|
93
|
+
idempotencyKey: input.idempotencyKey,
|
|
94
|
+
appId: input.appId,
|
|
95
|
+
mode: input.mode,
|
|
96
|
+
...(input.projectId ? { projectId: input.projectId } : {}),
|
|
97
|
+
...(input.gridId ? { gridId: input.gridId } : {}),
|
|
98
|
+
...(input.requestedModel
|
|
99
|
+
? { requestedModel: input.requestedModel }
|
|
100
|
+
: {}),
|
|
101
|
+
providerDataConsent: input.providerDataConsent ?? false,
|
|
102
|
+
},
|
|
103
|
+
});
|
|
104
|
+
return mapSession(data.crowdyStudioAgentCreateSession);
|
|
105
|
+
}
|
|
106
|
+
async attachClient(input) {
|
|
107
|
+
const data = await this.request(CrowdyStudioAgentAttachClientDocument, {
|
|
108
|
+
input: {
|
|
109
|
+
sessionId: input.sessionId,
|
|
110
|
+
idempotencyKey: input.idempotencyKey,
|
|
111
|
+
...(input.clientInstanceId
|
|
112
|
+
? { clientInstanceId: input.clientInstanceId }
|
|
113
|
+
: {}),
|
|
114
|
+
},
|
|
115
|
+
});
|
|
116
|
+
const attachment = data.crowdyStudioAgentAttachClient;
|
|
117
|
+
return {
|
|
118
|
+
session: mapSession(attachment.session),
|
|
119
|
+
clientEpoch: String(attachment.clientEpoch),
|
|
120
|
+
replayAfterSeq: String(attachment.replayAfterSeq),
|
|
121
|
+
};
|
|
122
|
+
}
|
|
123
|
+
async setMode(input) {
|
|
124
|
+
const data = await this.request(CrowdyStudioAgentSetModeDocument, {
|
|
125
|
+
input: {
|
|
126
|
+
...input,
|
|
127
|
+
mode: input.mode,
|
|
128
|
+
},
|
|
129
|
+
});
|
|
130
|
+
return mapSession(data.crowdyStudioAgentSetMode);
|
|
131
|
+
}
|
|
132
|
+
async acknowledgeEvents(input) {
|
|
133
|
+
const data = await this.request(CrowdyStudioAgentAcknowledgeEventsDocument, { input });
|
|
134
|
+
return {
|
|
135
|
+
throughSeq: String(data.crowdyStudioAgentAcknowledgeEvents.throughSeq),
|
|
136
|
+
};
|
|
137
|
+
}
|
|
138
|
+
async heartbeat(input) {
|
|
139
|
+
const data = await this.request(CrowdyStudioAgentHeartbeatDocument, {
|
|
140
|
+
input,
|
|
141
|
+
});
|
|
142
|
+
const heartbeat = data.crowdyStudioAgentHeartbeat;
|
|
143
|
+
return {
|
|
144
|
+
serverTime: heartbeat.serverTime,
|
|
145
|
+
...(heartbeat.playLeaseFreshUntil
|
|
146
|
+
? { playLeaseFreshUntil: heartbeat.playLeaseFreshUntil }
|
|
147
|
+
: {}),
|
|
148
|
+
...(heartbeat.workspaceLeaseExpiresAt
|
|
149
|
+
? { workspaceLeaseExpiresAt: heartbeat.workspaceLeaseExpiresAt }
|
|
150
|
+
: {}),
|
|
151
|
+
};
|
|
152
|
+
}
|
|
153
|
+
async sendMessage(input) {
|
|
154
|
+
const data = await this.request(CrowdyStudioAgentSendMessageDocument, {
|
|
155
|
+
input: {
|
|
156
|
+
sessionId: input.sessionId,
|
|
157
|
+
clientEpoch: input.clientEpoch,
|
|
158
|
+
idempotencyKey: input.idempotencyKey,
|
|
159
|
+
content: input.message,
|
|
160
|
+
},
|
|
161
|
+
});
|
|
162
|
+
return mapRun(data.crowdyStudioAgentSendMessage);
|
|
163
|
+
}
|
|
164
|
+
async approveTool(input) {
|
|
165
|
+
const data = await this.request(CrowdyStudioAgentApproveToolDocument, {
|
|
166
|
+
input,
|
|
167
|
+
});
|
|
168
|
+
return mapApproval(data.crowdyStudioAgentApproveTool);
|
|
169
|
+
}
|
|
170
|
+
async rejectTool(input) {
|
|
171
|
+
const data = await this.request(CrowdyStudioAgentRejectToolDocument, {
|
|
172
|
+
input: {
|
|
173
|
+
sessionId: input.sessionId,
|
|
174
|
+
clientEpoch: input.clientEpoch,
|
|
175
|
+
idempotencyKey: input.idempotencyKey,
|
|
176
|
+
toolCallId: input.toolCallId,
|
|
177
|
+
argumentHash: input.argumentHash,
|
|
178
|
+
...(input.reason ? { reason: input.reason } : {}),
|
|
179
|
+
},
|
|
180
|
+
});
|
|
181
|
+
return mapApproval(data.crowdyStudioAgentRejectTool);
|
|
182
|
+
}
|
|
183
|
+
async toolResult(input) {
|
|
184
|
+
const result = input.result;
|
|
185
|
+
const data = await this.request(CrowdyStudioAgentToolResultDocument, {
|
|
186
|
+
input: {
|
|
187
|
+
sessionId: input.sessionId,
|
|
188
|
+
clientEpoch: input.clientEpoch,
|
|
189
|
+
idempotencyKey: input.idempotencyKey,
|
|
190
|
+
result: {
|
|
191
|
+
protocolVersion: result.protocolVersion,
|
|
192
|
+
toolCallId: result.toolCallId,
|
|
193
|
+
status: result.status,
|
|
194
|
+
...(result.output !== undefined
|
|
195
|
+
? { outputJson: canonicalJson(result.output) }
|
|
196
|
+
: {}),
|
|
197
|
+
...(result.error
|
|
198
|
+
? {
|
|
199
|
+
errorCode: result.error.code,
|
|
200
|
+
errorMessage: result.error.message,
|
|
201
|
+
errorRetryable: result.error.retryable,
|
|
202
|
+
}
|
|
203
|
+
: {}),
|
|
204
|
+
observedContextVersion: result.observedContextVersion,
|
|
205
|
+
startedAt: result.startedAt,
|
|
206
|
+
finishedAt: result.finishedAt,
|
|
207
|
+
},
|
|
208
|
+
},
|
|
209
|
+
});
|
|
210
|
+
const call = data.crowdyStudioAgentToolResult;
|
|
211
|
+
return {
|
|
212
|
+
toolCallId: call.toolCallId,
|
|
213
|
+
toolName: call.toolName,
|
|
214
|
+
status: call.status,
|
|
215
|
+
argumentHash: call.argumentHash,
|
|
216
|
+
...(call.error ? { error: mapError(call.error) } : {}),
|
|
217
|
+
accepted: call.accepted,
|
|
218
|
+
};
|
|
219
|
+
}
|
|
220
|
+
async grantLease(input) {
|
|
221
|
+
const data = await this.request(CrowdyStudioAgentGrantLeaseDocument, {
|
|
222
|
+
input: {
|
|
223
|
+
...input,
|
|
224
|
+
scopes: [...input.scopes],
|
|
225
|
+
},
|
|
226
|
+
});
|
|
227
|
+
return mapLease(data.crowdyStudioAgentGrantLease);
|
|
228
|
+
}
|
|
229
|
+
async revokeLease(input) {
|
|
230
|
+
const data = await this.request(CrowdyStudioAgentRevokeLeaseDocument, {
|
|
231
|
+
input: {
|
|
232
|
+
...input,
|
|
233
|
+
reason: input.reason,
|
|
234
|
+
},
|
|
235
|
+
});
|
|
236
|
+
return mapLease(data.crowdyStudioAgentRevokeLease);
|
|
237
|
+
}
|
|
238
|
+
async pause(input) {
|
|
239
|
+
const data = await this.request(CrowdyStudioAgentPauseDocument, { input });
|
|
240
|
+
return mapSession(data.crowdyStudioAgentPause);
|
|
241
|
+
}
|
|
242
|
+
async resume(input) {
|
|
243
|
+
const data = await this.request(CrowdyStudioAgentResumeDocument, { input });
|
|
244
|
+
return mapSession(data.crowdyStudioAgentResume);
|
|
245
|
+
}
|
|
246
|
+
async cancelRun(input) {
|
|
247
|
+
const data = await this.request(CrowdyStudioAgentCancelRunDocument, {
|
|
248
|
+
input,
|
|
249
|
+
});
|
|
250
|
+
return mapRun(data.crowdyStudioAgentCancelRun);
|
|
251
|
+
}
|
|
252
|
+
async closeSession(input) {
|
|
253
|
+
const data = await this.request(CrowdyStudioAgentCloseSessionDocument, {
|
|
254
|
+
input,
|
|
255
|
+
});
|
|
256
|
+
return mapSession(data.crowdyStudioAgentCloseSession);
|
|
257
|
+
}
|
|
258
|
+
subscribeEvents(input, handlers) {
|
|
259
|
+
const client = this.createSubscriptionClient();
|
|
260
|
+
let closed = false;
|
|
261
|
+
const dispose = client.subscribe({
|
|
262
|
+
query: print(CrowdyStudioAgentEventsDocument),
|
|
263
|
+
variables: input,
|
|
264
|
+
}, {
|
|
265
|
+
next: (message) => {
|
|
266
|
+
if (message.errors?.length) {
|
|
267
|
+
handlers.error(mapGraphQLErrors(message.errors));
|
|
268
|
+
return;
|
|
269
|
+
}
|
|
270
|
+
const data = message.data;
|
|
271
|
+
if (data?.crowdyStudioAgentEvents) {
|
|
272
|
+
try {
|
|
273
|
+
handlers.next(mapEvent(data.crowdyStudioAgentEvents));
|
|
274
|
+
}
|
|
275
|
+
catch (error) {
|
|
276
|
+
handlers.error(error);
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
},
|
|
280
|
+
error: (error) => handlers.error(mapTransportError(error)),
|
|
281
|
+
complete: () => handlers.complete(),
|
|
282
|
+
});
|
|
283
|
+
const subscription = {
|
|
284
|
+
close: () => {
|
|
285
|
+
if (closed)
|
|
286
|
+
return;
|
|
287
|
+
closed = true;
|
|
288
|
+
this.activeSubscriptions.delete(subscription);
|
|
289
|
+
dispose();
|
|
290
|
+
void client.dispose();
|
|
291
|
+
},
|
|
292
|
+
};
|
|
293
|
+
this.activeSubscriptions.add(subscription);
|
|
294
|
+
return subscription;
|
|
295
|
+
}
|
|
296
|
+
/** Close all agent event sockets owned by this adapter. */
|
|
297
|
+
close() {
|
|
298
|
+
for (const subscription of [...this.activeSubscriptions]) {
|
|
299
|
+
subscription.close();
|
|
300
|
+
}
|
|
301
|
+
}
|
|
302
|
+
createSubscriptionClient() {
|
|
303
|
+
if (this.options.subscriptionClientFactory) {
|
|
304
|
+
return this.options.subscriptionClientFactory();
|
|
305
|
+
}
|
|
306
|
+
if (!this.options.wsUrl) {
|
|
307
|
+
throw new CrowdyAgentError('AGENT_HOST_UNAVAILABLE', 'Crowdy agent events require a graphql-transport-ws endpoint');
|
|
308
|
+
}
|
|
309
|
+
return createWsClient({
|
|
310
|
+
url: this.options.wsUrl,
|
|
311
|
+
lazy: false,
|
|
312
|
+
retryAttempts: 0,
|
|
313
|
+
...(this.options.webSocketImpl
|
|
314
|
+
? { webSocketImpl: this.options.webSocketImpl }
|
|
315
|
+
: {}),
|
|
316
|
+
connectionParams: () => {
|
|
317
|
+
const token = this.options.getToken();
|
|
318
|
+
return token ? { Authorization: `Bearer ${token}` } : {};
|
|
319
|
+
},
|
|
320
|
+
});
|
|
321
|
+
}
|
|
322
|
+
async request(document, variables) {
|
|
323
|
+
try {
|
|
324
|
+
return await this.graphql.request(document, variables);
|
|
325
|
+
}
|
|
326
|
+
catch (error) {
|
|
327
|
+
throw mapTransportError(error);
|
|
328
|
+
}
|
|
329
|
+
}
|
|
330
|
+
}
|
|
331
|
+
function mapSession(value) {
|
|
332
|
+
return {
|
|
333
|
+
contractVersion: 'crowdy.studio-agent/1',
|
|
334
|
+
sessionId: value.sessionId,
|
|
335
|
+
appId: String(value.appId),
|
|
336
|
+
...(value.projectId ? { projectId: value.projectId } : {}),
|
|
337
|
+
...(value.gridId ? { gridId: String(value.gridId) } : {}),
|
|
338
|
+
mode: value.mode,
|
|
339
|
+
status: value.status,
|
|
340
|
+
requestedModel: value.requestedModel,
|
|
341
|
+
...(value.model ? { model: value.model } : {}),
|
|
342
|
+
...(value.resolvedModel ? { resolvedModel: value.resolvedModel } : {}),
|
|
343
|
+
providerDataConsent: value.providerDataConsent,
|
|
344
|
+
registryDigest: value.registryDigest,
|
|
345
|
+
providerPolicyVersion: value.providerPolicyVersion,
|
|
346
|
+
appPolicyVersion: value.appPolicyVersion,
|
|
347
|
+
contextVersion: value.contextVersion,
|
|
348
|
+
currentClientEpoch: String(value.currentClientEpoch),
|
|
349
|
+
...(value.clientEpoch ? { clientEpoch: String(value.clientEpoch) } : {}),
|
|
350
|
+
lastEventSeq: String(value.lastEventSeq),
|
|
351
|
+
...(value.currentRun ? { currentRun: mapRun(value.currentRun) } : {}),
|
|
352
|
+
activeLeases: value.activeLeases.map(mapLease),
|
|
353
|
+
...(value.pendingApproval
|
|
354
|
+
? { pendingApproval: mapApproval(value.pendingApproval) }
|
|
355
|
+
: {}),
|
|
356
|
+
createdAt: value.createdAt,
|
|
357
|
+
updatedAt: value.updatedAt,
|
|
358
|
+
...(value.closedAt ? { closedAt: value.closedAt } : {}),
|
|
359
|
+
};
|
|
360
|
+
}
|
|
361
|
+
function mapRun(value) {
|
|
362
|
+
return {
|
|
363
|
+
runId: value.runId,
|
|
364
|
+
status: value.status,
|
|
365
|
+
providerRounds: value.providerRounds,
|
|
366
|
+
toolCalls: value.toolCalls,
|
|
367
|
+
...(value.errorCode ? { errorCode: value.errorCode } : {}),
|
|
368
|
+
...(value.terminalReason
|
|
369
|
+
? { terminalReason: value.terminalReason }
|
|
370
|
+
: {}),
|
|
371
|
+
...(value.reason ? { reason: value.reason } : {}),
|
|
372
|
+
...(value.startedAt ? { startedAt: value.startedAt } : {}),
|
|
373
|
+
...(value.finishedAt ? { finishedAt: value.finishedAt } : {}),
|
|
374
|
+
createdAt: value.createdAt,
|
|
375
|
+
cancelled: value.cancelled,
|
|
376
|
+
};
|
|
377
|
+
}
|
|
378
|
+
function mapApproval(value, reasons = []) {
|
|
379
|
+
return {
|
|
380
|
+
approvalId: value.approvalId,
|
|
381
|
+
toolCallId: value.toolCallId,
|
|
382
|
+
argumentHash: value.argumentHash,
|
|
383
|
+
status: value.status,
|
|
384
|
+
safeSummary: value.safeSummary,
|
|
385
|
+
reasons,
|
|
386
|
+
clientEpoch: String(value.clientEpoch),
|
|
387
|
+
expiresAt: value.expiresAt,
|
|
388
|
+
approved: value.approved,
|
|
389
|
+
rejected: value.rejected,
|
|
390
|
+
};
|
|
391
|
+
}
|
|
392
|
+
function mapLease(value) {
|
|
393
|
+
return {
|
|
394
|
+
leaseId: value.leaseId,
|
|
395
|
+
kind: value.kind,
|
|
396
|
+
status: value.status,
|
|
397
|
+
clientEpoch: String(value.clientEpoch),
|
|
398
|
+
scopes: value.scopes,
|
|
399
|
+
holder: value.holder,
|
|
400
|
+
...(value.controlledEntityId
|
|
401
|
+
? { controlledEntityId: value.controlledEntityId }
|
|
402
|
+
: {}),
|
|
403
|
+
...(value.hostCapabilityRevision
|
|
404
|
+
? { hostCapabilityRevision: value.hostCapabilityRevision }
|
|
405
|
+
: {}),
|
|
406
|
+
...(value.expectedProjectRevision
|
|
407
|
+
? { expectedProjectRevision: String(value.expectedProjectRevision) }
|
|
408
|
+
: {}),
|
|
409
|
+
contextVersion: value.contextVersion,
|
|
410
|
+
grantedAt: value.grantedAt,
|
|
411
|
+
expiresAt: value.expiresAt,
|
|
412
|
+
...(value.revokedReason
|
|
413
|
+
? {
|
|
414
|
+
revokedReason: mapPreemptionReason(value.revokedReason),
|
|
415
|
+
}
|
|
416
|
+
: {}),
|
|
417
|
+
};
|
|
418
|
+
}
|
|
419
|
+
function mapBudget(value) {
|
|
420
|
+
return {
|
|
421
|
+
dimensions: value.dimensions.map((dimension) => {
|
|
422
|
+
assertBudgetName(dimension.name);
|
|
423
|
+
assertBudgetScope(dimension.scope);
|
|
424
|
+
return {
|
|
425
|
+
name: dimension.name,
|
|
426
|
+
scope: dimension.scope,
|
|
427
|
+
limit: String(dimension.limit),
|
|
428
|
+
reserved: String(dimension.reserved),
|
|
429
|
+
consumed: String(dimension.consumed),
|
|
430
|
+
remaining: String(dimension.remaining),
|
|
431
|
+
unit: dimension.unit,
|
|
432
|
+
};
|
|
433
|
+
}),
|
|
434
|
+
...(value.resetAt ? { resetAt: value.resetAt } : {}),
|
|
435
|
+
platformFunded: value.platformFunded,
|
|
436
|
+
payer: mapPayer(value.payer),
|
|
437
|
+
};
|
|
438
|
+
}
|
|
439
|
+
function mapDescriptor(value) {
|
|
440
|
+
const parsed = parseJsonObject(value.descriptorJson, 'descriptorJson');
|
|
441
|
+
if (canonicalJson(parsed) !== value.descriptorJson) {
|
|
442
|
+
throw new CrowdyAgentError('AGENT_CONTEXT_STALE', `${value.name} descriptor JSON is not canonical`);
|
|
443
|
+
}
|
|
444
|
+
if (digestCanonicalJson(parsed) !== value.descriptorDigest) {
|
|
445
|
+
throw new CrowdyAgentError('AGENT_CONTEXT_STALE', `${value.name} descriptor digest does not match its canonical JSON`);
|
|
446
|
+
}
|
|
447
|
+
const descriptor = parsed;
|
|
448
|
+
if (descriptor.name !== value.name ||
|
|
449
|
+
descriptor.version !== value.version ||
|
|
450
|
+
descriptor.wireName !== value.wireName ||
|
|
451
|
+
descriptor.schemaVersion !== value.schemaVersion ||
|
|
452
|
+
descriptor.summary !== value.summary ||
|
|
453
|
+
descriptor.executor !== value.executor ||
|
|
454
|
+
canonicalJson(descriptor.modes) !== canonicalJson(value.modes) ||
|
|
455
|
+
descriptor.risk.class !== value.risk ||
|
|
456
|
+
canonicalJson(descriptor.risk.effects) !==
|
|
457
|
+
canonicalJson(value.riskEffects) ||
|
|
458
|
+
descriptor.risk.reversible !== value.riskReversible ||
|
|
459
|
+
canonicalJson(descriptor.scopes.map((scope) => scope.scope)) !==
|
|
460
|
+
canonicalJson(value.scopes) ||
|
|
461
|
+
canonicalJson(descriptor.scopes) !== value.scopeRequirementsJson ||
|
|
462
|
+
(descriptor.approval.policy === 'REQUIRED') !==
|
|
463
|
+
value.approvalRequired ||
|
|
464
|
+
descriptor.approval.policy !== value.approvalPolicy ||
|
|
465
|
+
canonicalJson(descriptor.approval.reasons) !==
|
|
466
|
+
canonicalJson(value.approvalReasons) ||
|
|
467
|
+
descriptor.approval.maxTtlSeconds !== value.approvalMaxTtlSeconds ||
|
|
468
|
+
descriptor.idempotency.class !== value.idempotencyClass ||
|
|
469
|
+
descriptor.idempotency.keyScope !== value.idempotencyKeyScope ||
|
|
470
|
+
descriptor.timeoutMs !== value.timeoutMs ||
|
|
471
|
+
canonicalJson(descriptor.inputSchema) !== value.inputSchemaJson ||
|
|
472
|
+
canonicalJson(descriptor.outputSchema) !== value.outputSchemaJson ||
|
|
473
|
+
canonicalJson(descriptor.redaction.input) !== value.inputRedactionJson ||
|
|
474
|
+
canonicalJson(descriptor.redaction.output) !== value.outputRedactionJson ||
|
|
475
|
+
descriptor.redaction.maxPersistedBytes !== value.maxPersistedBytes) {
|
|
476
|
+
throw new CrowdyAgentError('AGENT_CONTEXT_STALE', `${value.name} descriptor fields diverge from descriptorJson`);
|
|
477
|
+
}
|
|
478
|
+
return descriptor;
|
|
479
|
+
}
|
|
480
|
+
function mapEvent(value) {
|
|
481
|
+
const base = {
|
|
482
|
+
protocolVersion: value.protocolVersion,
|
|
483
|
+
eventId: value.eventId,
|
|
484
|
+
sessionId: value.sessionId,
|
|
485
|
+
seq: String(value.seq),
|
|
486
|
+
createdAt: value.createdAt,
|
|
487
|
+
};
|
|
488
|
+
const type = value.type;
|
|
489
|
+
switch (value.__typename) {
|
|
490
|
+
case 'AgentLifecycleEvent':
|
|
491
|
+
if (type === 'MODE_SELECTED') {
|
|
492
|
+
if (!value.lifecycleMode) {
|
|
493
|
+
throw invalidEvent('MODE_SELECTED omitted mode');
|
|
494
|
+
}
|
|
495
|
+
return {
|
|
496
|
+
...base,
|
|
497
|
+
type,
|
|
498
|
+
payload: { mode: value.lifecycleMode },
|
|
499
|
+
};
|
|
500
|
+
}
|
|
501
|
+
if (type === 'CONTEXT_CHANGED') {
|
|
502
|
+
if (!value.lifecycleContextVersion) {
|
|
503
|
+
throw invalidEvent('CONTEXT_CHANGED omitted contextVersion');
|
|
504
|
+
}
|
|
505
|
+
return {
|
|
506
|
+
...base,
|
|
507
|
+
type,
|
|
508
|
+
payload: {
|
|
509
|
+
contextVersion: value.lifecycleContextVersion,
|
|
510
|
+
reason: value.lifecycleReason ?? 'CONTEXT_CHANGED',
|
|
511
|
+
},
|
|
512
|
+
};
|
|
513
|
+
}
|
|
514
|
+
if (type === 'CLIENT_ATTACHED' || type === 'CLIENT_DETACHED') {
|
|
515
|
+
return {
|
|
516
|
+
...base,
|
|
517
|
+
type,
|
|
518
|
+
payload: {
|
|
519
|
+
...(value.lifecycleClientEpoch
|
|
520
|
+
? { clientEpoch: String(value.lifecycleClientEpoch) }
|
|
521
|
+
: {}),
|
|
522
|
+
...(value.lifecycleReplayAfterSeq
|
|
523
|
+
? { replayAfterSeq: String(value.lifecycleReplayAfterSeq) }
|
|
524
|
+
: {}),
|
|
525
|
+
...(value.lifecycleReason
|
|
526
|
+
? { reason: value.lifecycleReason }
|
|
527
|
+
: {}),
|
|
528
|
+
},
|
|
529
|
+
};
|
|
530
|
+
}
|
|
531
|
+
return {
|
|
532
|
+
...base,
|
|
533
|
+
type,
|
|
534
|
+
payload: {
|
|
535
|
+
sessionId: value.sessionId,
|
|
536
|
+
...(value.lifecycleReason
|
|
537
|
+
? { reason: value.lifecycleReason }
|
|
538
|
+
: {}),
|
|
539
|
+
},
|
|
540
|
+
};
|
|
541
|
+
case 'AgentMessageEvent': {
|
|
542
|
+
const role = value.messageRole;
|
|
543
|
+
if (role !== 'USER' && role !== 'ASSISTANT') {
|
|
544
|
+
throw invalidEvent('Message event contains an unknown role');
|
|
545
|
+
}
|
|
546
|
+
if (type === 'ASSISTANT_CHUNK') {
|
|
547
|
+
return {
|
|
548
|
+
...base,
|
|
549
|
+
type,
|
|
550
|
+
payload: {
|
|
551
|
+
runId: value.runId ?? '',
|
|
552
|
+
content: value.messageContent,
|
|
553
|
+
},
|
|
554
|
+
};
|
|
555
|
+
}
|
|
556
|
+
const message = {
|
|
557
|
+
messageId: value.messageEventId,
|
|
558
|
+
role,
|
|
559
|
+
content: value.messageContent,
|
|
560
|
+
...(value.runId ? { runId: value.runId } : {}),
|
|
561
|
+
createdAt: value.createdAt,
|
|
562
|
+
};
|
|
563
|
+
return {
|
|
564
|
+
...base,
|
|
565
|
+
type,
|
|
566
|
+
payload: { message },
|
|
567
|
+
};
|
|
568
|
+
}
|
|
569
|
+
case 'AgentRunEvent':
|
|
570
|
+
if (!value.runId)
|
|
571
|
+
throw invalidEvent('Run event omitted runId');
|
|
572
|
+
return {
|
|
573
|
+
...base,
|
|
574
|
+
type,
|
|
575
|
+
payload: {
|
|
576
|
+
runId: value.runId,
|
|
577
|
+
status: value.runStatus,
|
|
578
|
+
...(value.runCode ? { code: value.runCode } : {}),
|
|
579
|
+
...(value.runReason ? { reason: value.runReason } : {}),
|
|
580
|
+
...(value.runError ? { error: mapError(value.runError) } : {}),
|
|
581
|
+
},
|
|
582
|
+
};
|
|
583
|
+
case 'AgentToolEvent':
|
|
584
|
+
return {
|
|
585
|
+
...base,
|
|
586
|
+
type,
|
|
587
|
+
payload: {
|
|
588
|
+
toolCallId: value.toolEventCallId,
|
|
589
|
+
name: value.toolEventName,
|
|
590
|
+
version: value.toolEventVersion,
|
|
591
|
+
status: value.toolStatus,
|
|
592
|
+
...(value.toolSafeSummary
|
|
593
|
+
? { safeSummary: value.toolSafeSummary }
|
|
594
|
+
: {}),
|
|
595
|
+
...(value.toolArgumentHash
|
|
596
|
+
? { argumentHash: value.toolArgumentHash }
|
|
597
|
+
: {}),
|
|
598
|
+
...(value.toolInvocation
|
|
599
|
+
? { invocation: mapInvocation(value.toolInvocation) }
|
|
600
|
+
: {}),
|
|
601
|
+
...(value.toolResult
|
|
602
|
+
? { result: mapResultEnvelope(value.toolResult) }
|
|
603
|
+
: {}),
|
|
604
|
+
...(value.toolError ? { error: mapError(value.toolError) } : {}),
|
|
605
|
+
},
|
|
606
|
+
};
|
|
607
|
+
case 'AgentApprovalEvent':
|
|
608
|
+
return {
|
|
609
|
+
...base,
|
|
610
|
+
type,
|
|
611
|
+
payload: {
|
|
612
|
+
approval: {
|
|
613
|
+
approvalId: value.approvalEventId,
|
|
614
|
+
toolCallId: value.approvalToolCallId,
|
|
615
|
+
argumentHash: value.approvalArgumentHash,
|
|
616
|
+
status: value.approvalStatus,
|
|
617
|
+
safeSummary: value.approvalSafeSummary,
|
|
618
|
+
reasons: value.approvalReasons,
|
|
619
|
+
expiresAt: value.approvalExpiresAt,
|
|
620
|
+
approved: value.approvalStatus === 'GRANTED' ||
|
|
621
|
+
value.approvalStatus === 'CONSUMED',
|
|
622
|
+
rejected: value.approvalStatus === 'DENIED',
|
|
623
|
+
},
|
|
624
|
+
},
|
|
625
|
+
};
|
|
626
|
+
case 'AgentLeaseEvent':
|
|
627
|
+
return {
|
|
628
|
+
...base,
|
|
629
|
+
type,
|
|
630
|
+
payload: {
|
|
631
|
+
lease: {
|
|
632
|
+
leaseId: value.leaseEventId,
|
|
633
|
+
kind: value.leaseKind,
|
|
634
|
+
status: value.leaseStatus,
|
|
635
|
+
clientEpoch: String(value.leaseClientEpoch),
|
|
636
|
+
scopes: value.leaseScopes,
|
|
637
|
+
holder: value.leaseHolder,
|
|
638
|
+
contextVersion: value.leaseContextVersion,
|
|
639
|
+
...(value.leaseControlledEntityId
|
|
640
|
+
? { controlledEntityId: value.leaseControlledEntityId }
|
|
641
|
+
: {}),
|
|
642
|
+
...(value.leaseHostCapabilityRevision
|
|
643
|
+
? {
|
|
644
|
+
hostCapabilityRevision: value.leaseHostCapabilityRevision,
|
|
645
|
+
}
|
|
646
|
+
: {}),
|
|
647
|
+
...(value.leaseExpectedProjectRevision
|
|
648
|
+
? {
|
|
649
|
+
expectedProjectRevision: String(value.leaseExpectedProjectRevision),
|
|
650
|
+
}
|
|
651
|
+
: {}),
|
|
652
|
+
grantedAt: value.leaseGrantedAt,
|
|
653
|
+
expiresAt: value.leaseExpiresAt,
|
|
654
|
+
...(value.leaseReason
|
|
655
|
+
? {
|
|
656
|
+
revokedReason: mapPreemptionReason(value.leaseReason),
|
|
657
|
+
}
|
|
658
|
+
: {}),
|
|
659
|
+
},
|
|
660
|
+
},
|
|
661
|
+
};
|
|
662
|
+
case 'AgentCheckpointEvent':
|
|
663
|
+
if (value.checkpointReason !== 'AGENT_WRITE' &&
|
|
664
|
+
value.checkpointReason !== 'RESTORE_PREIMAGE' &&
|
|
665
|
+
value.checkpointReason !== 'MANUAL') {
|
|
666
|
+
throw invalidEvent(`Unknown checkpoint reason ${value.checkpointReason}`);
|
|
667
|
+
}
|
|
668
|
+
return {
|
|
669
|
+
...base,
|
|
670
|
+
type,
|
|
671
|
+
payload: {
|
|
672
|
+
checkpoint: {
|
|
673
|
+
checkpointId: value.checkpointEventId,
|
|
674
|
+
projectRevision: String(value.checkpointProjectRevision),
|
|
675
|
+
contentHash: value.checkpointContentHash,
|
|
676
|
+
reason: value.checkpointReason,
|
|
677
|
+
files: value.checkpointFiles.map((file) => {
|
|
678
|
+
if (file.target !== 'SERVER' && file.target !== 'CLIENT') {
|
|
679
|
+
throw invalidEvent(`Unknown checkpoint file target ${file.target}`);
|
|
680
|
+
}
|
|
681
|
+
return {
|
|
682
|
+
target: file.target,
|
|
683
|
+
path: file.path,
|
|
684
|
+
contentHash: file.contentHash,
|
|
685
|
+
byteLength: file.byteLength,
|
|
686
|
+
};
|
|
687
|
+
}),
|
|
688
|
+
createdAt: value.createdAt,
|
|
689
|
+
...(value.checkpointRestoredAt
|
|
690
|
+
? { restoredAt: value.checkpointRestoredAt }
|
|
691
|
+
: {}),
|
|
692
|
+
},
|
|
693
|
+
},
|
|
694
|
+
};
|
|
695
|
+
case 'AgentBudgetEvent':
|
|
696
|
+
return {
|
|
697
|
+
...base,
|
|
698
|
+
type,
|
|
699
|
+
payload: { budget: mapBudget(value.budgetSnapshot) },
|
|
700
|
+
};
|
|
701
|
+
}
|
|
702
|
+
}
|
|
703
|
+
function mapInvocation(value) {
|
|
704
|
+
return {
|
|
705
|
+
protocolVersion: value.protocolVersion,
|
|
706
|
+
sessionId: value.sessionId,
|
|
707
|
+
runId: value.runId,
|
|
708
|
+
toolCallId: value.toolCallId,
|
|
709
|
+
name: value.name,
|
|
710
|
+
version: value.version,
|
|
711
|
+
descriptorDigest: value.descriptorDigest,
|
|
712
|
+
arguments: parseJsonObject(value.argumentsJson, 'argumentsJson'),
|
|
713
|
+
argumentHash: value.argumentHash,
|
|
714
|
+
contextVersion: value.contextVersion,
|
|
715
|
+
...(value.clientEpoch
|
|
716
|
+
? { clientEpoch: String(value.clientEpoch) }
|
|
717
|
+
: {}),
|
|
718
|
+
...(value.leaseId ? { leaseId: value.leaseId } : {}),
|
|
719
|
+
...(value.approvalGrant
|
|
720
|
+
? { approvalGrant: value.approvalGrant }
|
|
721
|
+
: {}),
|
|
722
|
+
...(value.idempotencyKey
|
|
723
|
+
? { idempotencyKey: value.idempotencyKey }
|
|
724
|
+
: {}),
|
|
725
|
+
deadline: value.deadline,
|
|
726
|
+
};
|
|
727
|
+
}
|
|
728
|
+
function mapResultEnvelope(value) {
|
|
729
|
+
return {
|
|
730
|
+
protocolVersion: value.protocolVersion,
|
|
731
|
+
toolCallId: value.toolCallId,
|
|
732
|
+
status: value.status,
|
|
733
|
+
...(value.outputJson
|
|
734
|
+
? { output: parseJsonObject(value.outputJson, 'outputJson') }
|
|
735
|
+
: {}),
|
|
736
|
+
...(value.error ? { error: mapError(value.error) } : {}),
|
|
737
|
+
observedContextVersion: value.observedContextVersion,
|
|
738
|
+
startedAt: value.startedAt,
|
|
739
|
+
finishedAt: value.finishedAt,
|
|
740
|
+
};
|
|
741
|
+
}
|
|
742
|
+
function mapError(value) {
|
|
743
|
+
return {
|
|
744
|
+
code: value.code,
|
|
745
|
+
message: value.message,
|
|
746
|
+
retryable: value.retryable,
|
|
747
|
+
...(value.remediation ? { remediation: value.remediation } : {}),
|
|
748
|
+
...(value.field ? { field: value.field } : {}),
|
|
749
|
+
...(value.requiredScope ? { requiredScope: value.requiredScope } : {}),
|
|
750
|
+
};
|
|
751
|
+
}
|
|
752
|
+
function parseJsonObject(value, field) {
|
|
753
|
+
try {
|
|
754
|
+
const parsed = JSON.parse(value);
|
|
755
|
+
if (parsed === null ||
|
|
756
|
+
typeof parsed !== 'object' ||
|
|
757
|
+
Array.isArray(parsed)) {
|
|
758
|
+
throw new Error('not object');
|
|
759
|
+
}
|
|
760
|
+
return parsed;
|
|
761
|
+
}
|
|
762
|
+
catch {
|
|
763
|
+
throw new CrowdyAgentError('AGENT_EVENT_CURSOR_INVALID', `${field} must contain one JSON object`, { field });
|
|
764
|
+
}
|
|
765
|
+
}
|
|
766
|
+
function assertBudgetName(value) {
|
|
767
|
+
if (![
|
|
768
|
+
'REQUESTS',
|
|
769
|
+
'INPUT_TOKENS',
|
|
770
|
+
'OUTPUT_TOKENS',
|
|
771
|
+
'REASONING_TOKENS',
|
|
772
|
+
'PROVIDER_COST',
|
|
773
|
+
'TOOL_ROUNDS',
|
|
774
|
+
'WALL_CLOCK_MS',
|
|
775
|
+
'TOOL_CALLS',
|
|
776
|
+
'COMPILES',
|
|
777
|
+
].includes(value)) {
|
|
778
|
+
throw invalidEvent(`Unknown budget dimension ${value}`);
|
|
779
|
+
}
|
|
780
|
+
}
|
|
781
|
+
function assertBudgetScope(value) {
|
|
782
|
+
if (!['TURN', 'SESSION', 'PLAYER_DAY'].includes(value)) {
|
|
783
|
+
throw invalidEvent(`Unknown budget scope ${value}`);
|
|
784
|
+
}
|
|
785
|
+
}
|
|
786
|
+
function mapPayer(value) {
|
|
787
|
+
if (value !== 'PLATFORM' && value !== 'APP' && value !== 'USER') {
|
|
788
|
+
throw invalidEvent(`Unknown agent budget payer ${value}`);
|
|
789
|
+
}
|
|
790
|
+
return value;
|
|
791
|
+
}
|
|
792
|
+
function mapPreemptionReason(value) {
|
|
793
|
+
const reasons = [
|
|
794
|
+
'HUMAN_INPUT',
|
|
795
|
+
'HUMAN_EDIT',
|
|
796
|
+
'HUMAN_STOP',
|
|
797
|
+
'ESCAPE',
|
|
798
|
+
'DEATH',
|
|
799
|
+
'CONTEXT_CHANGED',
|
|
800
|
+
'PERMISSION_CHANGED',
|
|
801
|
+
'ADMISSION_CHANGED',
|
|
802
|
+
'CONTROL_TARGET_CHANGED',
|
|
803
|
+
'DISCONNECTED',
|
|
804
|
+
'CLIENT_REATTACHED',
|
|
805
|
+
'QUOTA_FAILURE',
|
|
806
|
+
'BUDGET_FAILURE',
|
|
807
|
+
'OPERATOR_KILL',
|
|
808
|
+
'LEASE_EXPIRED',
|
|
809
|
+
'SESSION_CLOSED',
|
|
810
|
+
];
|
|
811
|
+
if (!reasons.includes(value)) {
|
|
812
|
+
throw invalidEvent(`Unknown agent preemption reason ${value}`);
|
|
813
|
+
}
|
|
814
|
+
return value;
|
|
815
|
+
}
|
|
816
|
+
function invalidEvent(message) {
|
|
817
|
+
return new CrowdyAgentError('AGENT_EVENT_CURSOR_INVALID', message);
|
|
818
|
+
}
|
|
819
|
+
function mapGraphQLErrors(errors) {
|
|
820
|
+
const payloads = errors.filter((error) => error !== null &&
|
|
821
|
+
typeof error === 'object' &&
|
|
822
|
+
typeof error.message === 'string');
|
|
823
|
+
return mapTransportError(new CrowdyGraphQLError(payloads.length > 0
|
|
824
|
+
? payloads
|
|
825
|
+
: [{ message: 'Agent subscription failed' }]));
|
|
826
|
+
}
|
|
827
|
+
function mapTransportError(error) {
|
|
828
|
+
if (error instanceof CrowdyAgentError)
|
|
829
|
+
return error;
|
|
830
|
+
if (error instanceof CrowdyGraphQLError) {
|
|
831
|
+
const code = error.code;
|
|
832
|
+
if (typeof code === 'string' &&
|
|
833
|
+
(code.startsWith('AGENT_') ||
|
|
834
|
+
code === 'CROWDY_STUDIO_REVISION_CONFLICT')) {
|
|
835
|
+
return new CrowdyAgentError(code, error.message, {
|
|
836
|
+
retryable: error.extensions?.retryable === true,
|
|
837
|
+
...(typeof error.extensions?.remediation === 'string'
|
|
838
|
+
? { remediation: error.extensions.remediation }
|
|
839
|
+
: {}),
|
|
840
|
+
...(typeof error.extensions?.field === 'string'
|
|
841
|
+
? { field: error.extensions.field }
|
|
842
|
+
: {}),
|
|
843
|
+
...(typeof error.extensions?.requiredScope === 'string'
|
|
844
|
+
? { requiredScope: error.extensions.requiredScope }
|
|
845
|
+
: {}),
|
|
846
|
+
cause: error,
|
|
847
|
+
});
|
|
848
|
+
}
|
|
849
|
+
return error;
|
|
850
|
+
}
|
|
851
|
+
if (Array.isArray(error))
|
|
852
|
+
return mapGraphQLErrors(error);
|
|
853
|
+
return new CrowdyAgentError('AGENT_DISCONNECTED', 'Crowdy agent GraphQL transport disconnected', { retryable: true, cause: error });
|
|
854
|
+
}
|