Merge remote-tracking branch 'origin/main' into bigrefactor

# Conflicts:
#	packages/ai/src/providers/openai-codex-responses.ts
#	packages/coding-agent/src/core/agent-session.ts
#	packages/coding-agent/src/core/tools/read.ts
This commit is contained in:
Mario Zechner
2026-05-04 00:56:51 +02:00
5 changed files with 37 additions and 37 deletions

View File

@@ -16,14 +16,10 @@ export type {
OpenAICodexResponsesOptions,
OpenAICodexWebSocketDebugStats,
} from "./providers/openai-codex-responses.js";
export {
closeOpenAICodexWebSocketSessions,
getOpenAICodexWebSocketDebugStats,
resetOpenAICodexWebSocketDebugStats,
} from "./providers/openai-codex-responses.js";
export type { OpenAICompletionsOptions } from "./providers/openai-completions.js";
export type { OpenAIResponsesOptions } from "./providers/openai-responses.js";
export * from "./providers/register-builtins.js";
export * from "./session-resources.js";
export * from "./stream.js";
export * from "./types.js";
export * from "./utils/diagnostics.js";

View File

@@ -22,6 +22,7 @@ if (typeof process !== "undefined" && (process.versions?.node || process.version
import { getEnvApiKey } from "../env-api-keys.js";
import { clampThinkingLevel } from "../models.js";
import { registerSessionResourceCleanup } from "../session-resources.js";
import type {
Api,
AssistantMessage,
@@ -682,6 +683,8 @@ export function closeOpenAICodexWebSocketSessions(sessionId?: string): void {
websocketSessionCache.clear();
}
registerSessionResourceCleanup(closeOpenAICodexWebSocketSessions);
function isWebSocketSseFallbackActive(sessionId: string | undefined): boolean {
return sessionId ? websocketSseFallbackSessions.has(sessionId) : false;
}

View File

@@ -0,0 +1,24 @@
export type SessionResourceCleanup = (sessionId?: string) => void;
const sessionResourceCleanups = new Set<SessionResourceCleanup>();
export function registerSessionResourceCleanup(cleanup: SessionResourceCleanup): () => void {
sessionResourceCleanups.add(cleanup);
return () => {
sessionResourceCleanups.delete(cleanup);
};
}
export function cleanupSessionResources(sessionId?: string): void {
const errors: unknown[] = [];
for (const cleanup of sessionResourceCleanups) {
try {
cleanup(sessionId);
} catch (error) {
errors.push(error);
}
}
if (errors.length > 0) {
throw new AggregateError(errors, "Failed to cleanup session resources");
}
}

View File

@@ -26,12 +26,12 @@ import type {
import type { AssistantMessage, ImageContent, Message, Model, TextContent } from "@mariozechner/pi-ai";
import {
clampThinkingLevel,
cleanupSessionResources,
getSupportedThinkingLevels,
isContextOverflow,
modelsAreEqual,
resetApiProviders,
} from "@mariozechner/pi-ai";
import { closeOpenAICodexWebSocketSessions } from "@mariozechner/pi-ai/openai-codex-responses";
import { theme } from "../modes/interactive/theme/theme.js";
import { stripFrontmatter } from "../utils/frontmatter.js";
import { sleep } from "../utils/sleep.js";
@@ -753,7 +753,7 @@ export class AgentSession {
);
this._disconnectFromAgent();
this._eventListeners = [];
closeOpenAICodexWebSocketSessions(this.sessionId);
cleanupSessionResources(this.sessionId);
}
// =========================================================================

View File

@@ -33,20 +33,6 @@ interface CompactReadClassification {
label: string;
}
interface ReadRenderState {
hideCall?: boolean;
}
class ReadCallText extends Text {
constructor(private state: ReadRenderState) {
super("", 0, 0);
}
override render(width: number): string[] {
return this.state.hideCall ? [] : super.render(width);
}
}
const COMPACT_RESOURCE_FILE_NAMES = new Set(["AGENTS.md", "AGENTS.MD", "CLAUDE.md", "CLAUDE.MD"]);
/**
@@ -154,7 +140,7 @@ function getCompactReadClassification(
return undefined;
}
function formatCompactReadResult(classification: CompactReadClassification, theme: Theme): string {
function formatCompactReadCall(classification: CompactReadClassification, theme: Theme): string {
if (classification.kind === "skill") {
return (
theme.fg("customMessageLabel", `\x1b[1m[skill]\x1b[22m `) +
@@ -180,11 +166,8 @@ function formatReadResult(
cwd: string,
isError: boolean,
): string {
if (!options.expanded && !isError) {
const classification = getCompactReadClassification(args, cwd);
if (classification) {
return formatCompactReadResult(classification, theme);
}
if (!options.expanded && !isError && getCompactReadClassification(args, cwd)) {
return "";
}
const rawPath = str(args?.file_path ?? args?.path);
@@ -216,7 +199,7 @@ function formatReadResult(
export function createReadToolDefinition(
cwd: string,
options?: ReadToolOptions,
): ToolDefinition<typeof readSchema, ReadToolDetails | undefined, ReadRenderState> {
): ToolDefinition<typeof readSchema, ReadToolDetails | undefined> {
const autoResizeImages = options?.autoResizeImages ?? true;
const ops = options?.operations ?? defaultReadOperations;
return {
@@ -351,22 +334,16 @@ export function createReadToolDefinition(
);
},
renderCall(args, theme, context) {
const text =
context.lastComponent instanceof ReadCallText ? context.lastComponent : new ReadCallText(context.state);
context.state.hideCall = false;
text.setText(formatReadCall(args, theme));
const text = (context.lastComponent as Text | undefined) ?? new Text("", 0, 0);
const classification = !context.expanded ? getCompactReadClassification(args, context.cwd) : undefined;
text.setText(classification ? formatCompactReadCall(classification, theme) : formatReadCall(args, theme));
return text;
},
renderResult(result, options, theme, context) {
const text = (context.lastComponent as Text | undefined) ?? new Text("", 0, 0);
const hideCall =
!options.expanded &&
!context.isError &&
getCompactReadClassification(context.args, context.cwd) !== undefined;
text.setText(
formatReadResult(context.args, result, options, theme, context.showImages, context.cwd, context.isError),
);
context.state.hideCall = hideCall;
return text;
},
};