fix(core): present the project dir to the model as the App Data Dir in the default system prompt (#61)
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
1 parent
14b5e6384f
commit
816a823b75
24 files changed
+423
-68
No files matched your search
@@ -179,6 +179,13 @@ export const putAgentConfig = (
|
||||
{ method: "PUT", body },
|
||||
);
|
||||
|
||||
/** Overwrite system_config.yaml with the current defaults (keeps only name/description/version). */
|
||||
export const resetAgentConfig = (projectId: string, agentId: string) =>
|
||||
apiFetch<AgentConfigResponse>(
|
||||
`/api/projects/${encodeURIComponent(projectId)}/agents/${encodeURIComponent(agentId)}/config/reset`,
|
||||
{ method: "POST" },
|
||||
);
|
||||
|
||||
export const getAgentTraces = (projectId: string, agentId: string) =>
|
||||
apiFetch<AgentTracesResponse>(
|
||||
`/api/projects/${encodeURIComponent(projectId)}/agents/${encodeURIComponent(agentId)}/traces`,
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/**
|
||||
* Agent settings page: six tabs —
|
||||
* Overview (name/description/State path/active count/State version + snapshot
|
||||
* export-import), Prompt (AGENTS.md and system_prompt editors + placeholder
|
||||
* export-import + restore default configuration), Prompt (AGENTS.md and system_prompt editors + placeholder
|
||||
* reference), Runtime (max_turns, model.*, compaction.*), Tools (editable built-in
|
||||
* tools table, MCP Server read-only JSON), Vault (vault-tab.tsx), Schedule
|
||||
* (schedules-tab.tsx).
|
||||
@@ -116,6 +116,13 @@ export function AgentSettingsPage() {
|
||||
[load, reloadAgents],
|
||||
);
|
||||
|
||||
/** Config reset succeeded: the whole system_config.yaml was replaced, so reload every tab's data (and the list's tool counts). */
|
||||
const onConfigReset = useCallback(() => {
|
||||
toastSuccess(S.agent.resetConfigDone);
|
||||
load();
|
||||
void reloadAgents();
|
||||
}, [load, reloadAgents]);
|
||||
|
||||
const save = useCallback(
|
||||
async (update: AgentConfigUpdateRequest) => {
|
||||
if (!projectId || !agentId) return;
|
||||
@@ -177,7 +184,13 @@ export function AgentSettingsPage() {
|
||||
<Tabs items={TABS} active={tab} onChange={setTab} />
|
||||
<div className="py-4">
|
||||
{tab === "overview" && (
|
||||
<OverviewTab data={data} agentId={agentId} onSave={save} onImported={onImported} />
|
||||
<OverviewTab
|
||||
data={data}
|
||||
agentId={agentId}
|
||||
onSave={save}
|
||||
onImported={onImported}
|
||||
onConfigReset={onConfigReset}
|
||||
/>
|
||||
)}
|
||||
{tab === "prompt" && <PromptTab data={data} onSave={save} />}
|
||||
{tab === "runtime" && <RuntimeTab data={data} onSave={save} />}
|
||||
@@ -204,11 +217,13 @@ function OverviewTab({
|
||||
agentId,
|
||||
onSave,
|
||||
onImported,
|
||||
onConfigReset,
|
||||
}: {
|
||||
data: AgentConfigResponse;
|
||||
agentId: string;
|
||||
onSave: SaveFn;
|
||||
onImported: (version: number) => void;
|
||||
onConfigReset: () => void;
|
||||
}) {
|
||||
const { currentProject } = useProject();
|
||||
const projectId = currentProject?.projectId ?? null;
|
||||
@@ -219,8 +234,24 @@ function OverviewTab({
|
||||
const [importError, setImportError] = useState<string | null>(null);
|
||||
// base64 of the snapshot package pending confirmation for a version conflict (409 version_conflict); non-null shows the confirm modal.
|
||||
const [conflict, setConflict] = useState<string | null>(null);
|
||||
const [resetOpen, setResetOpen] = useState(false);
|
||||
const [resetting, setResetting] = useState(false);
|
||||
const { requestSave, element: saveConfirm } = useSaveConfirm();
|
||||
|
||||
const runReset = async () => {
|
||||
if (!projectId) return;
|
||||
setResetting(true);
|
||||
try {
|
||||
await api.resetAgentConfig(projectId, agentId);
|
||||
setResetOpen(false);
|
||||
onConfigReset();
|
||||
} catch (e) {
|
||||
toastError(apiErrorText(e));
|
||||
} finally {
|
||||
setResetting(false);
|
||||
}
|
||||
};
|
||||
|
||||
const submit = () => {
|
||||
const config: NonNullable<AgentConfigUpdateRequest["config"]> = {};
|
||||
if (name.trim() !== (data.config.name ?? "")) config.name = name.trim();
|
||||
@@ -336,6 +367,15 @@ function OverviewTab({
|
||||
)}
|
||||
</div>
|
||||
|
||||
{/* Restore default configuration: overwrite system_config.yaml with the current defaults (name/description/version kept) — the config-side analogue of a skill update. */}
|
||||
<div>
|
||||
<p className="mb-1 text-xs font-medium text-gray-500">{S.agent.resetConfigTitle}</p>
|
||||
<p className="mb-2 text-xs text-gray-500 dark:text-gray-400">{S.agent.resetConfigDesc}</p>
|
||||
<Button size="sm" disabled={resetting} onClick={() => setResetOpen(true)}>
|
||||
{S.agent.resetConfigAction}
|
||||
</Button>
|
||||
</div>
|
||||
|
||||
<Button size="sm" variant="primary" onClick={submit}>
|
||||
{S.common.save}
|
||||
</Button>
|
||||
@@ -353,6 +393,18 @@ function OverviewTab({
|
||||
>
|
||||
<p className="text-sm text-gray-600 dark:text-gray-300">{S.agent.importConflictBody}</p>
|
||||
</ConfirmModal>
|
||||
|
||||
{/* Reset confirmation: overwriting customizations with the defaults is destructive, so it keeps the danger tone. */}
|
||||
<ConfirmModal
|
||||
open={resetOpen}
|
||||
title={S.agent.resetConfigTitle}
|
||||
busy={resetting}
|
||||
onClose={() => setResetOpen(false)}
|
||||
onConfirm={() => void runReset()}
|
||||
confirmLabel={S.agent.resetConfigAction}
|
||||
>
|
||||
<p className="text-sm text-gray-600 dark:text-gray-300">{S.agent.resetConfigConfirmBody}</p>
|
||||
</ConfirmModal>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -190,12 +190,18 @@ export const en: Strings = {
|
||||
placeholders: [
|
||||
["{{AGENTS_MD}}", "Injects the AGENTS.md content"],
|
||||
["{{VAULT_KEYS}}", "Injects the vault key-name section (empty when no keys)"],
|
||||
["{{SKILL_METADATA}}", "Injects the installed skills' metadata lines (empty when none)"],
|
||||
["{{PLATFORM}}", "Runtime platform"],
|
||||
["{{OS_VERSION}}", "Operating system version"],
|
||||
["{{DATE}}", "Current date"],
|
||||
["{{CWD}}", "Absolute Workspace path"],
|
||||
[
|
||||
"{{PROJECT_DIR}}",
|
||||
"PenguinHarness app data root — all agents' data and project-level data; not the task working directory",
|
||||
],
|
||||
["{{AGENT_ID}}", "Current agent id"],
|
||||
["{{PROJECT_DIR}}", "Absolute Project directory (Agent State/scratchpad derive from it)"],
|
||||
["{{CWD}}", "Absolute Workspace path"],
|
||||
["{{PROVIDER}}", "Model provider group"],
|
||||
["{{MODEL_ID}}", "Upstream model id"],
|
||||
["{{SESSION_ID}}", "Current Session id"],
|
||||
] as ReadonlyArray<readonly [string, string]>,
|
||||
maxTurns: "max_turns (max turns per Task, -1 = unlimited)",
|
||||
@@ -265,6 +271,13 @@ export const en: Strings = {
|
||||
importConflictTitle: "Version conflict",
|
||||
importConflictBody:
|
||||
"The snapshot's version is not newer than the current one; importing will overwrite the existing Agent State. Continue?",
|
||||
resetConfigTitle: "Restore default configuration",
|
||||
resetConfigDesc:
|
||||
"Restores system_config.yaml to the current built-in defaults (same semantics as a skill update): the custom system prompt, tool list, model/compaction settings and MCP servers are overwritten; only name, description and the State version are kept.",
|
||||
resetConfigAction: "Restore default configuration",
|
||||
resetConfigConfirmBody:
|
||||
"This overwrites the agent's existing configuration with the current defaults: the custom system prompt, tool list, model/compaction settings and MCP servers are all replaced, keeping only name and description. Like a skill update this cannot be undone. Continue?",
|
||||
resetConfigDone: "Configuration restored to the current defaults",
|
||||
},
|
||||
|
||||
models: {
|
||||
|
||||
@@ -181,12 +181,18 @@ export const zh = {
|
||||
placeholders: [
|
||||
["{{AGENTS_MD}}", "注入 AGENTS.md 内容"],
|
||||
["{{VAULT_KEYS}}", "注入密钥保险柜的键名小节(无键时为空)"],
|
||||
["{{SKILL_METADATA}}", "注入已安装 Skill 的元数据行(无 Skill 时为空)"],
|
||||
["{{PLATFORM}}", "运行平台"],
|
||||
["{{OS_VERSION}}", "操作系统版本"],
|
||||
["{{DATE}}", "当前日期"],
|
||||
["{{CWD}}", "Workspace 绝对路径"],
|
||||
[
|
||||
"{{PROJECT_DIR}}",
|
||||
"PenguinHarness 应用数据根目录(存放全部 Agent 数据与 Project 级数据;不是本次任务的工作目录)",
|
||||
],
|
||||
["{{AGENT_ID}}", "当前 Agent id"],
|
||||
["{{PROJECT_DIR}}", "Project 目录绝对路径(Agent State/scratchpad 由此拼出)"],
|
||||
["{{CWD}}", "Workspace 绝对路径"],
|
||||
["{{PROVIDER}}", "模型 provider 分组"],
|
||||
["{{MODEL_ID}}", "上游模型 id"],
|
||||
["{{SESSION_ID}}", "当前 Session id"],
|
||||
] as ReadonlyArray<readonly [string, string]>,
|
||||
maxTurns: "max_turns(单 Task 最大轮次,-1 不限制)",
|
||||
@@ -242,6 +248,13 @@ export const zh = {
|
||||
importDone: (v: number): string => `导入完成,Agent State 版本 v${v}`,
|
||||
importConflictTitle: "版本冲突",
|
||||
importConflictBody: "快照包版本不高于当前版本,导入将覆盖现有 Agent State。确认继续?",
|
||||
resetConfigTitle: "还原为默认配置",
|
||||
resetConfigDesc:
|
||||
"把 system_config.yaml 还原为当前内置默认值(与 Skill 更新同语义):自定义的系统提示词、工具列表、模型/压缩参数与 MCP Server 将被覆盖,仅保留名称、描述与版本号。",
|
||||
resetConfigAction: "还原为默认配置",
|
||||
resetConfigConfirmBody:
|
||||
"此操作会用当前默认值覆盖该 Agent 的现有配置:自定义系统提示词、工具列表、模型/压缩参数与 MCP Server 全部被替换,仅保留名称与描述。与 Skill 更新一样不可撤销,确认继续?",
|
||||
resetConfigDone: "配置已还原为当前默认值",
|
||||
},
|
||||
|
||||
models: {
|
||||
|
||||
Reference in new issue
Block a user