remote-codex 0.1.5 → 0.1.7
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/apps/supervisor-api/dist/index.js +7749 -5501
- package/apps/supervisor-web/dist/assets/{highlighted-body-OFNGDK62-D-RjOTTL.js → highlighted-body-OFNGDK62-0cYcfOfd.js} +1 -1
- package/apps/supervisor-web/dist/assets/index-CbIt0KnL.css +32 -0
- package/apps/supervisor-web/dist/assets/index-nH6a8Wwn.js +377 -0
- package/apps/supervisor-web/dist/assets/{xterm-D8iZbRww.js → xterm-DisVWgDR.js} +1 -1
- package/apps/supervisor-web/dist/index.html +2 -2
- package/package.json +5 -1
- package/packages/agent-runtime/src/index.ts +2 -0
- package/packages/agent-runtime/src/registry.ts +44 -0
- package/packages/agent-runtime/src/types.ts +531 -0
- package/packages/codex/src/appServerManager.test.ts +328 -0
- package/packages/codex/src/appServerManager.ts +656 -0
- package/packages/codex/src/historyItems.ts +1185 -0
- package/packages/codex/src/hookHistory.ts +224 -0
- package/packages/codex/src/index.ts +6 -0
- package/packages/codex/src/jsonrpc.test.ts +58 -0
- package/packages/codex/src/jsonrpc.ts +198 -0
- package/packages/codex/src/requestMapper.test.ts +127 -0
- package/packages/codex/src/requestMapper.ts +511 -0
- package/packages/codex/src/runtimeAdapter.ts +692 -0
- package/packages/codex/src/types.ts +403 -0
- package/packages/db/migrations/0014_thread_history_items.sql +12 -0
- package/packages/db/migrations/0015_agent_provider_fields.sql +14 -0
- package/packages/db/migrations/0016_remove_codex_thread_goal_id.sql +46 -0
- package/packages/db/migrations/0017_remove_codex_thread_columns.sql +85 -0
- package/packages/db/src/client.ts +53 -0
- package/packages/db/src/index.ts +5 -0
- package/packages/db/src/migrate.test.ts +36 -0
- package/packages/db/src/migrate.ts +84 -0
- package/packages/db/src/repositories.ts +893 -0
- package/packages/db/src/schema.ts +177 -0
- package/packages/db/src/seed.ts +51 -0
- package/packages/shared/src/index.ts +878 -0
- package/scripts/service-manager.mjs +6 -4
- package/apps/supervisor-web/dist/assets/index-CdG3ogmZ.js +0 -376
- package/apps/supervisor-web/dist/assets/index-QM8NQf3e.css +0 -32
|
@@ -0,0 +1,511 @@
|
|
|
1
|
+
import type {
|
|
2
|
+
AgentActionRequest,
|
|
3
|
+
AgentActionRequestResponseInput,
|
|
4
|
+
AgentPendingProviderRequest,
|
|
5
|
+
AgentProviderRequest,
|
|
6
|
+
AgentProviderRequestMapping,
|
|
7
|
+
} from '../../agent-runtime/src/index';
|
|
8
|
+
import type { CodexServerRequest } from './types';
|
|
9
|
+
|
|
10
|
+
type CodexPendingRequestResponseKind =
|
|
11
|
+
| 'answers'
|
|
12
|
+
| 'mcpElicitation'
|
|
13
|
+
| 'commandExecutionApproval'
|
|
14
|
+
| 'fileChangeApproval'
|
|
15
|
+
| 'permissionsApproval'
|
|
16
|
+
| 'legacyExecApproval'
|
|
17
|
+
| 'legacyApplyPatchApproval';
|
|
18
|
+
|
|
19
|
+
function isRecord(value: unknown): value is Record<string, unknown> {
|
|
20
|
+
return typeof value === 'object' && value !== null && !Array.isArray(value);
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
function stringOrNull(value: unknown) {
|
|
24
|
+
return typeof value === 'string' && value.trim() ? value.trim() : null;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
function normalizeOptionLabelForApproval(value: string) {
|
|
28
|
+
return value
|
|
29
|
+
.replace(/\(recommended\)\s*$/i, '')
|
|
30
|
+
.trim()
|
|
31
|
+
.toLowerCase();
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
function isAllowOptionLabel(value: string) {
|
|
35
|
+
return /^(allow|approve|yes|continue|proceed|trust)\b/.test(value);
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
function isLikelyPositiveApprovalOption(value: string) {
|
|
39
|
+
const normalized = normalizeOptionLabelForApproval(value);
|
|
40
|
+
return (
|
|
41
|
+
isAllowOptionLabel(normalized) ||
|
|
42
|
+
/\b(allow|approve|yes|continue|proceed|trust)\b/.test(normalized)
|
|
43
|
+
);
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
function isLikelyApprovalPrompt(
|
|
47
|
+
requestMethod: string,
|
|
48
|
+
questions: Array<{
|
|
49
|
+
header: string;
|
|
50
|
+
question: string;
|
|
51
|
+
options: Array<{ label: string; description: string }> | null;
|
|
52
|
+
}>,
|
|
53
|
+
) {
|
|
54
|
+
const methodText = requestMethod.toLowerCase();
|
|
55
|
+
if (
|
|
56
|
+
methodText.includes('approval') ||
|
|
57
|
+
methodText.includes('authorize') ||
|
|
58
|
+
methodText.includes('requestuserinput')
|
|
59
|
+
) {
|
|
60
|
+
return true;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
const combinedText = questions
|
|
64
|
+
.flatMap((question) => [
|
|
65
|
+
question.header,
|
|
66
|
+
question.question,
|
|
67
|
+
...(question.options?.map((option) => option.label) ?? []),
|
|
68
|
+
])
|
|
69
|
+
.join(' ')
|
|
70
|
+
.toLowerCase();
|
|
71
|
+
|
|
72
|
+
return /(allow|approve|permission|authorize|authorization|auth|mcp|tool)/.test(
|
|
73
|
+
combinedText,
|
|
74
|
+
);
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
function buildAutoApprovedAnswersForServerQuestions(
|
|
78
|
+
requestMethod: string,
|
|
79
|
+
questions: Array<{
|
|
80
|
+
id: string;
|
|
81
|
+
header: string;
|
|
82
|
+
question: string;
|
|
83
|
+
isOther: boolean;
|
|
84
|
+
isSecret: boolean;
|
|
85
|
+
options: Array<{ label: string; description: string }> | null;
|
|
86
|
+
}>,
|
|
87
|
+
) {
|
|
88
|
+
if (!isLikelyApprovalPrompt(requestMethod, questions)) {
|
|
89
|
+
return null;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
const answers: Record<string, { answers: string[] }> = {};
|
|
93
|
+
|
|
94
|
+
for (const question of questions) {
|
|
95
|
+
if (!question.options || question.options.length === 0) {
|
|
96
|
+
return null;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
const recommendedOption = question.options.find((option) =>
|
|
100
|
+
/\(recommended\)\s*$/i.test(option.label),
|
|
101
|
+
);
|
|
102
|
+
const allowOption =
|
|
103
|
+
recommendedOption && isLikelyPositiveApprovalOption(recommendedOption.label)
|
|
104
|
+
? recommendedOption
|
|
105
|
+
: question.options.find((option) =>
|
|
106
|
+
isLikelyPositiveApprovalOption(option.label),
|
|
107
|
+
);
|
|
108
|
+
|
|
109
|
+
if (!allowOption) {
|
|
110
|
+
return null;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
answers[question.id] = {
|
|
114
|
+
answers: [allowOption.label],
|
|
115
|
+
};
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
return answers;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
function isMcpElicitationRequest(
|
|
122
|
+
request: CodexServerRequest,
|
|
123
|
+
): request is CodexServerRequest & {
|
|
124
|
+
params: {
|
|
125
|
+
threadId: string;
|
|
126
|
+
turnId?: string;
|
|
127
|
+
serverName?: string;
|
|
128
|
+
mode?: string;
|
|
129
|
+
message?: string;
|
|
130
|
+
requestedSchema?: Record<string, unknown>;
|
|
131
|
+
_meta?: Record<string, unknown>;
|
|
132
|
+
};
|
|
133
|
+
} {
|
|
134
|
+
return request.method === 'mcpServer/elicitation/request';
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
function buildAutoApprovedMcpElicitationResult(
|
|
138
|
+
request: CodexServerRequest,
|
|
139
|
+
) {
|
|
140
|
+
if (!isMcpElicitationRequest(request)) {
|
|
141
|
+
return null;
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
return {
|
|
145
|
+
action: 'accept',
|
|
146
|
+
content: {},
|
|
147
|
+
} as const;
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
function stringFromUnknown(value: unknown) {
|
|
151
|
+
return typeof value === 'string' && value.trim() ? value : null;
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
function arrayTextFromUnknown(value: unknown) {
|
|
155
|
+
if (!Array.isArray(value)) {
|
|
156
|
+
return null;
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
const parts = value
|
|
160
|
+
.map((entry) => (typeof entry === 'string' ? entry : null))
|
|
161
|
+
.filter((entry): entry is string => Boolean(entry));
|
|
162
|
+
return parts.length > 0 ? parts.join(' ') : null;
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
function commandTextFromApprovalParams(params: Record<string, unknown>) {
|
|
166
|
+
return stringFromUnknown(params.command) ?? arrayTextFromUnknown(params.command);
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
function buildApprovalRequestDescription(params: Record<string, unknown>) {
|
|
170
|
+
return [
|
|
171
|
+
stringFromUnknown(params.reason),
|
|
172
|
+
commandTextFromApprovalParams(params)
|
|
173
|
+
? `Command: ${commandTextFromApprovalParams(params)}`
|
|
174
|
+
: null,
|
|
175
|
+
stringFromUnknown(params.cwd) ? `CWD: ${stringFromUnknown(params.cwd)}` : null,
|
|
176
|
+
]
|
|
177
|
+
.filter(Boolean)
|
|
178
|
+
.join('\n');
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
function buildGenericApprovalThreadRequest(
|
|
182
|
+
request: CodexServerRequest,
|
|
183
|
+
options: {
|
|
184
|
+
title: string;
|
|
185
|
+
descriptionFallback: string;
|
|
186
|
+
},
|
|
187
|
+
): AgentActionRequest {
|
|
188
|
+
const params = request.params as {
|
|
189
|
+
turnId?: string;
|
|
190
|
+
itemId?: string;
|
|
191
|
+
};
|
|
192
|
+
const description = buildApprovalRequestDescription(request.params);
|
|
193
|
+
|
|
194
|
+
return {
|
|
195
|
+
id: String(request.id),
|
|
196
|
+
kind: 'requestUserInput',
|
|
197
|
+
title: options.title,
|
|
198
|
+
description: description || options.descriptionFallback,
|
|
199
|
+
turnId: params.turnId ?? null,
|
|
200
|
+
itemId: params.itemId ?? null,
|
|
201
|
+
createdAt: new Date().toISOString(),
|
|
202
|
+
questions: [
|
|
203
|
+
{
|
|
204
|
+
id: 'approval',
|
|
205
|
+
header: options.title,
|
|
206
|
+
question: description || options.descriptionFallback,
|
|
207
|
+
isOther: false,
|
|
208
|
+
isSecret: false,
|
|
209
|
+
options: [
|
|
210
|
+
{
|
|
211
|
+
label: 'Allow',
|
|
212
|
+
description: 'Permit this action and continue the current turn.',
|
|
213
|
+
},
|
|
214
|
+
{
|
|
215
|
+
label: 'Deny',
|
|
216
|
+
description: 'Decline this action.',
|
|
217
|
+
},
|
|
218
|
+
],
|
|
219
|
+
},
|
|
220
|
+
],
|
|
221
|
+
};
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
function yoloApprovalResultForServerRequest(request: CodexServerRequest) {
|
|
225
|
+
switch (request.method) {
|
|
226
|
+
case 'item/commandExecution/requestApproval':
|
|
227
|
+
return { decision: 'accept' };
|
|
228
|
+
case 'item/fileChange/requestApproval':
|
|
229
|
+
return { decision: 'accept' };
|
|
230
|
+
case 'item/permissions/requestApproval': {
|
|
231
|
+
const params = request.params as { permissions?: unknown };
|
|
232
|
+
return {
|
|
233
|
+
permissions: isRecord(params.permissions) ? params.permissions : {},
|
|
234
|
+
scope: 'turn',
|
|
235
|
+
};
|
|
236
|
+
}
|
|
237
|
+
case 'execCommandApproval':
|
|
238
|
+
return { decision: 'approved' };
|
|
239
|
+
case 'applyPatchApproval':
|
|
240
|
+
return { decision: 'approved' };
|
|
241
|
+
default:
|
|
242
|
+
return null;
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
function responseKindForApprovalRequest(
|
|
247
|
+
request: CodexServerRequest,
|
|
248
|
+
): CodexPendingRequestResponseKind | null {
|
|
249
|
+
switch (request.method) {
|
|
250
|
+
case 'item/commandExecution/requestApproval':
|
|
251
|
+
return 'commandExecutionApproval';
|
|
252
|
+
case 'item/fileChange/requestApproval':
|
|
253
|
+
return 'fileChangeApproval';
|
|
254
|
+
case 'item/permissions/requestApproval':
|
|
255
|
+
return 'permissionsApproval';
|
|
256
|
+
case 'execCommandApproval':
|
|
257
|
+
return 'legacyExecApproval';
|
|
258
|
+
case 'applyPatchApproval':
|
|
259
|
+
return 'legacyApplyPatchApproval';
|
|
260
|
+
default:
|
|
261
|
+
return null;
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
function buildThreadRequestFromMcpElicitation(
|
|
266
|
+
request: CodexServerRequest & {
|
|
267
|
+
params: {
|
|
268
|
+
threadId: string;
|
|
269
|
+
turnId?: string;
|
|
270
|
+
serverName?: string;
|
|
271
|
+
mode?: string;
|
|
272
|
+
message?: string;
|
|
273
|
+
requestedSchema?: Record<string, unknown>;
|
|
274
|
+
_meta?: Record<string, unknown>;
|
|
275
|
+
};
|
|
276
|
+
},
|
|
277
|
+
): AgentActionRequest {
|
|
278
|
+
const meta = isRecord(request.params._meta) ? request.params._meta : null;
|
|
279
|
+
const toolTitle = stringOrNull(meta?.tool_title);
|
|
280
|
+
const toolDescription = stringOrNull(meta?.tool_description);
|
|
281
|
+
const serverName = stringOrNull(request.params.serverName) ?? 'MCP';
|
|
282
|
+
const message =
|
|
283
|
+
stringOrNull(request.params.message) ??
|
|
284
|
+
`Allow the ${serverName} MCP server to continue?`;
|
|
285
|
+
|
|
286
|
+
return {
|
|
287
|
+
id: String(request.id),
|
|
288
|
+
kind: 'requestUserInput',
|
|
289
|
+
title: toolTitle ?? `${serverName} MCP`,
|
|
290
|
+
description: toolDescription ?? message,
|
|
291
|
+
turnId: request.params.turnId ?? null,
|
|
292
|
+
itemId: null,
|
|
293
|
+
createdAt: new Date().toISOString(),
|
|
294
|
+
questions: [
|
|
295
|
+
{
|
|
296
|
+
id: 'decision',
|
|
297
|
+
header: toolTitle ?? `${serverName} MCP`,
|
|
298
|
+
question: message,
|
|
299
|
+
isOther: false,
|
|
300
|
+
isSecret: false,
|
|
301
|
+
options: [
|
|
302
|
+
{
|
|
303
|
+
label: 'Allow',
|
|
304
|
+
description: 'Permit this MCP tool call.',
|
|
305
|
+
},
|
|
306
|
+
{
|
|
307
|
+
label: 'Deny',
|
|
308
|
+
description: 'Reject this MCP tool call.',
|
|
309
|
+
},
|
|
310
|
+
],
|
|
311
|
+
},
|
|
312
|
+
],
|
|
313
|
+
};
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
export function buildCodexProviderRequestResponse(
|
|
317
|
+
pending: AgentPendingProviderRequest,
|
|
318
|
+
input: AgentActionRequestResponseInput,
|
|
319
|
+
) {
|
|
320
|
+
const selectedAnswer = Object.values(input.answers)[0]?.answers[0]?.trim().toLowerCase();
|
|
321
|
+
const allowed = Boolean(selectedAnswer && /^(allow|approve|yes|continue|proceed)\b/.test(selectedAnswer));
|
|
322
|
+
|
|
323
|
+
switch (pending.responseKind as CodexPendingRequestResponseKind) {
|
|
324
|
+
case 'mcpElicitation':
|
|
325
|
+
return {
|
|
326
|
+
action: allowed ? 'accept' : 'decline',
|
|
327
|
+
content: {},
|
|
328
|
+
};
|
|
329
|
+
case 'commandExecutionApproval':
|
|
330
|
+
return { decision: allowed ? 'accept' : 'decline' };
|
|
331
|
+
case 'fileChangeApproval':
|
|
332
|
+
return { decision: allowed ? 'accept' : 'decline' };
|
|
333
|
+
case 'permissionsApproval':
|
|
334
|
+
return allowed
|
|
335
|
+
? {
|
|
336
|
+
permissions:
|
|
337
|
+
isRecord(pending.responsePayload?.permissions)
|
|
338
|
+
? pending.responsePayload.permissions
|
|
339
|
+
: {},
|
|
340
|
+
scope: 'turn',
|
|
341
|
+
}
|
|
342
|
+
: {
|
|
343
|
+
permissions: {},
|
|
344
|
+
scope: 'turn',
|
|
345
|
+
};
|
|
346
|
+
case 'legacyExecApproval':
|
|
347
|
+
case 'legacyApplyPatchApproval':
|
|
348
|
+
return { decision: allowed ? 'approved' : 'denied' };
|
|
349
|
+
case 'answers':
|
|
350
|
+
default:
|
|
351
|
+
return {
|
|
352
|
+
answers: input.answers,
|
|
353
|
+
};
|
|
354
|
+
}
|
|
355
|
+
}
|
|
356
|
+
|
|
357
|
+
export function mapCodexProviderRequest(
|
|
358
|
+
providerRequest: AgentProviderRequest,
|
|
359
|
+
approvalMode: 'yolo' | 'guarded',
|
|
360
|
+
): AgentProviderRequestMapping | null {
|
|
361
|
+
const request: CodexServerRequest = {
|
|
362
|
+
id: Number(providerRequest.id),
|
|
363
|
+
method: providerRequest.method,
|
|
364
|
+
params: isRecord(providerRequest.params) ? providerRequest.params : {},
|
|
365
|
+
};
|
|
366
|
+
const providerRequestId = providerRequest.id;
|
|
367
|
+
const approvalResponseKind = responseKindForApprovalRequest(request);
|
|
368
|
+
if (approvalResponseKind) {
|
|
369
|
+
const params = request.params as {
|
|
370
|
+
threadId?: string;
|
|
371
|
+
conversationId?: string;
|
|
372
|
+
permissions?: unknown;
|
|
373
|
+
};
|
|
374
|
+
const providerSessionId = params.threadId ?? params.conversationId;
|
|
375
|
+
if (!providerSessionId) {
|
|
376
|
+
return null;
|
|
377
|
+
}
|
|
378
|
+
|
|
379
|
+
const autoApprovedResult =
|
|
380
|
+
approvalMode === 'yolo' ? yoloApprovalResultForServerRequest(request) : null;
|
|
381
|
+
if (autoApprovedResult) {
|
|
382
|
+
return {
|
|
383
|
+
providerRequestId,
|
|
384
|
+
providerSessionId,
|
|
385
|
+
autoApprovedResult,
|
|
386
|
+
pendingRequest: null,
|
|
387
|
+
};
|
|
388
|
+
}
|
|
389
|
+
|
|
390
|
+
const title =
|
|
391
|
+
approvalResponseKind === 'commandExecutionApproval' ||
|
|
392
|
+
approvalResponseKind === 'legacyExecApproval'
|
|
393
|
+
? 'Command approval required'
|
|
394
|
+
: approvalResponseKind === 'fileChangeApproval' ||
|
|
395
|
+
approvalResponseKind === 'legacyApplyPatchApproval'
|
|
396
|
+
? 'File change approval required'
|
|
397
|
+
: 'Permissions approval required';
|
|
398
|
+
const threadRequest = buildGenericApprovalThreadRequest(request, {
|
|
399
|
+
title,
|
|
400
|
+
descriptionFallback: 'Codex needs approval before it can continue this action.',
|
|
401
|
+
});
|
|
402
|
+
const pendingRequest: AgentPendingProviderRequest = {
|
|
403
|
+
providerRequestId,
|
|
404
|
+
responseKind: approvalResponseKind,
|
|
405
|
+
request: threadRequest,
|
|
406
|
+
};
|
|
407
|
+
if (approvalResponseKind === 'permissionsApproval' && isRecord(params.permissions)) {
|
|
408
|
+
pendingRequest.responsePayload = { permissions: params.permissions };
|
|
409
|
+
}
|
|
410
|
+
|
|
411
|
+
return {
|
|
412
|
+
providerRequestId,
|
|
413
|
+
providerSessionId,
|
|
414
|
+
autoApprovedResult: null,
|
|
415
|
+
pendingRequest,
|
|
416
|
+
};
|
|
417
|
+
}
|
|
418
|
+
|
|
419
|
+
if (isMcpElicitationRequest(request)) {
|
|
420
|
+
const autoApprovedResult =
|
|
421
|
+
approvalMode === 'yolo'
|
|
422
|
+
? buildAutoApprovedMcpElicitationResult(request)
|
|
423
|
+
: null;
|
|
424
|
+
if (autoApprovedResult) {
|
|
425
|
+
return {
|
|
426
|
+
providerRequestId,
|
|
427
|
+
providerSessionId: request.params.threadId,
|
|
428
|
+
autoApprovedResult,
|
|
429
|
+
pendingRequest: null,
|
|
430
|
+
};
|
|
431
|
+
}
|
|
432
|
+
|
|
433
|
+
return {
|
|
434
|
+
providerRequestId,
|
|
435
|
+
providerSessionId: request.params.threadId,
|
|
436
|
+
autoApprovedResult: null,
|
|
437
|
+
pendingRequest: {
|
|
438
|
+
providerRequestId,
|
|
439
|
+
responseKind: 'mcpElicitation',
|
|
440
|
+
request: buildThreadRequestFromMcpElicitation(request),
|
|
441
|
+
},
|
|
442
|
+
};
|
|
443
|
+
}
|
|
444
|
+
|
|
445
|
+
const params = request.params as {
|
|
446
|
+
threadId?: string;
|
|
447
|
+
turnId?: string;
|
|
448
|
+
itemId?: string;
|
|
449
|
+
questions?: Array<{
|
|
450
|
+
id: string;
|
|
451
|
+
header: string;
|
|
452
|
+
question: string;
|
|
453
|
+
isOther: boolean;
|
|
454
|
+
isSecret: boolean;
|
|
455
|
+
options: Array<{ label: string; description: string }> | null;
|
|
456
|
+
}>;
|
|
457
|
+
};
|
|
458
|
+
|
|
459
|
+
if (!params.threadId || !Array.isArray(params.questions)) {
|
|
460
|
+
return null;
|
|
461
|
+
}
|
|
462
|
+
|
|
463
|
+
const autoApprovedAnswers =
|
|
464
|
+
approvalMode === 'yolo'
|
|
465
|
+
? buildAutoApprovedAnswersForServerQuestions(
|
|
466
|
+
request.method,
|
|
467
|
+
params.questions,
|
|
468
|
+
)
|
|
469
|
+
: null;
|
|
470
|
+
if (autoApprovedAnswers) {
|
|
471
|
+
return {
|
|
472
|
+
providerRequestId,
|
|
473
|
+
providerSessionId: params.threadId,
|
|
474
|
+
autoApprovedResult: { answers: autoApprovedAnswers },
|
|
475
|
+
pendingRequest: null,
|
|
476
|
+
};
|
|
477
|
+
}
|
|
478
|
+
|
|
479
|
+
const questions = params.questions.map((question) => ({
|
|
480
|
+
id: question.id,
|
|
481
|
+
header: question.header,
|
|
482
|
+
question: question.question,
|
|
483
|
+
isOther: question.isOther,
|
|
484
|
+
isSecret: question.isSecret,
|
|
485
|
+
options: question.options?.map((option) => ({
|
|
486
|
+
label: option.label,
|
|
487
|
+
description: option.description,
|
|
488
|
+
})) ?? null,
|
|
489
|
+
}));
|
|
490
|
+
const threadRequest: AgentActionRequest = {
|
|
491
|
+
id: String(request.id),
|
|
492
|
+
kind: 'requestUserInput',
|
|
493
|
+
title: questions[0]?.header || 'User input required',
|
|
494
|
+
description: questions[0]?.question ?? null,
|
|
495
|
+
turnId: params.turnId ?? null,
|
|
496
|
+
itemId: params.itemId ?? null,
|
|
497
|
+
createdAt: new Date().toISOString(),
|
|
498
|
+
questions,
|
|
499
|
+
};
|
|
500
|
+
|
|
501
|
+
return {
|
|
502
|
+
providerRequestId,
|
|
503
|
+
providerSessionId: params.threadId,
|
|
504
|
+
autoApprovedResult: null,
|
|
505
|
+
pendingRequest: {
|
|
506
|
+
providerRequestId,
|
|
507
|
+
responseKind: 'answers',
|
|
508
|
+
request: threadRequest,
|
|
509
|
+
},
|
|
510
|
+
};
|
|
511
|
+
}
|