@jeffusion/bungee-core 5.10.0 → 5.12.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/dist/main.js +31436 -17327
- package/dist/plugins/ai-transformer/index.js.map +2 -2
- package/dist/plugins/anthropic-request-sanitizer/index.js.map +2 -2
- package/dist/plugins/anthropic-tool-name-transformer/index.js.map +2 -2
- package/dist/plugins/chatgpt-oauth/control.js +850 -47
- package/dist/plugins/chatgpt-oauth/control.js.map +16 -7
- package/dist/plugins/chatgpt-oauth/index.js +691 -16
- package/dist/plugins/chatgpt-oauth/index.js.map +15 -7
- package/dist/plugins/chatgpt-oauth/manifest.json +117 -7
- package/dist/plugins/chatgpt-oauth/ui/AccountsPage.svelte +25 -15
- package/dist/plugins/chatgpt-oauth/ui/ChatgptQuotaWidget.svelte +7 -4
- package/dist/plugins/chatgpt-oauth/ui/account-model.js +16 -7
- package/dist/plugins/deepseek-reasoning-fix/index.js.map +2 -2
- package/dist/plugins/key-access/index.js.map +2 -2
- package/dist/plugins/key-rate-limit/index.js.map +2 -2
- package/dist/plugins/local-accounts/control.js.map +2 -2
- package/dist/plugins/local-accounts/index.js.map +2 -2
- package/dist/plugins/model-mapping/control.js +72 -17741
- package/dist/plugins/model-mapping/control.js.map +6 -58
- package/dist/plugins/model-mapping/index.js +32 -17433
- package/dist/plugins/model-mapping/index.js.map +6 -58
- package/dist/plugins/model-mapping/manifest.json +30 -14
- package/dist/plugins/models-dev/control.js +1042 -0
- package/dist/plugins/models-dev/control.js.map +16 -0
- package/dist/plugins/models-dev/index.js +15418 -0
- package/dist/plugins/models-dev/index.js.map +134 -0
- package/dist/plugins/models-dev/manifest.json +199 -0
- package/dist/plugins/models-dev/ui/ModelsDevSettings.svelte +120 -0
- package/dist/plugins/openai-messages-to-chat/index.js.map +2 -2
- package/dist/plugins/signature-repair/index.js.map +2 -2
- package/dist/plugins/token-budget/control.js +524 -9
- package/dist/plugins/token-budget/control.js.map +12 -4
- package/dist/plugins/token-budget/index.js +519 -12
- package/dist/plugins/token-budget/index.js.map +13 -6
- package/dist/plugins/token-budget/manifest.json +16 -2
- package/dist/plugins/token-metering/index.js +93 -2
- package/dist/plugins/token-metering/index.js.map +12 -6
- package/dist/plugins/token-stats/control.js +174 -312
- package/dist/plugins/token-stats/control.js.map +7 -7
- package/dist/plugins/token-stats/index.js +283 -486
- package/dist/plugins/token-stats/index.js.map +16 -12
- package/dist/plugins/token-stats/manifest.json +99 -12
- package/dist/plugins/token-stats/ui/ClientModelPicker.svelte +76 -0
- package/dist/plugins/token-stats/ui/PriceModelPicker.svelte +87 -0
- package/dist/plugins/token-stats/ui/TokenStatsSettings.svelte +136 -80
- package/dist/plugins/token-stats/ui/client-model-search.test.ts +58 -0
- package/dist/plugins/token-stats/ui/client-model-search.ts +16 -0
- package/dist/plugins/token-stats/ui/model-search.ts +45 -0
- package/dist/plugins/token-stats/ui/pricing-catalog.test.ts +114 -0
- package/dist/plugins/token-stats/ui/pricing-catalog.ts +17 -0
- package/package.json +2 -2
|
@@ -14770,6 +14770,512 @@ var require_winston_daily_rotate_file = __commonJS(function(exports, module) {
|
|
|
14770
14770
|
module.exports = DailyRotateFile;
|
|
14771
14771
|
});
|
|
14772
14772
|
|
|
14773
|
+
// packages/core/src/plugin-services/host-rpc.ts
|
|
14774
|
+
import { AsyncLocalStorage } from "async_hooks";
|
|
14775
|
+
|
|
14776
|
+
// packages/core/src/plugin-services/wire-contract.ts
|
|
14777
|
+
import { isProxy } from "util/types";
|
|
14778
|
+
var RPC_JSON_MAX_BYTES = 64 * 1024;
|
|
14779
|
+
var RPC_CONTRACT_MAX_BYTES = 256 * 1024;
|
|
14780
|
+
var JSON_MAX_DEPTH = 64;
|
|
14781
|
+
var SCHEMA_MAX_DEPTH = 64;
|
|
14782
|
+
var RPC_MAX_TIMEOUT_MS = 300000;
|
|
14783
|
+
var RPC_MAX_METHODS = 128;
|
|
14784
|
+
var RPC_SERVICE_ID = /^[a-z][a-z0-9.-]{0,127}$/;
|
|
14785
|
+
var RPC_METHOD_NAME = /^[A-Za-z_][A-Za-z0-9_.-]{0,127}$/;
|
|
14786
|
+
var RPC_CALL_PURPOSES = new Set(["bootstrap", "background", "management", "request", "attempt"]);
|
|
14787
|
+
var RPC_COMMAND_DEDUPLICATION = new Set(["local-transaction", "external-contract", "none"]);
|
|
14788
|
+
var RPC_COMMAND_POLICY_KEYS = new Set(["deduplication", "resultRetentionMs", "quotaBytes", "maxResultBytes"]);
|
|
14789
|
+
var CONTRACT_KEYS = ["id", "version", "methods"];
|
|
14790
|
+
var METHOD_KEYS = [
|
|
14791
|
+
"kind",
|
|
14792
|
+
"input",
|
|
14793
|
+
"output",
|
|
14794
|
+
"purposes",
|
|
14795
|
+
"timeoutMs",
|
|
14796
|
+
"maxInputBytes",
|
|
14797
|
+
"maxOutputBytes",
|
|
14798
|
+
"command"
|
|
14799
|
+
];
|
|
14800
|
+
|
|
14801
|
+
class RpcProtocolError extends Error {
|
|
14802
|
+
code;
|
|
14803
|
+
name = "RpcProtocolError";
|
|
14804
|
+
constructor(code, message) {
|
|
14805
|
+
super(message);
|
|
14806
|
+
this.code = code;
|
|
14807
|
+
}
|
|
14808
|
+
}
|
|
14809
|
+
function failData(category) {
|
|
14810
|
+
throw new RpcProtocolError("invalid_data", `invalid_data in ${category}`);
|
|
14811
|
+
}
|
|
14812
|
+
function failSize() {
|
|
14813
|
+
throw new RpcProtocolError("size_limit", "size_limit: JSON value exceeds the byte limit");
|
|
14814
|
+
}
|
|
14815
|
+
function failContract(reason) {
|
|
14816
|
+
throw new RpcProtocolError("invalid_contract", `invalid_contract: ${reason}`);
|
|
14817
|
+
}
|
|
14818
|
+
function isPlainObject(value) {
|
|
14819
|
+
if (typeof value !== "object" || value === null || Array.isArray(value))
|
|
14820
|
+
return false;
|
|
14821
|
+
if (isProxy(value))
|
|
14822
|
+
return false;
|
|
14823
|
+
const prototype = Object.getPrototypeOf(value);
|
|
14824
|
+
return prototype === Object.prototype || prototype === null;
|
|
14825
|
+
}
|
|
14826
|
+
function isPositiveSafeInteger(value) {
|
|
14827
|
+
return typeof value === "number" && Number.isSafeInteger(value) && value > 0;
|
|
14828
|
+
}
|
|
14829
|
+
function isNonNegativeSafeInteger(value) {
|
|
14830
|
+
return typeof value === "number" && Number.isSafeInteger(value) && value >= 0;
|
|
14831
|
+
}
|
|
14832
|
+
function hasLoneSurrogate(value) {
|
|
14833
|
+
for (let index = 0;index < value.length; index += 1) {
|
|
14834
|
+
const code = value.charCodeAt(index);
|
|
14835
|
+
if (code >= 55296 && code <= 56319) {
|
|
14836
|
+
if (index + 1 >= value.length)
|
|
14837
|
+
return true;
|
|
14838
|
+
const next = value.charCodeAt(index + 1);
|
|
14839
|
+
if (next < 56320 || next > 57343)
|
|
14840
|
+
return true;
|
|
14841
|
+
index += 1;
|
|
14842
|
+
} else if (code >= 56320 && code <= 57343) {
|
|
14843
|
+
return true;
|
|
14844
|
+
}
|
|
14845
|
+
}
|
|
14846
|
+
return false;
|
|
14847
|
+
}
|
|
14848
|
+
function isArrayIndex(key, length) {
|
|
14849
|
+
if (!/^(?:0|[1-9]\d*)$/.test(key))
|
|
14850
|
+
return false;
|
|
14851
|
+
const index = Number(key);
|
|
14852
|
+
return Number.isSafeInteger(index) && index >= 0 && index < length;
|
|
14853
|
+
}
|
|
14854
|
+
function assertKnownKeys(input, allowed, category) {
|
|
14855
|
+
for (const key of Object.keys(input)) {
|
|
14856
|
+
if (!allowed.includes(key))
|
|
14857
|
+
failContract(`unknown ${category} field`);
|
|
14858
|
+
}
|
|
14859
|
+
}
|
|
14860
|
+
function spend(budget, bytes) {
|
|
14861
|
+
budget.left -= bytes;
|
|
14862
|
+
if (budget.left < 0)
|
|
14863
|
+
failSize();
|
|
14864
|
+
}
|
|
14865
|
+
function snapshot(value, depth, ancestors, budget) {
|
|
14866
|
+
if (value === null) {
|
|
14867
|
+
spend(budget, 4);
|
|
14868
|
+
return null;
|
|
14869
|
+
}
|
|
14870
|
+
if (typeof value === "boolean") {
|
|
14871
|
+
spend(budget, value ? 4 : 5);
|
|
14872
|
+
return value;
|
|
14873
|
+
}
|
|
14874
|
+
if (typeof value === "string") {
|
|
14875
|
+
if (hasLoneSurrogate(value))
|
|
14876
|
+
failData("string");
|
|
14877
|
+
spend(budget, Buffer.byteLength(value, "utf8") + 2);
|
|
14878
|
+
return value;
|
|
14879
|
+
}
|
|
14880
|
+
if (typeof value === "number") {
|
|
14881
|
+
if (!Number.isFinite(value))
|
|
14882
|
+
failData("number");
|
|
14883
|
+
spend(budget, 1);
|
|
14884
|
+
return value;
|
|
14885
|
+
}
|
|
14886
|
+
if (typeof value !== "object")
|
|
14887
|
+
failData("json");
|
|
14888
|
+
const object = value;
|
|
14889
|
+
if (isProxy(object))
|
|
14890
|
+
failData("json");
|
|
14891
|
+
if (ancestors.has(object))
|
|
14892
|
+
failData("json");
|
|
14893
|
+
const nextDepth = depth + 1;
|
|
14894
|
+
if (nextDepth > JSON_MAX_DEPTH)
|
|
14895
|
+
failData("json");
|
|
14896
|
+
if (Array.isArray(object)) {
|
|
14897
|
+
if (Object.getPrototypeOf(object) !== Array.prototype)
|
|
14898
|
+
failData("array");
|
|
14899
|
+
const lengthDescriptor = Object.getOwnPropertyDescriptor(object, "length");
|
|
14900
|
+
if (!lengthDescriptor || !("value" in lengthDescriptor) || typeof lengthDescriptor.value !== "number") {
|
|
14901
|
+
failData("array");
|
|
14902
|
+
}
|
|
14903
|
+
const length = lengthDescriptor.value;
|
|
14904
|
+
if (!Number.isSafeInteger(length) || length < 0)
|
|
14905
|
+
failData("array");
|
|
14906
|
+
if (length > budget.left)
|
|
14907
|
+
failSize();
|
|
14908
|
+
spend(budget, 2);
|
|
14909
|
+
if (length > 1)
|
|
14910
|
+
spend(budget, length - 1);
|
|
14911
|
+
ancestors.add(object);
|
|
14912
|
+
const items = new Array(length);
|
|
14913
|
+
let count = 0;
|
|
14914
|
+
for (const key of Reflect.ownKeys(object)) {
|
|
14915
|
+
if (key === "length")
|
|
14916
|
+
continue;
|
|
14917
|
+
if (typeof key !== "string" || !isArrayIndex(key, length))
|
|
14918
|
+
failData("array");
|
|
14919
|
+
const descriptor = Object.getOwnPropertyDescriptor(object, key);
|
|
14920
|
+
if (!descriptor || !descriptor.enumerable || !("value" in descriptor))
|
|
14921
|
+
failData("array");
|
|
14922
|
+
items[Number(key)] = snapshot(descriptor.value, nextDepth, ancestors, budget);
|
|
14923
|
+
count += 1;
|
|
14924
|
+
}
|
|
14925
|
+
if (count !== length)
|
|
14926
|
+
failData("array");
|
|
14927
|
+
ancestors.delete(object);
|
|
14928
|
+
return items;
|
|
14929
|
+
}
|
|
14930
|
+
const prototype = Object.getPrototypeOf(object);
|
|
14931
|
+
if (prototype !== Object.prototype && prototype !== null)
|
|
14932
|
+
failData("object");
|
|
14933
|
+
const keys = Reflect.ownKeys(object);
|
|
14934
|
+
if (keys.length > budget.left)
|
|
14935
|
+
failSize();
|
|
14936
|
+
spend(budget, 2);
|
|
14937
|
+
if (keys.length > 1)
|
|
14938
|
+
spend(budget, keys.length - 1);
|
|
14939
|
+
ancestors.add(object);
|
|
14940
|
+
const result = {};
|
|
14941
|
+
for (const key of keys) {
|
|
14942
|
+
if (typeof key !== "string")
|
|
14943
|
+
failData("object");
|
|
14944
|
+
if (hasLoneSurrogate(key))
|
|
14945
|
+
failData("object");
|
|
14946
|
+
const descriptor = Object.getOwnPropertyDescriptor(object, key);
|
|
14947
|
+
if (!descriptor || !descriptor.enumerable || !("value" in descriptor))
|
|
14948
|
+
failData("object");
|
|
14949
|
+
spend(budget, Buffer.byteLength(key, "utf8") + 3);
|
|
14950
|
+
Object.defineProperty(result, key, {
|
|
14951
|
+
value: snapshot(descriptor.value, nextDepth, ancestors, budget),
|
|
14952
|
+
enumerable: true,
|
|
14953
|
+
writable: true,
|
|
14954
|
+
configurable: true
|
|
14955
|
+
});
|
|
14956
|
+
}
|
|
14957
|
+
ancestors.delete(object);
|
|
14958
|
+
return result;
|
|
14959
|
+
}
|
|
14960
|
+
function snapshotPureInput(input) {
|
|
14961
|
+
try {
|
|
14962
|
+
const pure = snapshot(input, 0, new Set, { left: RPC_CONTRACT_MAX_BYTES });
|
|
14963
|
+
if (Buffer.byteLength(JSON.stringify(pure), "utf8") > RPC_CONTRACT_MAX_BYTES)
|
|
14964
|
+
failContract("input must be bounded pure JSON data");
|
|
14965
|
+
return pure;
|
|
14966
|
+
} catch (error) {
|
|
14967
|
+
if (error instanceof RpcProtocolError && (error.code === "invalid_data" || error.code === "size_limit")) {
|
|
14968
|
+
failContract("input must be bounded pure JSON data");
|
|
14969
|
+
}
|
|
14970
|
+
throw error;
|
|
14971
|
+
}
|
|
14972
|
+
}
|
|
14973
|
+
function checkOptionalNonNegative(value, field) {
|
|
14974
|
+
if (value === undefined)
|
|
14975
|
+
return;
|
|
14976
|
+
if (!isNonNegativeSafeInteger(value))
|
|
14977
|
+
failContract(`${field} must be a non-negative safe integer`);
|
|
14978
|
+
return value;
|
|
14979
|
+
}
|
|
14980
|
+
function checkOptionalFinite(value, field) {
|
|
14981
|
+
if (value === undefined)
|
|
14982
|
+
return;
|
|
14983
|
+
if (typeof value !== "number" || !Number.isFinite(value))
|
|
14984
|
+
failContract(`${field} must be a finite number`);
|
|
14985
|
+
return value;
|
|
14986
|
+
}
|
|
14987
|
+
function checkSchema(input, depth, seen) {
|
|
14988
|
+
if (depth > SCHEMA_MAX_DEPTH)
|
|
14989
|
+
failContract("schema nesting exceeds the limit");
|
|
14990
|
+
if (!isPlainObject(input))
|
|
14991
|
+
failContract("schema must be a plain object");
|
|
14992
|
+
if (seen.has(input))
|
|
14993
|
+
failContract("schema must not contain cycles");
|
|
14994
|
+
seen.add(input);
|
|
14995
|
+
const type = input.type;
|
|
14996
|
+
if (type === "string") {
|
|
14997
|
+
assertKnownKeys(input, ["type", "minLength", "maxLength"], "schema");
|
|
14998
|
+
const min = checkOptionalNonNegative(input.minLength, "minLength");
|
|
14999
|
+
const max = checkOptionalNonNegative(input.maxLength, "maxLength");
|
|
15000
|
+
if (min !== undefined && max !== undefined && min > max)
|
|
15001
|
+
failContract("string minLength must not exceed maxLength");
|
|
15002
|
+
} else if (type === "number") {
|
|
15003
|
+
assertKnownKeys(input, ["type", "integer", "minimum", "maximum"], "schema");
|
|
15004
|
+
if (input.integer !== undefined && typeof input.integer !== "boolean")
|
|
15005
|
+
failContract("number integer flag must be boolean");
|
|
15006
|
+
const min = checkOptionalFinite(input.minimum, "minimum");
|
|
15007
|
+
const max = checkOptionalFinite(input.maximum, "maximum");
|
|
15008
|
+
if (min !== undefined && max !== undefined && min > max)
|
|
15009
|
+
failContract("number minimum must not exceed maximum");
|
|
15010
|
+
} else if (type === "boolean") {
|
|
15011
|
+
assertKnownKeys(input, ["type"], "schema");
|
|
15012
|
+
} else if (type === "null") {
|
|
15013
|
+
assertKnownKeys(input, ["type"], "schema");
|
|
15014
|
+
} else if (type === "literal") {
|
|
15015
|
+
assertKnownKeys(input, ["type", "value"], "schema");
|
|
15016
|
+
if (!Object.prototype.hasOwnProperty.call(input, "value"))
|
|
15017
|
+
failContract("literal schema requires a value");
|
|
15018
|
+
try {
|
|
15019
|
+
snapshot(input.value, 0, new Set, { left: Infinity });
|
|
15020
|
+
} catch (error) {
|
|
15021
|
+
if (error instanceof RpcProtocolError && error.code === "invalid_data") {
|
|
15022
|
+
failContract("literal value must be pure JSON");
|
|
15023
|
+
}
|
|
15024
|
+
throw error;
|
|
15025
|
+
}
|
|
15026
|
+
} else if (type === "array") {
|
|
15027
|
+
assertKnownKeys(input, ["type", "items", "maxItems"], "schema");
|
|
15028
|
+
if (!Object.prototype.hasOwnProperty.call(input, "items"))
|
|
15029
|
+
failContract("array schema requires items");
|
|
15030
|
+
checkSchema(input.items, depth + 1, seen);
|
|
15031
|
+
checkOptionalNonNegative(input.maxItems, "maxItems");
|
|
15032
|
+
} else if (type === "object") {
|
|
15033
|
+
assertKnownKeys(input, ["type", "properties", "optional"], "schema");
|
|
15034
|
+
const properties = input.properties;
|
|
15035
|
+
if (!isPlainObject(properties))
|
|
15036
|
+
failContract("object schema requires a properties record");
|
|
15037
|
+
for (const key of Object.keys(properties))
|
|
15038
|
+
checkSchema(properties[key], depth + 1, seen);
|
|
15039
|
+
const optional = input.optional;
|
|
15040
|
+
if (optional !== undefined) {
|
|
15041
|
+
if (!Array.isArray(optional))
|
|
15042
|
+
failContract("object optional must be an array of field names");
|
|
15043
|
+
const names = new Set;
|
|
15044
|
+
for (const name of optional) {
|
|
15045
|
+
if (typeof name !== "string")
|
|
15046
|
+
failContract("object optional entries must be strings");
|
|
15047
|
+
if (names.has(name))
|
|
15048
|
+
failContract("object optional entries must be unique");
|
|
15049
|
+
names.add(name);
|
|
15050
|
+
if (!Object.prototype.hasOwnProperty.call(properties, name)) {
|
|
15051
|
+
failContract("object optional names must exist in properties");
|
|
15052
|
+
}
|
|
15053
|
+
}
|
|
15054
|
+
}
|
|
15055
|
+
} else if (type === "record") {
|
|
15056
|
+
assertKnownKeys(input, ["type", "values", "maxEntries"], "schema");
|
|
15057
|
+
if (!Object.prototype.hasOwnProperty.call(input, "values"))
|
|
15058
|
+
failContract("record schema requires values");
|
|
15059
|
+
checkSchema(input.values, depth + 1, seen);
|
|
15060
|
+
checkOptionalNonNegative(input.maxEntries, "maxEntries");
|
|
15061
|
+
} else if (type === "union") {
|
|
15062
|
+
assertKnownKeys(input, ["type", "variants"], "schema");
|
|
15063
|
+
const variants = input.variants;
|
|
15064
|
+
if (!Array.isArray(variants) || variants.length === 0) {
|
|
15065
|
+
failContract("union schema requires a non-empty variants array");
|
|
15066
|
+
}
|
|
15067
|
+
for (const variant of variants)
|
|
15068
|
+
checkSchema(variant, depth + 1, seen);
|
|
15069
|
+
} else if (type === "json") {
|
|
15070
|
+
assertKnownKeys(input, ["type", "maxBytes"], "schema");
|
|
15071
|
+
if (input.maxBytes !== undefined && !isPositiveSafeInteger(input.maxBytes)) {
|
|
15072
|
+
failContract("json schema maxBytes must be a positive safe integer");
|
|
15073
|
+
}
|
|
15074
|
+
} else {
|
|
15075
|
+
failContract("unknown schema type");
|
|
15076
|
+
}
|
|
15077
|
+
seen.delete(input);
|
|
15078
|
+
}
|
|
15079
|
+
function checkByteLimit(value, field) {
|
|
15080
|
+
if (value === undefined)
|
|
15081
|
+
return;
|
|
15082
|
+
if (!isPositiveSafeInteger(value) || value > RPC_JSON_MAX_BYTES) {
|
|
15083
|
+
failContract(`${field} must be a positive integer no larger than the RPC envelope`);
|
|
15084
|
+
}
|
|
15085
|
+
return value;
|
|
15086
|
+
}
|
|
15087
|
+
function checkCommandPolicy(policy, maxOutputBytes) {
|
|
15088
|
+
const keys = Object.keys(policy);
|
|
15089
|
+
if (keys.length !== RPC_COMMAND_POLICY_KEYS.size || keys.some((key) => !RPC_COMMAND_POLICY_KEYS.has(key))) {
|
|
15090
|
+
failContract("command policy fields are fixed");
|
|
15091
|
+
}
|
|
15092
|
+
const deduplication = policy.deduplication;
|
|
15093
|
+
if (typeof deduplication !== "string" || !RPC_COMMAND_DEDUPLICATION.has(deduplication)) {
|
|
15094
|
+
failContract("invalid command deduplication");
|
|
15095
|
+
}
|
|
15096
|
+
const retention = policy.resultRetentionMs;
|
|
15097
|
+
if (retention !== null && !isPositiveSafeInteger(retention)) {
|
|
15098
|
+
failContract("resultRetentionMs must be a positive integer or null");
|
|
15099
|
+
}
|
|
15100
|
+
const maxResultBytes = policy.maxResultBytes;
|
|
15101
|
+
if (!isPositiveSafeInteger(maxResultBytes))
|
|
15102
|
+
failContract("maxResultBytes must be a positive safe integer");
|
|
15103
|
+
if (maxResultBytes > maxOutputBytes)
|
|
15104
|
+
failContract("maxResultBytes must not exceed maxOutputBytes");
|
|
15105
|
+
const quotaBytes = policy.quotaBytes;
|
|
15106
|
+
if (!isPositiveSafeInteger(quotaBytes))
|
|
15107
|
+
failContract("quotaBytes must be a positive safe integer");
|
|
15108
|
+
if (quotaBytes < maxResultBytes)
|
|
15109
|
+
failContract("quotaBytes must be able to hold maxResultBytes");
|
|
15110
|
+
}
|
|
15111
|
+
function checkMethod(definition) {
|
|
15112
|
+
assertKnownKeys(definition, METHOD_KEYS, "method");
|
|
15113
|
+
const kind = definition.kind;
|
|
15114
|
+
if (kind !== "query" && kind !== "command")
|
|
15115
|
+
failContract("method kind must be query or command");
|
|
15116
|
+
checkSchema(definition.input, 0, new Set);
|
|
15117
|
+
checkSchema(definition.output, 0, new Set);
|
|
15118
|
+
const purposes = definition.purposes;
|
|
15119
|
+
if (!Array.isArray(purposes) || purposes.length === 0)
|
|
15120
|
+
failContract("purposes must be a non-empty array");
|
|
15121
|
+
const seenPurposes = new Set;
|
|
15122
|
+
for (const purpose of purposes) {
|
|
15123
|
+
if (typeof purpose !== "string" || !RPC_CALL_PURPOSES.has(purpose))
|
|
15124
|
+
failContract("invalid purpose");
|
|
15125
|
+
if (seenPurposes.has(purpose))
|
|
15126
|
+
failContract("purposes must be unique");
|
|
15127
|
+
seenPurposes.add(purpose);
|
|
15128
|
+
}
|
|
15129
|
+
if (definition.timeoutMs !== undefined) {
|
|
15130
|
+
if (!isPositiveSafeInteger(definition.timeoutMs) || definition.timeoutMs > RPC_MAX_TIMEOUT_MS) {
|
|
15131
|
+
failContract("timeoutMs must be a positive integer no larger than the timeout bound");
|
|
15132
|
+
}
|
|
15133
|
+
}
|
|
15134
|
+
checkByteLimit(definition.maxInputBytes, "maxInputBytes");
|
|
15135
|
+
const maxOutputBytes = checkByteLimit(definition.maxOutputBytes, "maxOutputBytes");
|
|
15136
|
+
const command = definition.command;
|
|
15137
|
+
if (kind === "command") {
|
|
15138
|
+
if (!isPlainObject(command))
|
|
15139
|
+
failContract("command methods require an explicit command policy");
|
|
15140
|
+
checkCommandPolicy(command, maxOutputBytes ?? RPC_JSON_MAX_BYTES);
|
|
15141
|
+
} else if (command !== undefined) {
|
|
15142
|
+
failContract("query methods must not declare a command policy");
|
|
15143
|
+
}
|
|
15144
|
+
}
|
|
15145
|
+
function checkContract(contract) {
|
|
15146
|
+
if (!isPlainObject(contract))
|
|
15147
|
+
failContract("contract must be a plain object");
|
|
15148
|
+
assertKnownKeys(contract, CONTRACT_KEYS, "contract");
|
|
15149
|
+
if (typeof contract.id !== "string" || !RPC_SERVICE_ID.test(contract.id))
|
|
15150
|
+
failContract("invalid service id");
|
|
15151
|
+
if (!isPositiveSafeInteger(contract.version))
|
|
15152
|
+
failContract("service version must be a positive safe integer");
|
|
15153
|
+
const methods = contract.methods;
|
|
15154
|
+
if (!isPlainObject(methods))
|
|
15155
|
+
failContract("methods must be a plain object");
|
|
15156
|
+
const names = Object.keys(methods);
|
|
15157
|
+
if (names.length === 0)
|
|
15158
|
+
failContract("service must declare at least one method");
|
|
15159
|
+
if (names.length > RPC_MAX_METHODS)
|
|
15160
|
+
failContract("service declares too many methods");
|
|
15161
|
+
for (const name of names) {
|
|
15162
|
+
if (!RPC_METHOD_NAME.test(name))
|
|
15163
|
+
failContract("invalid method name");
|
|
15164
|
+
const definition = methods[name];
|
|
15165
|
+
if (!isPlainObject(definition))
|
|
15166
|
+
failContract("method definition must be a plain object");
|
|
15167
|
+
checkMethod(definition);
|
|
15168
|
+
}
|
|
15169
|
+
}
|
|
15170
|
+
function deepFreeze(value) {
|
|
15171
|
+
if (Array.isArray(value)) {
|
|
15172
|
+
for (const item of value)
|
|
15173
|
+
deepFreeze(item);
|
|
15174
|
+
return Object.freeze(value);
|
|
15175
|
+
}
|
|
15176
|
+
if (isPlainObject(value)) {
|
|
15177
|
+
for (const key of Object.keys(value))
|
|
15178
|
+
deepFreeze(value[key]);
|
|
15179
|
+
return Object.freeze(value);
|
|
15180
|
+
}
|
|
15181
|
+
return value;
|
|
15182
|
+
}
|
|
15183
|
+
function defineRpcService(contract) {
|
|
15184
|
+
const pure = snapshotPureInput(contract);
|
|
15185
|
+
checkContract(pure);
|
|
15186
|
+
return deepFreeze(pure);
|
|
15187
|
+
}
|
|
15188
|
+
|
|
15189
|
+
// packages/core/src/plugin-services/rpc-runtime.ts
|
|
15190
|
+
var PROCESSES = new Set(["control", "worker", "ingress"]);
|
|
15191
|
+
var SCOPES = new Set(["global", "binding"]);
|
|
15192
|
+
var PURPOSES = new Set(["bootstrap", "background", "management", "request", "attempt"]);
|
|
15193
|
+
var ENDPOINTS = new WeakMap;
|
|
15194
|
+
var REVOKED = new WeakMap;
|
|
15195
|
+
|
|
15196
|
+
// packages/core/src/plugin-services/host-rpc.ts
|
|
15197
|
+
var SERVICE_ERROR_MESSAGES = {
|
|
15198
|
+
unauthorized: "RPC call is not authorized",
|
|
15199
|
+
not_ready: "RPC endpoint is not ready",
|
|
15200
|
+
retired: "RPC endpoint is retiring",
|
|
15201
|
+
revoked: "RPC endpoint generation was revoked",
|
|
15202
|
+
unsupported_method: "RPC method is not published",
|
|
15203
|
+
wrong_purpose: "RPC method is not published for this purpose",
|
|
15204
|
+
invalid_input: "RPC input is not valid",
|
|
15205
|
+
invalid_output: "RPC output is not valid",
|
|
15206
|
+
invalid_operation_id: "RPC command operation id is invalid",
|
|
15207
|
+
overloaded: "RPC runtime is at capacity",
|
|
15208
|
+
cancelled: "RPC call was cancelled",
|
|
15209
|
+
timeout: "RPC call deadline exceeded",
|
|
15210
|
+
unknown: "RPC command outcome is unknown",
|
|
15211
|
+
capability_unavailable: "RPC command execution is unavailable",
|
|
15212
|
+
closed: "RPC runtime is closed",
|
|
15213
|
+
failed: "RPC call failed",
|
|
15214
|
+
conflict: "RPC command identity conflicts with an existing record",
|
|
15215
|
+
expired: "RPC command result has expired",
|
|
15216
|
+
pending: "RPC command is still pending",
|
|
15217
|
+
rejected: "RPC command was rejected",
|
|
15218
|
+
missing: "RPC command has no stored result",
|
|
15219
|
+
storage_failure: "RPC command storage failed",
|
|
15220
|
+
deadlock: "RPC call chain would deadlock",
|
|
15221
|
+
call_depth_exceeded: "RPC call depth exceeded",
|
|
15222
|
+
undeclared: "RPC service is not declared by the manifest",
|
|
15223
|
+
unavailable: "RPC service is unavailable",
|
|
15224
|
+
ambiguous_placement: "RPC service placement is ambiguous",
|
|
15225
|
+
invalid_registration: "RPC registration is invalid"
|
|
15226
|
+
};
|
|
15227
|
+
var SERVICE_ERROR_CODES = new Set(Object.keys(SERVICE_ERROR_MESSAGES));
|
|
15228
|
+
var EMPTY_OPTIONS = Object.freeze({});
|
|
15229
|
+
var FRAME_STORE = new AsyncLocalStorage;
|
|
15230
|
+
var CALLEE_INFO = new WeakMap;
|
|
15231
|
+
// packages/core/src/plugin-services/peer-channel-protocol.ts
|
|
15232
|
+
var CHANNEL_REQUEST_MAX_BYTES = 4 * 1024;
|
|
15233
|
+
var CHANNEL_RESULT_MAX_BYTES = 60 * 1024;
|
|
15234
|
+
var CHANNEL_MAX_CHUNK_BYTES = 60 * 1024;
|
|
15235
|
+
var PLUGIN_CHANNEL_LANES = Object.freeze(["event", "snapshot", "stream"]);
|
|
15236
|
+
var ERROR_CODES = new Set([
|
|
15237
|
+
"unavailable",
|
|
15238
|
+
"ambiguous",
|
|
15239
|
+
"unauthorized",
|
|
15240
|
+
"invalid",
|
|
15241
|
+
"overloaded",
|
|
15242
|
+
"expired",
|
|
15243
|
+
"conflict",
|
|
15244
|
+
"gap",
|
|
15245
|
+
"truncated",
|
|
15246
|
+
"rejected",
|
|
15247
|
+
"cancelled",
|
|
15248
|
+
"closed",
|
|
15249
|
+
"unknown",
|
|
15250
|
+
"failed"
|
|
15251
|
+
]);
|
|
15252
|
+
var RPC_CALL_PURPOSES2 = new Set(["bootstrap", "background", "management", "request", "attempt"]);
|
|
15253
|
+
|
|
15254
|
+
// packages/core/src/plugin-services/peer-channel-hub.ts
|
|
15255
|
+
var CHANNEL_MAX_TRANSFER_BUFFER_BYTES = 4 * CHANNEL_MAX_CHUNK_BYTES;
|
|
15256
|
+
var CHANNEL_MAX_TOTAL_BUFFER_BYTES = 16 * CHANNEL_MAX_CHUNK_BYTES;
|
|
15257
|
+
var CHANNEL_STREAM_MAX_TOTAL_BYTES = 64 * 1024 * 1024;
|
|
15258
|
+
var CHANNEL_STREAM_MAX_CREDIT_BYTES = 8 * CHANNEL_MAX_CHUNK_BYTES;
|
|
15259
|
+
var CHANNEL_STREAM_DEFAULT_CREDIT_BYTES = 4 * CHANNEL_MAX_CHUNK_BYTES;
|
|
15260
|
+
var CHANNEL_SNAPSHOT_MAX_BYTES = 64 * 1024 * 1024;
|
|
15261
|
+
var CHANNEL_EVENT_MAX_PAYLOAD_BYTES = 60 * 1024;
|
|
15262
|
+
var EMPTY = new Uint8Array(0);
|
|
15263
|
+
var HANDLE_REGISTRATIONS = new WeakMap;
|
|
15264
|
+
|
|
15265
|
+
// packages/core/src/plugin-services/snapshot-store.ts
|
|
15266
|
+
var DEFAULT_CHUNK_BYTES = 60 * 1024;
|
|
15267
|
+
var SNAPSHOT_FAMILY_REFS = new Map;
|
|
15268
|
+
|
|
15269
|
+
// packages/core/src/plugin-services.ts
|
|
15270
|
+
var CHANNEL_KINDS = new Set(["events", "snapshot", "stream"]);
|
|
15271
|
+
|
|
15272
|
+
// plugins/chatgpt-oauth/server/rpc.ts
|
|
15273
|
+
var command = { deduplication: "none", resultRetentionMs: null, quotaBytes: 65536, maxResultBytes: 65536 };
|
|
15274
|
+
var businessRpc = defineRpcService({ id: "chatgpt-oauth.credentials.v1", version: 1, methods: {
|
|
15275
|
+
getCredential: { kind: "command", input: { type: "object", properties: {} }, output: { type: "object", properties: { version: { type: "number", integer: true, minimum: 1 }, expiresAt: { type: "number" }, headers: { type: "record", values: { type: "string" }, maxEntries: 16 } } }, purposes: ["attempt"], command, timeoutMs: 15000 },
|
|
15276
|
+
rejectAccess: { kind: "command", input: { type: "object", properties: { version: { type: "number", integer: true, minimum: 1 } } }, output: { type: "object", properties: { rejected: { type: "boolean" } } }, purposes: ["attempt"], command, timeoutMs: 15000 }
|
|
15277
|
+
} });
|
|
15278
|
+
|
|
14773
15279
|
// packages/core/src/logger.ts
|
|
14774
15280
|
var import_winston = __toESM(require_winston());
|
|
14775
15281
|
var import_winston_daily_rotate_file = __toESM(require_winston_daily_rotate_file());
|
|
@@ -15282,6 +15788,14 @@ async function* parseCodexSSE(source, options = {}) {
|
|
|
15282
15788
|
yield* consumeLine(remainingLine);
|
|
15283
15789
|
yield* dispatch();
|
|
15284
15790
|
}
|
|
15791
|
+
function chatToolCall(state, value, includeIdentity, preserveCustomTools) {
|
|
15792
|
+
const custom = preserveCustomTools && state.kind === "custom_tool_call";
|
|
15793
|
+
return {
|
|
15794
|
+
index: state.index,
|
|
15795
|
+
...includeIdentity ? { id: state.id, type: custom ? "custom" : "function" } : {},
|
|
15796
|
+
[custom ? "custom" : "function"]: { ...includeIdentity ? { name: state.name } : {}, [custom ? "input" : "arguments"]: value }
|
|
15797
|
+
};
|
|
15798
|
+
}
|
|
15285
15799
|
function streamIncludesUsage(request) {
|
|
15286
15800
|
return request?.stream_options?.include_usage === true;
|
|
15287
15801
|
}
|
|
@@ -15366,6 +15880,7 @@ class CodexResponseProcessor {
|
|
|
15366
15880
|
output = [];
|
|
15367
15881
|
includeUsage;
|
|
15368
15882
|
target;
|
|
15883
|
+
preserveCustomTools;
|
|
15369
15884
|
text = "";
|
|
15370
15885
|
reasoning = "";
|
|
15371
15886
|
messageText = new Map;
|
|
@@ -15385,6 +15900,7 @@ class CodexResponseProcessor {
|
|
|
15385
15900
|
constructor(options = {}) {
|
|
15386
15901
|
this.includeUsage = options.includeUsage ?? (options.request ? streamIncludesUsage(options.request) : false);
|
|
15387
15902
|
this.target = options.target ?? "chat";
|
|
15903
|
+
this.preserveCustomTools = options.preserveCustomTools ?? false;
|
|
15388
15904
|
this.redactDiagnostic = options.redactDiagnostic;
|
|
15389
15905
|
}
|
|
15390
15906
|
validateOutputItem(item) {
|
|
@@ -15555,7 +16071,7 @@ class CodexResponseProcessor {
|
|
|
15555
16071
|
this.tools.set(`output:${String(data.output_index)}`, state);
|
|
15556
16072
|
const chunk = base();
|
|
15557
16073
|
chunk.choices[0].delta.role = "assistant";
|
|
15558
|
-
chunk.choices[0].delta.tool_calls = [
|
|
16074
|
+
chunk.choices[0].delta.tool_calls = [chatToolCall(state, "", true, this.preserveCustomTools)];
|
|
15559
16075
|
output.push(chunk);
|
|
15560
16076
|
} else if (type === "response.function_call_arguments.delta" || type === "response.custom_tool_call_input.delta") {
|
|
15561
16077
|
const state = this.findTool(data);
|
|
@@ -15564,7 +16080,7 @@ class CodexResponseProcessor {
|
|
|
15564
16080
|
state.arguments += delta;
|
|
15565
16081
|
state.emittedArguments = true;
|
|
15566
16082
|
const chunk = base();
|
|
15567
|
-
chunk.choices[0].delta.tool_calls = [
|
|
16083
|
+
chunk.choices[0].delta.tool_calls = [chatToolCall(state, delta, false, this.preserveCustomTools)];
|
|
15568
16084
|
output.push(chunk);
|
|
15569
16085
|
}
|
|
15570
16086
|
} else if (type === "response.function_call_arguments.done" || type === "response.custom_tool_call_input.done") {
|
|
@@ -15575,7 +16091,7 @@ class CodexResponseProcessor {
|
|
|
15575
16091
|
if (state && !state.emittedArguments && state.arguments) {
|
|
15576
16092
|
state.emittedArguments = true;
|
|
15577
16093
|
const chunk = base();
|
|
15578
|
-
chunk.choices[0].delta.tool_calls = [
|
|
16094
|
+
chunk.choices[0].delta.tool_calls = [chatToolCall(state, state.arguments, false, this.preserveCustomTools)];
|
|
15579
16095
|
output.push(chunk);
|
|
15580
16096
|
}
|
|
15581
16097
|
} else if (type === "response.output_item.done") {
|
|
@@ -15589,7 +16105,7 @@ class CodexResponseProcessor {
|
|
|
15589
16105
|
if (!state.emittedArguments && state.arguments) {
|
|
15590
16106
|
state.emittedArguments = true;
|
|
15591
16107
|
const chunk = base();
|
|
15592
|
-
chunk.choices[0].delta.tool_calls = [
|
|
16108
|
+
chunk.choices[0].delta.tool_calls = [chatToolCall(state, state.arguments, false, this.preserveCustomTools)];
|
|
15593
16109
|
output.push(chunk);
|
|
15594
16110
|
}
|
|
15595
16111
|
} else {
|
|
@@ -15599,7 +16115,7 @@ class CodexResponseProcessor {
|
|
|
15599
16115
|
if (data.output_index !== undefined)
|
|
15600
16116
|
this.tools.set(`output:${String(data.output_index)}`, state2);
|
|
15601
16117
|
const chunk = base();
|
|
15602
|
-
chunk.choices[0].delta.tool_calls = [
|
|
16118
|
+
chunk.choices[0].delta.tool_calls = [chatToolCall(state2, state2.arguments, true, this.preserveCustomTools)];
|
|
15603
16119
|
output.push(chunk);
|
|
15604
16120
|
}
|
|
15605
16121
|
this.upsertOutput(item, data.output_index === undefined ? undefined : Number(data.output_index), this.target === "responses", data.content_index === undefined ? undefined : Number(data.content_index), typeof data.item_id === "string" ? data.item_id : undefined);
|
|
@@ -15724,7 +16240,7 @@ async function consumeCodexResponse(source, options = {}) {
|
|
|
15724
16240
|
processor.process(event);
|
|
15725
16241
|
return processor.finish();
|
|
15726
16242
|
}
|
|
15727
|
-
function responsesToChatCompletion(response) {
|
|
16243
|
+
function responsesToChatCompletion(response, preserveCustomTools = false) {
|
|
15728
16244
|
let content = "";
|
|
15729
16245
|
let reasoning = "";
|
|
15730
16246
|
const tool_calls = [];
|
|
@@ -15737,7 +16253,9 @@ function responsesToChatCompletion(response) {
|
|
|
15737
16253
|
content += textFromItem(item);
|
|
15738
16254
|
if (item.type === "reasoning")
|
|
15739
16255
|
reasoning += (item.summary ?? []).filter((part) => part.type === "summary_text").map((part) => String(part.text ?? "")).join("") + (item.content ?? []).filter((part) => part.type === "reasoning_text").map((part) => String(part.text ?? "")).join("");
|
|
15740
|
-
if (item.type === "
|
|
16256
|
+
if (item.type === "custom_tool_call" && preserveCustomTools)
|
|
16257
|
+
tool_calls.push({ id: item.call_id, type: "custom", custom: { name: item.name, input: String(item.input ?? "") } });
|
|
16258
|
+
else if (item.type === "function_call" || item.type === "custom_tool_call")
|
|
15741
16259
|
tool_calls.push({ id: item.call_id, type: "function", function: { name: item.name, arguments: String(item.arguments ?? item.input ?? "") } });
|
|
15742
16260
|
if (item.type === "image_generation_call" && item.result)
|
|
15743
16261
|
images.push({ type: "image_url", image_url: { url: `data:${imageMime(item.output_format)};base64,${item.result}` } });
|
|
@@ -15840,13 +16358,140 @@ var MAX_DISCARD_BYTES = 64 * 1024;
|
|
|
15840
16358
|
var MAX_MODELS_BODY_BYTES = 256 * 1024;
|
|
15841
16359
|
var MAX_PROFILE_HEADER_VALUE_BYTES = 8192;
|
|
15842
16360
|
var CHATGPT_ORIGIN = "https://chatgpt.com";
|
|
16361
|
+
var SIWC_ORIGIN = "https://api.openai.com";
|
|
15843
16362
|
var CODEX_ROUTING_HINT_HEADER = "X-Codex-Routing-Hint";
|
|
16363
|
+
var SIWC_FORBIDDEN_FIELDS = [
|
|
16364
|
+
"background",
|
|
16365
|
+
"conversation",
|
|
16366
|
+
"max_output_tokens",
|
|
16367
|
+
"max_completion_tokens",
|
|
16368
|
+
"max_tool_calls",
|
|
16369
|
+
"metadata",
|
|
16370
|
+
"moderation",
|
|
16371
|
+
"multi_agent",
|
|
16372
|
+
"prompt",
|
|
16373
|
+
"prompt_cache_retention",
|
|
16374
|
+
"safety_identifier",
|
|
16375
|
+
"temperature",
|
|
16376
|
+
"top_logprobs",
|
|
16377
|
+
"top_p",
|
|
16378
|
+
"truncation",
|
|
16379
|
+
"user",
|
|
16380
|
+
"previous_response_id",
|
|
16381
|
+
"client_metadata",
|
|
16382
|
+
"context_management",
|
|
16383
|
+
"prompt_cache_options"
|
|
16384
|
+
];
|
|
15844
16385
|
function record(value) {
|
|
15845
16386
|
if (typeof value !== "object" || value === null || Array.isArray(value)) {
|
|
15846
16387
|
throw new CodexProtocolError("invalid_response", "Request must be a JSON object");
|
|
15847
16388
|
}
|
|
15848
16389
|
return value;
|
|
15849
16390
|
}
|
|
16391
|
+
function siwcTool(tool) {
|
|
16392
|
+
const value = record(tool);
|
|
16393
|
+
if (value.type !== "function" && value.type !== "custom") {
|
|
16394
|
+
throw new CodexProtocolError("invalid_response", "SIWC supports only function and custom tools");
|
|
16395
|
+
}
|
|
16396
|
+
const nested = value.type === "function" ? value.function : value.custom;
|
|
16397
|
+
const definition = nested === undefined ? value : record(nested);
|
|
16398
|
+
if (typeof definition.name !== "string" || !/^[A-Za-z0-9_-]{1,64}$/.test(definition.name)) {
|
|
16399
|
+
throw new CodexProtocolError("invalid_response", "SIWC tool names must be 1-64 ASCII letters, digits, underscores or hyphens");
|
|
16400
|
+
}
|
|
16401
|
+
const normalized = { ...definition, type: value.type };
|
|
16402
|
+
if (value.type === "custom" && normalized.format?.type === "grammar" && normalized.format.grammar !== undefined) {
|
|
16403
|
+
const grammar = record(normalized.format.grammar);
|
|
16404
|
+
if (!["lark", "regex"].includes(grammar.syntax) || typeof grammar.definition !== "string") {
|
|
16405
|
+
throw new CodexProtocolError("invalid_response", "SIWC custom tool grammar is invalid");
|
|
16406
|
+
}
|
|
16407
|
+
normalized.format = { type: "grammar", syntax: grammar.syntax, definition: grammar.definition };
|
|
16408
|
+
}
|
|
16409
|
+
return normalized;
|
|
16410
|
+
}
|
|
16411
|
+
function normalizeSiwcRequest(input, target) {
|
|
16412
|
+
if (input.previous_response_id !== undefined) {
|
|
16413
|
+
throw new CodexProtocolError("invalid_response", "SIWC requires the full conversation in input; previous_response_id is unsupported");
|
|
16414
|
+
}
|
|
16415
|
+
if (input.tools !== undefined && !Array.isArray(input.tools)) {
|
|
16416
|
+
throw new CodexProtocolError("invalid_response", "SIWC tools must be an array");
|
|
16417
|
+
}
|
|
16418
|
+
input.tools?.forEach(siwcTool);
|
|
16419
|
+
if (target === "chat" && !Array.isArray(input.messages)) {
|
|
16420
|
+
throw new CodexProtocolError("invalid_response", "Chat messages must be an array");
|
|
16421
|
+
}
|
|
16422
|
+
const out = target === "chat" ? convertChatCompletionsRequestToCodex(input) : JSON.parse(JSON.stringify(input));
|
|
16423
|
+
out.store = false;
|
|
16424
|
+
out.stream = true;
|
|
16425
|
+
if (out.instructions === undefined || out.instructions === null)
|
|
16426
|
+
out.instructions = "";
|
|
16427
|
+
if (typeof out.instructions !== "string")
|
|
16428
|
+
throw new CodexProtocolError("invalid_response", "SIWC instructions must be text");
|
|
16429
|
+
if (typeof out.input === "string")
|
|
16430
|
+
out.input = [{ type: "message", role: "user", content: [{ type: "input_text", text: out.input }] }];
|
|
16431
|
+
if (out.input === undefined)
|
|
16432
|
+
out.input = [];
|
|
16433
|
+
if (!Array.isArray(out.input))
|
|
16434
|
+
throw new CodexProtocolError("invalid_response", "SIWC input must contain the full conversation as an array");
|
|
16435
|
+
const inputTypes = new Set(["message", "function_call", "function_call_output", "custom_tool_call", "custom_tool_call_output", "reasoning", "compaction"]);
|
|
16436
|
+
for (const item of out.input) {
|
|
16437
|
+
const value = record(item);
|
|
16438
|
+
if (value.type === undefined && typeof value.role === "string")
|
|
16439
|
+
value.type = "message";
|
|
16440
|
+
if (!inputTypes.has(value.type))
|
|
16441
|
+
throw new CodexProtocolError("invalid_response", "SIWC input contains an unsupported item");
|
|
16442
|
+
if (value.type === "message") {
|
|
16443
|
+
if (!["system", "developer", "user", "assistant"].includes(value.role))
|
|
16444
|
+
throw new CodexProtocolError("invalid_response", "SIWC input contains an unsupported role");
|
|
16445
|
+
if (value.role === "system")
|
|
16446
|
+
value.role = "developer";
|
|
16447
|
+
}
|
|
16448
|
+
}
|
|
16449
|
+
if (Array.isArray(out.tools))
|
|
16450
|
+
out.tools = out.tools.map(siwcTool);
|
|
16451
|
+
if (out.tool_choice !== undefined) {
|
|
16452
|
+
if (typeof out.tool_choice === "string") {
|
|
16453
|
+
if (!["auto", "none", "required"].includes(out.tool_choice))
|
|
16454
|
+
throw new CodexProtocolError("invalid_response", "SIWC tool choice is unsupported");
|
|
16455
|
+
} else
|
|
16456
|
+
out.tool_choice = siwcTool(out.tool_choice);
|
|
16457
|
+
}
|
|
16458
|
+
for (const field of SIWC_FORBIDDEN_FIELDS)
|
|
16459
|
+
delete out[field];
|
|
16460
|
+
return out;
|
|
16461
|
+
}
|
|
16462
|
+
function setSiwcHeaders(context, target) {
|
|
16463
|
+
for (const name of Object.keys(context.headers)) {
|
|
16464
|
+
if (/^(chatgpt-account-id|session-id|thread-id|version|x-codex-.*|x-openai-internal-codex-.*)$/i.test(name))
|
|
16465
|
+
delete context.headers[name];
|
|
16466
|
+
}
|
|
16467
|
+
setHeader(context.headers, "User-Agent", "Bungee/5.11.0");
|
|
16468
|
+
setHeader(context.headers, "Originator", "Bungee");
|
|
16469
|
+
setHeader(context.headers, "Accept", target === "models" ? "application/json" : "text/event-stream");
|
|
16470
|
+
if (target !== "models")
|
|
16471
|
+
setHeader(context.headers, "Content-Type", "application/json");
|
|
16472
|
+
}
|
|
16473
|
+
function parseSiwcModelsBody(body) {
|
|
16474
|
+
let payload;
|
|
16475
|
+
try {
|
|
16476
|
+
payload = JSON.parse(body);
|
|
16477
|
+
} catch {
|
|
16478
|
+
throw new CodexModelsError("invalid_json");
|
|
16479
|
+
}
|
|
16480
|
+
if (typeof payload !== "object" || payload === null || Array.isArray(payload))
|
|
16481
|
+
throw new CodexModelsError("invalid_structure");
|
|
16482
|
+
const models = payload.models;
|
|
16483
|
+
if (!Array.isArray(models) || models.length > 512)
|
|
16484
|
+
throw new CodexModelsError("invalid_structure");
|
|
16485
|
+
const text = (value) => typeof value === "string" && value.length > 0 && value.length <= 512 && value === value.trim() && !/[\r\n\0]/.test(value);
|
|
16486
|
+
const listed = [];
|
|
16487
|
+
for (const model of models) {
|
|
16488
|
+
if (!model || typeof model !== "object" || Array.isArray(model) || !text(model.slug) || typeof model.visibility !== "string" || model.display_name !== undefined && !text(model.display_name))
|
|
16489
|
+
throw new CodexModelsError("invalid_structure");
|
|
16490
|
+
if (model.visibility === "list")
|
|
16491
|
+
listed.push({ id: model.slug });
|
|
16492
|
+
}
|
|
16493
|
+
return listed;
|
|
16494
|
+
}
|
|
15850
16495
|
function validHeaderValue(value) {
|
|
15851
16496
|
return typeof value === "string" && new TextEncoder().encode(value).byteLength <= MAX_PROFILE_HEADER_VALUE_BYTES && value.trim().length > 0 && !/[\r\n\0]/.test(value);
|
|
15852
16497
|
}
|
|
@@ -15895,7 +16540,7 @@ function responseHeaders(response, contentType) {
|
|
|
15895
16540
|
headers.set("content-type", contentType);
|
|
15896
16541
|
return headers;
|
|
15897
16542
|
}
|
|
15898
|
-
function
|
|
16543
|
+
function errorBody2(error, fallbackCode = "upstream_error") {
|
|
15899
16544
|
return { message: error?.message ?? "Upstream response could not be adapted", type: error?.type ?? "upstream_error", code: error?.code ?? fallbackCode };
|
|
15900
16545
|
}
|
|
15901
16546
|
function completionFromError(error, redact) {
|
|
@@ -16071,7 +16716,7 @@ function serialize(event) {
|
|
|
16071
16716
|
|
|
16072
16717
|
`;
|
|
16073
16718
|
}
|
|
16074
|
-
function protocolStreamBody(source, target, includeUsage, signal, redact) {
|
|
16719
|
+
function protocolStreamBody(source, target, includeUsage, signal, redact, preserveCustomTools = false) {
|
|
16075
16720
|
const protocolController = new AbortController;
|
|
16076
16721
|
const onAbort = () => protocolController.abort(signal.reason ?? "cancelled");
|
|
16077
16722
|
if (signal.aborted)
|
|
@@ -16089,7 +16734,7 @@ function protocolStreamBody(source, target, includeUsage, signal, redact) {
|
|
|
16089
16734
|
const completion = new Promise((resolve) => {
|
|
16090
16735
|
resolveCompletion = resolve;
|
|
16091
16736
|
});
|
|
16092
|
-
const processor = new CodexResponseProcessor({ target, includeUsage, redactDiagnostic: redact });
|
|
16737
|
+
const processor = new CodexResponseProcessor({ target, includeUsage, redactDiagnostic: redact, preserveCustomTools });
|
|
16093
16738
|
let terminalOutcome;
|
|
16094
16739
|
const events = parseCodexSSE(source, { signal: protocolController.signal });
|
|
16095
16740
|
const iterator = async function* () {
|
|
@@ -16119,7 +16764,7 @@ function protocolStreamBody(source, target, includeUsage, signal, redact) {
|
|
|
16119
16764
|
const outcome = completionFromError(error, redact);
|
|
16120
16765
|
settle(outcome.status === "cancelled" ? terminalOutcome ?? outcome : outcome);
|
|
16121
16766
|
if (outcome.status === "failed" && outcome.error) {
|
|
16122
|
-
const safe =
|
|
16767
|
+
const safe = errorBody2(outcome.error, outcome.code);
|
|
16123
16768
|
yield target === "responses" ? `event: error
|
|
16124
16769
|
data: ${JSON.stringify({ type: "error", code: safe.code, message: safe.message, param: null, error: safe })}
|
|
16125
16770
|
|
|
@@ -16161,6 +16806,26 @@ class ChatgptOauthAdapter {
|
|
|
16161
16806
|
constructor() {}
|
|
16162
16807
|
beforeRequest(context) {
|
|
16163
16808
|
const target = context.url.pathname === MODELS_PATH ? "models" : context.url.pathname === CHAT_COMPLETIONS_PATH ? "chat" : context.url.pathname === RESPONSES_PATH ? "responses" : undefined;
|
|
16809
|
+
if (context.url.origin === SIWC_ORIGIN) {
|
|
16810
|
+
if (target === undefined)
|
|
16811
|
+
return context;
|
|
16812
|
+
const input = target === "models" ? undefined : record(context.body);
|
|
16813
|
+
const stream = input?.stream === true;
|
|
16814
|
+
const includeUsage = input ? streamIncludesUsage(input) : false;
|
|
16815
|
+
context.body = input ? normalizeSiwcRequest(input, target) : undefined;
|
|
16816
|
+
if (target !== "models")
|
|
16817
|
+
context.url.pathname = RESPONSES_PATH;
|
|
16818
|
+
setSiwcHeaders(context, target);
|
|
16819
|
+
this.requests.set(context.requestId, Object.freeze({
|
|
16820
|
+
target,
|
|
16821
|
+
stream,
|
|
16822
|
+
includeUsage,
|
|
16823
|
+
siwc: true,
|
|
16824
|
+
allowMissingContentType: target !== "models",
|
|
16825
|
+
adaptedResponses: new WeakSet
|
|
16826
|
+
}));
|
|
16827
|
+
return context;
|
|
16828
|
+
}
|
|
16164
16829
|
if (context.url.pathname === CODEX_RESPONSES_PATH) {
|
|
16165
16830
|
setCodexRoutingHint(context.headers, context.body);
|
|
16166
16831
|
enforceCodexResponsesLite(context);
|
|
@@ -16216,6 +16881,14 @@ class ChatgptOauthAdapter {
|
|
|
16216
16881
|
return context;
|
|
16217
16882
|
}
|
|
16218
16883
|
reconcileOutboundRequest(context) {
|
|
16884
|
+
if (context.url.origin === SIWC_ORIGIN) {
|
|
16885
|
+
if (context.url.pathname === RESPONSES_PATH) {
|
|
16886
|
+
context.body = normalizeSiwcRequest(record(context.body), "responses");
|
|
16887
|
+
setSiwcHeaders(context, "responses");
|
|
16888
|
+
} else if (context.url.pathname === MODELS_PATH)
|
|
16889
|
+
setSiwcHeaders(context, "models");
|
|
16890
|
+
return context;
|
|
16891
|
+
}
|
|
16219
16892
|
if (context.url.pathname === CODEX_RESPONSES_PATH) {
|
|
16220
16893
|
setCodexRoutingHint(context.headers, context.body);
|
|
16221
16894
|
enforceCodexResponsesLite(context);
|
|
@@ -16239,7 +16912,7 @@ class ChatgptOauthAdapter {
|
|
|
16239
16912
|
return response;
|
|
16240
16913
|
};
|
|
16241
16914
|
const errorResponse = (status, completion, error) => {
|
|
16242
|
-
const response = mark(new Response(JSON.stringify({ error:
|
|
16915
|
+
const response = mark(new Response(JSON.stringify({ error: errorBody2(error) }), {
|
|
16243
16916
|
status,
|
|
16244
16917
|
statusText: result.response.statusText,
|
|
16245
16918
|
headers: responseHeaders(result.response, "application/json; charset=utf-8")
|
|
@@ -16260,7 +16933,8 @@ class ChatgptOauthAdapter {
|
|
|
16260
16933
|
return errorResponse(502, joinCompletion(result.completion, Promise.resolve({ status: "failed", code: "invalid_response" }), context.signal));
|
|
16261
16934
|
}
|
|
16262
16935
|
try {
|
|
16263
|
-
const
|
|
16936
|
+
const text = await readBoundedBody(result.response, context.signal);
|
|
16937
|
+
const models = state.siwc ? parseSiwcModelsBody(text) : parseCodexModelsBody(text, MAX_MODELS_BODY_BYTES);
|
|
16264
16938
|
const body = {
|
|
16265
16939
|
object: "list",
|
|
16266
16940
|
data: models.map(({ id }) => ({ id, object: "model", owned_by: "openai" }))
|
|
@@ -16286,7 +16960,7 @@ class ChatgptOauthAdapter {
|
|
|
16286
16960
|
return errorResponse(502, joinCompletion(result.completion, bodyCompletion, context.signal));
|
|
16287
16961
|
}
|
|
16288
16962
|
if (state.stream) {
|
|
16289
|
-
const converted = protocolStreamBody(result.response.body, state.target, state.includeUsage, context.signal, context.redactDiagnostic);
|
|
16963
|
+
const converted = protocolStreamBody(result.response.body, state.target, state.includeUsage, context.signal, context.redactDiagnostic, state.siwc);
|
|
16290
16964
|
const streamCompletion = joinCompletion(result.completion, converted.completion, context.signal);
|
|
16291
16965
|
streamCompletion.then(cleanup, cleanup);
|
|
16292
16966
|
return {
|
|
@@ -16301,7 +16975,7 @@ class ChatgptOauthAdapter {
|
|
|
16301
16975
|
target: state.target,
|
|
16302
16976
|
redactDiagnostic: context.redactDiagnostic
|
|
16303
16977
|
});
|
|
16304
|
-
const body = state.target === "chat" ? responsesToChatCompletion(stateResult.response) : stateResult.response;
|
|
16978
|
+
const body = state.target === "chat" ? responsesToChatCompletion(stateResult.response, state.siwc) : stateResult.response;
|
|
16305
16979
|
const protocolCompletion = Promise.resolve(stateResult.terminal === "completed" ? { status: "completed" } : { status: "incomplete", code: "incomplete" });
|
|
16306
16980
|
const nonStreamCompletion = joinCompletion(result.completion, protocolCompletion, context.signal);
|
|
16307
16981
|
nonStreamCompletion.then(cleanup, cleanup);
|
|
@@ -16319,6 +16993,7 @@ function validAccountRef(value) {
|
|
|
16319
16993
|
return typeof value === "string" && value.length >= 1 && value.length <= 128 && value.trim() === value;
|
|
16320
16994
|
}
|
|
16321
16995
|
var ChatgptOauthPlugin = definePlugin(class {
|
|
16996
|
+
static controlRpcContract = businessRpc;
|
|
16322
16997
|
static name = "chatgpt-oauth";
|
|
16323
16998
|
static version = "1.0.0";
|
|
16324
16999
|
adapter;
|
|
@@ -16340,4 +17015,4 @@ export {
|
|
|
16340
17015
|
server_default as default
|
|
16341
17016
|
};
|
|
16342
17017
|
|
|
16343
|
-
//# debugId=
|
|
17018
|
+
//# debugId=9E89B5DD5BF3FADA64756E2164756E21
|