@ljoukov/llm 7.0.11 → 7.0.12
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +6 -4
- package/dist/index.cjs +59 -13
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +28 -1
- package/dist/index.d.ts +28 -1
- package/dist/index.js +59 -13
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -628,20 +628,22 @@ Architecture note:
|
|
|
628
628
|
|
|
629
629
|
### Provider-Native Tools (`generateText()`)
|
|
630
630
|
|
|
631
|
-
Use this when the model provider executes the tool remotely (for example search/code-exec style tools).
|
|
631
|
+
Use this when the model provider executes the tool remotely (for example search/code-exec/shell style tools).
|
|
632
632
|
|
|
633
633
|
```ts
|
|
634
634
|
import { generateText } from "@ljoukov/llm";
|
|
635
635
|
|
|
636
636
|
const result = await generateText({
|
|
637
|
-
model: "gpt-5.
|
|
638
|
-
input: "
|
|
639
|
-
tools: [{ type: "
|
|
637
|
+
model: "gpt-5.5",
|
|
638
|
+
input: "Run python --version in a hosted shell and summarize the result.",
|
|
639
|
+
tools: [{ type: "shell" }],
|
|
640
640
|
});
|
|
641
641
|
|
|
642
642
|
console.log(result.text);
|
|
643
643
|
```
|
|
644
644
|
|
|
645
|
+
`{ type: "shell" }` uses OpenAI hosted shell containers by default. It is only supported for OpenAI API models; ChatGPT-authenticated, Gemini, and Fireworks providers reject it.
|
|
646
|
+
|
|
645
647
|
### Runtime Tools (`runToolLoop()`)
|
|
646
648
|
|
|
647
649
|
Use this when the model should call your local runtime functions.
|
package/dist/index.cjs
CHANGED
|
@@ -6197,12 +6197,40 @@ function toGeminiTools(tools) {
|
|
|
6197
6197
|
return { googleSearch: {} };
|
|
6198
6198
|
case "code-execution":
|
|
6199
6199
|
return { codeExecution: {} };
|
|
6200
|
+
case "shell":
|
|
6201
|
+
throw new Error("Gemini provider does not support the OpenAI shell tool.");
|
|
6200
6202
|
default:
|
|
6201
6203
|
throw new Error("Unsupported tool configuration");
|
|
6202
6204
|
}
|
|
6203
6205
|
});
|
|
6204
6206
|
}
|
|
6205
|
-
function
|
|
6207
|
+
function toOpenAiShellEnvironment(environment) {
|
|
6208
|
+
if (environment?.type === "container-reference") {
|
|
6209
|
+
return {
|
|
6210
|
+
type: "container_reference",
|
|
6211
|
+
container_id: environment.containerId
|
|
6212
|
+
};
|
|
6213
|
+
}
|
|
6214
|
+
return {
|
|
6215
|
+
type: "container_auto",
|
|
6216
|
+
...environment?.fileIds ? { file_ids: Array.from(environment.fileIds) } : {},
|
|
6217
|
+
...environment?.memoryLimit !== void 0 ? { memory_limit: environment.memoryLimit } : {},
|
|
6218
|
+
...environment?.networkPolicy ? {
|
|
6219
|
+
network_policy: environment.networkPolicy.type === "allowlist" ? {
|
|
6220
|
+
type: "allowlist",
|
|
6221
|
+
allowed_domains: Array.from(environment.networkPolicy.allowedDomains),
|
|
6222
|
+
...environment.networkPolicy.domainSecrets ? {
|
|
6223
|
+
domain_secrets: environment.networkPolicy.domainSecrets.map((secret) => ({
|
|
6224
|
+
domain: secret.domain,
|
|
6225
|
+
name: secret.name,
|
|
6226
|
+
value: secret.value
|
|
6227
|
+
}))
|
|
6228
|
+
} : {}
|
|
6229
|
+
} : { type: "disabled" }
|
|
6230
|
+
} : {}
|
|
6231
|
+
};
|
|
6232
|
+
}
|
|
6233
|
+
function toOpenAiTools(tools, options) {
|
|
6206
6234
|
if (!tools || tools.length === 0) {
|
|
6207
6235
|
return void 0;
|
|
6208
6236
|
}
|
|
@@ -6215,6 +6243,15 @@ function toOpenAiTools(tools) {
|
|
|
6215
6243
|
case "code-execution": {
|
|
6216
6244
|
return { type: "code_interpreter", container: { type: "auto" } };
|
|
6217
6245
|
}
|
|
6246
|
+
case "shell": {
|
|
6247
|
+
if (options.provider !== "openai") {
|
|
6248
|
+
throw new Error("OpenAI shell tool is only supported for OpenAI API models.");
|
|
6249
|
+
}
|
|
6250
|
+
return {
|
|
6251
|
+
type: "shell",
|
|
6252
|
+
environment: toOpenAiShellEnvironment(tool2.environment)
|
|
6253
|
+
};
|
|
6254
|
+
}
|
|
6218
6255
|
default:
|
|
6219
6256
|
throw new Error("Unsupported tool configuration");
|
|
6220
6257
|
}
|
|
@@ -7813,6 +7850,8 @@ async function runTextCall(params) {
|
|
|
7813
7850
|
let responseRole;
|
|
7814
7851
|
let latestUsage;
|
|
7815
7852
|
let responseImages = 0;
|
|
7853
|
+
let sawResponseDelta = false;
|
|
7854
|
+
let sawThoughtDelta = false;
|
|
7816
7855
|
const pushEvent = (event) => {
|
|
7817
7856
|
queue.push(event);
|
|
7818
7857
|
params.onEvent?.(event);
|
|
@@ -7823,8 +7862,10 @@ async function runTextCall(params) {
|
|
|
7823
7862
|
}
|
|
7824
7863
|
responseParts.push({ type: "text", text, ...channel === "thought" ? { thought: true } : {} });
|
|
7825
7864
|
if (channel === "thought") {
|
|
7865
|
+
sawThoughtDelta = true;
|
|
7826
7866
|
callLogger?.appendThoughtDelta(text);
|
|
7827
7867
|
} else {
|
|
7868
|
+
sawResponseDelta = true;
|
|
7828
7869
|
callLogger?.appendResponseDelta(text);
|
|
7829
7870
|
}
|
|
7830
7871
|
pushEvent({ type: "delta", channel, text });
|
|
@@ -7864,7 +7905,7 @@ async function runTextCall(params) {
|
|
|
7864
7905
|
}),
|
|
7865
7906
|
{ model: request.model, provider: "openai" }
|
|
7866
7907
|
);
|
|
7867
|
-
const openAiTools = toOpenAiTools(request.tools);
|
|
7908
|
+
const openAiTools = toOpenAiTools(request.tools, { provider: "openai" });
|
|
7868
7909
|
const reasoningEffort = resolveOpenAiReasoningEffort(
|
|
7869
7910
|
modelForProvider,
|
|
7870
7911
|
request.thinkingLevel
|
|
@@ -7925,12 +7966,17 @@ async function runTextCall(params) {
|
|
|
7925
7966
|
);
|
|
7926
7967
|
}
|
|
7927
7968
|
latestUsage = extractOpenAiUsageTokens(finalResponse.usage);
|
|
7928
|
-
if (
|
|
7969
|
+
if (!sawResponseDelta || !sawThoughtDelta) {
|
|
7970
|
+
const needsResponseFallback = !sawResponseDelta;
|
|
7971
|
+
const needsThoughtFallback = !sawThoughtDelta;
|
|
7929
7972
|
const fallback = extractOpenAiResponseParts(finalResponse);
|
|
7930
7973
|
blocked = blocked || fallback.blocked;
|
|
7931
7974
|
for (const part of fallback.parts) {
|
|
7932
7975
|
if (part.type === "text") {
|
|
7933
|
-
|
|
7976
|
+
const channel = part.thought === true ? "thought" : "response";
|
|
7977
|
+
if (channel === "response" && needsResponseFallback || channel === "thought" && needsThoughtFallback) {
|
|
7978
|
+
pushDelta(channel, part.text);
|
|
7979
|
+
}
|
|
7934
7980
|
} else if (part.type === "inlineData") {
|
|
7935
7981
|
pushInline(part.data, part.mimeType);
|
|
7936
7982
|
}
|
|
@@ -7947,7 +7993,7 @@ async function runTextCall(params) {
|
|
|
7947
7993
|
provider: "chatgpt"
|
|
7948
7994
|
});
|
|
7949
7995
|
const reasoningEffort = resolveOpenAiReasoningEffort(request.model, request.thinkingLevel);
|
|
7950
|
-
const openAiTools = toOpenAiTools(request.tools);
|
|
7996
|
+
const openAiTools = toOpenAiTools(request.tools, { provider: "chatgpt" });
|
|
7951
7997
|
const requestPayload = {
|
|
7952
7998
|
model: modelForProvider,
|
|
7953
7999
|
store: false,
|
|
@@ -7966,18 +8012,18 @@ async function runTextCall(params) {
|
|
|
7966
8012
|
},
|
|
7967
8013
|
...openAiTools ? { tools: openAiTools } : {}
|
|
7968
8014
|
};
|
|
7969
|
-
let
|
|
7970
|
-
let
|
|
8015
|
+
let sawResponseDelta2 = false;
|
|
8016
|
+
let sawThoughtDelta2 = false;
|
|
7971
8017
|
const result2 = await collectChatGptCodexResponseWithRetry({
|
|
7972
8018
|
request: requestPayload,
|
|
7973
8019
|
signal,
|
|
7974
8020
|
onDelta: (delta) => {
|
|
7975
8021
|
if (delta.thoughtDelta) {
|
|
7976
|
-
|
|
8022
|
+
sawThoughtDelta2 = true;
|
|
7977
8023
|
pushDelta("thought", delta.thoughtDelta);
|
|
7978
8024
|
}
|
|
7979
8025
|
if (delta.textDelta) {
|
|
7980
|
-
|
|
8026
|
+
sawResponseDelta2 = true;
|
|
7981
8027
|
pushDelta("response", delta.textDelta);
|
|
7982
8028
|
}
|
|
7983
8029
|
}
|
|
@@ -7993,10 +8039,10 @@ async function runTextCall(params) {
|
|
|
7993
8039
|
latestUsage = extractChatGptUsageTokens(result2.usage);
|
|
7994
8040
|
const fallbackText = typeof result2.text === "string" ? result2.text : "";
|
|
7995
8041
|
const fallbackThoughts = typeof result2.reasoningSummaryText === "string" && result2.reasoningSummaryText.length > 0 ? result2.reasoningSummaryText : typeof result2.reasoningText === "string" ? result2.reasoningText : "";
|
|
7996
|
-
if (!
|
|
8042
|
+
if (!sawThoughtDelta2 && fallbackThoughts.length > 0) {
|
|
7997
8043
|
pushDelta("thought", fallbackThoughts);
|
|
7998
8044
|
}
|
|
7999
|
-
if (!
|
|
8045
|
+
if (!sawResponseDelta2 && fallbackText.length > 0) {
|
|
8000
8046
|
pushDelta("response", fallbackText);
|
|
8001
8047
|
}
|
|
8002
8048
|
} else if (provider === "fireworks") {
|
|
@@ -8716,7 +8762,7 @@ async function runToolLoop(request) {
|
|
|
8716
8762
|
try {
|
|
8717
8763
|
if (providerInfo.provider === "openai") {
|
|
8718
8764
|
const openAiAgentTools = buildOpenAiToolsFromToolSet(request.tools);
|
|
8719
|
-
const openAiNativeTools = toOpenAiTools(request.modelTools);
|
|
8765
|
+
const openAiNativeTools = toOpenAiTools(request.modelTools, { provider: "openai" });
|
|
8720
8766
|
const openAiTools = openAiNativeTools ? [...openAiNativeTools, ...openAiAgentTools] : [...openAiAgentTools];
|
|
8721
8767
|
const reasoningEffort = resolveOpenAiReasoningEffort(
|
|
8722
8768
|
providerInfo.model,
|
|
@@ -9119,7 +9165,7 @@ async function runToolLoop(request) {
|
|
|
9119
9165
|
}
|
|
9120
9166
|
if (providerInfo.provider === "chatgpt") {
|
|
9121
9167
|
const openAiAgentTools = buildOpenAiToolsFromToolSet(request.tools);
|
|
9122
|
-
const openAiNativeTools = toOpenAiTools(request.modelTools);
|
|
9168
|
+
const openAiNativeTools = toOpenAiTools(request.modelTools, { provider: "chatgpt" });
|
|
9123
9169
|
const openAiTools = openAiNativeTools ? [...openAiNativeTools, ...openAiAgentTools] : [...openAiAgentTools];
|
|
9124
9170
|
const reasoningEffort = resolveOpenAiReasoningEffort(request.model, request.thinkingLevel);
|
|
9125
9171
|
const toolLoopInput = toChatGptInput(contents, {
|