@gajae-code/ai 0.7.4 → 0.7.5
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/CHANGELOG.md +7 -0
- package/package.json +2 -2
- package/src/providers/openai-codex-responses.ts +10 -9
- package/src/utils.ts +52 -0
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,13 @@
|
|
|
2
2
|
|
|
3
3
|
## [Unreleased]
|
|
4
4
|
|
|
5
|
+
## [0.7.5] - 2026-06-27
|
|
6
|
+
|
|
7
|
+
### Fixed
|
|
8
|
+
|
|
9
|
+
- Sanitized Codex history replay text fields so malformed/non-string replay text no longer corrupts the rebuilt request payload (#1199).
|
|
10
|
+
- Preserved object-valued tool replay fields when rebuilding Codex history payloads instead of coercing them to strings (#1200).
|
|
11
|
+
|
|
5
12
|
## [0.7.4] - 2026-06-27
|
|
6
13
|
|
|
7
14
|
### Fixed
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"type": "module",
|
|
3
3
|
"name": "@gajae-code/ai",
|
|
4
|
-
"version": "0.7.
|
|
4
|
+
"version": "0.7.5",
|
|
5
5
|
"description": "Unified LLM API with automatic model discovery and provider configuration",
|
|
6
6
|
"homepage": "https://gaebal-gajae.dev",
|
|
7
7
|
"author": "Yeachan-Heo",
|
|
@@ -43,7 +43,7 @@
|
|
|
43
43
|
"dependencies": {
|
|
44
44
|
"@anthropic-ai/sdk": "^0.94.0",
|
|
45
45
|
"@bufbuild/protobuf": "^2.12.0",
|
|
46
|
-
"@gajae-code/utils": "0.7.
|
|
46
|
+
"@gajae-code/utils": "0.7.5",
|
|
47
47
|
"openai": "^6.36.0",
|
|
48
48
|
"partial-json": "^0.1.7",
|
|
49
49
|
"zod": "4.4.3"
|
|
@@ -44,6 +44,7 @@ import {
|
|
|
44
44
|
getOpenAIResponsesHistoryItems,
|
|
45
45
|
getOpenAIResponsesHistoryPayload,
|
|
46
46
|
normalizeSystemPrompts,
|
|
47
|
+
sanitizeOpenAIResponsesHistoryItemsForReplay,
|
|
47
48
|
} from "../utils";
|
|
48
49
|
import { AssistantMessageEventStream } from "../utils/event-stream";
|
|
49
50
|
import { finalizeErrorMessage, type RawHttpRequestDump } from "../utils/http-inspector";
|
|
@@ -2550,17 +2551,16 @@ function convertMessages(model: Model<"openai-codex-responses">, context: Contex
|
|
|
2550
2551
|
for (const msg of transformedMessages) {
|
|
2551
2552
|
if (msg.role === "user" || msg.role === "developer") {
|
|
2552
2553
|
const providerPayload = (msg as { providerPayload?: AssistantMessage["providerPayload"] }).providerPayload;
|
|
2553
|
-
const historyItems = getOpenAIResponsesHistoryItems(providerPayload, model.provider)
|
|
2554
|
-
| Array<ResponseInput[number]>
|
|
2555
|
-
| undefined;
|
|
2554
|
+
const historyItems = getOpenAIResponsesHistoryItems(providerPayload, model.provider);
|
|
2556
2555
|
if (historyItems) {
|
|
2557
|
-
|
|
2556
|
+
const sanitizedHistoryItems = sanitizeOpenAIResponsesHistoryItemsForReplay(historyItems);
|
|
2557
|
+
for (const item of sanitizedHistoryItems) {
|
|
2558
2558
|
const maybe = item as { type?: string; call_id?: string };
|
|
2559
2559
|
if (maybe.type === "custom_tool_call" && typeof maybe.call_id === "string") {
|
|
2560
2560
|
customCallIds.add(maybe.call_id);
|
|
2561
2561
|
}
|
|
2562
2562
|
}
|
|
2563
|
-
messages.push(...
|
|
2563
|
+
messages.push(...sanitizedHistoryItems);
|
|
2564
2564
|
msgIndex += 1;
|
|
2565
2565
|
continue;
|
|
2566
2566
|
}
|
|
@@ -2579,18 +2579,19 @@ function convertMessages(model: Model<"openai-codex-responses">, context: Contex
|
|
|
2579
2579
|
model.provider,
|
|
2580
2580
|
assistantMsg.provider,
|
|
2581
2581
|
);
|
|
2582
|
-
const historyItems = providerPayload?.items
|
|
2582
|
+
const historyItems = providerPayload?.items;
|
|
2583
2583
|
if (historyItems) {
|
|
2584
|
-
|
|
2584
|
+
const sanitizedHistoryItems = sanitizeOpenAIResponsesHistoryItemsForReplay(historyItems);
|
|
2585
|
+
for (const item of sanitizedHistoryItems) {
|
|
2585
2586
|
const maybe = item as { type?: string; call_id?: string };
|
|
2586
2587
|
if (maybe.type === "custom_tool_call" && typeof maybe.call_id === "string") {
|
|
2587
2588
|
customCallIds.add(maybe.call_id);
|
|
2588
2589
|
}
|
|
2589
2590
|
}
|
|
2590
2591
|
if (providerPayload?.dt) {
|
|
2591
|
-
messages.push(...
|
|
2592
|
+
messages.push(...sanitizedHistoryItems);
|
|
2592
2593
|
} else {
|
|
2593
|
-
messages.splice(0, messages.length, ...
|
|
2594
|
+
messages.splice(0, messages.length, ...sanitizedHistoryItems);
|
|
2594
2595
|
// Keep customCallIds from the pre-splice state since historyItems may re-introduce them.
|
|
2595
2596
|
}
|
|
2596
2597
|
msgIndex += 1;
|
package/src/utils.ts
CHANGED
|
@@ -91,6 +91,57 @@ export function sanitizeOpenAIResponsesHistoryItemsForReplay(items: Array<Record
|
|
|
91
91
|
return sanitized ? [sanitized] : [];
|
|
92
92
|
});
|
|
93
93
|
}
|
|
94
|
+
function stringifyResponsesStringParamForReplay(value: unknown): string {
|
|
95
|
+
if (typeof value === "string") return value.toWellFormed();
|
|
96
|
+
try {
|
|
97
|
+
const encoded = JSON.stringify(value);
|
|
98
|
+
if (typeof encoded === "string") return encoded.toWellFormed();
|
|
99
|
+
} catch {
|
|
100
|
+
// Fall through to String().
|
|
101
|
+
}
|
|
102
|
+
return String(value ?? "").toWellFormed();
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
function normalizeResponsesMessageTextForReplay(value: unknown): string {
|
|
106
|
+
if (typeof value === "string") return value.toWellFormed();
|
|
107
|
+
if (value && typeof value === "object") {
|
|
108
|
+
const nestedText = (value as { text?: unknown }).text;
|
|
109
|
+
if (typeof nestedText === "string") return nestedText.toWellFormed();
|
|
110
|
+
}
|
|
111
|
+
return stringifyResponsesStringParamForReplay(value);
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
function sanitizeResponsesMessageContentForReplay(content: unknown): unknown {
|
|
115
|
+
if (typeof content === "string") return content.toWellFormed();
|
|
116
|
+
if (!Array.isArray(content)) return content;
|
|
117
|
+
return content.map(part => {
|
|
118
|
+
if (!part || typeof part !== "object") return part;
|
|
119
|
+
const sanitizedPart = { ...(part as Record<string, unknown>) };
|
|
120
|
+
if ("text" in sanitizedPart) {
|
|
121
|
+
sanitizedPart.text = normalizeResponsesMessageTextForReplay(sanitizedPart.text);
|
|
122
|
+
}
|
|
123
|
+
return sanitizedPart;
|
|
124
|
+
});
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
function sanitizeResponsesStringFieldsForReplay(item: Record<string, unknown>): void {
|
|
128
|
+
if (item.type === "message") {
|
|
129
|
+
item.content = sanitizeResponsesMessageContentForReplay(item.content);
|
|
130
|
+
}
|
|
131
|
+
if (item.type === "function_call" && "arguments" in item && typeof item.arguments !== "string") {
|
|
132
|
+
item.arguments = stringifyResponsesStringParamForReplay(item.arguments);
|
|
133
|
+
}
|
|
134
|
+
if (item.type === "custom_tool_call" && "input" in item && typeof item.input !== "string") {
|
|
135
|
+
item.input = stringifyResponsesStringParamForReplay(item.input);
|
|
136
|
+
}
|
|
137
|
+
if (
|
|
138
|
+
(item.type === "function_call_output" || item.type === "custom_tool_call_output") &&
|
|
139
|
+
"output" in item &&
|
|
140
|
+
typeof item.output !== "string"
|
|
141
|
+
) {
|
|
142
|
+
item.output = stringifyResponsesStringParamForReplay(item.output);
|
|
143
|
+
}
|
|
144
|
+
}
|
|
94
145
|
|
|
95
146
|
function sanitizeOpenAIResponsesHistoryItemForReplay(
|
|
96
147
|
item: Record<string, unknown>,
|
|
@@ -105,6 +156,7 @@ function sanitizeOpenAIResponsesHistoryItemForReplay(
|
|
|
105
156
|
if (typeof item.call_id === "string") {
|
|
106
157
|
sanitizedItem.call_id = normalizeReplayedResponsesHistoryCallId(item.call_id, normalizedCallIds);
|
|
107
158
|
}
|
|
159
|
+
sanitizeResponsesStringFieldsForReplay(sanitizedItem);
|
|
108
160
|
|
|
109
161
|
return sanitizedItem as unknown as OpenAIResponsesReplayItem;
|
|
110
162
|
}
|