@patdown/jev 0.4.0 → 0.5.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/dist/index.d.ts CHANGED
@@ -1,3 +1,4 @@
1
1
  export { JevNoulAnswerSchema, JevNoulQuestionSchema, JevNoulResultSchema, JevUsageSchema, type JevNoulAnswer, type JevNoulResult, } from '#src/jev-noul-schema';
2
- export { JevRequestFailed, JevSystemOne, JevSystemOneLive } from '#src/jev-system-one';
2
+ export { JevChoiceAnswerSchema, JevChoiceQuestionSchema, JevChoiceResultSchema, type JevChoiceAnswer, type JevChoiceResult, } from '#src/jev-choice-schema';
3
+ export { JevRequestFailed, JevSystemOne, JevSystemOneLive, type JevChoiceCriteria, } from '#src/jev-system-one';
3
4
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACN,mBAAmB,EACnB,qBAAqB,EACrB,mBAAmB,EACnB,cAAc,EACd,KAAK,aAAa,EAClB,KAAK,aAAa,GAClB,MAAM,sBAAsB,CAAA;AAE7B,OAAO,EAAE,gBAAgB,EAAE,YAAY,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACN,mBAAmB,EACnB,qBAAqB,EACrB,mBAAmB,EACnB,cAAc,EACd,KAAK,aAAa,EAClB,KAAK,aAAa,GAClB,MAAM,sBAAsB,CAAA;AAE7B,OAAO,EACN,qBAAqB,EACrB,uBAAuB,EACvB,qBAAqB,EACrB,KAAK,eAAe,EACpB,KAAK,eAAe,GACpB,MAAM,wBAAwB,CAAA;AAE/B,OAAO,EACN,gBAAgB,EAChB,YAAY,EACZ,gBAAgB,EAChB,KAAK,iBAAiB,GACtB,MAAM,qBAAqB,CAAA"}
package/dist/index.js CHANGED
@@ -1,2 +1,3 @@
1
1
  export { JevNoulAnswerSchema, JevNoulQuestionSchema, JevNoulResultSchema, JevUsageSchema, } from '#src/jev-noul-schema';
2
- export { JevRequestFailed, JevSystemOne, JevSystemOneLive } from '#src/jev-system-one';
2
+ export { JevChoiceAnswerSchema, JevChoiceQuestionSchema, JevChoiceResultSchema, } from '#src/jev-choice-schema';
3
+ export { JevRequestFailed, JevSystemOne, JevSystemOneLive, } from '#src/jev-system-one';
@@ -0,0 +1,31 @@
1
+ import { Schema } from 'effect';
2
+ /** Choice question body for POST /v1/systemone. Labels map to descriptions. */
3
+ export declare const JevChoiceQuestionSchema: Schema.Struct<{
4
+ readonly criteria: Schema.$Record<Schema.String, Schema.NullOr<Schema.String>>;
5
+ readonly instructions: Schema.optionalKey<Schema.String>;
6
+ readonly type: Schema.Literal<"choice">;
7
+ }>;
8
+ /** Choice answer from POST /v1/systemone. */
9
+ export declare const JevChoiceAnswerSchema: Schema.Struct<{
10
+ readonly choice: Schema.String;
11
+ readonly confidence: Schema.Finite;
12
+ readonly probabilities: Schema.$Record<Schema.String, Schema.Finite>;
13
+ readonly type: Schema.Literal<"choice">;
14
+ }>;
15
+ /** System One response when every question is choice. */
16
+ export declare const JevChoiceResultSchema: Schema.Struct<{
17
+ readonly answers: Schema.$Record<Schema.String, Schema.Struct<{
18
+ readonly choice: Schema.String;
19
+ readonly confidence: Schema.Finite;
20
+ readonly probabilities: Schema.$Record<Schema.String, Schema.Finite>;
21
+ readonly type: Schema.Literal<"choice">;
22
+ }>>;
23
+ readonly model: Schema.String;
24
+ readonly usage: Schema.Struct<{
25
+ readonly input_tokens: Schema.Finite;
26
+ readonly output_tokens: Schema.Finite;
27
+ }>;
28
+ }>;
29
+ export type JevChoiceAnswer = typeof JevChoiceAnswerSchema.Type;
30
+ export type JevChoiceResult = typeof JevChoiceResultSchema.Type;
31
+ //# sourceMappingURL=jev-choice-schema.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"jev-choice-schema.d.ts","sourceRoot":"","sources":["../src/jev-choice-schema.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAA;AAE/B,+EAA+E;AAC/E,eAAO,MAAM,uBAAuB;;;;EAIlC,CAAA;AAEF,6CAA6C;AAC7C,eAAO,MAAM,qBAAqB;;;;;EAKhC,CAAA;AAEF,yDAAyD;AACzD,eAAO,MAAM,qBAAqB;;;;;;;;;;;;EAOhC,CAAA;AAEF,MAAM,MAAM,eAAe,GAAG,OAAO,qBAAqB,CAAC,IAAI,CAAA;AAE/D,MAAM,MAAM,eAAe,GAAG,OAAO,qBAAqB,CAAC,IAAI,CAAA"}
@@ -0,0 +1,23 @@
1
+ import { Schema } from 'effect';
2
+ /** Choice question body for POST /v1/systemone. Labels map to descriptions. */
3
+ export const JevChoiceQuestionSchema = Schema.Struct({
4
+ criteria: Schema.Record(Schema.String, Schema.NullOr(Schema.String)),
5
+ instructions: Schema.optionalKey(Schema.String),
6
+ type: Schema.Literal('choice'),
7
+ });
8
+ /** Choice answer from POST /v1/systemone. */
9
+ export const JevChoiceAnswerSchema = Schema.Struct({
10
+ choice: Schema.String,
11
+ confidence: Schema.Finite,
12
+ probabilities: Schema.Record(Schema.String, Schema.Finite),
13
+ type: Schema.Literal('choice'),
14
+ });
15
+ /** System One response when every question is choice. */
16
+ export const JevChoiceResultSchema = Schema.Struct({
17
+ answers: Schema.Record(Schema.String, JevChoiceAnswerSchema),
18
+ model: Schema.String,
19
+ usage: Schema.Struct({
20
+ input_tokens: Schema.Finite,
21
+ output_tokens: Schema.Finite,
22
+ }),
23
+ });
@@ -1,5 +1,6 @@
1
1
  import { Context, Effect, Layer } from 'effect';
