Update agent SDKs and add gated Codex goals support (#114)
* add gated codex goals support * sync README SDK versions * bump claude agent sdk * add codex goals settings toggle
This commit is contained in:
@@ -34,6 +34,7 @@ describe('SettingsPanel', () => {
|
||||
expect(html).toContain('모델');
|
||||
expect(html).toContain('MoA 참조 모델');
|
||||
expect(html).toContain('패스트 모드');
|
||||
expect(html).toContain('Codex 실험 기능');
|
||||
expect(html).toContain('불러오는 중');
|
||||
expect(html).toContain('Claude');
|
||||
expect(html).toContain('계정');
|
||||
|
||||
@@ -3,17 +3,20 @@ import { useEffect, useState } from 'react';
|
||||
import {
|
||||
type ClaudeAccountSummary,
|
||||
type CodexAccountSummary,
|
||||
type CodexFeatureSnapshot,
|
||||
type FastModeSnapshot,
|
||||
type ModelConfigSnapshot,
|
||||
type ModelRoleConfig,
|
||||
addClaudeAccount,
|
||||
deleteAccount,
|
||||
fetchAccounts,
|
||||
fetchCodexFeatures,
|
||||
fetchFastMode,
|
||||
fetchModelConfig,
|
||||
refreshAllCodexAccounts as refreshAllCodexAccountsApi,
|
||||
refreshCodexAccount as refreshCodexAccountApi,
|
||||
setCurrentCodexAccount as setCurrentCodexAccountApi,
|
||||
updateCodexFeatures,
|
||||
updateFastMode,
|
||||
updateModels,
|
||||
} from './api';
|
||||
@@ -82,6 +85,8 @@ export function SettingsPanel({
|
||||
|
||||
<FastModeSettings />
|
||||
|
||||
<CodexFeatureSettings onRestartStack={onRestartStack} />
|
||||
|
||||
<AccountSettings onRestartStack={onRestartStack} />
|
||||
</div>
|
||||
);
|
||||
@@ -302,6 +307,104 @@ function FastModeSettings() {
|
||||
);
|
||||
}
|
||||
|
||||
function CodexFeatureSettings({
|
||||
onRestartStack,
|
||||
}: {
|
||||
onRestartStack: () => void;
|
||||
}) {
|
||||
const [state, setState] = useState<CodexFeatureSnapshot | null>(null);
|
||||
const [busy, setBusy] = useState(false);
|
||||
const [error, setError] = useState<string | null>(null);
|
||||
const [savedAt, setSavedAt] = useState<number | null>(null);
|
||||
|
||||
useEffect(() => {
|
||||
let cancelled = false;
|
||||
fetchCodexFeatures()
|
||||
.then((snapshot) => {
|
||||
if (cancelled) return;
|
||||
setState(snapshot);
|
||||
setError(null);
|
||||
})
|
||||
.catch((err) => {
|
||||
if (cancelled) return;
|
||||
setError(err instanceof Error ? err.message : String(err));
|
||||
});
|
||||
return () => {
|
||||
cancelled = true;
|
||||
};
|
||||
}, []);
|
||||
|
||||
async function toggleGoals() {
|
||||
if (!state) return;
|
||||
const previous = state;
|
||||
const optimistic = { ...state, goals: !state.goals };
|
||||
setState(optimistic);
|
||||
setBusy(true);
|
||||
setError(null);
|
||||
try {
|
||||
const fresh = await updateCodexFeatures({ goals: optimistic.goals });
|
||||
setState(fresh);
|
||||
setSavedAt(Date.now());
|
||||
} catch (err) {
|
||||
setState(previous);
|
||||
setError(err instanceof Error ? err.message : String(err));
|
||||
} finally {
|
||||
setBusy(false);
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<section className="settings-section">
|
||||
<h3>Codex 실험 기능</h3>
|
||||
{error ? <p className="settings-error">{error}</p> : null}
|
||||
{!state ? (
|
||||
<p className="settings-hint">불러오는 중…</p>
|
||||
) : (
|
||||
<>
|
||||
<label className="settings-toggle-row">
|
||||
<span className="settings-toggle-label">
|
||||
<span className="settings-toggle-title">/goal</span>
|
||||
<small className="settings-hint">
|
||||
CODEX_GOALS=true — Codex 0.128의 under-development goals
|
||||
기능입니다. 기본 OFF이며, 저장 후 스택 재시작이 필요합니다.
|
||||
</small>
|
||||
</span>
|
||||
<input
|
||||
checked={state.goals}
|
||||
disabled={busy}
|
||||
onChange={() => void toggleGoals()}
|
||||
type="checkbox"
|
||||
/>
|
||||
</label>
|
||||
<div className="settings-actions">
|
||||
{savedAt ? (
|
||||
<small className="settings-hint">
|
||||
저장됨. 적용하려면 스택 재시작 필요.
|
||||
</small>
|
||||
) : null}
|
||||
<button
|
||||
className="settings-restart"
|
||||
disabled={busy}
|
||||
onClick={() => {
|
||||
if (
|
||||
window.confirm(
|
||||
'스택을 재시작하면 진행 중인 모든 에이전트 작업이 중단됩니다. 진행할까요?',
|
||||
)
|
||||
) {
|
||||
onRestartStack();
|
||||
}
|
||||
}}
|
||||
type="button"
|
||||
>
|
||||
스택 재시작
|
||||
</button>
|
||||
</div>
|
||||
</>
|
||||
)}
|
||||
</section>
|
||||
);
|
||||
}
|
||||
|
||||
function formatExpiry(
|
||||
iso: string | null,
|
||||
): { label: string; cls: string } | null {
|
||||
|
||||
@@ -388,6 +388,10 @@ export interface FastModeSnapshot {
|
||||
claude: boolean;
|
||||
}
|
||||
|
||||
export interface CodexFeatureSnapshot {
|
||||
goals: boolean;
|
||||
}
|
||||
|
||||
export interface MoaReferenceStatus {
|
||||
model: string;
|
||||
checkedAt: string;
|
||||
@@ -538,6 +542,34 @@ export async function updateFastMode(
|
||||
return (await response.json()) as FastModeSnapshot;
|
||||
}
|
||||
|
||||
export async function fetchCodexFeatures(): Promise<CodexFeatureSnapshot> {
|
||||
return fetchJson('/api/settings/codex-features');
|
||||
}
|
||||
|
||||
export async function updateCodexFeatures(
|
||||
input: Partial<CodexFeatureSnapshot>,
|
||||
): Promise<CodexFeatureSnapshot> {
|
||||
const response = await fetch('/api/settings/codex-features', {
|
||||
method: 'PUT',
|
||||
headers: {
|
||||
accept: 'application/json',
|
||||
'content-type': 'application/json',
|
||||
},
|
||||
body: JSON.stringify(input),
|
||||
});
|
||||
if (!response.ok) {
|
||||
let msg = `update codex features failed: ${response.status}`;
|
||||
try {
|
||||
const payload = (await response.json()) as { error?: string };
|
||||
if (payload.error) msg = payload.error;
|
||||
} catch {
|
||||
/* ignore */
|
||||
}
|
||||
throw new Error(msg);
|
||||
}
|
||||
return (await response.json()) as CodexFeatureSnapshot;
|
||||
}
|
||||
|
||||
export async function fetchMoaSettings(): Promise<MoaSettingsSnapshot> {
|
||||
return fetchJson('/api/settings/moa');
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user