dsh-grok-subscription 1.1.3 → 2.0.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/lib/index.js CHANGED
@@ -7,7 +7,6 @@ var DISPLAY_NAME_ZH = "Grok \u8BA2\u9605";
7
7
  var SETTINGS_NAMESPACE = "grokSubscription";
8
8
  var CREDENTIAL_REF_NAME = "GROK_BUILD_ACCESS_TOKEN";
9
9
  var PROXY_BASE_URL = "https://cli-chat-proxy.grok.com/v1";
10
- var RESPONSES_URL = "https://cli-chat-proxy.grok.com/v1/responses";
11
10
  var MODELS_V2_URL = "https://cli-chat-proxy.grok.com/v1/models-v2";
12
11
  var BILLING_CREDITS_URL = "https://cli-chat-proxy.grok.com/v1/billing?format=credits";
13
12
  var TOKEN_AUTH_HEADER = "X-XAI-Token-Auth";
@@ -418,31 +417,6 @@ function toPiModels(models) {
418
417
  };
419
418
  });
420
419
  }
421
- function reasoningInfoOf(model) {
422
- if (model?.reasoning === false) return void 0;
423
- const efforts = Array.isArray(model?.reasoningEfforts) && model.reasoningEfforts.length ? model.reasoningEfforts : ["low", "medium", "high", "xhigh"];
424
- const title = (id) => `${id.charAt(0).toUpperCase()}${id.slice(1)}`;
425
- const preferred = model?.defaultEffort && efforts.includes(model.defaultEffort) ? model.defaultEffort : efforts.includes("high") ? "high" : efforts[efforts.length - 1];
426
- return {
427
- efforts: efforts.map((id) => ({ id, name: title(id) })),
428
- defaultEffort: preferred
429
- };
430
- }
431
- function toLlmModels(models) {
432
- return models.map((model) => {
433
- const info = {
434
- provider: PROVIDER_ID,
435
- id: model.id,
436
- name: model.name,
437
- // The bundled adapter inlines images through the host attachment store,
438
- // so it advertises the same modality map as the official pi-ai path.
439
- inputModalities: supportsImageInput(model.id) ? ["text", "image"] : ["text"]
440
- };
441
- const reasoning = reasoningInfoOf(model);
442
- if (reasoning) info.reasoning = reasoning;
443
- return info;
444
- });
445
- }
446
420
  async function fetchLiveCatalog(accessToken, options = {}) {
447
421
  const fetchImpl = options.fetch ?? globalThis.fetch;
448
422
  const signal = options.signal ?? AbortSignal.timeout(options.timeoutMs ?? CATALOG_TIMEOUT_MS);
@@ -909,81 +883,7 @@ async function optionalImport(specifier, options = {}) {
909
883
  }
910
884
  return void 0;
911
885
  }
912
- function textOf(content) {
913
- if (typeof content === "string") return content;
914
- if (!Array.isArray(content)) return "";
915
- return content.map((block) => {
916
- if (typeof block === "string") return block;
917
- if (block?.type === "text") return block.text ?? "";
918
- if (block?.type === "reasoning") return "";
919
- if (block?.type === "tool-result") {
920
- return typeof block.content === "string" ? block.content : textOf(block.content);
921
- }
922
- return "";
923
- }).join("");
924
- }
925
- function imagePlaceholderText(ref) {
926
- const name2 = typeof ref?.name === "string" && ref.name.trim() ? ` ${JSON.stringify(ref.name.trim())}` : "";
927
- return `[attached image${name2} could not be included in this request]`;
928
- }
929
- async function collectImageParts(options, resolveAttachments, policy = {}) {
930
- const parts = /* @__PURE__ */ new Map();
931
- const refs = [];
932
- for (const message of options.messages ?? []) {
933
- for (const block of message?.content ?? []) {
934
- if (block?.type !== "image" || !block.attachment) continue;
935
- const id = block.attachment.attachmentId;
936
- if (typeof id !== "string" || !id || parts.has(id)) continue;
937
- parts.set(id, void 0);
938
- refs.push(block.attachment);
939
- }
940
- }
941
- if (refs.length === 0) return parts;
942
- let store;
943
- try {
944
- store = resolveAttachments?.();
945
- } catch {
946
- store = void 0;
947
- }
948
- if (!store?.readImageRequest) return parts;
949
- const request = {
950
- maxPixels: policy.maxPixels ?? REQUEST_IMAGE_PIXEL_BUDGET,
951
- maxBytes: policy.maxBytes ?? REQUEST_IMAGE_MAX_BYTES
952
- };
953
- await Promise.all(refs.map(async (ref) => {
954
- try {
955
- const version = await store.readImageRequest(ref, request);
956
- if (!version?.data || typeof version.mediaType !== "string" || !version.mediaType) return;
957
- parts.set(ref.attachmentId, {
958
- mediaType: version.mediaType,
959
- base64: Buffer.from(version.data).toString("base64")
960
- });
961
- } catch {
962
- }
963
- }));
964
- return parts;
965
- }
966
- function imageContentParts(blocks, imageParts) {
967
- const parts = [];
968
- const text = textOf(blocks);
969
- if (text) parts.push({ type: "input_text", text });
970
- for (const block of blocks ?? []) {
971
- if (block?.type !== "image" || !block.attachment) continue;
972
- const resolved = imageParts?.get(block.attachment.attachmentId);
973
- if (resolved) {
974
- parts.push({
975
- type: "input_image",
976
- image_url: `data:${resolved.mediaType};base64,${resolved.base64}`
977
- });
978
- } else {
979
- parts.push({ type: "input_text", text: imagePlaceholderText(block.attachment) });
980
- }
981
- }
982
- return parts;
983
- }
984
886
  var PROMPT_CACHE_KEY_MAX_LENGTH = 64;
