ocpipe 0.2.1 → 0.3.1

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/src/predict.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  /**
2
- * DSTS SDK Predict class.
2
+ * ocpipe Predict class.
3
3
  *
4
4
  * Executes a signature by generating a prompt, calling OpenCode, and parsing the response.
5
5
  */
@@ -47,8 +47,13 @@ export interface PredictConfig {
47
47
  correction?: CorrectionConfig | false
48
48
  }
49
49
 
50
+ type AnySignature = SignatureDef<
51
+ Record<string, FieldConfig>,
52
+ Record<string, FieldConfig>
53
+ >
54
+
50
55
  /** Predict executes a signature by calling an LLM and parsing the response. */
51
- export class Predict<S extends SignatureDef<any, any>> {
56
+ export class Predict<S extends AnySignature> {
52
57
  constructor(
53
58
  public readonly sig: S,
54
59
  public readonly config: PredictConfig = {},
@@ -90,7 +95,11 @@ export class Predict<S extends SignatureDef<any, any>> {
90
95
  }
91
96
 
92
97
  // Parsing failed - attempt correction if enabled
93
- if (this.config.correction !== false && parseResult.errors && parseResult.json) {
98
+ if (
99
+ this.config.correction !== false &&
100
+ parseResult.errors &&
101
+ parseResult.json
102
+ ) {
94
103
  const corrected = await this.correctFields(
95
104
  parseResult.json,
96
105
  parseResult.errors,
@@ -111,9 +120,19 @@ export class Predict<S extends SignatureDef<any, any>> {
111
120
 
112
121
  // Correction failed or disabled - throw SchemaValidationError (non-retryable)
113
122
  const errors = parseResult.errors ?? []
114
- const errorMessages = errors.map((e) => `${e.path}: ${e.message}`).join('; ') || 'Unknown error'
115
- const correctionAttempts = this.config.correction !== false ? (typeof this.config.correction === 'object' ? this.config.correction.maxRounds ?? 3 : 3) : 0
116
- throw new SchemaValidationError(`Schema validation failed: ${errorMessages}`, errors, correctionAttempts)
123
+ const errorMessages =
124
+ errors.map((e) => `${e.path}: ${e.message}`).join('; ') || 'Unknown error'
125
+ const correctionAttempts =
126
+ this.config.correction !== false ?
127
+ typeof this.config.correction === 'object' ?
128
+ (this.config.correction.maxRounds ?? 3)
129
+ : 3
130
+ : 0
131
+ throw new SchemaValidationError(
132
+ `Schema validation failed: ${errorMessages}`,
133
+ errors,
134
+ correctionAttempts,
135
+ )
117
136
  }
118
137
 
119
138
  /** correctFields attempts to fix field errors using same-session patches with retries. */
@@ -123,32 +142,39 @@ export class Predict<S extends SignatureDef<any, any>> {
123
142
  ctx: ExecutionContext,
124
143
  sessionId: string,
125
144
  ): Promise<InferOutputs<S> | null> {
126
- const correctionConfig = typeof this.config.correction === 'object' ? this.config.correction : {}
145
+ const correctionConfig =
146
+ typeof this.config.correction === 'object' ? this.config.correction : {}
127
147
  const method: CorrectionMethod = correctionConfig.method ?? 'json-patch'
128
148
  const maxFields = correctionConfig.maxFields ?? 5
129
149
  const maxRounds = correctionConfig.maxRounds ?? 3
130
150
  const correctionModel = correctionConfig.model
131
151
 
132
- let currentJson = JSON.parse(JSON.stringify(json)) as Record<string, unknown>
152
+ let currentJson = JSON.parse(JSON.stringify(json)) as Record<
153
+ string,
154
+ unknown
155
+ >
133
156
  let currentErrors = initialErrors
134
157
 
135
158
  for (let round = 1; round <= maxRounds; round++) {
136
159
  const errorsToFix = currentErrors.slice(0, maxFields)
137
-
160
+
138
161
  if (errorsToFix.length === 0) {
139
162
  break
140
163
  }
141
164
 
142
- console.error(`\n>>> Correction round ${round}/${maxRounds} [${method}]: fixing ${errorsToFix.length} field(s)...`)
165
+ console.error(
166
+ `\n>>> Correction round ${round}/${maxRounds} [${method}]: fixing ${errorsToFix.length} field(s)...`,
167
+ )
143
168
 
144
169
  // Build prompt based on correction method
145
- const patchPrompt = method === 'jq'
146
- ? (errorsToFix.length === 1
147
- ? buildPatchPrompt(errorsToFix[0]!, currentJson, this.sig.outputs)
148
- : buildBatchPatchPrompt(errorsToFix, currentJson))
149
- : (errorsToFix.length === 1
150
- ? buildJsonPatchPrompt(errorsToFix[0]!, currentJson, this.sig.outputs)
151
- : buildBatchJsonPatchPrompt(errorsToFix, currentJson))
170
+ const patchPrompt =
171
+ method === 'jq' ?
172
+ errorsToFix.length === 1 ?
173
+ buildPatchPrompt(errorsToFix[0]!, currentJson, this.sig.outputs)
174
+ : buildBatchPatchPrompt(errorsToFix, currentJson)
175
+ : errorsToFix.length === 1 ?
176
+ buildJsonPatchPrompt(errorsToFix[0]!, currentJson, this.sig.outputs)
177
+ : buildBatchJsonPatchPrompt(errorsToFix, currentJson)
152
178
 
153
179
  // Use same session (model has context) unless correction model specified
154
180
  const patchResult = await runAgent({
@@ -183,14 +209,16 @@ export class Predict<S extends SignatureDef<any, any>> {
183
209
 
184
210
  // Update errors for next round
185
211
  currentErrors = revalidated.errors ?? []
186
-
212
+
187
213
  if (currentErrors.length === 0) {
188
214
  // No errors but also no data? Shouldn't happen, but handle gracefully
189
215
  console.error(` Unexpected state: no errors but validation failed`)
190
216
  break
191
217
  }
192
218
 
193
- console.error(` Round ${round} complete, ${currentErrors.length} error(s) remaining`)
219
+ console.error(
220
+ ` Round ${round} complete, ${currentErrors.length} error(s) remaining`,
221
+ )
194
222
  }
195
223
 
196
224
  console.error(` Schema correction failed after ${maxRounds} rounds`)
@@ -216,7 +244,7 @@ export class Predict<S extends SignatureDef<any, any>> {
216
244
 
217
245
  // Input fields as JSON
218
246
  const inputsWithDescriptions: Record<string, unknown> = {}
219
- for (const [name, config] of Object.entries(this.sig.inputs) as [
247
+ for (const [name] of Object.entries(this.sig.inputs) as [
220
248
  string,
221
249
  FieldConfig,
222
250
  ][]) {
@@ -231,7 +259,9 @@ export class Predict<S extends SignatureDef<any, any>> {
231
259
  // Output format with JSON Schema
232
260
  lines.push('OUTPUT FORMAT:')
233
261
  lines.push('Return a JSON object matching this schema EXACTLY.')
234
- lines.push('IMPORTANT: For optional fields, OMIT the field entirely - do NOT use null.')
262
+ lines.push(
263
+ 'IMPORTANT: For optional fields, OMIT the field entirely - do NOT use null.',
264
+ )
235
265
  lines.push('')
236
266
  lines.push('```json')
237
267
  lines.push(JSON.stringify(this.buildOutputJsonSchema(), null, 2))
@@ -244,7 +274,10 @@ export class Predict<S extends SignatureDef<any, any>> {
244
274
  private buildOutputJsonSchema(): Record<string, unknown> {
245
275
  // Build a Zod object from the output fields
246
276
  const shape: Record<string, z.ZodType> = {}
247
- for (const [name, config] of Object.entries(this.sig.outputs) as [string, FieldConfig][]) {
277
+ for (const [name, config] of Object.entries(this.sig.outputs) as [
278
+ string,
279
+ FieldConfig,
280
+ ][]) {
248
281
  shape[name] = config.type
249
282
  }
250
283
  const outputSchema = z.object(shape)
@@ -254,9 +287,14 @@ export class Predict<S extends SignatureDef<any, any>> {
254
287
 
255
288
  // Add field descriptions from our config (toJSONSchema uses .describe() metadata)
256
289
  // Since our FieldConfig has a separate desc field, merge it in
257
- const props = jsonSchema.properties as Record<string, Record<string, unknown>> | undefined
290
+ const props = jsonSchema.properties as
291
+ | Record<string, Record<string, unknown>>
292
+ | undefined
258
293
  if (props) {
259
- for (const [name, config] of Object.entries(this.sig.outputs) as [string, FieldConfig][]) {
294
+ for (const [name, config] of Object.entries(this.sig.outputs) as [
295
+ string,
296
+ FieldConfig,
297
+ ][]) {
260
298
  if (config.desc && props[name]) {
261
299
  // Only add if not already set by .describe()
262
300
  if (!props[name].description) {
package/src/signature.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  /**
2
- * DSTS SDK signature definition.
2
+ * ocpipe signature definition.
3
3
  *
4
4
  * Signatures declare input/output contracts for LLM interactions using Zod for validation.
5
5
  */
package/src/state.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  /**
2
- * DSTS SDK state management.
2
+ * ocpipe state management.
3
3
  *
4
4
  * Provides base state types and helpers for checkpointable workflow state.
5
5
  */
package/src/testing.ts CHANGED
@@ -1,7 +1,7 @@
1
1
  /**
2
- * DSTS SDK testing utilities.
2
+ * ocpipe testing utilities.
3
3
  *
4
- * Provides mock backends and test helpers for unit testing DSTS components.
4
+ * Provides mock backends and test helpers for unit testing ocpipe components.
5
5
  */
6
6
 
7
7
  import type { RunAgentOptions, RunAgentResult, FieldConfig } from './types.js'
@@ -34,7 +34,10 @@ export class MockAgentBackend {
34
34
  }
35
35
 
36
36
  /** addJsonResponse adds a mock JSON response. */
37
- addJsonResponse(data: Record<string, unknown>, options?: Partial<MockResponse>): this {
37
+ addJsonResponse(
38
+ data: Record<string, unknown>,
39
+ options?: Partial<MockResponse>,
40
+ ): this {
38
41
  return this.addResponse({
39
42
  response: JSON.stringify(data, null, 2),
40
43
  ...options,
@@ -76,7 +79,7 @@ export class MockAgentBackend {
76
79
  for (let i = 0; i < this.responses.length; i++) {
77
80
  const r = this.responses[i]
78
81
  if (!r) continue
79
-
82
+
80
83
  if (!r.match) {
81
84
  response = r
82
85
  responseIndex = i
@@ -116,7 +119,8 @@ export class MockAgentBackend {
116
119
 
117
120
  return {
118
121
  text: response.response ?? '',
119
- sessionId: response.sessionId ?? options.sessionId ?? this.defaultSessionId,
122
+ sessionId:
123
+ response.sessionId ?? options.sessionId ?? this.defaultSessionId,
120
124
  }
121
125
  }
122
126
 
@@ -127,12 +131,14 @@ export class MockAgentBackend {
127
131
  }
128
132
 
129
133
  /** createMockContext creates a test execution context. */
130
- export function createMockContext(overrides?: Partial<{
131
- sessionId: string
132
- defaultModel: { providerID: string; modelID: string }
133
- defaultAgent: string
134
- timeoutSec: number
135
- }>) {
134
+ export function createMockContext(
135
+ overrides?: Partial<{
136
+ sessionId: string
137
+ defaultModel: { providerID: string; modelID: string }
138
+ defaultAgent: string
139
+ timeoutSec: number
140
+ }>,
141
+ ) {
136
142
  return {
137
143
  sessionId: overrides?.sessionId,
138
144
  defaultModel: overrides?.defaultModel ?? {
@@ -145,12 +151,14 @@ export function createMockContext(overrides?: Partial<{
145
151
  }
146
152
 
147
153
  /** generateMockOutputs creates mock output data based on a schema. */
148
- export function generateMockOutputs(schema: Record<string, FieldConfig>): Record<string, unknown> {
154
+ export function generateMockOutputs(
155
+ schema: Record<string, FieldConfig>,
156
+ ): Record<string, unknown> {
149
157
  const result: Record<string, unknown> = {}
150
158
  for (const [name, config] of Object.entries(schema)) {
151
159
  // Use constructor name for type detection (works across zod versions)
152
160
  const typeName = config.type.constructor.name
153
-
161
+
154
162
  switch (typeName) {
155
163
  case 'ZodString':
156
164
  result[name] = `mock_${name}`
@@ -167,11 +175,12 @@ export function generateMockOutputs(schema: Record<string, FieldConfig>): Record
167
175
  case 'ZodObject':
168
176
  result[name] = {}
169
177
  break
170
- case 'ZodEnum':
178
+ case 'ZodEnum': {
171
179
  // Get first enum value via options property
172
180
  const enumType = config.type as { options?: readonly string[] }
173
181
  result[name] = enumType.options?.[0] ?? 'unknown'
174
182
  break
183
+ }
175
184
  default:
176
185
  result[name] = null
177
186
  }
package/src/types.ts CHANGED
@@ -1,7 +1,5 @@
1
1
  /**
2
- * DSTS SDK shared types.
3
- *
4
- * Core type definitions for the Declarative Self-Improving TypeScript SDK.
2
+ * ocpipe shared types.
5
3
  */
6
4
 
7
5
  import type { z } from 'zod/v4'
@@ -131,16 +129,26 @@ export interface SignatureDef<
131
129
  }
132
130
 
133
131
  /** Infer the input type from a signature definition. */
134
- export type InferInputs<S extends SignatureDef<any, any>> =
135
- S extends SignatureDef<infer I, any>
136
- ? { [K in keyof I]: z.infer<I[K]['type']> }
137
- : never
132
+ export type InferInputs<
133
+ S extends SignatureDef<
134
+ Record<string, FieldConfig>,
135
+ Record<string, FieldConfig>
136
+ >,
137
+ > =
138
+ S extends SignatureDef<infer I, Record<string, FieldConfig>> ?
139
+ { [K in keyof I]: z.infer<I[K]['type']> }
140
+ : never
138
141
 
139
142
  /** Infer the output type from a signature definition. */
140
- export type InferOutputs<S extends SignatureDef<any, any>> =
141
- S extends SignatureDef<any, infer O>
142
- ? { [K in keyof O]: z.infer<O[K]['type']> }
143
- : never
143
+ export type InferOutputs<
144
+ S extends SignatureDef<
145
+ Record<string, FieldConfig>,
146
+ Record<string, FieldConfig>
147
+ >,
148
+ > =
149
+ S extends SignatureDef<Record<string, FieldConfig>, infer O> ?
150
+ { [K in keyof O]: z.infer<O[K]['type']> }
151
+ : never
144
152
 
145
153
  // ============================================================================
146
154
  // Retry Configuration