@ebowwa/codespaces-types 1.1.0 → 1.2.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.
Files changed (67) hide show
  1. package/{dist/compile → compile}/index.js +41 -15
  2. package/compile/index.ts +553 -0
  3. package/compile/resources.js +116 -0
  4. package/compile/resources.ts +157 -0
  5. package/compile/schemas/resources.js +127 -0
  6. package/compile/schemas/resources.ts +144 -0
  7. package/{dist/compile → compile}/terminal-websocket.js +4 -1
  8. package/compile/terminal-websocket.ts +133 -0
  9. package/compile/time.js +30 -0
  10. package/compile/time.ts +32 -0
  11. package/{dist/compile → compile}/user/distributions.js +0 -1
  12. package/{dist/compile/user/distributions.d.ts → compile/user/distributions.ts} +0 -1
  13. package/{dist/compile → compile}/validation.js +23 -17
  14. package/compile/validation.ts +98 -0
  15. package/index.js +21 -0
  16. package/index.ts +5 -0
  17. package/package.json +38 -45
  18. package/runtime/ai.js +505 -0
  19. package/runtime/ai.ts +501 -0
  20. package/runtime/api.js +677 -0
  21. package/runtime/api.ts +857 -0
  22. package/runtime/database.js +94 -0
  23. package/runtime/database.ts +107 -0
  24. package/runtime/env.js +63 -0
  25. package/runtime/env.ts +68 -0
  26. package/{dist/runtime → runtime}/glm.js +7 -4
  27. package/runtime/glm.ts +36 -0
  28. package/runtime/index.js +28 -0
  29. package/{dist/runtime/index.js → runtime/index.ts} +1 -0
  30. package/runtime/ssh.js +47 -0
  31. package/runtime/ssh.ts +58 -0
  32. package/README.md +0 -65
  33. package/dist/compile/index.d.ts +0 -437
  34. package/dist/compile/index.d.ts.map +0 -1
  35. package/dist/compile/resources.d.ts +0 -69
  36. package/dist/compile/resources.d.ts.map +0 -1
  37. package/dist/compile/resources.js +0 -113
  38. package/dist/compile/schemas/resources.d.ts +0 -166
  39. package/dist/compile/schemas/resources.d.ts.map +0 -1
  40. package/dist/compile/schemas/resources.js +0 -123
  41. package/dist/compile/terminal-websocket.d.ts +0 -109
  42. package/dist/compile/terminal-websocket.d.ts.map +0 -1
  43. package/dist/compile/time.d.ts +0 -7
  44. package/dist/compile/time.d.ts.map +0 -1
  45. package/dist/compile/time.js +0 -27
  46. package/dist/compile/user/distributions.d.ts.map +0 -1
  47. package/dist/compile/validation.d.ts +0 -44
  48. package/dist/compile/validation.d.ts.map +0 -1
  49. package/dist/runtime/ai.d.ts +0 -1336
  50. package/dist/runtime/ai.d.ts.map +0 -1
  51. package/dist/runtime/ai.js +0 -416
  52. package/dist/runtime/api.d.ts +0 -1304
  53. package/dist/runtime/api.d.ts.map +0 -1
  54. package/dist/runtime/api.js +0 -673
  55. package/dist/runtime/database.d.ts +0 -376
  56. package/dist/runtime/database.d.ts.map +0 -1
  57. package/dist/runtime/database.js +0 -91
  58. package/dist/runtime/env.d.ts +0 -121
  59. package/dist/runtime/env.d.ts.map +0 -1
  60. package/dist/runtime/env.js +0 -54
  61. package/dist/runtime/glm.d.ts +0 -17
  62. package/dist/runtime/glm.d.ts.map +0 -1
  63. package/dist/runtime/index.d.ts +0 -13
  64. package/dist/runtime/index.d.ts.map +0 -1
  65. package/dist/runtime/ssh.d.ts +0 -111
  66. package/dist/runtime/ssh.d.ts.map +0 -1
  67. package/dist/runtime/ssh.js +0 -44
