Skip to content

Commit

Permalink
Ask for user confirmation if he's creating a task package while havin…
Browse files Browse the repository at this point in the history
…g an agent package already as those don't really interact.
  • Loading branch information
fabioz committed Aug 8, 2024
1 parent 3bcecc9 commit cb3530f
Show file tree
Hide file tree
Showing 4 changed files with 53 additions and 31 deletions.
36 changes: 31 additions & 5 deletions sema4ai/vscode-client/src/activities.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ import {
InterpreterInfo,
IVaultInfo,
LibraryVersionInfoDict,
LocalAgentPackageMetadataInfo,
LocalPackageMetadataInfo,
PackageInfo,
RobotTemplate,
Expand All @@ -43,7 +44,7 @@ import { connectWorkspace } from "./vault";
import {
getPackageTargetDirectory,
isActionPackage,
isPackageDirectory,
verifyIfIsPackageDirectory,
refreshFilesExplorer,
verifyIfPathOkToCreatePackage,
} from "./common";
Expand Down Expand Up @@ -713,19 +714,24 @@ export async function createRobot() {
roboCommands.SEMA4AI_LIST_ROBOT_TEMPLATES_INTERNAL
);

let asyncListAgentPackages: Thenable<ActionResult<LocalAgentPackageMetadataInfo[]>> = commands.executeCommand(
roboCommands.SEMA4AI_LOCAL_LIST_AGENT_PACKAGES_INTERNAL
);

let ws: WorkspaceFolder | undefined = await askForWs();
if (!ws) {
// Operation cancelled.
return;
}

if (await isPackageDirectory(ws.uri)) {
if (await verifyIfIsPackageDirectory(ws.uri)) {
return;
}

// Unfortunately vscode does not have a good way to request multiple inputs at once,
// so, for now we're asking each at a separate step.
let actionResultListRobotTemplatesInternal: ActionResult<RobotTemplate[]> = await asyncListRobotTemplates;
let actionResultListAgents: ActionResult<LocalAgentPackageMetadataInfo[]> = await asyncListAgentPackages;

if (!actionResultListRobotTemplatesInternal.success) {
feedbackRobocorpCodeError("ACT_LIST_ROBOT_TEMPLATE");
Expand All @@ -741,6 +747,26 @@ export async function createRobot() {
return;
}

if (actionResultListAgents.success && actionResultListAgents.result.length > 0) {
const msgStart =
actionResultListAgents.result.length === 1
? "It seems there is an Agent Package"
: "It seems there are Agent Packages";
let confirmCreateTaskInAgent = await showSelectOneQuickPick(
[
{ action: "cancel", label: "Cancel", detail: "Cancel Task Package Creation" },
{ action: "proceed", label: "Proceed", detail: "Proceed with Task Package Creation" },
],
"",
`${msgStart} already created in the workspace and Task Packages
don't usually interact with Agent Packages.
Are you sure you want to create a Task Package instead of an Action Package whose actions can be used in an Agent?`
);
if (!confirmCreateTaskInAgent || confirmCreateTaskInAgent.action === "cancel") {
return;
}
}

let selectedItem = await window.showQuickPick(
availableTemplates.map((robotTemplate) => robotTemplate.description),
{
Expand Down Expand Up @@ -806,14 +832,14 @@ export async function createTaskOrActionPackage() {
const TASK_PACKAGE = "Task Package (Robot)";
const ACTION_PACKAGE = "Action Package";

const sidebarOrganizationSelection = getSelectedAgentPackageOrganization();
const sidebarAgentPackageOrganizationSelection = getSelectedAgentPackageOrganization();

/**
* Since this function is only called from the sidebar, we check if there is an organization
* selected in the Agent Packages section - if so, we want to allow the user to create Action Package in it.
*/
if (sidebarOrganizationSelection?.uri) {
await createActionPackage(sidebarOrganizationSelection.uri);
if (sidebarAgentPackageOrganizationSelection?.uri) {
await createActionPackage(sidebarAgentPackageOrganizationSelection.uri);

return;
}
Expand Down
19 changes: 7 additions & 12 deletions sema4ai/vscode-client/src/common.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
import * as roboCommands from "./robocorpCommands";
import * as vscode from "vscode";
import { commands, FileType, Uri, window, WorkspaceFolder } from "vscode";
import { ActionResult, LocalAgentPackageMetadataInfo, LocalPackageMetadataInfo } from "./protocols";
import { ActionResult, LocalAgentPackageMetadataInfo, LocalPackageMetadataInfo, PackageYamlName } from "./protocols";
import { logError } from "./channel";
import { feedbackRobocorpCodeError } from "./rcc";
import { join } from "path";
import { fileExists, uriExists } from "./files";

export type GetPackageTargetDirectoryMessages = {
title: string;
Expand Down Expand Up @@ -154,25 +155,19 @@ export function refreshFilesExplorer() {
}

export async function getPackageYamlNameFromDirectory(uri: Uri): Promise<string | null> {
let dirContents: [string, FileType][] = await vscode.workspace.fs.readDirectory(uri);

for (const element of dirContents) {
if (
element[0] === "robot.yaml" ||
element[0] === "conda.yaml" ||
element[0] === "package.yaml" ||
element[0] === "agent-spec.yaml"
) {
return element[0];
for (const name of [PackageYamlName.Agent, PackageYamlName.Action, PackageYamlName.Task, "conda.yaml"]) {
if (await uriExists(Uri.joinPath(uri, name))) {
return name;
}
}

return null;
}

export async function isPackageDirectory(wsUri: Uri, ignore: string[] = []): Promise<boolean> {
export async function verifyIfIsPackageDirectory(wsUri: Uri, ignore: string[] = []): Promise<boolean> {
// Check if we still don't have a Robot in this folder (i.e.: if we have a Robot in the workspace
// root already, we shouldn't create another Robot inside it).
// Note: shows error message to the user.
try {
const packageYaml = await getPackageYamlNameFromDirectory(wsUri);

Expand Down
25 changes: 13 additions & 12 deletions sema4ai/vscode-client/src/robo/actionPackage.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ import {
getPackageYamlNameFromDirectory,
getWorkspacePackages,
isActionPackage,
isPackageDirectory,
verifyIfIsPackageDirectory,
refreshFilesExplorer,
verifyIfPathOkToCreatePackage,
} from "../common";
Expand Down Expand Up @@ -257,8 +257,8 @@ export async function runActionFromActionPackage(
vscode.debug.startDebugging(undefined, debugConfiguration, debugSessionOptions);
}

async function getActionPackageTargetDir(ws: WorkspaceFolder): Promise<string | null> {
if (await isPackageDirectory(ws.uri, [PackageYamlName.Agent])) {
async function askActionPackageTargetDir(ws: WorkspaceFolder): Promise<string | null> {
if (await verifyIfIsPackageDirectory(ws.uri, [PackageYamlName.Agent])) {
return null;
}

Expand All @@ -278,17 +278,18 @@ async function getActionPackageTargetDir(ws: WorkspaceFolder): Promise<string |
packageInfo = workspacePackages.agentPackages[0];
useAgentPackage = true;
} else {
const insideAgentPackageLabel = "Inside specific Agent Package";
const insideAgentPackageLabel = "Inside Agent Package";

const actionPackageLevelSelection = await window.showQuickPick(
[
{
"label": "At a root level",
"detail": "Action Package will be created at workspace root level",
"label": insideAgentPackageLabel,
"detail": "Action Package will be created inside an Agent Package",
},
{
"label": insideAgentPackageLabel,
"detail": "Action Package will be created inside specific Agent Package",
"label": "Workspace (root) level",
"detail":
"Action Package will be created at workspace root level",
},
],
{
Expand Down Expand Up @@ -359,7 +360,7 @@ async function getActionPackageTargetDir(ws: WorkspaceFolder): Promise<string |
return targetDir || null;
}

export async function createActionPackage(selectedOrganizationUri?: vscode.Uri) {
export async function createActionPackage(parentFolderUri?: vscode.Uri) {
/* We make sure Action Server exists - if not, downloadOrGetActionServerLocation will ask user to download it. */
const actionServerLocation = await downloadOrGetActionServerLocation();
if (!actionServerLocation) {
Expand All @@ -374,14 +375,14 @@ export async function createActionPackage(selectedOrganizationUri?: vscode.Uri)

let targetDir = "";

if (selectedOrganizationUri) {
if (parentFolderUri) {
const name = await getPackageDirectoryName("Please provide the name for the Action Package folder name.");
if (!name) {
return;
}
targetDir = path.join(selectedOrganizationUri.fsPath, name);
targetDir = path.join(parentFolderUri.fsPath, name);
} else {
targetDir = await getActionPackageTargetDir(ws);
targetDir = await askActionPackageTargetDir(ws);

/* Operation cancelled or directory conflict detected. */
if (!targetDir) {
Expand Down
4 changes: 2 additions & 2 deletions sema4ai/vscode-client/src/robo/agentPackage.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import { getAgentCliLocation } from "../agentCli";
import { askForWs } from "../ask";
import {
getPackageTargetDirectory,
isPackageDirectory,
verifyIfIsPackageDirectory,
refreshFilesExplorer,
verifyIfPathOkToCreatePackage
} from "../common";
Expand All @@ -26,7 +26,7 @@ export const createAgentPackage = async (): Promise<void> => {
}

const ws = await askForWs();
const isWorkspacePackageDirectory = ws ? await isPackageDirectory(ws.uri) : null;
const isWorkspacePackageDirectory = ws ? await verifyIfIsPackageDirectory(ws.uri) : null;

if (!ws || isWorkspacePackageDirectory) {
return;
Expand Down

0 comments on commit cb3530f

Please sign in to comment.