@mochabug/adapt-sdk 0.4.0 → 0.4.2

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.
@@ -1,5 +1,13 @@
1
1
  import type { JTDSchemaJson, SignalDescriptorJson } from '../api';
2
- /** JSON Schema subset supported by Gemini 3+ structured output. */
2
+ /**
3
+ * JSON Schema subset accepted by the Gemini structured-output API.
4
+ *
5
+ * This is the provider-specific representation produced by {@link GeminiConversion}.
6
+ * It covers the keywords that Gemini 3+ actually inspects when constraining
7
+ * model output: `type`, `properties`, `required`, `enum`, `items`,
8
+ * `additionalProperties`, `format`, `minimum`/`maximum`, `title`, and
9
+ * `description`.
10
+ */
3
11
  export interface GeminiSchema {
4
12
  type?: string | string[];
5
13
  title?: string;
@@ -13,40 +21,199 @@ export interface GeminiSchema {
13
21
  minimum?: number;
14
22
  maximum?: number;
15
23
  }
16
- export interface ConvertSuccess {
24
+ /**
25
+ * Successful conversion result for a JTD format.
26
+ *
27
+ * Returned when the raw LLM output has been coerced to match the JTD schema
28
+ * and passes JTD validation. `data` contains the deserialized, coerced, and
29
+ * JTD-validated JSON value.
30
+ */
31
+ export interface ConvertSuccessJson {
17
32
  success: true;
33
+ kind: 'json';
34
+ /** The deserialized, coerced, and JTD-validated JSON value. */
18
35
  data: unknown;
19
36
  }
37
+ /**
38
+ * Successful conversion result for a MIME (binary) format.
39
+ *
40
+ * Returned when the raw LLM output matches a MIME format. The base64 string
41
+ * produced by the model is decoded into raw binary bytes.
42
+ */
43
+ export interface ConvertSuccessBinary {
44
+ success: true;
45
+ kind: 'binary';
46
+ /** The concrete MIME type of the binary content (e.g. `"image/png"`). */
47
+ mimeType: string;
48
+ /** The raw binary data decoded from the base64 string returned by the LLM. */
49
+ data: Uint8Array;
50
+ /** Optional filename, provided by the caller if available. */
51
+ filename?: string;
52
+ }
53
+ /**
54
+ * Failed conversion result.
55
+ *
56
+ * `errors` contains one or more human-readable strings describing validation
57
+ * or coercion failures. Each entry uses a JSON Pointer path prefix
58
+ * (e.g. `"/foo/bar: ..."`) to locate the problem within the data.
59
+ */
20
60
  export interface ConvertFailure {
21
61
  success: false;
62
+ /** Array of human-readable error messages with JSON Pointer path prefixes. */
22
63
  errors: string[];
23
64
  }
24
- export type ConvertResult = ConvertSuccess | ConvertFailure;
25
- export interface GeminiConversionResult {
26
- /** Gemini 3+ compatible JSON Schema for structured output. */
27
- schema: GeminiSchema;
28
- /** Convert Gemini JSON output back to JTD-conforming JSON. */
29
- convert: (geminiJson: unknown) => ConvertResult;
30
- }
31
65
  /**
32
- * Convert a JTD schema to a Gemini 3+ compatible JSON Schema, with a
33
- * converter function that transforms and validates Gemini output against
34
- * the original JTD schema.
66
+ * Discriminated union of conversion outcomes.
35
67
  *
36
- * @throws {Error} if the JTD schema contains forms that cannot be represented.
68
+ * Check `success` first, then narrow on `kind` (`'json'` or `'binary'`)
69
+ * for successful results.
37
70
  */
38
- export declare function convertToGeminiSchema(jtdSchema: JTDSchemaJson): GeminiConversionResult;
71
+ export type ConvertResult = ConvertSuccessJson | ConvertSuccessBinary | ConvertFailure;
39
72
  /**
40
- * Convert a SignalDescriptorJson to a Gemini 3+ compatible JSON Schema.
73
+ * Converts JTD schemas or Adapt signal descriptors into Gemini-compatible
74
+ * JSON Schema, and converts raw LLM output back into validated data.
75
+ *
76
+ * ### JTD form mapping
77
+ * - **type** -- mapped to the corresponding JSON Schema `type` (`string`,
78
+ * `number`, `integer`, `boolean`). Integer sub-types (int8 .. uint32) add
79
+ * `minimum`/`maximum` bounds. `timestamp` becomes `string` with
80
+ * `format: "date-time"`.
81
+ * - **enum** -- mapped to `type: "string"` with an `enum` array.
82
+ * - **elements** -- mapped to `type: "array"` with `items`.
83
+ * - **properties / optionalProperties** -- mapped to `type: "object"` with
84
+ * `properties`, `required`, and `additionalProperties: false`. Optional
85
+ * properties are included but not listed in `required`.
86
+ * - **values** -- mapped to `type: "object"` with `additionalProperties` set
87
+ * to the value schema (Gemini supports free-form object keys natively).
88
+ * - **discriminator** -- mapped to a wrapper object: a `type: "string"` enum
89
+ * property for the discriminator tag, plus one property per variant. The
90
+ * LLM is instructed via `description` to populate only the property
91
+ * matching the chosen tag. (Gemini does not support `anyOf`.)
92
+ *
93
+ * ### MIME formats
94
+ * MIME signal formats become `type: "string"` with a description requesting
95
+ * base64-encoded content. On {@link convert}, the base64 string is decoded
96
+ * into a {@link ConvertSuccessBinary} result.
97
+ *
98
+ * ### Serialization
99
+ * `JSON.stringify(conv)` produces a JSON-safe object via {@link toJSON}.
100
+ * Use {@link fromJSON} to restore a fully functional instance from the
101
+ * serialized form (string or parsed object).
41
102
  *
42
- * Handles single and multi-format signals:
43
- * - Single format: schema is the converted format directly.
44
- * - Multiple formats: schema is a wrapper object with `format_0`, `format_1`, etc.
45
- * as optional properties. The convert function extracts the selected format.
103
+ * ```ts
104
+ * const conv = GeminiConversion.fromJTD(jtdSchema);
105
+ * conv.schema; // Gemini JSON Schema to pass to the LLM
106
+ * conv.convert(output); // coerce + validate -> ConvertResult
46
107
  *
47
- * MIME type formats are mapped to base64 strings.
108
+ * // Serialize & restore
109
+ * const cached = JSON.stringify(conv);
110
+ * const restored = GeminiConversion.fromJSON(cached);
111
+ * ```
112
+ */
113
+ export declare class GeminiConversion {
114
+ /** The Gemini-specific JSON Schema to pass to the Gemini API as the response schema. */
115
+ readonly schema: GeminiSchema;
116
+ /**
117
+ * The original JTD schema used to build this conversion.
118
+ * Set when created via {@link fromJTD}; `undefined` when created via {@link fromSignal}.
119
+ */
120
+ readonly jtdSchema?: JTDSchemaJson;
121
+ /**
122
+ * The original signal descriptor used to build this conversion.
123
+ * Set when created via {@link fromSignal}; `undefined` when created via {@link fromJTD}.
124
+ */
125
+ readonly descriptor?: SignalDescriptorJson;
126
+ /**
127
+ * Build a conversion from a JTD schema.
128
+ *
129
+ * Recursively converts every JTD form into the equivalent Gemini JSON Schema
130
+ * node. Definitions (`jtdSchema.definitions`) are resolved inline because
131
+ * Gemini does not support `$ref`.
132
+ *
133
+ * @param jtdSchema - A valid JTD schema (RFC 8927).
134
+ * @returns A new {@link GeminiConversion} with `jtdSchema` set.
135
+ * @throws If the schema contains an unknown JTD type, an unresolved `ref`,
136
+ * or circular / excessively deep refs (exceeding 32 levels).
137
+ */
138
+ static fromJTD(jtdSchema: JTDSchemaJson): GeminiConversion;
139
+ /**
140
+ * Build a conversion from an Adapt signal descriptor.
141
+ *
142
+ * If the descriptor has a single format, its schema is used directly
143
+ * (unwrapped). If it has multiple formats, a wrapper object schema is
144
+ * produced with `format_0`, `format_1`, ... properties -- the LLM must
145
+ * populate exactly one. MIME formats become base64 string schemas.
146
+ *
147
+ * @param descriptor - An Adapt signal descriptor with one or more formats.
148
+ * @returns A new {@link GeminiConversion} with `descriptor` set.
149
+ * @throws If the descriptor has no formats, or a format has neither
150
+ * `jtdSchema` nor `mimeType`.
151
+ */
152
+ static fromSignal(descriptor: SignalDescriptorJson): GeminiConversion;
153
+ /**
154
+ * Restore a {@link GeminiConversion} from its serialized form.
155
+ *
156
+ * Accepts either the JSON string produced by `JSON.stringify(conv)` or the
157
+ * already-parsed plain object. The original `jtdSchema` or `descriptor` is
158
+ * re-processed through the corresponding factory, so the restored instance
159
+ * is fully functional.
160
+ *
161
+ * @param data - A JSON string or parsed object previously produced by {@link toJSON}.
162
+ * @returns A fully reconstructed {@link GeminiConversion}.
163
+ * @throws If the serialized data contains neither `jtdSchema` nor `descriptor`.
164
+ */
165
+ static fromJSON(data: string | Record<string, unknown>): GeminiConversion;
166
+ private constructor();
167
+ /**
168
+ * Convert raw LLM output into a validated result.
169
+ *
170
+ * For JTD-based conversions, the value is coerced (e.g. non-integer numbers
171
+ * are rounded for integer types, discriminator wrapper objects are unwrapped
172
+ * into flat tagged unions), then validated against the original JTD schema.
173
+ * Returns {@link ConvertSuccessJson} on success.
174
+ *
175
+ * For MIME-based conversions, the value is expected to be a base64 string
176
+ * which is decoded into raw bytes. Returns {@link ConvertSuccessBinary} on
177
+ * success.
178
+ *
179
+ * For multi-format signals, the first non-null `format_N` property is
180
+ * selected and converted individually.
181
+ *
182
+ * @param json - The raw value returned by the Gemini API (typically parsed JSON).
183
+ * @returns A {@link ConvertResult} indicating success or failure with errors.
184
+ */
185
+ convert: (json: unknown) => ConvertResult;
186
+ /**
187
+ * Produce a JSON-serializable representation of this conversion.
188
+ *
189
+ * The output includes the Gemini `schema` and either the original
190
+ * `jtdSchema` or `descriptor` (whichever was used to create this instance),
191
+ * which is sufficient to fully restore the conversion via {@link fromJSON}.
192
+ *
193
+ * Called automatically by `JSON.stringify(conv)`.
194
+ */
195
+ toJSON(): {
196
+ schema: GeminiSchema;
197
+ descriptor: SignalDescriptorJson;
198
+ jtdSchema?: undefined;
199
+ } | {
200
+ schema: GeminiSchema;
201
+ jtdSchema: JTDSchemaJson | undefined;
202
+ descriptor?: undefined;
203
+ };
204
+ }
205
+ /**
206
+ * Convenience alias for {@link GeminiConversion.fromJTD}.
207
+ *
208
+ * @param jtdSchema - A valid JTD schema (RFC 8927).
209
+ * @returns A new {@link GeminiConversion}.
210
+ */
211
+ export declare function convertToGeminiSchema(jtdSchema: JTDSchemaJson): GeminiConversion;
212
+ /**
213
+ * Convenience alias for {@link GeminiConversion.fromSignal}.
48
214
  *
49
- * @throws {Error} if the descriptor has no formats.
215
+ * @param descriptor - An Adapt signal descriptor.
216
+ * @returns A new {@link GeminiConversion}.
50
217
  */
51
- export declare function convertSignalToGeminiSchema(descriptor: SignalDescriptorJson): GeminiConversionResult;
218
+ export declare function convertSignalToGeminiSchema(descriptor: SignalDescriptorJson): GeminiConversion;
52
219
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/gemini/index.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EACV,aAAa,EACb,oBAAoB,EAErB,MAAM,QAAQ,CAAC;AAOhB,mEAAmE;AACnE,MAAM,WAAW,YAAY;IAC3B,IAAI,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC;IACzB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,YAAY,CAAC,CAAC;IAC1C,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;IACpB,oBAAoB,CAAC,EAAE,OAAO,GAAG,YAAY,CAAC;IAC9C,IAAI,CAAC,EAAE,CAAC,MAAM,GAAG,MAAM,GAAG,IAAI,CAAC,EAAE,CAAC;IAClC,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,YAAY,CAAC;IACrB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,cAAc;IAC7B,OAAO,EAAE,IAAI,CAAC;IACd,IAAI,EAAE,OAAO,CAAC;CACf;AAED,MAAM,WAAW,cAAc;IAC7B,OAAO,EAAE,KAAK,CAAC;IACf,MAAM,EAAE,MAAM,EAAE,CAAC;CAClB;AAED,MAAM,MAAM,aAAa,GAAG,cAAc,GAAG,cAAc,CAAC;AAE5D,MAAM,WAAW,sBAAsB;IACrC,8DAA8D;IAC9D,MAAM,EAAE,YAAY,CAAC;IACrB,8DAA8D;IAC9D,OAAO,EAAE,CAAC,UAAU,EAAE,OAAO,KAAK,aAAa,CAAC;CACjD;AAmYD;;;;;;GAMG;AACH,wBAAgB,qBAAqB,CACnC,SAAS,EAAE,aAAa,GACvB,sBAAsB,CAiBxB;AAmCD;;;;;;;;;;;GAWG;AACH,wBAAgB,2BAA2B,CACzC,UAAU,EAAE,oBAAoB,GAC/B,sBAAsB,CA0FxB"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/gemini/index.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EACV,aAAa,EACb,oBAAoB,EAErB,MAAM,QAAQ,CAAC;AAOhB;;;;;;;;GAQG;AACH,MAAM,WAAW,YAAY;IAC3B,IAAI,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC;IACzB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,YAAY,CAAC,CAAC;IAC1C,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;IACpB,oBAAoB,CAAC,EAAE,OAAO,GAAG,YAAY,CAAC;IAC9C,IAAI,CAAC,EAAE,CAAC,MAAM,GAAG,MAAM,GAAG,IAAI,CAAC,EAAE,CAAC;IAClC,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,YAAY,CAAC;IACrB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED;;;;;;GAMG;AACH,MAAM,WAAW,kBAAkB;IACjC,OAAO,EAAE,IAAI,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,+DAA+D;IAC/D,IAAI,EAAE,OAAO,CAAC;CACf;AAED;;;;;GAKG;AACH,MAAM,WAAW,oBAAoB;IACnC,OAAO,EAAE,IAAI,CAAC;IACd,IAAI,EAAE,QAAQ,CAAC;IACf,yEAAyE;IACzE,QAAQ,EAAE,MAAM,CAAC;IACjB,8EAA8E;IAC9E,IAAI,EAAE,UAAU,CAAC;IACjB,8DAA8D;IAC9D,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED;;;;;;GAMG;AACH,MAAM,WAAW,cAAc;IAC7B,OAAO,EAAE,KAAK,CAAC;IACf,8EAA8E;IAC9E,MAAM,EAAE,MAAM,EAAE,CAAC;CAClB;AAED;;;;;GAKG;AACH,MAAM,MAAM,aAAa,GACrB,kBAAkB,GAClB,oBAAoB,GACpB,cAAc,CAAC;AA0TnB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAwCG;AACH,qBAAa,gBAAgB;IAC3B,wFAAwF;IACxF,QAAQ,CAAC,MAAM,EAAE,YAAY,CAAC;IAC9B;;;OAGG;IACH,QAAQ,CAAC,SAAS,CAAC,EAAE,aAAa,CAAC;IACnC;;;OAGG;IACH,QAAQ,CAAC,UAAU,CAAC,EAAE,oBAAoB,CAAC;IAI3C;;;;;;;;;;;OAWG;IACH,MAAM,CAAC,OAAO,CAAC,SAAS,EAAE,aAAa,GAAG,gBAAgB;IAK1D;;;;;;;;;;;;OAYG;IACH,MAAM,CAAC,UAAU,CAAC,UAAU,EAAE,oBAAoB,GAAG,gBAAgB;IAKrE;;;;;;;;;;;OAWG;IACH,MAAM,CAAC,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,gBAAgB;IAezE,OAAO;IAYP;;;;;;;;;;;;;;;;;OAiBG;IACH,OAAO,GAAI,MAAM,OAAO,KAAG,aAAa,CAQtC;IAIF;;;;;;;;OAQG;IACH,MAAM;;;;;;;;;CAMP;AA4KD;;;;;GAKG;AACH,wBAAgB,qBAAqB,CACnC,SAAS,EAAE,aAAa,GACvB,gBAAgB,CAElB;AAED;;;;;GAKG;AACH,wBAAgB,2BAA2B,CACzC,UAAU,EAAE,oBAAoB,GAC/B,gBAAgB,CAElB"}
@@ -1,5 +1,13 @@
1
1
  import type { JTDSchemaJson, SignalDescriptorJson } from '../api';
2
- /** JSON Schema subset supported by OpenAI structured output (strict mode). */
2
+ /**
3
+ * JSON Schema subset accepted by the OpenAI structured-output API (strict mode).
4
+ *
5
+ * This is the provider-specific representation produced by {@link OpenAIConversion}.
6
+ * It covers the keywords that OpenAI inspects when constraining model output in
7
+ * strict mode: `type`, `properties`, `required`, `additionalProperties`, `enum`,
8
+ * `format`, `items`, `minimum`/`maximum`, `anyOf`, `$defs`, `$ref`, and
9
+ * `description`.
10
+ */
3
11
  export interface OpenAISchema {
4
12
  type?: string | string[];
5
13
  description?: string;
@@ -15,41 +23,231 @@ export interface OpenAISchema {
15
23
  $defs?: Record<string, OpenAISchema>;
16
24
  $ref?: string;
17
25
  }
18
- export interface ConvertSuccess {
26
+ /**
27
+ * Successful conversion result for a JTD format.
28
+ *
29
+ * Returned when the raw LLM output has been coerced to match the JTD schema
30
+ * and passes JTD validation. `data` contains the deserialized, coerced, and
31
+ * JTD-validated JSON value.
32
+ */
33
+ export interface ConvertSuccessJson {
19
34
  success: true;
35
+ kind: 'json';
36
+ /** The deserialized, coerced, and JTD-validated JSON value. */
20
37
  data: unknown;
21
38
  }
39
+ /**
40
+ * Successful conversion result for a MIME (binary) format.
41
+ *
42
+ * Returned when the raw LLM output matches a MIME format. The base64 string
43
+ * produced by the model is decoded into raw binary bytes.
44
+ */
45
+ export interface ConvertSuccessBinary {
46
+ success: true;
47
+ kind: 'binary';
48
+ /** The concrete MIME type of the binary content (e.g. `"image/png"`). */
49
+ mimeType: string;
50
+ /** The raw binary data decoded from the base64 string returned by the LLM. */
51
+ data: Uint8Array;
52
+ /** Optional filename, provided by the caller if available. */
53
+ filename?: string;
54
+ }
55
+ /**
56
+ * Failed conversion result.
57
+ *
58
+ * `errors` contains one or more human-readable strings describing validation
59
+ * or coercion failures. Each entry uses a JSON Pointer path prefix
60
+ * (e.g. `"/foo/bar: ..."`) to locate the problem within the data.
61
+ */
22
62
  export interface ConvertFailure {
23
63
  success: false;
64
+ /** Array of human-readable error messages with JSON Pointer path prefixes. */
24
65
  errors: string[];
25
66
  }
26
- export type ConvertResult = ConvertSuccess | ConvertFailure;
27
- export interface OpenAIConversionResult {
28
- /** OpenAI strict mode compatible JSON Schema. */
29
- schema: OpenAISchema;
30
- /** Whether the schema supports strict mode. False for unstructured (empty) schemas. */
31
- strict: boolean;
32
- /** Convert OpenAI JSON output back to JTD-conforming JSON. */
33
- convert: (openaiJson: unknown) => ConvertResult;
34
- }
35
67
  /**
36
- * Convert a JTD schema to an OpenAI strict mode compatible JSON Schema, with a
37
- * converter function that transforms and validates OpenAI output against
38
- * the original JTD schema.
68
+ * Discriminated union of conversion outcomes.
39
69
  *
40
- * @throws {Error} if the JTD schema contains forms that cannot be represented.
70
+ * Check `success` first, then narrow on `kind` (`'json'` or `'binary'`)
71
+ * for successful results.
41
72
  */
42
- export declare function convertToOpenAISchema(jtdSchema: JTDSchemaJson): OpenAIConversionResult;
73
+ export type ConvertResult = ConvertSuccessJson | ConvertSuccessBinary | ConvertFailure;
43
74
  /**
44
- * Convert a SignalDescriptorJson to an OpenAI strict mode compatible JSON Schema.
75
+ * Converts JTD schemas or Adapt signal descriptors into OpenAI-compatible
76
+ * JSON Schema (strict mode), and converts raw LLM output back into
77
+ * validated data.
78
+ *
79
+ * ### JTD form mapping
80
+ * - **type** -- mapped to the corresponding JSON Schema `type` (`string`,
81
+ * `number`, `integer`, `boolean`). Integer sub-types (int8 .. uint32) add
82
+ * `minimum`/`maximum` bounds. `timestamp` becomes `string` with
83
+ * `format: "date-time"`.
84
+ * - **enum** -- mapped to `type: "string"` with an `enum` array.
85
+ * - **elements** -- mapped to `type: "array"` with `items`.
86
+ * - **properties / optionalProperties** -- mapped to `type: "object"` with
87
+ * `properties`, `required`, and `additionalProperties: false`. OpenAI
88
+ * strict mode requires all properties to be present, so **optional
89
+ * properties are made required and nullable** (their schemas are wrapped
90
+ * with a `"null"` type variant). During {@link convert}, null values for
91
+ * optional properties are stripped back out.
92
+ * - **values** -- mapped to an array of `{key, value}` objects because
93
+ * OpenAI strict mode does not support `additionalProperties`. During
94
+ * {@link convert}, the array is coerced back into a plain `Record`.
95
+ * - **discriminator** -- mapped to `anyOf` with one variant per mapping
96
+ * entry. Each variant is a flat object containing the discriminator key
97
+ * (with a single-value `enum`) plus the variant's own properties.
98
+ *
99
+ * ### Unstructured schemas
100
+ * Empty JTD schemas or schemas with only `additionalProperties: true` are
101
+ * considered unstructured. They produce an empty `{}` JSON Schema with
102
+ * `strict: false`, and during {@link convert} the raw string output is
103
+ * parsed via `JSON.parse` back into an arbitrary value.
104
+ *
105
+ * ### MIME formats
106
+ * MIME signal formats become `type: "string"` with a description requesting
107
+ * base64-encoded content. On {@link convert}, the base64 string is decoded
108
+ * into a {@link ConvertSuccessBinary} result.
109
+ *
110
+ * ### Serialization
111
+ * `JSON.stringify(conv)` produces a JSON-safe object via {@link toJSON}.
112
+ * Use {@link fromJSON} to restore a fully functional instance from the
113
+ * serialized form (string or parsed object).
114
+ *
115
+ * ```ts
116
+ * const conv = OpenAIConversion.fromJTD(jtdSchema);
117
+ * conv.schema; // OpenAI JSON Schema to pass to the LLM
118
+ * conv.strict; // whether strict mode applies
119
+ * conv.convert(output); // coerce + validate -> ConvertResult
45
120
  *
46
- * Handles single and multi-format signals:
47
- * - Single format: schema is the converted format directly.
48
- * - Multiple formats: wrapper object with `format_0`, `format_1`, etc.
49
- * All format properties are required and nullable (OAI strict mode).
50
- * The model sets exactly one to a value and the rest to null.
121
+ * // Serialize & restore
122
+ * const cached = JSON.stringify(conv);
123
+ * const restored = OpenAIConversion.fromJSON(cached);
124
+ * ```
125
+ */
126
+ export declare class OpenAIConversion {
127
+ /** The OpenAI-specific JSON Schema to pass to the OpenAI API as the response format. */
128
+ readonly schema: OpenAISchema;
129
+ /**
130
+ * Whether the schema qualifies for OpenAI strict structured-output mode.
131
+ *
132
+ * This is `false` when the root JTD schema is empty or unstructured (e.g.
133
+ * the empty schema `{}` or a properties form with no real properties and
134
+ * `additionalProperties: true`). In that case `schema` is `{}` and the
135
+ * model output is unconstrained.
136
+ */
137
+ readonly strict: boolean;
138
+ /**
139
+ * The original JTD schema used to build this conversion.
140
+ * Set when created via {@link fromJTD}; `undefined` when created via {@link fromSignal}.
141
+ */
142
+ readonly jtdSchema?: JTDSchemaJson;
143
+ /**
144
+ * The original signal descriptor used to build this conversion.
145
+ * Set when created via {@link fromSignal}; `undefined` when created via {@link fromJTD}.
146
+ */
147
+ readonly descriptor?: SignalDescriptorJson;
148
+ /**
149
+ * Build a conversion from a JTD schema.
150
+ *
151
+ * Recursively converts every JTD form into the equivalent OpenAI JSON Schema
152
+ * node. Definitions (`jtdSchema.definitions`) are emitted as `$defs` at the
153
+ * root level, and references become `$ref` pointers.
154
+ *
155
+ * If the root schema is unstructured, the result has an empty `schema` and
156
+ * `strict: false`.
157
+ *
158
+ * @param jtdSchema - A valid JTD schema (RFC 8927).
159
+ * @returns A new {@link OpenAIConversion} with `jtdSchema` set.
160
+ * @throws If the schema contains an unknown JTD type, an unresolved `ref`,
161
+ * or nesting exceeding 32 levels.
162
+ */
163
+ static fromJTD(jtdSchema: JTDSchemaJson): OpenAIConversion;
164
+ /**
165
+ * Build a conversion from an Adapt signal descriptor.
166
+ *
167
+ * If the descriptor has a single format, its schema is used directly
168
+ * (unwrapped). If it has multiple formats, a wrapper object schema is
169
+ * produced with `format_0`, `format_1`, ... properties -- each made
170
+ * required and nullable so the LLM populates exactly one and sets the
171
+ * rest to `null`.
172
+ *
173
+ * @param descriptor - An Adapt signal descriptor with one or more formats.
174
+ * @returns A new {@link OpenAIConversion} with `descriptor` set.
175
+ * @throws If the descriptor has no formats, or a format has neither
176
+ * `jtdSchema` nor `mimeType`.
177
+ */
178
+ static fromSignal(descriptor: SignalDescriptorJson): OpenAIConversion;
179
+ /**
180
+ * Restore an {@link OpenAIConversion} from its serialized form.
181
+ *
182
+ * Accepts either the JSON string produced by `JSON.stringify(conv)` or the
183
+ * already-parsed plain object. The original `jtdSchema` or `descriptor` is
184
+ * re-processed through the corresponding factory, so the restored instance
185
+ * is fully functional.
186
+ *
187
+ * @param data - A JSON string or parsed object previously produced by {@link toJSON}.
188
+ * @returns A fully reconstructed {@link OpenAIConversion}.
189
+ * @throws If the serialized data contains neither `jtdSchema` nor `descriptor`.
190
+ */
191
+ static fromJSON(data: string | Record<string, unknown>): OpenAIConversion;
192
+ private constructor();
193
+ /**
194
+ * Convert raw LLM output into a validated result.
195
+ *
196
+ * For JTD-based conversions, the value is coerced to conform to the original
197
+ * JTD schema:
198
+ * - Non-integer numbers are rounded for integer types.
199
+ * - Null values on optional properties are stripped (OpenAI required+nullable
200
+ * encoding is reversed).
201
+ * - `{key, value}` arrays from the values form are reassembled into Records.
202
+ * - Unstructured/empty schemas parse the raw JSON string via `JSON.parse`.
203
+ *
204
+ * The coerced value is then validated against the JTD schema. Returns
205
+ * {@link ConvertSuccessJson} on success.
206
+ *
207
+ * For MIME-based conversions, the value is expected to be a base64 string
208
+ * which is decoded into raw bytes. Returns {@link ConvertSuccessBinary}.
209
+ *
210
+ * For multi-format signals, the first non-null `format_N` property is
211
+ * selected and converted individually.
212
+ *
213
+ * @param json - The raw value returned by the OpenAI API (typically parsed JSON).
214
+ * @returns A {@link ConvertResult} indicating success or failure with errors.
215
+ */
216
+ convert: (json: unknown) => ConvertResult;
217
+ /**
218
+ * Produce a JSON-serializable representation of this conversion.
219
+ *
220
+ * The output includes the OpenAI `schema`, `strict` flag, and either the
221
+ * original `jtdSchema` or `descriptor` (whichever was used to create this
222
+ * instance), which is sufficient to fully restore the conversion via
223
+ * {@link fromJSON}.
224
+ *
225
+ * Called automatically by `JSON.stringify(conv)`.
226
+ */
227
+ toJSON(): {
228
+ schema: OpenAISchema;
229
+ strict: boolean;
230
+ descriptor: SignalDescriptorJson;
231
+ jtdSchema?: undefined;
232
+ } | {
233
+ schema: OpenAISchema;
234
+ strict: boolean;
235
+ jtdSchema: JTDSchemaJson | undefined;
236
+ descriptor?: undefined;
237
+ };
238
+ }
239
+ /**
240
+ * Convenience alias for {@link OpenAIConversion.fromJTD}.
241
+ *
242
+ * @param jtdSchema - A valid JTD schema (RFC 8927).
243
+ * @returns A new {@link OpenAIConversion}.
244
+ */
245
+ export declare function convertToOpenAISchema(jtdSchema: JTDSchemaJson): OpenAIConversion;
246
+ /**
247
+ * Convenience alias for {@link OpenAIConversion.fromSignal}.
51
248
  *
52
- * @throws {Error} if the descriptor has no formats.
249
+ * @param descriptor - An Adapt signal descriptor.
250
+ * @returns A new {@link OpenAIConversion}.
53
251
  */
54
- export declare function convertSignalToOpenAISchema(descriptor: SignalDescriptorJson): OpenAIConversionResult;
252
+ export declare function convertSignalToOpenAISchema(descriptor: SignalDescriptorJson): OpenAIConversion;
55
253
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/openai/index.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EACV,aAAa,EACb,oBAAoB,EAErB,MAAM,QAAQ,CAAC;AAOhB,8EAA8E;AAC9E,MAAM,WAAW,YAAY;IAC3B,IAAI,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC;IACzB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,YAAY,CAAC,CAAC;IAC1C,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;IACpB,oBAAoB,CAAC,EAAE,KAAK,CAAC;IAC7B,IAAI,CAAC,EAAE,CAAC,MAAM,GAAG,MAAM,GAAG,IAAI,CAAC,EAAE,CAAC;IAClC,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,YAAY,CAAC;IACrB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,KAAK,CAAC,EAAE,YAAY,EAAE,CAAC;IACvB,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,YAAY,CAAC,CAAC;IACrC,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,cAAc;IAC7B,OAAO,EAAE,IAAI,CAAC;IACd,IAAI,EAAE,OAAO,CAAC;CACf;AAED,MAAM,WAAW,cAAc;IAC7B,OAAO,EAAE,KAAK,CAAC;IACf,MAAM,EAAE,MAAM,EAAE,CAAC;CAClB;AAED,MAAM,MAAM,aAAa,GAAG,cAAc,GAAG,cAAc,CAAC;AAE5D,MAAM,WAAW,sBAAsB;IACrC,iDAAiD;IACjD,MAAM,EAAE,YAAY,CAAC;IACrB,uFAAuF;IACvF,MAAM,EAAE,OAAO,CAAC;IAChB,8DAA8D;IAC9D,OAAO,EAAE,CAAC,UAAU,EAAE,OAAO,KAAK,aAAa,CAAC;CACjD;AA8jBD;;;;;;GAMG;AACH,wBAAgB,qBAAqB,CACnC,SAAS,EAAE,aAAa,GACvB,sBAAsB,CAkCxB;AAqCD;;;;;;;;;;GAUG;AACH,wBAAgB,2BAA2B,CACzC,UAAU,EAAE,oBAAoB,GAC/B,sBAAsB,CAiGxB"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/openai/index.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EACV,aAAa,EACb,oBAAoB,EAErB,MAAM,QAAQ,CAAC;AAOhB;;;;;;;;GAQG;AACH,MAAM,WAAW,YAAY;IAC3B,IAAI,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC;IACzB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,YAAY,CAAC,CAAC;IAC1C,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;IACpB,oBAAoB,CAAC,EAAE,KAAK,CAAC;IAC7B,IAAI,CAAC,EAAE,CAAC,MAAM,GAAG,MAAM,GAAG,IAAI,CAAC,EAAE,CAAC;IAClC,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,YAAY,CAAC;IACrB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,KAAK,CAAC,EAAE,YAAY,EAAE,CAAC;IACvB,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,YAAY,CAAC,CAAC;IACrC,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED;;;;;;GAMG;AACH,MAAM,WAAW,kBAAkB;IACjC,OAAO,EAAE,IAAI,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,+DAA+D;IAC/D,IAAI,EAAE,OAAO,CAAC;CACf;AAED;;;;;GAKG;AACH,MAAM,WAAW,oBAAoB;IACnC,OAAO,EAAE,IAAI,CAAC;IACd,IAAI,EAAE,QAAQ,CAAC;IACf,yEAAyE;IACzE,QAAQ,EAAE,MAAM,CAAC;IACjB,8EAA8E;IAC9E,IAAI,EAAE,UAAU,CAAC;IACjB,8DAA8D;IAC9D,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED;;;;;;GAMG;AACH,MAAM,WAAW,cAAc;IAC7B,OAAO,EAAE,KAAK,CAAC;IACf,8EAA8E;IAC9E,MAAM,EAAE,MAAM,EAAE,CAAC;CAClB;AAED;;;;;GAKG;AACH,MAAM,MAAM,aAAa,GACrB,kBAAkB,GAClB,oBAAoB,GACpB,cAAc,CAAC;AA0jBnB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAmDG;AACH,qBAAa,gBAAgB;IAC3B,wFAAwF;IACxF,QAAQ,CAAC,MAAM,EAAE,YAAY,CAAC;IAC9B;;;;;;;OAOG;IACH,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAC;IACzB;;;OAGG;IACH,QAAQ,CAAC,SAAS,CAAC,EAAE,aAAa,CAAC;IACnC;;;OAGG;IACH,QAAQ,CAAC,UAAU,CAAC,EAAE,oBAAoB,CAAC;IAI3C;;;;;;;;;;;;;;OAcG;IACH,MAAM,CAAC,OAAO,CAAC,SAAS,EAAE,aAAa,GAAG,gBAAgB;IAyB1D;;;;;;;;;;;;;OAaG;IACH,MAAM,CAAC,UAAU,CAAC,UAAU,EAAE,oBAAoB,GAAG,gBAAgB;IAKrE;;;;;;;;;;;OAWG;IACH,MAAM,CAAC,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,gBAAgB;IAezE,OAAO;IAcP;;;;;;;;;;;;;;;;;;;;;;OAsBG;IACH,OAAO,GAAI,MAAM,OAAO,KAAG,aAAa,CAQtC;IAIF;;;;;;;;;OASG;IACH,MAAM;;;;;;;;;;;CAcP;AAqMD;;;;;GAKG;AACH,wBAAgB,qBAAqB,CACnC,SAAS,EAAE,aAAa,GACvB,gBAAgB,CAElB;AAED;;;;;GAKG;AACH,wBAAgB,2BAA2B,CACzC,UAAU,EAAE,oBAAoB,GAC/B,gBAAgB,CAElB"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mochabug/adapt-sdk",
3
- "version": "0.4.0",
3
+ "version": "0.4.2",
4
4
  "description": "The API toolkit to facilitate mochabug adapt plugin development",
5
5
  "publishConfig": {
6
6
  "access": "public"