@codefionn/llmleaf-client 0.1.6 → 0.1.8
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/README.md +17 -0
- package/dist/client.d.ts +11 -1
- package/dist/client.d.ts.map +1 -1
- package/dist/client.js +41 -1
- package/dist/client.js.map +1 -1
- package/dist/gen/llmleaf/v1/llmleaf_pb.d.ts +739 -0
- package/dist/gen/llmleaf/v1/llmleaf_pb.d.ts.map +1 -1
- package/dist/gen/llmleaf/v1/llmleaf_pb.js +132 -22
- package/dist/gen/llmleaf/v1/llmleaf_pb.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js.map +1 -1
- package/dist/types.d.ts +215 -0
- package/dist/types.d.ts.map +1 -1
- package/dist/wire.d.ts +12 -1
- package/dist/wire.d.ts.map +1 -1
- package/dist/wire.js +451 -0
- package/dist/wire.js.map +1 -1
- package/package.json +1 -1
- package/src/client.ts +49 -0
- package/src/gen/llmleaf/v1/llmleaf_pb.ts +871 -22
- package/src/index.ts +24 -0
- package/src/types.ts +257 -0
- package/src/wire.ts +455 -0
package/src/wire.ts
CHANGED
|
@@ -48,6 +48,26 @@ import type {
|
|
|
48
48
|
BatchResultLine,
|
|
49
49
|
BatchResponse,
|
|
50
50
|
BatchError,
|
|
51
|
+
ErrorBody,
|
|
52
|
+
ResponsesRequest,
|
|
53
|
+
ResponsesInput,
|
|
54
|
+
ResponseItem,
|
|
55
|
+
ResponseMessageItem,
|
|
56
|
+
ResponseMessageContent,
|
|
57
|
+
ResponseContentPart,
|
|
58
|
+
ResponseFunctionCallItem,
|
|
59
|
+
ResponseFunctionCallOutputItem,
|
|
60
|
+
ResponseReasoningItem,
|
|
61
|
+
ResponseReasoningText,
|
|
62
|
+
ResponsesToolDef,
|
|
63
|
+
ResponsesToolChoice,
|
|
64
|
+
ResponsesReasoning,
|
|
65
|
+
ResponsesResponse,
|
|
66
|
+
ResponsesUsage,
|
|
67
|
+
ResponsesInputTokensDetails,
|
|
68
|
+
ResponsesOutputTokensDetails,
|
|
69
|
+
ResponsesIncompleteDetails,
|
|
70
|
+
ResponsesStreamEvent,
|
|
51
71
|
} from "./types.js";
|
|
52
72
|
|
|
53
73
|
// A plain JSON object on the wire.
|
|
@@ -676,3 +696,438 @@ export function decodeBatchResultLine(v: unknown): BatchResultLine {
|
|
|
676
696
|
if (error !== undefined) line.error = error;
|
|
677
697
|
return line;
|
|
678
698
|
}
|
|
699
|
+
|
|
700
|
+
// ===========================================================================
|
|
701
|
+
// Responses (POST /v1/responses) — encode
|
|
702
|
+
// ===========================================================================
|
|
703
|
+
|
|
704
|
+
function encodeResponseContentPart(p: ResponseContentPart): Json {
|
|
705
|
+
switch (p.type) {
|
|
706
|
+
case "input_text":
|
|
707
|
+
return { type: "input_text", text: p.text };
|
|
708
|
+
case "input_image": {
|
|
709
|
+
// image_url is a plain STRING here, not the chat dialect's nested {url} object.
|
|
710
|
+
const out: Json = { type: "input_image", image_url: p.imageUrl };
|
|
711
|
+
put(out, "detail", p.detail);
|
|
712
|
+
return out;
|
|
713
|
+
}
|
|
714
|
+
case "output_text":
|
|
715
|
+
// A constructed output_text part carries an (empty) annotations array (SPEC.md).
|
|
716
|
+
return { type: "output_text", text: p.text, annotations: [] };
|
|
717
|
+
}
|
|
718
|
+
}
|
|
719
|
+
|
|
720
|
+
function encodeResponseMessageContent(content: ResponseMessageContent | undefined): unknown {
|
|
721
|
+
if (content === undefined) return undefined;
|
|
722
|
+
if (typeof content === "string") return content;
|
|
723
|
+
return content.map(encodeResponseContentPart);
|
|
724
|
+
}
|
|
725
|
+
|
|
726
|
+
/** A plain message item is a bare role-keyed object with NO `"type"` (SPEC.md). */
|
|
727
|
+
function encodeResponseMessageItem(m: ResponseMessageItem): Json {
|
|
728
|
+
const out: Json = { role: m.role };
|
|
729
|
+
put(out, "id", m.id);
|
|
730
|
+
const content = encodeResponseMessageContent(m.content);
|
|
731
|
+
if (content !== undefined) out["content"] = content;
|
|
732
|
+
put(out, "status", m.status);
|
|
733
|
+
return out;
|
|
734
|
+
}
|
|
735
|
+
|
|
736
|
+
function encodeResponseFunctionCallItem(fc: ResponseFunctionCallItem): Json {
|
|
737
|
+
const out: Json = {
|
|
738
|
+
type: "function_call",
|
|
739
|
+
call_id: fc.callId,
|
|
740
|
+
name: fc.name,
|
|
741
|
+
arguments: fc.arguments,
|
|
742
|
+
};
|
|
743
|
+
put(out, "id", fc.id);
|
|
744
|
+
put(out, "status", fc.status);
|
|
745
|
+
return out;
|
|
746
|
+
}
|
|
747
|
+
|
|
748
|
+
function encodeResponseFunctionCallOutputItem(fo: ResponseFunctionCallOutputItem): Json {
|
|
749
|
+
const out: Json = {
|
|
750
|
+
type: "function_call_output",
|
|
751
|
+
call_id: fo.callId,
|
|
752
|
+
output: fo.output,
|
|
753
|
+
};
|
|
754
|
+
put(out, "id", fo.id);
|
|
755
|
+
return out;
|
|
756
|
+
}
|
|
757
|
+
|
|
758
|
+
function encodeResponseReasoningItem(r: ResponseReasoningItem): Json {
|
|
759
|
+
const out: Json = { type: "reasoning" };
|
|
760
|
+
put(out, "id", r.id);
|
|
761
|
+
// The list an entry lives in decides its wire token: summary -> "summary_text",
|
|
762
|
+
// content -> "reasoning_text" (SPEC.md).
|
|
763
|
+
if (r.summary && r.summary.length > 0) {
|
|
764
|
+
out["summary"] = r.summary.map((s) => ({ type: "summary_text", text: s.text }));
|
|
765
|
+
}
|
|
766
|
+
if (r.content && r.content.length > 0) {
|
|
767
|
+
out["content"] = r.content.map((c) => ({ type: "reasoning_text", text: c.text }));
|
|
768
|
+
}
|
|
769
|
+
// Opaque blob replayed verbatim to continue an encrypted reasoning turn.
|
|
770
|
+
put(out, "encrypted_content", r.encryptedContent);
|
|
771
|
+
return out;
|
|
772
|
+
}
|
|
773
|
+
|
|
774
|
+
function encodeResponseItem(item: ResponseItem): Json {
|
|
775
|
+
switch (item.type) {
|
|
776
|
+
case "function_call":
|
|
777
|
+
return encodeResponseFunctionCallItem(item);
|
|
778
|
+
case "function_call_output":
|
|
779
|
+
return encodeResponseFunctionCallOutputItem(item);
|
|
780
|
+
case "reasoning":
|
|
781
|
+
return encodeResponseReasoningItem(item);
|
|
782
|
+
case "message":
|
|
783
|
+
return encodeResponseMessageItem(item);
|
|
784
|
+
}
|
|
785
|
+
}
|
|
786
|
+
|
|
787
|
+
function encodeResponsesInput(input: ResponsesInput): unknown {
|
|
788
|
+
// A bare string is one user message; otherwise an array of items.
|
|
789
|
+
if (typeof input === "string") return input;
|
|
790
|
+
return input.map(encodeResponseItem);
|
|
791
|
+
}
|
|
792
|
+
|
|
793
|
+
function encodeResponsesToolDef(t: ResponsesToolDef): Json {
|
|
794
|
+
// FLAT: type/name/parameters at the top level, no nested `function` object.
|
|
795
|
+
const out: Json = { type: t.type, name: t.name };
|
|
796
|
+
put(out, "description", t.description);
|
|
797
|
+
put(out, "parameters", parseRawJson("ResponsesToolDef.parameters", t.parameters));
|
|
798
|
+
put(out, "strict", t.strict);
|
|
799
|
+
return out;
|
|
800
|
+
}
|
|
801
|
+
|
|
802
|
+
function encodeResponsesToolChoice(tc: ResponsesToolChoice): unknown {
|
|
803
|
+
// FLAT named object {type,name}, unlike the chat dialect's nested `function`.
|
|
804
|
+
if (typeof tc === "string") return tc;
|
|
805
|
+
return { type: tc.type, name: tc.name };
|
|
806
|
+
}
|
|
807
|
+
|
|
808
|
+
function encodeResponsesReasoning(r: ResponsesReasoning): Json {
|
|
809
|
+
const out: Json = {};
|
|
810
|
+
put(out, "effort", r.effort);
|
|
811
|
+
put(out, "summary", r.summary);
|
|
812
|
+
return out;
|
|
813
|
+
}
|
|
814
|
+
|
|
815
|
+
/** Build the responses request body. `forceStream` overrides `stream` for the streaming call. */
|
|
816
|
+
export function encodeResponsesRequest(req: ResponsesRequest, forceStream?: boolean): Json {
|
|
817
|
+
const out: Json = {
|
|
818
|
+
model: req.model,
|
|
819
|
+
input: encodeResponsesInput(req.input),
|
|
820
|
+
};
|
|
821
|
+
put(out, "instructions", req.instructions);
|
|
822
|
+
const stream = forceStream !== undefined ? forceStream : req.stream;
|
|
823
|
+
put(out, "stream", stream);
|
|
824
|
+
put(out, "temperature", req.temperature);
|
|
825
|
+
put(out, "top_p", req.topP);
|
|
826
|
+
put(out, "max_output_tokens", req.maxOutputTokens);
|
|
827
|
+
if (req.tools && req.tools.length > 0) out["tools"] = req.tools.map(encodeResponsesToolDef);
|
|
828
|
+
put(out, "tool_choice", req.toolChoice && encodeResponsesToolChoice(req.toolChoice));
|
|
829
|
+
put(out, "reasoning", req.reasoning && encodeResponsesReasoning(req.reasoning));
|
|
830
|
+
put(out, "store", req.store);
|
|
831
|
+
|
|
832
|
+
// `extra`: parsed and merged at the top level of the request object (SPEC.md).
|
|
833
|
+
const extra = parseRawJson("ResponsesRequest.extra", req.extra);
|
|
834
|
+
if (extra !== undefined) {
|
|
835
|
+
if (typeof extra !== "object" || extra === null || Array.isArray(extra)) {
|
|
836
|
+
throw new TypeError("ResponsesRequest.extra must be a JSON object");
|
|
837
|
+
}
|
|
838
|
+
for (const [k, v] of Object.entries(extra as Json)) out[k] = v;
|
|
839
|
+
}
|
|
840
|
+
return out;
|
|
841
|
+
}
|
|
842
|
+
|
|
843
|
+
// ===========================================================================
|
|
844
|
+
// Responses — decode
|
|
845
|
+
// ===========================================================================
|
|
846
|
+
|
|
847
|
+
function decodeResponseContentPart(v: unknown): ResponseContentPart | undefined {
|
|
848
|
+
const o = obj(v);
|
|
849
|
+
if (!o) return undefined;
|
|
850
|
+
switch (str(o["type"])) {
|
|
851
|
+
case "input_text":
|
|
852
|
+
return { type: "input_text", text: str(o["text"]) };
|
|
853
|
+
case "input_image": {
|
|
854
|
+
const part: ResponseInputImagePartLocal = {
|
|
855
|
+
type: "input_image",
|
|
856
|
+
imageUrl: str(o["image_url"]),
|
|
857
|
+
};
|
|
858
|
+
const detail = optStr(o["detail"]);
|
|
859
|
+
if (detail !== undefined) part.detail = detail;
|
|
860
|
+
return part;
|
|
861
|
+
}
|
|
862
|
+
case "output_text":
|
|
863
|
+
return { type: "output_text", text: str(o["text"]) };
|
|
864
|
+
default:
|
|
865
|
+
return undefined; // unknown content part — skip
|
|
866
|
+
}
|
|
867
|
+
}
|
|
868
|
+
|
|
869
|
+
// A local alias so the decoder can build the image part incrementally.
|
|
870
|
+
type ResponseInputImagePartLocal = Extract<ResponseContentPart, { type: "input_image" }>;
|
|
871
|
+
|
|
872
|
+
function decodeResponseMessageContent(v: unknown): ResponseMessageContent | undefined {
|
|
873
|
+
if (v === undefined || v === null) return undefined;
|
|
874
|
+
if (typeof v === "string") return v;
|
|
875
|
+
if (Array.isArray(v)) {
|
|
876
|
+
const parts: ResponseContentPart[] = [];
|
|
877
|
+
for (const raw of v) {
|
|
878
|
+
const p = decodeResponseContentPart(raw);
|
|
879
|
+
if (p !== undefined) parts.push(p);
|
|
880
|
+
}
|
|
881
|
+
return parts;
|
|
882
|
+
}
|
|
883
|
+
return undefined;
|
|
884
|
+
}
|
|
885
|
+
|
|
886
|
+
function decodeResponseMessageItem(o: Json): ResponseMessageItem {
|
|
887
|
+
const item: ResponseMessageItem = { type: "message", role: str(o["role"]) };
|
|
888
|
+
const id = optStr(o["id"]);
|
|
889
|
+
if (id !== undefined) item.id = id;
|
|
890
|
+
const content = decodeResponseMessageContent(o["content"]);
|
|
891
|
+
if (content !== undefined) item.content = content;
|
|
892
|
+
const status = optStr(o["status"]);
|
|
893
|
+
if (status !== undefined) item.status = status;
|
|
894
|
+
return item;
|
|
895
|
+
}
|
|
896
|
+
|
|
897
|
+
function decodeResponseFunctionCallItem(o: Json): ResponseFunctionCallItem {
|
|
898
|
+
const item: ResponseFunctionCallItem = {
|
|
899
|
+
type: "function_call",
|
|
900
|
+
callId: str(o["call_id"]),
|
|
901
|
+
name: str(o["name"]),
|
|
902
|
+
arguments: str(o["arguments"]),
|
|
903
|
+
};
|
|
904
|
+
const id = optStr(o["id"]);
|
|
905
|
+
if (id !== undefined) item.id = id;
|
|
906
|
+
const status = optStr(o["status"]);
|
|
907
|
+
if (status !== undefined) item.status = status;
|
|
908
|
+
return item;
|
|
909
|
+
}
|
|
910
|
+
|
|
911
|
+
function decodeResponseFunctionCallOutputItem(o: Json): ResponseFunctionCallOutputItem {
|
|
912
|
+
const item: ResponseFunctionCallOutputItem = {
|
|
913
|
+
type: "function_call_output",
|
|
914
|
+
callId: str(o["call_id"]),
|
|
915
|
+
output: str(o["output"]),
|
|
916
|
+
};
|
|
917
|
+
const id = optStr(o["id"]);
|
|
918
|
+
if (id !== undefined) item.id = id;
|
|
919
|
+
return item;
|
|
920
|
+
}
|
|
921
|
+
|
|
922
|
+
function decodeReasoningTextList(v: unknown): ResponseReasoningText[] {
|
|
923
|
+
return arr(v)
|
|
924
|
+
.map((raw): ResponseReasoningText | undefined => {
|
|
925
|
+
const o = obj(raw);
|
|
926
|
+
return o ? { text: str(o["text"]) } : undefined;
|
|
927
|
+
})
|
|
928
|
+
.filter((x): x is ResponseReasoningText => x !== undefined);
|
|
929
|
+
}
|
|
930
|
+
|
|
931
|
+
function decodeResponseReasoningItem(o: Json): ResponseReasoningItem {
|
|
932
|
+
const item: ResponseReasoningItem = { type: "reasoning" };
|
|
933
|
+
const id = optStr(o["id"]);
|
|
934
|
+
if (id !== undefined) item.id = id;
|
|
935
|
+
const summary = decodeReasoningTextList(o["summary"]);
|
|
936
|
+
if (summary.length > 0) item.summary = summary;
|
|
937
|
+
const content = decodeReasoningTextList(o["content"]);
|
|
938
|
+
if (content.length > 0) item.content = content;
|
|
939
|
+
const enc = optStr(o["encrypted_content"]);
|
|
940
|
+
if (enc !== undefined) item.encryptedContent = enc;
|
|
941
|
+
return item;
|
|
942
|
+
}
|
|
943
|
+
|
|
944
|
+
function decodeResponseItem(v: unknown): ResponseItem | undefined {
|
|
945
|
+
const o = obj(v);
|
|
946
|
+
if (!o) return undefined;
|
|
947
|
+
const type = optStr(o["type"]);
|
|
948
|
+
// A role-keyed object with no `type` is a plain message item (SPEC.md).
|
|
949
|
+
if (type === undefined || type === "message") return decodeResponseMessageItem(o);
|
|
950
|
+
switch (type) {
|
|
951
|
+
case "function_call":
|
|
952
|
+
return decodeResponseFunctionCallItem(o);
|
|
953
|
+
case "function_call_output":
|
|
954
|
+
return decodeResponseFunctionCallOutputItem(o);
|
|
955
|
+
case "reasoning":
|
|
956
|
+
return decodeResponseReasoningItem(o);
|
|
957
|
+
default:
|
|
958
|
+
return undefined; // unknown item type — skip
|
|
959
|
+
}
|
|
960
|
+
}
|
|
961
|
+
|
|
962
|
+
function decodeErrorBody(v: unknown): ErrorBody | undefined {
|
|
963
|
+
const o = obj(v);
|
|
964
|
+
if (!o) return undefined;
|
|
965
|
+
const body: ErrorBody = { message: str(o["message"]) };
|
|
966
|
+
const type = optStr(o["type"]);
|
|
967
|
+
if (type !== undefined) body.type = type;
|
|
968
|
+
const code = optStr(o["code"]);
|
|
969
|
+
if (code !== undefined) body.code = code;
|
|
970
|
+
return body;
|
|
971
|
+
}
|
|
972
|
+
|
|
973
|
+
function decodeResponsesReasoning(v: unknown): ResponsesReasoning | undefined {
|
|
974
|
+
const o = obj(v);
|
|
975
|
+
if (!o) return undefined;
|
|
976
|
+
const r: ResponsesReasoning = {};
|
|
977
|
+
const effort = optStr(o["effort"]);
|
|
978
|
+
if (effort !== undefined) r.effort = effort;
|
|
979
|
+
const summary = optStr(o["summary"]);
|
|
980
|
+
if (summary !== undefined) r.summary = summary;
|
|
981
|
+
return r;
|
|
982
|
+
}
|
|
983
|
+
|
|
984
|
+
function decodeResponsesIncompleteDetails(
|
|
985
|
+
v: unknown,
|
|
986
|
+
): ResponsesIncompleteDetails | undefined {
|
|
987
|
+
const o = obj(v);
|
|
988
|
+
if (!o) return undefined;
|
|
989
|
+
return { reason: str(o["reason"]) };
|
|
990
|
+
}
|
|
991
|
+
|
|
992
|
+
function decodeResponsesInputTokensDetails(
|
|
993
|
+
v: unknown,
|
|
994
|
+
): ResponsesInputTokensDetails | undefined {
|
|
995
|
+
const o = obj(v);
|
|
996
|
+
if (!o) return undefined;
|
|
997
|
+
const d: ResponsesInputTokensDetails = {};
|
|
998
|
+
const cached = optNum(o["cached_tokens"]);
|
|
999
|
+
if (cached !== undefined) d.cachedTokens = cached;
|
|
1000
|
+
return d;
|
|
1001
|
+
}
|
|
1002
|
+
|
|
1003
|
+
function decodeResponsesOutputTokensDetails(
|
|
1004
|
+
v: unknown,
|
|
1005
|
+
): ResponsesOutputTokensDetails | undefined {
|
|
1006
|
+
const o = obj(v);
|
|
1007
|
+
if (!o) return undefined;
|
|
1008
|
+
const d: ResponsesOutputTokensDetails = {};
|
|
1009
|
+
const reasoning = optNum(o["reasoning_tokens"]);
|
|
1010
|
+
if (reasoning !== undefined) d.reasoningTokens = reasoning;
|
|
1011
|
+
return d;
|
|
1012
|
+
}
|
|
1013
|
+
|
|
1014
|
+
export function decodeResponsesUsage(v: unknown): ResponsesUsage | undefined {
|
|
1015
|
+
const o = obj(v);
|
|
1016
|
+
if (!o) return undefined;
|
|
1017
|
+
const usage: ResponsesUsage = {
|
|
1018
|
+
inputTokens: num(o["input_tokens"]),
|
|
1019
|
+
outputTokens: num(o["output_tokens"]),
|
|
1020
|
+
totalTokens: num(o["total_tokens"]),
|
|
1021
|
+
};
|
|
1022
|
+
const itd = decodeResponsesInputTokensDetails(o["input_tokens_details"]);
|
|
1023
|
+
if (itd !== undefined) usage.inputTokensDetails = itd;
|
|
1024
|
+
const otd = decodeResponsesOutputTokensDetails(o["output_tokens_details"]);
|
|
1025
|
+
if (otd !== undefined) usage.outputTokensDetails = otd;
|
|
1026
|
+
return usage;
|
|
1027
|
+
}
|
|
1028
|
+
|
|
1029
|
+
export function decodeResponsesResponse(v: unknown): ResponsesResponse {
|
|
1030
|
+
const o = obj(v) ?? {};
|
|
1031
|
+
const resp: ResponsesResponse = {
|
|
1032
|
+
id: str(o["id"]),
|
|
1033
|
+
object: str(o["object"], "response"),
|
|
1034
|
+
createdAt: num(o["created_at"]),
|
|
1035
|
+
status: str(o["status"]),
|
|
1036
|
+
model: str(o["model"]),
|
|
1037
|
+
output: arr(o["output"])
|
|
1038
|
+
.map(decodeResponseItem)
|
|
1039
|
+
.filter((x): x is ResponseItem => x !== undefined),
|
|
1040
|
+
};
|
|
1041
|
+
const inc = decodeResponsesIncompleteDetails(o["incomplete_details"]);
|
|
1042
|
+
if (inc !== undefined) resp.incompleteDetails = inc;
|
|
1043
|
+
const err = decodeErrorBody(o["error"]);
|
|
1044
|
+
if (err !== undefined) resp.error = err;
|
|
1045
|
+
const usage = decodeResponsesUsage(o["usage"]);
|
|
1046
|
+
if (usage !== undefined) resp.usage = usage;
|
|
1047
|
+
const store = optBool(o["store"]);
|
|
1048
|
+
if (store !== undefined) resp.store = store;
|
|
1049
|
+
const instructions = optStr(o["instructions"]);
|
|
1050
|
+
if (instructions !== undefined) resp.instructions = instructions;
|
|
1051
|
+
const maxOut = optNum(o["max_output_tokens"]);
|
|
1052
|
+
if (maxOut !== undefined) resp.maxOutputTokens = maxOut;
|
|
1053
|
+
const temp = optNum(o["temperature"]);
|
|
1054
|
+
if (temp !== undefined) resp.temperature = temp;
|
|
1055
|
+
const topP = optNum(o["top_p"]);
|
|
1056
|
+
if (topP !== undefined) resp.topP = topP;
|
|
1057
|
+
const reasoning = decodeResponsesReasoning(o["reasoning"]);
|
|
1058
|
+
if (reasoning !== undefined) resp.reasoning = reasoning;
|
|
1059
|
+
return resp;
|
|
1060
|
+
}
|
|
1061
|
+
|
|
1062
|
+
// Streaming: typed events, NO `[DONE]` sentinel. The stream ends after the terminal
|
|
1063
|
+
// event; SDKs skip event types they don't recognise (the dialect grows by adding types).
|
|
1064
|
+
const TERMINAL_RESPONSES_EVENT_TYPES = new Set<string>([
|
|
1065
|
+
"response.completed",
|
|
1066
|
+
"response.incomplete",
|
|
1067
|
+
"response.failed",
|
|
1068
|
+
]);
|
|
1069
|
+
|
|
1070
|
+
const KNOWN_RESPONSES_EVENT_TYPES = new Set<string>([
|
|
1071
|
+
"response.created",
|
|
1072
|
+
"response.in_progress",
|
|
1073
|
+
"response.completed",
|
|
1074
|
+
"response.incomplete",
|
|
1075
|
+
"response.failed",
|
|
1076
|
+
"response.output_item.added",
|
|
1077
|
+
"response.output_item.done",
|
|
1078
|
+
"response.content_part.added",
|
|
1079
|
+
"response.content_part.done",
|
|
1080
|
+
"response.output_text.delta",
|
|
1081
|
+
"response.output_text.done",
|
|
1082
|
+
"response.refusal.delta",
|
|
1083
|
+
"response.refusal.done",
|
|
1084
|
+
"response.reasoning_text.delta",
|
|
1085
|
+
"response.reasoning_text.done",
|
|
1086
|
+
"response.reasoning_summary_part.added",
|
|
1087
|
+
"response.reasoning_summary_part.done",
|
|
1088
|
+
"response.reasoning_summary_text.delta",
|
|
1089
|
+
"response.reasoning_summary_text.done",
|
|
1090
|
+
"response.function_call_arguments.delta",
|
|
1091
|
+
"response.function_call_arguments.done",
|
|
1092
|
+
"error",
|
|
1093
|
+
]);
|
|
1094
|
+
|
|
1095
|
+
/** True for `response.completed` / `response.incomplete` / `response.failed`. */
|
|
1096
|
+
export function isTerminalResponsesEvent(type: string): boolean {
|
|
1097
|
+
return TERMINAL_RESPONSES_EVENT_TYPES.has(type);
|
|
1098
|
+
}
|
|
1099
|
+
|
|
1100
|
+
/**
|
|
1101
|
+
* Decode one streaming SSE frame's JSON into a {@link ResponsesStreamEvent}, or
|
|
1102
|
+
* `undefined` when the `type` is one the SDK doesn't recognise (the caller skips it).
|
|
1103
|
+
*/
|
|
1104
|
+
export function decodeResponsesStreamEvent(v: unknown): ResponsesStreamEvent | undefined {
|
|
1105
|
+
const o = obj(v);
|
|
1106
|
+
if (!o) return undefined;
|
|
1107
|
+
const type = str(o["type"]);
|
|
1108
|
+
if (!KNOWN_RESPONSES_EVENT_TYPES.has(type)) return undefined; // unknown event — skip (SPEC.md)
|
|
1109
|
+
const event: ResponsesStreamEvent = {
|
|
1110
|
+
type,
|
|
1111
|
+
sequenceNumber: num(o["sequence_number"]),
|
|
1112
|
+
};
|
|
1113
|
+
if (obj(o["response"])) event.response = decodeResponsesResponse(o["response"]);
|
|
1114
|
+
const outputIndex = optNum(o["output_index"]);
|
|
1115
|
+
if (outputIndex !== undefined) event.outputIndex = outputIndex;
|
|
1116
|
+
const itemId = optStr(o["item_id"]);
|
|
1117
|
+
if (itemId !== undefined) event.itemId = itemId;
|
|
1118
|
+
const contentIndex = optNum(o["content_index"]);
|
|
1119
|
+
if (contentIndex !== undefined) event.contentIndex = contentIndex;
|
|
1120
|
+
const item = decodeResponseItem(o["item"]);
|
|
1121
|
+
if (item !== undefined) event.item = item;
|
|
1122
|
+
const part = decodeResponseContentPart(o["part"]);
|
|
1123
|
+
if (part !== undefined) event.part = part;
|
|
1124
|
+
const delta = optStr(o["delta"]);
|
|
1125
|
+
if (delta !== undefined) event.delta = delta;
|
|
1126
|
+
const text = optStr(o["text"]);
|
|
1127
|
+
if (text !== undefined) event.text = text;
|
|
1128
|
+
const args = optStr(o["arguments"]);
|
|
1129
|
+
if (args !== undefined) event.arguments = args;
|
|
1130
|
+
const message = optStr(o["message"]);
|
|
1131
|
+
if (message !== undefined) event.message = message;
|
|
1132
|
+
return event;
|
|
1133
|
+
}
|