omnigateway 0.1.8 → 0.2.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/README.md +27 -33
- package/bin/omni.js +607 -78
- package/gateway.js +2877 -150
- package/package.json +1 -1
- package/public/assets/{Chip-CM9ZMdr9.js → Chip-BB_5C1Zp.js} +1 -1
- package/public/assets/Confirm-B6aAiVbT.js +4 -0
- package/public/assets/{CopyValue-WrOTcHwq.js → CopyValue-CRQDLo7k.js} +1 -1
- package/public/assets/{Field-Br6jKPz8.js → Field-uHZxl4fI.js} +1 -1
- package/public/assets/Lamp-B-5SjXbG.js +25 -0
- package/public/assets/{Meter-BzMaum0C.js → Meter-DI_BRUKt.js} +1 -1
- package/public/assets/Modal-CI6jk2D4.js +82 -0
- package/public/assets/{Rack-BFWC50ex.js → Rack-D1WJswv3.js} +8 -4
- package/public/assets/{Readout-DMJs4gYD.js → Readout-BocZ2HXP.js} +1 -1
- package/public/assets/{States-BNeCLhZn.js → States-Bbiu5cHE.js} +1 -1
- package/public/assets/{Table-nOg_lgEJ.js → Table-CdPWxYaz.js} +1 -1
- package/public/assets/Toggle-CiLC67Dw.js +39 -0
- package/public/assets/TokenBreakdown-B96iPBm9.js +28 -0
- package/public/assets/_app-BBOF6A0T.js +1 -0
- package/public/assets/{_app.accounts-BTb5vHI_.js → _app.accounts-BNkhpvaB.js} +8 -5
- package/public/assets/_app.console-Daz4aKhf.js +44 -0
- package/public/assets/_app.index-LO6d38oe.js +62 -0
- package/public/assets/{_app.keys-B-cy-2DS.js → _app.keys-kBqLqoFf.js} +3 -3
- package/public/assets/_app.logs-_wYNS47N.js +32 -0
- package/public/assets/{_app.models-BAmXHlf2.js → _app.models-Cjng8ohC.js} +5 -5
- package/public/assets/_app.settings-a0FKyQAi.js +38 -0
- package/public/assets/{_app.usage-BLrQ2hB8.js → _app.usage-D3KtgLrC.js} +9 -6
- package/public/assets/dist-C-IbPRiV.js +1 -0
- package/public/assets/index-PW6EvVh5.js +170 -0
- package/public/assets/{login-BpUl6C5b.js → login-CTvH_KAd.js} +1 -1
- package/public/assets/queries-D2o-X8Pj.js +144 -0
- package/public/assets/{trash-2-DjWP2u19.js → trash-2-BcZb-sCT.js} +1 -1
- package/public/index.html +2 -2
- package/public/assets/Lamp-DO-sRDg2.js +0 -25
- package/public/assets/Modal-lhjr949H.js +0 -82
- package/public/assets/Toggle-DYoCVD37.js +0 -42
- package/public/assets/_app-lXr06Xli.js +0 -1
- package/public/assets/_app.console-DHUClMsI.js +0 -25
- package/public/assets/_app.index-DZ--9mKU.js +0 -61
- package/public/assets/_app.logs-BQjAIT2P.js +0 -33
- package/public/assets/_app.settings-CG8bv_rm.js +0 -34
- package/public/assets/index-UAZ0O5y0.js +0 -170
- package/public/assets/queries-D_-Jj9vt.js +0 -144
package/bin/omni.js
CHANGED
|
@@ -91,9 +91,8 @@ function formatUsd(value) {
|
|
|
91
91
|
}
|
|
92
92
|
|
|
93
93
|
// apps/cli/src/run.ts
|
|
94
|
-
import { mkdirSync as mkdirSync2, writeFileSync as writeFileSync2 } from "fs";
|
|
94
|
+
import { existsSync as existsSync6, mkdirSync as mkdirSync2, readFileSync as readFileSync3, renameSync, rmSync as rmSync2, writeFileSync as writeFileSync2 } from "fs";
|
|
95
95
|
import { homedir as homedir3 } from "os";
|
|
96
|
-
import { dirname as dirname3 } from "path";
|
|
97
96
|
|
|
98
97
|
// packages/control/src/adminAuth.ts
|
|
99
98
|
import { hash, verify } from "@node-rs/argon2";
|
|
@@ -153,6 +152,11 @@ function createAdminAuth(store, opts) {
|
|
|
153
152
|
};
|
|
154
153
|
}
|
|
155
154
|
// packages/ir/src/capabilities.ts
|
|
155
|
+
var ANTHROPIC_NATIVE_TOOLS = {
|
|
156
|
+
anthropic: true,
|
|
157
|
+
openai: false,
|
|
158
|
+
kimi: false
|
|
159
|
+
};
|
|
156
160
|
var PROVIDER_CAPABILITIES = {
|
|
157
161
|
anthropic: { tools: true, images: true, reasoning: true },
|
|
158
162
|
openai: { tools: true, images: true, reasoning: true },
|
|
@@ -759,14 +763,232 @@ function parseRecord(record) {
|
|
|
759
763
|
`) };
|
|
760
764
|
}
|
|
761
765
|
|
|
766
|
+
// packages/providers/src/anthropic/tools.ts
|
|
767
|
+
var COMMON = ["cache_control", "strict", "defer_loading", "allowed_callers"];
|
|
768
|
+
var COMMON_WITH_EXAMPLES = [...COMMON, "input_examples"];
|
|
769
|
+
var searchDomains = ["max_uses", "allowed_domains", "blocked_domains"];
|
|
770
|
+
var ANTHROPIC_TOOL_SPECS = {
|
|
771
|
+
web_search_20250305: {
|
|
772
|
+
family: "webSearch",
|
|
773
|
+
name: "web_search",
|
|
774
|
+
required: [],
|
|
775
|
+
optional: [...COMMON, ...searchDomains, "user_location"]
|
|
776
|
+
},
|
|
777
|
+
web_search_20260209: {
|
|
778
|
+
family: "webSearch",
|
|
779
|
+
name: "web_search",
|
|
780
|
+
required: [],
|
|
781
|
+
optional: [...COMMON, ...searchDomains, "user_location"]
|
|
782
|
+
},
|
|
783
|
+
web_search_20260318: {
|
|
784
|
+
family: "webSearch",
|
|
785
|
+
name: "web_search",
|
|
786
|
+
required: [],
|
|
787
|
+
optional: [...COMMON, ...searchDomains, "user_location", "response_inclusion"]
|
|
788
|
+
},
|
|
789
|
+
web_fetch_20250910: {
|
|
790
|
+
family: "webFetch",
|
|
791
|
+
name: "web_fetch",
|
|
792
|
+
required: [],
|
|
793
|
+
optional: [...COMMON, ...searchDomains, "citations", "max_content_tokens"]
|
|
794
|
+
},
|
|
795
|
+
web_fetch_20260209: {
|
|
796
|
+
family: "webFetch",
|
|
797
|
+
name: "web_fetch",
|
|
798
|
+
required: [],
|
|
799
|
+
optional: [...COMMON, ...searchDomains, "citations", "max_content_tokens"]
|
|
800
|
+
},
|
|
801
|
+
web_fetch_20260309: {
|
|
802
|
+
family: "webFetch",
|
|
803
|
+
name: "web_fetch",
|
|
804
|
+
required: [],
|
|
805
|
+
optional: [...COMMON, ...searchDomains, "citations", "max_content_tokens", "use_cache"]
|
|
806
|
+
},
|
|
807
|
+
web_fetch_20260318: {
|
|
808
|
+
family: "webFetch",
|
|
809
|
+
name: "web_fetch",
|
|
810
|
+
required: [],
|
|
811
|
+
optional: [
|
|
812
|
+
...COMMON,
|
|
813
|
+
...searchDomains,
|
|
814
|
+
"citations",
|
|
815
|
+
"max_content_tokens",
|
|
816
|
+
"use_cache",
|
|
817
|
+
"response_inclusion"
|
|
818
|
+
]
|
|
819
|
+
},
|
|
820
|
+
code_execution_20250522: {
|
|
821
|
+
family: "codeExecution",
|
|
822
|
+
name: "code_execution",
|
|
823
|
+
required: [],
|
|
824
|
+
optional: [...COMMON]
|
|
825
|
+
},
|
|
826
|
+
code_execution_20250825: {
|
|
827
|
+
family: "codeExecution",
|
|
828
|
+
name: "code_execution",
|
|
829
|
+
required: [],
|
|
830
|
+
optional: [...COMMON]
|
|
831
|
+
},
|
|
832
|
+
code_execution_20260120: {
|
|
833
|
+
family: "codeExecution",
|
|
834
|
+
name: "code_execution",
|
|
835
|
+
required: [],
|
|
836
|
+
optional: [...COMMON]
|
|
837
|
+
},
|
|
838
|
+
code_execution_20260521: {
|
|
839
|
+
family: "codeExecution",
|
|
840
|
+
name: "code_execution",
|
|
841
|
+
required: [],
|
|
842
|
+
optional: [...COMMON]
|
|
843
|
+
},
|
|
844
|
+
bash_20241022: {
|
|
845
|
+
family: "bash",
|
|
846
|
+
name: "bash",
|
|
847
|
+
required: [],
|
|
848
|
+
optional: [...COMMON_WITH_EXAMPLES]
|
|
849
|
+
},
|
|
850
|
+
bash_20250124: {
|
|
851
|
+
family: "bash",
|
|
852
|
+
name: "bash",
|
|
853
|
+
required: [],
|
|
854
|
+
optional: [...COMMON_WITH_EXAMPLES]
|
|
855
|
+
},
|
|
856
|
+
text_editor_20241022: {
|
|
857
|
+
family: "textEditor",
|
|
858
|
+
name: "str_replace_editor",
|
|
859
|
+
required: [],
|
|
860
|
+
optional: [...COMMON_WITH_EXAMPLES]
|
|
861
|
+
},
|
|
862
|
+
text_editor_20250124: {
|
|
863
|
+
family: "textEditor",
|
|
864
|
+
name: "str_replace_editor",
|
|
865
|
+
required: [],
|
|
866
|
+
optional: [...COMMON_WITH_EXAMPLES]
|
|
867
|
+
},
|
|
868
|
+
text_editor_20250429: {
|
|
869
|
+
family: "textEditor",
|
|
870
|
+
name: "str_replace_based_edit_tool",
|
|
871
|
+
required: [],
|
|
872
|
+
optional: [...COMMON_WITH_EXAMPLES]
|
|
873
|
+
},
|
|
874
|
+
text_editor_20250728: {
|
|
875
|
+
family: "textEditor",
|
|
876
|
+
name: "str_replace_based_edit_tool",
|
|
877
|
+
required: [],
|
|
878
|
+
optional: [...COMMON_WITH_EXAMPLES, "max_characters"]
|
|
879
|
+
},
|
|
880
|
+
computer_20241022: {
|
|
881
|
+
family: "computer",
|
|
882
|
+
name: "computer",
|
|
883
|
+
required: ["display_width_px", "display_height_px"],
|
|
884
|
+
optional: [...COMMON_WITH_EXAMPLES, "display_number"]
|
|
885
|
+
},
|
|
886
|
+
computer_20250124: {
|
|
887
|
+
family: "computer",
|
|
888
|
+
name: "computer",
|
|
889
|
+
required: ["display_width_px", "display_height_px"],
|
|
890
|
+
optional: [...COMMON_WITH_EXAMPLES, "display_number"]
|
|
891
|
+
},
|
|
892
|
+
computer_20251124: {
|
|
893
|
+
family: "computer",
|
|
894
|
+
name: "computer",
|
|
895
|
+
required: ["display_width_px", "display_height_px"],
|
|
896
|
+
optional: [...COMMON_WITH_EXAMPLES, "display_number", "enable_zoom"]
|
|
897
|
+
},
|
|
898
|
+
memory_20250818: {
|
|
899
|
+
family: "memory",
|
|
900
|
+
name: "memory",
|
|
901
|
+
required: [],
|
|
902
|
+
optional: [...COMMON_WITH_EXAMPLES]
|
|
903
|
+
},
|
|
904
|
+
tool_search_tool_regex_20251119: {
|
|
905
|
+
family: "toolSearchRegex",
|
|
906
|
+
name: "tool_search_tool_regex",
|
|
907
|
+
required: [],
|
|
908
|
+
optional: [...COMMON]
|
|
909
|
+
},
|
|
910
|
+
tool_search_tool_regex: {
|
|
911
|
+
family: "toolSearchRegex",
|
|
912
|
+
name: "tool_search_tool_regex",
|
|
913
|
+
required: [],
|
|
914
|
+
optional: [...COMMON]
|
|
915
|
+
},
|
|
916
|
+
tool_search_tool_bm25_20251119: {
|
|
917
|
+
family: "toolSearchBm25",
|
|
918
|
+
name: "tool_search_tool_bm25",
|
|
919
|
+
required: [],
|
|
920
|
+
optional: [...COMMON]
|
|
921
|
+
},
|
|
922
|
+
tool_search_tool_bm25: {
|
|
923
|
+
family: "toolSearchBm25",
|
|
924
|
+
name: "tool_search_tool_bm25",
|
|
925
|
+
required: [],
|
|
926
|
+
optional: [...COMMON]
|
|
927
|
+
},
|
|
928
|
+
advisor_20260301: {
|
|
929
|
+
family: "advisor",
|
|
930
|
+
name: "advisor",
|
|
931
|
+
required: ["model"],
|
|
932
|
+
optional: [...COMMON, "caching", "max_uses", "max_tokens"]
|
|
933
|
+
},
|
|
934
|
+
mcp_toolset: {
|
|
935
|
+
family: "mcpToolset",
|
|
936
|
+
required: ["mcp_server_name"],
|
|
937
|
+
optional: ["cache_control", "configs", "default_config"]
|
|
938
|
+
}
|
|
939
|
+
};
|
|
940
|
+
var ANTHROPIC_NATIVE_BLOCK_TYPES = new Set([
|
|
941
|
+
"server_tool_use",
|
|
942
|
+
"web_search_tool_result",
|
|
943
|
+
"web_fetch_tool_result",
|
|
944
|
+
"code_execution_tool_result",
|
|
945
|
+
"bash_code_execution_tool_result",
|
|
946
|
+
"text_editor_code_execution_tool_result",
|
|
947
|
+
"mcp_tool_use",
|
|
948
|
+
"mcp_tool_result",
|
|
949
|
+
"tool_search_tool_result",
|
|
950
|
+
"tool_reference",
|
|
951
|
+
"advisor_tool_result",
|
|
952
|
+
"advisor_result",
|
|
953
|
+
"advisor_redacted_result",
|
|
954
|
+
"container_upload",
|
|
955
|
+
"compaction",
|
|
956
|
+
"search_result",
|
|
957
|
+
"document",
|
|
958
|
+
"mid_conv_system",
|
|
959
|
+
"tool_addition",
|
|
960
|
+
"tool_removal",
|
|
961
|
+
"fallback",
|
|
962
|
+
"redacted_thinking"
|
|
963
|
+
]);
|
|
964
|
+
|
|
762
965
|
// packages/providers/src/anthropic/decode.ts
|
|
763
966
|
var STOP_REASON = {
|
|
764
967
|
end_turn: "endTurn",
|
|
765
968
|
max_tokens: "maxTokens",
|
|
766
969
|
stop_sequence: "stopSequence",
|
|
767
970
|
tool_use: "toolUse",
|
|
768
|
-
refusal: "contentFilter"
|
|
971
|
+
refusal: "contentFilter",
|
|
972
|
+
pause_turn: "pauseTurn"
|
|
769
973
|
};
|
|
974
|
+
var KNOWN_EVENTS = new Set([
|
|
975
|
+
"message_start",
|
|
976
|
+
"content_block_start",
|
|
977
|
+
"content_block_delta",
|
|
978
|
+
"content_block_stop",
|
|
979
|
+
"message_delta",
|
|
980
|
+
"message_stop",
|
|
981
|
+
"error",
|
|
982
|
+
"ping"
|
|
983
|
+
]);
|
|
984
|
+
var KNOWN_DELTAS = new Set([
|
|
985
|
+
"text_delta",
|
|
986
|
+
"thinking_delta",
|
|
987
|
+
"signature_delta",
|
|
988
|
+
"input_json_delta",
|
|
989
|
+
"citations_delta",
|
|
990
|
+
"compaction_delta"
|
|
991
|
+
]);
|
|
770
992
|
var ERROR_TYPE = {
|
|
771
993
|
overloaded_error: "OVERLOADED",
|
|
772
994
|
rate_limit_error: "RATE_LIMIT",
|
|
@@ -792,10 +1014,21 @@ async function* decodeAnthropic(messages) {
|
|
|
792
1014
|
let outputTokens = 0;
|
|
793
1015
|
let stopReason = "endTurn";
|
|
794
1016
|
let terminal = false;
|
|
1017
|
+
const nativeBlocks = new Set;
|
|
1018
|
+
const protocolError = (message) => ({
|
|
1019
|
+
type: "error",
|
|
1020
|
+
code: "UPSTREAM",
|
|
1021
|
+
message,
|
|
1022
|
+
retryable: false
|
|
1023
|
+
});
|
|
795
1024
|
for await (const msg of messages) {
|
|
796
1025
|
const d = json(msg.data);
|
|
797
1026
|
if (d === null)
|
|
798
1027
|
continue;
|
|
1028
|
+
if (!KNOWN_EVENTS.has(msg.event)) {
|
|
1029
|
+
yield protocolError(`unrecognized Anthropic stream event "${msg.event}"`);
|
|
1030
|
+
return;
|
|
1031
|
+
}
|
|
799
1032
|
switch (msg.event) {
|
|
800
1033
|
case "message_start": {
|
|
801
1034
|
const m = d.message ?? {};
|
|
@@ -820,6 +1053,18 @@ async function* decodeAnthropic(messages) {
|
|
|
820
1053
|
index,
|
|
821
1054
|
block: { type: "toolUse", id: String(cb.id), name: String(cb.name) }
|
|
822
1055
|
};
|
|
1056
|
+
else if (cb.type !== undefined && ANTHROPIC_NATIVE_BLOCK_TYPES.has(cb.type)) {
|
|
1057
|
+
nativeBlocks.add(index);
|
|
1058
|
+
const { type: _blockType, ...data } = cb;
|
|
1059
|
+
yield {
|
|
1060
|
+
type: "blockStart",
|
|
1061
|
+
index,
|
|
1062
|
+
block: { type: "anthropicNative", blockType: cb.type, data }
|
|
1063
|
+
};
|
|
1064
|
+
} else {
|
|
1065
|
+
yield protocolError(`unrecognized Anthropic content block type "${String(cb.type)}"`);
|
|
1066
|
+
return;
|
|
1067
|
+
}
|
|
823
1068
|
break;
|
|
824
1069
|
}
|
|
825
1070
|
case "content_block_delta": {
|
|
@@ -843,17 +1088,51 @@ async function* decodeAnthropic(messages) {
|
|
|
843
1088
|
yield {
|
|
844
1089
|
type: "blockDelta",
|
|
845
1090
|
index,
|
|
846
|
-
delta: { type: "toolJson", partial: delta.partial_json ?? "" }
|
|
1091
|
+
delta: nativeBlocks.has(index) ? { type: "anthropicNativeJson", partial: delta.partial_json ?? "" } : { type: "toolJson", partial: delta.partial_json ?? "" }
|
|
1092
|
+
};
|
|
1093
|
+
else if (delta.type === "citations_delta")
|
|
1094
|
+
yield {
|
|
1095
|
+
type: "blockDelta",
|
|
1096
|
+
index,
|
|
1097
|
+
delta: {
|
|
1098
|
+
type: "anthropicNative",
|
|
1099
|
+
deltaType: delta.type,
|
|
1100
|
+
data: { citation: delta.citation }
|
|
1101
|
+
}
|
|
847
1102
|
};
|
|
1103
|
+
else if (delta.type === "compaction_delta")
|
|
1104
|
+
yield {
|
|
1105
|
+
type: "blockDelta",
|
|
1106
|
+
index,
|
|
1107
|
+
delta: {
|
|
1108
|
+
type: "anthropicNative",
|
|
1109
|
+
deltaType: delta.type,
|
|
1110
|
+
data: {
|
|
1111
|
+
...delta.content === undefined ? {} : { content: delta.content },
|
|
1112
|
+
...delta.encrypted_content === undefined ? {} : { encrypted_content: delta.encrypted_content }
|
|
1113
|
+
}
|
|
1114
|
+
}
|
|
1115
|
+
};
|
|
1116
|
+
else if (delta.type === undefined || !KNOWN_DELTAS.has(delta.type)) {
|
|
1117
|
+
yield protocolError(`unrecognized Anthropic content block delta "${String(delta.type)}"`);
|
|
1118
|
+
return;
|
|
1119
|
+
}
|
|
848
1120
|
break;
|
|
849
1121
|
}
|
|
850
1122
|
case "content_block_stop":
|
|
1123
|
+
nativeBlocks.delete(d.index ?? 0);
|
|
851
1124
|
yield { type: "blockEnd", index: d.index ?? 0 };
|
|
852
1125
|
break;
|
|
853
1126
|
case "message_delta": {
|
|
854
1127
|
const reason = d.delta?.stop_reason;
|
|
855
|
-
if (typeof reason === "string")
|
|
856
|
-
|
|
1128
|
+
if (typeof reason === "string") {
|
|
1129
|
+
const mapped = STOP_REASON[reason];
|
|
1130
|
+
if (mapped === undefined) {
|
|
1131
|
+
yield protocolError(`unrecognized Anthropic stop reason "${reason}"`);
|
|
1132
|
+
return;
|
|
1133
|
+
}
|
|
1134
|
+
stopReason = mapped;
|
|
1135
|
+
}
|
|
857
1136
|
inputTokens = d.usage?.input_tokens ?? inputTokens;
|
|
858
1137
|
outputTokens = d.usage?.output_tokens ?? outputTokens;
|
|
859
1138
|
break;
|
|
@@ -912,7 +1191,12 @@ function encodeBlock(b) {
|
|
|
912
1191
|
const cache = wireCacheControl(cacheControlOf(b));
|
|
913
1192
|
switch (b.type) {
|
|
914
1193
|
case "text":
|
|
915
|
-
return {
|
|
1194
|
+
return {
|
|
1195
|
+
type: "text",
|
|
1196
|
+
text: b.text,
|
|
1197
|
+
...b.citations === undefined ? {} : { citations: b.citations },
|
|
1198
|
+
...cache
|
|
1199
|
+
};
|
|
916
1200
|
case "image":
|
|
917
1201
|
return {
|
|
918
1202
|
type: "image",
|
|
@@ -931,11 +1215,16 @@ function encodeBlock(b) {
|
|
|
931
1215
|
is_error: b.isError,
|
|
932
1216
|
...cache
|
|
933
1217
|
};
|
|
1218
|
+
case "anthropicNative":
|
|
1219
|
+
return { ...b.data, type: b.blockType, ...cache };
|
|
934
1220
|
}
|
|
935
1221
|
}
|
|
936
1222
|
function encodeSystemTurn(content) {
|
|
937
|
-
|
|
1223
|
+
if (content.every((block) => block.type === "text")) {
|
|
1224
|
+
return content.map((block) => block.text).join(`
|
|
938
1225
|
`);
|
|
1226
|
+
}
|
|
1227
|
+
return content.map(encodeBlock);
|
|
939
1228
|
}
|
|
940
1229
|
function systemCacheControl(req) {
|
|
941
1230
|
const cacheable = req.messages.flatMap((message) => message.content.flatMap((block) => block.type === "thinking" ? [] : [{ role: message.role, block }]));
|
|
@@ -947,6 +1236,23 @@ function systemCacheControl(req) {
|
|
|
947
1236
|
lost: markedSystemBlocks.length > (promoted === undefined ? 0 : 1)
|
|
948
1237
|
};
|
|
949
1238
|
}
|
|
1239
|
+
function encodeTool(t) {
|
|
1240
|
+
if (t.provider === "anthropic") {
|
|
1241
|
+
return {
|
|
1242
|
+
type: t.type,
|
|
1243
|
+
...t.name === "" ? {} : { name: t.name },
|
|
1244
|
+
...t.wire,
|
|
1245
|
+
...wireCacheControl(t.cacheControl)
|
|
1246
|
+
};
|
|
1247
|
+
}
|
|
1248
|
+
return {
|
|
1249
|
+
name: t.name,
|
|
1250
|
+
...t.description === undefined ? {} : { description: t.description },
|
|
1251
|
+
input_schema: t.inputSchema,
|
|
1252
|
+
...t.options ?? {},
|
|
1253
|
+
...wireCacheControl(t.cacheControl)
|
|
1254
|
+
};
|
|
1255
|
+
}
|
|
950
1256
|
function encodeToolChoice(c) {
|
|
951
1257
|
switch (c.type) {
|
|
952
1258
|
case "auto":
|
|
@@ -1001,14 +1307,8 @@ function toWire(req, model, opts) {
|
|
|
1001
1307
|
body.temperature = req.temperature;
|
|
1002
1308
|
if (req.stopSequences !== undefined)
|
|
1003
1309
|
body.stop_sequences = req.stopSequences;
|
|
1004
|
-
if (req.tools !== undefined)
|
|
1005
|
-
body.tools = req.tools.map(
|
|
1006
|
-
name: t.name,
|
|
1007
|
-
...t.description === undefined ? {} : { description: t.description },
|
|
1008
|
-
input_schema: t.inputSchema,
|
|
1009
|
-
...wireCacheControl(t.cacheControl)
|
|
1010
|
-
}));
|
|
1011
|
-
}
|
|
1310
|
+
if (req.tools !== undefined)
|
|
1311
|
+
body.tools = req.tools.map(encodeTool);
|
|
1012
1312
|
if (req.toolChoice !== undefined)
|
|
1013
1313
|
body.tool_choice = encodeToolChoice(req.toolChoice);
|
|
1014
1314
|
if (req.reasoning !== undefined) {
|
|
@@ -1355,6 +1655,9 @@ function toChatWire(req, model) {
|
|
|
1355
1655
|
content: block.content
|
|
1356
1656
|
});
|
|
1357
1657
|
break;
|
|
1658
|
+
case "anthropicNative":
|
|
1659
|
+
note2("kimi:anthropic-native-block-dropped");
|
|
1660
|
+
break;
|
|
1358
1661
|
}
|
|
1359
1662
|
}
|
|
1360
1663
|
if (toolCalls.length > 0) {
|
|
@@ -1382,7 +1685,10 @@ function toChatWire(req, model) {
|
|
|
1382
1685
|
if (req.stopSequences !== undefined)
|
|
1383
1686
|
body.stop = req.stopSequences;
|
|
1384
1687
|
if (req.tools !== undefined) {
|
|
1385
|
-
|
|
1688
|
+
const custom = req.tools.filter((t) => t.provider === "custom");
|
|
1689
|
+
if (custom.length !== req.tools.length)
|
|
1690
|
+
note2("kimi:anthropic-tool-dropped");
|
|
1691
|
+
body.tools = custom.map((t) => ({
|
|
1386
1692
|
type: "function",
|
|
1387
1693
|
function: { name: t.name, description: t.description, parameters: t.inputSchema }
|
|
1388
1694
|
}));
|
|
@@ -1649,6 +1955,9 @@ ${block.text}
|
|
|
1649
1955
|
output: block.content
|
|
1650
1956
|
});
|
|
1651
1957
|
break;
|
|
1958
|
+
case "anthropicNative":
|
|
1959
|
+
note2("openai:anthropic-native-block-dropped");
|
|
1960
|
+
break;
|
|
1652
1961
|
}
|
|
1653
1962
|
}
|
|
1654
1963
|
flush();
|
|
@@ -1672,7 +1981,10 @@ ${block.text}
|
|
|
1672
1981
|
body.temperature = req.temperature;
|
|
1673
1982
|
}
|
|
1674
1983
|
if (req.tools !== undefined) {
|
|
1675
|
-
|
|
1984
|
+
const custom = req.tools.filter((t) => t.provider === "custom");
|
|
1985
|
+
if (custom.length !== req.tools.length)
|
|
1986
|
+
note2("openai:anthropic-tool-dropped");
|
|
1987
|
+
body.tools = custom.map((t) => ({
|
|
1676
1988
|
type: "function",
|
|
1677
1989
|
name: t.name,
|
|
1678
1990
|
description: t.description,
|
|
@@ -16638,11 +16950,12 @@ var settingsSchema = exports_external.object({
|
|
|
16638
16950
|
recency: exports_external.number()
|
|
16639
16951
|
}).strict(),
|
|
16640
16952
|
maxAttempts: exports_external.number().int().min(1).max(10),
|
|
16641
|
-
requestDeadlineMs: exports_external.number().int().
|
|
16953
|
+
requestDeadlineMs: exports_external.number().int().min(0),
|
|
16642
16954
|
breakerThreshold: exports_external.number().int().min(1),
|
|
16643
16955
|
breakerCooldownMs: exports_external.number().int().positive(),
|
|
16644
16956
|
logRetentionDays: exports_external.number().int().min(1),
|
|
16645
|
-
quotaPollIntervalMs: exports_external.number().int().min(0)
|
|
16957
|
+
quotaPollIntervalMs: exports_external.number().int().min(0),
|
|
16958
|
+
rtkEnabled: exports_external.boolean()
|
|
16646
16959
|
});
|
|
16647
16960
|
var credentialPatchSchema = exports_external.object({
|
|
16648
16961
|
label: exports_external.string().min(1).optional(),
|
|
@@ -16829,6 +17142,11 @@ async function buildSnapshot(store, now) {
|
|
|
16829
17142
|
}
|
|
16830
17143
|
|
|
16831
17144
|
// packages/router/src/filters.ts
|
|
17145
|
+
function needsAnthropicNative(request2) {
|
|
17146
|
+
if (request2.tools?.some((t) => t.provider === "anthropic") === true)
|
|
17147
|
+
return true;
|
|
17148
|
+
return request2.messages.some((m) => m.content.some((b) => b.type === "anthropicNative"));
|
|
17149
|
+
}
|
|
16832
17150
|
function requiredCapabilities(request2) {
|
|
16833
17151
|
const images = request2.messages.some((m) => m.content.some((b) => b.type === "image"));
|
|
16834
17152
|
return {
|
|
@@ -16845,10 +17163,11 @@ function eligible(input) {
|
|
|
16845
17163
|
const { request: request2, model, snapshot, now } = input;
|
|
16846
17164
|
const { breakerThreshold, breakerCooldownMs } = snapshot.settings;
|
|
16847
17165
|
const need = requiredCapabilities(request2);
|
|
17166
|
+
const needNative = needsAnthropicNative(request2);
|
|
16848
17167
|
const pairs = [];
|
|
16849
17168
|
const excluded = [];
|
|
16850
17169
|
for (const target of model.targets) {
|
|
16851
|
-
const missing = ["tools", "images", "reasoning"].find((cap) => need[cap] && !target.capabilities[cap]);
|
|
17170
|
+
const missing = needNative && !ANTHROPIC_NATIVE_TOOLS[target.provider] ? "anthropicTools" : ["tools", "images", "reasoning"].find((cap) => need[cap] && !target.capabilities[cap]);
|
|
16852
17171
|
for (const credential of snapshot.credentials) {
|
|
16853
17172
|
if (credential.provider !== target.provider)
|
|
16854
17173
|
continue;
|
|
@@ -17043,7 +17362,11 @@ async function dryRun(deps, modelId, input) {
|
|
|
17043
17362
|
}
|
|
17044
17363
|
],
|
|
17045
17364
|
stream: false,
|
|
17046
|
-
...need.tools ? {
|
|
17365
|
+
...need.tools ? {
|
|
17366
|
+
tools: [
|
|
17367
|
+
{ provider: "custom", name: "probe", description: "", inputSchema: { type: "object" } }
|
|
17368
|
+
]
|
|
17369
|
+
} : {},
|
|
17047
17370
|
...need.reasoning ? { reasoning: { mode: "adaptive" } } : {}
|
|
17048
17371
|
};
|
|
17049
17372
|
const result = rank({ request: probe, model, snapshot, now, rand: 0 });
|
|
@@ -17111,7 +17434,8 @@ var DEFAULT_SETTINGS = {
|
|
|
17111
17434
|
breakerThreshold: 3,
|
|
17112
17435
|
breakerCooldownMs: 30000,
|
|
17113
17436
|
logRetentionDays: 30,
|
|
17114
|
-
quotaPollIntervalMs: 300000
|
|
17437
|
+
quotaPollIntervalMs: 300000,
|
|
17438
|
+
rtkEnabled: false
|
|
17115
17439
|
};
|
|
17116
17440
|
|
|
17117
17441
|
// packages/store/src/sqlite/config.ts
|
|
@@ -17147,12 +17471,18 @@ function createConfigRepo(db, emit2 = () => {}) {
|
|
|
17147
17471
|
const raw = readRaw(SETTINGS_KEY);
|
|
17148
17472
|
if (raw === null)
|
|
17149
17473
|
return DEFAULT_SETTINGS;
|
|
17150
|
-
|
|
17151
|
-
|
|
17152
|
-
|
|
17153
|
-
|
|
17154
|
-
|
|
17155
|
-
|
|
17474
|
+
try {
|
|
17475
|
+
const parsed = JSON.parse(raw);
|
|
17476
|
+
const stored = parsed !== null && typeof parsed === "object" && !Array.isArray(parsed) ? parsed : {};
|
|
17477
|
+
return {
|
|
17478
|
+
...DEFAULT_SETTINGS,
|
|
17479
|
+
...stored,
|
|
17480
|
+
rtkEnabled: stored.rtkEnabled === true,
|
|
17481
|
+
weights: { ...DEFAULT_SETTINGS.weights, ...stored.weights }
|
|
17482
|
+
};
|
|
17483
|
+
} catch {
|
|
17484
|
+
return DEFAULT_SETTINGS;
|
|
17485
|
+
}
|
|
17156
17486
|
},
|
|
17157
17487
|
async putSettings(patch) {
|
|
17158
17488
|
const current = await this.getSettings();
|
|
@@ -17594,6 +17924,20 @@ ALTER TABLE request_logs ADD COLUMN state TEXT NOT NULL DEFAULT 'done';
|
|
|
17594
17924
|
CREATE INDEX idx_request_logs_pending ON request_logs(state) WHERE state = 'pending';
|
|
17595
17925
|
`;
|
|
17596
17926
|
|
|
17927
|
+
// packages/store/src/sqlite/migrations/005_rtk_metrics.sql
|
|
17928
|
+
var _005_rtk_metrics_default = `ALTER TABLE request_logs ADD COLUMN rtk_applied INTEGER NOT NULL DEFAULT 0;
|
|
17929
|
+
ALTER TABLE request_logs ADD COLUMN rtk_filter_hits INTEGER NOT NULL DEFAULT 0;
|
|
17930
|
+
ALTER TABLE request_logs ADD COLUMN rtk_original_code_units INTEGER NOT NULL DEFAULT 0;
|
|
17931
|
+
ALTER TABLE request_logs ADD COLUMN rtk_compressed_code_units INTEGER NOT NULL DEFAULT 0;
|
|
17932
|
+
ALTER TABLE request_logs ADD COLUMN rtk_estimated_tokens_saved INTEGER NOT NULL DEFAULT 0;
|
|
17933
|
+
ALTER TABLE request_logs ADD COLUMN rtk_filters TEXT NOT NULL DEFAULT '[]';
|
|
17934
|
+
`;
|
|
17935
|
+
|
|
17936
|
+
// packages/store/src/sqlite/migrations/006_rtk_usage.sql
|
|
17937
|
+
var _006_rtk_usage_default = `ALTER TABLE usage_daily ADD COLUMN rtk_saved_tokens INTEGER NOT NULL DEFAULT 0;
|
|
17938
|
+
ALTER TABLE usage_daily ADD COLUMN rtk_applied_requests INTEGER NOT NULL DEFAULT 0;
|
|
17939
|
+
`;
|
|
17940
|
+
|
|
17597
17941
|
// packages/store/src/sqlite/rollup.ts
|
|
17598
17942
|
function startOfLocalDay(at) {
|
|
17599
17943
|
const day = new Date(at);
|
|
@@ -17604,8 +17948,8 @@ var UPSERT = `
|
|
|
17604
17948
|
INSERT INTO usage_daily
|
|
17605
17949
|
(day, provider, credential_id, requested_model, resolved_model, api_key_id,
|
|
17606
17950
|
requests, errors, input_tokens, output_tokens, cache_read_tokens,
|
|
17607
|
-
cache_write_tokens, cost_usd, duration_ms_sum)
|
|
17608
|
-
VALUES (
|
|
17951
|
+
cache_write_tokens, rtk_saved_tokens, rtk_applied_requests, cost_usd, duration_ms_sum)
|
|
17952
|
+
VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)
|
|
17609
17953
|
ON CONFLICT (day, provider, credential_id, requested_model, resolved_model, api_key_id)
|
|
17610
17954
|
DO UPDATE SET
|
|
17611
17955
|
requests = requests + excluded.requests,
|
|
@@ -17613,8 +17957,10 @@ var UPSERT = `
|
|
|
17613
17957
|
input_tokens = input_tokens + excluded.input_tokens,
|
|
17614
17958
|
output_tokens = output_tokens + excluded.output_tokens,
|
|
17615
17959
|
cache_read_tokens = cache_read_tokens + excluded.cache_read_tokens,
|
|
17616
|
-
cache_write_tokens
|
|
17617
|
-
|
|
17960
|
+
cache_write_tokens = cache_write_tokens + excluded.cache_write_tokens,
|
|
17961
|
+
rtk_saved_tokens = rtk_saved_tokens + excluded.rtk_saved_tokens,
|
|
17962
|
+
rtk_applied_requests = rtk_applied_requests + excluded.rtk_applied_requests,
|
|
17963
|
+
cost_usd = cost_usd + excluded.cost_usd,
|
|
17618
17964
|
duration_ms_sum = duration_ms_sum + excluded.duration_ms_sum`;
|
|
17619
17965
|
function keyOf(log) {
|
|
17620
17966
|
return [
|
|
@@ -17634,6 +17980,8 @@ function countersOf(log) {
|
|
|
17634
17980
|
outputTokens: log.outputTokens,
|
|
17635
17981
|
cacheReadTokens: log.cacheReadTokens,
|
|
17636
17982
|
cacheWriteTokens: log.cacheWriteTokens,
|
|
17983
|
+
rtkSavedTokens: log.rtkEstimatedTokensSaved,
|
|
17984
|
+
rtkAppliedRequests: log.rtkApplied ? 1 : 0,
|
|
17637
17985
|
costUsd: log.costUsd,
|
|
17638
17986
|
durationMsSum: log.durationMs
|
|
17639
17987
|
};
|
|
@@ -17647,6 +17995,8 @@ function upsert(db, key, c) {
|
|
|
17647
17995
|
c.outputTokens,
|
|
17648
17996
|
c.cacheReadTokens,
|
|
17649
17997
|
c.cacheWriteTokens,
|
|
17998
|
+
c.rtkSavedTokens,
|
|
17999
|
+
c.rtkAppliedRequests,
|
|
17650
18000
|
c.costUsd,
|
|
17651
18001
|
c.durationMsSum
|
|
17652
18002
|
]);
|
|
@@ -17677,6 +18027,8 @@ function backfillDaily(db) {
|
|
|
17677
18027
|
outputTokens: 0,
|
|
17678
18028
|
cacheReadTokens: 0,
|
|
17679
18029
|
cacheWriteTokens: 0,
|
|
18030
|
+
rtkSavedTokens: 0,
|
|
18031
|
+
rtkAppliedRequests: 0,
|
|
17680
18032
|
costUsd: 0,
|
|
17681
18033
|
durationMsSum: 0
|
|
17682
18034
|
};
|
|
@@ -17695,13 +18047,42 @@ function backfillDaily(db) {
|
|
|
17695
18047
|
upsert(db, group.key, group.counters);
|
|
17696
18048
|
return groups.size;
|
|
17697
18049
|
}
|
|
18050
|
+
function backfillRtkUsage(db) {
|
|
18051
|
+
const groups = new Map;
|
|
18052
|
+
for (const row of db.query(`SELECT at, api_key_id, requested_model, resolved_provider, resolved_model, credential_id,
|
|
18053
|
+
rtk_applied, rtk_estimated_tokens_saved
|
|
18054
|
+
FROM request_logs
|
|
18055
|
+
WHERE state = 'done'`).all()) {
|
|
18056
|
+
const key = [
|
|
18057
|
+
startOfLocalDay(row.at),
|
|
18058
|
+
row.resolved_provider ?? "",
|
|
18059
|
+
row.credential_id ?? "",
|
|
18060
|
+
row.requested_model,
|
|
18061
|
+
row.resolved_model ?? "",
|
|
18062
|
+
row.api_key_id ?? ""
|
|
18063
|
+
];
|
|
18064
|
+
const id = key.join("\x00");
|
|
18065
|
+
const group = groups.get(id) ?? { key, saved: 0, applied: 0 };
|
|
18066
|
+
group.saved += row.rtk_estimated_tokens_saved;
|
|
18067
|
+
group.applied += row.rtk_applied === 1 ? 1 : 0;
|
|
18068
|
+
groups.set(id, group);
|
|
18069
|
+
}
|
|
18070
|
+
for (const { key, saved, applied } of groups.values()) {
|
|
18071
|
+
db.run(`UPDATE usage_daily
|
|
18072
|
+
SET rtk_saved_tokens = ?, rtk_applied_requests = ?
|
|
18073
|
+
WHERE day = ? AND provider = ? AND credential_id = ? AND requested_model = ?
|
|
18074
|
+
AND resolved_model = ? AND api_key_id = ?`, [saved, applied, ...key]);
|
|
18075
|
+
}
|
|
18076
|
+
}
|
|
17698
18077
|
|
|
17699
18078
|
// packages/store/src/sqlite/db.ts
|
|
17700
18079
|
var MIGRATIONS = [
|
|
17701
18080
|
{ id: 1, sql: _001_init_default },
|
|
17702
18081
|
{ id: 2, sql: _002_usage_daily_default, after: backfillDaily },
|
|
17703
18082
|
{ id: 3, sql: _003_quota_snapshot_default },
|
|
17704
|
-
{ id: 4, sql: _004_request_state_default }
|
|
18083
|
+
{ id: 4, sql: _004_request_state_default },
|
|
18084
|
+
{ id: 5, sql: _005_rtk_metrics_default },
|
|
18085
|
+
{ id: 6, sql: _006_rtk_usage_default, after: backfillRtkUsage }
|
|
17705
18086
|
];
|
|
17706
18087
|
function openDb(path) {
|
|
17707
18088
|
const db = new Database(path, { create: true });
|
|
@@ -17770,7 +18151,38 @@ function createKeyRepo(db) {
|
|
|
17770
18151
|
}
|
|
17771
18152
|
};
|
|
17772
18153
|
}
|
|
18154
|
+
// packages/rtk/src/catalog.ts
|
|
18155
|
+
var RTK_FILTER_IDS = [
|
|
18156
|
+
"git-diff",
|
|
18157
|
+
"git-status",
|
|
18158
|
+
"git-log",
|
|
18159
|
+
"grep",
|
|
18160
|
+
"path-list",
|
|
18161
|
+
"numbered-read",
|
|
18162
|
+
"build-output",
|
|
18163
|
+
"test-output",
|
|
18164
|
+
"deduplicate-log",
|
|
18165
|
+
"smart-truncate",
|
|
18166
|
+
"lint-output",
|
|
18167
|
+
"package-output",
|
|
18168
|
+
"tree-output",
|
|
18169
|
+
"git-operation",
|
|
18170
|
+
"docker-build"
|
|
18171
|
+
];
|
|
18172
|
+
var FILTER_IDS = new Set(RTK_FILTER_IDS);
|
|
18173
|
+
function isRtkFilterId(value) {
|
|
18174
|
+
return FILTER_IDS.has(value);
|
|
18175
|
+
}
|
|
18176
|
+
|
|
17773
18177
|
// packages/store/src/sqlite/usage.ts
|
|
18178
|
+
function parseRtkFilters(raw) {
|
|
18179
|
+
try {
|
|
18180
|
+
const parsed = JSON.parse(raw);
|
|
18181
|
+
return Array.isArray(parsed) ? parsed.filter(isRtkFilterId) : [];
|
|
18182
|
+
} catch {
|
|
18183
|
+
return [];
|
|
18184
|
+
}
|
|
18185
|
+
}
|
|
17774
18186
|
var toLog = (r) => ({
|
|
17775
18187
|
id: r.id,
|
|
17776
18188
|
state: r.state === "pending" ? "pending" : "done",
|
|
@@ -17790,7 +18202,13 @@ var toLog = (r) => ({
|
|
|
17790
18202
|
ttftMs: r.ttft_ms,
|
|
17791
18203
|
durationMs: r.duration_ms,
|
|
17792
18204
|
costUsd: r.cost_usd,
|
|
17793
|
-
degradations: JSON.parse(r.degradations)
|
|
18205
|
+
degradations: JSON.parse(r.degradations),
|
|
18206
|
+
rtkApplied: r.rtk_applied === 1,
|
|
18207
|
+
rtkFilterHits: r.rtk_filter_hits,
|
|
18208
|
+
rtkOriginalCodeUnits: r.rtk_original_code_units,
|
|
18209
|
+
rtkCompressedCodeUnits: r.rtk_compressed_code_units,
|
|
18210
|
+
rtkEstimatedTokensSaved: r.rtk_estimated_tokens_saved,
|
|
18211
|
+
rtkFilters: parseRtkFilters(r.rtk_filters)
|
|
17794
18212
|
});
|
|
17795
18213
|
var GROUP_COLUMN = {
|
|
17796
18214
|
raw: {
|
|
@@ -17835,8 +18253,9 @@ function label(value) {
|
|
|
17835
18253
|
var COLUMNS = `(id, state, at, api_key_id, requested_model, resolved_provider, resolved_model,
|
|
17836
18254
|
credential_id, attempts, status, error_code, input_tokens, output_tokens,
|
|
17837
18255
|
cache_read_tokens, cache_write_tokens, ttft_ms, duration_ms, cost_usd,
|
|
17838
|
-
degradations
|
|
17839
|
-
|
|
18256
|
+
degradations, rtk_applied, rtk_filter_hits, rtk_original_code_units,
|
|
18257
|
+
rtk_compressed_code_units, rtk_estimated_tokens_saved, rtk_filters)`;
|
|
18258
|
+
var PLACEHOLDERS = "(?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)";
|
|
17840
18259
|
function values(log, state) {
|
|
17841
18260
|
return [
|
|
17842
18261
|
log.id,
|
|
@@ -17857,7 +18276,13 @@ function values(log, state) {
|
|
|
17857
18276
|
log.ttftMs,
|
|
17858
18277
|
log.durationMs,
|
|
17859
18278
|
log.costUsd,
|
|
17860
|
-
JSON.stringify(log.degradations)
|
|
18279
|
+
JSON.stringify(log.degradations),
|
|
18280
|
+
log.rtkApplied === true ? 1 : 0,
|
|
18281
|
+
log.rtkFilterHits ?? 0,
|
|
18282
|
+
log.rtkOriginalCodeUnits ?? 0,
|
|
18283
|
+
log.rtkCompressedCodeUnits ?? 0,
|
|
18284
|
+
log.rtkEstimatedTokensSaved ?? 0,
|
|
18285
|
+
JSON.stringify(log.rtkFilters ?? [])
|
|
17861
18286
|
];
|
|
17862
18287
|
}
|
|
17863
18288
|
var COMPLETE = `INSERT INTO request_logs ${COLUMNS} VALUES ${PLACEHOLDERS}
|
|
@@ -17878,7 +18303,13 @@ var COMPLETE = `INSERT INTO request_logs ${COLUMNS} VALUES ${PLACEHOLDERS}
|
|
|
17878
18303
|
ttft_ms = excluded.ttft_ms,
|
|
17879
18304
|
duration_ms = excluded.duration_ms,
|
|
17880
18305
|
cost_usd = excluded.cost_usd,
|
|
17881
|
-
degradations = excluded.degradations
|
|
18306
|
+
degradations = excluded.degradations,
|
|
18307
|
+
rtk_applied = excluded.rtk_applied,
|
|
18308
|
+
rtk_filter_hits = excluded.rtk_filter_hits,
|
|
18309
|
+
rtk_original_code_units = excluded.rtk_original_code_units,
|
|
18310
|
+
rtk_compressed_code_units = excluded.rtk_compressed_code_units,
|
|
18311
|
+
rtk_estimated_tokens_saved = excluded.rtk_estimated_tokens_saved,
|
|
18312
|
+
rtk_filters = excluded.rtk_filters`;
|
|
17882
18313
|
function createUsageRepo(db) {
|
|
17883
18314
|
const complete = db.transaction((log) => {
|
|
17884
18315
|
db.run(COMPLETE, values(log, "done"));
|
|
@@ -17923,6 +18354,8 @@ function createUsageRepo(db) {
|
|
|
17923
18354
|
COALESCE(SUM(output_tokens), 0) AS output_tokens,
|
|
17924
18355
|
COALESCE(SUM(cache_read_tokens), 0) AS cache_read_tokens,
|
|
17925
18356
|
COALESCE(SUM(cache_write_tokens), 0) AS cache_write_tokens,
|
|
18357
|
+
COALESCE(SUM(${daily ? "rtk_saved_tokens" : "rtk_estimated_tokens_saved"}), 0) AS rtk_saved_tokens,
|
|
18358
|
+
COALESCE(SUM(${daily ? "rtk_applied_requests" : "CASE WHEN rtk_applied = 1 THEN 1 ELSE 0 END"}), 0) AS rtk_applied_requests,
|
|
17926
18359
|
COALESCE(SUM(cost_usd), 0) AS cost_usd
|
|
17927
18360
|
FROM ${daily ? "usage_daily" : "request_logs"}
|
|
17928
18361
|
WHERE ${daily ? "" : "state = 'done' AND "}${timeColumn} >= ? AND ${timeColumn} <= ?
|
|
@@ -17936,6 +18369,8 @@ function createUsageRepo(db) {
|
|
|
17936
18369
|
outputTokens: r.output_tokens,
|
|
17937
18370
|
cacheReadTokens: r.cache_read_tokens,
|
|
17938
18371
|
cacheWriteTokens: r.cache_write_tokens,
|
|
18372
|
+
rtkSavedTokens: r.rtk_saved_tokens,
|
|
18373
|
+
rtkAppliedRequests: r.rtk_applied_requests,
|
|
17939
18374
|
costUsd: r.cost_usd,
|
|
17940
18375
|
errors: r.errors,
|
|
17941
18376
|
durationMsSum: r.duration_ms_sum
|
|
@@ -18436,33 +18871,77 @@ async function describeModelsForSetup(store) {
|
|
|
18436
18871
|
label: modelDisplayName(model)
|
|
18437
18872
|
}));
|
|
18438
18873
|
}
|
|
18439
|
-
|
|
18440
|
-
|
|
18441
|
-
|
|
18442
|
-
|
|
18443
|
-
|
|
18444
|
-
|
|
18445
|
-
|
|
18446
|
-
|
|
18447
|
-
|
|
18448
|
-
|
|
18449
|
-
|
|
18450
|
-
|
|
18451
|
-
|
|
18452
|
-
|
|
18453
|
-
if (limits.contextWindow !== undefined && !/^claude-/i.test(modelId)) {
|
|
18454
|
-
env2.CLAUDE_CODE_MAX_CONTEXT_TOKENS = String(limits.contextWindow);
|
|
18874
|
+
var CLAUDE_MAPPING_KEYS = {
|
|
18875
|
+
defaultModel: "ANTHROPIC_MODEL",
|
|
18876
|
+
fableModel: "ANTHROPIC_DEFAULT_FABLE_MODEL",
|
|
18877
|
+
opusModel: "ANTHROPIC_DEFAULT_OPUS_MODEL",
|
|
18878
|
+
sonnetModel: "ANTHROPIC_DEFAULT_SONNET_MODEL",
|
|
18879
|
+
haikuModel: "ANTHROPIC_DEFAULT_HAIKU_MODEL"
|
|
18880
|
+
};
|
|
18881
|
+
function settingsObject(existing) {
|
|
18882
|
+
if (existing === undefined)
|
|
18883
|
+
return {};
|
|
18884
|
+
try {
|
|
18885
|
+
const parsed = JSON.parse(existing);
|
|
18886
|
+
if (typeof parsed !== "object" || parsed === null || Array.isArray(parsed)) {
|
|
18887
|
+
throw new Error("settings root is not an object");
|
|
18455
18888
|
}
|
|
18456
|
-
return
|
|
18457
|
-
|
|
18458
|
-
|
|
18889
|
+
return parsed;
|
|
18890
|
+
} catch (error51) {
|
|
18891
|
+
const reason = error51 instanceof Error ? error51.message : "invalid JSON";
|
|
18892
|
+
throw new Error(`cannot parse existing settings.json: ${reason}`);
|
|
18893
|
+
}
|
|
18894
|
+
}
|
|
18895
|
+
function claudeSettings(described, input, mapping, existing) {
|
|
18896
|
+
if (mapping.defaultModel === "")
|
|
18897
|
+
throw new Error("default model is required");
|
|
18898
|
+
const ids = new Set(described.map(({ model }) => model.id));
|
|
18899
|
+
const visibleId = (slot, id) => {
|
|
18900
|
+
if (!ids.has(id))
|
|
18901
|
+
throw new Error(`${slot} names unknown virtual model "${id}"`);
|
|
18902
|
+
const useMirror = input.discoveryMirrors === true && !/^(?:claude|anthropic)/i.test(id);
|
|
18903
|
+
return useMirror ? `claude/${id}` : id;
|
|
18904
|
+
};
|
|
18905
|
+
const settings = settingsObject(existing);
|
|
18906
|
+
const currentEnv = settings.env;
|
|
18907
|
+
const env2 = typeof currentEnv === "object" && currentEnv !== null && !Array.isArray(currentEnv) ? { ...currentEnv } : {};
|
|
18908
|
+
for (const key of Object.values(CLAUDE_MAPPING_KEYS))
|
|
18909
|
+
delete env2[key];
|
|
18910
|
+
delete env2.CLAUDE_CODE_MAX_CONTEXT_TOKENS;
|
|
18911
|
+
env2.ANTHROPIC_BASE_URL = input.baseUrl;
|
|
18912
|
+
env2.ANTHROPIC_AUTH_TOKEN = input.apiKey ?? KEY_PLACEHOLDER;
|
|
18913
|
+
env2.CLAUDE_CODE_ENABLE_GATEWAY_MODEL_DISCOVERY = "1";
|
|
18914
|
+
for (const [slot, key] of Object.entries(CLAUDE_MAPPING_KEYS)) {
|
|
18915
|
+
const id = mapping[slot];
|
|
18916
|
+
if (id !== undefined && id !== "")
|
|
18917
|
+
env2[key] = visibleId(slot, id);
|
|
18918
|
+
}
|
|
18919
|
+
return {
|
|
18920
|
+
path: "settings.json",
|
|
18921
|
+
contents: `${JSON.stringify({ ...settings, env: env2 }, null, 2)}
|
|
18459
18922
|
`
|
|
18460
|
-
|
|
18461
|
-
});
|
|
18923
|
+
};
|
|
18462
18924
|
}
|
|
18463
|
-
function opencodeConfig(described, input) {
|
|
18925
|
+
function opencodeConfig(described, input, mapping) {
|
|
18926
|
+
if (mapping.defaultModel === "")
|
|
18927
|
+
throw new Error("default model is required");
|
|
18928
|
+
const byId = new Map(described.map((entry) => [entry.model.id, entry]));
|
|
18929
|
+
const selected = [];
|
|
18930
|
+
const seen = new Set;
|
|
18931
|
+
for (const slot of Object.keys(CLAUDE_MAPPING_KEYS)) {
|
|
18932
|
+
const id = mapping[slot];
|
|
18933
|
+
if (id === undefined || id === "")
|
|
18934
|
+
continue;
|
|
18935
|
+
const entry = byId.get(id);
|
|
18936
|
+
if (entry === undefined)
|
|
18937
|
+
throw new Error(`${slot} names unknown virtual model "${id}"`);
|
|
18938
|
+
if (!seen.has(id)) {
|
|
18939
|
+
seen.add(id);
|
|
18940
|
+
selected.push(entry);
|
|
18941
|
+
}
|
|
18942
|
+
}
|
|
18464
18943
|
const models = {};
|
|
18465
|
-
for (const { model, limits, label: label2 } of
|
|
18944
|
+
for (const { model, limits, label: label2 } of selected) {
|
|
18466
18945
|
const limit = limits.contextWindow === undefined ? undefined : {
|
|
18467
18946
|
context: limits.contextWindow,
|
|
18468
18947
|
...limits.maxOutputTokens === undefined ? {} : { output: limits.maxOutputTokens }
|
|
@@ -18471,6 +18950,7 @@ function opencodeConfig(described, input) {
|
|
|
18471
18950
|
}
|
|
18472
18951
|
const contents = `${JSON.stringify({
|
|
18473
18952
|
$schema: "https://opencode.ai/config.json",
|
|
18953
|
+
model: `omnigateway/${mapping.defaultModel}`,
|
|
18474
18954
|
provider: {
|
|
18475
18955
|
omnigateway: {
|
|
18476
18956
|
npm: "@ai-sdk/openai-compatible",
|
|
@@ -19867,7 +20347,7 @@ var settingsSet = {
|
|
|
19867
20347
|
};
|
|
19868
20348
|
|
|
19869
20349
|
// apps/cli/src/commands/setup.ts
|
|
19870
|
-
import {
|
|
20350
|
+
import { join as join4 } from "path";
|
|
19871
20351
|
var OPTIONS = {
|
|
19872
20352
|
dir: { type: "string" },
|
|
19873
20353
|
key: { type: "string" },
|
|
@@ -19901,39 +20381,65 @@ ${f.contents}`).join(`
|
|
|
19901
20381
|
function at(dir, file2) {
|
|
19902
20382
|
return { path: join4(dir, file2.path), contents: file2.contents };
|
|
19903
20383
|
}
|
|
20384
|
+
async function promptMapping(models, prompt) {
|
|
20385
|
+
const choices = models.map(({ model }) => model.id).join(", ");
|
|
20386
|
+
if (prompt.input === undefined) {
|
|
20387
|
+
throw new CliError("model mapping requires an interactive terminal");
|
|
20388
|
+
}
|
|
20389
|
+
const ask = async (label2, required2) => {
|
|
20390
|
+
const answer = await prompt.input?.(`${label2} model${required2 ? "" : " (blank to omit)"} [${choices}]: `);
|
|
20391
|
+
if (required2 && answer === "")
|
|
20392
|
+
throw new CliError("default model is required");
|
|
20393
|
+
return answer === "" ? undefined : answer;
|
|
20394
|
+
};
|
|
20395
|
+
const defaultModel = await ask("Default", true);
|
|
20396
|
+
if (defaultModel === undefined)
|
|
20397
|
+
throw new CliError("default model is required");
|
|
20398
|
+
const fableModel = await ask("Fable", false);
|
|
20399
|
+
const opusModel = await ask("Opus", false);
|
|
20400
|
+
const sonnetModel = await ask("Sonnet", false);
|
|
20401
|
+
const haikuModel = await ask("Haiku", false);
|
|
20402
|
+
return {
|
|
20403
|
+
defaultModel,
|
|
20404
|
+
...fableModel === undefined ? {} : { fableModel },
|
|
20405
|
+
...opusModel === undefined ? {} : { opusModel },
|
|
20406
|
+
...sonnetModel === undefined ? {} : { sonnetModel },
|
|
20407
|
+
...haikuModel === undefined ? {} : { haikuModel }
|
|
20408
|
+
};
|
|
20409
|
+
}
|
|
19904
20410
|
var setupClaude = {
|
|
19905
20411
|
usage: "setup claude [--dir <path>] [--key <key>] [--dry-run]",
|
|
19906
|
-
summary: "Write
|
|
20412
|
+
summary: "Write Claude Code settings for this gateway",
|
|
19907
20413
|
options: OPTIONS,
|
|
19908
|
-
async run(args, { ctx, writer, setupFs }) {
|
|
20414
|
+
async run(args, { ctx, writer, prompt, setupFs }) {
|
|
19909
20415
|
const models = await described(ctx);
|
|
19910
|
-
const dir = stringFlag(args.values, "dir") ?? join4(setupFs.homeDir, ".claude"
|
|
20416
|
+
const dir = stringFlag(args.values, "dir") ?? join4(setupFs.homeDir, ".claude");
|
|
19911
20417
|
const key = stringFlag(args.values, "key");
|
|
19912
20418
|
const dryRun2 = boolFlag(args.values, "dry-run");
|
|
19913
|
-
const
|
|
20419
|
+
const mapping = await promptMapping(models, prompt);
|
|
20420
|
+
const path = join4(dir, "settings.json");
|
|
20421
|
+
const file2 = claudeSettings(models, {
|
|
19914
20422
|
baseUrl: baseUrl(ctx),
|
|
19915
20423
|
discoveryMirrors: ctx.config().exposeClaudeCodeAliases,
|
|
19916
20424
|
...key === undefined ? {} : { apiKey: key }
|
|
19917
|
-
}
|
|
19918
|
-
finish(ctx, writer,
|
|
19919
|
-
if (!dryRun2) {
|
|
19920
|
-
note(ctx, writer, `run one with: CLAUDE_CONFIG_DIR=${dirname2(files[0]?.path ?? dir)} claude`);
|
|
19921
|
-
}
|
|
20425
|
+
}, mapping, setupFs.read(path) ?? undefined);
|
|
20426
|
+
finish(ctx, writer, [at(dir, file2)], dryRun2, key, setupFs.write);
|
|
19922
20427
|
}
|
|
19923
20428
|
};
|
|
19924
20429
|
var setupOpencode = {
|
|
19925
20430
|
usage: "setup opencode [--dir <path>] [--key <key>] [--dry-run]",
|
|
19926
20431
|
summary: "Write an opencode.json provider entry for this gateway",
|
|
19927
20432
|
options: OPTIONS,
|
|
19928
|
-
async run(args, { ctx, writer, setupFs }) {
|
|
20433
|
+
async run(args, { ctx, writer, prompt, setupFs }) {
|
|
19929
20434
|
const models = await described(ctx);
|
|
19930
20435
|
const dir = stringFlag(args.values, "dir") ?? setupFs.cwd;
|
|
19931
20436
|
const key = stringFlag(args.values, "key");
|
|
19932
20437
|
const dryRun2 = boolFlag(args.values, "dry-run");
|
|
20438
|
+
const mapping = await promptMapping(models, prompt);
|
|
19933
20439
|
const file2 = opencodeConfig(models, {
|
|
19934
20440
|
baseUrl: baseUrl(ctx),
|
|
19935
20441
|
...key === undefined ? {} : { apiKey: key }
|
|
19936
|
-
});
|
|
20442
|
+
}, mapping);
|
|
19937
20443
|
finish(ctx, writer, [at(dir, file2)], dryRun2, key, setupFs.write);
|
|
19938
20444
|
}
|
|
19939
20445
|
};
|
|
@@ -20316,6 +20822,12 @@ function createPrompt(ctx, writer) {
|
|
|
20316
20822
|
const isTty = process.stdin.isTTY === true;
|
|
20317
20823
|
return {
|
|
20318
20824
|
isTty,
|
|
20825
|
+
async input(question) {
|
|
20826
|
+
if (!isTty)
|
|
20827
|
+
throw new CliError(`${question} \u2014 refusing without a terminal`);
|
|
20828
|
+
writer.err(question);
|
|
20829
|
+
return (await readLine()).trim();
|
|
20830
|
+
},
|
|
20319
20831
|
async secret(question) {
|
|
20320
20832
|
if (!isTty)
|
|
20321
20833
|
return (await readAllStdin()).trim();
|
|
@@ -20336,6 +20848,20 @@ function createPrompt(ctx, writer) {
|
|
|
20336
20848
|
};
|
|
20337
20849
|
}
|
|
20338
20850
|
|
|
20851
|
+
// apps/cli/src/setupFs.ts
|
|
20852
|
+
import { dirname as dirname2 } from "path";
|
|
20853
|
+
function atomicWriteFile(path, contents, ops) {
|
|
20854
|
+
const temporary = `${path}.${process.pid}.tmp`;
|
|
20855
|
+
ops.mkdir(dirname2(path));
|
|
20856
|
+
try {
|
|
20857
|
+
ops.write(temporary, contents);
|
|
20858
|
+
ops.rename(temporary, path);
|
|
20859
|
+
} catch (error51) {
|
|
20860
|
+
ops.remove(temporary);
|
|
20861
|
+
throw error51;
|
|
20862
|
+
}
|
|
20863
|
+
}
|
|
20864
|
+
|
|
20339
20865
|
// apps/cli/src/run.ts
|
|
20340
20866
|
var VERSION = "0.0.0";
|
|
20341
20867
|
async function run(argv, writer, options = {}) {
|
|
@@ -20377,10 +20903,13 @@ async function run(argv, writer, options = {}) {
|
|
|
20377
20903
|
setupFs: options.setupFs ?? {
|
|
20378
20904
|
homeDir: homedir3(),
|
|
20379
20905
|
cwd: process.cwd(),
|
|
20380
|
-
|
|
20381
|
-
|
|
20382
|
-
|
|
20383
|
-
|
|
20906
|
+
read: (path) => existsSync6(path) ? readFileSync3(path, "utf8") : null,
|
|
20907
|
+
write: (path, contents) => atomicWriteFile(path, contents, {
|
|
20908
|
+
mkdir: (directory) => mkdirSync2(directory, { recursive: true }),
|
|
20909
|
+
write: (temporary, data) => writeFileSync2(temporary, data),
|
|
20910
|
+
rename: renameSync,
|
|
20911
|
+
remove: (temporary) => rmSync2(temporary, { force: true })
|
|
20912
|
+
})
|
|
20384
20913
|
},
|
|
20385
20914
|
service: () => options.service?.({ root: ctx.root.root, env: ctx.env }) ?? createServiceDeps({ root: ctx.root.root, env: ctx.env, scope, now: ctx.now }),
|
|
20386
20915
|
foreground: options.foreground ?? runForeground,
|