@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.
Files changed (67) hide show
  1. package/dist/services/aigateway/api-reference.d.ts +4 -0
  2. package/dist/services/aigateway/api-reference.d.ts.map +1 -0
  3. package/dist/services/aigateway/api-reference.js +146 -0
  4. package/dist/services/aigateway/api-reference.js.map +1 -0
  5. package/dist/services/aigateway/index.d.ts +2 -0
  6. package/dist/services/aigateway/index.d.ts.map +1 -0
  7. package/dist/services/aigateway/index.js +2 -0
  8. package/dist/services/aigateway/index.js.map +1 -0
  9. package/dist/services/aigateway/service.d.ts +221 -0
  10. package/dist/services/aigateway/service.d.ts.map +1 -0
  11. package/dist/services/aigateway/service.js +280 -0
  12. package/dist/services/aigateway/service.js.map +1 -0
  13. package/dist/services/api-reference.d.ts +1 -0
  14. package/dist/services/api-reference.d.ts.map +1 -1
  15. package/dist/services/api-reference.js.map +1 -1
  16. package/dist/services/coder/client.d.ts +5 -1
  17. package/dist/services/coder/client.d.ts.map +1 -1
  18. package/dist/services/coder/client.js +8 -1
  19. package/dist/services/coder/client.js.map +1 -1
  20. package/dist/services/coder/protocol.d.ts +1 -1
  21. package/dist/services/coder/sessions.d.ts +2 -0
  22. package/dist/services/coder/sessions.d.ts.map +1 -1
  23. package/dist/services/coder/skills.d.ts +4 -1
  24. package/dist/services/coder/skills.d.ts.map +1 -1
  25. package/dist/services/coder/skills.js +14 -1
  26. package/dist/services/coder/skills.js.map +1 -1
  27. package/dist/services/coder/types.d.ts +64 -8
  28. package/dist/services/coder/types.d.ts.map +1 -1
  29. package/dist/services/coder/types.js +36 -1
  30. package/dist/services/coder/types.js.map +1 -1
  31. package/dist/services/config.d.ts +1 -0
  32. package/dist/services/config.d.ts.map +1 -1
  33. package/dist/services/config.js +2 -0
  34. package/dist/services/config.js.map +1 -1
  35. package/dist/services/index.d.ts +1 -0
  36. package/dist/services/index.d.ts.map +1 -1
  37. package/dist/services/index.js +1 -0
  38. package/dist/services/index.js.map +1 -1
  39. package/dist/services/keyvalue/service.d.ts +2 -2
  40. package/dist/services/project/deploy.d.ts +2 -2
  41. package/dist/services/sandbox/getStatus.d.ts +1 -0
  42. package/dist/services/sandbox/getStatus.d.ts.map +1 -1
  43. package/dist/services/sandbox/getStatus.js +3 -2
  44. package/dist/services/sandbox/getStatus.js.map +1 -1
  45. package/dist/services/sandbox/list.d.ts +1 -1
  46. package/dist/services/sandbox/run.d.ts +4 -4
  47. package/dist/services/sandbox/run.d.ts.map +1 -1
  48. package/dist/services/sandbox/run.js +103 -3
  49. package/dist/services/sandbox/run.js.map +1 -1
  50. package/dist/services/sandbox/types.d.ts +8 -8
  51. package/dist/services/session/events.d.ts +2 -2
  52. package/dist/services/stats.d.ts +1 -1
  53. package/dist/services/stream/service.d.ts +2 -2
  54. package/dist/services/vector/service.d.ts +2 -2
  55. package/package.json +2 -2
  56. package/src/env.d.ts +6 -0
  57. package/src/services/aigateway/api-reference.ts +167 -0
  58. package/src/services/aigateway/index.ts +24 -0
  59. package/src/services/aigateway/service.ts +355 -0
  60. package/src/services/api-reference.ts +1 -0
  61. package/src/services/coder/client.ts +10 -0
  62. package/src/services/coder/skills.ts +19 -0
  63. package/src/services/coder/types.ts +51 -1
  64. package/src/services/config.ts +2 -0
  65. package/src/services/index.ts +1 -0
  66. package/src/services/sandbox/getStatus.ts +4 -2
  67. 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
+ }
@@ -60,6 +60,7 @@ interface Endpoint {
60
60
  exampleBody?: string | object;
61
61
  exampleHeaders?: Record<string, string>;
62
62
  ttlNote?: string;
63
+ public?: boolean;
63
64
  }
64
65
 
65
66
  interface Service {
@@ -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'),
@@ -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,
@@ -1,4 +1,5 @@
1
1
  export * from './adapter.ts';
2
+ export * from './aigateway/index.ts';
2
3
  export * from './auth/index.ts';
3
4
  export * from './email/index.ts';
4
5
  export * from './exception.ts';
@@ -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) {