nexus-ai-pro 2.20.2 → 2.22.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/API_STABILITY.md +93 -0
- package/CHANGELOG.md +208 -1
- package/README.md +11 -6
- package/SECURITY.md +16 -2
- package/dist/adapter-kit/gather.d.ts +76 -0
- package/dist/adapter-kit/gather.js +147 -0
- package/dist/adapter-kit/index.d.ts +1 -0
- package/dist/adapter-kit/index.js +1 -0
- package/dist/adapter-kit/record.d.ts +3 -1
- package/dist/adapter-kit/record.js +20 -5
- package/dist/agent/openapi.d.ts +94 -8
- package/dist/agent/openapi.js +528 -32
- package/dist/cli/adapters.d.ts +4 -3
- package/dist/cli/adapters.js +71 -2
- package/dist/cli/doctor.js +3 -0
- package/dist/cli.js +3 -1
- package/dist/core/config-builder.d.ts +1 -0
- package/dist/core/config-builder.js +1 -0
- package/dist/core/defaults.d.ts +34 -0
- package/dist/core/defaults.js +39 -0
- package/dist/core/secure-stream.js +4 -1
- package/dist/decisions/completion.d.ts +10 -7
- package/dist/decisions/completion.js +82 -8
- package/dist/decisions/core.d.ts +88 -43
- package/dist/decisions/core.js +115 -28
- package/dist/decisions/errors.d.ts +25 -0
- package/dist/decisions/errors.js +12 -0
- package/dist/decisions/index.d.ts +6 -5
- package/dist/decisions/index.js +2 -1
- package/dist/decisions/integrations.d.ts +14 -5
- package/dist/decisions/integrations.js +16 -1
- package/dist/decisions/mock.d.ts +5 -3
- package/dist/decisions/mock.js +4 -1
- package/dist/decisions/pictures.d.ts +43 -0
- package/dist/decisions/pictures.js +103 -0
- package/dist/decisions/typesafe.d.ts +33 -5
- package/dist/decisions/typesafe.js +121 -8
- package/dist/doctor/index.d.ts +6 -9
- package/dist/doctor/index.js +41 -0
- package/dist/embeddings/adapters.d.ts +1 -1
- package/dist/embeddings/adapters.js +3 -3
- package/dist/embeddings/batch-google.d.ts +27 -8
- package/dist/embeddings/batch-google.js +112 -36
- package/dist/embeddings/batch-mock.js +1 -1
- package/dist/embeddings/batch.js +10 -4
- package/dist/embeddings/engine.js +14 -13
- package/dist/embeddings/index.d.ts +1 -1
- package/dist/embeddings/inputs.d.ts +26 -3
- package/dist/embeddings/inputs.js +84 -5
- package/dist/embeddings/mock.js +1 -1
- package/dist/embeddings/models.js +39 -4
- package/dist/loaders/csv.d.ts +23 -1
- package/dist/loaders/csv.js +125 -72
- package/dist/loaders/index.d.ts +7 -2
- package/dist/loaders/input.d.ts +6 -0
- package/dist/loaders/input.js +42 -1
- package/dist/loaders/json.d.ts +14 -3
- package/dist/loaders/json.js +171 -20
- package/dist/loaders/web.d.ts +55 -0
- package/dist/loaders/web.js +20 -1
- package/dist/mcp/client.d.ts +54 -5
- package/dist/mcp/client.js +171 -20
- package/dist/mcp/http.d.ts +45 -0
- package/dist/mcp/http.js +233 -0
- package/dist/mcp/index.d.ts +4 -2
- package/dist/mcp/index.js +3 -1
- package/dist/mcp/protocol.d.ts +107 -0
- package/dist/mcp/sampling.d.ts +41 -0
- package/dist/mcp/sampling.js +52 -0
- package/dist/mcp/server.d.ts +96 -14
- package/dist/mcp/server.js +274 -59
- package/dist/models/data.js +20 -1
- package/dist/operations/adapters.d.ts +1 -0
- package/dist/operations/adapters.js +3 -1
- package/dist/protocols/a2a-grpc.js +10 -3
- package/dist/protocols/a2a-signing.d.ts +65 -0
- package/dist/protocols/a2a-signing.js +133 -0
- package/dist/protocols/a2a.d.ts +14 -0
- package/dist/protocols/a2a.js +60 -5
- package/dist/providers/cohere.js +16 -2
- package/dist/providers/google.js +7 -1
- package/dist/providers/ollama.d.ts +1 -1
- package/dist/providers/ollama.js +35 -27
- package/dist/providers/openai.js +19 -2
- package/dist/rag/pinecone.d.ts +63 -2
- package/dist/rag/pinecone.js +80 -0
- package/dist/realtime/conversation.js +18 -0
- package/dist/realtime/gemini-live.transport.d.ts +28 -3
- package/dist/realtime/gemini-live.transport.js +170 -32
- package/dist/realtime/session.d.ts +2 -0
- package/dist/realtime/session.js +19 -4
- package/dist/realtime/types.d.ts +35 -3
- package/dist/security/output-guard.js +4 -1
- package/dist/server/auth.d.ts +263 -2
- package/dist/server/auth.js +432 -5
- package/dist/server/deployments.d.ts +3 -2
- package/dist/server/deployments.js +6 -1
- package/dist/telephony/index.d.ts +1 -1
- package/dist/telephony/manager.d.ts +8 -1
- package/dist/telephony/manager.js +13 -0
- package/dist/telephony/providers/telnyx.d.ts +18 -5
- package/dist/telephony/providers/telnyx.js +44 -7
- package/dist/telephony/providers/twilio.d.ts +3 -1
- package/dist/telephony/providers/twilio.js +16 -0
- package/dist/tracing/stores.d.ts +2 -0
- package/dist/tracing/stores.js +1 -0
- package/dist/tracing/tracer.d.ts +5 -2
- package/dist/tracing/tracer.js +6 -3
- package/dist/types/embeddings.d.ts +47 -5
- package/dist/types/messages.d.ts +7 -0
- package/dist/types/principal.d.ts +1 -1
- package/dist/types/response.d.ts +5 -0
- package/dist/types/telephony.d.ts +38 -0
- package/dist/types/tracing.d.ts +6 -0
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/dist/voice/providers/google.d.ts +44 -0
- package/dist/voice/providers/google.js +215 -0
- package/dist-cjs/adapter-kit/gather.d.ts +76 -0
- package/dist-cjs/adapter-kit/gather.js +152 -0
- package/dist-cjs/adapter-kit/index.d.ts +1 -0
- package/dist-cjs/adapter-kit/index.js +4 -1
- package/dist-cjs/adapter-kit/record.d.ts +3 -1
- package/dist-cjs/adapter-kit/record.js +20 -5
- package/dist-cjs/agent/openapi.d.ts +94 -8
- package/dist-cjs/agent/openapi.js +530 -32
- package/dist-cjs/cli/adapters.d.ts +4 -3
- package/dist-cjs/cli/adapters.js +70 -1
- package/dist-cjs/cli/doctor.js +3 -0
- package/dist-cjs/core/config-builder.d.ts +1 -0
- package/dist-cjs/core/config-builder.js +5 -1
- package/dist-cjs/core/defaults.d.ts +34 -0
- package/dist-cjs/core/defaults.js +44 -0
- package/dist-cjs/core/secure-stream.js +4 -1
- package/dist-cjs/decisions/completion.d.ts +10 -7
- package/dist-cjs/decisions/completion.js +81 -7
- package/dist-cjs/decisions/core.d.ts +88 -43
- package/dist-cjs/decisions/core.js +134 -46
- package/dist-cjs/decisions/errors.d.ts +25 -0
- package/dist-cjs/decisions/errors.js +16 -0
- package/dist-cjs/decisions/index.d.ts +6 -5
- package/dist-cjs/decisions/index.js +5 -1
- package/dist-cjs/decisions/integrations.d.ts +14 -5
- package/dist-cjs/decisions/integrations.js +16 -1
- package/dist-cjs/decisions/mock.d.ts +5 -3
- package/dist-cjs/decisions/mock.js +4 -1
- package/dist-cjs/decisions/pictures.d.ts +43 -0
- package/dist-cjs/decisions/pictures.js +109 -0
- package/dist-cjs/decisions/typesafe.d.ts +33 -5
- package/dist-cjs/decisions/typesafe.js +126 -13
- package/dist-cjs/doctor/index.d.ts +6 -9
- package/dist-cjs/doctor/index.js +41 -0
- package/dist-cjs/embeddings/adapters.d.ts +1 -1
- package/dist-cjs/embeddings/adapters.js +3 -3
- package/dist-cjs/embeddings/batch-google.d.ts +27 -8
- package/dist-cjs/embeddings/batch-google.js +112 -36
- package/dist-cjs/embeddings/batch-mock.js +1 -1
- package/dist-cjs/embeddings/batch.js +9 -3
- package/dist-cjs/embeddings/engine.js +13 -12
- package/dist-cjs/embeddings/index.d.ts +1 -1
- package/dist-cjs/embeddings/inputs.d.ts +26 -3
- package/dist-cjs/embeddings/inputs.js +89 -5
- package/dist-cjs/embeddings/mock.js +1 -1
- package/dist-cjs/embeddings/models.js +39 -4
- package/dist-cjs/loaders/csv.d.ts +23 -1
- package/dist-cjs/loaders/csv.js +126 -71
- package/dist-cjs/loaders/index.d.ts +7 -2
- package/dist-cjs/loaders/input.d.ts +6 -0
- package/dist-cjs/loaders/input.js +43 -1
- package/dist-cjs/loaders/json.d.ts +14 -3
- package/dist-cjs/loaders/json.js +170 -19
- package/dist-cjs/loaders/web.d.ts +55 -0
- package/dist-cjs/loaders/web.js +21 -1
- package/dist-cjs/mcp/client.d.ts +54 -5
- package/dist-cjs/mcp/client.js +171 -20
- package/dist-cjs/mcp/http.d.ts +45 -0
- package/dist-cjs/mcp/http.js +236 -0
- package/dist-cjs/mcp/index.d.ts +4 -2
- package/dist-cjs/mcp/index.js +5 -1
- package/dist-cjs/mcp/protocol.d.ts +107 -0
- package/dist-cjs/mcp/sampling.d.ts +41 -0
- package/dist-cjs/mcp/sampling.js +55 -0
- package/dist-cjs/mcp/server.d.ts +96 -14
- package/dist-cjs/mcp/server.js +273 -58
- package/dist-cjs/models/data.js +20 -1
- package/dist-cjs/operations/adapters.d.ts +1 -0
- package/dist-cjs/operations/adapters.js +3 -1
- package/dist-cjs/protocols/a2a-grpc.js +10 -3
- package/dist-cjs/protocols/a2a-signing.d.ts +65 -0
- package/dist-cjs/protocols/a2a-signing.js +140 -0
- package/dist-cjs/protocols/a2a.d.ts +14 -0
- package/dist-cjs/protocols/a2a.js +65 -6
- package/dist-cjs/providers/cohere.js +16 -2
- package/dist-cjs/providers/google.js +7 -1
- package/dist-cjs/providers/ollama.d.ts +1 -1
- package/dist-cjs/providers/ollama.js +35 -27
- package/dist-cjs/providers/openai.js +19 -2
- package/dist-cjs/rag/pinecone.d.ts +63 -2
- package/dist-cjs/rag/pinecone.js +81 -0
- package/dist-cjs/realtime/conversation.js +18 -0
- package/dist-cjs/realtime/gemini-live.transport.d.ts +28 -3
- package/dist-cjs/realtime/gemini-live.transport.js +170 -32
- package/dist-cjs/realtime/session.d.ts +2 -0
- package/dist-cjs/realtime/session.js +19 -4
- package/dist-cjs/realtime/types.d.ts +35 -3
- package/dist-cjs/security/output-guard.js +4 -1
- package/dist-cjs/server/auth.d.ts +263 -2
- package/dist-cjs/server/auth.js +437 -5
- package/dist-cjs/server/deployments.d.ts +3 -2
- package/dist-cjs/server/deployments.js +6 -1
- package/dist-cjs/telephony/index.d.ts +1 -1
- package/dist-cjs/telephony/manager.d.ts +8 -1
- package/dist-cjs/telephony/manager.js +13 -0
- package/dist-cjs/telephony/providers/telnyx.d.ts +18 -5
- package/dist-cjs/telephony/providers/telnyx.js +44 -7
- package/dist-cjs/telephony/providers/twilio.d.ts +3 -1
- package/dist-cjs/telephony/providers/twilio.js +16 -0
- package/dist-cjs/tracing/stores.d.ts +2 -0
- package/dist-cjs/tracing/stores.js +1 -0
- package/dist-cjs/tracing/tracer.d.ts +5 -2
- package/dist-cjs/tracing/tracer.js +6 -3
- package/dist-cjs/types/embeddings.d.ts +47 -5
- package/dist-cjs/types/messages.d.ts +7 -0
- package/dist-cjs/types/principal.d.ts +1 -1
- package/dist-cjs/types/response.d.ts +5 -0
- package/dist-cjs/types/telephony.d.ts +38 -0
- package/dist-cjs/types/tracing.d.ts +6 -0
- package/dist-cjs/version.d.ts +1 -1
- package/dist-cjs/version.js +1 -1
- package/dist-cjs/voice/providers/google.d.ts +44 -0
- package/dist-cjs/voice/providers/google.js +252 -0
- package/llms.txt +1 -1
- package/package.json +17 -1
package/dist/decisions/core.d.ts
CHANGED
|
@@ -1,13 +1,18 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Typed decisions: questions a model answers with a yes or no, a choice,
|
|
3
|
-
*
|
|
2
|
+
* Typed decisions: questions a model answers with a yes or no, a choice, a score, or a box around
|
|
3
|
+
* something in a picture, each with a confidence read alike from any provider, so software acts on an
|
|
4
|
+
* answer without parsing text.
|
|
4
5
|
*/
|
|
5
6
|
import type { CacheAdapter } from '../cache/adapters.js';
|
|
7
|
+
import type { ImageContent } from '../types/messages.js';
|
|
6
8
|
import type { OperationLifecycleLike, ProviderCallContext } from '../types/lifecycle.js';
|
|
7
9
|
import type { ResponseCost } from '../types/response.js';
|
|
8
10
|
import type { RunKind } from '../types/tracing.js';
|
|
9
|
-
/**
|
|
10
|
-
|
|
11
|
+
/**
|
|
12
|
+
* The kinds of question there are: a yes or no, a choice among options, a score on levels, or a box
|
|
13
|
+
* around something in a picture.
|
|
14
|
+
*/
|
|
15
|
+
export type DecisionQuestionType = 'yes-no' | 'choice' | 'score' | 'box';
|
|
11
16
|
/** A question answered yes or no, with the probability that it is yes. */
|
|
12
17
|
export interface YesNoQuestion {
|
|
13
18
|
/** Discriminates the question. */
|
|
@@ -38,12 +43,40 @@ export interface ScoreQuestion {
|
|
|
38
43
|
/** What each level means, lowest first. Two to ten. */
|
|
39
44
|
levels: readonly string[];
|
|
40
45
|
}
|
|
46
|
+
/** A question answered with where something is in a picture of the state: a box around it. */
|
|
47
|
+
export interface BoxQuestion {
|
|
48
|
+
/** Discriminates the question. */
|
|
49
|
+
type: 'box';
|
|
50
|
+
/**
|
|
51
|
+
* What to find, and in which picture, by its path in backticks, such as "the dent in `photo`". A box
|
|
52
|
+
* is given even for something the picture does not show: ask a yes or no beside it whether it does.
|
|
53
|
+
*/
|
|
54
|
+
question: string;
|
|
55
|
+
}
|
|
41
56
|
/** Any question. */
|
|
42
|
-
export type DecisionQuestion = YesNoQuestion | ChoiceQuestion | ScoreQuestion;
|
|
57
|
+
export type DecisionQuestion = YesNoQuestion | ChoiceQuestion | ScoreQuestion | BoxQuestion;
|
|
43
58
|
/** Questions by the names their answers come back under. */
|
|
44
59
|
export type DecisionQuestions = Record<string, DecisionQuestion>;
|
|
45
|
-
/**
|
|
60
|
+
/**
|
|
61
|
+
* What every question of a decision is about: text, or any JSON value. An object or a list may hold
|
|
62
|
+
* pictures, as image parts (`{ type: 'image', source }`) or image assets, anywhere in it; a question
|
|
63
|
+
* names each by its path in backticks, such as `photo` or `frames[2].frame`.
|
|
64
|
+
*/
|
|
46
65
|
export type DecisionState = string | Record<string, unknown> | readonly unknown[];
|
|
66
|
+
/**
|
|
67
|
+
* Where something is in a picture: each edge a fraction, from 0 to 1, of the picture's height (`top`,
|
|
68
|
+
* `bottom`) or width (`left`, `right`), measured from its top-left corner.
|
|
69
|
+
*/
|
|
70
|
+
export interface DecisionBox {
|
|
71
|
+
/** The top edge, from the picture's top. */
|
|
72
|
+
top: number;
|
|
73
|
+
/** The bottom edge, from the picture's top: at least `top`. */
|
|
74
|
+
bottom: number;
|
|
75
|
+
/** The left edge, from the picture's left. */
|
|
76
|
+
left: number;
|
|
77
|
+
/** The right edge, from the picture's left: at least `left`. */
|
|
78
|
+
right: number;
|
|
79
|
+
}
|
|
47
80
|
/** A yes-or-no question's answer. */
|
|
48
81
|
export interface YesNoAnswer {
|
|
49
82
|
/** Discriminates the answer. */
|
|
@@ -86,15 +119,27 @@ export interface ScoreAnswer {
|
|
|
86
119
|
*/
|
|
87
120
|
confidence: number;
|
|
88
121
|
}
|
|
122
|
+
/** A box question's answer. */
|
|
123
|
+
export interface BoxAnswer {
|
|
124
|
+
/** Discriminates the answer. */
|
|
125
|
+
type: 'box';
|
|
126
|
+
/** Where it is. */
|
|
127
|
+
box: DecisionBox;
|
|
128
|
+
/**
|
|
129
|
+
* How sure the answer is, from 0 to 1: the provider's own, such as TypeSafe AI's Jev gives, or how
|
|
130
|
+
* far several readings of the box agree, for a model asked more than once.
|
|
131
|
+
*/
|
|
132
|
+
confidence: number;
|
|
133
|
+
}
|
|
89
134
|
/** Any answer. */
|
|
90
|
-
export type DecisionAnswer = YesNoAnswer | ChoiceAnswer | ScoreAnswer;
|
|
135
|
+
export type DecisionAnswer = YesNoAnswer | ChoiceAnswer | ScoreAnswer | BoxAnswer;
|
|
91
136
|
/** The options of a choice question, as a union of their names. */
|
|
92
137
|
type OptionsOf<O> = O extends readonly (infer K)[] ? K : keyof O;
|
|
93
138
|
/** The answer a question gets: a choice's answer names only its options. */
|
|
94
139
|
export type AnswerOf<Q> = Q extends YesNoQuestion ? YesNoAnswer : Q extends {
|
|
95
140
|
type: 'choice';
|
|
96
141
|
options: infer O;
|
|
97
|
-
} ? ChoiceAnswer<Extract<OptionsOf<O>, string>> : Q extends ScoreQuestion ? ScoreAnswer : DecisionAnswer;
|
|
142
|
+
} ? ChoiceAnswer<Extract<OptionsOf<O>, string>> : Q extends ScoreQuestion ? ScoreAnswer : Q extends BoxQuestion ? BoxAnswer : DecisionAnswer;
|
|
98
143
|
/** Answers by their questions' names, each typed by its question. */
|
|
99
144
|
export type DecisionAnswers<Q extends DecisionQuestions> = {
|
|
100
145
|
[K in keyof Q]: AnswerOf<Q[K]>;
|
|
@@ -152,12 +197,12 @@ export type DecisionProviderQuestion = YesNoQuestion | {
|
|
|
152
197
|
name: string;
|
|
153
198
|
description?: string;
|
|
154
199
|
}>;
|
|
155
|
-
} | ScoreQuestion;
|
|
200
|
+
} | ScoreQuestion | BoxQuestion;
|
|
156
201
|
/** What a provider is asked. */
|
|
157
202
|
export interface DecisionProviderRequest {
|
|
158
203
|
/** The model to ask. */
|
|
159
204
|
model: string;
|
|
160
|
-
/** What every question is about. */
|
|
205
|
+
/** What every question is about, with any pictures it holds, which `statePictures()` lists. */
|
|
161
206
|
state: DecisionState;
|
|
162
207
|
/** The questions, by name. */
|
|
163
208
|
questions: Record<string, DecisionProviderQuestion>;
|
|
@@ -172,6 +217,10 @@ export type DecisionDistribution = {
|
|
|
172
217
|
} | {
|
|
173
218
|
type: 'score';
|
|
174
219
|
probabilities: readonly number[];
|
|
220
|
+
} | {
|
|
221
|
+
type: 'box';
|
|
222
|
+
box: DecisionBox;
|
|
223
|
+
confidence: number;
|
|
175
224
|
};
|
|
176
225
|
/** What a provider answers. */
|
|
177
226
|
export interface DecisionProviderResult {
|
|
@@ -194,6 +243,8 @@ export interface DecisionProviderCapabilities {
|
|
|
194
243
|
maxLevels: number;
|
|
195
244
|
/** Most questions one decision may ask, when it has a limit. */
|
|
196
245
|
maxQuestions?: number;
|
|
246
|
+
/** Whether it reads the pictures a state holds. A provider without it is not asked about a picture. */
|
|
247
|
+
images?: boolean;
|
|
197
248
|
/** The model asked when a request names none. */
|
|
198
249
|
defaultModel: string;
|
|
199
250
|
/** The models it serves, when it lists them. */
|
|
@@ -232,30 +283,7 @@ export interface DecisionProvider {
|
|
|
232
283
|
/** Answers every question of a decision. */
|
|
233
284
|
decide(request: DecisionProviderRequest, context: DecisionCallContext): Promise<DecisionProviderResult>;
|
|
234
285
|
}
|
|
235
|
-
|
|
236
|
-
export type DecisionErrorCode = 'DECISION_NO_PROVIDER' | 'DECISION_UNSUPPORTED' | 'DECISION_INVALID' | 'DECISION_FAILED';
|
|
237
|
-
/** Raised for a decision no provider can serve, a question that is malformed, or a provider's failure. */
|
|
238
|
-
export declare class DecisionError extends Error {
|
|
239
|
-
/**
|
|
240
|
-
* A stable code: `DECISION_NO_PROVIDER`, `DECISION_UNSUPPORTED` (a provider cannot take the
|
|
241
|
-
* question), `DECISION_INVALID` (the request, or an answer, is malformed), or `DECISION_FAILED`.
|
|
242
|
-
*/
|
|
243
|
-
readonly code: DecisionErrorCode;
|
|
244
|
-
/** Whether asking again, or another provider, may help: a timeout or an overloaded service may. */
|
|
245
|
-
readonly retryable: boolean;
|
|
246
|
-
/** The HTTP status a provider answered with, when it did. */
|
|
247
|
-
readonly status?: number | undefined;
|
|
248
|
-
constructor(message: string,
|
|
249
|
-
/**
|
|
250
|
-
* A stable code: `DECISION_NO_PROVIDER`, `DECISION_UNSUPPORTED` (a provider cannot take the
|
|
251
|
-
* question), `DECISION_INVALID` (the request, or an answer, is malformed), or `DECISION_FAILED`.
|
|
252
|
-
*/
|
|
253
|
-
code: DecisionErrorCode,
|
|
254
|
-
/** Whether asking again, or another provider, may help: a timeout or an overloaded service may. */
|
|
255
|
-
retryable?: boolean,
|
|
256
|
-
/** The HTTP status a provider answered with, when it did. */
|
|
257
|
-
status?: number | undefined);
|
|
258
|
-
}
|
|
286
|
+
export { DecisionError, type DecisionErrorCode } from './errors.js';
|
|
259
287
|
/** A yes-or-no answer's confidence: how far its probability is from an even chance, `|2p - 1|`. */
|
|
260
288
|
export declare function yesNoConfidence(probability: number): number;
|
|
261
289
|
/**
|
|
@@ -275,6 +303,11 @@ export declare function scoreConfidence(probabilities: readonly number[]): numbe
|
|
|
275
303
|
* `DECISION_INVALID` for probabilities that do not fit the question.
|
|
276
304
|
*/
|
|
277
305
|
export declare function decisionAnswer(question: DecisionProviderQuestion, distribution: DecisionDistribution): DecisionAnswer;
|
|
306
|
+
/**
|
|
307
|
+
* How far two boxes overlap, from 0 to 1: the area they share over the area they cover together, the
|
|
308
|
+
* intersection over union by which a box is judged against where the thing is.
|
|
309
|
+
*/
|
|
310
|
+
export declare function boxOverlap(a: DecisionBox, b: DecisionBox): number;
|
|
278
311
|
/** What to do with an answer: act on it, have a person review it, or neither. */
|
|
279
312
|
export type GateOutcome = 'act' | 'review' | 'abstain';
|
|
280
313
|
/** The confidences a gate acts at, and has reviewed at. */
|
|
@@ -345,6 +378,7 @@ export interface CalibrationReport {
|
|
|
345
378
|
/**
|
|
346
379
|
* The probability an answer gives its own answer: a yes or no's `max(p, 1 - p)`, a choice's for its
|
|
347
380
|
* option, and a score's for its level. Its confidence measures how far that is above an even spread.
|
|
381
|
+
* A box has no probabilities, so its confidence stands for one.
|
|
348
382
|
*/
|
|
349
383
|
export declare function answerProbability(answer: DecisionAnswer): number;
|
|
350
384
|
/**
|
|
@@ -355,11 +389,13 @@ export declare function answerProbability(answer: DecisionAnswer): number;
|
|
|
355
389
|
*/
|
|
356
390
|
export declare function calibrate(samples: readonly CalibrationSample[], options?: CalibrateOptions): CalibrationReport;
|
|
357
391
|
/**
|
|
358
|
-
* Whether an answer is right: a yes-or-no or a choice by its answer,
|
|
359
|
-
* level, or by its weighted score within `tolerance` levels when one is given
|
|
392
|
+
* Whether an answer is right: a yes-or-no or a choice by its answer, a score by its most probable
|
|
393
|
+
* level, or by its weighted score within `tolerance` levels when one is given, and a box by how far it
|
|
394
|
+
* overlaps the expected one, `boxOverlap()`, at least `overlap` (one half by default).
|
|
360
395
|
*/
|
|
361
|
-
export declare function answeredRight(answer: DecisionAnswer, expected: boolean | string | number, options?: {
|
|
396
|
+
export declare function answeredRight(answer: DecisionAnswer, expected: boolean | string | number | DecisionBox, options?: {
|
|
362
397
|
tolerance?: number;
|
|
398
|
+
overlap?: number;
|
|
363
399
|
}): boolean;
|
|
364
400
|
/** A decision model's price, in US dollars per million tokens. */
|
|
365
401
|
export interface DecisionPrice {
|
|
@@ -493,8 +529,11 @@ export interface DecisionConformanceCase {
|
|
|
493
529
|
state: DecisionState;
|
|
494
530
|
/** The question. */
|
|
495
531
|
question: DecisionQuestion;
|
|
496
|
-
/**
|
|
497
|
-
|
|
532
|
+
/**
|
|
533
|
+
* The right answer: a yes or no, a choice's option, a score's level, or where a box should be, which
|
|
534
|
+
* an answer overlapping it by half or more matches.
|
|
535
|
+
*/
|
|
536
|
+
expected: boolean | string | number | DecisionBox;
|
|
498
537
|
}
|
|
499
538
|
/** Options for `runDecisionConformance()`. */
|
|
500
539
|
export interface DecisionConformanceOptions {
|
|
@@ -505,6 +544,11 @@ export interface DecisionConformanceOptions {
|
|
|
505
544
|
* as it is told passes without them; a real model is held to them.
|
|
506
545
|
*/
|
|
507
546
|
cases?: readonly DecisionConformanceCase[];
|
|
547
|
+
/**
|
|
548
|
+
* A picture for the checks of a provider that reads pictures or answers boxes: it is asked a yes or
|
|
549
|
+
* no about the picture, and a box around what it shows. Without one, those checks are skipped.
|
|
550
|
+
*/
|
|
551
|
+
picture?: ImageContent;
|
|
508
552
|
}
|
|
509
553
|
/** How a provider did against the decision contract. */
|
|
510
554
|
export interface DecisionConformanceReport {
|
|
@@ -514,12 +558,13 @@ export interface DecisionConformanceReport {
|
|
|
514
558
|
passed: string[];
|
|
515
559
|
/** Checks that failed, each with why. */
|
|
516
560
|
failures: string[];
|
|
561
|
+
/** Checks that were not run, each with why, such as a box with no picture given to ask about. */
|
|
562
|
+
skipped: string[];
|
|
517
563
|
}
|
|
518
564
|
/**
|
|
519
565
|
* Checks a provider against the decision contract: its capabilities are coherent; each question type
|
|
520
|
-
* it declares comes back as probabilities that fit the question;
|
|
521
|
-
*
|
|
522
|
-
* throws; failures are listed.
|
|
566
|
+
* it declares comes back as probabilities, or a box, that fit the question; a provider that reads
|
|
567
|
+
* pictures answers about one; several questions in one decision each get their own answer; a stopped
|
|
568
|
+
* call is not answered; and every case is answered right. Never throws; failures are listed.
|
|
523
569
|
*/
|
|
524
570
|
export declare function runDecisionConformance(provider: DecisionProvider, options?: DecisionConformanceOptions): Promise<DecisionConformanceReport>;
|
|
525
|
-
export {};
|
package/dist/decisions/core.js
CHANGED
|
@@ -2,18 +2,9 @@ import { createCacheKey } from '../cache/memory-cache.js';
|
|
|
2
2
|
import { withLifecycle } from '../lifecycle/run.js';
|
|
3
3
|
import { generateRequestId } from '../utils/ids.js';
|
|
4
4
|
import { sha256Hex } from '../utils/sha256.js';
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
status;
|
|
9
|
-
constructor(message, code, retryable = false, status) {
|
|
10
|
-
super(message);
|
|
11
|
-
this.code = code;
|
|
12
|
-
this.retryable = retryable;
|
|
13
|
-
this.status = status;
|
|
14
|
-
this.name = 'DecisionError';
|
|
15
|
-
}
|
|
16
|
-
}
|
|
5
|
+
import { DecisionError } from './errors.js';
|
|
6
|
+
import { pictureDigest, replacePictures, statePictures } from './pictures.js';
|
|
7
|
+
export { DecisionError } from './errors.js';
|
|
17
8
|
export function yesNoConfidence(probability) {
|
|
18
9
|
return clamp(Math.abs(2 * probability - 1));
|
|
19
10
|
}
|
|
@@ -73,8 +64,36 @@ export function decisionAnswer(question, distribution) {
|
|
|
73
64
|
confidence: scoreConfidence(weights),
|
|
74
65
|
};
|
|
75
66
|
}
|
|
67
|
+
if (question.type === 'box' && distribution.type === 'box') {
|
|
68
|
+
const edge = (name) => {
|
|
69
|
+
const value = distribution.box?.[name];
|
|
70
|
+
if (typeof value !== 'number' || !Number.isFinite(value) || value < 0 || value > 1) {
|
|
71
|
+
throw new DecisionError(`The box's ${name} edge is ${String(value)}, not a number from 0 to 1`, 'DECISION_INVALID');
|
|
72
|
+
}
|
|
73
|
+
return value;
|
|
74
|
+
};
|
|
75
|
+
const box = { top: edge('top'), bottom: edge('bottom'), left: edge('left'), right: edge('right') };
|
|
76
|
+
if (box.top > box.bottom || box.left > box.right) {
|
|
77
|
+
throw new DecisionError(`The box's edges cross: top ${box.top} and bottom ${box.bottom}, left ${box.left} and right ${box.right}`, 'DECISION_INVALID');
|
|
78
|
+
}
|
|
79
|
+
const confidence = distribution.confidence;
|
|
80
|
+
if (typeof confidence !== 'number' || !Number.isFinite(confidence) || confidence < 0 || confidence > 1) {
|
|
81
|
+
throw new DecisionError(`The box's confidence is ${String(confidence)}, not a number from 0 to 1`, 'DECISION_INVALID');
|
|
82
|
+
}
|
|
83
|
+
return { type: 'box', box, confidence };
|
|
84
|
+
}
|
|
76
85
|
throw new DecisionError(`Unknown question type "${question.type}"`, 'DECISION_INVALID');
|
|
77
86
|
}
|
|
87
|
+
export function boxOverlap(a, b) {
|
|
88
|
+
const width = Math.max(0, Math.min(a.right, b.right) - Math.max(a.left, b.left));
|
|
89
|
+
const height = Math.max(0, Math.min(a.bottom, b.bottom) - Math.max(a.top, b.top));
|
|
90
|
+
const shared = width * height;
|
|
91
|
+
const area = (box) => Math.max(0, box.right - box.left) * Math.max(0, box.bottom - box.top);
|
|
92
|
+
const union = area(a) + area(b) - shared;
|
|
93
|
+
if (union <= 0)
|
|
94
|
+
return a.top === b.top && a.left === b.left && a.bottom === b.bottom && a.right === b.right ? 1 : 0;
|
|
95
|
+
return shared / union;
|
|
96
|
+
}
|
|
78
97
|
export function gate(answer, thresholds) {
|
|
79
98
|
if (answer.confidence >= thresholds.act)
|
|
80
99
|
return 'act';
|
|
@@ -85,6 +104,8 @@ export function answerProbability(answer) {
|
|
|
85
104
|
return Math.max(answer.probability, 1 - answer.probability);
|
|
86
105
|
if (answer.type === 'choice')
|
|
87
106
|
return answer.probabilities[answer.choice] ?? 0;
|
|
107
|
+
if (answer.type === 'box')
|
|
108
|
+
return answer.confidence;
|
|
88
109
|
return answer.probabilities[answer.level] ?? 0;
|
|
89
110
|
}
|
|
90
111
|
export function calibrate(samples, options = {}) {
|
|
@@ -144,6 +165,11 @@ export function answeredRight(answer, expected, options = {}) {
|
|
|
144
165
|
return answer.yes === expected;
|
|
145
166
|
if (answer.type === 'choice')
|
|
146
167
|
return answer.choice === expected;
|
|
168
|
+
if (answer.type === 'box') {
|
|
169
|
+
if (expected === null || typeof expected !== 'object')
|
|
170
|
+
return false;
|
|
171
|
+
return boxOverlap(answer.box, expected) >= (options.overlap ?? 0.5);
|
|
172
|
+
}
|
|
147
173
|
if (typeof expected !== 'number')
|
|
148
174
|
return false;
|
|
149
175
|
return options.tolerance === undefined
|
|
@@ -194,6 +220,7 @@ export class DecisionManager {
|
|
|
194
220
|
async decide(request) {
|
|
195
221
|
request.signal?.throwIfAborted();
|
|
196
222
|
const questions = normalizeQuestions(request.questions);
|
|
223
|
+
const pictures = picturesOf(request.state, questions);
|
|
197
224
|
const chosen = request.provider ?? this.config.defaultProvider ?? this.providers.keys().next().value;
|
|
198
225
|
if (chosen === undefined)
|
|
199
226
|
throw new DecisionError('No decision provider is registered', 'DECISION_NO_PROVIDER');
|
|
@@ -203,14 +230,14 @@ export class DecisionManager {
|
|
|
203
230
|
const provider = this.providers.get(name);
|
|
204
231
|
if (!provider)
|
|
205
232
|
throw new DecisionError(`No decision provider is registered as "${name}"`, 'DECISION_NO_PROVIDER');
|
|
206
|
-
const unfit = unsupported(provider, questions);
|
|
233
|
+
const unfit = unsupported(provider, questions, pictures);
|
|
207
234
|
if (unfit) {
|
|
208
235
|
if (position > 0)
|
|
209
236
|
continue;
|
|
210
237
|
throw new DecisionError(`Decision provider "${name}" ${unfit}`, 'DECISION_UNSUPPORTED');
|
|
211
238
|
}
|
|
212
239
|
try {
|
|
213
|
-
return (await this.ask(name, provider, request, questions));
|
|
240
|
+
return (await this.ask(name, provider, request, questions, pictures));
|
|
214
241
|
}
|
|
215
242
|
catch (error) {
|
|
216
243
|
last = error;
|
|
@@ -220,12 +247,15 @@ export class DecisionManager {
|
|
|
220
247
|
}
|
|
221
248
|
throw last;
|
|
222
249
|
}
|
|
223
|
-
async ask(name, provider, request, questions) {
|
|
250
|
+
async ask(name, provider, request, questions, pictures) {
|
|
224
251
|
const model = request.model ?? provider.info.capabilities.defaultModel;
|
|
225
252
|
const started = Date.now();
|
|
226
253
|
const cache = request.cache === false ? undefined : this.config.cache;
|
|
254
|
+
const described = pictures.length
|
|
255
|
+
? replacePictures(request.state, (picture) => ({ picture: pictureDigest(picture.part) }))
|
|
256
|
+
: request.state;
|
|
227
257
|
const key = cache
|
|
228
|
-
? `nexus:decision:${sha256Hex(createCacheKey({ name, model, tenant: request.tenantId, state:
|
|
258
|
+
? `nexus:decision:${sha256Hex(createCacheKey({ name, model, tenant: request.tenantId, state: described, questions }))}`
|
|
229
259
|
: undefined;
|
|
230
260
|
if (cache && key) {
|
|
231
261
|
const hit = await cache.store.get(key);
|
|
@@ -245,7 +275,7 @@ export class DecisionManager {
|
|
|
245
275
|
const run = this.runtime.tracer?.startRun({
|
|
246
276
|
name: `decide ${Object.keys(questions).join(', ')}`,
|
|
247
277
|
kind: 'decision',
|
|
248
|
-
inputs: { state:
|
|
278
|
+
inputs: { state: described, questions },
|
|
249
279
|
model,
|
|
250
280
|
provider: name,
|
|
251
281
|
...(request.metadata ? { metadata: request.metadata } : {}),
|
|
@@ -257,11 +287,18 @@ export class DecisionManager {
|
|
|
257
287
|
provider: name,
|
|
258
288
|
model,
|
|
259
289
|
...(request.tenantId !== undefined ? { tenantId: request.tenantId } : {}),
|
|
260
|
-
metadata: {
|
|
290
|
+
metadata: {
|
|
291
|
+
questions: Object.keys(questions).length,
|
|
292
|
+
...(pictures.length ? { pictures: pictures.length } : {}),
|
|
293
|
+
...request.metadata,
|
|
294
|
+
},
|
|
261
295
|
}, request.signal ? { signal: request.signal } : {}, async (ticket) => {
|
|
262
296
|
const estimate = charged
|
|
263
297
|
? undefined
|
|
264
|
-
: priceDecision(model, {
|
|
298
|
+
: priceDecision(model, {
|
|
299
|
+
inputTokens: Math.ceil(JSON.stringify({ state: described, questions }).length / 4) +
|
|
300
|
+
pictures.length * PICTURE_TOKENS,
|
|
301
|
+
}, this.prices());
|
|
265
302
|
if (ticket && estimate)
|
|
266
303
|
await ticket.reserve(estimate.amount);
|
|
267
304
|
const answered = await provider.decide({ model, state: request.state, questions }, {
|
|
@@ -321,7 +358,7 @@ export async function decide(provider, request) {
|
|
|
321
358
|
return new DecisionManager({ providers: { [provider.info.name]: provider } }).decide(request);
|
|
322
359
|
}
|
|
323
360
|
export async function runDecisionConformance(provider, options = {}) {
|
|
324
|
-
const report = { provider: provider.info.name, passed: [], failures: [] };
|
|
361
|
+
const report = { provider: provider.info.name, passed: [], failures: [], skipped: [] };
|
|
325
362
|
const check = async (name, run) => {
|
|
326
363
|
try {
|
|
327
364
|
await run();
|
|
@@ -342,6 +379,8 @@ export async function runDecisionConformance(provider, options = {}) {
|
|
|
342
379
|
throw new Error('a choice needs two options');
|
|
343
380
|
if (capabilities.types.includes('score') && !(capabilities.maxLevels >= 2))
|
|
344
381
|
throw new Error('a score needs two levels');
|
|
382
|
+
if (capabilities.types.includes('box') && capabilities.images !== true)
|
|
383
|
+
throw new Error('it answers boxes, and reads no pictures to find them in');
|
|
345
384
|
if (!capabilities.defaultModel.trim())
|
|
346
385
|
throw new Error('it names no default model');
|
|
347
386
|
});
|
|
@@ -358,11 +397,19 @@ export async function runDecisionConformance(provider, options = {}) {
|
|
|
358
397
|
options: { early: 'Before it was due', late: 'After it was due' },
|
|
359
398
|
},
|
|
360
399
|
score: { type: 'score', question: 'How much of it was paid?', levels: ['None', 'Some', 'All'] },
|
|
400
|
+
box: { type: 'box', question: 'What `photo` shows most, wherever it is' },
|
|
361
401
|
};
|
|
402
|
+
const picture = options.picture;
|
|
403
|
+
const stateFor = (type) => type === 'box' && picture ? { invoice: state, photo: picture } : state;
|
|
404
|
+
const askable = capabilities.types.filter((type) => type !== 'box' || picture);
|
|
362
405
|
for (const type of capabilities.types) {
|
|
406
|
+
if (!askable.includes(type)) {
|
|
407
|
+
report.skipped.push(`a ${type} question: no picture was given to ask about`);
|
|
408
|
+
continue;
|
|
409
|
+
}
|
|
363
410
|
await check(`a ${type} question`, async () => {
|
|
364
411
|
const question = samples[type];
|
|
365
|
-
const { answers } = await ask(
|
|
412
|
+
const { answers } = await ask(stateFor(type), { asked: question });
|
|
366
413
|
const answer = answers.asked;
|
|
367
414
|
if (answer.type !== type)
|
|
368
415
|
throw new Error(`answered as a ${answer.type}`);
|
|
@@ -370,9 +417,21 @@ export async function runDecisionConformance(provider, options = {}) {
|
|
|
370
417
|
throw new Error(`confidence ${answer.confidence}`);
|
|
371
418
|
});
|
|
372
419
|
}
|
|
420
|
+
if (capabilities.images) {
|
|
421
|
+
if (picture) {
|
|
422
|
+
await check('a question about a picture', async () => {
|
|
423
|
+
const { answers } = await ask({ invoice: state, photo: picture }, { shown: { type: 'yes-no', question: 'Does `photo` show anything at all?' } });
|
|
424
|
+
if (answers.shown.type !== 'yes-no')
|
|
425
|
+
throw new Error(`answered as a ${answers.shown.type}`);
|
|
426
|
+
});
|
|
427
|
+
}
|
|
428
|
+
else {
|
|
429
|
+
report.skipped.push('a question about a picture: no picture was given to ask about');
|
|
430
|
+
}
|
|
431
|
+
}
|
|
373
432
|
await check('several questions in one decision', async () => {
|
|
374
|
-
const questions = Object.fromEntries(
|
|
375
|
-
const { answers } = await ask(state, questions);
|
|
433
|
+
const questions = Object.fromEntries(askable.map((type) => [`q-${type}`, samples[type]]));
|
|
434
|
+
const { answers } = await ask(askable.includes('box') ? stateFor('box') : state, questions);
|
|
376
435
|
for (const name of Object.keys(questions))
|
|
377
436
|
if (!answers[name])
|
|
378
437
|
throw new Error(`"${name}" got no answer`);
|
|
@@ -380,11 +439,12 @@ export async function runDecisionConformance(provider, options = {}) {
|
|
|
380
439
|
await check('a stopped decision is not answered', async () => {
|
|
381
440
|
const controller = new AbortController();
|
|
382
441
|
controller.abort(new Error('stopped'));
|
|
383
|
-
const
|
|
442
|
+
const type = askable[0] ?? 'yes-no';
|
|
443
|
+
const question = samples[type];
|
|
384
444
|
const answered = await provider
|
|
385
445
|
.decide({
|
|
386
446
|
model: options.model ?? capabilities.defaultModel,
|
|
387
|
-
state,
|
|
447
|
+
state: stateFor(type),
|
|
388
448
|
questions: normalizeQuestions({ asked: question }),
|
|
389
449
|
}, { signal: controller.signal, requestId: generateRequestId() })
|
|
390
450
|
.then(() => true, () => false);
|
|
@@ -396,7 +456,13 @@ export async function runDecisionConformance(provider, options = {}) {
|
|
|
396
456
|
const { answers } = await ask(item.state, { asked: item.question });
|
|
397
457
|
const answer = answers.asked;
|
|
398
458
|
if (!answeredRight(answer, item.expected)) {
|
|
399
|
-
const given = answer.type === 'yes-no'
|
|
459
|
+
const given = answer.type === 'yes-no'
|
|
460
|
+
? answer.yes
|
|
461
|
+
: answer.type === 'choice'
|
|
462
|
+
? answer.choice
|
|
463
|
+
: answer.type === 'box'
|
|
464
|
+
? answer.box
|
|
465
|
+
: answer.level;
|
|
400
466
|
throw new Error(`expected ${JSON.stringify(item.expected)}, answered ${JSON.stringify(given)}`);
|
|
401
467
|
}
|
|
402
468
|
});
|
|
@@ -438,18 +504,39 @@ function normalizeQuestions(questions) {
|
|
|
438
504
|
}
|
|
439
505
|
normalized[name] = question;
|
|
440
506
|
}
|
|
507
|
+
else if (question?.type === 'box') {
|
|
508
|
+
if (typeof question.question !== 'string' || !question.question.trim()) {
|
|
509
|
+
throw new DecisionError(`Box "${name}" needs a question: what to find, and in which picture`, 'DECISION_INVALID');
|
|
510
|
+
}
|
|
511
|
+
normalized[name] = { type: 'box', question: question.question };
|
|
512
|
+
}
|
|
441
513
|
else {
|
|
442
|
-
throw new DecisionError(`Question "${name}" is a yes-no, a choice, or a
|
|
514
|
+
throw new DecisionError(`Question "${name}" is a yes-no, a choice, a score, or a box, not ${JSON.stringify(question?.type)}`, 'DECISION_INVALID');
|
|
443
515
|
}
|
|
444
516
|
}
|
|
445
517
|
return normalized;
|
|
446
518
|
}
|
|
447
|
-
|
|
519
|
+
const PICTURE_TOKENS = 1_600;
|
|
520
|
+
function picturesOf(state, questions) {
|
|
521
|
+
const pictures = typeof state === 'string' ? [] : statePictures(state);
|
|
522
|
+
if (pictures.some((picture) => picture.path === '')) {
|
|
523
|
+
throw new DecisionError('A picture that is the whole state has no path for a question to name it by: hold it under a key, such as { photo: picture }', 'DECISION_INVALID');
|
|
524
|
+
}
|
|
525
|
+
const box = Object.entries(questions).find(([, question]) => question.type === 'box');
|
|
526
|
+
if (box && pictures.length === 0) {
|
|
527
|
+
throw new DecisionError(`Box "${box[0]}" asks where something is in a picture, and the state holds none`, 'DECISION_INVALID');
|
|
528
|
+
}
|
|
529
|
+
return pictures;
|
|
530
|
+
}
|
|
531
|
+
function unsupported(provider, questions, pictures = []) {
|
|
448
532
|
const capabilities = provider.info.capabilities;
|
|
449
533
|
const count = Object.keys(questions).length;
|
|
450
534
|
if (capabilities.maxQuestions !== undefined && count > capabilities.maxQuestions) {
|
|
451
535
|
return `takes at most ${capabilities.maxQuestions} questions, not ${count}`;
|
|
452
536
|
}
|
|
537
|
+
if (pictures.length > 0 && capabilities.images !== true) {
|
|
538
|
+
return `does not read pictures, and the state holds ${pictures.length}, such as \`${pictures[0]?.path}\``;
|
|
539
|
+
}
|
|
453
540
|
for (const [name, question] of Object.entries(questions)) {
|
|
454
541
|
if (!capabilities.types.includes(question.type))
|
|
455
542
|
return `does not answer ${question.type} questions, such as "${name}"`;
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/** Why a decision failed, apart from the rest of the contract, so every part of it can raise one. */
|
|
2
|
+
/** Why a decision failed. */
|
|
3
|
+
export type DecisionErrorCode = 'DECISION_NO_PROVIDER' | 'DECISION_UNSUPPORTED' | 'DECISION_INVALID' | 'DECISION_FAILED';
|
|
4
|
+
/** Raised for a decision no provider can serve, a question that is malformed, or a provider's failure. */
|
|
5
|
+
export declare class DecisionError extends Error {
|
|
6
|
+
/**
|
|
7
|
+
* A stable code: `DECISION_NO_PROVIDER`, `DECISION_UNSUPPORTED` (a provider cannot take the
|
|
8
|
+
* question), `DECISION_INVALID` (the request, or an answer, is malformed), or `DECISION_FAILED`.
|
|
9
|
+
*/
|
|
10
|
+
readonly code: DecisionErrorCode;
|
|
11
|
+
/** Whether asking again, or another provider, may help: a timeout or an overloaded service may. */
|
|
12
|
+
readonly retryable: boolean;
|
|
13
|
+
/** The HTTP status a provider answered with, when it did. */
|
|
14
|
+
readonly status?: number | undefined;
|
|
15
|
+
constructor(message: string,
|
|
16
|
+
/**
|
|
17
|
+
* A stable code: `DECISION_NO_PROVIDER`, `DECISION_UNSUPPORTED` (a provider cannot take the
|
|
18
|
+
* question), `DECISION_INVALID` (the request, or an answer, is malformed), or `DECISION_FAILED`.
|
|
19
|
+
*/
|
|
20
|
+
code: DecisionErrorCode,
|
|
21
|
+
/** Whether asking again, or another provider, may help: a timeout or an overloaded service may. */
|
|
22
|
+
retryable?: boolean,
|
|
23
|
+
/** The HTTP status a provider answered with, when it did. */
|
|
24
|
+
status?: number | undefined);
|
|
25
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
export class DecisionError extends Error {
|
|
2
|
+
code;
|
|
3
|
+
retryable;
|
|
4
|
+
status;
|
|
5
|
+
constructor(message, code, retryable = false, status) {
|
|
6
|
+
super(message);
|
|
7
|
+
this.code = code;
|
|
8
|
+
this.retryable = retryable;
|
|
9
|
+
this.status = status;
|
|
10
|
+
this.name = 'DecisionError';
|
|
11
|
+
}
|
|
12
|
+
}
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Typed decisions: questions a model answers with a yes or no, a choice,
|
|
3
|
-
*
|
|
4
|
-
* The contract, its manager, gates, and calibration;
|
|
5
|
-
* decisions in graphs, agents, and evaluations.
|
|
2
|
+
* Typed decisions: questions a model answers with a yes or no, a choice, a score, or a box around
|
|
3
|
+
* something in a picture, each with a confidence read alike from any provider, so software acts on an
|
|
4
|
+
* answer without parsing text. The contract, its manager, gates, and calibration; the pictures a state
|
|
5
|
+
* holds; decisions from any completion model; and decisions in graphs, agents, and evaluations.
|
|
6
6
|
*/
|
|
7
7
|
export { type CompletionDecisionMethod, completionDecisions, type CompletionDecisionsOptions, type DecisionCompletionClient, } from './completion.js';
|
|
8
8
|
export { decisionEvaluator, type DecisionEvaluatorOptions, decisionGuard, type DecisionGuardOptions, type DecisionGuardReview, type DecisionManagerLike, decisionModel, type DecisionModelOptions, decisionPermissions, type DecisionPermissionsOptions, type DecisionRequestOptions, decisionRoute, type DecisionRouteOptions, reviewUnsure, } from './integrations.js';
|
|
9
|
-
export { answeredRight, type AnswerOf, answerProbability, type CachedDecision, calibrate, type CalibrateOptions, type CalibrationBin, type CalibrationReport, type CalibrationSample, type ChoiceAnswer, choiceConfidence, type ChoiceQuestion, decide, DECISION_PRICES, decisionAnswer, type DecisionAnswer, type DecisionAnswers, type DecisionCallContext, type DecisionConfig, type DecisionConformanceCase, type DecisionConformanceOptions, type DecisionConformanceReport, type DecisionDistribution, DecisionError, type DecisionErrorCode, DecisionManager, type DecisionPrice, type DecisionProvider, type DecisionProviderCapabilities, type DecisionProviderInfo, type DecisionProviderQuestion, type DecisionProviderRequest, type DecisionProviderResult, type DecisionQuestion, type DecisionQuestions, type DecisionQuestionType, type DecisionRequest, type DecisionResult, type DecisionRunLike, type DecisionRuntime, type DecisionState, type DecisionTracerLike, type DecisionUsage, gate, type GateOutcome, type GateThresholds, priceDecision, runDecisionConformance, type ScoreAnswer, scoreConfidence, type ScoreQuestion, type YesNoAnswer, yesNoConfidence, type YesNoQuestion, } from './core.js';
|
|
9
|
+
export { answeredRight, type AnswerOf, answerProbability, type BoxAnswer, boxOverlap, type BoxQuestion, type CachedDecision, calibrate, type CalibrateOptions, type CalibrationBin, type CalibrationReport, type CalibrationSample, type ChoiceAnswer, choiceConfidence, type ChoiceQuestion, decide, DECISION_PRICES, decisionAnswer, type DecisionAnswer, type DecisionAnswers, type DecisionBox, type DecisionCallContext, type DecisionConfig, type DecisionConformanceCase, type DecisionConformanceOptions, type DecisionConformanceReport, type DecisionDistribution, DecisionError, type DecisionErrorCode, DecisionManager, type DecisionPrice, type DecisionProvider, type DecisionProviderCapabilities, type DecisionProviderInfo, type DecisionProviderQuestion, type DecisionProviderRequest, type DecisionProviderResult, type DecisionQuestion, type DecisionQuestions, type DecisionQuestionType, type DecisionRequest, type DecisionResult, type DecisionRunLike, type DecisionRuntime, type DecisionState, type DecisionTracerLike, type DecisionUsage, gate, type GateOutcome, type GateThresholds, priceDecision, runDecisionConformance, type ScoreAnswer, scoreConfidence, type ScoreQuestion, type YesNoAnswer, yesNoConfidence, type YesNoQuestion, } from './core.js';
|
|
10
|
+
export { type DecisionPicture, type ReadDecisionPicture, readPicture, statePictures } from './pictures.js';
|
package/dist/decisions/index.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
1
|
export { completionDecisions, } from './completion.js';
|
|
2
2
|
export { decisionEvaluator, decisionGuard, decisionModel, decisionPermissions, decisionRoute, reviewUnsure, } from './integrations.js';
|
|
3
|
-
export { answeredRight, answerProbability, calibrate, choiceConfidence, decide, DECISION_PRICES, decisionAnswer, DecisionError, DecisionManager, gate, priceDecision, runDecisionConformance, scoreConfidence, yesNoConfidence, } from './core.js';
|
|
3
|
+
export { answeredRight, answerProbability, boxOverlap, calibrate, choiceConfidence, decide, DECISION_PRICES, decisionAnswer, DecisionError, DecisionManager, gate, priceDecision, runDecisionConformance, scoreConfidence, yesNoConfidence, } from './core.js';
|
|
4
|
+
export { readPicture, statePictures } from './pictures.js';
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
import type { AgentMiddleware } from '../agent/create-agent.js';
|
|
7
7
|
import type { PermissionPolicyLike, PermissionRequest } from '../agent/permissions.js';
|
|
8
8
|
import type { EvaluationContext, EvaluationScore, Evaluator } from '../types/evaluate.js';
|
|
9
|
-
import type
|
|
9
|
+
import { type BoxQuestion, type ChoiceAnswer, type ChoiceQuestion, type DecisionBox, type DecisionQuestions, type DecisionRequest, type DecisionResult, type DecisionState, type ScoreQuestion, type YesNoAnswer, type YesNoQuestion } from './core.js';
|
|
10
10
|
/** Anything that answers decisions, such as a `DecisionManager`. */
|
|
11
11
|
export interface DecisionManagerLike {
|
|
12
12
|
/** Answers every question of a decision. */
|
|
@@ -117,8 +117,8 @@ export declare function decisionModel<const K extends string>(decisions: Decisio
|
|
|
117
117
|
export interface DecisionEvaluatorOptions<I = unknown, O = unknown> {
|
|
118
118
|
/** The score's key. */
|
|
119
119
|
key: string;
|
|
120
|
-
/** The question: a yes or no, a score, or a
|
|
121
|
-
question: YesNoQuestion | ScoreQuestion | ChoiceQuestion;
|
|
120
|
+
/** The question: a yes or no, a score, a choice, or a box about a picture the state holds. */
|
|
121
|
+
question: YesNoQuestion | ScoreQuestion | ChoiceQuestion | BoxQuestion;
|
|
122
122
|
/** What the question is about. Defaults to the example's inputs, the output, and what was expected. */
|
|
123
123
|
state?: (context: EvaluationContext<I, O>) => DecisionState;
|
|
124
124
|
/**
|
|
@@ -126,13 +126,22 @@ export interface DecisionEvaluatorOptions<I = unknown, O = unknown> {
|
|
|
126
126
|
* passes (the top one by default); for a choice, the option that does.
|
|
127
127
|
*/
|
|
128
128
|
passing?: boolean | number | string;
|
|
129
|
+
/**
|
|
130
|
+
* For a box, where the thing is, such as from the example's expected output: the score is how far
|
|
131
|
+
* the box overlaps it, `boxOverlap()`, and it passes at `overlap` or more. Without it, the score is
|
|
132
|
+
* the box's confidence.
|
|
133
|
+
*/
|
|
134
|
+
where?: (context: EvaluationContext<I, O>) => DecisionBox | undefined;
|
|
135
|
+
/** The overlap a box passes at, from 0 to 1. Defaults to one half. */
|
|
136
|
+
overlap?: number;
|
|
129
137
|
/** Whom and what to ask. */
|
|
130
138
|
request?: DecisionRequestOptions;
|
|
131
139
|
}
|
|
132
140
|
/**
|
|
133
141
|
* An evaluator that asks a decision: the score is the probability of yes, the score's level as a
|
|
134
|
-
* share of the top one,
|
|
135
|
-
*
|
|
142
|
+
* share of the top one, the passing option's probability, or how far a box overlaps where the thing
|
|
143
|
+
* is, and its metadata carries the answer's confidence and probabilities, or its box, so an uncertain
|
|
144
|
+
* score can go to people with `reviewUnsure()`.
|
|
136
145
|
*/
|
|
137
146
|
export declare function decisionEvaluator<I = unknown, O = unknown>(decisions: DecisionManagerLike, options: DecisionEvaluatorOptions<I, O>): Evaluator<I, O>;
|
|
138
147
|
/**
|