@opengeni/codex 0.2.13 → 0.2.15

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.
@@ -167,7 +167,13 @@ export function boundModelToolOutputItems<T extends ModelHistoryItem>(
167
167
  items: readonly T[],
168
168
  policyTokens = DEFAULT_MODEL_TOOL_OUTPUT_TRUNCATION_TOKENS,
169
169
  ): T[] {
170
- return items.map((item) => boundModelToolOutputItem(item, policyTokens));
170
+ let bounded: T[] | null = null;
171
+ for (const [index, item] of items.entries()) {
172
+ const next = boundModelToolOutputItem(item, policyTokens);
173
+ if (next !== item && bounded === null) bounded = items.slice(0, index);
174
+ bounded?.push(next);
175
+ }
176
+ return bounded ?? (items as T[]);
171
177
  }
172
178
 
173
179
  function boundToolOutputValue(output: unknown, budgetTokens: number): unknown {
package/src/normalize.ts CHANGED
@@ -115,6 +115,32 @@ export function normalizeCodexRequestBody(
115
115
  return body;
116
116
  }
117
117
 
118
+ /**
119
+ * Copy-on-write form for model clients that may retain converted input items.
120
+ * Only records the mutable normalizer can touch are copied; large content,
121
+ * tools, and unchanged protocol items remain shared immutable values.
122
+ */
123
+ export function normalizedCodexRequestBody(
124
+ body: Readonly<Record<string, unknown>>,
125
+ resolveModel: (slug: string) => string,
126
+ ): Record<string, unknown> {
127
+ const projected: Record<string, unknown> = { ...body };
128
+ if (body.reasoning && typeof body.reasoning === "object" && !Array.isArray(body.reasoning)) {
129
+ projected.reasoning = { ...(body.reasoning as Record<string, unknown>) };
130
+ }
131
+ if (Array.isArray(body.input)) {
132
+ projected.input = body.input.map((item) => {
133
+ if (!item || typeof item !== "object" || Array.isArray(item)) return item;
134
+ const record = item as Record<string, unknown>;
135
+ return "id" in record ||
136
+ (record.type === "tool_search_call" && typeof record.arguments === "string")
137
+ ? { ...record }
138
+ : item;
139
+ });
140
+ }
141
+ return normalizeCodexRequestBody(projected, resolveModel);
142
+ }
143
+
118
144
  /**
119
145
  * Build a longest-prefix model resolver. Catalog slugs come from GET /models
120
146
  * (api-client.ts). One leading `namespace/` segment is stripped first; an