2
2
  import { HttpClient } from 'effect/unstable/http';
3
+ import { type JevChoiceAnswer } from '#src/jev-choice-schema';
3
4
  import { type JevNoulAnswer } from '#src/jev-noul-schema';
4
5
  declare const JevRequestFailed_base: new <A extends Record<string, any> = {}>(args: import("effect/Types").VoidIfEmpty<{ readonly [P in keyof A as P extends "_tag" ? never : P]: A[P]; }>) => import("effect/Cause").YieldableError & {
5
6
  readonly _tag: "JevRequestFailed";
@@ -12,8 +13,11 @@ export declare class JevRequestFailed extends JevRequestFailed_base<{
12
13
  readonly requestId?: string | undefined;
13
14
  }> {
14
15
  }
16
+ /** Labels for a Choice question. Values are short descriptions shown to the model. */
17
+ export type JevChoiceCriteria = Readonly<Record<string, string | null>>;
15
18
  declare const JevSystemOne_base: Context.ServiceClass<JevSystemOne, "@patdown/jev/JevSystemOne", {
16
19
  readonly askNoul: (instructions: string, state: string) => Effect.Effect<JevNoulAnswer, JevRequestFailed, HttpClient.HttpClient>;
20
+ readonly askChoice: (instructions: string, state: string, criteria: JevChoiceCriteria) => Effect.Effect<JevChoiceAnswer, JevRequestFailed, HttpClient.HttpClient>;
17
21
  }>;
18
22
  /**
19
23
  * Client for TypeSafe System One (Jev). Implemented with Effect HttpClient so a Decision-based
@@ -1 +1 @@
1
- {"version":3,"file":"jev-system-one.d.ts","sourceRoot":"","sources":["../src/jev-system-one.ts"],"names":[],"mappings":"AAAA,OAAO,EAAU,OAAO,EAAQ,MAAM,EAAE,KAAK,EAAoB,MAAM,QAAQ,CAAA;AAE/E,OAAO,EAAE,UAAU,EAAyC,MAAM,sBAAsB,CAAA;AAExF,OAAO,EAAuB,KAAK,aAAa,EAAE,MAAM,sBAAsB,CAAA;;;;AAQ9E,kGAAkG;AAClG,qBAAa,gBAAiB,SAAQ,sBAAqC;IAC1E,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAA;IACxB,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAA;IACxB,QAAQ,CAAC,iBAAiB,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;IAC/C,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;CACvC,CAAC;CAAG;;sBASe,CACjB,YAAY,EAAE,MAAM,EACpB,KAAK,EAAE,MAAM,KACT,MAAM,CAAC,MAAM,CAAC,aAAa,EAAE,gBAAgB,EAAE,UAAU,CAAC,UAAU,CAAC;;AAV5E;;;GAGG;AACH,qBAAa,YAAa,SAAQ,iBAQF;CAAG;AAqKnC,qEAAqE;AACrE,eAAO,MAAM,gBAAgB,yCAE3B,CAAA"}
1
+ {"version":3,"file":"jev-system-one.d.ts","sourceRoot":"","sources":["../src/jev-system-one.ts"],"names":[],"mappings":"AAAA,OAAO,EAAU,OAAO,EAAQ,MAAM,EAAE,KAAK,EAAoB,MAAM,QAAQ,CAAA;AAE/E,OAAO,EAAE,UAAU,EAAyC,MAAM,sBAAsB,CAAA;AAExF,OAAO,EAAyB,KAAK,eAAe,EAAE,MAAM,wBAAwB,CAAA;AACpF,OAAO,EAAuB,KAAK,aAAa,EAAE,MAAM,sBAAsB,CAAA;;;;AAU9E,kGAAkG;AAClG,qBAAa,gBAAiB,SAAQ,sBAAqC;IAC1E,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAA;IACxB,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAA;IACxB,QAAQ,CAAC,iBAAiB,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;IAC/C,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;CACvC,CAAC;CAAG;AAEL,sFAAsF;AACtF,MAAM,MAAM,iBAAiB,GAAG,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC,CAAC,CAAA;;sBASnD,CACjB,YAAY,EAAE,MAAM,EACpB,KAAK,EAAE,MAAM,KACT,MAAM,CAAC,MAAM,CAAC,aAAa,EAAE,gBAAgB,EAAE,UAAU,CAAC,UAAU,CAAC;wBACtD,CACnB,YAAY,EAAE,MAAM,EACpB,KAAK,EAAE,MAAM,EACb,QAAQ,EAAE,iBAAiB,KACvB,MAAM,CAAC,MAAM,CAAC,eAAe,EAAE,gBAAgB,EAAE,UAAU,CAAC,UAAU,CAAC;;AAf9E;;;GAGG;AACH,qBAAa,YAAa,SAAQ,iBAaF;CAAG;AA8QnC,qEAAqE;AACrE,eAAO,MAAM,gBAAgB,yCAG3B,CAAA"}
@@ -1,9 +1,11 @@
1
1
  import { Config, Context, Data, Effect, Layer, Redacted, Schema } from 'effect';
2
2
  import { HttpClient, HttpClientRequest, HttpClientResponse } from 'effect/unstable/http';
3
+ import { JevChoiceResultSchema } from '#src/jev-choice-schema';
3
4
  import { JevNoulResultSchema } from '#src/jev-noul-schema';
4
5
  const defaultJevBaseUrl = 'https://api.typesafe.ai';
5
6
  const defaultJevModel = 'jev-latest';
6
7
  const defaultNoulQuestionName = 'noul';
8
+ const defaultChoiceQuestionName = 'choice';
7
9
  /** Jev / System One HTTP or config failure. Swap this service later for Effect's Decision API. */
8
10
  export class JevRequestFailed extends Data.TaggedError('JevRequestFailed') {
9
11
  }
@@ -33,6 +35,15 @@ function noulAnswerFromResult(result, questionName) {
33
35
  }
34
36
  return Effect.succeed(answer);
35
37
  }
