fix: restore interactive OpenAI REPL on React 18
This commit is contained in:
@@ -1,8 +1,8 @@
|
||||
import { c as _c } from "react-compiler-runtime";
|
||||
import * as React from 'react';
|
||||
import { use } from 'react';
|
||||
import { Box } from '../ink.js';
|
||||
import type { AgentDefinitionsResult } from '../tools/AgentTool/loadAgentsDir.js';
|
||||
import type { MemoryFileInfo } from '../utils/claudemd.js';
|
||||
import { getMemoryFiles } from '../utils/claudemd.js';
|
||||
import { getGlobalConfig } from '../utils/config.js';
|
||||
import { getActiveNotices, type StatusNoticeContext } from '../utils/statusNoticeDefinitions.js';
|
||||
@@ -10,28 +10,53 @@ type Props = {
|
||||
agentDefinitions?: AgentDefinitionsResult;
|
||||
};
|
||||
|
||||
let cachedMemoryFiles: MemoryFileInfo[] = [];
|
||||
let memoryFilesPromise: Promise<void> | null = null;
|
||||
|
||||
async function loadMemoryFiles(): Promise<void> {
|
||||
if (memoryFilesPromise) {
|
||||
return memoryFilesPromise;
|
||||
}
|
||||
memoryFilesPromise = getMemoryFiles().then(files => {
|
||||
cachedMemoryFiles = files;
|
||||
}).finally(() => {
|
||||
memoryFilesPromise = null;
|
||||
});
|
||||
return memoryFilesPromise;
|
||||
}
|
||||
|
||||
/**
|
||||
* StatusNotices contains the information displayed to users at startup. We have
|
||||
* moved neutral or positive status to src/components/Status.tsx instead, which
|
||||
* users can access through /status.
|
||||
*/
|
||||
export function StatusNotices(t0) {
|
||||
const $ = _c(4);
|
||||
const $ = _c(8);
|
||||
const {
|
||||
agentDefinitions
|
||||
} = t0 === undefined ? {} : t0;
|
||||
const t1 = getGlobalConfig();
|
||||
let t2;
|
||||
const [memoryFiles, setMemoryFiles] = React.useState(cachedMemoryFiles);
|
||||
let t1;
|
||||
if ($[0] === Symbol.for("react.memo_cache_sentinel")) {
|
||||
t2 = getMemoryFiles();
|
||||
$[0] = t2;
|
||||
} else {
|
||||
t2 = $[0];
|
||||
t1 = () => {
|
||||
if (cachedMemoryFiles.length > 0) {
|
||||
setMemoryFiles(cachedMemoryFiles);
|
||||
return;
|
||||
}
|
||||
void loadMemoryFiles().then(() => {
|
||||
setMemoryFiles(cachedMemoryFiles);
|
||||
});
|
||||
};
|
||||
$[0] = t1;
|
||||
} else {
|
||||
t1 = $[0];
|
||||
}
|
||||
React.useEffect(t1, [t1]);
|
||||
const t2 = getGlobalConfig();
|
||||
const context = {
|
||||
config: t1,
|
||||
config: t2,
|
||||
agentDefinitions,
|
||||
memoryFiles: use(t2)
|
||||
memoryFiles
|
||||
};
|
||||
const activeNotices = getActiveNotices(context);
|
||||
if (activeNotices.length === 0) {
|
||||
|
||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -232,7 +232,7 @@ const reconciler = createReconciler<
|
||||
unknown,
|
||||
DOMElement,
|
||||
HostContext,
|
||||
null, // UpdatePayload - not used in React 19
|
||||
boolean,
|
||||
NodeJS.Timeout,
|
||||
-1,
|
||||
null
|
||||
@@ -398,6 +398,14 @@ const reconciler = createReconciler<
|
||||
): boolean {
|
||||
return props['autoFocus'] === true
|
||||
},
|
||||
prepareUpdate(
|
||||
_node: DOMElement,
|
||||
_type: ElementNames,
|
||||
oldProps: Props,
|
||||
newProps: Props,
|
||||
): boolean {
|
||||
return oldProps !== newProps
|
||||
},
|
||||
commitMount(node: DOMElement): void {
|
||||
getFocusManager(node).handleAutoFocus(node)
|
||||
},
|
||||
@@ -422,9 +430,9 @@ const reconciler = createReconciler<
|
||||
cleanupYogaNode(removeNode)
|
||||
getFocusManager(node).handleNodeRemoved(removeNode, node)
|
||||
},
|
||||
// React 19 commitUpdate receives old and new props directly instead of an updatePayload
|
||||
commitUpdate(
|
||||
node: DOMElement,
|
||||
_updatePayload: boolean,
|
||||
_type: ElementNames,
|
||||
oldProps: Props,
|
||||
newProps: Props,
|
||||
|
||||
@@ -596,7 +596,6 @@ export function REPL({
|
||||
sshSession,
|
||||
thinkingConfig
|
||||
}: Props): React.ReactNode {
|
||||
logForDebugging('[REPL:render] function entry');
|
||||
const isRemoteSession = !!remoteSessionConfig;
|
||||
|
||||
// Env-var gates hoisted to mount-time — isEnvTruthy does toLowerCase+trim+
|
||||
@@ -608,12 +607,6 @@ export function REPL({
|
||||
// biome-ignore lint/correctness/useHookAtTopLevel: feature() is a compile-time constant
|
||||
useMemo(() => isEnvTruthy(process.env.CLAUDE_CODE_DISABLE_MESSAGE_ACTIONS), []) : false;
|
||||
|
||||
// Log REPL mount/unmount lifecycle
|
||||
useEffect(() => {
|
||||
logForDebugging(`[REPL:mount] REPL mounted, disabled=${disabled}`);
|
||||
return () => logForDebugging(`[REPL:unmount] REPL unmounting`);
|
||||
}, [disabled]);
|
||||
|
||||
// Agent definition is state so /resume can update it mid-session
|
||||
const [mainThreadAgentDefinition, setMainThreadAgentDefinition] = useState(initialMainThreadAgentDefinition);
|
||||
const toolPermissionContext = useAppState(s => s.toolPermissionContext);
|
||||
|
||||
Reference in New Issue
Block a user