oira666_pi-limits-wait 0.4.2 → 0.4.4
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/package.json +1 -1
- package/src/index.ts +24 -12
package/package.json
CHANGED
package/src/index.ts
CHANGED
|
@@ -115,6 +115,16 @@ function formatModel(model: Pick<Model<Api>, "provider" | "id">): string {
|
|
|
115
115
|
return `${model.provider}/${model.id}`;
|
|
116
116
|
}
|
|
117
117
|
|
|
118
|
+
function isInternalSyntheticModel(model: Pick<Model<Api>, "provider" | "id">): boolean {
|
|
119
|
+
return model.provider.startsWith("pi-") || model.id.startsWith("synthetic-");
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
function isFallbackEligibleModel(model: Model<Api>): boolean {
|
|
123
|
+
if (isInternalSyntheticModel(model)) return false;
|
|
124
|
+
const key = modelKey(model);
|
|
125
|
+
return primaryModel ? key === modelKey(primaryModel) || fallbackModels.some((entry) => modelKey(entry.model) === key) : true;
|
|
126
|
+
}
|
|
127
|
+
|
|
118
128
|
function isThinkingLevel(value: unknown): value is ThinkingLevel {
|
|
119
129
|
return ["off", "minimal", "low", "medium", "high", "xhigh"].includes(String(value));
|
|
120
130
|
}
|
|
@@ -626,7 +636,7 @@ type StreamSimpleFn = (
|
|
|
626
636
|
model: Model<Api>,
|
|
627
637
|
context: Context,
|
|
628
638
|
options?: SimpleStreamOptions,
|
|
629
|
-
) => AssistantMessageEventStream
|
|
639
|
+
) => AssistantMessageEventStream | Promise<AssistantMessageEventStream>;
|
|
630
640
|
|
|
631
641
|
export function __configureFallbackModelsForTests(
|
|
632
642
|
models: FallbackModel[],
|
|
@@ -677,7 +687,8 @@ export function streamWithLimitsRetry(
|
|
|
677
687
|
|
|
678
688
|
void (async () => {
|
|
679
689
|
let committed = false;
|
|
680
|
-
|
|
690
|
+
const allowFallback = fallbackEnabled() && isFallbackEligibleModel(model);
|
|
691
|
+
let attempt: FallbackModel = allowFallback ? initialAttempt(model) : { model, reasoningEffort: primaryThinkingLevel };
|
|
681
692
|
|
|
682
693
|
const flush = (buffer: AssistantMessageEvent[]) => {
|
|
683
694
|
for (const event of buffer) output.push(event);
|
|
@@ -693,7 +704,7 @@ export function streamWithLimitsRetry(
|
|
|
693
704
|
|
|
694
705
|
try {
|
|
695
706
|
try {
|
|
696
|
-
const attemptOptions =
|
|
707
|
+
const attemptOptions = allowFallback
|
|
697
708
|
? await optionsForModel(model, attempt, options)
|
|
698
709
|
: options;
|
|
699
710
|
const attemptDelegate = attempt.model.api === model.api
|
|
@@ -701,7 +712,7 @@ export function streamWithLimitsRetry(
|
|
|
701
712
|
: builtinStreamSimpleByApi.get(attempt.model.api)
|
|
702
713
|
?? getApiProviders().find((provider) => provider.api === attempt.model.api)?.streamSimple;
|
|
703
714
|
if (!attemptDelegate) throw new Error(`No stream handler registered for API ${attempt.model.api}.`);
|
|
704
|
-
const inner = attemptDelegate(attempt.model, context, attemptOptions);
|
|
715
|
+
const inner = await attemptDelegate(attempt.model, context, attemptOptions);
|
|
705
716
|
for await (const event of inner) {
|
|
706
717
|
if (!committed) {
|
|
707
718
|
if (event.type === "error") {
|
|
@@ -709,7 +720,7 @@ export function streamWithLimitsRetry(
|
|
|
709
720
|
retryable = !options?.signal?.aborted ? getRetryableError(errMsg) : undefined;
|
|
710
721
|
if (retryable) break;
|
|
711
722
|
|
|
712
|
-
if (
|
|
723
|
+
if (allowFallback) {
|
|
713
724
|
nonRetryableError = { message: errMsg, event };
|
|
714
725
|
break;
|
|
715
726
|
}
|
|
@@ -732,7 +743,7 @@ export function streamWithLimitsRetry(
|
|
|
732
743
|
}
|
|
733
744
|
|
|
734
745
|
// First non-start, non-error event means this attempt is real.
|
|
735
|
-
if (
|
|
746
|
+
if (allowFallback) await switchPiModel(attempt);
|
|
736
747
|
if (buffer.length > 0) {
|
|
737
748
|
flush(buffer);
|
|
738
749
|
} else {
|
|
@@ -758,7 +769,7 @@ export function streamWithLimitsRetry(
|
|
|
758
769
|
const errMsg = err instanceof Error ? err.message : String(err);
|
|
759
770
|
retryable = !options?.signal?.aborted ? getRetryableError(errMsg) : undefined;
|
|
760
771
|
if (!retryable) {
|
|
761
|
-
if (
|
|
772
|
+
if (allowFallback && !options?.signal?.aborted) {
|
|
762
773
|
nonRetryableError = { message: errMsg };
|
|
763
774
|
} else {
|
|
764
775
|
if (!committed) {
|
|
@@ -788,7 +799,7 @@ export function streamWithLimitsRetry(
|
|
|
788
799
|
}
|
|
789
800
|
|
|
790
801
|
if (nonRetryableError) {
|
|
791
|
-
if (
|
|
802
|
+
if (allowFallback && !committed) {
|
|
792
803
|
rememberNonRetryableFailure(attempt.model, nonRetryableError.message);
|
|
793
804
|
const next = nextAvailableCandidate(attempt.model);
|
|
794
805
|
if (next) {
|
|
@@ -843,7 +854,7 @@ export function streamWithLimitsRetry(
|
|
|
843
854
|
return;
|
|
844
855
|
}
|
|
845
856
|
|
|
846
|
-
if (
|
|
857
|
+
if (allowFallback) {
|
|
847
858
|
rememberRateLimit(attempt.model, retryable);
|
|
848
859
|
const next = nextAvailableCandidate(attempt.model);
|
|
849
860
|
if (next) {
|
|
@@ -918,22 +929,23 @@ export default function (pi: ExtensionAPI) {
|
|
|
918
929
|
suppressNextModelSelect = false;
|
|
919
930
|
return;
|
|
920
931
|
}
|
|
932
|
+
if (isInternalSyntheticModel(event.model)) return;
|
|
921
933
|
primaryModel = event.model;
|
|
922
934
|
primaryThinkingLevel = pi.getThinkingLevel();
|
|
923
935
|
});
|
|
924
936
|
|
|
925
937
|
pi.on("before_agent_start", (event, ctx) => {
|
|
926
938
|
sharedCtx = ctx;
|
|
927
|
-
primaryModel
|
|
939
|
+
if (!primaryModel && ctx.model && !isInternalSyntheticModel(ctx.model)) primaryModel = ctx.model;
|
|
928
940
|
primaryThinkingLevel ??= pi.getThinkingLevel();
|
|
929
941
|
loadFallbackSettings(ctx);
|
|
930
942
|
|
|
931
943
|
// Some extensions may register providers after this extension loads. Wrap
|
|
932
944
|
// any APIs that exist by the time an agent starts too.
|
|
933
945
|
for (const model of ctx.modelRegistry.getAll()) {
|
|
934
|
-
registerWrappedApi(pi, model.api);
|
|
946
|
+
if (!isInternalSyntheticModel(model)) registerWrappedApi(pi, model.api);
|
|
935
947
|
}
|
|
936
|
-
if (ctx.model) registerWrappedApi(pi, ctx.model.api);
|
|
948
|
+
if (ctx.model && !isInternalSyntheticModel(ctx.model)) registerWrappedApi(pi, ctx.model.api);
|
|
937
949
|
|
|
938
950
|
// Anthropic subscription/OAuth requests identify as Claude Code, not Pi.
|
|
939
951
|
// Check the session-wide Anthropic OAuth configuration rather than only the
|