show auth key once the agent is created
This commit is contained in:
@@ -29,6 +29,14 @@ type EditableAgent = {
|
||||
llmName: string;
|
||||
};
|
||||
|
||||
type LaunchCredentials = {
|
||||
url: string;
|
||||
authType: string;
|
||||
authHeaderName: string;
|
||||
authKey: string;
|
||||
authKeyMasked: string;
|
||||
};
|
||||
|
||||
const DEFAULT_ENTRY_POINT = "fastapi_server/server_dashscope.py";
|
||||
const DEFAULT_LLM_NAME = "qwen-plus";
|
||||
const DEFAULT_PORT = 8100;
|
||||
@@ -106,6 +114,7 @@ export default function App() {
|
||||
const [selectedId, setSelectedId] = useState<string | null>(null);
|
||||
const [editor, setEditor] = useState<EditableAgent | null>(null);
|
||||
const [statusMessage, setStatusMessage] = useState<string>("");
|
||||
const [launchCredentials, setLaunchCredentials] = useState<LaunchCredentials | null>(null);
|
||||
const [busy, setBusy] = useState(false);
|
||||
|
||||
const configKeySet = useMemo(
|
||||
@@ -401,6 +410,7 @@ export default function App() {
|
||||
|
||||
setBusy(true);
|
||||
setStatusMessage("Starting agent...");
|
||||
setLaunchCredentials(null);
|
||||
try {
|
||||
const resp = await createPipeline({
|
||||
graph_id: editor.graphId,
|
||||
@@ -414,6 +424,13 @@ export default function App() {
|
||||
});
|
||||
await refreshRunning();
|
||||
setStatusMessage(`Agent started. URL: ${resp.url}`);
|
||||
setLaunchCredentials({
|
||||
url: resp.url,
|
||||
authType: resp.auth_type,
|
||||
authHeaderName: resp.auth_header_name,
|
||||
authKey: resp.auth_key_once,
|
||||
authKeyMasked: resp.auth_key_masked,
|
||||
});
|
||||
} catch (error) {
|
||||
setStatusMessage((error as Error).message);
|
||||
} finally {
|
||||
@@ -459,6 +476,23 @@ export default function App() {
|
||||
})),
|
||||
];
|
||||
const graphArchImage = editor ? getGraphArchImage(editor.graphId) : null;
|
||||
const authHeaderValue = launchCredentials
|
||||
? `${launchCredentials.authHeaderName}: Bearer ${launchCredentials.authKey}`
|
||||
: "";
|
||||
const canUseClipboard = typeof navigator !== "undefined" && Boolean(navigator.clipboard);
|
||||
|
||||
async function copyText(text: string, label: string): Promise<void> {
|
||||
if (!canUseClipboard) {
|
||||
setStatusMessage(`Clipboard is not available. Please copy ${label} manually.`);
|
||||
return;
|
||||
}
|
||||
try {
|
||||
await navigator.clipboard.writeText(text);
|
||||
setStatusMessage(`${label} copied.`);
|
||||
} catch {
|
||||
setStatusMessage(`Failed to copy ${label}.`);
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="app">
|
||||
@@ -517,6 +551,47 @@ export default function App() {
|
||||
</header>
|
||||
|
||||
{statusMessage ? <p className="status">{statusMessage}</p> : null}
|
||||
{launchCredentials ? (
|
||||
<div className="launch-credentials">
|
||||
<h3>Access Credentials (shown once)</h3>
|
||||
<div>
|
||||
<strong>URL:</strong>{" "}
|
||||
<a href={launchCredentials.url} target="_blank" rel="noreferrer">
|
||||
{launchCredentials.url}
|
||||
</a>
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => copyText(launchCredentials.url, "URL")}
|
||||
disabled={busy}
|
||||
>
|
||||
Copy URL
|
||||
</button>
|
||||
</div>
|
||||
<div>
|
||||
<strong>{launchCredentials.authType} key:</strong> {launchCredentials.authKey}
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => copyText(launchCredentials.authKey, "auth key")}
|
||||
disabled={busy}
|
||||
>
|
||||
Copy Key
|
||||
</button>
|
||||
</div>
|
||||
<div>
|
||||
<strong>Header:</strong> <code>{authHeaderValue}</code>
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => copyText(authHeaderValue, "auth header")}
|
||||
disabled={busy}
|
||||
>
|
||||
Copy Header
|
||||
</button>
|
||||
</div>
|
||||
<p className="empty">
|
||||
Stored after launch as masked value: {launchCredentials.authKeyMasked}
|
||||
</p>
|
||||
</div>
|
||||
) : null}
|
||||
|
||||
{!editor ? (
|
||||
<div className="empty-panel">
|
||||
@@ -646,6 +721,9 @@ export default function App() {
|
||||
{run.url}
|
||||
</a>
|
||||
</div>
|
||||
<div>
|
||||
<strong>auth:</strong> {run.auth_header_name} Bearer {run.auth_key_masked}
|
||||
</div>
|
||||
</div>
|
||||
))
|
||||
)}
|
||||
|
||||
@@ -108,6 +108,33 @@ button:disabled {
|
||||
padding: 10px;
|
||||
}
|
||||
|
||||
.launch-credentials {
|
||||
background: #fff4df;
|
||||
border: 1px solid #f0d5a8;
|
||||
border-radius: 8px;
|
||||
margin-top: 12px;
|
||||
padding: 12px;
|
||||
}
|
||||
|
||||
.launch-credentials h3 {
|
||||
margin: 0 0 8px;
|
||||
}
|
||||
|
||||
.launch-credentials > div {
|
||||
align-items: center;
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 8px;
|
||||
margin: 6px 0;
|
||||
}
|
||||
|
||||
.launch-credentials code {
|
||||
background: #fff;
|
||||
border: 1px solid #f0d5a8;
|
||||
border-radius: 4px;
|
||||
padding: 2px 6px;
|
||||
}
|
||||
|
||||
.empty-panel {
|
||||
margin-top: 30px;
|
||||
}
|
||||
|
||||
@@ -62,9 +62,14 @@ export type PipelineRunInfo = {
|
||||
prompt_set_id: string;
|
||||
url: string;
|
||||
port: number;
|
||||
auth_type: string;
|
||||
auth_header_name: string;
|
||||
auth_key_masked: string;
|
||||
};
|
||||
|
||||
export type PipelineCreateResponse = PipelineRunInfo;
|
||||
export type PipelineCreateResponse = PipelineRunInfo & {
|
||||
auth_key_once: string;
|
||||
};
|
||||
|
||||
export type PipelineListResponse = {
|
||||
items: PipelineRunInfo[];
|
||||
|
||||
Reference in New Issue
Block a user