@kb-labs/rest-api-contracts 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md ADDED
@@ -0,0 +1,48 @@
1
+ # @kb-labs/api-contracts
2
+
3
+ Shared API contracts for KB Labs REST, CLI, and Studio surfaces.
4
+
5
+ ## Overview
6
+
7
+ Provides Zod schemas and TypeScript types for consistent API shapes across all KB Labs services.
8
+
9
+ ## API Reference
10
+
11
+ ### Error Codes
12
+
13
+ - `ErrorCode` — standardized error code enum
14
+ - `getErrorCode(error)` — extract error code from an error value
15
+
16
+ ### Response Envelopes
17
+
18
+ - `SuccessEnvelope<T>` — `{ ok: true, data: T, meta }`
19
+ - `ErrorEnvelope` — `{ ok: false, error: { code, message, details?, traceId? }, meta }`
20
+
21
+ ### System Types
22
+
23
+ - `SystemInfo` — system information shape
24
+ - `SystemHealth` — health snapshot shape
25
+ - `ReadyState` — readiness probe shape
26
+ - `isReady(state)` — type guard for readiness
27
+
28
+ ## Usage
29
+
30
+ ```typescript
31
+ import { ErrorCode, SuccessEnvelope, ErrorEnvelope } from '@kb-labs/api-contracts';
32
+
33
+ const success: SuccessEnvelope<{ id: string }> = {
34
+ ok: true,
35
+ data: { id: '01K...' },
36
+ meta: { requestId: '01K...', durationMs: 12, apiVersion: '1.0.0' },
37
+ };
38
+
39
+ const error: ErrorEnvelope = {
40
+ ok: false,
41
+ error: { code: ErrorCode.INTERNAL_ERROR, message: 'Something went wrong' },
42
+ meta: { requestId: '01K...', durationMs: 5, apiVersion: '1.0.0' },
43
+ };
44
+ ```
45
+
46
+ ## License
47
+
48
+ KB Public License v1.1 © KB Labs
@@ -0,0 +1,502 @@
1
+ import { z } from 'zod';
2
+ import { StudioRegistry } from '@kb-labs/studio-contracts';
3
+ export { ActionConfirm, ActionHandler, ActionHandlerType, AlertData, AlertOptions, BreadcrumbData, BreadcrumbOptions, COMPOSITE_WIDGET_KINDS, CardData, CardListData, CardListOptions, CardOptions, ChartAreaData, ChartAreaOptions, ChartBarData, ChartBarOptions, ChartLineData, ChartLineOptions, ChartPieData, ChartPieOptions, CheckboxGroupData, CheckboxGroupOptions, CompositeWidgetDecl, CompositeWidgetKind, ConfirmData, ConfirmOptions, DataSource, DatePickerData, DatePickerOptions, DiffData, DiffOptions, EmitActionHandler, FlattenedRegistry, FormData, FormOptions, GridLayoutConfig, GridOptions, InputData, InputOptions, JsonData, JsonOptions, LayoutConfig, LayoutHint, LayoutKind, LeafWidgetDecl, LeafWidgetKind, LogsData, LogsOptions, MenuData, MenuOptions, MetricData, MetricGroupData, MetricGroupOptions, MetricOptions, MockDataSource, ModalData, ModalOptions, NavigateActionHandler, RestActionHandler, RestDataSource, STANDARD_EVENTS, STUDIO_SCHEMA_VERSION, STUDIO_SCHEMA_VERSION_NUMBER, SchemaRef, SectionOptions, SelectData, SelectOptions, StackLayoutConfig, StackOptions, StandardEventName, StaticDataSource, StepperData, StepperOptions, StudioConfig, StudioLayoutDecl, StudioMenuDecl, StudioPluginEntry, StudioRegistry, StudioWidgetDecl, StudioWidgetKind, SwitchData, SwitchOptions, TableColumn, TableData, TableOptions, TabsOptions, TimelineData, TimelineOptions, TreeData, TreeOptions, UserContext, VisibilityRule, WIDGET_CATEGORIES, WidgetAction, WidgetCategory, WidgetData, WidgetDataMap, WidgetEvent, WidgetEventConfig, WidgetOptionsMap, createEmptyRegistry, flattenRegistry, isCompositeKind, isCompositeWidget, isEmitActionHandler, isGridConfig, isLeafWidget, isMockDataSource, isNavigateActionHandler, isRestActionHandler, isRestDataSource, isStackConfig, isStaticDataSource, matchesVisibility, needsMigration, validateSchemaVersion } from '@kb-labs/studio-contracts';
4
+
5
+ /**
6
+ * Standardized error codes shared across CLI, REST and Studio.
7
+ * These values intentionally line up with the codes used by the
8
+ * plugin runtime so adapters can map them to HTTP status codes.
9
+ */
10
+ declare enum ErrorCode {
11
+ INTERNAL = "INTERNAL",
12
+ PLUGIN_PERMISSION_DENIED = "PLUGIN_PERMISSION_DENIED",
13
+ PLUGIN_CAPABILITY_MISSING = "PLUGIN_CAPABILITY_MISSING",
14
+ PLUGIN_HANDLER_NOT_FOUND = "PLUGIN_HANDLER_NOT_FOUND",
15
+ PLUGIN_TIMEOUT = "PLUGIN_TIMEOUT",
16
+ PLUGIN_SCHEMA_VALIDATION_FAILED = "PLUGIN_SCHEMA_VALIDATION_FAILED",
17
+ PLUGIN_ARTIFACT_FAILED = "PLUGIN_ARTIFACT_FAILED",
18
+ PLUGIN_QUOTA_EXCEEDED = "PLUGIN_QUOTA_EXCEEDED",
19
+ ARTIFACT_READ_DENIED = "ARTIFACT_READ_DENIED",
20
+ ARTIFACT_WRITE_DENIED = "ARTIFACT_WRITE_DENIED",
21
+ CONFLICT = "CONFLICT"
22
+ }
23
+ /**
24
+ * Helper describing a compact permission summary.
25
+ */
26
+ interface PermissionSummary {
27
+ fs?: {
28
+ mode?: string;
29
+ allowCount?: number;
30
+ denyCount?: number;
31
+ };
32
+ net?: 'none' | {
33
+ allowHostsCount?: number;
34
+ denyHostsCount?: number;
35
+ };
36
+ env?: {
37
+ allowCount?: number;
38
+ };
39
+ quotas?: {
40
+ timeoutMs?: number;
41
+ memoryMb?: number;
42
+ cpuMs?: number;
43
+ };
44
+ capabilities?: string[];
45
+ }
46
+ /**
47
+ * Permissions diff emitted when the runtime compares required
48
+ * vs granted permissions for a failing invocation.
49
+ */
50
+ interface PermissionDiff {
51
+ required?: string[];
52
+ granted?: string[];
53
+ }
54
+
55
+ interface EnvelopeMeta {
56
+ requestId: string;
57
+ durationMs: number;
58
+ apiVersion: string;
59
+ [key: string]: unknown;
60
+ }
61
+ type SuccessEnvelope<T = unknown> = {
62
+ ok: true;
63
+ data: T;
64
+ meta?: EnvelopeMeta;
65
+ };
66
+ type ErrorEnvelope = {
67
+ ok: false;
68
+ error: {
69
+ code: string;
70
+ message: string;
71
+ details?: Record<string, unknown>;
72
+ cause?: unknown;
73
+ traceId?: string;
74
+ };
75
+ meta: EnvelopeMeta;
76
+ };
77
+ declare const errorEnvelopeSchema: z.ZodObject<{
78
+ ok: z.ZodLiteral<false>;
79
+ error: z.ZodObject<{
80
+ code: z.ZodString;
81
+ message: z.ZodString;
82
+ details: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
83
+ cause: z.ZodOptional<z.ZodUnknown>;
84
+ traceId: z.ZodOptional<z.ZodString>;
85
+ }, "strip", z.ZodTypeAny, {
86
+ code: string;
87
+ message: string;
88
+ details?: Record<string, unknown> | undefined;
89
+ cause?: unknown;
90
+ traceId?: string | undefined;
91
+ }, {
92
+ code: string;
93
+ message: string;
94
+ details?: Record<string, unknown> | undefined;
95
+ cause?: unknown;
96
+ traceId?: string | undefined;
97
+ }>;
98
+ meta: z.ZodObject<{
99
+ requestId: z.ZodString;
100
+ durationMs: z.ZodNumber;
101
+ apiVersion: z.ZodString;
102
+ }, "strip", z.ZodTypeAny, {
103
+ requestId: string;
104
+ durationMs: number;
105
+ apiVersion: string;
106
+ }, {
107
+ requestId: string;
108
+ durationMs: number;
109
+ apiVersion: string;
110
+ }>;
111
+ }, "strip", z.ZodTypeAny, {
112
+ ok: false;
113
+ error: {
114
+ code: string;
115
+ message: string;
116
+ details?: Record<string, unknown> | undefined;
117
+ cause?: unknown;
118
+ traceId?: string | undefined;
119
+ };
120
+ meta: {
121
+ requestId: string;
122
+ durationMs: number;
123
+ apiVersion: string;
124
+ };
125
+ }, {
126
+ ok: false;
127
+ error: {
128
+ code: string;
129
+ message: string;
130
+ details?: Record<string, unknown> | undefined;
131
+ cause?: unknown;
132
+ traceId?: string | undefined;
133
+ };
134
+ meta: {
135
+ requestId: string;
136
+ durationMs: number;
137
+ apiVersion: string;
138
+ };
139
+ }>;
140
+ /**
141
+ * Structured error produced by the plugin runtime.
142
+ */
143
+ interface PluginErrorEnvelope {
144
+ status: 'error';
145
+ http: number;
146
+ code: string;
147
+ message: string;
148
+ details?: Record<string, unknown>;
149
+ trace?: string;
150
+ meta: {
151
+ requestId: string;
152
+ pluginId: string;
153
+ pluginVersion: string;
154
+ routeOrCommand: string;
155
+ timeMs: number;
156
+ cpuMs?: number;
157
+ memMb?: number;
158
+ perms?: PermissionSummary | PermissionDiff | Record<string, unknown>;
159
+ };
160
+ }
161
+
162
+ interface SystemHealthSnapshot {
163
+ schema: 'kb.health/1';
164
+ ts: string;
165
+ uptimeSec: number;
166
+ version: {
167
+ kbLabs: string;
168
+ cli: string;
169
+ rest: string;
170
+ studio?: string;
171
+ git?: {
172
+ sha: string;
173
+ dirty: boolean;
174
+ };
175
+ [key: string]: unknown;
176
+ };
177
+ registry: {
178
+ total: number;
179
+ withRest: number;
180
+ withStudio: number;
181
+ errors: number;
182
+ generatedAt: string;
183
+ expiresAt?: string;
184
+ partial: boolean;
185
+ stale: boolean;
186
+ };
187
+ status: 'healthy' | 'degraded';
188
+ components: Array<{
189
+ id: string;
190
+ version?: string;
191
+ restRoutes?: number;
192
+ studioWidgets?: number;
193
+ lastError?: string;
194
+ meta?: Record<string, unknown>;
195
+ }>;
196
+ meta?: Record<string, unknown>;
197
+ }
198
+ interface SystemInfoPayload {
199
+ schema: 'kb.info/1';
200
+ ts: string;
201
+ uptimeSec: number;
202
+ environment: string;
203
+ versions: Record<string, string>;
204
+ features?: Record<string, boolean>;
205
+ meta?: Record<string, unknown>;
206
+ }
207
+ interface SystemCapabilitiesPayload {
208
+ schema: 'kb.capabilities/1';
209
+ capabilities: Array<{
210
+ id: string;
211
+ describe: string;
212
+ granted: boolean;
213
+ origin?: string;
214
+ }>;
215
+ plugins?: Record<string, string[]>;
216
+ meta?: Record<string, unknown>;
217
+ }
218
+ interface SystemConfigPayload {
219
+ schema: 'kb.config.redacted/1';
220
+ config: Record<string, unknown>;
221
+ redacted: string[];
222
+ meta?: Record<string, unknown>;
223
+ }
224
+ type InfoResponse = SuccessEnvelope<SystemInfoPayload>;
225
+ type CapabilitiesResponse = SuccessEnvelope<SystemCapabilitiesPayload>;
226
+ type ConfigResponse = SuccessEnvelope<SystemConfigPayload>;
227
+
228
+ interface ReadyComponents {
229
+ cliApi: {
230
+ initialized: boolean;
231
+ };
232
+ registry: {
233
+ loaded: boolean;
234
+ partial: boolean;
235
+ stale: boolean;
236
+ };
237
+ plugins: {
238
+ mounted: number;
239
+ inProgress: boolean;
240
+ routeCount: number;
241
+ errors: number;
242
+ failures: Array<{
243
+ id: string;
244
+ error: string;
245
+ }>;
246
+ lastCompletedAt: string | null;
247
+ lastDurationMs: number | null;
248
+ };
249
+ redis: {
250
+ enabled: boolean;
251
+ healthy: boolean;
252
+ states?: Record<string, unknown>;
253
+ };
254
+ }
255
+ interface ReadyResponseBase {
256
+ schema: 'kb.ready/1';
257
+ ts: string;
258
+ reason: string;
259
+ components: ReadyComponents;
260
+ }
261
+ type ReadyResponse = ReadyResponseBase & {
262
+ ready: true;
263
+ status: 'ready' | 'degraded';
264
+ };
265
+ type NotReadyResponse = ReadyResponseBase & {
266
+ ready: false;
267
+ status: 'initializing' | 'degraded';
268
+ };
269
+
270
+ /**
271
+ * @module @kb-labs/rest-api-contracts/studio
272
+ * Re-exports from @kb-labs/studio-contracts + REST-specific types.
273
+ *
274
+ * Studio should ONLY import from this package - no server-side dependencies.
275
+ *
276
+ * @example
277
+ * ```typescript
278
+ * // Preferred: Import directly from studio-contracts
279
+ * import { StudioWidgetDecl, StudioConfig } from '@kb-labs/studio-contracts';
280
+ *
281
+ * // Still works: Import via rest-api-contracts (re-export)
282
+ * import { StudioWidgetDecl, StudioConfig } from '@kb-labs/rest-api-contracts';
283
+ * ```
284
+ */
285
+
286
+ /**
287
+ * GET /studio/registry response
288
+ * Extends StudioRegistry with REST-specific metadata
289
+ */
290
+ type StudioRegistryResponse = StudioRegistry;
291
+ /**
292
+ * Batch data request for multiple widgets
293
+ */
294
+ interface BatchDataRequest {
295
+ widgetIds: string[];
296
+ }
297
+ /**
298
+ * Batch data response
299
+ */
300
+ interface BatchDataResponse {
301
+ /** widgetId -> data mapping */
302
+ data: Record<string, unknown>;
303
+ /** widgetId -> error message for failed widgets */
304
+ errors?: Record<string, string>;
305
+ }
306
+ /**
307
+ * Action execution request
308
+ */
309
+ interface ActionRequest {
310
+ widgetId: string;
311
+ actionId: string;
312
+ payload?: unknown;
313
+ }
314
+ /**
315
+ * Action execution response
316
+ */
317
+ interface ActionResponse {
318
+ success: boolean;
319
+ data?: unknown;
320
+ error?: string;
321
+ }
322
+
323
+ /**
324
+ * @module @kb-labs/rest-api-contracts/observability
325
+ * Observability contracts for system monitoring endpoints
326
+ */
327
+ /**
328
+ * Statistics from State Broker daemon
329
+ *
330
+ * Provides metrics about in-memory cache performance, namespace usage,
331
+ * and multi-tenancy statistics.
332
+ */
333
+ interface StateBrokerStats {
334
+ /** Daemon uptime in milliseconds */
335
+ uptime: number;
336
+ /** Total number of cache entries across all namespaces */
337
+ totalEntries: number;
338
+ /** Total cache size in bytes (estimated) */
339
+ totalSize: number;
340
+ /** Cache hit rate (0-1) */
341
+ hitRate: number;
342
+ /** Cache miss rate (0-1) */
343
+ missRate: number;
344
+ /** Number of evicted entries */
345
+ evictions: number;
346
+ /** Stats per namespace (mind, workflow, etc.) */
347
+ namespaces: Record<string, NamespaceStats>;
348
+ /** Stats per tenant (multi-tenancy support) */
349
+ byTenant?: Record<string, TenantStats>;
350
+ }
351
+ /**
352
+ * Statistics for a specific namespace
353
+ */
354
+ interface NamespaceStats {
355
+ /** Number of entries in this namespace */
356
+ entries: number;
357
+ /** Number of cache hits */
358
+ hits: number;
359
+ /** Number of cache misses */
360
+ misses: number;
361
+ /** Estimated size in bytes */
362
+ size: number;
363
+ }
364
+ /**
365
+ * Statistics for a specific tenant
366
+ */
367
+ interface TenantStats {
368
+ /** Number of entries for this tenant */
369
+ entries: number;
370
+ /** Total operations performed */
371
+ operations: number;
372
+ }
373
+ /**
374
+ * DevKit health check results
375
+ *
376
+ * Provides monorepo health metrics including health score, issues breakdown,
377
+ * and type coverage statistics.
378
+ */
379
+ interface DevKitHealthSnapshot {
380
+ /** Health score (0-100) */
381
+ healthScore: number;
382
+ /** Letter grade (A-F) based on health score */
383
+ grade: 'A' | 'B' | 'C' | 'D' | 'F';
384
+ /** Breakdown of issues affecting health score */
385
+ issues: {
386
+ /** Number of duplicate dependencies */
387
+ duplicateDeps?: number;
388
+ /** Number of packages missing README files */
389
+ missingReadmes?: number;
390
+ /** Number of TypeScript type errors */
391
+ typeErrors?: number;
392
+ /** Number of broken imports */
393
+ brokenImports?: number;
394
+ /** Number of unused exports */
395
+ unusedExports?: number;
396
+ /** Other issues (custom keys) */
397
+ [key: string]: number | undefined;
398
+ };
399
+ /** Total number of packages in monorepo */
400
+ packages: number;
401
+ /** Average TypeScript type coverage (0-100) */
402
+ avgTypeCoverage?: number;
403
+ /** Number of packages with poor type coverage (<70%) */
404
+ poorTypeCoverageCount?: number;
405
+ }
406
+ /**
407
+ * Response payload for GET /api/v1/observability/state-broker
408
+ */
409
+ interface StateBrokerStatsPayload {
410
+ ok: true;
411
+ data: StateBrokerStats;
412
+ meta: {
413
+ source: 'state-broker';
414
+ daemonUrl: string;
415
+ };
416
+ }
417
+ /**
418
+ * Response payload for GET /api/v1/observability/devkit
419
+ */
420
+ interface DevKitHealthPayload {
421
+ ok: true;
422
+ data: DevKitHealthSnapshot;
423
+ meta: {
424
+ source: 'devkit-cli';
425
+ repoRoot: string;
426
+ command: string;
427
+ };
428
+ }
429
+ /**
430
+ * Historical data point
431
+ */
432
+ interface HistoricalDataPoint {
433
+ /** Unix timestamp in milliseconds */
434
+ timestamp: number;
435
+ /** Metric value */
436
+ value: number;
437
+ }
438
+ /**
439
+ * Heatmap cell data (7 days × 24 hours)
440
+ */
441
+ interface HeatmapCell {
442
+ /** Day of week: 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun' */
443
+ day: string;
444
+ /** Hour of day: 0-23 */
445
+ hour: number;
446
+ /** Aggregated metric value */
447
+ value: number;
448
+ }
449
+ /**
450
+ * Response payload for GET /api/v1/observability/metrics/history
451
+ */
452
+ interface MetricsHistoryPayload {
453
+ ok: true;
454
+ data: HistoricalDataPoint[];
455
+ meta: {
456
+ source: 'historical-metrics-collector';
457
+ metric: 'requests' | 'errors' | 'latency' | 'uptime';
458
+ range: '1m' | '5m' | '10m' | '30m' | '1h';
459
+ interval: '5s' | '1m' | '5m';
460
+ points: number;
461
+ };
462
+ }
463
+ /**
464
+ * Response payload for GET /api/v1/observability/metrics/heatmap
465
+ */
466
+ interface MetricsHeatmapPayload {
467
+ ok: true;
468
+ data: HeatmapCell[];
469
+ meta: {
470
+ source: 'historical-metrics-collector';
471
+ metric: 'latency' | 'errors' | 'requests';
472
+ days: 7 | 14 | 30;
473
+ cells: number;
474
+ };
475
+ }
476
+
477
+ /**
478
+ * Adapter value can be:
479
+ * - string: single adapter package
480
+ * - string[]: multiple adapters (first = primary)
481
+ * - null: disabled/NoOp
482
+ */
483
+ type AdapterValue = string | string[] | null;
484
+ /**
485
+ * Platform configuration snapshot.
486
+ * Returns current platform adapters and their options (redacted for sensitive data).
487
+ */
488
+ interface PlatformConfigPayload {
489
+ schema: 'kb.platform.config/1';
490
+ ts: string;
491
+ /** Adapter packages (can be string, string[], or null for each key) */
492
+ adapters: Record<string, AdapterValue>;
493
+ adapterOptions: Record<string, unknown>;
494
+ execution: {
495
+ mode: string;
496
+ };
497
+ /** List of keys that were redacted from adapterOptions */
498
+ redacted: string[];
499
+ }
500
+ type PlatformConfigResponse = SuccessEnvelope<PlatformConfigPayload>;
501
+
502
+ export { type ActionRequest, type ActionResponse, type AdapterValue, type BatchDataRequest, type BatchDataResponse, type CapabilitiesResponse, type ConfigResponse, type DevKitHealthPayload, type DevKitHealthSnapshot, type EnvelopeMeta, ErrorCode, type ErrorEnvelope, type HeatmapCell, type HistoricalDataPoint, type InfoResponse, type MetricsHeatmapPayload, type MetricsHistoryPayload, type NamespaceStats, type NotReadyResponse, type PermissionDiff, type PermissionSummary, type PlatformConfigPayload, type PlatformConfigResponse, type PluginErrorEnvelope, type ReadyComponents, type ReadyResponse, type StateBrokerStats, type StateBrokerStatsPayload, type StudioRegistryResponse, type SuccessEnvelope, type SystemCapabilitiesPayload, type SystemConfigPayload, type SystemHealthSnapshot, type SystemInfoPayload, type TenantStats, errorEnvelopeSchema };
package/dist/index.js ADDED
@@ -0,0 +1,37 @@
1
+ import { z } from 'zod';
2
+ export { COMPOSITE_WIDGET_KINDS, STANDARD_EVENTS, STUDIO_SCHEMA_VERSION, STUDIO_SCHEMA_VERSION_NUMBER, WIDGET_CATEGORIES, createEmptyRegistry, flattenRegistry, isCompositeKind, isCompositeWidget, isEmitActionHandler, isGridConfig, isLeafWidget, isMockDataSource, isNavigateActionHandler, isRestActionHandler, isRestDataSource, isStackConfig, isStaticDataSource, matchesVisibility, needsMigration, validateSchemaVersion } from '@kb-labs/studio-contracts';
3
+
4
+ // src/error-code.ts
5
+ var ErrorCode = /* @__PURE__ */ ((ErrorCode2) => {
6
+ ErrorCode2["INTERNAL"] = "INTERNAL";
7
+ ErrorCode2["PLUGIN_PERMISSION_DENIED"] = "PLUGIN_PERMISSION_DENIED";
8
+ ErrorCode2["PLUGIN_CAPABILITY_MISSING"] = "PLUGIN_CAPABILITY_MISSING";
9
+ ErrorCode2["PLUGIN_HANDLER_NOT_FOUND"] = "PLUGIN_HANDLER_NOT_FOUND";
10
+ ErrorCode2["PLUGIN_TIMEOUT"] = "PLUGIN_TIMEOUT";
11
+ ErrorCode2["PLUGIN_SCHEMA_VALIDATION_FAILED"] = "PLUGIN_SCHEMA_VALIDATION_FAILED";
12
+ ErrorCode2["PLUGIN_ARTIFACT_FAILED"] = "PLUGIN_ARTIFACT_FAILED";
13
+ ErrorCode2["PLUGIN_QUOTA_EXCEEDED"] = "PLUGIN_QUOTA_EXCEEDED";
14
+ ErrorCode2["ARTIFACT_READ_DENIED"] = "ARTIFACT_READ_DENIED";
15
+ ErrorCode2["ARTIFACT_WRITE_DENIED"] = "ARTIFACT_WRITE_DENIED";
16
+ ErrorCode2["CONFLICT"] = "CONFLICT";
17
+ return ErrorCode2;
18
+ })(ErrorCode || {});
19
+ var errorEnvelopeSchema = z.object({
20
+ ok: z.literal(false),
21
+ error: z.object({
22
+ code: z.string(),
23
+ message: z.string(),
24
+ details: z.record(z.string(), z.unknown()).optional(),
25
+ cause: z.unknown().optional(),
26
+ traceId: z.string().optional()
27
+ }),
28
+ meta: z.object({
29
+ requestId: z.string(),
30
+ durationMs: z.number(),
31
+ apiVersion: z.string()
32
+ })
33
+ });
34
+
35
+ export { ErrorCode, errorEnvelopeSchema };
36
+ //# sourceMappingURL=index.js.map
37
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/error-code.ts","../src/envelopes.ts"],"names":["ErrorCode"],"mappings":";;;;AAKO,IAAK,SAAA,qBAAAA,UAAAA,KAAL;AACL,EAAAA,WAAA,UAAA,CAAA,GAAW,UAAA;AACX,EAAAA,WAAA,0BAAA,CAAA,GAA2B,0BAAA;AAC3B,EAAAA,WAAA,2BAAA,CAAA,GAA4B,2BAAA;AAC5B,EAAAA,WAAA,0BAAA,CAAA,GAA2B,0BAAA;AAC3B,EAAAA,WAAA,gBAAA,CAAA,GAAiB,gBAAA;AACjB,EAAAA,WAAA,iCAAA,CAAA,GAAkC,iCAAA;AAClC,EAAAA,WAAA,wBAAA,CAAA,GAAyB,wBAAA;AACzB,EAAAA,WAAA,uBAAA,CAAA,GAAwB,uBAAA;AACxB,EAAAA,WAAA,sBAAA,CAAA,GAAuB,sBAAA;AACvB,EAAAA,WAAA,uBAAA,CAAA,GAAwB,uBAAA;AACxB,EAAAA,WAAA,UAAA,CAAA,GAAW,UAAA;AAXD,EAAA,OAAAA,UAAAA;AAAA,CAAA,EAAA,SAAA,IAAA,EAAA;ACuBL,IAAM,mBAAA,GAAsB,EAAE,MAAA,CAAO;AAAA,EAC1C,EAAA,EAAI,CAAA,CAAE,OAAA,CAAQ,KAAK,CAAA;AAAA,EACnB,KAAA,EAAO,EAAE,MAAA,CAAO;AAAA,IACd,IAAA,EAAM,EAAE,MAAA,EAAO;AAAA,IACf,OAAA,EAAS,EAAE,MAAA,EAAO;AAAA,IAClB,OAAA,EAAS,CAAA,CAAE,MAAA,CAAO,CAAA,CAAE,MAAA,IAAU,CAAA,CAAE,OAAA,EAAS,CAAA,CAAE,QAAA,EAAS;AAAA,IACpD,KAAA,EAAO,CAAA,CAAE,OAAA,EAAQ,CAAE,QAAA,EAAS;AAAA,IAC5B,OAAA,EAAS,CAAA,CAAE,MAAA,EAAO,CAAE,QAAA;AAAS,GAC9B,CAAA;AAAA,EACD,IAAA,EAAM,EAAE,MAAA,CAAO;AAAA,IACb,SAAA,EAAW,EAAE,MAAA,EAAO;AAAA,IACpB,UAAA,EAAY,EAAE,MAAA,EAAO;AAAA,IACrB,UAAA,EAAY,EAAE,MAAA;AAAO,GACtB;AACH,CAAC","file":"index.js","sourcesContent":["/**\n * Standardized error codes shared across CLI, REST and Studio.\n * These values intentionally line up with the codes used by the\n * plugin runtime so adapters can map them to HTTP status codes.\n */\nexport enum ErrorCode {\n INTERNAL = 'INTERNAL',\n PLUGIN_PERMISSION_DENIED = 'PLUGIN_PERMISSION_DENIED',\n PLUGIN_CAPABILITY_MISSING = 'PLUGIN_CAPABILITY_MISSING',\n PLUGIN_HANDLER_NOT_FOUND = 'PLUGIN_HANDLER_NOT_FOUND',\n PLUGIN_TIMEOUT = 'PLUGIN_TIMEOUT',\n PLUGIN_SCHEMA_VALIDATION_FAILED = 'PLUGIN_SCHEMA_VALIDATION_FAILED',\n PLUGIN_ARTIFACT_FAILED = 'PLUGIN_ARTIFACT_FAILED',\n PLUGIN_QUOTA_EXCEEDED = 'PLUGIN_QUOTA_EXCEEDED',\n ARTIFACT_READ_DENIED = 'ARTIFACT_READ_DENIED',\n ARTIFACT_WRITE_DENIED = 'ARTIFACT_WRITE_DENIED',\n CONFLICT = 'CONFLICT',\n}\n\n/**\n * Helper describing a compact permission summary.\n */\nexport interface PermissionSummary {\n fs?: {\n mode?: string;\n allowCount?: number;\n denyCount?: number;\n };\n net?: 'none' | { allowHostsCount?: number; denyHostsCount?: number };\n env?: { allowCount?: number };\n quotas?: {\n timeoutMs?: number;\n memoryMb?: number;\n cpuMs?: number;\n };\n capabilities?: string[];\n}\n\n/**\n * Permissions diff emitted when the runtime compares required\n * vs granted permissions for a failing invocation.\n */\nexport interface PermissionDiff {\n required?: string[];\n granted?: string[];\n}\n\n","import { z } from 'zod';\nimport type { PermissionDiff, PermissionSummary } from './error-code';\n\nexport interface EnvelopeMeta {\n requestId: string;\n durationMs: number;\n apiVersion: string;\n [key: string]: unknown;\n}\n\nexport type SuccessEnvelope<T = unknown> = {\n ok: true;\n data: T;\n meta?: EnvelopeMeta;\n};\n\nexport type ErrorEnvelope = {\n ok: false;\n error: {\n code: string;\n message: string;\n details?: Record<string, unknown>;\n cause?: unknown;\n traceId?: string;\n };\n meta: EnvelopeMeta;\n};\n\nexport const errorEnvelopeSchema = z.object({\n ok: z.literal(false),\n error: z.object({\n code: z.string(),\n message: z.string(),\n details: z.record(z.string(), z.unknown()).optional(),\n cause: z.unknown().optional(),\n traceId: z.string().optional(),\n }),\n meta: z.object({\n requestId: z.string(),\n durationMs: z.number(),\n apiVersion: z.string(),\n }),\n});\n\n/**\n * Structured error produced by the plugin runtime.\n */\nexport interface PluginErrorEnvelope {\n status: 'error';\n http: number;\n code: string;\n message: string;\n details?: Record<string, unknown>;\n trace?: string;\n meta: {\n requestId: string;\n pluginId: string;\n pluginVersion: string;\n routeOrCommand: string;\n timeMs: number;\n cpuMs?: number;\n memMb?: number;\n perms?: PermissionSummary | PermissionDiff | Record<string, unknown>;\n };\n}\n\n\n"]}
package/package.json ADDED
@@ -0,0 +1,47 @@
1
+ {
2
+ "name": "@kb-labs/rest-api-contracts",
3
+ "version": "1.0.0",
4
+ "description": "Shared API contracts for KB Labs REST/CLI/Studio surfaces",
5
+ "type": "module",
6
+ "main": "./dist/index.js",
7
+ "types": "./dist/index.d.ts",
8
+ "exports": {
9
+ ".": {
10
+ "import": "./dist/index.js",
11
+ "types": "./dist/index.d.ts"
12
+ }
13
+ },
14
+ "files": [
15
+ "dist",
16
+ "README.md"
17
+ ],
18
+ "dependencies": {
19
+ "@kb-labs/studio-contracts": "link:../../../kb-labs-studio/packages/studio-contracts",
20
+ "zod": "^3.23.8"
21
+ },
22
+ "devDependencies": {
23
+ "@kb-labs/devkit": "link:../../../kb-labs-devkit",
24
+ "@types/node": "^24.3.3",
25
+ "rimraf": "^6.0.1",
26
+ "tsup": "^8.5.0",
27
+ "typescript": "^5.6.3",
28
+ "vitest": "^3.2.4"
29
+ },
30
+ "engines": {
31
+ "node": ">=20.0.0",
32
+ "pnpm": ">=9.0.0"
33
+ },
34
+ "publishConfig": {
35
+ "access": "public"
36
+ },
37
+ "scripts": {
38
+ "build": "tsup --config tsup.config.ts",
39
+ "dev": "tsup --config tsup.config.ts --watch",
40
+ "clean": "rimraf dist",
41
+ "lint": "eslint src",
42
+ "test": "vitest run --passWithNoTests",
43
+ "lint:fix": "eslint . --fix",
44
+ "type-check": "tsc --noEmit",
45
+ "test:watch": "vitest"
46
+ }
47
+ }