feat: add Ops AI Workspace npm setup command

This commit is contained in:
DCCONSTRUCTIONS
2026-06-24 20:40:12 +03:00
parent 763b90f3ba
commit 43e5f570e5
7 changed files with 160 additions and 31 deletions
@@ -1547,6 +1547,29 @@ export function AIWorkspaceProductConsole({ open, workspaceSlug, onClose }: TAIW
[opsWorkspaceSlug, runRegistryAction, selectedProjectId, updateRegistry, workspaceSlug]
);
const copySetupCommand = useCallback(
async (executorId: string, input: TAIWorkspaceExecutorInput, port: string) => {
await runRegistryAction(
"setup-command",
async () => {
const payload = await workspaceAIWorkspaceService.updateExecutor(workspaceSlug, executorId, input);
await updateRegistry(payload);
const setup = await workspaceAIWorkspaceService.createAgentSetupCommand(workspaceSlug, executorId, {
port,
opsWorkspaceSlug,
opsProjectId: selectedProjectId,
});
const command = String(setup.install?.command || "").trim();
if (!command) throw new Error("setup_command_empty");
if (!navigator.clipboard?.writeText) throw new Error("clipboard_unavailable");
await navigator.clipboard.writeText(command);
},
"npm setup command скопирована"
);
},
[opsWorkspaceSlug, runRegistryAction, selectedProjectId, updateRegistry, workspaceSlug]
);
const createThread = async () => {
try {
setThreadError("");
@@ -2236,6 +2259,7 @@ export function AIWorkspaceProductConsole({ open, workspaceSlug, onClose }: TAIW
onDelete={deleteExecutor}
onOpsWorkspaceChange={setSelectedOpsWorkspaceSlug}
onProjectChange={setSelectedProjectId}
onCopySetupCommand={copySetupCommand}
onDownloadAgent={downloadAgent}
getWindowsAgentInstallerUrl={(executorId, options) =>
workspaceAIWorkspaceService.getWindowsAgentInstallerUrl(workspaceSlug, executorId, {
@@ -68,6 +68,7 @@ type TAIWorkspaceProductSettingsModalProps = {
onDelete: (executorId: string) => Promise<TAIWorkspaceExecutorListResponse | null>;
onOpsWorkspaceChange: (workspaceSlug: string) => void;
onProjectChange: (projectId: string) => void;
onCopySetupCommand: (executorId: string, input: TAIWorkspaceExecutorInput, port: string) => Promise<void>;
onDownloadAgent: (executorId: string, input: TAIWorkspaceExecutorInput, port: string) => Promise<void>;
getWindowsAgentInstallerUrl: (
executorId: string,
@@ -324,6 +325,7 @@ export function AIWorkspaceProductSettingsModal({
onDelete,
onOpsWorkspaceChange,
onProjectChange,
onCopySetupCommand,
onDownloadAgent,
getWindowsAgentInstallerUrl,
}: TAIWorkspaceProductSettingsModalProps) {
@@ -450,6 +452,11 @@ export function AIWorkspaceProductSettingsModal({
await onDownloadAgent(editingExecutor.id, toInput(draft), draft.agentPort || DEFAULT_WINDOWS_AGENT_PORT);
};
const copySetupCommand = async () => {
if (!editingExecutor) return;
await onCopySetupCommand(editingExecutor.id, toInput(draft), draft.agentPort || DEFAULT_WINDOWS_AGENT_PORT);
};
const activeCheckDetails = activeExecutor
? [formatCheckTime(activeExecutor.lastSeenAt), activeExecutor.statusDetail].filter(Boolean).join(" · ")
: "";
@@ -696,18 +703,26 @@ export function AIWorkspaceProductSettingsModal({
placeholder="XXXX-XXXX-XXXX"
/>
</label>
<button
type="button"
className="modal-btn ai-settings-download ai-settings-inline-download btn-primary"
disabled={isBusy}
onClick={() => void copySetupCommand()}
>
Copy npx
</button>
<a
className="modal-btn ai-settings-download ai-settings-inline-download"
href={getWindowsAgentInstallerUrl(editingExecutor.id)}
onClick={downloadAgent}
download
>
Скачать агент
Legacy .ps1
</a>
</div>
) : draft.connectionMode === "hub" ? (
<div className="ai-settings-check-note">
После сохранения общий AI Workspace создаст pairing code и installer агента.
После сохранения общий AI Workspace создаст pairing code и npm setup command.
</div>
) : null}