38
+ function choiceAnswerFromResult(result, questionName) {
39
+ const answer = result.answers[questionName];
40
+ if (answer === undefined) {
41
+ return Effect.fail(new JevRequestFailed({
42
+ message: `jev: response missing choice answer ${questionName}`,
43
+ }));
44
+ }
45
+ return Effect.succeed(answer);
46
+ }
36
47
  function encodeJevNoulBody(prepared, model, instructions, state) {
37
48
  return HttpClientRequest.bodyJson(prepared, {
38
49
  model,
@@ -51,6 +62,27 @@ function encodeJevNoulBody(prepared, model, instructions, state) {
51
62
  message: 'jev: failed to encode System One request body',
52
63
  })));
53
64
  }
65
+ function encodeJevChoiceBody(prepared, options) {
66
+ const labels = Object.keys(options.criteria);
67
+ if (labels.length < 2) {
68
+ return Effect.fail(new JevRequestFailed({
69
+ message: 'jev: choice criteria need at least two labels',
70
+ }));
71
+ }
72
+ return HttpClientRequest.bodyJson(prepared, {
73
+ model: options.model,
74
+ questions: {
75
+ [defaultChoiceQuestionName]: {
76
+ criteria: options.criteria,
77
+ instructions: options.instructions,
78
+ type: 'choice',
79
+ },
80
+ },
81
+ state: options.state,
82
+ }).pipe(Effect.mapError(() => new JevRequestFailed({
83
+ message: 'jev: failed to encode System One choice request body',
84
+ })));
85
+ }
54
86
  const JevErrorBodySchema = Schema.Struct({
55
87
  detail: Schema.Struct({ error_type: Schema.String }),
56
88
  });
