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