985
- var REPLAY_KIND = "grok-build-responses";
986
- var REPLAY_VERSION = 1;
987
887
  function promptCacheKey(options) {
988
888
  const sessionId = typeof options?.sessionId === "string" ? options.sessionId.trim() : "";
989
889
  if (!sessionId) return void 0;
@@ -991,455 +891,10 @@ function promptCacheKey(options) {
991
891
  const key = `grok${suffix}:${sessionId}`;
992
892
  return key.length <= PROMPT_CACHE_KEY_MAX_LENGTH ? key : key.slice(0, PROMPT_CACHE_KEY_MAX_LENGTH);
993
893
  }
994
- function cacheStableTools(tools) {
995
- if (!Array.isArray(tools) || tools.length === 0) return [];
996
- return tools.map((tool, index) => ({ tool, index })).sort((left, right) => {
997
- const byName = String(left.tool?.name ?? "").localeCompare(String(right.tool?.name ?? ""));
998
- return byName === 0 ? left.index - right.index : byName;
999
- }).map(({ tool }) => ({
1000
- type: "function",
1001
- name: tool.name,
1002
- description: tool.description,
1003
- parameters: tool.parameters
1004
- }));
1005
- }
1006
- function replayEnvelope(message) {
1007
- const state = message?.source?.replayState;
1008
- return state?.response?.kind === REPLAY_KIND && state.response.version === REPLAY_VERSION && Array.isArray(state.blocks) ? state : void 0;
1009
- }
1010
- function replayReasoningItem(message, contentIndex) {
1011
- const entry = replayEnvelope(message)?.blocks[contentIndex];
1012
- const item = entry?.type === "reasoning" ? entry.item : void 0;
1013
- return item?.type === "reasoning" && typeof item.encrypted_content === "string" && item.encrypted_content ? item : void 0;
1014
- }
1015
- function responsesInput(options, imageParts) {
1016
- const input = [];
1017
- const system = typeof options.system === "string" && options.system ? options.system : void 0;
1018
- if (system) input.push({ role: "system", content: system });
1019
- for (const message of options.messages ?? []) {
1020
- const role = message.role === "assistant" ? "assistant" : message.role === "system" ? "system" : "user";
1021
- const toolCalls = (message.content ?? []).filter((block) => block?.type === "tool-call");
1022
- const toolResults = (message.content ?? []).filter((block) => block?.type === "tool-result");
1023
- if (toolResults.length) {
1024
- for (const block of toolResults) {
1025
- input.push({
1026
- type: "function_call_output",
1027
- call_id: block.toolCallId ?? block.id,
1028
- output: textOf(block.content)
1029
- });
1030
- }
1031
- continue;
1032
- }
1033
- if (role === "assistant" && toolCalls.length) {
1034
- const content = message.content ?? [];
1035
- for (let index = 0; index < content.length; index++) {
1036
- const block = content[index];
1037
- if (block?.type === "reasoning") {
1038
- const item = replayReasoningItem(message, index);
1039
- if (item) input.push(item);
1040
- continue;
1041
- }
1042
- if (block?.type !== "tool-call") continue;
1043
- input.push({
1044
- type: "function_call",
1045
- call_id: block.id,
1046
- name: block.name,
1047
- arguments: typeof block.arguments === "string" ? block.arguments : JSON.stringify(block.arguments ?? {})
1048
- });
1049
- }
1050
- const text2 = textOf(message.content);
1051
- if (text2) input.push({ role: "assistant", content: text2 });
1052
- continue;
1053
- }
1054
- const hasImage = (message.content ?? []).some((block) => block?.type === "image");
1055
- if (role === "user" && hasImage) {
1056
- const parts = imageContentParts(message.content, imageParts);
1057
- if (parts.length > 0) input.push({ role, content: parts });
1058
- continue;
1059
- }
1060
- if (role === "assistant") {
1061
- const content = message.content ?? [];
1062
- const output = [];
1063
- let text2 = "";
1064
- for (let index = 0; index < content.length; index++) {
1065
- const block = content[index];
1066
- if (block?.type === "reasoning") {
1067
- const item = replayReasoningItem(message, index);
1068
- if (item) output.push(item);
1069
- } else if (block?.type === "text" && block.text) {
1070
- text2 += block.text;
1071
- }
1072
- }
1073
- if (text2) output.push({ role: "assistant", content: text2 });
1074
- input.push(...output);
1075
- continue;
1076
- }
1077
- const text = textOf(message.content);
1078
- if (!text) continue;
1079
- input.push({ role, content: text });
1080
- }
1081
- return input;
1082
- }
1083
- function mapFinish(reason) {
1084
- if (reason === "toolUse" || reason === "tool_calls") return { kind: "tool-calls" };
1085
- if (reason === "length" || reason === "max_tokens") return { kind: "max-tokens" };
1086
- return { kind: "stop" };
1087
- }
1088
- function finiteOr(value, fallback) {
1089
- return typeof value === "number" && Number.isFinite(value) ? value : fallback;
1090
- }
1091
- function jsonSafeChunk(value) {
1092
- if (value === null) return null;
1093
- const type = typeof value;
1094
- if (type === "string" || type === "boolean") return value;
1095
- if (type === "number") return Number.isFinite(value) && !Object.is(value, -0) ? value : void 0;
1096
- if (type !== "object") return void 0;
1097
- if (Array.isArray(value)) {
1098
- const list = [];
1099
- for (const item of value) {
1100
- const safe = jsonSafeChunk(item);
1101
- if (safe !== void 0) list.push(safe);
1102
- }
1103
- return list;
1104
- }
1105
- const out = {};
1106
- for (const [key, item] of Object.entries(value)) {
1107
- const safe = jsonSafeChunk(item);
1108
- if (safe !== void 0) out[key] = safe;
1109
- }
1110
- return out;
1111
- }
1112
- async function* streamResponsesUnsafe(options, token) {
1113
- const headers = {
1114
- Accept: "text/event-stream",
1115
- "Content-Type": "application/json",
1116
- ...buildProxyHeaders(token)
1117
- };
1118
- try {
1119
- const llm = await optionalImport("@deepseek-ai/dsh-llm");
1120
- if (typeof llm?.attributionHeaders === "function") Object.assign(headers, llm.attributionHeaders());
1121
- } catch {
1122
- }
1123
- const body = {
1124
- model: options.model,
1125
- input: responsesInput(options, await collectImageParts(options, options.resolveAttachments)),
1126
- stream: true,
1127
- // grok-4.7 returns ciphertext by default, but naming it keeps replay explicit
1128
- // for every reasoning model on this proxy.
1129
- include: ["reasoning.encrypted_content"]
1130
- };
1131
- const cacheKey = promptCacheKey(options);
1132
- if (cacheKey) body.prompt_cache_key = cacheKey;
1133
- if (typeof options.maxTokens === "number") body.max_output_tokens = options.maxTokens;
1134
- if (typeof options.temperature === "number") body.temperature = options.temperature;
1135
- const tools = cacheStableTools(options.tools);
1136
- if (tools.length) body.tools = tools;
1137
- if (options.reasoningEffort) body.reasoning = { effort: options.reasoningEffort };
1138
- const response = await fetch(RESPONSES_URL, {
1139
- method: "POST",
1140
- headers,
1141
- body: JSON.stringify(body),
1142
- redirect: "error",
1143
- signal: options.signal
1144
- });
1145
- if (!response.ok) {
1146
- const error = new Error(`Grok Build proxy returned HTTP ${response.status}`);
1147
- error.status = response.status;
1148
- throw error;
1149
- }
1150
- if (!response.body) throw new Error("Grok Build proxy returned an empty body");
1151
- const decoder = new TextDecoder();
1152
- let buffer = "";
1153
- let textIndex;
1154
- let reasoningIndex;
1155
- let textContent = "";
1156
- let reasoningContent = "";
1157
- let nextIndex = 0;
1158
- const emittedBlocks = [];
1159
- const toolBlocks = /* @__PURE__ */ new Map();
1160
- const toolNames = /* @__PURE__ */ new Map();
1161
- let usage;
1162
- let finish = { kind: "stop" };
1163
- const toolIdOf = (payload) => {
1164
- const id = payload?.item_id ?? payload?.call_id ?? payload?.id;
1165
- return typeof id === "string" && id ? id : void 0;
1166
- };
1167
- const learnToolName = (id, name2) => {
1168
- if (typeof id !== "string" || !id || typeof name2 !== "string" || !name2) return;
1169
- toolNames.set(id, name2);
1170
- const tool = toolBlocks.get(id);
1171
- if (tool) tool.name = name2;
1172
- };
1173
- const adoptToolArguments = (id, value) => {
1174
- if (typeof id !== "string" || typeof value !== "string" || !value) return;
1175
- const tool = toolBlocks.get(id);
1176
- if (tool && value.length > tool.arguments.length) tool.arguments = value;
1177
- };
1178
- const flushSse = function* (raw) {
1179
- const lines = raw.split("\n");
1180
- let event = "message";
1181
- const data = [];
1182
- for (const line of lines) {
1183
- if (line.startsWith("event:")) event = line.slice(6).trim();
1184
- else if (line.startsWith("data:")) data.push(line.slice(5).trim());
1185
- }
1186
- const payloadText = data.join("\n");
1187
- if (!payloadText || payloadText === "[DONE]") return;
1188
- let payload;
1189
- try {
1190
- payload = JSON.parse(payloadText);
1191
- } catch {
1192
- return;
1193
- }
1194
- const type = payload.type ?? event;
1195
- if (type === "response.output_text.delta" || type === "response.text.delta") {
1196
- const delta = payload.delta ?? payload.text ?? "";
1197
- if (!delta) return;
1198
- if (textIndex === void 0) {
1199
- textIndex = nextIndex++;
1200
- emittedBlocks[textIndex] = { type: "text" };
1201
- yield { type: "block-start", index: textIndex, blockType: "text" };
1202
- }
1203
- textContent += delta;
1204
- yield { type: "text-delta", index: textIndex, text: String(delta) };
1205
- return;
1206
- }
1207
- if (type === "response.reasoning_text.delta" || type === "response.reasoning.delta" || type === "response.reasoning_summary_text.delta") {
1208
- const delta = payload.delta ?? payload.text ?? "";
1209
- if (!delta) return;
1210
- if (reasoningIndex === void 0) {
1211
- reasoningIndex = nextIndex++;
1212
- emittedBlocks[reasoningIndex] = { type: "reasoning" };
1213
- yield { type: "block-start", index: reasoningIndex, blockType: "reasoning" };
1214
- }
1215
- reasoningContent += delta;
1216
- yield { type: "reasoning-delta", index: reasoningIndex, text: String(delta) };
1217
- return;
1218
- }
1219
- if (type === "response.output_item.added" || type === "response.output_item.done") {
1220
- const item = payload.item;
1221
- if (item?.type === "reasoning" && typeof item.encrypted_content === "string" && item.encrypted_content) {
1222
- if (reasoningIndex === void 0) {
1223
- reasoningIndex = nextIndex++;
1224
- emittedBlocks[reasoningIndex] = { type: "reasoning" };
1225
- yield { type: "block-start", index: reasoningIndex, blockType: "reasoning" };
1226
- }
1227
- emittedBlocks[reasoningIndex] = { type: "reasoning", item };
1228
- }
1229
- if (item?.type === "function_call") {
1230
- learnToolName(item.id, item.name);
1231
- learnToolName(item.call_id, item.name);
1232
- adoptToolArguments(item.id, item.arguments);
1233
- }
1234
- return;
1235
- }
1236
- if (type === "response.function_call_arguments.done") {
1237
- const id = toolIdOf(payload);
1238
- learnToolName(id, payload.name);
1239
- adoptToolArguments(id, payload.arguments);
1240
- return;
1241
- }
1242
- if (type === "response.function_call_arguments.delta") {
1243
- const id = toolIdOf(payload);
1244
- if (!id) return;
1245
- let tool = toolBlocks.get(id);
1246
- if (!tool) {
1247
- tool = {
1248
- index: nextIndex++,
1249
- id,
1250
- // Never leave this undefined: an unserializable chunk aborts the turn.
1251
- name: toolNames.get(id) ?? "tool",
1252
- arguments: ""
1253
- };
1254
- emittedBlocks[tool.index] = { type: "tool-call" };
1255
- toolBlocks.set(id, tool);
1256
- yield { type: "block-start", index: tool.index, blockType: "tool-call" };
1257
- }
1258
- const delta = payload.delta ?? payload.arguments ?? "";
1259
- tool.arguments += delta;
1260
- yield { type: "tool-call-delta", index: tool.index, id, name: tool.name, argumentsDelta: String(delta) };
1261
- return;
1262
- }
1263
- if (type === "response.completed") {
1264
- for (const item of payload.response?.output ?? []) {
1265
- if (item?.type !== "function_call") continue;
1266
- learnToolName(item.id, item.name);
1267
- learnToolName(item.call_id, item.name);
1268
- const id = typeof item.id === "string" && item.id ? item.id : void 0;
1269
- if (id && !toolBlocks.has(id)) {
1270
- const tool = { index: nextIndex++, id, name: toolNames.get(id) ?? "tool", arguments: "" };
1271
- toolBlocks.set(id, tool);
1272
- emittedBlocks[tool.index] = { type: "tool-call" };
1273
- yield { type: "block-start", index: tool.index, blockType: "tool-call" };
1274
- }
1275
- adoptToolArguments(id, item.arguments);
1276
- }
1277
- const responseUsage = payload.response?.usage ?? payload.usage;
1278
- if (responseUsage) {
1279
- const details = responseUsage.input_tokens_details ?? responseUsage.prompt_tokens_details ?? {};
1280
- const cachedTokens = finiteOr(details.cached_tokens, 0);
1281
- const cacheWriteTokens = finiteOr(details.cache_write_tokens, 0);
1282
- const promptTotal = finiteOr(
1283
- responseUsage.input_tokens ?? responseUsage.prompt_tokens,
1284
- 0
1285
- );
1286
- const outputTokens = finiteOr(
1287
- responseUsage.output_tokens ?? responseUsage.completion_tokens,
1288
- 0
1289
- );
1290
- usage = {
1291
- // The provider folds cache hits into the prompt count, while DSH's
1292
- // fields are disjoint: billed input = inputTokens + cacheRead +
1293
- // cacheWrite. Subtracting is what makes the host's "cache hit" figure
1294
- // real instead of a permanent 0%. Both cache fields stay numeric so
1295
- // consumers can always add them up.
1296
- inputTokens: Math.max(0, promptTotal - cachedTokens - cacheWriteTokens),
1297
- outputTokens,
1298
- cacheReadTokens: cachedTokens,
1299
- cacheWriteTokens
1300
- };
1301
- const reasoningTokens = finiteOr(responseUsage.output_tokens_details?.reasoning_tokens, void 0);
1302
- if (reasoningTokens !== void 0) usage.reasoningTokens = reasoningTokens;
1303
- usage.totalTokens = finiteOr(responseUsage.total_tokens, promptTotal + outputTokens);
1304
- }
1305
- finish = mapFinish(payload.response?.status === "incomplete" ? "length" : "stop");
1306
- if (toolBlocks.size) finish = { kind: "tool-calls" };
1307
- }
1308
- if (type === "response.failed" || type === "error") {
1309
- const raw2 = payload.error?.message ?? payload.message;
1310
- const failure = {
1311
- message: typeof raw2 === "string" && raw2 ? raw2 : "Grok Build stream failed",
1312
- code: "PROVIDER"
1313
- };
1314
- const status = finiteOr(payload.error?.status, void 0);
1315
- if (status !== void 0) failure.status = status;
1316
- finish = { kind: "error", failure };
1317
- }
1318
- };
1319
- for await (const chunk of response.body) {
1320
- buffer += decoder.decode(chunk, { stream: true });
1321
- let separator;
1322
- while ((separator = buffer.indexOf("\n\n")) !== -1) {
1323
- const raw = buffer.slice(0, separator);
1324
- buffer = buffer.slice(separator + 2);
1325
- yield* flushSse(raw);
1326
- }
1327
- }
1328
- if (buffer.trim()) yield* flushSse(buffer);
1329
- if (reasoningIndex !== void 0) {
1330
- yield { type: "block-end", index: reasoningIndex, block: { type: "reasoning", text: reasoningContent } };
1331
- }
1332
- if (textIndex !== void 0) {
1333
- yield { type: "block-end", index: textIndex, block: { type: "text", text: textContent } };
1334
- }
1335
- for (const tool of toolBlocks.values()) {
1336
- yield {
1337
- type: "block-end",
1338
- index: tool.index,
1339
- block: { type: "tool-call", id: tool.id, name: tool.name ?? "tool", arguments: tool.arguments }
1340
- };
1341
- }
1342
- if (usage) yield { type: "usage", usage };
1343
- const finishChunk = { type: "finish", reason: finish };
1344
- if (finish.kind !== "error" && finish.kind !== "aborted" && emittedBlocks.length === nextIndex) {
1345
- finishChunk.replayState = {
1346
- response: { kind: REPLAY_KIND, version: REPLAY_VERSION },
1347
- blocks: emittedBlocks
1348
- };
1349
- }
1350
- yield finishChunk;
1351
- }
1352
- async function* streamResponses(options, token) {
1353
- for await (const chunk of streamResponsesUnsafe(options, token)) {
1354
- const safe = jsonSafeChunk(chunk);
1355
- if (safe) yield safe;
1356
- }
1357
- }
1358
894
  function visiblePiModels(session) {
1359
895
  if (session.publicAccount()?.signedIn !== true) return [];
1360
896
  return toPiModels(session.models()).map((model) => model.provider === PROVIDER_ID ? model : { ...model, provider: PROVIDER_ID });
1361
897
  }
1362
- function createDuckAdapter(session, adapterOptions = {}) {
1363
- const providerInfo = () => ({ id: PROVIDER_ID, name: DISPLAY_NAME });
1364
- const list = () => {
1365
- const signedIn = session.publicAccount()?.signedIn === true;
1366
- return signedIn ? toLlmModels(session.models()) : [];
1367
- };
1368
- return {
1369
- providerInfo,
1370
- providerRetryPolicy() {
1371
- return void 0;
1372
- },
1373
- async listModels(provider) {
1374
- if (provider !== PROVIDER_ID) return [];
1375
- return list();
1376
- },
1377
- async resolveModel(provider, model) {
1378
- const found = list().find((item) => item.id === model);
1379
- const raw = session.publicAccount()?.signedIn === true ? session.models().find((item) => item.id === model) : void 0;
1380
- const info = {
1381
- provider,
1382
- id: model,
1383
- name: found?.name ?? model,
1384
- // The host gates prompt attachment admission on resolveModelInfo, NOT on
1385
- // listModels, so this must match the catalog's modality map exactly.
1386
- inputModalities: supportsImageInput(model) ? ["text", "image"] : ["text"],
1387
- context: { contextWindow: raw?.contextWindow ?? 5e5 }
1388
- };
1389
- const reasoning = reasoningInfoOf(raw);
1390
- if (reasoning) info.reasoning = reasoning;
1391
- else if (found?.reasoning) info.reasoning = found.reasoning;
1392
- return info;
1393
- },
1394
- async prepareCall(provider, model, signal) {
1395
- const resolved = await this.resolveModel(provider, model, signal);
1396
- return {
1397
- model: resolved,
1398
- stream: (options) => this.stream(options)
1399
- };
1400
- },
1401
- async *stream(options) {
1402
- if (options.provider !== PROVIDER_ID) {
1403
- yield { type: "finish", reason: { kind: "error", failure: { message: "Unknown provider", code: "NO_ADAPTER" } } };
1404
- return;
1405
- }
1406
- const callOptions = typeof adapterOptions.resolveAttachments === "function" ? { ...options, resolveAttachments: adapterOptions.resolveAttachments } : options;
1407
- let token = await session.currentToken();
1408
- if (!token) {
1409
- yield { type: "finish", reason: { kind: "error", failure: { message: "Grok subscription is not signed in", code: "MISSING_CREDENTIAL" } } };
1410
- return;
1411
- }
1412
- for (let attempt = 0; ; attempt++) {
1413
- let emitted = false;
1414
- try {
1415
- for await (const chunk of streamResponses(callOptions, token, callOptions.resolveAttachments)) {
1416
- emitted = true;
1417
- yield chunk;
1418
- }
1419
- return;
1420
- } catch (error) {
1421
- const aborted = options.signal?.aborted === true;
1422
- const status = finiteOr(error?.status, void 0);
1423
- const canRetry = !aborted && !emitted && attempt === 0 && status === 401 && typeof session.refreshToken === "function";
1424
- if (canRetry) {
1425
- const renewed = await session.refreshToken();
1426
- if (renewed && renewed !== token) {
1427
- token = renewed;
1428
- continue;
1429
- }
1430
- }
1431
- const failure = {
1432
- message: status === 401 ? "Grok Build session is expired or unauthorized (HTTP 401). Run grok login, then Pull from Grok CLI." : error instanceof Error ? error.message : "Grok Build request failed",
1433
- code: aborted ? "ABORTED" : status === 401 ? "UNAUTHORIZED" : "PROVIDER"
1434
- };
1435
- if (status !== void 0) failure.status = status;
1436
- yield { type: "finish", reason: { kind: aborted ? "aborted" : "error", failure } };
1437
- return;
1438
- }
1439
- }
1440
- }
1441
- };
1442
- }
1443
898
  function createStore(session) {
1444
899
  return {
1445
900
  async read(providerId) {
@@ -1473,52 +928,23 @@ function buildAuthConfig() {
1473
928
  }
1474
929
  };
1475
930
  }
1476
- function withEncryptedReasoningInclude(api) {
1477
- const inject2 = (options) => ({
1478
- ...options,
1479
- samplingParams: {
1480
- ...options?.samplingParams,
1481
- include: ["reasoning.encrypted_content"]
1482
- }
1483
- });
931
+ function withGrokRequestSemantics(api) {
932
+ const inject2 = (options) => {
933
+ const cacheKey = options?.cacheRetention === "none" ? void 0 : promptCacheKey(options);
934
+ return {
935
+ ...options,
936
+ samplingParams: {
937
+ ...options?.samplingParams,
938
+ include: ["reasoning.encrypted_content"],
939
+ ...cacheKey === void 0 ? {} : { prompt_cache_key: cacheKey }
940
+ }
941
+ };
942
+ };
1484
943
  return {
1485
944
  stream: (model, context, options) => api.stream(model, context, inject2(options)),
1486
945
  streamSimple: (model, context, options) => api.streamSimple(model, context, inject2(options))
1487
946
  };
1488
947
  }
1489
- function wrapAsHostAdapter(candidate, dshLlm) {
1490
- if (!dshLlm?.LlmAdapter || candidate instanceof dshLlm.LlmAdapter) return candidate;
1491
- class GrokBuildAdapter extends dshLlm.LlmAdapter {
1492
- providerInfo(provider) {
1493
- return candidate.providerInfo(provider);
1494
- }
1495
- providerRetryPolicy(provider) {
1496
- return candidate.providerRetryPolicy(provider);
1497
- }
1498
- listModels(provider) {
1499
- return candidate.listModels(provider);
1500
- }
1501
- resolveModel(provider, model, signal) {
1502
- return candidate.resolveModel(provider, model, signal);
1503
- }
1504
- prepareCall(provider, model, signal) {
1505
- return candidate.prepareCall(provider, model, signal);
1506
- }
1507
- stream(options) {
1508
- return candidate.stream(options);
1509
- }
1510
- }
1511
- return new GrokBuildAdapter();
1512
- }
1513
- function createGrokBuildAdapterSync(session, options = {}) {
1514
- const duck = createDuckAdapter(session, { resolveAttachments: options.resolveAttachments });
1515
- const dshLlm = options.dshLlm;
1516
- return {
1517
- adapter: wrapAsHostAdapter(duck, dshLlm),
1518
- kind: "custom-mvp",
1519
- note: "Registered a sync duck Responses adapter; pi-ai upgrade may follow in the background."
1520
- };
1521
- }
1522
948
  async function createGrokBuildAdapter(session, options = {}) {
1523
949
  const importOpts = options.importOptions ?? {};
1524
950
  const [piAi, dshPi, dshLlm] = await Promise.all([
@@ -1526,13 +952,11 @@ async function createGrokBuildAdapter(session, options = {}) {
1526
952
  optionalImport("@deepseek-ai/dsh-llm-pi-ai", importOpts),
1527
953
  optionalImport("@deepseek-ai/dsh-llm", importOpts)
1528
954
  ]);
1529
- const duck = createDuckAdapter(session, { resolveAttachments: options.resolveAttachments });
1530
- const asHostAdapter = (candidate) => wrapAsHostAdapter(candidate, dshLlm);
1531
955
  if (!piAi?.createProvider || !dshPi?.PiAiAdapter) {
1532
956
  return {
1533
- adapter: asHostAdapter(duck),
1534
- kind: "custom-mvp",
1535
- note: "PiAiAdapter or @earendil-works/pi-ai is not available in this host; using a documented custom Responses adapter."
957
+ adapter: void 0,
958
+ kind: "unavailable",
959
+ note: "the host pi-ai adapter is unavailable: @earendil-works/pi-ai and @deepseek-ai/dsh-llm-pi-ai must be resolvable from the DSH install"
1536
960
  };
1537
961
  }
1538
962
  let responsesApi;
@@ -1543,9 +967,13 @@ async function createGrokBuildAdapter(session, options = {}) {
1543
967
  responsesApi = void 0;
1544
968
  }
1545
969
  if (!responsesApi) {
1546
- return { adapter: asHostAdapter(duck), kind: "custom-mvp", note: "openai-responses API module is unavailable; using the custom adapter." };
970
+ return {
971
+ adapter: void 0,
972
+ kind: "unavailable",
973
+ note: "the pi-ai openai-responses API module is unavailable in this host"
974
+ };
1547
975
  }
1548
- responsesApi = withEncryptedReasoningInclude(responsesApi);
976
+ responsesApi = withGrokRequestSemantics(responsesApi);
1549
977
  const store = createStore(session);
1550
978
  const authModels = piAi.createModels({
1551
979
  credentials: store,
@@ -2729,31 +2157,17 @@ function apply(ctx, options = {}) {
2729
2157
  logger: ctx.logger,
2730
2158
  onCatalogChange: notifyCatalogChange
2731
2159
  });
2732
- const adapterState = { kind: "custom-mvp", upgraded: false };
2160
+ const adapterState = { kind: "starting" };
2733
2161
  const pluginManager = options.pluginManager ?? createGrokPluginManager();
2734
2162
  const handler = createRpcHandler(session, {
2735
2163
  pluginManager,
2736
2164
  diagnostics: () => ({
2737
- adapter: adapterState.upgraded ? "pi-ai" : "fallback",
2738
- adapterKind: adapterState.kind,
2165
+ adapter: adapterState.kind,
2739
2166
  imageInput: typeof resolveAttachments()?.readImageRequest === "function",
2740
- hostPeersResolved: adapterState.upgraded
2167
+ hostPeersResolved: adapterState.kind === "pi-ai"
2741
2168
  })
2742
2169
  });
2743
2170
  const resolveAttachments = attachmentResolver(ctx);
2744
- const createSync = options.createSync ?? createGrokBuildAdapterSync;
2745
- try {
2746
- const created = createSync(session, { resolveAttachments });
2747
- if (created.note) ctx.logger?.debug?.(created.note);
2748
- adapterState.kind = created.kind;
2749
- ctx.llm.registerAdapter([PROVIDER_ID], created.adapter);
2750
- notifyCatalogChange();
2751
- } catch (error) {
2752
- ctx.logger?.warn?.(
2753
- "Grok subscription duck adapter failed to register: %s",
2754
- error instanceof Error ? error.message : "unknown"
2755
- );
2756
- }
2757
2171
  const defer = options.defer ?? scheduleDeferred2;
2758
2172
  defer(() => {
2759
2173
  void deferredBoot(ctx, session, notifyCatalogChange, options, adapterState);
@@ -2788,24 +2202,32 @@ async function deferredBoot(ctx, session, notifyCatalogChange, options = {}, ada
2788
2202
  );
2789
2203
  });
2790
2204
  }
2791
- if (options.skipUpgrade) return;
2792
- const createAsync = options.createAsync ?? createGrokBuildAdapter;
2205
+ if (options.skipAdapter) {
2206
+ adapterState.kind = "unavailable";
2207
+ return;
2208
+ }
2209
+ const buildAdapter = options.buildAdapter ?? createGrokBuildAdapter;
2793
2210
  try {
2794
- const created = await createAsync(session, { ...options.adapterOptions, resolveAttachments: attachmentResolver(ctx) });
2795
- if (created.kind === "pi-ai") {
2796
- if (created.note) ctx.logger?.warn?.(created.note);
2797
- ctx.llm.registerAdapter([PROVIDER_ID], created.adapter);
2798
- if (adapterState) {
2799
- adapterState.kind = created.kind;
2800
- adapterState.upgraded = true;
2801
- }
2802
- notifyCatalogChange?.();
2803
- } else if (created.note) {
2804
- ctx.logger?.debug?.(created.note);
2211
+ const created = await buildAdapter(session, {
2212
+ ...options.adapterOptions,
2213
+ resolveAttachments: attachmentResolver(ctx)
2214
+ });
2215
+ if (!created?.adapter) {
2216
+ adapterState.kind = "unavailable";
2217
+ ctx.logger?.warn?.(
2218
+ "Grok subscription adapter is unavailable: %s",
2219
+ created?.note ?? "unknown"
2220
+ );
2221
+ return;
2805
2222
  }
2223
+ if (created.note) ctx.logger?.warn?.(created.note);
2224
+ ctx.llm.registerAdapter([PROVIDER_ID], created.adapter);
2225
+ adapterState.kind = created.kind ?? "pi-ai";
2226
+ notifyCatalogChange?.();
2806
2227
  } catch (error) {
2228
+ adapterState.kind = "unavailable";
2807
2229
  ctx.logger?.warn?.(
2808
- "Grok subscription adapter upgrade failed: %s",
2230
+ "Grok subscription adapter registration failed: %s",
2809
2231
  error instanceof Error ? error.message : "unknown"
2810
2232
  );
2811
2233
  }