@@ -88,21 +120,29 @@ function jevHttpFailure(response, state) {
88
120
  });
89
121
  });
90
122
  }
91
- function askJevNoul(instructions, state) {
123
+ function prepareJevSystemOneRequest(baseUrl, apiKey) {
124
+ return HttpClientRequest.post(`${baseUrl}/v1/systemone`).pipe(HttpClientRequest.bearerToken(apiKey), HttpClientRequest.acceptJson);
125
+ }
126
+ function executeJevSystemOneRequest(request, state) {
92
127
  return Effect.gen(function* () {
93
- const apiKey = yield* readJevApiKey();
94
- const baseUrl = yield* Effect.orDie(readJevBaseUrl());
95
- const model = yield* Effect.orDie(readJevModel());
96
128
  const client = yield* HttpClient.HttpClient;
97
- const prepared = HttpClientRequest.post(`${baseUrl}/v1/systemone`).pipe(HttpClientRequest.bearerToken(apiKey), HttpClientRequest.acceptJson);
98
- const request = yield* encodeJevNoulBody(prepared, model, instructions, state);
99
129
  const response = yield* client.execute(request).pipe(Effect.mapError((error) => new JevRequestFailed({
100
130
  message: `jev: System One transport/request failure (${error.reason._tag}); no usable HTTP response`,
101
131
  })));
102
132
  if (response.status < 200 || response.status >= 300) {
103
- const error = yield* jevHttpFailure(response, state);
104
- return yield* error;
133
+ return yield* Effect.fail(yield* jevHttpFailure(response, state));
105
134
  }
135
+ return response;
136
+ });
137
+ }
138
+ function askJevNoul(instructions, state) {
139
+ return Effect.gen(function* () {
140
+ const apiKey = yield* readJevApiKey();
141
+ const baseUrl = yield* Effect.orDie(readJevBaseUrl());
142
+ const model = yield* Effect.orDie(readJevModel());
143
+ const prepared = prepareJevSystemOneRequest(baseUrl, apiKey);
144
+ const request = yield* encodeJevNoulBody(prepared, model, instructions, state);
145
+ const response = yield* executeJevSystemOneRequest(request, state);
106
146
  const result = yield* HttpClientResponse.schemaBodyJson(JevNoulResultSchema)(response).pipe(Effect.mapError(() => new JevRequestFailed({
107
147
  message: `jev: System One HTTP ${String(response.status)} response could not be decoded as the expected noul result`,
108
148
  status: response.status,
@@ -111,7 +151,29 @@ function askJevNoul(instructions, state) {
111
151
  return yield* noulAnswerFromResult(result, defaultNoulQuestionName);
112
152
  });
113
153
  }
154
+ function askJevChoice(instructions, state, criteria) {
155
+ return Effect.gen(function* () {
156
+ const apiKey = yield* readJevApiKey();
157
+ const baseUrl = yield* Effect.orDie(readJevBaseUrl());
158
+ const model = yield* Effect.orDie(readJevModel());
159
+ const prepared = prepareJevSystemOneRequest(baseUrl, apiKey);
160
+ const request = yield* encodeJevChoiceBody(prepared, {
161
+ model,
162
+ instructions,
163
+ state,
164
+ criteria,
165
+ });
166
+ const response = yield* executeJevSystemOneRequest(request, state);
167
+ const result = yield* HttpClientResponse.schemaBodyJson(JevChoiceResultSchema)(response).pipe(Effect.mapError(() => new JevRequestFailed({
168
+ message: `jev: System One HTTP ${String(response.status)} response could not be decoded as the expected choice result`,
169
+ status: response.status,
170
+ requestId: safeJevErrorIdentifier(response.headers['x-typesafe-request-id']),
171
+ })));
172
+ return yield* choiceAnswerFromResult(result, defaultChoiceQuestionName);
173
+ });
174
+ }
114
175
  /** Live Jev client using Effect HttpClient and TYPESAFE_* config. */
115
176
  export const JevSystemOneLive = Layer.succeed(JevSystemOne, {
116
177
  askNoul: askJevNoul,
178
+ askChoice: askJevChoice,
117
179
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@patdown/jev",
3
- "version": "0.4.0",
3
+ "version": "0.5.0",
4
4
  "description": "Effect HttpClient for TypeSafe System One (Jev)",
5
5
  "homepage": "https://github.com/tyler-dot-earth/patdown",
6
6
  "bugs": {