@agentuity/core 2.0.13 → 2.0.15
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/dist/services/aigateway/api-reference.d.ts +4 -0
- package/dist/services/aigateway/api-reference.d.ts.map +1 -0
- package/dist/services/aigateway/api-reference.js +146 -0
- package/dist/services/aigateway/api-reference.js.map +1 -0
- package/dist/services/aigateway/index.d.ts +2 -0
- package/dist/services/aigateway/index.d.ts.map +1 -0
- package/dist/services/aigateway/index.js +2 -0
- package/dist/services/aigateway/index.js.map +1 -0
- package/dist/services/aigateway/service.d.ts +221 -0
- package/dist/services/aigateway/service.d.ts.map +1 -0
- package/dist/services/aigateway/service.js +280 -0
- package/dist/services/aigateway/service.js.map +1 -0
- package/dist/services/api-reference.d.ts +1 -0
- package/dist/services/api-reference.d.ts.map +1 -1
- package/dist/services/api-reference.js.map +1 -1
- package/dist/services/coder/client.d.ts +5 -1
- package/dist/services/coder/client.d.ts.map +1 -1
- package/dist/services/coder/client.js +8 -1
- package/dist/services/coder/client.js.map +1 -1
- package/dist/services/coder/protocol.d.ts +1 -1
- package/dist/services/coder/sessions.d.ts +2 -0
- package/dist/services/coder/sessions.d.ts.map +1 -1
- package/dist/services/coder/skills.d.ts +4 -1
- package/dist/services/coder/skills.d.ts.map +1 -1
- package/dist/services/coder/skills.js +14 -1
- package/dist/services/coder/skills.js.map +1 -1
- package/dist/services/coder/types.d.ts +64 -8
- package/dist/services/coder/types.d.ts.map +1 -1
- package/dist/services/coder/types.js +36 -1
- package/dist/services/coder/types.js.map +1 -1
- package/dist/services/config.d.ts +1 -0
- package/dist/services/config.d.ts.map +1 -1
- package/dist/services/config.js +2 -0
- package/dist/services/config.js.map +1 -1
- package/dist/services/index.d.ts +1 -0
- package/dist/services/index.d.ts.map +1 -1
- package/dist/services/index.js +1 -0
- package/dist/services/index.js.map +1 -1
- package/dist/services/keyvalue/service.d.ts +2 -2
- package/dist/services/project/deploy.d.ts +2 -2
- package/dist/services/sandbox/getStatus.d.ts +1 -0
- package/dist/services/sandbox/getStatus.d.ts.map +1 -1
- package/dist/services/sandbox/getStatus.js +3 -2
- package/dist/services/sandbox/getStatus.js.map +1 -1
- package/dist/services/sandbox/list.d.ts +1 -1
- package/dist/services/sandbox/run.d.ts +4 -4
- package/dist/services/sandbox/run.d.ts.map +1 -1
- package/dist/services/sandbox/run.js +103 -3
- package/dist/services/sandbox/run.js.map +1 -1
- package/dist/services/sandbox/types.d.ts +8 -8
- package/dist/services/session/events.d.ts +2 -2
- package/dist/services/stats.d.ts +1 -1
- package/dist/services/stream/service.d.ts +2 -2
- package/dist/services/vector/service.d.ts +2 -2
- package/package.json +2 -2
- package/src/env.d.ts +6 -0
- package/src/services/aigateway/api-reference.ts +167 -0
- package/src/services/aigateway/index.ts +24 -0
- package/src/services/aigateway/service.ts +355 -0
- package/src/services/api-reference.ts +1 -0
- package/src/services/coder/client.ts +10 -0
- package/src/services/coder/skills.ts +19 -0
- package/src/services/coder/types.ts +51 -1
- package/src/services/config.ts +2 -0
- package/src/services/index.ts +1 -0
- package/src/services/sandbox/getStatus.ts +4 -2
- package/src/services/sandbox/run.ts +156 -3
|
@@ -0,0 +1,355 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import { StructuredError } from '../../error.ts';
|
|
3
|
+
import { FetchAdapter } from '../adapter.ts';
|
|
4
|
+
import { buildUrl, toServiceException, toPayload } from '../_util.ts';
|
|
5
|
+
|
|
6
|
+
const AIGatewayModelsResponseError = StructuredError('AIGatewayModelsResponseError')<{
|
|
7
|
+
error?: string;
|
|
8
|
+
message?: string;
|
|
9
|
+
}>();
|
|
10
|
+
|
|
11
|
+
export const AIGatewayPricingSchema = z.object({
|
|
12
|
+
input: z.number().describe('Input token price.'),
|
|
13
|
+
output: z.number().describe('Output token price.'),
|
|
14
|
+
cached_input: z.number().optional().describe('Cached input token price.'),
|
|
15
|
+
unit: z.string().describe('Pricing unit.'),
|
|
16
|
+
currency: z.string().describe('Pricing currency.'),
|
|
17
|
+
});
|
|
18
|
+
|
|
19
|
+
export type AIGatewayPricing = z.infer<typeof AIGatewayPricingSchema>;
|
|
20
|
+
|
|
21
|
+
export const AIGatewayModelProviderSchema = z.object({
|
|
22
|
+
env: z.array(z.string()).optional().describe('Environment variables used by this provider.'),
|
|
23
|
+
api: z.string().optional().describe('Provider API URL.'),
|
|
24
|
+
doc: z.string().optional().describe('Provider documentation URL.'),
|
|
25
|
+
logo_url: z.string().optional().describe('Provider logo URL.'),
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
export type AIGatewayModelProvider = z.infer<typeof AIGatewayModelProviderSchema>;
|
|
29
|
+
|
|
30
|
+
export const AIGatewayModelSchema = z.object({
|
|
31
|
+
id: z.string().describe('Model identifier.'),
|
|
32
|
+
name: z.string().describe('Display name.'),
|
|
33
|
+
created: z.number().optional().describe('Unix timestamp when the model was created.'),
|
|
34
|
+
api: z.string().optional().describe('Compatible provider API shape.'),
|
|
35
|
+
family: z.string().optional().describe('Model family.'),
|
|
36
|
+
context_window: z.number().optional().describe('Maximum context window.'),
|
|
37
|
+
max_output_tokens: z.number().optional().describe('Maximum output token count.'),
|
|
38
|
+
input_modalities: z.array(z.string()).optional().describe('Supported input modalities.'),
|
|
39
|
+
output_modalities: z.array(z.string()).optional().describe('Supported output modalities.'),
|
|
40
|
+
attachment: z.boolean().optional().describe('Whether the model supports attachments.'),
|
|
41
|
+
reasoning: z.boolean().optional().describe('Whether the model supports reasoning.'),
|
|
42
|
+
tool_call: z.boolean().optional().describe('Whether the model supports tool calls.'),
|
|
43
|
+
temperature: z.boolean().optional().describe('Whether the model supports temperature.'),
|
|
44
|
+
knowledge: z.string().optional().describe('Knowledge cutoff or label.'),
|
|
45
|
+
open_weights: z.boolean().optional().describe('Whether the model has open weights.'),
|
|
46
|
+
provider: AIGatewayModelProviderSchema.optional().describe('Provider metadata.'),
|
|
47
|
+
pricing: AIGatewayPricingSchema.optional().describe('Model pricing.'),
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
export type AIGatewayModel = z.infer<typeof AIGatewayModelSchema>;
|
|
51
|
+
|
|
52
|
+
export const AIGatewayModelsSchema = z.record(z.string(), z.array(AIGatewayModelSchema));
|
|
53
|
+
export type AIGatewayModels = z.infer<typeof AIGatewayModelsSchema>;
|
|
54
|
+
|
|
55
|
+
export const AIGatewayModelsResponseSchema = z.object({
|
|
56
|
+
success: z.boolean(),
|
|
57
|
+
data: AIGatewayModelsSchema.optional(),
|
|
58
|
+
message: z.string().optional(),
|
|
59
|
+
error: z.string().optional(),
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
export type AIGatewayModelsResponse = z.infer<typeof AIGatewayModelsResponseSchema>;
|
|
63
|
+
|
|
64
|
+
export const AIGatewayChatMessageSchema = z.object({
|
|
65
|
+
role: z.enum(['system', 'developer', 'user', 'assistant', 'tool']),
|
|
66
|
+
content: z
|
|
67
|
+
.union([
|
|
68
|
+
z.string(),
|
|
69
|
+
z.array(
|
|
70
|
+
z
|
|
71
|
+
.object({
|
|
72
|
+
type: z.string(),
|
|
73
|
+
})
|
|
74
|
+
.catchall(z.unknown())
|
|
75
|
+
),
|
|
76
|
+
z.null(),
|
|
77
|
+
])
|
|
78
|
+
.optional(),
|
|
79
|
+
name: z.string().optional(),
|
|
80
|
+
tool_call_id: z.string().optional(),
|
|
81
|
+
tool_calls: z.array(z.unknown()).optional(),
|
|
82
|
+
});
|
|
83
|
+
|
|
84
|
+
export type AIGatewayChatMessage = z.infer<typeof AIGatewayChatMessageSchema>;
|
|
85
|
+
|
|
86
|
+
const missingCompletionInputMessage = 'either prompt or messages must be provided';
|
|
87
|
+
|
|
88
|
+
function hasCompletionInput(params: { prompt?: string | string[]; messages?: unknown[] }): boolean {
|
|
89
|
+
if (params.messages && params.messages.length > 0) {
|
|
90
|
+
return true;
|
|
91
|
+
}
|
|
92
|
+
if (typeof params.prompt === 'string') {
|
|
93
|
+
return params.prompt.trim().length > 0;
|
|
94
|
+
}
|
|
95
|
+
if (Array.isArray(params.prompt)) {
|
|
96
|
+
return params.prompt.length > 0 && params.prompt.every((item) => item.trim().length > 0);
|
|
97
|
+
}
|
|
98
|
+
return false;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
export const AIGatewayChatCompletionParamsSchema = z
|
|
102
|
+
.object({
|
|
103
|
+
model: z.string().describe('Model to use for the completion.'),
|
|
104
|
+
messages: z.array(AIGatewayChatMessageSchema).optional().describe('Messages to complete.'),
|
|
105
|
+
prompt: z
|
|
106
|
+
.union([z.string(), z.array(z.string())])
|
|
107
|
+
.optional()
|
|
108
|
+
.describe('Prompt to complete.'),
|
|
109
|
+
temperature: z.number().optional(),
|
|
110
|
+
top_p: z.number().optional(),
|
|
111
|
+
max_tokens: z.number().optional(),
|
|
112
|
+
stream: z.boolean().optional(),
|
|
113
|
+
stop: z.union([z.string(), z.array(z.string())]).optional(),
|
|
114
|
+
})
|
|
115
|
+
.catchall(z.unknown())
|
|
116
|
+
.superRefine((params, ctx) => {
|
|
117
|
+
if (!hasCompletionInput(params)) {
|
|
118
|
+
ctx.addIssue({
|
|
119
|
+
code: 'custom',
|
|
120
|
+
message: missingCompletionInputMessage,
|
|
121
|
+
path: ['messages'],
|
|
122
|
+
});
|
|
123
|
+
}
|
|
124
|
+
});
|
|
125
|
+
|
|
126
|
+
export type AIGatewayChatCompletionParams = z.infer<typeof AIGatewayChatCompletionParamsSchema>;
|
|
127
|
+
|
|
128
|
+
export const AIGatewayChatCompletionStreamParamsSchema =
|
|
129
|
+
AIGatewayChatCompletionParamsSchema.safeExtend({
|
|
130
|
+
stream: z.literal(true).describe('Enable Server-Sent Events streaming.'),
|
|
131
|
+
});
|
|
132
|
+
|
|
133
|
+
export type AIGatewayChatCompletionStreamParams = z.infer<
|
|
134
|
+
typeof AIGatewayChatCompletionStreamParamsSchema
|
|
135
|
+
>;
|
|
136
|
+
|
|
137
|
+
export const AIGatewayChatCompletionSchema = z
|
|
138
|
+
.object({
|
|
139
|
+
id: z.string().optional(),
|
|
140
|
+
object: z.string().optional(),
|
|
141
|
+
created: z.number().optional(),
|
|
142
|
+
model: z.string().optional(),
|
|
143
|
+
choices: z.array(z.unknown()).optional(),
|
|
144
|
+
usage: z.unknown().optional(),
|
|
145
|
+
agentuity: z
|
|
146
|
+
.object({
|
|
147
|
+
headers: z
|
|
148
|
+
.record(z.string(), z.string())
|
|
149
|
+
.optional()
|
|
150
|
+
.describe('AI Gateway response headers captured from the HTTP response.'),
|
|
151
|
+
cost: z
|
|
152
|
+
.object({
|
|
153
|
+
total: z.number().optional().describe('Total estimated gateway cost in USD.'),
|
|
154
|
+
promptTokens: z
|
|
155
|
+
.number()
|
|
156
|
+
.optional()
|
|
157
|
+
.describe('Prompt token count used for gateway billing.'),
|
|
158
|
+
completionTokens: z
|
|
159
|
+
.number()
|
|
160
|
+
.optional()
|
|
161
|
+
.describe('Completion token count used for gateway billing.'),
|
|
162
|
+
})
|
|
163
|
+
.optional()
|
|
164
|
+
.describe('Parsed AI Gateway cost information when available.'),
|
|
165
|
+
})
|
|
166
|
+
.optional()
|
|
167
|
+
.describe('Agentuity AI Gateway metadata.'),
|
|
168
|
+
})
|
|
169
|
+
.catchall(z.unknown());
|
|
170
|
+
|
|
171
|
+
export type AIGatewayChatCompletion = z.infer<typeof AIGatewayChatCompletionSchema>;
|
|
172
|
+
|
|
173
|
+
export const AIGatewayResponseMetadataSchema = z.object({
|
|
174
|
+
headers: z.record(z.string(), z.string()).optional(),
|
|
175
|
+
cost: z
|
|
176
|
+
.object({
|
|
177
|
+
total: z.number().optional(),
|
|
178
|
+
promptTokens: z.number().optional(),
|
|
179
|
+
completionTokens: z.number().optional(),
|
|
180
|
+
})
|
|
181
|
+
.optional(),
|
|
182
|
+
});
|
|
183
|
+
|
|
184
|
+
export type AIGatewayResponseMetadata = z.infer<typeof AIGatewayResponseMetadataSchema>;
|
|
185
|
+
|
|
186
|
+
export type AIGatewayStreamingCompletion = {
|
|
187
|
+
stream: ReadableStream<Uint8Array>;
|
|
188
|
+
metadata: Promise<AIGatewayResponseMetadata>;
|
|
189
|
+
};
|
|
190
|
+
|
|
191
|
+
function parseNumber(value: string | undefined): number | undefined {
|
|
192
|
+
if (value === undefined || value.trim() === '') {
|
|
193
|
+
return undefined;
|
|
194
|
+
}
|
|
195
|
+
const parsed = Number(value);
|
|
196
|
+
return Number.isFinite(parsed) ? parsed : undefined;
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
function extractGatewayMetadataFromHeaders(headers: Headers): AIGatewayResponseMetadata {
|
|
200
|
+
const captured: Record<string, string> = {};
|
|
201
|
+
for (const [key, value] of headers.entries()) {
|
|
202
|
+
const lower = key.toLowerCase();
|
|
203
|
+
if (
|
|
204
|
+
lower.startsWith('x-gateway-') ||
|
|
205
|
+
(lower.startsWith('x-agentuity-') &&
|
|
206
|
+
(lower.includes('cost') || lower.includes('token') || lower.includes('usage')))
|
|
207
|
+
) {
|
|
208
|
+
captured[lower] = value;
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
const total = parseNumber(captured['x-gateway-cost']);
|
|
213
|
+
const promptTokens = parseNumber(captured['x-gateway-prompt-tokens']);
|
|
214
|
+
const completionTokens = parseNumber(captured['x-gateway-completion-tokens']);
|
|
215
|
+
const cost =
|
|
216
|
+
total !== undefined || promptTokens !== undefined || completionTokens !== undefined
|
|
217
|
+
? { total, promptTokens, completionTokens }
|
|
218
|
+
: undefined;
|
|
219
|
+
|
|
220
|
+
return {
|
|
221
|
+
...(Object.keys(captured).length > 0 ? { headers: captured } : {}),
|
|
222
|
+
...(cost ? { cost } : {}),
|
|
223
|
+
};
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
async function extractGatewayMetadata(response: Response): Promise<AIGatewayResponseMetadata> {
|
|
227
|
+
const metadata = extractGatewayMetadataFromHeaders(response.headers);
|
|
228
|
+
const trailers = (response as Response & { trailers?: Promise<Headers> }).trailers;
|
|
229
|
+
if (trailers) {
|
|
230
|
+
try {
|
|
231
|
+
const trailerMetadata = extractGatewayMetadataFromHeaders(await trailers);
|
|
232
|
+
const cost =
|
|
233
|
+
metadata.cost || trailerMetadata.cost
|
|
234
|
+
? { ...(metadata.cost ?? {}), ...(trailerMetadata.cost ?? {}) }
|
|
235
|
+
: undefined;
|
|
236
|
+
return {
|
|
237
|
+
headers: { ...metadata.headers, ...trailerMetadata.headers },
|
|
238
|
+
...(cost ? { cost } : {}),
|
|
239
|
+
};
|
|
240
|
+
} catch {
|
|
241
|
+
// Some runtimes expose a trailers promise but reject when trailers are unavailable.
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
return metadata;
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
function attachGatewayMetadata<T extends Record<string, unknown>>(
|
|
248
|
+
payload: T,
|
|
249
|
+
metadata: AIGatewayResponseMetadata
|
|
250
|
+
): T {
|
|
251
|
+
if (!metadata.headers && !metadata.cost) {
|
|
252
|
+
return payload;
|
|
253
|
+
}
|
|
254
|
+
return {
|
|
255
|
+
...payload,
|
|
256
|
+
agentuity: {
|
|
257
|
+
...(typeof payload.agentuity === 'object' && payload.agentuity !== null
|
|
258
|
+
? payload.agentuity
|
|
259
|
+
: {}),
|
|
260
|
+
...metadata,
|
|
261
|
+
},
|
|
262
|
+
};
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
export class AIGatewayService {
|
|
266
|
+
constructor(
|
|
267
|
+
readonly baseUrl: string,
|
|
268
|
+
readonly adapter: FetchAdapter
|
|
269
|
+
) {}
|
|
270
|
+
|
|
271
|
+
async listModels(): Promise<AIGatewayModels> {
|
|
272
|
+
const method = 'GET';
|
|
273
|
+
const url = buildUrl(this.baseUrl, '/models');
|
|
274
|
+
const response = await this.adapter.invoke<AIGatewayModelsResponse>(url, {
|
|
275
|
+
method,
|
|
276
|
+
telemetry: { name: 'aigateway.models.list' },
|
|
277
|
+
});
|
|
278
|
+
if (!response.ok) {
|
|
279
|
+
throw await toServiceException(method, url, response.response);
|
|
280
|
+
}
|
|
281
|
+
const payload = AIGatewayModelsResponseSchema.parse(response.data);
|
|
282
|
+
if (!payload.success) {
|
|
283
|
+
throw new AIGatewayModelsResponseError({
|
|
284
|
+
message: payload.error || payload.message || 'AI Gateway failed to list models',
|
|
285
|
+
error: payload.error,
|
|
286
|
+
});
|
|
287
|
+
}
|
|
288
|
+
if (!payload.data) {
|
|
289
|
+
throw new AIGatewayModelsResponseError({
|
|
290
|
+
message: 'AI Gateway model response did not include data',
|
|
291
|
+
});
|
|
292
|
+
}
|
|
293
|
+
return payload.data;
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
async complete(params: AIGatewayChatCompletionParams): Promise<AIGatewayChatCompletion> {
|
|
297
|
+
const method = 'POST';
|
|
298
|
+
const url = buildUrl(this.baseUrl, '/');
|
|
299
|
+
const [body, contentType] = await toPayload(
|
|
300
|
+
AIGatewayChatCompletionParamsSchema.parse(params)
|
|
301
|
+
);
|
|
302
|
+
const response = await this.adapter.invoke<AIGatewayChatCompletion>(url, {
|
|
303
|
+
method,
|
|
304
|
+
body,
|
|
305
|
+
contentType,
|
|
306
|
+
telemetry: { name: 'aigateway.completions.create' },
|
|
307
|
+
});
|
|
308
|
+
if (!response.ok) {
|
|
309
|
+
throw await toServiceException(method, url, response.response);
|
|
310
|
+
}
|
|
311
|
+
const payload = attachGatewayMetadata(
|
|
312
|
+
response.data as Record<string, unknown>,
|
|
313
|
+
await extractGatewayMetadata(response.response)
|
|
314
|
+
);
|
|
315
|
+
return AIGatewayChatCompletionSchema.parse(payload);
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
async streamComplete(
|
|
319
|
+
params: AIGatewayChatCompletionParams
|
|
320
|
+
): Promise<ReadableStream<Uint8Array>> {
|
|
321
|
+
return (await this.streamCompleteWithMetadata(params)).stream;
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
async streamCompleteWithMetadata(
|
|
325
|
+
params: AIGatewayChatCompletionParams
|
|
326
|
+
): Promise<AIGatewayStreamingCompletion> {
|
|
327
|
+
const method = 'POST';
|
|
328
|
+
const url = buildUrl(this.baseUrl, '/');
|
|
329
|
+
const [body, contentType] = await toPayload(
|
|
330
|
+
AIGatewayChatCompletionParamsSchema.parse({ ...params, stream: true })
|
|
331
|
+
);
|
|
332
|
+
const response = await this.adapter.invoke<never>(url, {
|
|
333
|
+
method,
|
|
334
|
+
body,
|
|
335
|
+
contentType,
|
|
336
|
+
headers: { Accept: 'text/event-stream' },
|
|
337
|
+
binary: true,
|
|
338
|
+
telemetry: { name: 'aigateway.completions.stream' },
|
|
339
|
+
});
|
|
340
|
+
if (!response.ok) {
|
|
341
|
+
throw await toServiceException(method, url, response.response);
|
|
342
|
+
}
|
|
343
|
+
if (!response.response.body) {
|
|
344
|
+
throw await toServiceException(
|
|
345
|
+
method,
|
|
346
|
+
url,
|
|
347
|
+
new Response('Streaming response did not include a body', { status: 502 })
|
|
348
|
+
);
|
|
349
|
+
}
|
|
350
|
+
return {
|
|
351
|
+
stream: response.response.body,
|
|
352
|
+
metadata: extractGatewayMetadata(response.response),
|
|
353
|
+
};
|
|
354
|
+
}
|
|
355
|
+
}
|
|
@@ -32,6 +32,7 @@ import {
|
|
|
32
32
|
coderUpdateCustomAgent,
|
|
33
33
|
} from './agents.ts';
|
|
34
34
|
import {
|
|
35
|
+
coderCreateCustomSkill,
|
|
35
36
|
coderCreateSkillBucket,
|
|
36
37
|
coderDeleteSavedSkill,
|
|
37
38
|
coderDeleteSkillBucket,
|
|
@@ -79,6 +80,7 @@ import type {
|
|
|
79
80
|
CoderSkillBucket,
|
|
80
81
|
CoderSkillBucketListResponse,
|
|
81
82
|
CoderCreateSkillBucketRequest,
|
|
83
|
+
CoderCreateCustomSkillRequest,
|
|
82
84
|
CoderUpdateCustomAgentRequest,
|
|
83
85
|
CoderCreateWorkspaceRequest,
|
|
84
86
|
CoderUpdateWorkspaceRequest,
|
|
@@ -449,6 +451,14 @@ export class CoderClient {
|
|
|
449
451
|
return coderSaveSkill(client, { body });
|
|
450
452
|
}
|
|
451
453
|
|
|
454
|
+
/**
|
|
455
|
+
* Creates a custom SKILL.md-backed skill in the caller's library.
|
|
456
|
+
*/
|
|
457
|
+
async createCustomSkill(body: CoderCreateCustomSkillRequest): Promise<CoderSavedSkill> {
|
|
458
|
+
const client = await this.#getClient();
|
|
459
|
+
return coderCreateCustomSkill(client, { body });
|
|
460
|
+
}
|
|
461
|
+
|
|
452
462
|
/**
|
|
453
463
|
* Deletes a saved skill from the caller's library.
|
|
454
464
|
*/
|
|
@@ -2,12 +2,14 @@ import { z } from 'zod/v4';
|
|
|
2
2
|
import { type APIClient } from '../api.ts';
|
|
3
3
|
import {
|
|
4
4
|
CoderCreateSkillBucketRequestSchema,
|
|
5
|
+
CoderCreateCustomSkillRequestSchema,
|
|
5
6
|
CoderSavedSkillListResponseSchema,
|
|
6
7
|
CoderSavedSkillSchema,
|
|
7
8
|
CoderSaveSkillRequestSchema,
|
|
8
9
|
CoderSkillBucketListResponseSchema,
|
|
9
10
|
CoderSkillBucketSchema,
|
|
10
11
|
type CoderCreateSkillBucketRequest,
|
|
12
|
+
type CoderCreateCustomSkillRequest,
|
|
11
13
|
type CoderSavedSkill,
|
|
12
14
|
type CoderSavedSkillListResponse,
|
|
13
15
|
type CoderSaveSkillRequest,
|
|
@@ -59,6 +61,23 @@ export async function coderSaveSkill(
|
|
|
59
61
|
return resp.skill;
|
|
60
62
|
}
|
|
61
63
|
|
|
64
|
+
export async function coderCreateCustomSkill(
|
|
65
|
+
client: APIClient,
|
|
66
|
+
params: { body: CoderCreateCustomSkillRequest }
|
|
67
|
+
): Promise<CoderSavedSkill> {
|
|
68
|
+
const body = CoderCreateCustomSkillRequestSchema.parse(params.body);
|
|
69
|
+
return coderSaveSkill(client, {
|
|
70
|
+
body: {
|
|
71
|
+
source: 'custom',
|
|
72
|
+
repo: 'custom',
|
|
73
|
+
skillId: body.skillId,
|
|
74
|
+
name: body.name,
|
|
75
|
+
...(body.description !== undefined ? { description: body.description } : {}),
|
|
76
|
+
content: body.content,
|
|
77
|
+
},
|
|
78
|
+
});
|
|
79
|
+
}
|
|
80
|
+
|
|
62
81
|
export async function coderDeleteSavedSkill(
|
|
63
82
|
client: APIClient,
|
|
64
83
|
params: { skillId: string }
|
|
@@ -42,12 +42,18 @@ export const CoderSessionBucketSchema = z
|
|
|
42
42
|
.describe('Derived bucket used for session listing and UI grouping');
|
|
43
43
|
export type CoderSessionBucket = z.infer<typeof CoderSessionBucketSchema>;
|
|
44
44
|
|
|
45
|
+
export const CoderWorkspaceSystemPromptModeSchema = z
|
|
46
|
+
.enum(['append', 'overwrite'])
|
|
47
|
+
.describe('How a workspace system prompt is applied to the Lead agent prompt');
|
|
48
|
+
export type CoderWorkspaceSystemPromptMode = z.infer<typeof CoderWorkspaceSystemPromptModeSchema>;
|
|
49
|
+
|
|
45
50
|
export const CoderSkillRefSchema = z
|
|
46
51
|
.object({
|
|
47
52
|
skillId: z.string().describe('Unique skill identifier'),
|
|
48
53
|
repo: z.string().describe('Repository slug for the skill source'),
|
|
49
54
|
name: z.string().optional().describe('Human-readable skill name'),
|
|
50
55
|
url: z.string().optional().describe('Canonical URL for the skill repository or page'),
|
|
56
|
+
content: z.string().optional().describe('Inline SKILL.md content for custom skills'),
|
|
51
57
|
})
|
|
52
58
|
.describe('Skill reference attached to a coder session');
|
|
53
59
|
export type CoderSkillRef = z.infer<typeof CoderSkillRefSchema>;
|
|
@@ -83,6 +89,7 @@ export const CoderSavedSkillSchema = z
|
|
|
83
89
|
description: z.string().optional().describe('Skill description'),
|
|
84
90
|
url: z.string().optional().describe('Skill URL'),
|
|
85
91
|
installs: z.number().optional().describe('Number of installs'),
|
|
92
|
+
content: z.string().optional().describe('Inline SKILL.md content for custom skills'),
|
|
86
93
|
createdAt: z.string().describe('Creation timestamp (ISO-8601)'),
|
|
87
94
|
updatedAt: z.string().describe('Last update timestamp (ISO-8601)'),
|
|
88
95
|
})
|
|
@@ -123,6 +130,16 @@ export const CoderWorkspaceDetailSchema = z
|
|
|
123
130
|
.optional()
|
|
124
131
|
.default('')
|
|
125
132
|
.describe('Shell script run while preparing workspace snapshots'),
|
|
133
|
+
systemPrompt: z
|
|
134
|
+
.string()
|
|
135
|
+
.optional()
|
|
136
|
+
.default('')
|
|
137
|
+
.describe(
|
|
138
|
+
'Additional Lead agent system prompt applied to sessions created from this workspace'
|
|
139
|
+
),
|
|
140
|
+
systemPromptMode: CoderWorkspaceSystemPromptModeSchema.optional()
|
|
141
|
+
.default('append')
|
|
142
|
+
.describe('Whether the workspace system prompt appends to or overwrites the Lead prompt'),
|
|
126
143
|
snapshot: z
|
|
127
144
|
.object({
|
|
128
145
|
status: z.string().describe('Workspace snapshot build status'),
|
|
@@ -353,6 +370,7 @@ function hasWorkspaceSelections(input: {
|
|
|
353
370
|
repos?: unknown[];
|
|
354
371
|
dependencies?: unknown[];
|
|
355
372
|
setupScript?: string;
|
|
373
|
+
systemPrompt?: string;
|
|
356
374
|
savedSkillIds?: unknown[];
|
|
357
375
|
skillBucketIds?: unknown[];
|
|
358
376
|
enabledAgents?: unknown[];
|
|
@@ -361,6 +379,7 @@ function hasWorkspaceSelections(input: {
|
|
|
361
379
|
(input.repos?.length ?? 0) > 0 ||
|
|
362
380
|
(input.dependencies?.length ?? 0) > 0 ||
|
|
363
381
|
Boolean(input.setupScript?.trim()) ||
|
|
382
|
+
Boolean(input.systemPrompt?.trim()) ||
|
|
364
383
|
(input.savedSkillIds?.length ?? 0) > 0 ||
|
|
365
384
|
(input.skillBucketIds?.length ?? 0) > 0 ||
|
|
366
385
|
(input.enabledAgents?.length ?? 0) > 0
|
|
@@ -381,6 +400,15 @@ export const CoderCreateWorkspaceRequestSchema = z
|
|
|
381
400
|
.string()
|
|
382
401
|
.optional()
|
|
383
402
|
.describe('Shell script run while preparing workspace snapshots'),
|
|
403
|
+
systemPrompt: z
|
|
404
|
+
.string()
|
|
405
|
+
.optional()
|
|
406
|
+
.describe(
|
|
407
|
+
'Additional Lead agent system prompt applied to sessions created from this workspace'
|
|
408
|
+
),
|
|
409
|
+
systemPromptMode: CoderWorkspaceSystemPromptModeSchema.optional().describe(
|
|
410
|
+
'Whether the workspace system prompt appends to or overwrites the Lead prompt'
|
|
411
|
+
),
|
|
384
412
|
savedSkillIds: z.array(z.string()).optional().describe('Saved skill IDs'),
|
|
385
413
|
skillBucketIds: z.array(z.string()).optional().describe('Skill bucket IDs'),
|
|
386
414
|
enabledAgents: z
|
|
@@ -390,7 +418,7 @@ export const CoderCreateWorkspaceRequestSchema = z
|
|
|
390
418
|
})
|
|
391
419
|
.refine(hasWorkspaceSelections, {
|
|
392
420
|
message:
|
|
393
|
-
'A workspace needs at least one repo, dependency, setup script, saved skill, skill bucket, or agent',
|
|
421
|
+
'A workspace needs at least one repo, dependency, setup script, system prompt, saved skill, skill bucket, or agent',
|
|
394
422
|
})
|
|
395
423
|
.describe('Request body for creating a workspace');
|
|
396
424
|
export type CoderCreateWorkspaceRequest = z.infer<typeof CoderCreateWorkspaceRequestSchema>;
|
|
@@ -409,6 +437,15 @@ export const CoderUpdateWorkspaceRequestSchema = z
|
|
|
409
437
|
.string()
|
|
410
438
|
.optional()
|
|
411
439
|
.describe('Shell script run while preparing workspace snapshots'),
|
|
440
|
+
systemPrompt: z
|
|
441
|
+
.string()
|
|
442
|
+
.optional()
|
|
443
|
+
.describe(
|
|
444
|
+
'Additional Lead agent system prompt applied to sessions created from this workspace'
|
|
445
|
+
),
|
|
446
|
+
systemPromptMode: CoderWorkspaceSystemPromptModeSchema.optional().describe(
|
|
447
|
+
'Whether the workspace system prompt appends to or overwrites the Lead prompt'
|
|
448
|
+
),
|
|
412
449
|
savedSkillIds: z.array(z.string()).optional().describe('Saved skill IDs'),
|
|
413
450
|
skillBucketIds: z.array(z.string()).optional().describe('Skill bucket IDs'),
|
|
414
451
|
enabledAgents: z
|
|
@@ -529,6 +566,19 @@ export const CoderSaveSkillRequestSchema = z
|
|
|
529
566
|
.describe('Request body for saving a skill to the library');
|
|
530
567
|
export type CoderSaveSkillRequest = z.infer<typeof CoderSaveSkillRequestSchema>;
|
|
531
568
|
|
|
569
|
+
export const CoderCreateCustomSkillRequestSchema = z
|
|
570
|
+
.object({
|
|
571
|
+
skillId: z.string().describe('Skill identifier'),
|
|
572
|
+
name: z.string().describe('Skill name'),
|
|
573
|
+
description: z.string().optional().describe('Skill description'),
|
|
574
|
+
content: z
|
|
575
|
+
.string()
|
|
576
|
+
.refine((value) => value.trim().length > 0, 'SKILL.md content is required')
|
|
577
|
+
.describe('SKILL.md content'),
|
|
578
|
+
})
|
|
579
|
+
.describe('Request body for creating a custom skill');
|
|
580
|
+
export type CoderCreateCustomSkillRequest = z.infer<typeof CoderCreateCustomSkillRequestSchema>;
|
|
581
|
+
|
|
532
582
|
export const CoderCreateSkillBucketRequestSchema = z
|
|
533
583
|
.object({
|
|
534
584
|
name: z.string().describe('Skill bucket name'),
|
package/src/services/config.ts
CHANGED
|
@@ -6,6 +6,7 @@ export const ServiceUrlsSchema = z
|
|
|
6
6
|
keyvalue: z.string().describe('URL for the key-value storage service.'),
|
|
7
7
|
stream: z.string().describe('URL for the stream service.'),
|
|
8
8
|
vector: z.string().describe('URL for the vector storage service.'),
|
|
9
|
+
aigateway: z.string().describe('URL for the AI Gateway service.'),
|
|
9
10
|
catalyst: z.string().describe('URL for the Catalyst API gateway.'),
|
|
10
11
|
otel: z.string().describe('URL for the OpenTelemetry collector.'),
|
|
11
12
|
sandbox: z.string().describe('URL for the sandbox service.'),
|
|
@@ -42,6 +43,7 @@ export function getServiceUrls(region?: string): ServiceUrls {
|
|
|
42
43
|
keyvalue: getEnv('AGENTUITY_KEYVALUE_URL') || transportUrl,
|
|
43
44
|
stream: getEnv('AGENTUITY_STREAM_URL') || buildRegionalURL(resolvedRegion, 'streams'),
|
|
44
45
|
vector: getEnv('AGENTUITY_VECTOR_URL') || transportUrl,
|
|
46
|
+
aigateway: getEnv('AGENTUITY_AIGATEWAY_URL') || buildRegionalURL(resolvedRegion, 'aigateway'),
|
|
45
47
|
catalyst: getEnv('AGENTUITY_CATALYST_URL') || transportUrl,
|
|
46
48
|
otel: getEnv('AGENTUITY_OTLP_URL') || buildRegionalURL(resolvedRegion, 'otel'),
|
|
47
49
|
sandbox: getEnv('AGENTUITY_SANDBOX_URL') || transportUrl,
|
package/src/services/index.ts
CHANGED
|
@@ -23,6 +23,7 @@ export const SandboxGetStatusParamsSchema = z.object({
|
|
|
23
23
|
.nonnegative()
|
|
24
24
|
.optional()
|
|
25
25
|
.describe('Maximum time in milliseconds to wait for the desired status'),
|
|
26
|
+
signal: z.custom<AbortSignal>().optional().describe('abort signal for cancellation'),
|
|
26
27
|
});
|
|
27
28
|
|
|
28
29
|
export type SandboxGetStatusParams = z.infer<typeof SandboxGetStatusParamsSchema>;
|
|
@@ -36,7 +37,7 @@ export async function sandboxGetStatus(
|
|
|
36
37
|
client: APIClient,
|
|
37
38
|
params: SandboxGetStatusParams
|
|
38
39
|
): Promise<SandboxStatusResult> {
|
|
39
|
-
const { sandboxId, orgId, waitForStatus, waitMs } = params;
|
|
40
|
+
const { sandboxId, orgId, waitForStatus, waitMs, signal } = params;
|
|
40
41
|
const queryParams = new URLSearchParams();
|
|
41
42
|
if (orgId) {
|
|
42
43
|
queryParams.set('orgId', orgId);
|
|
@@ -55,7 +56,8 @@ export async function sandboxGetStatus(
|
|
|
55
56
|
|
|
56
57
|
const resp = await client.get<z.infer<typeof SandboxStatusResponseSchema>>(
|
|
57
58
|
url,
|
|
58
|
-
SandboxStatusResponseSchema
|
|
59
|
+
SandboxStatusResponseSchema,
|
|
60
|
+
signal
|
|
59
61
|
);
|
|
60
62
|
|
|
61
63
|
if (resp.success) {
|