extrait 0.4.0 → 0.5.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +20 -0
- package/dist/index.cjs +276 -192
- package/dist/index.d.ts +2 -2
- package/dist/index.js +258 -184
- package/dist/prompt.d.ts +2 -0
- package/dist/types.d.ts +9 -3
- package/package.json +9 -3
package/dist/index.js
CHANGED
|
@@ -697,45 +697,38 @@ function unwrap(schema) {
|
|
|
697
697
|
let optional = false;
|
|
698
698
|
let nullable = false;
|
|
699
699
|
while (true) {
|
|
700
|
-
const typeName = current?._def?.
|
|
700
|
+
const typeName = current?._def?.type;
|
|
701
701
|
if (!typeName) {
|
|
702
702
|
break;
|
|
703
703
|
}
|
|
704
|
-
if (typeName === "
|
|
704
|
+
if (typeName === "optional") {
|
|
705
705
|
optional = true;
|
|
706
706
|
current = current._def?.innerType ?? current;
|
|
707
707
|
continue;
|
|
708
708
|
}
|
|
709
|
-
if (typeName === "
|
|
709
|
+
if (typeName === "default") {
|
|
710
710
|
optional = true;
|
|
711
711
|
current = current._def?.innerType ?? current;
|
|
712
712
|
continue;
|
|
713
713
|
}
|
|
714
|
-
if (typeName === "
|
|
714
|
+
if (typeName === "nullable") {
|
|
715
715
|
nullable = true;
|
|
716
716
|
current = current._def?.innerType ?? current;
|
|
717
717
|
continue;
|
|
718
718
|
}
|
|
719
|
-
if (typeName === "
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
}
|
|
727
|
-
if (typeName === "ZodCatch") {
|
|
728
|
-
current = current._def?.innerType ?? current;
|
|
719
|
+
if (typeName === "pipe") {
|
|
720
|
+
const outType = current._def?.out?._def?.type;
|
|
721
|
+
if (outType === "transform") {
|
|
722
|
+
current = current._def?.in ?? current;
|
|
723
|
+
} else {
|
|
724
|
+
current = current._def?.out ?? current;
|
|
725
|
+
}
|
|
729
726
|
continue;
|
|
730
727
|
}
|
|
731
|
-
if (typeName === "
|
|
728
|
+
if (typeName === "catch" || typeName === "readonly") {
|
|
732
729
|
current = current._def?.innerType ?? current;
|
|
733
730
|
continue;
|
|
734
731
|
}
|
|
735
|
-
if (typeName === "ZodPipeline") {
|
|
736
|
-
current = current._def?.out ?? current;
|
|
737
|
-
continue;
|
|
738
|
-
}
|
|
739
732
|
break;
|
|
740
733
|
}
|
|
741
734
|
return {
|
|
@@ -749,81 +742,74 @@ function formatCore(schema, depth, seen) {
|
|
|
749
742
|
return "unknown";
|
|
750
743
|
}
|
|
751
744
|
seen.add(schema);
|
|
752
|
-
const typeName = schema?._def?.
|
|
745
|
+
const typeName = schema?._def?.type;
|
|
753
746
|
switch (typeName) {
|
|
754
|
-
case "
|
|
747
|
+
case "string":
|
|
755
748
|
return "string";
|
|
756
|
-
case "
|
|
749
|
+
case "number":
|
|
757
750
|
return isIntegerNumber(schema) ? "int" : "number";
|
|
758
|
-
case "
|
|
751
|
+
case "boolean":
|
|
759
752
|
return "boolean";
|
|
760
|
-
case "
|
|
753
|
+
case "bigint":
|
|
761
754
|
return "bigint";
|
|
762
|
-
case "
|
|
755
|
+
case "date":
|
|
763
756
|
return "Date";
|
|
764
|
-
case "
|
|
757
|
+
case "undefined":
|
|
765
758
|
return "undefined";
|
|
766
|
-
case "
|
|
759
|
+
case "null":
|
|
767
760
|
return "null";
|
|
768
|
-
case "
|
|
761
|
+
case "any":
|
|
769
762
|
return "any";
|
|
770
|
-
case "
|
|
763
|
+
case "unknown":
|
|
771
764
|
return "unknown";
|
|
772
|
-
case "
|
|
765
|
+
case "never":
|
|
773
766
|
return "never";
|
|
774
|
-
case "
|
|
767
|
+
case "void":
|
|
775
768
|
return "void";
|
|
776
|
-
case "
|
|
777
|
-
const value = schema._def?.
|
|
769
|
+
case "literal": {
|
|
770
|
+
const value = schema._def?.values?.[0];
|
|
778
771
|
return JSON.stringify(value);
|
|
779
772
|
}
|
|
780
|
-
case "
|
|
781
|
-
const
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
const values = Object.values(schema._def?.values ?? {});
|
|
786
|
-
const unique = [...new Set(values.filter((value) => typeof value !== "string" || Number.isNaN(Number(value))))];
|
|
787
|
-
return unique.map((value) => JSON.stringify(value)).join(" | ") || "string";
|
|
773
|
+
case "enum": {
|
|
774
|
+
const entries = schema._def?.entries;
|
|
775
|
+
const values = Object.values(entries ?? {});
|
|
776
|
+
const unique = [...new Set(values.filter((v) => typeof v !== "string" || Number.isNaN(Number(v))))];
|
|
777
|
+
return unique.map((v) => JSON.stringify(v)).join(" | ") || "string";
|
|
788
778
|
}
|
|
789
|
-
case "
|
|
790
|
-
const inner = formatType(schema._def?.
|
|
779
|
+
case "array": {
|
|
780
|
+
const inner = formatType(schema._def?.element ?? schema, depth, seen);
|
|
791
781
|
return requiresParentheses(inner) ? `(${inner})[]` : `${inner}[]`;
|
|
792
782
|
}
|
|
793
|
-
case "
|
|
783
|
+
case "tuple": {
|
|
794
784
|
const items = (schema._def?.items ?? []).map((item) => formatType(item, depth, seen));
|
|
795
785
|
return `[${items.join(", ")}]`;
|
|
796
786
|
}
|
|
797
|
-
case "
|
|
787
|
+
case "union": {
|
|
798
788
|
const options = (schema._def?.options ?? []).map((option) => formatType(option, depth, seen));
|
|
799
789
|
return options.join(" | ") || "unknown";
|
|
800
790
|
}
|
|
801
|
-
case "
|
|
802
|
-
const options = Array.from((schema._def?.options ?? new Map).values()).map((option) => formatType(option, depth, seen));
|
|
803
|
-
return options.join(" | ") || "unknown";
|
|
804
|
-
}
|
|
805
|
-
case "ZodIntersection": {
|
|
791
|
+
case "intersection": {
|
|
806
792
|
const left = formatType(schema._def?.left ?? schema, depth, seen);
|
|
807
793
|
const right = formatType(schema._def?.right ?? schema, depth, seen);
|
|
808
794
|
return `${left} & ${right}`;
|
|
809
795
|
}
|
|
810
|
-
case "
|
|
796
|
+
case "record": {
|
|
811
797
|
const keyType = formatType(schema._def?.keyType ?? schema, depth, seen);
|
|
812
798
|
const valueType = formatType(schema._def?.valueType ?? schema, depth, seen);
|
|
813
799
|
return `Record<${keyType}, ${valueType}>`;
|
|
814
800
|
}
|
|
815
|
-
case "
|
|
801
|
+
case "map": {
|
|
816
802
|
const keyType = formatType(schema._def?.keyType ?? schema, depth, seen);
|
|
817
803
|
const valueType = formatType(schema._def?.valueType ?? schema, depth, seen);
|
|
818
804
|
return `Map<${keyType}, ${valueType}>`;
|
|
819
805
|
}
|
|
820
|
-
case "
|
|
806
|
+
case "set": {
|
|
821
807
|
const valueType = formatType(schema._def?.valueType ?? schema, depth, seen);
|
|
822
808
|
return `Set<${valueType}>`;
|
|
823
809
|
}
|
|
824
|
-
case "
|
|
810
|
+
case "object":
|
|
825
811
|
return formatObject(schema, depth, seen);
|
|
826
|
-
case "
|
|
812
|
+
case "lazy":
|
|
827
813
|
return "unknown";
|
|
828
814
|
default:
|
|
829
815
|
return "unknown";
|
|
@@ -859,40 +845,28 @@ function requiresParentheses(typeText) {
|
|
|
859
845
|
}
|
|
860
846
|
function isIntegerNumber(schema) {
|
|
861
847
|
const checks = schema._def?.checks ?? [];
|
|
862
|
-
return checks.some((check) => check.
|
|
848
|
+
return checks.some((check) => check.isInt === true);
|
|
863
849
|
}
|
|
864
850
|
function readSchemaDescription(schema) {
|
|
865
851
|
let current = schema;
|
|
866
|
-
while (current?._def?.
|
|
867
|
-
const
|
|
868
|
-
if (typeof
|
|
869
|
-
return sanitizeDescription(
|
|
870
|
-
}
|
|
871
|
-
const fallback = current.description;
|
|
872
|
-
if (typeof fallback === "string" && fallback.trim().length > 0) {
|
|
873
|
-
return sanitizeDescription(fallback);
|
|
852
|
+
while (current?._def?.type) {
|
|
853
|
+
const desc = current.description;
|
|
854
|
+
if (typeof desc === "string" && desc.trim().length > 0) {
|
|
855
|
+
return sanitizeDescription(desc);
|
|
874
856
|
}
|
|
875
|
-
const typeName = current._def.
|
|
876
|
-
if (typeName === "
|
|
857
|
+
const typeName = current._def.type;
|
|
858
|
+
if (typeName === "optional" || typeName === "default" || typeName === "nullable") {
|
|
877
859
|
current = current._def.innerType ?? current;
|
|
878
860
|
continue;
|
|
879
861
|
}
|
|
880
|
-
if (typeName === "
|
|
881
|
-
current = current._def.
|
|
862
|
+
if (typeName === "pipe") {
|
|
863
|
+
current = current._def.in ?? current;
|
|
882
864
|
continue;
|
|
883
865
|
}
|
|
884
|
-
if (typeName === "
|
|
885
|
-
current = current._def.type ?? current;
|
|
886
|
-
continue;
|
|
887
|
-
}
|
|
888
|
-
if (typeName === "ZodCatch" || typeName === "ZodReadonly") {
|
|
866
|
+
if (typeName === "catch" || typeName === "readonly") {
|
|
889
867
|
current = current._def.innerType ?? current;
|
|
890
868
|
continue;
|
|
891
869
|
}
|
|
892
|
-
if (typeName === "ZodPipeline") {
|
|
893
|
-
current = current._def.out ?? current;
|
|
894
|
-
continue;
|
|
895
|
-
}
|
|
896
870
|
break;
|
|
897
871
|
}
|
|
898
872
|
return;
|
|
@@ -2177,6 +2151,12 @@ function buildHeaders(options) {
|
|
|
2177
2151
|
};
|
|
2178
2152
|
}
|
|
2179
2153
|
function buildMessages(request) {
|
|
2154
|
+
if (Array.isArray(request.messages) && request.messages.length > 0) {
|
|
2155
|
+
return request.messages.map((message) => toOpenAIMessage(message));
|
|
2156
|
+
}
|
|
2157
|
+
if (typeof request.prompt !== "string" || request.prompt.trim().length === 0) {
|
|
2158
|
+
throw new Error("LLMRequest must include a prompt or messages.");
|
|
2159
|
+
}
|
|
2180
2160
|
const messages = [];
|
|
2181
2161
|
if (request.systemPrompt) {
|
|
2182
2162
|
messages.push({ role: "system", content: request.systemPrompt });
|
|
@@ -2188,18 +2168,16 @@ function buildResponsesInput(request) {
|
|
|
2188
2168
|
if (isRecord2(request.body) && "input" in request.body) {
|
|
2189
2169
|
return request.body.input;
|
|
2190
2170
|
}
|
|
2191
|
-
|
|
2192
|
-
|
|
2193
|
-
input.push({
|
|
2194
|
-
role: "system",
|
|
2195
|
-
content: request.systemPrompt
|
|
2196
|
-
});
|
|
2171
|
+
if (Array.isArray(request.messages) && request.messages.length > 0) {
|
|
2172
|
+
return request.messages.map((message) => toOpenAIMessage(message));
|
|
2197
2173
|
}
|
|
2198
|
-
|
|
2199
|
-
|
|
2200
|
-
|
|
2201
|
-
|
|
2202
|
-
|
|
2174
|
+
return buildMessages(request);
|
|
2175
|
+
}
|
|
2176
|
+
function toOpenAIMessage(message) {
|
|
2177
|
+
return {
|
|
2178
|
+
role: message.role,
|
|
2179
|
+
content: message.content
|
|
2180
|
+
};
|
|
2203
2181
|
}
|
|
2204
2182
|
function toResponsesTools(tools) {
|
|
2205
2183
|
if (!Array.isArray(tools) || tools.length === 0) {
|
|
@@ -2611,6 +2589,7 @@ function createAnthropicCompatibleAdapter(options) {
|
|
|
2611
2589
|
if (hasMCPClients(request.mcpClients)) {
|
|
2612
2590
|
return streamWithMCPToolLoop(options, fetcher, path, request, callbacks);
|
|
2613
2591
|
}
|
|
2592
|
+
const input = resolveAnthropicInput(request);
|
|
2614
2593
|
const response = await fetcher(buildURL(options.baseURL, path), {
|
|
2615
2594
|
method: "POST",
|
|
2616
2595
|
headers: buildHeaders2(options),
|
|
@@ -2618,8 +2597,8 @@ function createAnthropicCompatibleAdapter(options) {
|
|
|
2618
2597
|
...options.defaultBody,
|
|
2619
2598
|
...request.body,
|
|
2620
2599
|
model: options.model,
|
|
2621
|
-
system:
|
|
2622
|
-
messages:
|
|
2600
|
+
system: input.systemPrompt,
|
|
2601
|
+
messages: input.messages,
|
|
2623
2602
|
temperature: request.temperature,
|
|
2624
2603
|
max_tokens: resolveMaxTokens(request.maxTokens, options.defaultMaxTokens),
|
|
2625
2604
|
stream: true
|
|
@@ -2670,6 +2649,7 @@ function createAnthropicCompatibleAdapter(options) {
|
|
|
2670
2649
|
};
|
|
2671
2650
|
}
|
|
2672
2651
|
async function completePassThrough(options, fetcher, path, request) {
|
|
2652
|
+
const input = resolveAnthropicInput(request);
|
|
2673
2653
|
const response = await fetcher(buildURL(options.baseURL, path), {
|
|
2674
2654
|
method: "POST",
|
|
2675
2655
|
headers: buildHeaders2(options),
|
|
@@ -2677,8 +2657,8 @@ async function completePassThrough(options, fetcher, path, request) {
|
|
|
2677
2657
|
...options.defaultBody,
|
|
2678
2658
|
...request.body,
|
|
2679
2659
|
model: options.model,
|
|
2680
|
-
system:
|
|
2681
|
-
messages:
|
|
2660
|
+
system: input.systemPrompt,
|
|
2661
|
+
messages: input.messages,
|
|
2682
2662
|
temperature: request.temperature,
|
|
2683
2663
|
max_tokens: resolveMaxTokens(request.maxTokens, options.defaultMaxTokens),
|
|
2684
2664
|
stream: false
|
|
@@ -2705,7 +2685,8 @@ async function completePassThrough(options, fetcher, path, request) {
|
|
|
2705
2685
|
}
|
|
2706
2686
|
async function completeWithMCPToolLoop(options, fetcher, path, request) {
|
|
2707
2687
|
const maxToolRounds = normalizeMaxToolRounds(request.maxToolRounds ?? options.defaultMaxToolRounds);
|
|
2708
|
-
|
|
2688
|
+
const input = resolveAnthropicInput(request);
|
|
2689
|
+
let messages = input.messages;
|
|
2709
2690
|
let aggregatedUsage;
|
|
2710
2691
|
let finishReason;
|
|
2711
2692
|
let lastPayload;
|
|
@@ -2721,7 +2702,7 @@ async function completeWithMCPToolLoop(options, fetcher, path, request) {
|
|
|
2721
2702
|
...options.defaultBody,
|
|
2722
2703
|
...request.body,
|
|
2723
2704
|
model: options.model,
|
|
2724
|
-
system:
|
|
2705
|
+
system: input.systemPrompt,
|
|
2725
2706
|
messages,
|
|
2726
2707
|
temperature: request.temperature,
|
|
2727
2708
|
max_tokens: resolveMaxTokens(request.maxTokens, options.defaultMaxTokens),
|
|
@@ -2788,7 +2769,8 @@ async function completeWithMCPToolLoop(options, fetcher, path, request) {
|
|
|
2788
2769
|
}
|
|
2789
2770
|
async function streamWithMCPToolLoop(options, fetcher, path, request, callbacks) {
|
|
2790
2771
|
const maxToolRounds = normalizeMaxToolRounds(request.maxToolRounds ?? options.defaultMaxToolRounds);
|
|
2791
|
-
|
|
2772
|
+
const input = resolveAnthropicInput(request);
|
|
2773
|
+
let messages = input.messages;
|
|
2792
2774
|
let aggregatedUsage;
|
|
2793
2775
|
let finishReason;
|
|
2794
2776
|
let lastPayload;
|
|
@@ -2805,7 +2787,7 @@ async function streamWithMCPToolLoop(options, fetcher, path, request, callbacks)
|
|
|
2805
2787
|
...options.defaultBody,
|
|
2806
2788
|
...request.body,
|
|
2807
2789
|
model: options.model,
|
|
2808
|
-
system:
|
|
2790
|
+
system: input.systemPrompt,
|
|
2809
2791
|
messages,
|
|
2810
2792
|
temperature: request.temperature,
|
|
2811
2793
|
max_tokens: resolveMaxTokens(request.maxTokens, options.defaultMaxTokens),
|
|
@@ -2916,6 +2898,59 @@ function buildHeaders2(options) {
|
|
|
2916
2898
|
...options.headers
|
|
2917
2899
|
};
|
|
2918
2900
|
}
|
|
2901
|
+
function resolveAnthropicInput(request) {
|
|
2902
|
+
if (Array.isArray(request.messages) && request.messages.length > 0) {
|
|
2903
|
+
return toAnthropicInput(request.messages);
|
|
2904
|
+
}
|
|
2905
|
+
if (typeof request.prompt !== "string" || request.prompt.trim().length === 0) {
|
|
2906
|
+
throw new Error("LLMRequest must include a prompt or messages.");
|
|
2907
|
+
}
|
|
2908
|
+
return {
|
|
2909
|
+
systemPrompt: request.systemPrompt,
|
|
2910
|
+
messages: [{ role: "user", content: request.prompt }]
|
|
2911
|
+
};
|
|
2912
|
+
}
|
|
2913
|
+
function toAnthropicInput(messages) {
|
|
2914
|
+
const systemParts = [];
|
|
2915
|
+
const normalizedMessages = [];
|
|
2916
|
+
let sawNonSystem = false;
|
|
2917
|
+
for (const message of messages) {
|
|
2918
|
+
if (message.role === "system") {
|
|
2919
|
+
if (sawNonSystem) {
|
|
2920
|
+
throw new Error('Anthropic-compatible messages only support "system" turns at the beginning.');
|
|
2921
|
+
}
|
|
2922
|
+
systemParts.push(stringifyAnthropicSystemContent(message.content));
|
|
2923
|
+
continue;
|
|
2924
|
+
}
|
|
2925
|
+
sawNonSystem = true;
|
|
2926
|
+
normalizedMessages.push({
|
|
2927
|
+
role: message.role,
|
|
2928
|
+
content: message.content
|
|
2929
|
+
});
|
|
2930
|
+
}
|
|
2931
|
+
if (normalizedMessages.length === 0) {
|
|
2932
|
+
throw new Error("Anthropic-compatible requests require at least one non-system message.");
|
|
2933
|
+
}
|
|
2934
|
+
return {
|
|
2935
|
+
systemPrompt: systemParts.length > 0 ? systemParts.join(`
|
|
2936
|
+
|
|
2937
|
+
`) : undefined,
|
|
2938
|
+
messages: normalizedMessages
|
|
2939
|
+
};
|
|
2940
|
+
}
|
|
2941
|
+
function stringifyAnthropicSystemContent(content) {
|
|
2942
|
+
if (typeof content === "string") {
|
|
2943
|
+
return content;
|
|
2944
|
+
}
|
|
2945
|
+
if (content === null || content === undefined) {
|
|
2946
|
+
return "";
|
|
2947
|
+
}
|
|
2948
|
+
try {
|
|
2949
|
+
return JSON.stringify(content, null, 2) ?? "";
|
|
2950
|
+
} catch {
|
|
2951
|
+
return String(content);
|
|
2952
|
+
}
|
|
2953
|
+
}
|
|
2919
2954
|
function resolveMaxTokens(value, fallback) {
|
|
2920
2955
|
const requested = toFiniteNumber(value);
|
|
2921
2956
|
if (requested !== undefined && requested > 0) {
|
|
@@ -3802,17 +3837,15 @@ async function structured(adapter, schemaOrOptions, promptInput, callOptions) {
|
|
|
3802
3837
|
const useOutdent = normalized.outdent ?? true;
|
|
3803
3838
|
const resolvedPrompt = applyPromptOutdent(resolvePrompt(normalized.prompt, { mode }), useOutdent);
|
|
3804
3839
|
const resolvedSystemPrompt = applyOutdentToOptionalPrompt(normalized.systemPrompt, useOutdent);
|
|
3805
|
-
const
|
|
3806
|
-
schemaInstruction: normalized.schemaInstruction
|
|
3807
|
-
}) : resolvedPrompt.prompt.trim();
|
|
3808
|
-
const systemPrompt = mergeSystemPrompts(resolvedPrompt.systemPrompt, resolvedSystemPrompt);
|
|
3840
|
+
const preparedPrompt = prepareStructuredPromptPayload(resolvedPrompt, resolvedSystemPrompt, normalized.schema, normalized.schemaInstruction);
|
|
3809
3841
|
const first = await executeAttempt(adapter, {
|
|
3810
|
-
prompt,
|
|
3842
|
+
prompt: preparedPrompt.prompt,
|
|
3843
|
+
messages: preparedPrompt.messages,
|
|
3811
3844
|
schema: normalized.schema,
|
|
3812
3845
|
parseOptions,
|
|
3813
3846
|
stream: streamConfig,
|
|
3814
3847
|
request: normalized.request,
|
|
3815
|
-
systemPrompt,
|
|
3848
|
+
systemPrompt: preparedPrompt.systemPrompt,
|
|
3816
3849
|
observe: normalized.observe,
|
|
3817
3850
|
debug: debugConfig,
|
|
3818
3851
|
attemptNumber: 1,
|
|
@@ -3872,7 +3905,7 @@ async function structured(adapter, schemaOrOptions, promptInput, callOptions) {
|
|
|
3872
3905
|
parseOptions,
|
|
3873
3906
|
stream: streamConfig,
|
|
3874
3907
|
request: normalized.request,
|
|
3875
|
-
systemPrompt,
|
|
3908
|
+
systemPrompt: preparedPrompt.systemPrompt,
|
|
3876
3909
|
observe: normalized.observe,
|
|
3877
3910
|
debug: debugConfig,
|
|
3878
3911
|
attemptNumber,
|
|
@@ -3934,12 +3967,15 @@ function isPromptResolver(value) {
|
|
|
3934
3967
|
return typeof value === "object" && value !== null && "resolvePrompt" in value && typeof value.resolvePrompt === "function";
|
|
3935
3968
|
}
|
|
3936
3969
|
function normalizePromptPayload(value) {
|
|
3937
|
-
|
|
3938
|
-
|
|
3970
|
+
const prompt = typeof value.prompt === "string" ? value.prompt : undefined;
|
|
3971
|
+
const messages = Array.isArray(value.messages) ? value.messages.filter(isLLMMessage) : undefined;
|
|
3972
|
+
if ((!prompt || prompt.trim().length === 0) && (!messages || messages.length === 0)) {
|
|
3973
|
+
throw new Error("Structured prompt payload must include a non-empty prompt or messages.");
|
|
3939
3974
|
}
|
|
3940
3975
|
return {
|
|
3941
|
-
prompt
|
|
3942
|
-
systemPrompt: typeof value.systemPrompt === "string" ? value.systemPrompt : undefined
|
|
3976
|
+
prompt,
|
|
3977
|
+
systemPrompt: typeof value.systemPrompt === "string" ? value.systemPrompt : undefined,
|
|
3978
|
+
messages: messages && messages.length > 0 ? messages.map((message) => ({ ...message })) : undefined
|
|
3943
3979
|
};
|
|
3944
3980
|
}
|
|
3945
3981
|
function applyPromptOutdent(payload, enabled) {
|
|
@@ -3947,10 +3983,24 @@ function applyPromptOutdent(payload, enabled) {
|
|
|
3947
3983
|
return payload;
|
|
3948
3984
|
}
|
|
3949
3985
|
return {
|
|
3950
|
-
prompt: structuredOutdent.string(payload.prompt),
|
|
3951
|
-
systemPrompt: applyOutdentToOptionalPrompt(payload.systemPrompt, enabled)
|
|
3986
|
+
prompt: typeof payload.prompt === "string" ? structuredOutdent.string(payload.prompt) : undefined,
|
|
3987
|
+
systemPrompt: applyOutdentToOptionalPrompt(payload.systemPrompt, enabled),
|
|
3988
|
+
messages: payload.messages?.map((message) => ({
|
|
3989
|
+
...message,
|
|
3990
|
+
content: typeof message.content === "string" ? structuredOutdent.string(message.content) : message.content
|
|
3991
|
+
}))
|
|
3952
3992
|
};
|
|
3953
3993
|
}
|
|
3994
|
+
function isLLMMessage(value) {
|
|
3995
|
+
if (typeof value !== "object" || value === null) {
|
|
3996
|
+
return false;
|
|
3997
|
+
}
|
|
3998
|
+
const candidate = value;
|
|
3999
|
+
if (candidate.role !== "system" && candidate.role !== "user" && candidate.role !== "assistant" && candidate.role !== "tool") {
|
|
4000
|
+
return false;
|
|
4001
|
+
}
|
|
4002
|
+
return "content" in candidate;
|
|
4003
|
+
}
|
|
3954
4004
|
function applyOutdentToOptionalPrompt(value, enabled) {
|
|
3955
4005
|
if (!enabled || typeof value !== "string") {
|
|
3956
4006
|
return value;
|
|
@@ -3966,6 +4016,60 @@ function mergeSystemPrompts(primary, secondary) {
|
|
|
3966
4016
|
|
|
3967
4017
|
`);
|
|
3968
4018
|
}
|
|
4019
|
+
function prepareStructuredPromptPayload(payload, systemPrompt, schema, schemaInstruction) {
|
|
4020
|
+
if (Array.isArray(payload.messages) && payload.messages.length > 0) {
|
|
4021
|
+
const messages = payload.messages.map((message) => ({ ...message }));
|
|
4022
|
+
const mergedSystemPrompt = mergeSystemPrompts(payload.systemPrompt, systemPrompt);
|
|
4023
|
+
const systemMessages = mergedSystemPrompt ? [{ role: "system", content: mergedSystemPrompt }] : [];
|
|
4024
|
+
return {
|
|
4025
|
+
messages: injectStructuredFormatIntoMessages([...systemMessages, ...messages], schema, schemaInstruction)
|
|
4026
|
+
};
|
|
4027
|
+
}
|
|
4028
|
+
const resolvedPrompt = payload.prompt?.trim();
|
|
4029
|
+
if (!resolvedPrompt) {
|
|
4030
|
+
throw new Error("Structured prompt payload must include a non-empty prompt or messages.");
|
|
4031
|
+
}
|
|
4032
|
+
return {
|
|
4033
|
+
prompt: shouldInjectFormat(resolvedPrompt, schemaInstruction) ? formatPrompt(schema, resolvedPrompt, {
|
|
4034
|
+
schemaInstruction
|
|
4035
|
+
}) : resolvedPrompt,
|
|
4036
|
+
systemPrompt: mergeSystemPrompts(payload.systemPrompt, systemPrompt)
|
|
4037
|
+
};
|
|
4038
|
+
}
|
|
4039
|
+
function injectStructuredFormatIntoMessages(messages, schema, schemaInstruction) {
|
|
4040
|
+
const lastUserIndex = findLastUserMessageIndex(messages);
|
|
4041
|
+
if (lastUserIndex === -1) {
|
|
4042
|
+
throw new Error("Structured prompts with messages must include at least one user message.");
|
|
4043
|
+
}
|
|
4044
|
+
const target = messages[lastUserIndex];
|
|
4045
|
+
const content = typeof target?.content === "string" ? target.content.trim() : stringifyPromptContent(target?.content);
|
|
4046
|
+
const formatted = shouldInjectFormat(content, schemaInstruction) ? formatPrompt(schema, content, { schemaInstruction }) : content.trim();
|
|
4047
|
+
return messages.map((message, index) => index === lastUserIndex ? {
|
|
4048
|
+
...message,
|
|
4049
|
+
content: formatted
|
|
4050
|
+
} : message);
|
|
4051
|
+
}
|
|
4052
|
+
function findLastUserMessageIndex(messages) {
|
|
4053
|
+
for (let index = messages.length - 1;index >= 0; index -= 1) {
|
|
4054
|
+
if (messages[index]?.role === "user") {
|
|
4055
|
+
return index;
|
|
4056
|
+
}
|
|
4057
|
+
}
|
|
4058
|
+
return -1;
|
|
4059
|
+
}
|
|
4060
|
+
function stringifyPromptContent(content) {
|
|
4061
|
+
if (typeof content === "string") {
|
|
4062
|
+
return content;
|
|
4063
|
+
}
|
|
4064
|
+
if (content === null || content === undefined) {
|
|
4065
|
+
return "";
|
|
4066
|
+
}
|
|
4067
|
+
try {
|
|
4068
|
+
return JSON.stringify(content, null, 2) ?? "";
|
|
4069
|
+
} catch {
|
|
4070
|
+
return String(content);
|
|
4071
|
+
}
|
|
4072
|
+
}
|
|
3969
4073
|
function shouldInjectFormat(prompt, schemaInstruction) {
|
|
3970
4074
|
const instruction = resolveSchemaInstruction(schemaInstruction);
|
|
3971
4075
|
return !prompt.trimStart().startsWith(instruction);
|
|
@@ -4144,6 +4248,7 @@ function normalizeDebugConfig(option) {
|
|
|
4144
4248
|
async function executeAttempt(adapter, input) {
|
|
4145
4249
|
const response = await callModel(adapter, {
|
|
4146
4250
|
prompt: input.prompt,
|
|
4251
|
+
messages: input.messages,
|
|
4147
4252
|
systemPrompt: input.systemPrompt,
|
|
4148
4253
|
request: input.request,
|
|
4149
4254
|
stream: input.stream,
|
|
@@ -4181,6 +4286,7 @@ async function executeAttempt(adapter, input) {
|
|
|
4181
4286
|
async function callModel(adapter, options) {
|
|
4182
4287
|
const requestPayload = {
|
|
4183
4288
|
prompt: options.prompt,
|
|
4289
|
+
messages: options.messages,
|
|
4184
4290
|
systemPrompt: options.systemPrompt,
|
|
4185
4291
|
temperature: options.request?.temperature,
|
|
4186
4292
|
maxTokens: options.request?.maxTokens,
|
|
@@ -4491,6 +4597,7 @@ function emitObserve(observe, event) {
|
|
|
4491
4597
|
}
|
|
4492
4598
|
function emitDebugRequest(config, input) {
|
|
4493
4599
|
const requestBody = input.requestPayload.body !== undefined ? JSON.stringify(input.requestPayload.body, null, 2) : "(none)";
|
|
4600
|
+
const requestMessages = input.requestPayload.messages !== undefined ? JSON.stringify(input.requestPayload.messages, null, 2) : "(none)";
|
|
4494
4601
|
const lines = [
|
|
4495
4602
|
color(config, title(config, [
|
|
4496
4603
|
"[structured][request]",
|
|
@@ -4504,7 +4611,9 @@ function emitDebugRequest(config, input) {
|
|
|
4504
4611
|
`stream=${input.stream}`
|
|
4505
4612
|
].join(" ")),
|
|
4506
4613
|
color(config, "prompt:", "yellow"),
|
|
4507
|
-
input.requestPayload.prompt,
|
|
4614
|
+
input.requestPayload.prompt ?? "(none)",
|
|
4615
|
+
color(config, "messages:", "yellow"),
|
|
4616
|
+
requestMessages,
|
|
4508
4617
|
color(config, "systemPrompt:", "yellow"),
|
|
4509
4618
|
input.requestPayload.systemPrompt ?? "(none)",
|
|
4510
4619
|
color(config, "request.body:", "yellow"),
|
|
@@ -4725,35 +4834,28 @@ function toPromptMessage(input, values) {
|
|
|
4725
4834
|
}
|
|
4726
4835
|
return renderPromptTemplate(input, values);
|
|
4727
4836
|
}
|
|
4728
|
-
function joinMessages(messages) {
|
|
4729
|
-
return messages.join(`
|
|
4730
|
-
|
|
4731
|
-
`);
|
|
4732
|
-
}
|
|
4733
4837
|
|
|
4734
4838
|
class PromptMessageBuilderImpl {
|
|
4735
|
-
|
|
4736
|
-
userMessages = [];
|
|
4839
|
+
messages = [];
|
|
4737
4840
|
system(input, ...values) {
|
|
4738
|
-
|
|
4739
|
-
if (message.length > 0) {
|
|
4740
|
-
this.systemMessages.push(message);
|
|
4741
|
-
}
|
|
4742
|
-
return this;
|
|
4841
|
+
return this.pushMessage("system", input, values);
|
|
4743
4842
|
}
|
|
4744
4843
|
user(input, ...values) {
|
|
4844
|
+
return this.pushMessage("user", input, values);
|
|
4845
|
+
}
|
|
4846
|
+
assistant(input, ...values) {
|
|
4847
|
+
return this.pushMessage("assistant", input, values);
|
|
4848
|
+
}
|
|
4849
|
+
pushMessage(role, input, values) {
|
|
4745
4850
|
const message = toPromptMessage(input, values);
|
|
4746
4851
|
if (message.length > 0) {
|
|
4747
|
-
this.
|
|
4852
|
+
this.messages.push({ role, content: message });
|
|
4748
4853
|
}
|
|
4749
4854
|
return this;
|
|
4750
4855
|
}
|
|
4751
4856
|
build() {
|
|
4752
|
-
const prompt = joinMessages(this.userMessages);
|
|
4753
|
-
const systemPrompt = joinMessages(this.systemMessages);
|
|
4754
4857
|
return {
|
|
4755
|
-
|
|
4756
|
-
systemPrompt: systemPrompt.length > 0 ? systemPrompt : undefined
|
|
4858
|
+
messages: this.messages.map((message) => ({ ...message }))
|
|
4757
4859
|
};
|
|
4758
4860
|
}
|
|
4759
4861
|
resolvePrompt(_context) {
|
|
@@ -4863,8 +4965,8 @@ function inferSchemaExample(schema) {
|
|
|
4863
4965
|
}
|
|
4864
4966
|
function getObjectShape(schema) {
|
|
4865
4967
|
const unwrapped = unwrap2(schema).schema;
|
|
4866
|
-
const typeName = unwrapped._def?.
|
|
4867
|
-
if (typeName !== "
|
|
4968
|
+
const typeName = unwrapped._def?.type;
|
|
4969
|
+
if (typeName !== "object") {
|
|
4868
4970
|
return null;
|
|
4869
4971
|
}
|
|
4870
4972
|
const rawShape = unwrapped._def?.shape;
|
|
@@ -4875,33 +4977,25 @@ function getObjectShape(schema) {
|
|
|
4875
4977
|
}
|
|
4876
4978
|
function readDefaultValue(schema) {
|
|
4877
4979
|
let current = schema;
|
|
4878
|
-
while (current?._def?.
|
|
4879
|
-
const typeName = current._def.
|
|
4880
|
-
if (typeName === "
|
|
4881
|
-
|
|
4882
|
-
|
|
4883
|
-
|
|
4980
|
+
while (current?._def?.type) {
|
|
4981
|
+
const typeName = current._def.type;
|
|
4982
|
+
if (typeName === "default") {
|
|
4983
|
+
try {
|
|
4984
|
+
const raw = current._def.defaultValue;
|
|
4985
|
+
if (typeof raw === "function") {
|
|
4884
4986
|
return raw();
|
|
4885
|
-
} catch {
|
|
4886
|
-
return;
|
|
4887
4987
|
}
|
|
4988
|
+
return raw;
|
|
4989
|
+
} catch {
|
|
4990
|
+
return;
|
|
4888
4991
|
}
|
|
4889
|
-
return raw;
|
|
4890
4992
|
}
|
|
4891
|
-
if (typeName === "
|
|
4993
|
+
if (typeName === "optional" || typeName === "nullable" || typeName === "catch" || typeName === "readonly") {
|
|
4892
4994
|
current = current._def.innerType ?? current;
|
|
4893
4995
|
continue;
|
|
4894
4996
|
}
|
|
4895
|
-
if (typeName === "
|
|
4896
|
-
current = current._def.
|
|
4897
|
-
continue;
|
|
4898
|
-
}
|
|
4899
|
-
if (typeName === "ZodBranded") {
|
|
4900
|
-
current = current._def.type ?? current;
|
|
4901
|
-
continue;
|
|
4902
|
-
}
|
|
4903
|
-
if (typeName === "ZodPipeline") {
|
|
4904
|
-
current = current._def.out ?? current;
|
|
4997
|
+
if (typeName === "pipe") {
|
|
4998
|
+
current = current._def.in ?? current;
|
|
4905
4999
|
continue;
|
|
4906
5000
|
}
|
|
4907
5001
|
return;
|
|
@@ -4910,34 +5004,22 @@ function readDefaultValue(schema) {
|
|
|
4910
5004
|
}
|
|
4911
5005
|
function readSchemaDescription2(schema) {
|
|
4912
5006
|
let current = schema;
|
|
4913
|
-
while (current?._def?.
|
|
4914
|
-
const
|
|
4915
|
-
if (typeof
|
|
4916
|
-
return
|
|
5007
|
+
while (current?._def?.type) {
|
|
5008
|
+
const desc = current.description;
|
|
5009
|
+
if (typeof desc === "string" && desc.trim().length > 0) {
|
|
5010
|
+
return desc.trim();
|
|
4917
5011
|
}
|
|
4918
|
-
const
|
|
4919
|
-
if (
|
|
4920
|
-
return fallback.trim();
|
|
4921
|
-
}
|
|
4922
|
-
const typeName = current._def.typeName;
|
|
4923
|
-
if (typeName === "ZodOptional" || typeName === "ZodDefault" || typeName === "ZodNullable") {
|
|
5012
|
+
const typeName = current._def.type;
|
|
5013
|
+
if (typeName === "optional" || typeName === "default" || typeName === "nullable") {
|
|
4924
5014
|
current = current._def.innerType ?? current;
|
|
4925
5015
|
continue;
|
|
4926
5016
|
}
|
|
4927
|
-
if (typeName === "
|
|
5017
|
+
if (typeName === "catch" || typeName === "readonly") {
|
|
4928
5018
|
current = current._def.innerType ?? current;
|
|
4929
5019
|
continue;
|
|
4930
5020
|
}
|
|
4931
|
-
if (typeName === "
|
|
4932
|
-
current = current._def.
|
|
4933
|
-
continue;
|
|
4934
|
-
}
|
|
4935
|
-
if (typeName === "ZodBranded") {
|
|
4936
|
-
current = current._def.type ?? current;
|
|
4937
|
-
continue;
|
|
4938
|
-
}
|
|
4939
|
-
if (typeName === "ZodPipeline") {
|
|
4940
|
-
current = current._def.out ?? current;
|
|
5021
|
+
if (typeName === "pipe") {
|
|
5022
|
+
current = current._def.in ?? current;
|
|
4941
5023
|
continue;
|
|
4942
5024
|
}
|
|
4943
5025
|
break;
|
|
@@ -4947,27 +5029,19 @@ function readSchemaDescription2(schema) {
|
|
|
4947
5029
|
function unwrap2(schema) {
|
|
4948
5030
|
let current = schema;
|
|
4949
5031
|
let optional = false;
|
|
4950
|
-
while (current?._def?.
|
|
4951
|
-
const typeName = current._def.
|
|
4952
|
-
if (typeName === "
|
|
5032
|
+
while (current?._def?.type) {
|
|
5033
|
+
const typeName = current._def.type;
|
|
5034
|
+
if (typeName === "optional" || typeName === "default") {
|
|
4953
5035
|
optional = true;
|
|
4954
5036
|
current = current._def.innerType ?? current;
|
|
4955
5037
|
continue;
|
|
4956
5038
|
}
|
|
4957
|
-
if (typeName === "
|
|
5039
|
+
if (typeName === "nullable" || typeName === "catch" || typeName === "readonly") {
|
|
4958
5040
|
current = current._def.innerType ?? current;
|
|
4959
5041
|
continue;
|
|
4960
5042
|
}
|
|
4961
|
-
if (typeName === "
|
|
4962
|
-
current = current._def.
|
|
4963
|
-
continue;
|
|
4964
|
-
}
|
|
4965
|
-
if (typeName === "ZodBranded") {
|
|
4966
|
-
current = current._def.type ?? current;
|
|
4967
|
-
continue;
|
|
4968
|
-
}
|
|
4969
|
-
if (typeName === "ZodPipeline") {
|
|
4970
|
-
current = current._def.out ?? current;
|
|
5043
|
+
if (typeName === "pipe") {
|
|
5044
|
+
current = current._def.in ?? current;
|
|
4971
5045
|
continue;
|
|
4972
5046
|
}
|
|
4973
5047
|
break;
|