neoctl 0.2.54 → 0.2.56
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 +58 -58
- package/dist/agents/agent-activity.js +1 -1
- package/dist/agents/agent-activity.js.map +1 -1
- package/dist/context/compaction.js +2 -1
- package/dist/context/compaction.js.map +1 -1
- package/dist/context/context-manager.d.ts +7 -1
- package/dist/context/context-manager.js +0 -1
- package/dist/context/context-manager.js.map +1 -1
- package/dist/context/system.md +16 -16
- package/dist/core/context-metrics.js +2 -1
- package/dist/core/context-metrics.js.map +1 -1
- package/dist/core/execution-state.js +3 -3
- package/dist/core/execution-state.js.map +1 -1
- package/dist/core/message-pipeline.d.ts +3 -0
- package/dist/core/message-pipeline.js +31 -23
- package/dist/core/message-pipeline.js.map +1 -1
- package/dist/core/query-engine.d.ts +3 -0
- package/dist/core/query-engine.js +58 -26
- package/dist/core/query-engine.js.map +1 -1
- package/dist/core/query.d.ts +3 -1
- package/dist/core/query.js +34 -8
- package/dist/core/query.js.map +1 -1
- package/dist/core/run-agent.d.ts +1 -0
- package/dist/core/run-agent.js +2 -1
- package/dist/core/run-agent.js.map +1 -1
- package/dist/execution/filesystem.js +22 -22
- package/dist/execution/process.js +44 -44
- package/dist/model/agent-settings-boundary.js +7 -6
- package/dist/model/agent-settings-boundary.js.map +1 -1
- package/dist/model/anthropic-mapper.d.ts +4 -0
- package/dist/model/anthropic-mapper.js +114 -15
- package/dist/model/anthropic-mapper.js.map +1 -1
- package/dist/model/model-gateway.d.ts +5 -0
- package/dist/model/model-gateway.js +1 -0
- package/dist/model/model-gateway.js.map +1 -1
- package/dist/model/model-metadata.json +144 -143
- package/dist/model/openai-chat-mapper.js +45 -12
- package/dist/model/openai-chat-mapper.js.map +1 -1
- package/dist/model/openai-responses-mapper.js +70 -17
- package/dist/model/openai-responses-mapper.js.map +1 -1
- package/dist/model/settings-store.d.ts +2 -1
- package/dist/model/settings-store.js +49 -5
- package/dist/model/settings-store.js.map +1 -1
- package/dist/model/settings-sync.d.ts +10 -2
- package/dist/model/settings-sync.js +17 -4
- package/dist/model/settings-sync.js.map +1 -1
- package/dist/model/thinking-lifecycle.d.ts +5 -0
- package/dist/model/thinking-lifecycle.js +43 -0
- package/dist/model/thinking-lifecycle.js.map +1 -0
- package/dist/repl/index.js +11 -9
- package/dist/repl/index.js.map +1 -1
- package/dist/session/session-store.d.ts +9 -0
- package/dist/session/session-store.js +11 -0
- package/dist/session/session-store.js.map +1 -1
- package/dist/types/events.d.ts +3 -0
- package/dist/web/index.d.ts +2 -0
- package/dist/web/index.js +42 -14
- package/dist/web/index.js.map +1 -1
- package/dist/web/model-settings-api.js +20 -5
- package/dist/web/model-settings-api.js.map +1 -1
- package/docs/prompt-config.md +86 -86
- package/package.json +96 -96
- package/scripts/copy-prompt-resources.mjs +5 -5
|
@@ -1,143 +1,144 @@
|
|
|
1
|
-
{
|
|
2
|
-
"updatedAt": "2026-11-03",
|
|
3
|
-
"notes": [
|
|
4
|
-
"Bundled metadata for current mainstream Claude models and supported OpenAI models.",
|
|
5
|
-
"
|
|
6
|
-
"
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
"claude-
|
|
11
|
-
"
|
|
12
|
-
"openai-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
{"id": "claude-
|
|
17
|
-
{"id": "claude-
|
|
18
|
-
{"id": "claude-
|
|
19
|
-
{
|
|
20
|
-
|
|
21
|
-
"
|
|
22
|
-
"
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
"
|
|
27
|
-
"
|
|
28
|
-
"
|
|
29
|
-
"
|
|
30
|
-
"
|
|
31
|
-
"
|
|
32
|
-
|
|
33
|
-
"
|
|
34
|
-
"
|
|
35
|
-
"
|
|
36
|
-
"
|
|
37
|
-
"
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
"
|
|
43
|
-
"
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
"
|
|
48
|
-
"
|
|
49
|
-
"
|
|
50
|
-
"
|
|
51
|
-
"
|
|
52
|
-
"
|
|
53
|
-
|
|
54
|
-
"
|
|
55
|
-
"
|
|
56
|
-
"
|
|
57
|
-
"
|
|
58
|
-
"
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
"
|
|
64
|
-
"
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
"
|
|
69
|
-
"
|
|
70
|
-
"
|
|
71
|
-
"
|
|
72
|
-
"
|
|
73
|
-
"
|
|
74
|
-
|
|
75
|
-
"
|
|
76
|
-
"
|
|
77
|
-
"
|
|
78
|
-
"
|
|
79
|
-
"
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
"
|
|
85
|
-
"
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
"
|
|
90
|
-
"
|
|
91
|
-
"
|
|
92
|
-
"
|
|
93
|
-
"
|
|
94
|
-
|
|
95
|
-
"
|
|
96
|
-
"
|
|
97
|
-
"
|
|
98
|
-
"
|
|
99
|
-
"
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
"
|
|
105
|
-
"
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
"
|
|
110
|
-
"
|
|
111
|
-
"
|
|
112
|
-
"
|
|
113
|
-
"
|
|
114
|
-
|
|
115
|
-
"
|
|
116
|
-
"
|
|
117
|
-
"
|
|
118
|
-
"
|
|
119
|
-
"
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
"
|
|
125
|
-
"
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
"
|
|
130
|
-
"
|
|
131
|
-
"
|
|
132
|
-
"
|
|
133
|
-
"
|
|
134
|
-
|
|
135
|
-
"
|
|
136
|
-
"
|
|
137
|
-
"
|
|
138
|
-
"
|
|
139
|
-
"
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
1
|
+
{
|
|
2
|
+
"updatedAt": "2026-11-03",
|
|
3
|
+
"notes": [
|
|
4
|
+
"Bundled metadata for current mainstream Claude models and supported OpenAI models.",
|
|
5
|
+
"Claude contextWindowTokens is neo's configured 256000-token usage ceiling, not the upstream model maximum or a pricing guarantee.",
|
|
6
|
+
"MODEL_CONTEXT_WINDOW_TOKENS or OPENAI_CONTEXT_WINDOW_TOKENS overrides contextWindowTokens at runtime.",
|
|
7
|
+
"Model IDs and aliases are matched case-insensitively. Availability depends on the connected API and account."
|
|
8
|
+
],
|
|
9
|
+
"sources": {
|
|
10
|
+
"claude-models": "https://platform.claude.com/docs/en/models/overview",
|
|
11
|
+
"claude-effort": "https://platform.claude.com/docs/en/build-with-claude/effort",
|
|
12
|
+
"openai-models": "https://developers.openai.com/api/docs/models",
|
|
13
|
+
"openai-reasoning": "https://developers.openai.com/api/docs/guides/reasoning"
|
|
14
|
+
},
|
|
15
|
+
"models": [
|
|
16
|
+
{"id": "claude-fable-5-1", "provider": "anthropic", "protocols": ["anthropic"], "modelIds": ["claude-fable-5-1"], "contextWindowTokens": 256000, "maxOutputTokens": 128000, "knowledgeCutoff": "2026-06", "reasoning": true, "reasoningEfforts": ["low", "medium", "high", "xhigh", "max"], "imageInput": true, "source": "claude-models", "notes": "Adaptive thinking; thinking cannot be disabled."},
|
|
17
|
+
{"id": "claude-haiku-5-5", "provider": "anthropic", "protocols": ["anthropic"], "modelIds": ["claude-haiku-5-5"], "contextWindowTokens": 256000, "maxOutputTokens": 128000, "knowledgeCutoff": "2026-06", "reasoning": true, "reasoningEfforts": ["none", "low", "medium", "high", "xhigh", "max"], "imageInput": true, "source": "claude-models", "notes": "none disables thinking; other efforts use adaptive thinking."},
|
|
18
|
+
{"id": "claude-opus-5-5", "provider": "anthropic", "protocols": ["anthropic"], "modelIds": ["claude-opus-5-5"], "contextWindowTokens": 256000, "maxOutputTokens": 128000, "knowledgeCutoff": "2026-06", "reasoning": true, "reasoningEfforts": ["low", "medium", "high", "xhigh", "max"], "imageInput": true, "source": "claude-models", "notes": "Adaptive thinking; thinking cannot be disabled."},
|
|
19
|
+
{"id": "claude-sonnet-5-5", "provider": "anthropic", "protocols": ["anthropic"], "modelIds": ["claude-sonnet-5-5"], "contextWindowTokens": 256000, "maxOutputTokens": 128000, "knowledgeCutoff": "2026-06", "reasoning": true, "reasoningEfforts": ["low", "medium", "high", "xhigh", "max"], "imageInput": true, "source": "claude-models", "notes": "Adaptive thinking; thinking cannot be disabled."},
|
|
20
|
+
{
|
|
21
|
+
"id": "gpt-5.6-sol",
|
|
22
|
+
"provider": "openai",
|
|
23
|
+
"modelIds": [
|
|
24
|
+
"gpt-5.6-sol"
|
|
25
|
+
],
|
|
26
|
+
"contextWindowTokens": 256000,
|
|
27
|
+
"maxOutputTokens": 128000,
|
|
28
|
+
"knowledgeCutoff": "2026-02-16",
|
|
29
|
+
"reasoning": true,
|
|
30
|
+
"imageInput": true,
|
|
31
|
+
"source": "openai-models",
|
|
32
|
+
"reasoningEfforts": [
|
|
33
|
+
"none",
|
|
34
|
+
"low",
|
|
35
|
+
"medium",
|
|
36
|
+
"high",
|
|
37
|
+
"xhigh",
|
|
38
|
+
"max"
|
|
39
|
+
]
|
|
40
|
+
},
|
|
41
|
+
{
|
|
42
|
+
"id": "gpt-5.6-terra",
|
|
43
|
+
"provider": "openai",
|
|
44
|
+
"modelIds": [
|
|
45
|
+
"gpt-5.6-terra"
|
|
46
|
+
],
|
|
47
|
+
"contextWindowTokens": 256000,
|
|
48
|
+
"maxOutputTokens": 128000,
|
|
49
|
+
"knowledgeCutoff": "2026-02-16",
|
|
50
|
+
"reasoning": true,
|
|
51
|
+
"imageInput": true,
|
|
52
|
+
"source": "openai-models",
|
|
53
|
+
"reasoningEfforts": [
|
|
54
|
+
"none",
|
|
55
|
+
"low",
|
|
56
|
+
"medium",
|
|
57
|
+
"high",
|
|
58
|
+
"xhigh",
|
|
59
|
+
"max"
|
|
60
|
+
]
|
|
61
|
+
},
|
|
62
|
+
{
|
|
63
|
+
"id": "gpt-5.6-luna",
|
|
64
|
+
"provider": "openai",
|
|
65
|
+
"modelIds": [
|
|
66
|
+
"gpt-5.6-luna"
|
|
67
|
+
],
|
|
68
|
+
"contextWindowTokens": 256000,
|
|
69
|
+
"maxOutputTokens": 128000,
|
|
70
|
+
"knowledgeCutoff": "2026-02-16",
|
|
71
|
+
"reasoning": true,
|
|
72
|
+
"imageInput": true,
|
|
73
|
+
"source": "openai-models",
|
|
74
|
+
"reasoningEfforts": [
|
|
75
|
+
"none",
|
|
76
|
+
"low",
|
|
77
|
+
"medium",
|
|
78
|
+
"high",
|
|
79
|
+
"xhigh",
|
|
80
|
+
"max"
|
|
81
|
+
]
|
|
82
|
+
},
|
|
83
|
+
{
|
|
84
|
+
"id": "gpt-6-sol",
|
|
85
|
+
"provider": "openai",
|
|
86
|
+
"modelIds": [
|
|
87
|
+
"gpt-6-sol"
|
|
88
|
+
],
|
|
89
|
+
"contextWindowTokens": 256000,
|
|
90
|
+
"maxOutputTokens": 128000,
|
|
91
|
+
"reasoning": true,
|
|
92
|
+
"imageInput": true,
|
|
93
|
+
"source": "openai-models",
|
|
94
|
+
"reasoningEfforts": [
|
|
95
|
+
"none",
|
|
96
|
+
"low",
|
|
97
|
+
"medium",
|
|
98
|
+
"high",
|
|
99
|
+
"xhigh",
|
|
100
|
+
"max"
|
|
101
|
+
]
|
|
102
|
+
},
|
|
103
|
+
{
|
|
104
|
+
"id": "gpt-6.1-sol",
|
|
105
|
+
"provider": "openai",
|
|
106
|
+
"modelIds": [
|
|
107
|
+
"gpt-6.1-sol"
|
|
108
|
+
],
|
|
109
|
+
"contextWindowTokens": 256000,
|
|
110
|
+
"maxOutputTokens": 128000,
|
|
111
|
+
"reasoning": true,
|
|
112
|
+
"imageInput": true,
|
|
113
|
+
"source": "openai-models",
|
|
114
|
+
"reasoningEfforts": [
|
|
115
|
+
"none",
|
|
116
|
+
"low",
|
|
117
|
+
"medium",
|
|
118
|
+
"high",
|
|
119
|
+
"xhigh",
|
|
120
|
+
"max"
|
|
121
|
+
]
|
|
122
|
+
},
|
|
123
|
+
{
|
|
124
|
+
"id": "gpt-6-astra",
|
|
125
|
+
"provider": "openai",
|
|
126
|
+
"modelIds": [
|
|
127
|
+
"gpt-6-astra"
|
|
128
|
+
],
|
|
129
|
+
"contextWindowTokens": 256000,
|
|
130
|
+
"maxOutputTokens": 128000,
|
|
131
|
+
"reasoning": true,
|
|
132
|
+
"imageInput": true,
|
|
133
|
+
"source": "openai-models",
|
|
134
|
+
"reasoningEfforts": [
|
|
135
|
+
"none",
|
|
136
|
+
"low",
|
|
137
|
+
"medium",
|
|
138
|
+
"high",
|
|
139
|
+
"xhigh",
|
|
140
|
+
"max"
|
|
141
|
+
]
|
|
142
|
+
}
|
|
143
|
+
]
|
|
144
|
+
}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { createTextMessage, createThinkingMessage } from "../types/messages.js";
|
|
2
2
|
import { buildPromptCacheIdentity } from "../core/prompt-cache-key.js";
|
|
3
3
|
import { decodeSSE } from "./sse-decoder.js";
|
|
4
|
+
import { withThinkingLifecycle } from "./thinking-lifecycle.js";
|
|
4
5
|
import { asNumber, asString, buildChatMessages, buildChatTools, dropUndefined, normalizeOpenAIStreamError, normalizeUsage, toToolUse, } from "./openai-mappers.js";
|
|
5
6
|
export function buildChatRequest(request, options) {
|
|
6
7
|
const tools = buildChatTools(request.tools);
|
|
@@ -29,7 +30,11 @@ function chatThinkingOption(_model, _reasoning, _reasoningDisabled) {
|
|
|
29
30
|
return undefined;
|
|
30
31
|
}
|
|
31
32
|
export async function* normalizeChatStream(stream, options) {
|
|
32
|
-
|
|
33
|
+
yield* withThinkingLifecycle(normalizeChatStreamEvents(stream, options));
|
|
34
|
+
}
|
|
35
|
+
async function* normalizeChatStreamEvents(stream, options) {
|
|
36
|
+
const textBlocks = [];
|
|
37
|
+
const choiceScopes = new Map();
|
|
33
38
|
const thinkingParts = [];
|
|
34
39
|
const toolBuffers = new Map();
|
|
35
40
|
const announcedToolCalls = new Set();
|
|
@@ -50,16 +55,27 @@ export async function* normalizeChatStream(stream, options) {
|
|
|
50
55
|
const choices = Array.isArray(event.choices) ? event.choices : [];
|
|
51
56
|
for (const choice of choices) {
|
|
52
57
|
const delta = choice.delta;
|
|
53
|
-
const
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
58
|
+
const choiceIndex = asNumber(choice.index) ?? 0;
|
|
59
|
+
const scope = { ...choiceScopes.get(choiceIndex) };
|
|
60
|
+
for (const key of ["role", "channel", "phase"]) {
|
|
61
|
+
const value = delta?.[key] ?? choice[key] ?? event[key];
|
|
62
|
+
if (value !== undefined)
|
|
63
|
+
scope[key] = value;
|
|
57
64
|
}
|
|
58
|
-
|
|
65
|
+
choiceScopes.set(choiceIndex, scope);
|
|
66
|
+
// Some compatible chunks include the last reasoning text and first answer
|
|
67
|
+
// together. Publish thinking first so the answer boundary really ends it.
|
|
68
|
+
const reasoningContent = asString(delta?.reasoning_content) ?? asString(delta?.reasoning);
|
|
59
69
|
if (reasoningContent) {
|
|
60
70
|
thinkingParts.push(reasoningContent);
|
|
61
71
|
yield { type: "thinking_delta", text: reasoningContent };
|
|
62
72
|
}
|
|
73
|
+
const content = asString(delta?.content);
|
|
74
|
+
if (content) {
|
|
75
|
+
const visible = allowsVisibleChatContent(event, choice, scope);
|
|
76
|
+
appendChatText(textBlocks, content, visible);
|
|
77
|
+
yield { type: "assistant_delta", text: content, ...(visible ? { displayChannel: "visible" } : {}) };
|
|
78
|
+
}
|
|
63
79
|
const toolCalls = Array.isArray(delta?.tool_calls) ? delta?.tool_calls : [];
|
|
64
80
|
for (const toolCall of toolCalls) {
|
|
65
81
|
const index = asNumber(toolCall.index) ?? toolBuffers.size;
|
|
@@ -94,9 +110,8 @@ export async function* normalizeChatStream(stream, options) {
|
|
|
94
110
|
const thinking = thinkingParts.join("").trim();
|
|
95
111
|
if (thinking)
|
|
96
112
|
yield { type: "assistant_message", message: createThinkingMessage(thinking) };
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
yield { type: "assistant_message", message: createTextMessage("assistant", text) };
|
|
113
|
+
if (textBlocks.length)
|
|
114
|
+
yield { type: "assistant_message", message: { ...createTextMessage("assistant", ""), blocks: textBlocks } };
|
|
100
115
|
yield { type: "response_completed", responseId, stopReason: "completed", usage };
|
|
101
116
|
}
|
|
102
117
|
export function* normalizeChatObject(response) {
|
|
@@ -107,12 +122,15 @@ export function* normalizeChatObject(response) {
|
|
|
107
122
|
const choices = Array.isArray(body.choices) ? body.choices : [];
|
|
108
123
|
for (const choice of choices) {
|
|
109
124
|
const message = choice.message;
|
|
110
|
-
const reasoningContent = asString(message?.reasoning_content);
|
|
125
|
+
const reasoningContent = asString(message?.reasoning_content) ?? asString(message?.reasoning);
|
|
111
126
|
if (reasoningContent)
|
|
112
127
|
yield { type: "assistant_message", message: createThinkingMessage(reasoningContent) };
|
|
113
128
|
const content = asString(message?.content);
|
|
114
|
-
if (content)
|
|
115
|
-
|
|
129
|
+
if (content) {
|
|
130
|
+
const blocks = [];
|
|
131
|
+
appendChatText(blocks, content, allowsVisibleChatContent(body, choice, message));
|
|
132
|
+
yield { type: "assistant_message", message: { ...createTextMessage("assistant", ""), blocks } };
|
|
133
|
+
}
|
|
116
134
|
const toolCalls = Array.isArray(message?.tool_calls) ? message?.tool_calls : [];
|
|
117
135
|
for (const toolCall of toolCalls) {
|
|
118
136
|
const fn = toolCall.function;
|
|
@@ -131,4 +149,19 @@ export function* normalizeChatObject(response) {
|
|
|
131
149
|
yield { type: "usage", usage };
|
|
132
150
|
yield { type: "response_completed", responseId, stopReason: "completed", usage };
|
|
133
151
|
}
|
|
152
|
+
// Chat content is public by contract, but compatible servers may explicitly
|
|
153
|
+
// label private channels. Never authorize reasoning fields or an analysis channel.
|
|
154
|
+
function allowsVisibleChatContent(...scopes) {
|
|
155
|
+
return scopes.every(scope => !scope || ((scope.role === undefined || scope.role === "assistant") &&
|
|
156
|
+
(scope.channel === undefined || ["commentary", "answer", "final"].includes(String(scope.channel))) &&
|
|
157
|
+
(scope.phase === undefined || ["commentary", "answer", "final", "final_answer"].includes(String(scope.phase)))));
|
|
158
|
+
}
|
|
159
|
+
function appendChatText(blocks, text, visible) {
|
|
160
|
+
const displayChannel = visible ? "visible" : undefined;
|
|
161
|
+
const last = blocks.at(-1);
|
|
162
|
+
if (last && last.displayChannel === displayChannel)
|
|
163
|
+
last.text += text;
|
|
164
|
+
else
|
|
165
|
+
blocks.push({ type: "text", text, ...(visible ? { displayChannel: "visible" } : {}) });
|
|
166
|
+
}
|
|
134
167
|
//# sourceMappingURL=openai-chat-mapper.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"openai-chat-mapper.js","sourceRoot":"","sources":["../../src/model/openai-chat-mapper.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,qBAAqB,
|
|
1
|
+
{"version":3,"file":"openai-chat-mapper.js","sourceRoot":"","sources":["../../src/model/openai-chat-mapper.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import { createTextMessage, createThinkingMessage } from "../types/messages.js";
|
|
2
2
|
import { buildPromptCacheIdentity } from "../core/prompt-cache-key.js";
|
|
3
3
|
import { decodeSSE } from "./sse-decoder.js";
|
|
4
|
+
import { withThinkingLifecycle } from "./thinking-lifecycle.js";
|
|
5
|
+
import { findModelMetadata } from "./context-window.js";
|
|
4
6
|
import { ModelAPIError } from "./errors.js";
|
|
5
7
|
import { asNumber, asString, buildResponsesInput, buildResponsesTools, dropUndefined, ensureToolBuffer, normalizeOpenAIStreamError, normalizeUsage, toToolUse, } from "./openai-mappers.js";
|
|
6
8
|
export function buildResponsesRequest(request, options) {
|
|
@@ -18,6 +20,10 @@ export function buildResponsesRequest(request, options) {
|
|
|
18
20
|
const instructions = [promptCache.stableSystemPrompt, promptCache.dynamicSystemPrompt].filter(Boolean).join("\n\n") || undefined;
|
|
19
21
|
const input = [...stableRuntimeInput, ...conversationInput];
|
|
20
22
|
const reasoningDisabled = request.reasoning === null || (request.reasoning === undefined && options.defaultReasoning === null);
|
|
23
|
+
const reasoning = request.reasoning ?? options.defaultReasoning ?? undefined;
|
|
24
|
+
const supportsReasoning = findModelMetadata(model)?.reasoning ?? (!!reasoning || /^(?:o[134](?:-|$)|gpt-[5-9](?:[.-]|$))/i.test(model));
|
|
25
|
+
const visibleReasoning = !reasoningDisabled && reasoning?.effort !== "none" && supportsReasoning
|
|
26
|
+
? { ...reasoning, summary: reasoning?.summary ?? "auto" } : reasoning;
|
|
21
27
|
const toolChoice = constrainedResponsesToolChoice(request.toolChoice, tools);
|
|
22
28
|
const body = dropUndefined({
|
|
23
29
|
model,
|
|
@@ -25,7 +31,7 @@ export function buildResponsesRequest(request, options) {
|
|
|
25
31
|
input,
|
|
26
32
|
previous_response_id: request.previousResponseId,
|
|
27
33
|
max_output_tokens: request.maxOutputTokens ?? options.defaultMaxOutputTokens,
|
|
28
|
-
reasoning: reasoningDisabled ? undefined :
|
|
34
|
+
reasoning: reasoningDisabled ? undefined : visibleReasoning,
|
|
29
35
|
text: request.textFormat ? { format: request.textFormat } : undefined,
|
|
30
36
|
metadata: request.metadata,
|
|
31
37
|
service_tier: request.serviceTier,
|
|
@@ -49,6 +55,9 @@ function supportsExplicitPromptCaching(model) {
|
|
|
49
55
|
return major > 5 || (major === 5 && minor >= 6);
|
|
50
56
|
}
|
|
51
57
|
export async function* normalizeResponsesStream(stream, options) {
|
|
58
|
+
yield* withThinkingLifecycle(normalizeResponsesStreamEvents(stream, options));
|
|
59
|
+
}
|
|
60
|
+
async function* normalizeResponsesStreamEvents(stream, options) {
|
|
52
61
|
const textBlocks = [];
|
|
53
62
|
const thinkingParts = [];
|
|
54
63
|
const toolBuffers = new Map();
|
|
@@ -57,6 +66,38 @@ export async function* normalizeResponsesStream(stream, options) {
|
|
|
57
66
|
let reasoningPartKey;
|
|
58
67
|
const outputItems = new Map();
|
|
59
68
|
const contentParts = new Map();
|
|
69
|
+
const reasoningTextByPart = new Map();
|
|
70
|
+
const completedReasoning = new Map();
|
|
71
|
+
function* publishReasoning(text, key, snapshot = false) {
|
|
72
|
+
if (!text)
|
|
73
|
+
return;
|
|
74
|
+
const previous = reasoningTextByPart.get(key) ?? "";
|
|
75
|
+
const delta = snapshot ? (text.startsWith(previous) ? text.slice(previous.length) : previous ? "" : text) : text;
|
|
76
|
+
reasoningTextByPart.set(key, snapshot ? text : previous + text);
|
|
77
|
+
if (!delta)
|
|
78
|
+
return;
|
|
79
|
+
const separated = reasoningPartKey !== undefined && reasoningPartKey !== key ? `\n\n${delta}` : delta;
|
|
80
|
+
reasoningPartKey = key;
|
|
81
|
+
thinkingParts.push(separated);
|
|
82
|
+
yield { type: "thinking_delta", text: separated };
|
|
83
|
+
}
|
|
84
|
+
function* publishReasoningItem(item, fallback) {
|
|
85
|
+
const id = asString(item.id) ?? String(fallback);
|
|
86
|
+
completedReasoning.set(id, item);
|
|
87
|
+
let structured = false;
|
|
88
|
+
for (const field of ["summary", "content"]) {
|
|
89
|
+
const parts = Array.isArray(item[field]) ? item[field] : [];
|
|
90
|
+
for (const [index, part] of parts.entries()) {
|
|
91
|
+
const text = typeof part === "string" ? part : part && typeof part === "object" ? extractReasoningText(part) : "";
|
|
92
|
+
if (text) {
|
|
93
|
+
structured = true;
|
|
94
|
+
yield* publishReasoning(text, `${id}:${field}:${index}`, true);
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
if (!structured)
|
|
99
|
+
yield* publishReasoning(extractReasoningText(item), `${id}:content:0`, true);
|
|
100
|
+
}
|
|
60
101
|
for await (const sse of decodeSSE(stream, options.streamIdleTimeoutMs ?? 120000)) {
|
|
61
102
|
const event = sse.data;
|
|
62
103
|
const type = asString(event.type ?? sse.event);
|
|
@@ -69,7 +110,7 @@ export async function* normalizeResponsesStream(stream, options) {
|
|
|
69
110
|
yield { type: "response_started", responseId };
|
|
70
111
|
}
|
|
71
112
|
const itemKey = asString(event.item_id) ?? asNumber(event.output_index) ?? 0;
|
|
72
|
-
if (type === "response.output_item.added") {
|
|
113
|
+
if (type === "response.output_item.added" || type === "response.output_item.done") {
|
|
73
114
|
const item = event.item;
|
|
74
115
|
if (item) {
|
|
75
116
|
outputItems.set(asNumber(event.output_index) ?? 0, item);
|
|
@@ -94,17 +135,19 @@ export async function* normalizeResponsesStream(stream, options) {
|
|
|
94
135
|
if (type === "response.output_text.done" || (type === "response.output_item.done" && event.item?.type === "message")) {
|
|
95
136
|
yield { type: "assistant_text_done" };
|
|
96
137
|
}
|
|
138
|
+
const reasoningEvent = { ...event, item_id: event.item_id ?? outputItems.get(asNumber(event.output_index) ?? 0)?.id };
|
|
97
139
|
if (isReasoningDeltaEvent(type)) {
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
140
|
+
yield* publishReasoning(extractThinkingDelta(event), reasoningPartKeyForEvent(type, reasoningEvent));
|
|
141
|
+
}
|
|
142
|
+
if (type?.startsWith("response.reasoning") && (type.endsWith(".done") || type.endsWith(".added"))) {
|
|
143
|
+
const part = event.part && typeof event.part === "object" ? event.part : event;
|
|
144
|
+
yield* publishReasoning(extractReasoningText(part), reasoningPartKeyForEvent(type, reasoningEvent), true);
|
|
145
|
+
if (type.endsWith(".done"))
|
|
146
|
+
yield { type: "thinking_done" };
|
|
147
|
+
}
|
|
148
|
+
if (type === "response.output_item.done" && event.item?.type === "reasoning") {
|
|
149
|
+
yield* publishReasoningItem(event.item, itemKey);
|
|
150
|
+
yield { type: "thinking_done" };
|
|
108
151
|
}
|
|
109
152
|
if (type === "response.output_item.added") {
|
|
110
153
|
const item = event.item;
|
|
@@ -149,7 +192,12 @@ export async function* normalizeResponsesStream(stream, options) {
|
|
|
149
192
|
if (type === "response.completed") {
|
|
150
193
|
const response = event.response;
|
|
151
194
|
responseId = asString(response?.id) ?? responseId;
|
|
152
|
-
const
|
|
195
|
+
for (const [index, item] of (Array.isArray(response?.output) ? response.output : []).entries()) {
|
|
196
|
+
if (item.type === "reasoning")
|
|
197
|
+
yield* publishReasoningItem(item, index);
|
|
198
|
+
}
|
|
199
|
+
yield { type: "thinking_done" };
|
|
200
|
+
const thinking = collectThinkingFromResponse({ output: [...completedReasoning.values()] }, thinkingParts);
|
|
153
201
|
if (thinking)
|
|
154
202
|
yield { type: "assistant_message", message: createThinkingMessage(thinking) };
|
|
155
203
|
if (textBlocks.length)
|
|
@@ -161,7 +209,12 @@ export async function* normalizeResponsesStream(stream, options) {
|
|
|
161
209
|
}
|
|
162
210
|
if (type === "response.incomplete") {
|
|
163
211
|
const response = event.response;
|
|
164
|
-
const
|
|
212
|
+
for (const [index, item] of (Array.isArray(response?.output) ? response.output : []).entries()) {
|
|
213
|
+
if (item.type === "reasoning")
|
|
214
|
+
yield* publishReasoningItem(item, index);
|
|
215
|
+
}
|
|
216
|
+
yield { type: "thinking_done" };
|
|
217
|
+
const thinking = collectThinkingFromResponse({ output: [...completedReasoning.values()] }, thinkingParts);
|
|
165
218
|
if (thinking)
|
|
166
219
|
yield { type: "assistant_message", message: createThinkingMessage(thinking) };
|
|
167
220
|
const usage = normalizeUsage(response?.usage);
|
|
@@ -282,11 +335,11 @@ function collectThinkingFromResponse(response, streamedParts) {
|
|
|
282
335
|
return (fromOutput || streamed).trim();
|
|
283
336
|
}
|
|
284
337
|
function reasoningPartKeyForEvent(type, event) {
|
|
285
|
-
const itemId = asString(event.item_id) ??
|
|
286
|
-
if (type
|
|
338
|
+
const itemId = asString(event.item_id) ?? String(asNumber(event.output_index) ?? 0);
|
|
339
|
+
if (type?.startsWith("response.reasoning_summary")) {
|
|
287
340
|
return `${itemId}:summary:${asNumber(event.summary_index) ?? 0}`;
|
|
288
341
|
}
|
|
289
|
-
if (type
|
|
342
|
+
if (type?.startsWith("response.reasoning")) {
|
|
290
343
|
return `${itemId}:content:${asNumber(event.content_index) ?? 0}`;
|
|
291
344
|
}
|
|
292
345
|
return undefined;
|