zelari-code 1.36.0 → 1.38.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/cli/chatgptOAuth.js +142 -43
- package/dist/cli/chatgptOAuth.js.map +1 -1
- package/dist/cli/desktopConfig.js +18 -3
- package/dist/cli/desktopConfig.js.map +1 -1
- package/dist/cli/hooks/useSlashDispatch.js +11 -1
- package/dist/cli/hooks/useSlashDispatch.js.map +1 -1
- package/dist/cli/main.bundled.js +369 -53
- package/dist/cli/main.bundled.js.map +4 -4
- package/dist/cli/main.js +1 -0
- package/dist/cli/main.js.map +1 -1
- package/dist/cli/provider/anthropic.js +10 -0
- package/dist/cli/provider/anthropic.js.map +1 -1
- package/dist/cli/provider/chatgpt.js +10 -0
- package/dist/cli/provider/chatgpt.js.map +1 -1
- package/dist/cli/provider/openai-compatible.js +19 -6
- package/dist/cli/provider/openai-compatible.js.map +1 -1
- package/dist/cli/providerConfig.js +30 -0
- package/dist/cli/providerConfig.js.map +1 -1
- package/dist/cli/slashCommands.js +7 -0
- package/dist/cli/slashCommands.js.map +1 -1
- package/dist/cli/slashHandlers/provider.js +32 -1
- package/dist/cli/slashHandlers/provider.js.map +1 -1
- package/dist/cli/thinking.js +147 -0
- package/dist/cli/thinking.js.map +1 -0
- package/dist/cli/thinking.test.js +93 -0
- package/dist/cli/thinking.test.js.map +1 -0
- package/package.json +2 -2
package/dist/cli/main.bundled.js
CHANGED
|
@@ -794,16 +794,19 @@ __export(chatgptOAuth_exports, {
|
|
|
794
794
|
CHATGPT_DEVICE_CODE_URL: () => CHATGPT_DEVICE_CODE_URL,
|
|
795
795
|
CHATGPT_DEVICE_REDIRECT_URI: () => CHATGPT_DEVICE_REDIRECT_URI,
|
|
796
796
|
CHATGPT_DEVICE_TOKEN_URL: () => CHATGPT_DEVICE_TOKEN_URL,
|
|
797
|
+
CHATGPT_DEVICE_VERIFY_URL: () => CHATGPT_DEVICE_VERIFY_URL,
|
|
797
798
|
CHATGPT_SCOPE: () => CHATGPT_SCOPE,
|
|
798
799
|
CHATGPT_TOKEN_URL: () => CHATGPT_TOKEN_URL,
|
|
799
800
|
ChatgptOAuthError: () => ChatgptOAuthError,
|
|
800
801
|
DEFAULT_CHATGPT_CLIENT_ID: () => DEFAULT_CHATGPT_CLIENT_ID,
|
|
801
802
|
decodeJwtClaims: () => decodeJwtClaims,
|
|
802
803
|
extractChatgptAccountId: () => extractChatgptAccountId,
|
|
804
|
+
pollChatgptDeviceAuth: () => pollChatgptDeviceAuth,
|
|
803
805
|
refreshChatgptToken: () => refreshChatgptToken,
|
|
804
806
|
runChatgptBrowserFlow: () => runChatgptBrowserFlow,
|
|
805
807
|
runChatgptDeviceFlow: () => runChatgptDeviceFlow,
|
|
806
|
-
runChatgptOAuthFlow: () => runChatgptOAuthFlow
|
|
808
|
+
runChatgptOAuthFlow: () => runChatgptOAuthFlow,
|
|
809
|
+
startChatgptDeviceAuth: () => startChatgptDeviceAuth
|
|
807
810
|
});
|
|
808
811
|
function decodeJwtClaims(token) {
|
|
809
812
|
const parts = token.split(".");
|
|
@@ -845,6 +848,29 @@ function parseTokenPayload(obj, fallbackRefresh) {
|
|
|
845
848
|
}
|
|
846
849
|
return result;
|
|
847
850
|
}
|
|
851
|
+
function errorSnippet(body) {
|
|
852
|
+
const err = body.error;
|
|
853
|
+
if (typeof err === "string" && err.trim()) return err.trim().slice(0, 160);
|
|
854
|
+
if (err && typeof err === "object") {
|
|
855
|
+
const msg2 = err.message;
|
|
856
|
+
if (typeof msg2 === "string" && msg2.trim()) return msg2.trim().slice(0, 160);
|
|
857
|
+
}
|
|
858
|
+
const msg = body.message;
|
|
859
|
+
if (typeof msg === "string" && msg.trim()) return msg.trim().slice(0, 160);
|
|
860
|
+
return "";
|
|
861
|
+
}
|
|
862
|
+
function formatHttpError(prefix, status, body) {
|
|
863
|
+
const detail = errorSnippet(body);
|
|
864
|
+
return detail ? `${prefix} HTTP ${status}: ${detail}` : `${prefix} HTTP ${status}`;
|
|
865
|
+
}
|
|
866
|
+
async function readJsonBody(response) {
|
|
867
|
+
try {
|
|
868
|
+
const parsed = await response.json();
|
|
869
|
+
if (parsed && typeof parsed === "object") return parsed;
|
|
870
|
+
} catch {
|
|
871
|
+
}
|
|
872
|
+
return {};
|
|
873
|
+
}
|
|
848
874
|
async function postForm(url2, data, fetchImpl) {
|
|
849
875
|
let response;
|
|
850
876
|
try {
|
|
@@ -862,13 +888,34 @@ async function postForm(url2, data, fetchImpl) {
|
|
|
862
888
|
"network_error"
|
|
863
889
|
);
|
|
864
890
|
}
|
|
865
|
-
|
|
891
|
+
return { status: response.status, body: await readJsonBody(response) };
|
|
892
|
+
}
|
|
893
|
+
async function postJson(url2, data, fetchImpl) {
|
|
894
|
+
let response;
|
|
866
895
|
try {
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
|
|
896
|
+
response = await fetchImpl(url2, {
|
|
897
|
+
method: "POST",
|
|
898
|
+
headers: {
|
|
899
|
+
"Content-Type": "application/json",
|
|
900
|
+
Accept: "application/json"
|
|
901
|
+
},
|
|
902
|
+
body: JSON.stringify(data)
|
|
903
|
+
});
|
|
904
|
+
} catch (err) {
|
|
905
|
+
throw new ChatgptOAuthError(
|
|
906
|
+
`ChatGPT OAuth network error: ${err instanceof Error ? err.message : String(err)}`,
|
|
907
|
+
"network_error"
|
|
908
|
+
);
|
|
870
909
|
}
|
|
871
|
-
return { status: response.status, body };
|
|
910
|
+
return { status: response.status, body: await readJsonBody(response) };
|
|
911
|
+
}
|
|
912
|
+
function parsePollInterval(raw, fallback = 5) {
|
|
913
|
+
if (typeof raw === "number" && Number.isFinite(raw) && raw > 0) return raw;
|
|
914
|
+
if (typeof raw === "string") {
|
|
915
|
+
const n = Number.parseInt(raw, 10);
|
|
916
|
+
if (Number.isFinite(n) && n > 0) return n;
|
|
917
|
+
}
|
|
918
|
+
return fallback;
|
|
872
919
|
}
|
|
873
920
|
async function refreshChatgptToken(options) {
|
|
874
921
|
if (!options.refreshToken.trim()) {
|
|
@@ -887,77 +934,82 @@ async function refreshChatgptToken(options) {
|
|
|
887
934
|
);
|
|
888
935
|
if (status >= 400) {
|
|
889
936
|
const code = status === 400 || status === 401 ? "invalid_grant" : `http_${status}`;
|
|
890
|
-
throw new ChatgptOAuthError(
|
|
891
|
-
`ChatGPT token refresh HTTP ${status}: ${String(body.error ?? "").slice(0, 160)}`,
|
|
892
|
-
code
|
|
893
|
-
);
|
|
937
|
+
throw new ChatgptOAuthError(formatHttpError("ChatGPT token refresh", status, body), code);
|
|
894
938
|
}
|
|
895
939
|
return parseTokenPayload(body, options.refreshToken);
|
|
896
940
|
}
|
|
897
|
-
async function
|
|
941
|
+
async function startChatgptDeviceAuth(options = {}) {
|
|
898
942
|
const clientId2 = options.clientId || process.env.CHATGPT_OAUTH_CLIENT_ID || DEFAULT_CHATGPT_CLIENT_ID;
|
|
899
943
|
const fetchImpl = options.fetchImpl ?? fetch;
|
|
900
|
-
const
|
|
901
|
-
const { verifier, challenge } = generatePkcePair();
|
|
902
|
-
const start = await postForm(
|
|
903
|
-
CHATGPT_DEVICE_CODE_URL,
|
|
904
|
-
{
|
|
905
|
-
client_id: clientId2,
|
|
906
|
-
scope: CHATGPT_SCOPE,
|
|
907
|
-
code_challenge: challenge,
|
|
908
|
-
code_challenge_method: "S256"
|
|
909
|
-
},
|
|
910
|
-
fetchImpl
|
|
911
|
-
);
|
|
944
|
+
const start = await postJson(CHATGPT_DEVICE_CODE_URL, { client_id: clientId2 }, fetchImpl);
|
|
912
945
|
if (start.status >= 400) {
|
|
913
946
|
throw new ChatgptOAuthError(
|
|
914
|
-
|
|
947
|
+
formatHttpError("ChatGPT device-code", start.status, start.body),
|
|
915
948
|
`device_http_${start.status}`
|
|
916
949
|
);
|
|
917
950
|
}
|
|
918
|
-
const
|
|
919
|
-
const userCode = start.body.user_code;
|
|
920
|
-
const verificationUri = typeof start.body.verification_uri === "string" && start.body.verification_uri || typeof start.body.
|
|
921
|
-
if (
|
|
951
|
+
const deviceAuthId = typeof start.body.device_auth_id === "string" && start.body.device_auth_id || typeof start.body.device_code === "string" && start.body.device_code || "";
|
|
952
|
+
const userCode = typeof start.body.user_code === "string" && start.body.user_code || typeof start.body.usercode === "string" && start.body.usercode || "";
|
|
953
|
+
const verificationUri = typeof start.body.verification_uri === "string" && start.body.verification_uri || typeof start.body.verification_url === "string" && start.body.verification_url || `${CHATGPT_DEVICE_VERIFY_URL}?user_code=${encodeURIComponent(userCode)}`;
|
|
954
|
+
if (!deviceAuthId || !userCode) {
|
|
922
955
|
throw new ChatgptOAuthError("Device-code response missing fields", "no_device_code");
|
|
923
956
|
}
|
|
924
|
-
|
|
957
|
+
return {
|
|
958
|
+
deviceAuthId,
|
|
925
959
|
userCode,
|
|
926
960
|
verificationUri,
|
|
961
|
+
interval: parsePollInterval(start.body.interval, 5),
|
|
927
962
|
...typeof start.body.verification_uri_complete === "string" ? { verificationUriComplete: start.body.verification_uri_complete } : {}
|
|
928
963
|
};
|
|
929
|
-
|
|
930
|
-
|
|
931
|
-
|
|
932
|
-
|
|
933
|
-
|
|
934
|
-
} catch {
|
|
935
|
-
}
|
|
964
|
+
}
|
|
965
|
+
async function pollChatgptDeviceAuth(options) {
|
|
966
|
+
const clientId2 = options.clientId || process.env.CHATGPT_OAUTH_CLIENT_ID || DEFAULT_CHATGPT_CLIENT_ID;
|
|
967
|
+
const fetchImpl = options.fetchImpl ?? fetch;
|
|
968
|
+
const sleep = options.sleepImpl ?? ((ms) => new Promise((r) => setTimeout(r, ms)));
|
|
936
969
|
const timeoutMs = options.timeoutMs ?? 3e5;
|
|
937
970
|
const deadline = Date.now() + timeoutMs;
|
|
938
|
-
let interval = 5;
|
|
971
|
+
let interval = options.interval ?? 5;
|
|
939
972
|
let authorizationCode;
|
|
973
|
+
let codeVerifier;
|
|
940
974
|
while (Date.now() < deadline) {
|
|
941
|
-
const poll = await
|
|
975
|
+
const poll = await postJson(
|
|
942
976
|
CHATGPT_DEVICE_TOKEN_URL,
|
|
943
|
-
{
|
|
977
|
+
{ device_auth_id: options.deviceAuthId, user_code: options.userCode },
|
|
944
978
|
fetchImpl
|
|
945
979
|
);
|
|
946
980
|
const authCode = poll.body.authorization_code;
|
|
947
981
|
if (typeof authCode === "string" && authCode.length > 0) {
|
|
948
982
|
authorizationCode = authCode;
|
|
983
|
+
if (typeof poll.body.code_verifier === "string" && poll.body.code_verifier) {
|
|
984
|
+
codeVerifier = poll.body.code_verifier;
|
|
985
|
+
}
|
|
949
986
|
break;
|
|
950
987
|
}
|
|
988
|
+
if (poll.status === 403 || poll.status === 404) {
|
|
989
|
+
await sleep(interval * 1e3);
|
|
990
|
+
continue;
|
|
991
|
+
}
|
|
951
992
|
const err = typeof poll.body.error === "string" ? poll.body.error : "";
|
|
952
993
|
if (err === "slow_down") interval += 5;
|
|
953
994
|
else if (err && err !== "authorization_pending") {
|
|
954
995
|
throw new ChatgptOAuthError(`Device authorization failed: ${err}`, err);
|
|
996
|
+
} else if (poll.status >= 400) {
|
|
997
|
+
throw new ChatgptOAuthError(
|
|
998
|
+
formatHttpError("ChatGPT device poll", poll.status, poll.body),
|
|
999
|
+
`poll_http_${poll.status}`
|
|
1000
|
+
);
|
|
955
1001
|
}
|
|
956
1002
|
await sleep(interval * 1e3);
|
|
957
1003
|
}
|
|
958
1004
|
if (!authorizationCode) {
|
|
959
1005
|
throw new ChatgptOAuthError("Timed out waiting for ChatGPT device authorization", "timeout");
|
|
960
1006
|
}
|
|
1007
|
+
if (!codeVerifier) {
|
|
1008
|
+
throw new ChatgptOAuthError(
|
|
1009
|
+
"Device token response missing code_verifier (server-issued PKCE)",
|
|
1010
|
+
"no_code_verifier"
|
|
1011
|
+
);
|
|
1012
|
+
}
|
|
961
1013
|
const token = await postForm(
|
|
962
1014
|
CHATGPT_TOKEN_URL,
|
|
963
1015
|
{
|
|
@@ -965,13 +1017,13 @@ async function runChatgptDeviceFlow(options) {
|
|
|
965
1017
|
code: authorizationCode,
|
|
966
1018
|
redirect_uri: CHATGPT_DEVICE_REDIRECT_URI,
|
|
967
1019
|
client_id: clientId2,
|
|
968
|
-
code_verifier:
|
|
1020
|
+
code_verifier: codeVerifier
|
|
969
1021
|
},
|
|
970
1022
|
fetchImpl
|
|
971
1023
|
);
|
|
972
1024
|
if (token.status >= 400) {
|
|
973
1025
|
throw new ChatgptOAuthError(
|
|
974
|
-
|
|
1026
|
+
formatHttpError("ChatGPT token exchange", token.status, token.body),
|
|
975
1027
|
`token_http_${token.status}`
|
|
976
1028
|
);
|
|
977
1029
|
}
|
|
@@ -1024,12 +1076,47 @@ async function runChatgptBrowserFlow(options) {
|
|
|
1024
1076
|
);
|
|
1025
1077
|
if (token.status >= 400) {
|
|
1026
1078
|
throw new ChatgptOAuthError(
|
|
1027
|
-
|
|
1079
|
+
formatHttpError("ChatGPT token exchange", token.status, token.body),
|
|
1028
1080
|
`token_http_${token.status}`
|
|
1029
1081
|
);
|
|
1030
1082
|
}
|
|
1031
1083
|
return parseTokenPayload(token.body);
|
|
1032
1084
|
}
|
|
1085
|
+
async function runChatgptDeviceFlow(options = {}) {
|
|
1086
|
+
const session = await startChatgptDeviceAuth({
|
|
1087
|
+
clientId: options.clientId,
|
|
1088
|
+
fetchImpl: options.fetchImpl
|
|
1089
|
+
});
|
|
1090
|
+
const info = {
|
|
1091
|
+
userCode: session.userCode,
|
|
1092
|
+
verificationUri: session.verificationUri,
|
|
1093
|
+
...session.verificationUriComplete ? { verificationUriComplete: session.verificationUriComplete } : {}
|
|
1094
|
+
};
|
|
1095
|
+
if (options.onUserCode) {
|
|
1096
|
+
await options.onUserCode(info);
|
|
1097
|
+
} else {
|
|
1098
|
+
process.stderr.write(
|
|
1099
|
+
`[chatgpt oauth] Open ${info.verificationUri} and enter:
|
|
1100
|
+
${info.userCode}
|
|
1101
|
+
`
|
|
1102
|
+
);
|
|
1103
|
+
}
|
|
1104
|
+
try {
|
|
1105
|
+
await (options.openBrowserImpl ?? openBrowser)(
|
|
1106
|
+
info.verificationUriComplete ?? info.verificationUri
|
|
1107
|
+
);
|
|
1108
|
+
} catch {
|
|
1109
|
+
}
|
|
1110
|
+
return pollChatgptDeviceAuth({
|
|
1111
|
+
deviceAuthId: session.deviceAuthId,
|
|
1112
|
+
userCode: session.userCode,
|
|
1113
|
+
clientId: options.clientId,
|
|
1114
|
+
interval: session.interval,
|
|
1115
|
+
fetchImpl: options.fetchImpl,
|
|
1116
|
+
sleepImpl: options.sleepImpl,
|
|
1117
|
+
timeoutMs: options.timeoutMs
|
|
1118
|
+
});
|
|
1119
|
+
}
|
|
1033
1120
|
async function runChatgptOAuthFlow(options = {}) {
|
|
1034
1121
|
const flow = (process.env.CHATGPT_OAUTH_FLOW ?? "device").toLowerCase();
|
|
1035
1122
|
if (flow === "browser") {
|
|
@@ -1037,7 +1124,7 @@ async function runChatgptOAuthFlow(options = {}) {
|
|
|
1037
1124
|
}
|
|
1038
1125
|
return runChatgptDeviceFlow(options);
|
|
1039
1126
|
}
|
|
1040
|
-
var DEFAULT_CHATGPT_CLIENT_ID, CHATGPT_AUTHORIZE_URL, CHATGPT_TOKEN_URL, CHATGPT_DEVICE_CODE_URL, CHATGPT_DEVICE_TOKEN_URL, CHATGPT_DEVICE_REDIRECT_URI, CHATGPT_SCOPE, CHATGPT_AUTH_CLAIMS, ChatgptOAuthError;
|
|
1127
|
+
var DEFAULT_CHATGPT_CLIENT_ID, CHATGPT_AUTHORIZE_URL, CHATGPT_TOKEN_URL, CHATGPT_DEVICE_CODE_URL, CHATGPT_DEVICE_TOKEN_URL, CHATGPT_DEVICE_REDIRECT_URI, CHATGPT_DEVICE_VERIFY_URL, CHATGPT_SCOPE, CHATGPT_AUTH_CLAIMS, ChatgptOAuthError;
|
|
1041
1128
|
var init_chatgptOAuth = __esm({
|
|
1042
1129
|
"src/cli/chatgptOAuth.ts"() {
|
|
1043
1130
|
"use strict";
|
|
@@ -1049,6 +1136,7 @@ var init_chatgptOAuth = __esm({
|
|
|
1049
1136
|
CHATGPT_DEVICE_CODE_URL = "https://auth.openai.com/api/accounts/deviceauth/usercode";
|
|
1050
1137
|
CHATGPT_DEVICE_TOKEN_URL = "https://auth.openai.com/api/accounts/deviceauth/token";
|
|
1051
1138
|
CHATGPT_DEVICE_REDIRECT_URI = "https://auth.openai.com/deviceauth/callback";
|
|
1139
|
+
CHATGPT_DEVICE_VERIFY_URL = "https://auth.openai.com/codex/device";
|
|
1052
1140
|
CHATGPT_SCOPE = "openid profile email offline_access";
|
|
1053
1141
|
CHATGPT_AUTH_CLAIMS = "https://api.openai.com/auth";
|
|
1054
1142
|
ChatgptOAuthError = class extends Error {
|
|
@@ -1152,7 +1240,7 @@ async function startAnthropicOAuth(options = {}) {
|
|
|
1152
1240
|
}
|
|
1153
1241
|
return { authorizeUrl, state: state3 };
|
|
1154
1242
|
}
|
|
1155
|
-
async function
|
|
1243
|
+
async function postJson2(url2, payload, fetchImpl) {
|
|
1156
1244
|
let response;
|
|
1157
1245
|
try {
|
|
1158
1246
|
response = await fetchImpl(url2, {
|
|
@@ -1212,7 +1300,7 @@ async function completeAnthropicOAuth(options) {
|
|
|
1212
1300
|
redirect_uri: ANTHROPIC_REDIRECT_URI,
|
|
1213
1301
|
state: parsed.state ?? pending.state
|
|
1214
1302
|
};
|
|
1215
|
-
const { status, body } = await
|
|
1303
|
+
const { status, body } = await postJson2(ANTHROPIC_TOKEN_URL, payload, fetchImpl);
|
|
1216
1304
|
if (status >= 400) {
|
|
1217
1305
|
const code = status === 400 || status === 401 ? "invalid_grant" : `http_${status}`;
|
|
1218
1306
|
throw new AnthropicOAuthError(
|
|
@@ -1227,7 +1315,7 @@ async function refreshAnthropicToken(options) {
|
|
|
1227
1315
|
throw new AnthropicOAuthError("Missing refreshToken", "no_refresh_token");
|
|
1228
1316
|
}
|
|
1229
1317
|
const fetchImpl = options.fetchImpl ?? fetch;
|
|
1230
|
-
const { status, body } = await
|
|
1318
|
+
const { status, body } = await postJson2(
|
|
1231
1319
|
ANTHROPIC_TOKEN_URL,
|
|
1232
1320
|
{
|
|
1233
1321
|
grant_type: "refresh_token",
|
|
@@ -1532,6 +1620,112 @@ var init_keyStore = __esm({
|
|
|
1532
1620
|
}
|
|
1533
1621
|
});
|
|
1534
1622
|
|
|
1623
|
+
// src/cli/thinking.ts
|
|
1624
|
+
function thinkingCapabilityFor(id) {
|
|
1625
|
+
return PROVIDER_THINKING_CAPABILITY[id] ?? {};
|
|
1626
|
+
}
|
|
1627
|
+
function stringifyThinkingSpec(spec) {
|
|
1628
|
+
if (spec === "auto") return "auto";
|
|
1629
|
+
if (spec.kind === "off") return "off";
|
|
1630
|
+
if (spec.kind === "effort") return spec.effort;
|
|
1631
|
+
return `budget:${spec.budgetTokens}`;
|
|
1632
|
+
}
|
|
1633
|
+
function parseThinkingSpec(raw) {
|
|
1634
|
+
const s = (raw ?? "").trim().toLowerCase();
|
|
1635
|
+
if (!s || s === "auto") return "auto";
|
|
1636
|
+
if (s === "off") return { kind: "off" };
|
|
1637
|
+
if (s === "low" || s === "medium" || s === "high") return { kind: "effort", effort: s };
|
|
1638
|
+
const m = /^budget:(\d+)$/.exec(s);
|
|
1639
|
+
if (m) {
|
|
1640
|
+
const n = Number.parseInt(m[1], 10);
|
|
1641
|
+
if (Number.isFinite(n) && n > 0) return { kind: "budget", budgetTokens: n };
|
|
1642
|
+
}
|
|
1643
|
+
return "auto";
|
|
1644
|
+
}
|
|
1645
|
+
function isValidThinkingInput(raw) {
|
|
1646
|
+
const s = raw.trim().toLowerCase();
|
|
1647
|
+
if (s === "auto" || s === "off" || s === "low" || s === "medium" || s === "high") return true;
|
|
1648
|
+
return /^budget:\d+$/.test(s) && Number.parseInt(s.slice(7), 10) > 0;
|
|
1649
|
+
}
|
|
1650
|
+
function degrade(note) {
|
|
1651
|
+
return { patch: {}, degraded: true, note };
|
|
1652
|
+
}
|
|
1653
|
+
function translateOpenAiCompatibleThinking(providerId, spec) {
|
|
1654
|
+
if (spec === "auto") return { patch: {}, degraded: false };
|
|
1655
|
+
const cap3 = thinkingCapabilityFor(providerId);
|
|
1656
|
+
switch (spec.kind) {
|
|
1657
|
+
case "off":
|
|
1658
|
+
if (providerId === "deepseek" || providerId === "glm") {
|
|
1659
|
+
return { patch: { thinking: { type: "disabled" } }, degraded: false };
|
|
1660
|
+
}
|
|
1661
|
+
if (cap3.effort) return { patch: { reasoning_effort: "low" }, degraded: false };
|
|
1662
|
+
return degrade(`thinking 'off' is not supported for provider "${providerId}"`);
|
|
1663
|
+
case "effort":
|
|
1664
|
+
if (!cap3.effort) {
|
|
1665
|
+
return degrade(`thinking 'effort' is not supported for provider "${providerId}"`);
|
|
1666
|
+
}
|
|
1667
|
+
if (providerId === "deepseek") {
|
|
1668
|
+
return {
|
|
1669
|
+
patch: {
|
|
1670
|
+
thinking: { type: "enabled" },
|
|
1671
|
+
reasoning_effort: spec.effort === "high" ? "max" : "high"
|
|
1672
|
+
},
|
|
1673
|
+
degraded: false
|
|
1674
|
+
};
|
|
1675
|
+
}
|
|
1676
|
+
return { patch: { reasoning_effort: spec.effort }, degraded: false };
|
|
1677
|
+
case "budget":
|
|
1678
|
+
if (!cap3.budget) {
|
|
1679
|
+
return degrade(`thinking 'budget' is not supported for provider "${providerId}"`);
|
|
1680
|
+
}
|
|
1681
|
+
return {
|
|
1682
|
+
patch: { thinking: { type: "enabled", budget_tokens: spec.budgetTokens } },
|
|
1683
|
+
degraded: false
|
|
1684
|
+
};
|
|
1685
|
+
}
|
|
1686
|
+
}
|
|
1687
|
+
function translateResponsesThinking(spec) {
|
|
1688
|
+
if (spec === "auto") return { patch: {}, degraded: false };
|
|
1689
|
+
switch (spec.kind) {
|
|
1690
|
+
case "off":
|
|
1691
|
+
return { patch: { reasoning: { effort: "minimal" } }, degraded: false };
|
|
1692
|
+
case "effort":
|
|
1693
|
+
return { patch: { reasoning: { effort: spec.effort } }, degraded: false };
|
|
1694
|
+
case "budget":
|
|
1695
|
+
return degrade('thinking "budget" is not supported for chatgpt \u2014 use low/medium/high');
|
|
1696
|
+
}
|
|
1697
|
+
}
|
|
1698
|
+
function translateAnthropicThinking(spec) {
|
|
1699
|
+
if (spec === "auto") return { patch: {}, degraded: false };
|
|
1700
|
+
switch (spec.kind) {
|
|
1701
|
+
case "off":
|
|
1702
|
+
return { patch: { thinking: { type: "disabled" } }, degraded: false };
|
|
1703
|
+
case "budget":
|
|
1704
|
+
return {
|
|
1705
|
+
patch: { thinking: { type: "enabled", budget_tokens: spec.budgetTokens } },
|
|
1706
|
+
degraded: false
|
|
1707
|
+
};
|
|
1708
|
+
case "effort":
|
|
1709
|
+
return degrade('thinking "effort" is not supported for anthropic \u2014 use budget:N');
|
|
1710
|
+
}
|
|
1711
|
+
}
|
|
1712
|
+
var PROVIDER_THINKING_CAPABILITY;
|
|
1713
|
+
var init_thinking = __esm({
|
|
1714
|
+
"src/cli/thinking.ts"() {
|
|
1715
|
+
"use strict";
|
|
1716
|
+
PROVIDER_THINKING_CAPABILITY = {
|
|
1717
|
+
"openai-compatible": { effort: true },
|
|
1718
|
+
"grok": { effort: true },
|
|
1719
|
+
"chatgpt": { effort: true },
|
|
1720
|
+
"anthropic": { budget: true },
|
|
1721
|
+
"glm": { budget: true },
|
|
1722
|
+
"deepseek": { effort: true },
|
|
1723
|
+
"minimax": { effort: true },
|
|
1724
|
+
"custom": { effort: true }
|
|
1725
|
+
};
|
|
1726
|
+
}
|
|
1727
|
+
});
|
|
1728
|
+
|
|
1535
1729
|
// src/cli/providerConfig.ts
|
|
1536
1730
|
var providerConfig_exports = {};
|
|
1537
1731
|
__export(providerConfig_exports, {
|
|
@@ -1542,10 +1736,12 @@ __export(providerConfig_exports, {
|
|
|
1542
1736
|
getModelForProvider: () => getModelForProvider,
|
|
1543
1737
|
getProviderConfig: () => getProviderConfig,
|
|
1544
1738
|
getProviderConfigPath: () => getProviderConfigPath,
|
|
1739
|
+
getThinkingForProvider: () => getThinkingForProvider,
|
|
1545
1740
|
loadProviderConfig: () => loadProviderConfig,
|
|
1546
1741
|
setActiveProviderId: () => setActiveProviderId,
|
|
1547
1742
|
setCustomEndpoint: () => setCustomEndpoint,
|
|
1548
|
-
setModelForProvider: () => setModelForProvider
|
|
1743
|
+
setModelForProvider: () => setModelForProvider,
|
|
1744
|
+
setThinkingForProvider: () => setThinkingForProvider
|
|
1549
1745
|
});
|
|
1550
1746
|
import { promises as fs2, existsSync as existsSync3, readFileSync as readFileSync3, writeFileSync as writeFileSync3, mkdirSync as mkdirSync3 } from "node:fs";
|
|
1551
1747
|
import path4 from "node:path";
|
|
@@ -1566,6 +1762,7 @@ function getProviderConfig() {
|
|
|
1566
1762
|
stored = {
|
|
1567
1763
|
activeProviderId: parsed.activeProviderId,
|
|
1568
1764
|
modelByProvider: { ...DEFAULTS.modelByProvider, ...parsed.modelByProvider },
|
|
1765
|
+
thinkingByProvider: { ...DEFAULTS.thinkingByProvider, ...parsed.thinkingByProvider },
|
|
1569
1766
|
customEndpoints: mergeCustomEndpoints(parsed.customEndpoints)
|
|
1570
1767
|
};
|
|
1571
1768
|
}
|
|
@@ -1575,6 +1772,7 @@ function getProviderConfig() {
|
|
|
1575
1772
|
const base = stored ?? {
|
|
1576
1773
|
...DEFAULTS,
|
|
1577
1774
|
modelByProvider: { ...DEFAULTS.modelByProvider },
|
|
1775
|
+
thinkingByProvider: { ...DEFAULTS.thinkingByProvider },
|
|
1578
1776
|
customEndpoints: { ...DEFAULTS.customEndpoints }
|
|
1579
1777
|
};
|
|
1580
1778
|
if (envActive && PROVIDERS.some((p3) => p3.id === envActive)) {
|
|
@@ -1662,6 +1860,19 @@ function getModelForProvider(id) {
|
|
|
1662
1860
|
const config2 = getProviderConfig();
|
|
1663
1861
|
return config2.modelByProvider[id] ?? DEFAULTS.modelByProvider[id] ?? "";
|
|
1664
1862
|
}
|
|
1863
|
+
function getThinkingForProvider(id) {
|
|
1864
|
+
const config2 = getProviderConfig();
|
|
1865
|
+
return parseThinkingSpec(config2.thinkingByProvider[id]);
|
|
1866
|
+
}
|
|
1867
|
+
function setThinkingForProvider(id, spec) {
|
|
1868
|
+
const found = PROVIDERS.find((p3) => p3.id === id);
|
|
1869
|
+
if (!found) {
|
|
1870
|
+
throw new Error(`Unknown provider id: "${id}". Available: ${PROVIDERS.map((p3) => p3.id).join(", ")}`);
|
|
1871
|
+
}
|
|
1872
|
+
const config2 = getProviderConfig();
|
|
1873
|
+
config2.thinkingByProvider[id] = stringifyThinkingSpec(spec);
|
|
1874
|
+
writeProviderConfig(config2);
|
|
1875
|
+
}
|
|
1665
1876
|
function getActiveProvider() {
|
|
1666
1877
|
const config2 = getProviderConfig();
|
|
1667
1878
|
const spec = PROVIDERS.find((p3) => p3.id === config2.activeProviderId);
|
|
@@ -1681,6 +1892,7 @@ async function loadProviderConfig() {
|
|
|
1681
1892
|
return {
|
|
1682
1893
|
activeProviderId: parsed.activeProviderId,
|
|
1683
1894
|
modelByProvider: { ...DEFAULTS.modelByProvider, ...parsed.modelByProvider },
|
|
1895
|
+
thinkingByProvider: { ...DEFAULTS.thinkingByProvider, ...parsed.thinkingByProvider },
|
|
1684
1896
|
customEndpoints: mergeCustomEndpoints(parsed.customEndpoints)
|
|
1685
1897
|
};
|
|
1686
1898
|
}
|
|
@@ -1689,6 +1901,7 @@ async function loadProviderConfig() {
|
|
|
1689
1901
|
return {
|
|
1690
1902
|
...DEFAULTS,
|
|
1691
1903
|
modelByProvider: { ...DEFAULTS.modelByProvider },
|
|
1904
|
+
thinkingByProvider: { ...DEFAULTS.thinkingByProvider },
|
|
1692
1905
|
customEndpoints: { ...DEFAULTS.customEndpoints }
|
|
1693
1906
|
};
|
|
1694
1907
|
}
|
|
@@ -1697,6 +1910,7 @@ var init_providerConfig = __esm({
|
|
|
1697
1910
|
"src/cli/providerConfig.ts"() {
|
|
1698
1911
|
"use strict";
|
|
1699
1912
|
init_keyStore();
|
|
1913
|
+
init_thinking();
|
|
1700
1914
|
DEFAULTS = {
|
|
1701
1915
|
activeProviderId: "openai-compatible",
|
|
1702
1916
|
modelByProvider: {
|
|
@@ -1710,6 +1924,16 @@ var init_providerConfig = __esm({
|
|
|
1710
1924
|
"anthropic": "claude-sonnet-4-5",
|
|
1711
1925
|
"custom": ""
|
|
1712
1926
|
},
|
|
1927
|
+
thinkingByProvider: {
|
|
1928
|
+
"openai-compatible": "auto",
|
|
1929
|
+
"minimax": "auto",
|
|
1930
|
+
"glm": "auto",
|
|
1931
|
+
"grok": "auto",
|
|
1932
|
+
"deepseek": "auto",
|
|
1933
|
+
"chatgpt": "auto",
|
|
1934
|
+
"anthropic": "auto",
|
|
1935
|
+
"custom": "auto"
|
|
1936
|
+
},
|
|
1713
1937
|
customEndpoints: {}
|
|
1714
1938
|
};
|
|
1715
1939
|
}
|
|
@@ -28027,10 +28251,18 @@ function openaiCompatibleProvider(config2) {
|
|
|
28027
28251
|
// the harness will fall back to the ~4-char/token approximation.
|
|
28028
28252
|
stream_options: { include_usage: true }
|
|
28029
28253
|
};
|
|
28030
|
-
|
|
28254
|
+
const thinkingSpec = config2.thinking ?? "auto";
|
|
28255
|
+
if (config2.providerId === "deepseek" && thinkingSpec === "auto") {
|
|
28031
28256
|
const thinking = resolveDeepSeekThinking();
|
|
28032
28257
|
if (thinking.thinking) body.thinking = { type: thinking.thinking };
|
|
28033
28258
|
if (thinking.reasoningEffort) body.reasoning_effort = thinking.reasoningEffort;
|
|
28259
|
+
} else if (thinkingSpec !== "auto") {
|
|
28260
|
+
const t = translateOpenAiCompatibleThinking(config2.providerId, thinkingSpec);
|
|
28261
|
+
if (t.degraded) {
|
|
28262
|
+
console.warn(`[thinking] ${t.note ?? "unsupported"} \u2014 falling back to provider default.`);
|
|
28263
|
+
} else {
|
|
28264
|
+
Object.assign(body, t.patch);
|
|
28265
|
+
}
|
|
28034
28266
|
}
|
|
28035
28267
|
if (params.tools && params.tools.length > 0) {
|
|
28036
28268
|
const orderedTools = [...params.tools].sort(
|
|
@@ -28281,6 +28513,7 @@ async function providerFromEnv() {
|
|
|
28281
28513
|
baseUrl: resolveBaseUrl(providerId),
|
|
28282
28514
|
model: getModelForProvider(providerId),
|
|
28283
28515
|
providerId,
|
|
28516
|
+
thinking: getThinkingForProvider(providerId),
|
|
28284
28517
|
...extraFromStored(providerId)
|
|
28285
28518
|
};
|
|
28286
28519
|
}
|
|
@@ -28292,6 +28525,7 @@ async function providerConfigFor(providerId) {
|
|
|
28292
28525
|
baseUrl: resolveBaseUrl(providerId),
|
|
28293
28526
|
model: getModelForProvider(providerId),
|
|
28294
28527
|
providerId,
|
|
28528
|
+
thinking: getThinkingForProvider(providerId),
|
|
28295
28529
|
...extraFromStored(providerId)
|
|
28296
28530
|
};
|
|
28297
28531
|
}
|
|
@@ -28301,6 +28535,7 @@ var init_openai_compatible = __esm({
|
|
|
28301
28535
|
"use strict";
|
|
28302
28536
|
init_keyStore();
|
|
28303
28537
|
init_providerConfig();
|
|
28538
|
+
init_thinking();
|
|
28304
28539
|
RETRYABLE_STATUSES = /* @__PURE__ */ new Set([429, 500, 502, 503, 504]);
|
|
28305
28540
|
MAX_RETRIES = (() => {
|
|
28306
28541
|
const raw = process.env.ZELARI_PROVIDER_MAX_RETRIES;
|
|
@@ -28554,6 +28789,12 @@ function anthropicMessagesProvider(config2) {
|
|
|
28554
28789
|
input_schema: t.parameters
|
|
28555
28790
|
}));
|
|
28556
28791
|
}
|
|
28792
|
+
const thinkingSpec = config2.thinking ?? "auto";
|
|
28793
|
+
if (thinkingSpec !== "auto") {
|
|
28794
|
+
const t = translateAnthropicThinking(thinkingSpec);
|
|
28795
|
+
if (t.degraded) console.warn(`[thinking] ${t.note ?? "unsupported"} \u2014 falling back to provider default.`);
|
|
28796
|
+
else Object.assign(body, t.patch);
|
|
28797
|
+
}
|
|
28557
28798
|
const base = config2.baseUrl.replace(/\/$/, "").replace(/\/v1$/, "");
|
|
28558
28799
|
const url2 = `${base}/v1/messages`;
|
|
28559
28800
|
let response;
|
|
@@ -28692,6 +28933,7 @@ var init_anthropic = __esm({
|
|
|
28692
28933
|
"src/cli/provider/anthropic.ts"() {
|
|
28693
28934
|
"use strict";
|
|
28694
28935
|
init_chatStats();
|
|
28936
|
+
init_thinking();
|
|
28695
28937
|
ANTHROPIC_VERSION = "2023-06-01";
|
|
28696
28938
|
ANTHROPIC_BETA = "oauth-2025-04-20";
|
|
28697
28939
|
ANTHROPIC_BETA_EXTENDED_CACHE_TTL = "extended-cache-ttl-2025-04-11";
|
|
@@ -28759,6 +29001,12 @@ function chatgptResponsesProvider(config2) {
|
|
|
28759
29001
|
parameters: t.parameters
|
|
28760
29002
|
}));
|
|
28761
29003
|
}
|
|
29004
|
+
const thinkingSpec = config2.thinking ?? "auto";
|
|
29005
|
+
if (thinkingSpec !== "auto") {
|
|
29006
|
+
const t = translateResponsesThinking(thinkingSpec);
|
|
29007
|
+
if (t.degraded) console.warn(`[thinking] ${t.note ?? "unsupported"} \u2014 falling back to provider default.`);
|
|
29008
|
+
else Object.assign(body, t.patch);
|
|
29009
|
+
}
|
|
28762
29010
|
const base = config2.baseUrl.replace(/\/$/, "");
|
|
28763
29011
|
const url2 = `${base}/responses`;
|
|
28764
29012
|
let response;
|
|
@@ -28873,6 +29121,7 @@ function chatgptResponsesProvider(config2) {
|
|
|
28873
29121
|
var init_chatgpt = __esm({
|
|
28874
29122
|
"src/cli/provider/chatgpt.ts"() {
|
|
28875
29123
|
"use strict";
|
|
29124
|
+
init_thinking();
|
|
28876
29125
|
}
|
|
28877
29126
|
});
|
|
28878
29127
|
|
|
@@ -42545,6 +42794,8 @@ var init_oauthDesktop = __esm({
|
|
|
42545
42794
|
var provider_exports = {};
|
|
42546
42795
|
__export(provider_exports, {
|
|
42547
42796
|
buildModelPickerItems: () => buildModelPickerItems,
|
|
42797
|
+
handleEffortSet: () => handleEffortSet,
|
|
42798
|
+
handleEffortShow: () => handleEffortShow,
|
|
42548
42799
|
handleLoginKey: () => handleLoginKey,
|
|
42549
42800
|
handleLoginOAuth: () => handleLoginOAuth,
|
|
42550
42801
|
handleLoginOAuthGrok: () => handleLoginOAuthGrok,
|
|
@@ -42792,6 +43043,39 @@ function handleModelSet(ctx, model) {
|
|
|
42792
43043
|
appendSystem(ctx.setMessages, `[model error] ${err instanceof Error ? err.message : String(err)}`);
|
|
42793
43044
|
}
|
|
42794
43045
|
}
|
|
43046
|
+
function handleEffortShow(ctx) {
|
|
43047
|
+
const id = ctx.activeProviderSpec.id;
|
|
43048
|
+
const cap3 = thinkingCapabilityFor(id);
|
|
43049
|
+
const current = stringifyThinkingSpec(getThinkingForProvider(id));
|
|
43050
|
+
const options = [
|
|
43051
|
+
"auto",
|
|
43052
|
+
"off",
|
|
43053
|
+
...cap3.effort ? ["low", "medium", "high"] : [],
|
|
43054
|
+
...cap3.budget ? ["budget:<tokens>"] : []
|
|
43055
|
+
];
|
|
43056
|
+
appendSystem(
|
|
43057
|
+
ctx.setMessages,
|
|
43058
|
+
`[effort] ${ctx.activeProviderSpec.displayName}: ${current} \u2014 options: ${options.join(", ")}`
|
|
43059
|
+
);
|
|
43060
|
+
}
|
|
43061
|
+
function handleEffortSet(ctx, raw) {
|
|
43062
|
+
const id = ctx.activeProviderSpec.id;
|
|
43063
|
+
if (!isValidThinkingInput(raw)) {
|
|
43064
|
+
appendSystem(
|
|
43065
|
+
ctx.setMessages,
|
|
43066
|
+
`[effort] invalid spec "${raw}" \u2014 use auto | off | low | medium | high | budget:<tokens>`
|
|
43067
|
+
);
|
|
43068
|
+
return;
|
|
43069
|
+
}
|
|
43070
|
+
const spec = parseThinkingSpec(raw);
|
|
43071
|
+
try {
|
|
43072
|
+
setThinkingForProvider(id, spec);
|
|
43073
|
+
ctx.setProviderConfig(getProviderConfig());
|
|
43074
|
+
appendSystem(ctx.setMessages, `[effort] ${ctx.activeProviderSpec.displayName} \u2192 ${stringifyThinkingSpec(spec)}`);
|
|
43075
|
+
} catch (err) {
|
|
43076
|
+
appendSystem(ctx.setMessages, `[effort error] ${err instanceof Error ? err.message : String(err)}`);
|
|
43077
|
+
}
|
|
43078
|
+
}
|
|
42795
43079
|
function buildModelPickerItems(models, activeModel, defaultModel) {
|
|
42796
43080
|
const items = models.map((m) => ({
|
|
42797
43081
|
value: m.id,
|
|
@@ -42895,6 +43179,7 @@ var init_provider2 = __esm({
|
|
|
42895
43179
|
init_refreshRegistry();
|
|
42896
43180
|
init_keyValidator();
|
|
42897
43181
|
init_providerConfig();
|
|
43182
|
+
init_thinking();
|
|
42898
43183
|
init_modelDiscovery();
|
|
42899
43184
|
init_messageHelpers();
|
|
42900
43185
|
init_duration();
|
|
@@ -43238,6 +43523,7 @@ function parseSetConfigFlags(argv) {
|
|
|
43238
43523
|
let provider;
|
|
43239
43524
|
let model;
|
|
43240
43525
|
let endpoint;
|
|
43526
|
+
let thinking;
|
|
43241
43527
|
let endpointClear = false;
|
|
43242
43528
|
for (let i = 0; i < argv.length; i++) {
|
|
43243
43529
|
const arg = argv[i];
|
|
@@ -43250,14 +43536,17 @@ function parseSetConfigFlags(argv) {
|
|
|
43250
43536
|
} else if (arg === "--endpoint") {
|
|
43251
43537
|
endpoint = argv[i + 1];
|
|
43252
43538
|
i++;
|
|
43539
|
+
} else if (arg === "--thinking") {
|
|
43540
|
+
thinking = argv[i + 1];
|
|
43541
|
+
i++;
|
|
43253
43542
|
} else if (arg === "--endpoint-clear") {
|
|
43254
43543
|
endpointClear = true;
|
|
43255
43544
|
}
|
|
43256
43545
|
}
|
|
43257
|
-
if (!provider && !model && !endpoint && !endpointClear) {
|
|
43546
|
+
if (!provider && !model && !endpoint && !endpointClear && !thinking) {
|
|
43258
43547
|
return {
|
|
43259
43548
|
request: null,
|
|
43260
|
-
error: "--set-config requires --provider, --model, --endpoint, and/or --endpoint-clear"
|
|
43549
|
+
error: "--set-config requires --provider, --model, --endpoint, --thinking, and/or --endpoint-clear"
|
|
43261
43550
|
};
|
|
43262
43551
|
}
|
|
43263
43552
|
if (provider !== void 0 && provider.trim().length === 0) {
|
|
@@ -43272,12 +43561,16 @@ function parseSetConfigFlags(argv) {
|
|
|
43272
43561
|
if (endpoint && endpointClear) {
|
|
43273
43562
|
return { request: null, error: "--endpoint and --endpoint-clear conflict" };
|
|
43274
43563
|
}
|
|
43564
|
+
if (thinking !== void 0 && !isValidThinkingInput(thinking)) {
|
|
43565
|
+
return { request: null, error: `invalid --thinking value '${thinking}'` };
|
|
43566
|
+
}
|
|
43275
43567
|
return {
|
|
43276
43568
|
request: {
|
|
43277
43569
|
provider: provider?.trim(),
|
|
43278
43570
|
model: model?.trim(),
|
|
43279
43571
|
endpoint: endpoint?.trim(),
|
|
43280
|
-
endpointClear: endpointClear || void 0
|
|
43572
|
+
endpointClear: endpointClear || void 0,
|
|
43573
|
+
thinking: thinking?.trim().toLowerCase()
|
|
43281
43574
|
}
|
|
43282
43575
|
};
|
|
43283
43576
|
}
|
|
@@ -43352,7 +43645,9 @@ function buildDesktopConfigSnapshot() {
|
|
|
43352
43645
|
authKind: !hasKey ? "none" : oauth ? "oauth" : "api_key",
|
|
43353
43646
|
expiresAt: stored?.expiresAt ?? null,
|
|
43354
43647
|
hasRefreshToken: Boolean(stored?.refreshToken),
|
|
43355
|
-
oauthSupported: isOAuthProvider(p3.id)
|
|
43648
|
+
oauthSupported: isOAuthProvider(p3.id),
|
|
43649
|
+
thinking: config2.thinkingByProvider[p3.id] ?? "auto",
|
|
43650
|
+
thinkingCapability: thinkingCapabilityFor(p3.id)
|
|
43356
43651
|
};
|
|
43357
43652
|
});
|
|
43358
43653
|
return {
|
|
@@ -43394,6 +43689,9 @@ function applySetConfig(req) {
|
|
|
43394
43689
|
if (req.model) {
|
|
43395
43690
|
setModelForProvider(targetProvider, req.model);
|
|
43396
43691
|
}
|
|
43692
|
+
if (req.thinking) {
|
|
43693
|
+
setThinkingForProvider(targetProvider, parseThinkingSpec(req.thinking));
|
|
43694
|
+
}
|
|
43397
43695
|
const after = getProviderConfig();
|
|
43398
43696
|
const ep = getCustomEndpoint(after.activeProviderId);
|
|
43399
43697
|
return {
|
|
@@ -43470,6 +43768,7 @@ var init_desktopConfig = __esm({
|
|
|
43470
43768
|
init_providerConfig();
|
|
43471
43769
|
init_modelDiscovery();
|
|
43472
43770
|
init_updater();
|
|
43771
|
+
init_thinking();
|
|
43473
43772
|
DISCOVERABLE = [
|
|
43474
43773
|
"grok",
|
|
43475
43774
|
"glm",
|
|
@@ -50629,6 +50928,13 @@ ${formatSkillList(availableSkills)}`
|
|
|
50629
50928
|
}
|
|
50630
50929
|
return { handled: true, kind: "provider_set", provider: subcommand };
|
|
50631
50930
|
}
|
|
50931
|
+
case "effort": {
|
|
50932
|
+
const spec = args[0];
|
|
50933
|
+
if (!spec || spec === "show") {
|
|
50934
|
+
return { handled: true, kind: "effort_show" };
|
|
50935
|
+
}
|
|
50936
|
+
return { handled: true, kind: "effort_set", effortSpec: spec };
|
|
50937
|
+
}
|
|
50632
50938
|
case "branch": {
|
|
50633
50939
|
const name = args[0];
|
|
50634
50940
|
if (!name) {
|
|
@@ -53122,6 +53428,16 @@ function useSlashDispatch(params) {
|
|
|
53122
53428
|
setInput("");
|
|
53123
53429
|
return;
|
|
53124
53430
|
}
|
|
53431
|
+
if (result.kind === "effort_set" && result.effortSpec) {
|
|
53432
|
+
handleEffortSet(providerCtx, result.effortSpec);
|
|
53433
|
+
setInput("");
|
|
53434
|
+
return;
|
|
53435
|
+
}
|
|
53436
|
+
if (result.kind === "effort_show") {
|
|
53437
|
+
handleEffortShow(providerCtx);
|
|
53438
|
+
setInput("");
|
|
53439
|
+
return;
|
|
53440
|
+
}
|
|
53125
53441
|
if (result.kind === "models_list") {
|
|
53126
53442
|
handleModelsList(providerCtx);
|
|
53127
53443
|
setInput("");
|
|
@@ -56186,7 +56502,7 @@ function pickRootComponent() {
|
|
|
56186
56502
|
}
|
|
56187
56503
|
if (argv.includes("--help") || argv.includes("-h")) {
|
|
56188
56504
|
console.log(
|
|
56189
|
-
"zelari-code \u2014 AI Council coding agent CLI.\n\nUsage: zelari-code [options]\n\nOptions:\n --version, -v Print version and exit\n --help, -h Print this help and exit\n --doctor Diagnose install health (shim, bundle, PATH, deps,\n node/git/bash in the agent shell)\n --inspect [--json] Unified project inspection (config, skills, MCP,\n hooks, plugins, AGENTS.md, trust status)\n --trust [path] Trust the cwd (or path) so project MCP + hooks load\n --fix-path Add the npm global prefix to the user PATH\n (Windows only; fixes 'command not found' after install)\n --fix-budget Set recommended ZELARI_MAX_TOOL_LOOP_HARD=180,\n ZELARI_MAX_TOOL_LOOP_ITERATIONS=60, ZELARI_CONTEXT_LIMIT=400000\n at User scope (prevents the agent stopping mid-task)\n --permission-mcp <socket> MCP stdio server for external agent permission prompts\n (spawned by claude --permission-prompt-tool)\n --skip-checks Skip the boot-time prerequisite check\n (alias for ZELARI_SKIP_PREFLIGHT=1)\n --no-wizard Skip the first-run wizard\n --reset-config Re-run the wizard (clears provider.json on commit)\n --headless Run a single task without mounting the TUI\n --task <text> Task prompt (required in headless mode)\n --output json|plain Output format (default: json)\n --mode kraken|council|zelari Dispatch mode (default: kraken; agent=alias)\n --council Alias for --mode council\n --phase plan|build Work phase (default: build)\n --provider <id> Provider override (default: active)\n --model <id> Model override (default: provider default)\n serve Companion host for Android/remote clients (Tailscale)\n --bind <ip> Listen address (default: 127.0.0.1; use Tailscale IP)\n --port <n> Port (default: 7421)\n --token <secret> Bearer token (default: ~/.zelari-code/companion.token)\n --project <path> Allowlisted project root (repeatable)\n --save-projects Persist --project list to companion.json\n --print-config Print provider/model config as JSON (no secrets)\n --plugins-status JSON status of optional plugins (Playwright, eslint, \u2026)\n --plugins-install <id> Install plugin (playwright also fetches Chromium)\n --cwd <path> Workspace for -D installs (default: process.cwd())\n --set-config Persist provider/model/endpoint\n --provider <id> Set active provider\n --model <id> Set model for that provider\n --endpoint <url> Custom OpenAI-compatible base URL\n --endpoint-clear Remove custom endpoint override\n --set-key Store an API key (never printed back)\n --provider <id> Provider id (required)\n --key <secret> API key (required)\n --login-oauth Start subscription OAuth (grok, chatgpt, anthropic)\n --provider <id> grok | chatgpt | anthropic\n --code <paste> Anthropic magic-link code (CODE#STATE)\n --no-browser Do not open the system browser\n --refresh-oauth Force-refresh an OAuth access token\n --provider <id> grok | chatgpt | anthropic\n --logout-oauth Clear stored OAuth credentials\n --provider <id> grok | chatgpt | anthropic\n --discover-models Refresh model list for a provider\n --provider <id> Provider (default: active)\n --print-mcp Print MCP server config (user + project)\n --cwd <path> Project root for .zelari/mcp.json\n --set-mcp Add/update an MCP server entry\n --name <id> Server name (required)\n --command <bin> Executable (required)\n --args <json> JSON array of args (optional)\n --scope user|project Default: user\n --enabled true|false Default: true\n --cwd <path> Required when scope=project\n --set-mcp-preset Install a named MCP preset (e.g. cua)\n --preset cua Cua Driver desktop computer-use (MCP)\n --scope user|project Default: user\n --cwd <path> Required when scope=project\n --remove-mcp Remove an MCP server entry\n --name <id> --scope user|project [--cwd <path>]\n --print-skills Print skills (builtin + user + project)\n --cwd <path> Project root for .zelari/skills\n --set-skill Add/update a SKILL.md skill\n --name <id> Skill id (required)\n --description <t> One-line description (required)\n --body <text> Markdown instructions (required)\n --category <c> plan|refactor|debug|review|test|docs|ops|git|db|maint\n --tools <csv> Comma-separated required tools (optional)\n --cost <l> low|medium|high (default: medium)\n --scope user|project Default: user\n --cwd <path> Required when scope=project\n --remove-skill Remove a user/project SKILL.md\n --name <id> --scope user|project [--cwd <path>]\n --generate-skill-from-url Fetch URL + draft skill via model (JSON)\n --url <https://...> Required\n --provider <id> Override active provider\n --model <name> Override model for the selected provider\n --print-ssh-targets Print SSH deploy/monitor targets\n --set-ssh-target Upsert target (--json '{...}' or flags)\n --remove-ssh-target --id <id>\n --test-ssh-target --id <id> (BatchMode ssh true)\n --print-ssh-pubkey --path <private-or-.pub> (display public key)\n\nEnvironment:\n ZELARI_NO_WIZARD=1 Skip the first-run wizard\n ZELARI_SKIP_PREFLIGHT=1 Skip the boot prerequisite check\n ZELARI_NO_PLUGIN_PROMPT=1 Skip the boot plugin-install prompt\n ANATHEMA_DEV=1 Disable background update check + preflight\n"
|
|
56505
|
+
"zelari-code \u2014 AI Council coding agent CLI.\n\nUsage: zelari-code [options]\n\nOptions:\n --version, -v Print version and exit\n --help, -h Print this help and exit\n --doctor Diagnose install health (shim, bundle, PATH, deps,\n node/git/bash in the agent shell)\n --inspect [--json] Unified project inspection (config, skills, MCP,\n hooks, plugins, AGENTS.md, trust status)\n --trust [path] Trust the cwd (or path) so project MCP + hooks load\n --fix-path Add the npm global prefix to the user PATH\n (Windows only; fixes 'command not found' after install)\n --fix-budget Set recommended ZELARI_MAX_TOOL_LOOP_HARD=180,\n ZELARI_MAX_TOOL_LOOP_ITERATIONS=60, ZELARI_CONTEXT_LIMIT=400000\n at User scope (prevents the agent stopping mid-task)\n --permission-mcp <socket> MCP stdio server for external agent permission prompts\n (spawned by claude --permission-prompt-tool)\n --skip-checks Skip the boot-time prerequisite check\n (alias for ZELARI_SKIP_PREFLIGHT=1)\n --no-wizard Skip the first-run wizard\n --reset-config Re-run the wizard (clears provider.json on commit)\n --headless Run a single task without mounting the TUI\n --task <text> Task prompt (required in headless mode)\n --output json|plain Output format (default: json)\n --mode kraken|council|zelari Dispatch mode (default: kraken; agent=alias)\n --council Alias for --mode council\n --phase plan|build Work phase (default: build)\n --provider <id> Provider override (default: active)\n --model <id> Model override (default: provider default)\n serve Companion host for Android/remote clients (Tailscale)\n --bind <ip> Listen address (default: 127.0.0.1; use Tailscale IP)\n --port <n> Port (default: 7421)\n --token <secret> Bearer token (default: ~/.zelari-code/companion.token)\n --project <path> Allowlisted project root (repeatable)\n --save-projects Persist --project list to companion.json\n --print-config Print provider/model config as JSON (no secrets)\n --plugins-status JSON status of optional plugins (Playwright, eslint, \u2026)\n --plugins-install <id> Install plugin (playwright also fetches Chromium)\n --cwd <path> Workspace for -D installs (default: process.cwd())\n --set-config Persist provider/model/endpoint\n --provider <id> Set active provider\n --model <id> Set model for that provider\n --endpoint <url> Custom OpenAI-compatible base URL\n --endpoint-clear Remove custom endpoint override\n --thinking <spec> Thinking effort (auto|off|low|medium|high|budget:N)\n --set-key Store an API key (never printed back)\n --provider <id> Provider id (required)\n --key <secret> API key (required)\n --login-oauth Start subscription OAuth (grok, chatgpt, anthropic)\n --provider <id> grok | chatgpt | anthropic\n --code <paste> Anthropic magic-link code (CODE#STATE)\n --no-browser Do not open the system browser\n --refresh-oauth Force-refresh an OAuth access token\n --provider <id> grok | chatgpt | anthropic\n --logout-oauth Clear stored OAuth credentials\n --provider <id> grok | chatgpt | anthropic\n --discover-models Refresh model list for a provider\n --provider <id> Provider (default: active)\n --print-mcp Print MCP server config (user + project)\n --cwd <path> Project root for .zelari/mcp.json\n --set-mcp Add/update an MCP server entry\n --name <id> Server name (required)\n --command <bin> Executable (required)\n --args <json> JSON array of args (optional)\n --scope user|project Default: user\n --enabled true|false Default: true\n --cwd <path> Required when scope=project\n --set-mcp-preset Install a named MCP preset (e.g. cua)\n --preset cua Cua Driver desktop computer-use (MCP)\n --scope user|project Default: user\n --cwd <path> Required when scope=project\n --remove-mcp Remove an MCP server entry\n --name <id> --scope user|project [--cwd <path>]\n --print-skills Print skills (builtin + user + project)\n --cwd <path> Project root for .zelari/skills\n --set-skill Add/update a SKILL.md skill\n --name <id> Skill id (required)\n --description <t> One-line description (required)\n --body <text> Markdown instructions (required)\n --category <c> plan|refactor|debug|review|test|docs|ops|git|db|maint\n --tools <csv> Comma-separated required tools (optional)\n --cost <l> low|medium|high (default: medium)\n --scope user|project Default: user\n --cwd <path> Required when scope=project\n --remove-skill Remove a user/project SKILL.md\n --name <id> --scope user|project [--cwd <path>]\n --generate-skill-from-url Fetch URL + draft skill via model (JSON)\n --url <https://...> Required\n --provider <id> Override active provider\n --model <name> Override model for the selected provider\n --print-ssh-targets Print SSH deploy/monitor targets\n --set-ssh-target Upsert target (--json '{...}' or flags)\n --remove-ssh-target --id <id>\n --test-ssh-target --id <id> (BatchMode ssh true)\n --print-ssh-pubkey --path <private-or-.pub> (display public key)\n\nEnvironment:\n ZELARI_NO_WIZARD=1 Skip the first-run wizard\n ZELARI_SKIP_PREFLIGHT=1 Skip the boot prerequisite check\n ZELARI_NO_PLUGIN_PROMPT=1 Skip the boot plugin-install prompt\n ANATHEMA_DEV=1 Disable background update check + preflight\n"
|
|
56190
56506
|
);
|
|
56191
56507
|
process.exit(0);
|
|
56192
56508
|
}
|