package/runtime/ai.ts ADDED
@@ -0,0 +1,501 @@
1
+ /**
2
+ * Zod schemas for AI module runtime validation
3
+ *
4
+ * Provides:
5
+ * - Runtime type validation for all AI operations
6
+ * - Type inference for TypeScript types
7
+ * - Safe parsing with error handling
8
+ * - Streaming support for Server-Sent Events
9
+ * - Reusable schemas across multiple AI providers
10
+ */
11
+
12
+ import { z } from "zod";
13
+
14
+ // ============================================================================
15
+ // BASE SCHEMAS
16
+ // ============================================================================
17
+
18
+ /**
19
+ * Chat message role (OpenAI-compatible)
20
+ */
21
+ export const ChatMessageRoleSchema = z.enum(["system", "user", "assistant"]);
22
+
23
+ /**
24
+ * Base chat message (OpenAI-compatible)
25
+ */
26
+ export const ChatMessageSchema = z.object({
27
+ role: ChatMessageRoleSchema,
28
+ content: z.string(),
29
+ });
30
+
31
+ /**
32
+ * Token usage information (camelCase)
33
+ */
34
+ export const TokenUsageSchema = z.object({
35
+ promptTokens: z.number().int().nonnegative(),
36
+ completionTokens: z.number().int().nonnegative(),
37
+ totalTokens: z.number().int().nonnegative(),
38
+ });
39
+
40
+ /**
41
+ * Raw API usage (snake_case from most APIs)
42
+ */
43
+ export const RawUsageSchema = z.object({
44
+ prompt_tokens: z.number().int().nonnegative(),
45
+ completion_tokens: z.number().int().nonnegative(),
46
+ total_tokens: z.number().int().nonnegative(),
47
+ });
48
+
49
+ // ============================================================================
50
+ // REQUEST SCHEMAS
51
+ // ============================================================================
52
+
53
+ /**
54
+ * Base AI request options shared across all AI requests
55
+ */
56
+ export const BaseAIRequestOptionsSchema = z.object({
57
+ model: z.string().optional(),
58
+ temperature: z.number().min(0).max(2).optional(),
59
+ maxTokens: z.number().int().positive().optional(),
60
+ });
61
+
62
+ /**
63
+ * Chat completion options (extends base with stream/timeout/retry)
64
+ */
65
+ export const ChatCompletionOptionsSchema = BaseAIRequestOptionsSchema.extend({
66
+ stream: z.boolean().optional().default(false),
67
+ timeout: z.number().int().positive().optional().default(30000),
68
+ maxRetries: z.number().int().nonnegative().optional().default(3),
69
+ });
70
+
71
+ /**
72
+ * Simple prompt-based AI request
73
+ */
74
+ export const AIRequestSchema = BaseAIRequestOptionsSchema.extend({
75
+ prompt: z.string(),
76
+ systemPrompt: z.string().optional(),
77
+ });
78
+
79
+ /**
80
+ * Multi-turn chat request
81
+ */
82
+ export const AIChatModuleRequestSchema = BaseAIRequestOptionsSchema.extend({
83
+ messages: z.array(ChatMessageSchema).min(1),
84
+ });
85
+
86
+ // ============================================================================
87
+ // RESPONSE SCHEMAS
88
+ // ============================================================================
89
+
90
+ /**
91
+ * Latency information
92
+ */
93
+ export const LatencyInfoSchema = z.object({
94
+ totalMs: z.number().nonnegative(),
95
+ formatted: z.string(),
96
+ });
97
+
98
+ /**
99
+ * Raw API response choice (snake_case from API)
100
+ */
101
+ export const RawChoiceSchema = z.object({
102
+ index: z.number().int().nonnegative(),
103
+ message: z.object({
104
+ role: z.string(),
105
+ content: z.string(),
106
+ }),
107
+ finish_reason: z.string(),
108
+ });
109
+
110
+ /**
111
+ * Raw chat completion response from API (snake_case)
112
+ */
113
+ export const RawChatCompletionResponseSchema = z.object({
114
+ id: z.string(),
115
+ object: z.string(),
116
+ created: z.number().int().nonnegative(),
117
+ model: z.string(),
118
+ choices: z.array(RawChoiceSchema).min(1),
119
+ usage: RawUsageSchema.optional(),
120
+ });
121
+
122
+ /**
123
+ * Chat completion response (internal camelCase)
124
+ */
125
+ export const ChatCompletionResponseSchema = z.object({
126
+ id: z.string(),
127
+ object: z.string(),
128
+ created: z.number().int().nonnegative(),
129
+ model: z.string(),
130
+ choices: z
131
+ .array(
132
+ z.object({
133
+ index: z.number().int().nonnegative(),
134
+ message: z.object({
135
+ role: z.string(),
136
+ content: z.string(),
137
+ }),
138
+ finish_reason: z.string(),
139
+ }),
140
+ )
141
+ .min(1),
142
+ usage: TokenUsageSchema.optional(),
143
+ latency: LatencyInfoSchema.optional(),
144
+ });
145
+
146
+ /**
147
+ * Simple AI response
148
+ */
149
+ export const AIResponseSchema = z.object({
150
+ success: z.boolean(),
151
+ content: z.string().optional(),
152
+ error: z.string().optional(),
153
+ usage: TokenUsageSchema.optional(),
154
+ });
155
+
156
+ /**
157
+ * Chat response
158
+ */
159
+ export const AIChatResponseSchema = z.object({
160
+ success: z.boolean(),
161
+ message: z.string().optional(),
162
+ usage: TokenUsageSchema.optional(),
163
+ error: z.string().optional(),
164
+ });
165
+
166
+ // ============================================================================
167
+ // STREAMING SCHEMAS
168
+ // ============================================================================
169
+
170
+ /**
171
+ * Stream delta content (incremental content from streaming responses)
172
+ */
173
+ export const StreamDeltaSchema = z.object({
174
+ role: z.string().optional(),
175
+ content: z.string().optional(),
176
+ });
177
+
178
+ /**
179
+ * Stream chunk type
180
+ */
181
+ export const StreamChunkTypeSchema = z.enum(["text", "done", "error"]);
182
+
183
+ /**
184
+ * Raw stream chunk from API (snake_case)
185
+ */
186
+ export const RawStreamChunkSchema = z.object({
187
+ id: z.string(),
188
+ object: z.string(),
189
+ created: z.number().int().nonnegative(),
190
+ model: z.string(),
191
+ choices: z
192
+ .array(
193
+ z.object({
194
+ index: z.number().int().nonnegative(),
195
+ delta: StreamDeltaSchema,
196
+ finish_reason: z.string().nullable().optional(),
197
+ }),
198
+ )
199
+ .min(1),
200
+ usage: RawUsageSchema.optional(),
201
+ });
202
+
203
+ /**
204
+ * Processed stream chunk (internal camelCase)
205
+ */
206
+ export const StreamChunkSchema = z.object({
207
+ type: StreamChunkTypeSchema,
208
+ id: z.string().optional(),
209
+ content: z.string().optional(),
210
+ finishReason: z.string().optional(),
211
+ usage: TokenUsageSchema.optional(),
212
+ error: z.string().optional(),
213
+ });
214
+
215
+ // ============================================================================
216
+ // ERROR SCHEMAS
217
+ // ============================================================================
218
+
219
+ /**
220
+ * Generic API error response (most providers use this format)
221
+ */
222
+ export const APIErrorResponseSchema = z.object({
223
+ error: z
224
+ .object({
225
+ message: z.string(),
226
+ type: z.string().optional(),
227
+ code: z.string().optional(),
228
+ })
229
+ .optional(),
230
+ });
231
+
232
+ /**
233
+ * Error types categorization
234
+ */
235
+ export const ErrorTypeSchema = z.enum([
236
+ "timeout",
237
+ "auth",
238
+ "rate_limit",
239
+ "network",
240
+ "validation",
241
+ "unknown",
242
+ ]);
243
+
244
+ // ============================================================================
245
+ // TYPE INFERENCE
246
+ // ============================================================================
247
+
248
+ export type ChatMessageRole = z.infer<typeof ChatMessageRoleSchema>;
249
+ export type ChatMessage = z.infer<typeof ChatMessageSchema>;
250
+ export type TokenUsage = z.infer<typeof TokenUsageSchema>;
251
+ export type BaseAIRequestOptions = z.infer<typeof BaseAIRequestOptionsSchema>;
252
+ export type ChatCompletionOptions = z.infer<typeof ChatCompletionOptionsSchema>;
253
+ export type AIRequest = z.infer<typeof AIRequestSchema>;
254
+ export type AIChatModuleRequest = z.infer<typeof AIChatModuleRequestSchema>;
255
+ export type LatencyInfo = z.infer<typeof LatencyInfoSchema>;
256
+ export type RawChatCompletionResponse = z.infer<
257
+ typeof RawChatCompletionResponseSchema
258
+ >;
259
+ export type ChatCompletionResponse = z.infer<
260
+ typeof ChatCompletionResponseSchema
261
+ >;
262
+ export type AIResponse = z.infer<typeof AIResponseSchema>;
263
+ export type AIChatResponse = z.infer<typeof AIChatResponseSchema>;
264
+ export type APIErrorResponse = z.infer<typeof APIErrorResponseSchema>;
265
+ export type ErrorType = z.infer<typeof ErrorTypeSchema>;
266
+ export type StreamDelta = z.infer<typeof StreamDeltaSchema>;
267
+ export type StreamChunkType = z.infer<typeof StreamChunkTypeSchema>;
268
+ export type RawStreamChunk = z.infer<typeof RawStreamChunkSchema>;
269
+ export type StreamChunk = z.infer<typeof StreamChunkSchema>;
270
+
271
+ // ============================================================================
272
+ // VALIDATION HELPERS
273
+ // ============================================================================
274
+
275
+ /**
276
+ * Validate chat message
277
+ */
278
+ export function validateChatMessage(data: unknown) {
279
+ return ChatMessageSchema.safeParse(data);
280
+ }
281
+
282
+ /**
283
+ * Validate chat messages array
284
+ */
285
+ export function validateChatMessages(data: unknown) {
286
+ return z.array(ChatMessageSchema).min(1).safeParse(data);
287
+ }
288
+
289
+ /**
290
+ * Validate chat completion options
291
+ */
292
+ export function validateChatCompletionOptions(data: unknown) {
293
+ return ChatCompletionOptionsSchema.safeParse(data);
294
+ }
295
+
296
+ /**
297
+ * Validate raw API response
298
+ */
299
+ export function validateRawResponse(data: unknown) {
300
+ return RawChatCompletionResponseSchema.safeParse(data);
301
+ }
302
+
303
+ /**
304
+ * Validate and convert raw usage to internal format
305
+ */
306
+ export function convertUsage(raw: unknown): TokenUsage | null {
307
+ const result = RawUsageSchema.safeParse(raw);
308
+ if (!result.success) return null;
309
+
310
+ return {
311
+ promptTokens: result.data.prompt_tokens,
312
+ completionTokens: result.data.completion_tokens,
313
+ totalTokens: result.data.total_tokens,
314
+ };
315
+ }
316
+
317
+ /**
318
+ * Categorize error from unknown data
319
+ * Generic error categorization that works across providers
320
+ */
321
+ export function categorizeError(data: unknown): ErrorType {
322
+ if (data instanceof Error) {
323
+ if (data.message.includes("timeout")) {
324
+ return "timeout";
325
+ }
326
+ if (data.message.includes("unauthorized") || data.message.includes("401")) {
327
+ return "auth";
328
+ }
329
+ if (data.message.includes("rate limit") || data.message.includes("429")) {
330
+ return "rate_limit";
331
+ }
332
+ if (data instanceof TypeError || data.message.includes("fetch")) {
333
+ return "network";
334
+ }
335
+ }
336
+
337
+ const errorResult = APIErrorResponseSchema.safeParse(data);
338
+ if (errorResult.success && errorResult.data.error) {
339
+ const errorMsg = errorResult.data.error.message.toLowerCase();
340
+ if (errorMsg.includes("timeout")) return "timeout";
341
+ if (
342
+ errorMsg.includes("unauthorized") ||
343
+ errorMsg.includes("invalid api key") ||
344
+ errorMsg.includes("401")
345
+ )
346
+ return "auth";
347
+ if (errorMsg.includes("rate limit") || errorMsg.includes("429"))
348
+ return "rate_limit";
349
+ }
350
+
351
+ return "unknown";
352
+ }
353
+
354
+ // ============================================================================
355
+ // STREAMING HELPERS
356
+ // ============================================================================
357
+
358
+ /**
359
+ * Parse a single SSE line
360
+ * Returns null if line is empty or just whitespace
361
+ */
362
+ export function parseSSERow(line: string): string | null {
363
+ const trimmed = line.trim();
364
+ if (!trimmed || trimmed === "") return null;
365
+ if (!trimmed.startsWith("data: ")) return null;
366
+
367
+ const data = trimmed.slice(6);
368
+ if (data === "[DONE]") return data;
369
+
370
+ return data;
371
+ }
372
+
373
+ /**
374
+ * Parse SSE response body and yield stream chunks
375
+ * Converts raw SSE lines to processed StreamChunk objects
376
+ */
377
+ export async function* parseSSEStream(
378
+ response: Response,
379
+ ): AsyncGenerator<StreamChunk, void, unknown> {
380
+ if (!response.body) {
381
+ yield {
382
+ type: "error",
383
+ error: "Response body is null",
384
+ };
385
+ return;
386
+ }
387
+
388
+ const reader = response.body.getReader();
389
+ const decoder = new TextDecoder();
390
+ let buffer = "";
391
+
392
+ try {
393
+ while (true) {
394
+ const { done, value } = await reader.read();
395
+ if (done) break;
396
+
397
+ buffer += decoder.decode(value, { stream: true });
398
+ const lines = buffer.split("\n");
399
+ buffer = lines.pop() || ""; // Keep the last incomplete line in buffer
400
+
401
+ for (const line of lines) {
402
+ const data = parseSSERow(line);
403
+ if (!data) continue;
404
+
405
+ if (data === "[DONE]") {
406
+ yield {
407
+ type: "done",
408
+ };
409
+ return;
410
+ }
411
+
412
+ try {
413
+ const raw = JSON.parse(data);
414
+ const rawChunkResult = RawStreamChunkSchema.safeParse(raw);
415
+
416
+ if (!rawChunkResult.success) {
417
+ yield {
418
+ type: "error",
419
+ error: `Invalid stream chunk: ${rawChunkResult.error.message}`,
420
+ };
421
+ continue;
422
+ }
423
+
424
+ const rawChunk = rawChunkResult.data;
425
+ const delta = rawChunk.choices[0].delta;
426
+
427
+ // Convert usage if present (usually only in final chunk)
428
+ const usage: TokenUsage | undefined = rawChunk.usage
429
+ ? {
430
+ promptTokens: rawChunk.usage.prompt_tokens,
431
+ completionTokens: rawChunk.usage.completion_tokens,
432
+ totalTokens: rawChunk.usage.total_tokens,
433
+ }
434
+ : undefined;
435
+
436
+ yield {
437
+ type: "text",
438
+ id: rawChunk.id,
439
+ content: delta.content || "",
440
+ finishReason: rawChunk.choices[0].finish_reason || undefined,
441
+ usage,
442
+ };
443
+ } catch (error) {
444
+ yield {
445
+ type: "error",
446
+ error: `Failed to parse stream chunk: ${error instanceof Error ? error.message : String(error)}`,
447
+ };
448
+ }
449
+ }
450
+ }
451
+ } finally {
452
+ reader.releaseLock();
453
+ }
454
+ }
455
+
456
+ // ============================================================================
457
+ // EXPORTS
458
+ // ============================================================================
459
+
460
+ export default {
461
+ // Messages
462
+ ChatMessageSchema,
463
+ ChatMessageRoleSchema,
464
+
465
+ // Usage
466
+ TokenUsageSchema,
467
+ RawUsageSchema,
468
+
469
+ // Requests
470
+ BaseAIRequestOptionsSchema,
471
+ ChatCompletionOptionsSchema,
472
+ AIRequestSchema,
473
+ AIChatModuleRequestSchema,
474
+
475
+ // Responses
476
+ LatencyInfoSchema,
477
+ RawChatCompletionResponseSchema,
478
+ ChatCompletionResponseSchema,
479
+ AIResponseSchema,
480
+ AIChatResponseSchema,
481
+
482
+ // Streaming
483
+ StreamDeltaSchema,
484
+ StreamChunkTypeSchema,
485
+ RawStreamChunkSchema,
486
+ StreamChunkSchema,
487
+
488
+ // Errors
489
+ APIErrorResponseSchema,
490
+ ErrorTypeSchema,
491
+
492
+ // Helpers
493
+ validateChatMessage,
494
+ validateChatMessages,
495
+ validateChatCompletionOptions,
496
+ validateRawResponse,
497
+ convertUsage,
498
+ categorizeError,
499
+ parseSSERow,
500
+ parseSSEStream,
501
+ };