@popcomputer/structured-chat 0.1.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/LICENSE +22 -0
- package/README.md +780 -0
- package/dist/adapters/openai-compatible-model.d.ts +89 -0
- package/dist/adapters/openai-compatible-model.js +231 -0
- package/dist/core/answer.d.ts +73 -0
- package/dist/core/answer.js +60 -0
- package/dist/core/chat.d.ts +124 -0
- package/dist/core/chat.js +490 -0
- package/dist/core/collect-stage.d.ts +203 -0
- package/dist/core/collect-stage.js +645 -0
- package/dist/core/command.d.ts +16 -0
- package/dist/core/command.js +17 -0
- package/dist/core/definition.d.ts +10 -0
- package/dist/core/definition.js +14 -0
- package/dist/core/json-value.d.ts +11 -0
- package/dist/core/json-value.js +3 -0
- package/dist/core/model-guard.d.ts +52 -0
- package/dist/core/model-guard.js +37 -0
- package/dist/core/model.d.ts +99 -0
- package/dist/core/model.js +109 -0
- package/dist/core/protocol.d.ts +257 -0
- package/dist/core/protocol.js +153 -0
- package/dist/core/question.d.ts +52 -0
- package/dist/core/question.js +62 -0
- package/dist/core/repair.d.ts +14 -0
- package/dist/core/repair.js +9 -0
- package/dist/core/session.d.ts +78 -0
- package/dist/core/session.js +34 -0
- package/dist/core/stage-name.d.ts +3 -0
- package/dist/core/stage-name.js +3 -0
- package/dist/core/stage.d.ts +88 -0
- package/dist/core/stage.js +104 -0
- package/dist/core/tool-set.d.ts +49 -0
- package/dist/core/tool-set.js +66 -0
- package/dist/core/tool.d.ts +149 -0
- package/dist/core/tool.js +215 -0
- package/dist/core/view.d.ts +95 -0
- package/dist/core/view.js +69 -0
- package/dist/index.d.ts +16 -0
- package/dist/index.js +16 -0
- package/dist/integrations/assistant-ui.d.ts +95 -0
- package/dist/integrations/assistant-ui.js +114 -0
- package/dist/testing/in-memory-session-store.d.ts +4 -0
- package/dist/testing/in-memory-session-store.js +38 -0
- package/dist/testing/scenario.d.ts +59 -0
- package/dist/testing/scenario.js +147 -0
- package/dist/testing.d.ts +4 -0
- package/dist/testing.js +2 -0
- package/examples/agency-search.ts +101 -0
- package/examples/answer-modes.ts +92 -0
- package/examples/prompt-injection-policy.ts +66 -0
- package/package.json +89 -0
|
@@ -0,0 +1,203 @@
|
|
|
1
|
+
import { Effect, Schema } from "effect";
|
|
2
|
+
import type * as ParseResult from "effect/ParseResult";
|
|
3
|
+
import type { AnswerDefinition, AnswerDefinitionContract, AnswerMode } from "./answer.js";
|
|
4
|
+
import { ChatModelUnavailable, StructuredChatModel, type UnsupportedModelToolSchema, type UntrustedMessage } from "./model.js";
|
|
5
|
+
import type { ModelGuardError, ModelGuardRequirements, ModelGuardTuple } from "./model-guard.js";
|
|
6
|
+
import { InvalidToolCall, type InvalidToolProjection } from "./tool.js";
|
|
7
|
+
import type { AdaptiveChoiceQuestion, ChoiceQuestion, QuestionChoice } from "./question.js";
|
|
8
|
+
import { type StructuredDefinition } from "./definition.js";
|
|
9
|
+
/** Safe reason that a collect-stage model proposal was rejected. */
|
|
10
|
+
export declare const InvalidCollectStageResponseReasonSchema: Schema.Literal<["invalid_evidence", "invalid_repair"]>;
|
|
11
|
+
declare const InvalidCollectStageResponse_base: Schema.TaggedErrorClass<InvalidCollectStageResponse, "InvalidCollectStageResponse", {
|
|
12
|
+
readonly _tag: Schema.tag<"InvalidCollectStageResponse">;
|
|
13
|
+
} & {
|
|
14
|
+
stage: Schema.filter<Schema.filter<typeof Schema.NonEmptyTrimmedString>>;
|
|
15
|
+
reason: Schema.Literal<["invalid_evidence", "invalid_repair"]>;
|
|
16
|
+
}>;
|
|
17
|
+
/** A collect-stage proposal was not grounded in a user message. */
|
|
18
|
+
export declare class InvalidCollectStageResponse extends InvalidCollectStageResponse_base {
|
|
19
|
+
}
|
|
20
|
+
/** Named answer fields accepted by a collect stage. */
|
|
21
|
+
export type AnswerFields = Readonly<Record<string, AnswerDefinitionContract>>;
|
|
22
|
+
type AnswerValue<Answer> = Answer extends AnswerDefinition<infer _Mode, infer ValueSchema, infer _Error, infer _Requirements> ? Schema.Schema.Type<ValueSchema> : never;
|
|
23
|
+
/** Complete typed answers required by a collect stage. */
|
|
24
|
+
export type CollectAnswers<Fields extends AnswerFields> = {
|
|
25
|
+
readonly [Field in keyof Fields]: AnswerValue<Fields[Field]>;
|
|
26
|
+
};
|
|
27
|
+
/**
|
|
28
|
+
* Location of the user-authored text that supported an accepted answer.
|
|
29
|
+
*
|
|
30
|
+
* The quote is untrusted conversation data. For semantic answers it supports
|
|
31
|
+
* an inference; it is not required to equal the accepted typed value.
|
|
32
|
+
*/
|
|
33
|
+
export interface AcceptedAnswerEvidence {
|
|
34
|
+
readonly messageIndex: number;
|
|
35
|
+
readonly quote: string;
|
|
36
|
+
}
|
|
37
|
+
/** One typed answer persisted together with its supporting transcript data. */
|
|
38
|
+
export interface AcceptedAnswer<Value> {
|
|
39
|
+
readonly value: Value;
|
|
40
|
+
readonly evidence: AcceptedAnswerEvidence;
|
|
41
|
+
}
|
|
42
|
+
declare const AnswerValidationRejected_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 & {
|
|
43
|
+
readonly _tag: "AnswerValidationRejected";
|
|
44
|
+
} & Readonly<A>;
|
|
45
|
+
/** A domain validator rejected one structurally valid proposed answer. */
|
|
46
|
+
export declare class AnswerValidationRejected<Error, Question> extends AnswerValidationRejected_base<{
|
|
47
|
+
readonly stage: string;
|
|
48
|
+
readonly field: string;
|
|
49
|
+
readonly error: Error;
|
|
50
|
+
readonly question: Question;
|
|
51
|
+
}> {
|
|
52
|
+
}
|
|
53
|
+
/** Accepted answer units keyed by their collect-stage field. */
|
|
54
|
+
export type CollectAcceptedAnswers<Fields extends AnswerFields> = {
|
|
55
|
+
readonly [Field in keyof Fields]: AcceptedAnswer<AnswerValue<Fields[Field]>>;
|
|
56
|
+
};
|
|
57
|
+
/** One assistant question persisted together with its transcript location. */
|
|
58
|
+
export interface IssuedCollectQuestion {
|
|
59
|
+
readonly messageIndex: number;
|
|
60
|
+
readonly text: string;
|
|
61
|
+
}
|
|
62
|
+
/** Server-owned progress for one collect stage. */
|
|
63
|
+
export interface CollectStageState<Fields extends AnswerFields> {
|
|
64
|
+
readonly accepted: Partial<CollectAcceptedAnswers<Fields>>;
|
|
65
|
+
readonly asked: Partial<Record<keyof Fields & string, IssuedCollectQuestion>>;
|
|
66
|
+
}
|
|
67
|
+
/** Typed question selected for the next missing answer. */
|
|
68
|
+
export type CollectStageQuestion<Fields extends AnswerFields> = {
|
|
69
|
+
[Field in keyof Fields & string]: {
|
|
70
|
+
readonly field: Field;
|
|
71
|
+
readonly mode: Fields[Field]["mode"];
|
|
72
|
+
readonly description: string;
|
|
73
|
+
readonly question: Fields[Field]["question"];
|
|
74
|
+
};
|
|
75
|
+
}[keyof Fields & string];
|
|
76
|
+
type QuestionOptions<Question> = Question extends ChoiceQuestion<infer Value> ? ReadonlyArray<QuestionChoice<Value>> : Question extends AdaptiveChoiceQuestion ? ReadonlyArray<QuestionChoice<string>> : readonly [];
|
|
77
|
+
/** Browser-ready question deterministically selected after fact extraction. */
|
|
78
|
+
export type CollectStagePrompt<Fields extends AnswerFields> = {
|
|
79
|
+
[Field in keyof Fields & string]: {
|
|
80
|
+
readonly field: Field;
|
|
81
|
+
readonly mode: Fields[Field]["mode"];
|
|
82
|
+
readonly text: string;
|
|
83
|
+
readonly options: QuestionOptions<Fields[Field]["question"]>;
|
|
84
|
+
readonly escape?: {
|
|
85
|
+
readonly label: string;
|
|
86
|
+
};
|
|
87
|
+
};
|
|
88
|
+
}[keyof Fields & string];
|
|
89
|
+
type AnswerValidationError<Answer> = Answer extends AnswerDefinition<infer _Mode, infer _Schema, infer Error, infer _Requirements> ? Error : never;
|
|
90
|
+
type AnswerValidationRequirements<Answer> = Answer extends AnswerDefinition<infer _Mode, infer _Schema, infer _Error, infer Requirements> ? Requirements : never;
|
|
91
|
+
/** Failure union produced by all field validators in a collect stage. */
|
|
92
|
+
export type CollectAnswerValidationError<Fields extends AnswerFields> = {
|
|
93
|
+
[Field in keyof Fields & string]: [
|
|
94
|
+
AnswerValidationError<Fields[Field]>
|
|
95
|
+
] extends [never] ? never : AnswerValidationRejected<AnswerValidationError<Fields[Field]>, Extract<CollectStagePrompt<Fields>, {
|
|
96
|
+
readonly field: Field;
|
|
97
|
+
}>>;
|
|
98
|
+
}[keyof Fields & string];
|
|
99
|
+
/** Effect service union required by all field validators in a collect stage. */
|
|
100
|
+
export type CollectAnswerValidationRequirements<Fields extends AnswerFields> = AnswerValidationRequirements<Fields[keyof Fields]>;
|
|
101
|
+
/** Result of one collect-stage model turn. */
|
|
102
|
+
export interface CollectStageTurn<Fields extends AnswerFields> {
|
|
103
|
+
readonly state: CollectStageState<Fields>;
|
|
104
|
+
readonly complete: boolean;
|
|
105
|
+
readonly question: CollectStagePrompt<Fields> | undefined;
|
|
106
|
+
}
|
|
107
|
+
type RuntimeAnswerValue = Schema.Schema.Type<Schema.Schema.AnyNoContext>;
|
|
108
|
+
type RuntimeAcceptedAnswer = AcceptedAnswer<RuntimeAnswerValue>;
|
|
109
|
+
interface RuntimeCollectStageState {
|
|
110
|
+
readonly accepted: Readonly<Partial<Record<string, RuntimeAcceptedAnswer>>>;
|
|
111
|
+
readonly asked: Readonly<Partial<Record<string, IssuedCollectQuestion>>>;
|
|
112
|
+
}
|
|
113
|
+
interface RuntimeCollectStagePrompt {
|
|
114
|
+
readonly field: string;
|
|
115
|
+
readonly mode: AnswerMode;
|
|
116
|
+
readonly text: string;
|
|
117
|
+
readonly options: ReadonlyArray<QuestionChoice<RuntimeAnswerValue>>;
|
|
118
|
+
readonly escape?: {
|
|
119
|
+
readonly label: string;
|
|
120
|
+
};
|
|
121
|
+
}
|
|
122
|
+
interface RuntimeCollectStageTurn {
|
|
123
|
+
readonly state: RuntimeCollectStageState;
|
|
124
|
+
readonly complete: boolean;
|
|
125
|
+
readonly question: RuntimeCollectStagePrompt | undefined;
|
|
126
|
+
}
|
|
127
|
+
interface RuntimeCollectRepair {
|
|
128
|
+
readonly _tag: "ReplaceAcceptedAnswer" | "ReconfirmAnswer";
|
|
129
|
+
readonly field: string;
|
|
130
|
+
readonly value?: RuntimeAnswerValue;
|
|
131
|
+
readonly evidence: {
|
|
132
|
+
readonly quote: string;
|
|
133
|
+
};
|
|
134
|
+
}
|
|
135
|
+
interface RuntimeCollectRepairResult {
|
|
136
|
+
readonly state: RuntimeCollectStageState;
|
|
137
|
+
readonly requiresConfirmation: boolean;
|
|
138
|
+
}
|
|
139
|
+
/** @internal Erased collect-stage behavior consumed by the chat runtime. */
|
|
140
|
+
export interface CollectStageRuntime {
|
|
141
|
+
readonly initialState: RuntimeCollectStageState;
|
|
142
|
+
readonly stateSchema: Schema.Schema.AnyNoContext;
|
|
143
|
+
readonly isInitial: (state: RuntimeCollectStageState) => boolean;
|
|
144
|
+
readonly isValid: (state: RuntimeCollectStageState) => boolean;
|
|
145
|
+
readonly isGroundedInMessages: (state: RuntimeCollectStageState, messages: ReadonlyArray<UntrustedMessage>) => boolean;
|
|
146
|
+
readonly isComplete: (state: RuntimeCollectStageState) => boolean;
|
|
147
|
+
readonly repairSchema: Schema.Schema.AnyNoContext;
|
|
148
|
+
readonly applyRepairs: (state: RuntimeCollectStageState, messages: ReadonlyArray<UntrustedMessage>, repairs: ReadonlyArray<RuntimeCollectRepair>) => Effect.Effect<RuntimeCollectRepairResult, unknown, unknown>;
|
|
149
|
+
readonly run: (input: {
|
|
150
|
+
readonly state: RuntimeCollectStageState;
|
|
151
|
+
readonly messages: ReadonlyArray<UntrustedMessage>;
|
|
152
|
+
}) => Effect.Effect<RuntimeCollectStageTurn, unknown, unknown>;
|
|
153
|
+
}
|
|
154
|
+
declare const collectStageRuntime: unique symbol;
|
|
155
|
+
/** Minimum sealed collect-stage shape accepted by a chat definition. */
|
|
156
|
+
export interface CollectStageDefinitionContract extends StructuredDefinition<"collect_stage"> {
|
|
157
|
+
readonly _tag: "CollectStage";
|
|
158
|
+
readonly name: string;
|
|
159
|
+
readonly [collectStageRuntime]: CollectStageRuntime;
|
|
160
|
+
}
|
|
161
|
+
/** @internal Read the erased runtime from an authentic collect stage. */
|
|
162
|
+
export declare const readCollectStageRuntime: (stage: CollectStageDefinitionContract) => CollectStageRuntime;
|
|
163
|
+
/** Shared conversational policy for questions in one collect stage. */
|
|
164
|
+
export interface CollectQuestionPolicy {
|
|
165
|
+
/** Trusted style guidance applied to every adaptive question in this stage. */
|
|
166
|
+
readonly guidance?: string;
|
|
167
|
+
/** A browser-visible answer that keeps the current field unresolved. */
|
|
168
|
+
readonly escape?: string;
|
|
169
|
+
}
|
|
170
|
+
/** Definition input for one schema-derived fact collection stage. */
|
|
171
|
+
export interface DefineCollectStageInput<Name extends string, Fields extends AnswerFields, Guards extends ModelGuardTuple> {
|
|
172
|
+
readonly name: Name;
|
|
173
|
+
readonly questions?: CollectQuestionPolicy;
|
|
174
|
+
readonly fields: Fields;
|
|
175
|
+
readonly guards?: Guards;
|
|
176
|
+
}
|
|
177
|
+
/** One schema-derived stage that is complete only when every fact is known. */
|
|
178
|
+
export interface CollectStage<Name extends string, Fields extends AnswerFields, Guards extends ModelGuardTuple = readonly []> extends CollectStageDefinitionContract {
|
|
179
|
+
readonly _tag: "CollectStage";
|
|
180
|
+
readonly name: Name;
|
|
181
|
+
readonly fields: Fields;
|
|
182
|
+
readonly questions: CollectQuestionPolicy;
|
|
183
|
+
readonly answersSchema: Schema.Schema<CollectAnswers<Fields>, unknown, never>;
|
|
184
|
+
readonly stateSchema: Schema.Schema<CollectStageState<Fields>, unknown, never>;
|
|
185
|
+
readonly initialState: CollectStageState<Fields>;
|
|
186
|
+
readonly guards: Guards;
|
|
187
|
+
/** Strictly parse persisted or client-returned stage state. */
|
|
188
|
+
readonly parseState: (input: Schema.Schema.Encoded<Schema.Schema<CollectStageState<Fields>, unknown, never>>) => Effect.Effect<CollectStageState<Fields>, ParseResult.ParseError>;
|
|
189
|
+
/** Test whether every schema-defined answer has been populated. */
|
|
190
|
+
readonly isComplete: (state: CollectStageState<Fields>) => boolean;
|
|
191
|
+
/** Select the first missing question in schema declaration order. */
|
|
192
|
+
readonly nextQuestion: (state: CollectStageState<Fields>) => CollectStageQuestion<Fields> | undefined;
|
|
193
|
+
/** Record the first assistant question issued for one field. */
|
|
194
|
+
readonly markAsked: <Field extends keyof Fields & string>(state: CollectStageState<Fields>, field: Field, messageIndex: number, text: string) => CollectStageState<Fields>;
|
|
195
|
+
/** Extract grounded answers and deterministically advance one turn. */
|
|
196
|
+
readonly run: (input: {
|
|
197
|
+
readonly state: CollectStageState<Fields>;
|
|
198
|
+
readonly messages: ReadonlyArray<UntrustedMessage>;
|
|
199
|
+
}) => Effect.Effect<CollectStageTurn<Fields>, ChatModelUnavailable | UnsupportedModelToolSchema | InvalidToolCall | InvalidToolProjection | InvalidCollectStageResponse | CollectAnswerValidationError<Fields> | ModelGuardError<Guards>, StructuredChatModel | CollectAnswerValidationRequirements<Fields> | ModelGuardRequirements<Guards>>;
|
|
200
|
+
}
|
|
201
|
+
/** Define one deterministic schema-derived fact collection stage. */
|
|
202
|
+
export declare const defineCollectStage: <const Name extends string, const Fields extends AnswerFields, const Guards extends ModelGuardTuple = readonly []>(definition: DefineCollectStageInput<Name, Fields, Guards>) => CollectStage<Name, Fields, Guards>;
|
|
203
|
+
export {};
|