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