save api key
This commit is contained in:
@@ -22,6 +22,7 @@ class GraphConfigUpsertRequest(BaseModel):
|
||||
prompt_set_id: Optional[str] = Field(default=None)
|
||||
tool_keys: List[str] = Field(default_factory=list)
|
||||
prompt_dict: Dict[str, str] = Field(default_factory=dict)
|
||||
api_key: Optional[str] = Field(default=None)
|
||||
|
||||
class GraphConfigUpsertResponse(BaseModel):
|
||||
graph_id: str
|
||||
@@ -29,6 +30,7 @@ class GraphConfigUpsertResponse(BaseModel):
|
||||
prompt_set_id: str
|
||||
tool_keys: List[str]
|
||||
prompt_keys: List[str]
|
||||
api_key: str
|
||||
|
||||
class GraphConfigReadResponse(BaseModel):
|
||||
graph_id: Optional[str] = Field(default=None)
|
||||
@@ -36,6 +38,7 @@ class GraphConfigReadResponse(BaseModel):
|
||||
prompt_set_id: str
|
||||
tool_keys: List[str]
|
||||
prompt_dict: Dict[str, str]
|
||||
api_key: str = Field(default="")
|
||||
|
||||
class GraphConfigListItem(BaseModel):
|
||||
graph_id: Optional[str] = Field(default=None)
|
||||
@@ -45,6 +48,7 @@ class GraphConfigListItem(BaseModel):
|
||||
description: str
|
||||
is_active: bool
|
||||
tool_keys: List[str]
|
||||
api_key: str = Field(default="")
|
||||
created_at: Optional[str] = Field(default=None)
|
||||
updated_at: Optional[str] = Field(default=None)
|
||||
|
||||
@@ -169,6 +173,7 @@ async def upsert_graph_config(body: GraphConfigUpsertRequest):
|
||||
prompt_set_id=body.prompt_set_id,
|
||||
tool_list=body.tool_keys,
|
||||
prompt_dict=body.prompt_dict,
|
||||
api_key=body.api_key,
|
||||
)
|
||||
except ValueError as e:
|
||||
raise HTTPException(status_code=400, detail=str(e))
|
||||
@@ -181,6 +186,7 @@ async def upsert_graph_config(body: GraphConfigUpsertRequest):
|
||||
prompt_set_id=resolved_prompt_set_id,
|
||||
tool_keys=body.tool_keys,
|
||||
prompt_keys=list(body.prompt_dict.keys()),
|
||||
api_key=(body.api_key or "").strip(),
|
||||
)
|
||||
|
||||
@app.get("/v1/graph-configs", response_model=GraphConfigListResponse)
|
||||
@@ -222,6 +228,7 @@ async def get_default_graph_config(pipeline_id: str):
|
||||
prompt_set_id=active["prompt_set_id"],
|
||||
tool_keys=tool_keys,
|
||||
prompt_dict=prompt_dict,
|
||||
api_key=(active.get("api_key") or ""),
|
||||
)
|
||||
|
||||
@app.get("/v1/graphs/{graph_id}/default-config", response_model=GraphConfigReadResponse)
|
||||
@@ -254,6 +261,7 @@ async def get_graph_config(pipeline_id: str, prompt_set_id: str):
|
||||
prompt_set_id=prompt_set_id,
|
||||
tool_keys=tool_keys,
|
||||
prompt_dict=prompt_dict,
|
||||
api_key=(meta.get("api_key") or ""),
|
||||
)
|
||||
|
||||
|
||||
|
||||
@@ -101,7 +101,7 @@ function toEditable(
|
||||
toolKeys: config.tool_keys || [],
|
||||
prompts: config.prompt_dict || {},
|
||||
port: DEFAULT_PORT,
|
||||
apiKey: DEFAULT_API_KEY,
|
||||
apiKey: config.api_key || DEFAULT_API_KEY,
|
||||
llmName: DEFAULT_LLM_NAME,
|
||||
};
|
||||
}
|
||||
@@ -207,8 +207,8 @@ export default function App() {
|
||||
const editable = toEditable(detail, false);
|
||||
editable.id = id;
|
||||
editable.port = editor?.pipelineId === editable.pipelineId ? editor.port : DEFAULT_PORT;
|
||||
editable.apiKey = editor?.pipelineId === editable.pipelineId ? editor.apiKey : DEFAULT_API_KEY;
|
||||
editable.llmName = editor?.pipelineId === editable.pipelineId ? editor.llmName : DEFAULT_LLM_NAME;
|
||||
// apiKey is loaded from backend (persisted in DB) — don't override with default
|
||||
setEditor(editable);
|
||||
setStatusMessage("");
|
||||
} catch (error) {
|
||||
@@ -305,6 +305,7 @@ export default function App() {
|
||||
prompt_set_id: "default",
|
||||
tool_keys: [],
|
||||
prompt_dict: fallbackPrompts,
|
||||
api_key: "",
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -340,6 +341,7 @@ export default function App() {
|
||||
prompt_set_id: editor.promptSetId,
|
||||
tool_keys: editor.toolKeys,
|
||||
prompt_dict: editor.prompts,
|
||||
api_key: editor.apiKey.trim(),
|
||||
});
|
||||
|
||||
await refreshConfigs();
|
||||
@@ -347,7 +349,7 @@ export default function App() {
|
||||
const saved = toEditable(detail, false);
|
||||
saved.id = makeAgentKey(upsertResp.pipeline_id, upsertResp.prompt_set_id);
|
||||
saved.port = editor.port;
|
||||
saved.apiKey = editor.apiKey;
|
||||
// apiKey is loaded from backend (persisted in DB) — don't override
|
||||
saved.llmName = editor.llmName;
|
||||
setEditor(saved);
|
||||
setSelectedId(saved.id);
|
||||
|
||||
@@ -6,6 +6,7 @@ export type GraphConfigListItem = {
|
||||
description: string;
|
||||
is_active: boolean;
|
||||
tool_keys: string[];
|
||||
api_key: string;
|
||||
created_at?: string | null;
|
||||
updated_at?: string | null;
|
||||
};
|
||||
@@ -21,6 +22,7 @@ export type GraphConfigReadResponse = {
|
||||
prompt_set_id: string;
|
||||
tool_keys: string[];
|
||||
prompt_dict: Record<string, string>;
|
||||
api_key: string;
|
||||
};
|
||||
|
||||
export type GraphConfigUpsertRequest = {
|
||||
@@ -29,6 +31,7 @@ export type GraphConfigUpsertRequest = {
|
||||
prompt_set_id?: string;
|
||||
tool_keys: string[];
|
||||
prompt_dict: Record<string, string>;
|
||||
api_key?: string;
|
||||
};
|
||||
|
||||
export type GraphConfigUpsertResponse = {
|
||||
@@ -37,6 +40,7 @@ export type GraphConfigUpsertResponse = {
|
||||
prompt_set_id: string;
|
||||
tool_keys: string[];
|
||||
prompt_keys: string[];
|
||||
api_key: string;
|
||||
};
|
||||
|
||||
export type AvailableGraphsResponse = {
|
||||
|
||||
@@ -28,7 +28,7 @@ class DBConfigManager:
|
||||
if pipeline_id and graph_id:
|
||||
cur.execute(
|
||||
"""
|
||||
SELECT id, pipeline_id, graph_id, name, description, is_active, created_at, updated_at, list
|
||||
SELECT id, pipeline_id, graph_id, name, description, is_active, created_at, updated_at, list, api_key
|
||||
FROM prompt_sets
|
||||
WHERE pipeline_id = %s AND graph_id = %s
|
||||
ORDER BY updated_at DESC, created_at DESC
|
||||
@@ -38,7 +38,7 @@ class DBConfigManager:
|
||||
elif pipeline_id:
|
||||
cur.execute(
|
||||
"""
|
||||
SELECT id, pipeline_id, graph_id, name, description, is_active, created_at, updated_at, list
|
||||
SELECT id, pipeline_id, graph_id, name, description, is_active, created_at, updated_at, list, api_key
|
||||
FROM prompt_sets
|
||||
WHERE pipeline_id = %s
|
||||
ORDER BY updated_at DESC, created_at DESC
|
||||
@@ -48,7 +48,7 @@ class DBConfigManager:
|
||||
elif graph_id:
|
||||
cur.execute(
|
||||
"""
|
||||
SELECT id, pipeline_id, graph_id, name, description, is_active, created_at, updated_at, list
|
||||
SELECT id, pipeline_id, graph_id, name, description, is_active, created_at, updated_at, list, api_key
|
||||
FROM prompt_sets
|
||||
WHERE graph_id = %s
|
||||
ORDER BY updated_at DESC, created_at DESC
|
||||
@@ -58,7 +58,7 @@ class DBConfigManager:
|
||||
else:
|
||||
cur.execute(
|
||||
"""
|
||||
SELECT id, pipeline_id, graph_id, name, description, is_active, created_at, updated_at, list
|
||||
SELECT id, pipeline_id, graph_id, name, description, is_active, created_at, updated_at, list, api_key
|
||||
FROM prompt_sets
|
||||
ORDER BY updated_at DESC, created_at DESC
|
||||
"""
|
||||
@@ -76,6 +76,7 @@ class DBConfigManager:
|
||||
"created_at": row["created_at"].isoformat() if row["created_at"] else None,
|
||||
"updated_at": row["updated_at"].isoformat() if row["updated_at"] else None,
|
||||
"tool_keys": self._parse_tool_list(row.get("list")),
|
||||
"api_key": row.get("api_key") or "",
|
||||
}
|
||||
for row in rows
|
||||
]
|
||||
@@ -88,7 +89,7 @@ class DBConfigManager:
|
||||
with conn.cursor(row_factory=dict_row) as cur:
|
||||
cur.execute(
|
||||
"""
|
||||
SELECT id, pipeline_id, graph_id, name, description, is_active, created_at, updated_at, list
|
||||
SELECT id, pipeline_id, graph_id, name, description, is_active, created_at, updated_at, list, api_key
|
||||
FROM prompt_sets
|
||||
WHERE id = %s AND pipeline_id = %s
|
||||
""",
|
||||
@@ -109,6 +110,7 @@ class DBConfigManager:
|
||||
"created_at": row["created_at"].isoformat() if row["created_at"] else None,
|
||||
"updated_at": row["updated_at"].isoformat() if row["updated_at"] else None,
|
||||
"tool_keys": self._parse_tool_list(row.get("list")),
|
||||
"api_key": row.get("api_key") or "",
|
||||
}
|
||||
|
||||
def get_config(
|
||||
@@ -160,6 +162,7 @@ class DBConfigManager:
|
||||
prompt_set_id: Optional[str],
|
||||
tool_list: Optional[Sequence[str]],
|
||||
prompt_dict: Optional[Mapping[str, str]],
|
||||
api_key: Optional[str] = None,
|
||||
) -> str:
|
||||
"""
|
||||
Persist prompt + tool configuration.
|
||||
@@ -182,6 +185,7 @@ class DBConfigManager:
|
||||
|
||||
normalized_prompt_dict = self._normalize_prompt_dict(prompt_dict)
|
||||
tool_csv = self._join_tool_list(tool_list)
|
||||
normalized_api_key = self._normalize_api_key(api_key)
|
||||
|
||||
with psycopg.connect(self.conn_str) as conn:
|
||||
resolved_set_id, _ = self._resolve_prompt_set(
|
||||
@@ -200,10 +204,13 @@ class DBConfigManager:
|
||||
cur.execute(
|
||||
"""
|
||||
UPDATE prompt_sets
|
||||
SET list = %s, graph_id = COALESCE(%s, graph_id), updated_at = now()
|
||||
SET list = %s,
|
||||
graph_id = COALESCE(%s, graph_id),
|
||||
api_key = COALESCE(%s, api_key),
|
||||
updated_at = now()
|
||||
WHERE id = %s
|
||||
""",
|
||||
(tool_csv, normalized_graph_id, resolved_set_id),
|
||||
(tool_csv, normalized_graph_id, normalized_api_key, resolved_set_id),
|
||||
)
|
||||
|
||||
keys = list(normalized_prompt_dict.keys())
|
||||
@@ -340,4 +347,9 @@ class DBConfigManager:
|
||||
if graph_id is None:
|
||||
return None
|
||||
value = str(graph_id).strip()
|
||||
return value or None
|
||||
return value or None
|
||||
|
||||
def _normalize_api_key(self, api_key: Optional[str]) -> Optional[str]:
|
||||
if api_key is None:
|
||||
return None
|
||||
return str(api_key).strip()
|
||||
Reference in New Issue
Block a user