Skip to content

Commit

Permalink
import planner url, upgade from preview, v2.28.1
Browse files Browse the repository at this point in the history
  • Loading branch information
jan-dolejsi committed Jul 27, 2024
1 parent 759cfdc commit 37ea303
Show file tree
Hide file tree
Showing 6 changed files with 98 additions and 23 deletions.
4 changes: 2 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 3 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
"description": "Planning Domain Description Language support",
"author": "Jan Dolejsi",
"license": "MIT",
"version": "2.28.0",
"version": "2.28.1",
"publisher": "jan-dolejsi",
"engines": {
"vscode": "^1.69.0",
Expand Down Expand Up @@ -675,7 +675,7 @@
"markdownDescription": "The PDDL Extension can work with multiple **PDDL Planners**. It has a notion of planner _kind_. The _kind_s are defined by the PDDL Extension, or by other extensions injecting in their _Planner Providers_. For more information, see [Configuring the PDDL planner](https://github.com/jan-dolejsi/vscode-pddl/wiki/Configuring-the-PDDL-planner) wiki page.",
"default": [
{
"kind": "PLANNING_AS_A_SERVICE_PREVIEW",
"kind": "PLANNING_AS_A_SERVICE",
"url": "https://solver.planning.domains:5001/package",
"title": "Planning as a service (solver.planning.domains)",
"canConfigure": false
Expand All @@ -697,7 +697,7 @@
"COMMAND",
"SERVICE_SYNC",
"SERVICE_ASYNC",
"PLANNING_AS_A_SERVICE_PREVIEW"
"PLANNING_AS_A_SERVICE"
]
},
"title": {
Expand Down
48 changes: 41 additions & 7 deletions src/configuration/PlannersConfiguration.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,11 @@ import * as path from 'path';
import { parseTree, findNodeAtLocation } from 'jsonc-parser';
import { window, commands, workspace, ConfigurationTarget, QuickPickItem, ExtensionContext, StatusBarItem, StatusBarAlignment, Uri, Range, WorkspaceFolder, TextDocument, ViewColumn, env } from 'vscode';
import { PddlWorkspace, planner } from 'pddl-workspace';
import { CommandPlannerProvider, SolveServicePlannerProvider, RequestServicePlannerProvider, ExecutablePlannerProvider, Popf, JavaPlannerProvider, Lpg, Pddl4jProvider, PlanningAsAServiceProvider, PlanutilsServerProvider, PythonPlannerProvider, NodeJsPlannerProvider, SchedulingServiceProvider } from './plannerConfigurations';
import {
CommandPlannerProvider, SolveServicePlannerProvider, RequestServicePlannerProvider, ExecutablePlannerProvider,
Popf, JavaPlannerProvider, Lpg, Pddl4jProvider, PlanningAsAServiceProvider, PlanutilsServerProvider,
PythonPlannerProvider, NodeJsPlannerProvider, SchedulingServiceProvider, PreviewPlanningAsAServiceProvider
} from './plannerConfigurations';
import { CONF_PDDL, PDDL_PLANNER, EXECUTABLE_OR_SERVICE, EXECUTABLE_OPTIONS } from './configuration';
import { instrumentOperationAsVsCodeCommand } from 'vscode-extension-telemetry-wrapper';
import { showError, jsonNodeToRange, isHttp } from '../utils';
Expand Down Expand Up @@ -136,6 +140,11 @@ export class PlannersConfiguration {
}

async migrateLegacyConfiguration(workspaceFolder?: WorkspaceFolder): Promise<void> {
await this.migrateLegacySelectedPlannerConfiguration(workspaceFolder);
await this.migrateLegacyPaaSPreviews(workspaceFolder);
}

async migrateLegacySelectedPlannerConfiguration(workspaceFolder?: WorkspaceFolder): Promise<void> {
const config = workspace.getConfiguration(PDDL_PLANNER, workspaceFolder);
const legacyPlannerInspect = config.inspect<string>(EXECUTABLE_OR_SERVICE);
const legacySyntaxInspect = config.inspect<string>(EXECUTABLE_OPTIONS);
Expand All @@ -158,11 +167,7 @@ export class PlannersConfiguration {

async migrateLegacyConfigurationInTarget(legacyPlanner: string, legacySyntax: string | undefined, scope: PlannerConfigurationScope, workspaceFolder?: WorkspaceFolder): Promise<void> {
const config = workspace.getConfiguration(PDDL_PLANNER, workspaceFolder);
const migratedPlanner = isHttp(legacyPlanner)
? legacyPlanner.endsWith('/solve')
? new SolveServicePlannerProvider([]).createPlannerConfiguration(legacyPlanner)
: new RequestServicePlannerProvider([]).createPlannerConfiguration(legacyPlanner)
: new CommandPlannerProvider().createPlannerConfiguration(legacyPlanner, legacySyntax);
const migratedPlanner = this.migrateLegacyPlannerConfigurationInTarget(legacyPlanner, legacySyntax);

const target = this.toConfigurationTarget(scope);

Expand All @@ -173,6 +178,35 @@ export class PlannersConfiguration {
console.log(`Migrated ${legacyPlanner} to ${newPlannerConfig.scope.toString()}:${newPlannerConfig.configuration.title}`);
}

private migrateLegacyPlannerConfigurationInTarget(legacyPlanner: string, legacySyntax: string | undefined): planner.PlannerConfiguration {
if (isHttp(legacyPlanner)) {
if (legacyPlanner.endsWith('/solve')) {
return new SolveServicePlannerProvider([]).createPlannerConfiguration(legacyPlanner);
} else if (legacyPlanner.endsWith('/package')) {
return new PlanningAsAServiceProvider([]).createPlannerConfiguration(legacyPlanner);
} else {
return new RequestServicePlannerProvider([]).createPlannerConfiguration(legacyPlanner);
}
} else {
return new CommandPlannerProvider().createPlannerConfiguration(legacyPlanner, legacySyntax);
}
}

async migrateLegacyPaaSPreviews(workspaceFolder: WorkspaceFolder | undefined): Promise<void> {
const planners = this.getPlanners(workspaceFolder);
const previewKind = new PreviewPlanningAsAServiceProvider([]).kind.kind;
const awaitables = planners
.filter(p => p.configuration.kind === previewKind)
.map(async p => await this.migrateLegacyPaaSPreview(p));
Promise.all(awaitables);
}

private async migrateLegacyPaaSPreview(config: ScopedPlannerConfiguration): Promise<void> {
config.configuration.kind = planner.WellKnownPlannerKind.PLANNING_AS_A_SERVICE.kind;
await this.savePlannerConfiguration(config.index, config.scope, config.configuration, this.toWorkspaceFolder(config));
console.log(`Migrated '${config.configuration.title}' to ${config.configuration.kind}`);
}

refreshStatusBar(): void {
if (!this.plannerSelector) {
return;
Expand Down Expand Up @@ -411,7 +445,7 @@ export class PlannersConfiguration {
for (const scope of PlannersConfiguration.SCOPES) {
// todo: get the planners for all scopes, then filter
const planners = this.getPlannersPerScope(scope, workingFolder);
if (!Array.isArray(planners)) { console.error(`Planners configuration for scope ${scope} is invalid: ${planners}`); continue; }
if (!Array.isArray(planners)) { console.error(`Planners configuration for scope ${scope} is invalid: `, planners); continue; }
const indexFound = planners.findIndex(p => p.title === selectedPlannerTitle);
if (indexFound > -1) {
return this.toScopedConfiguration(planners[indexFound], indexFound, scope, workingFolder);
Expand Down
5 changes: 3 additions & 2 deletions src/session/SessionRepository.ts
Original file line number Diff line number Diff line change
Expand Up @@ -241,7 +241,8 @@ export async function duplicateSession(session: SessionContent): Promise<string>
}

const SAVE_TABS_PLUGIN_NAME = "save-tabs";
const SOLVER_PLUGIN_NAME = "solver";
export const SOLVER_PLUGIN_NAME = "solver";
export const PLANNING_AS_A_SERVICE_PLUGIN_NAME = "planning-as-a-service-plugin";

/**
* Fetches session from the planning.domains server.
Expand Down Expand Up @@ -283,7 +284,7 @@ async function getRawSession(sessionConfiguration: SessionConfiguration): Promis
if (pluginsMatch = SESSION_PLUGINS_PATTERN.exec(sessionContent)) {
const rawPlugins = JSON.parse(pluginsMatch[1]);

[SAVE_TABS_PLUGIN_NAME, SOLVER_PLUGIN_NAME].forEach(pluginName => {
[SAVE_TABS_PLUGIN_NAME, SOLVER_PLUGIN_NAME, PLANNING_AS_A_SERVICE_PLUGIN_NAME].forEach(pluginName => {
if (rawPlugins.hasOwnProperty(pluginName)) {
plugins.set(pluginName, toRawSessionPlugin(pluginName, rawPlugins[pluginName]));
}
Expand Down
34 changes: 25 additions & 9 deletions src/session/SessionSourceControl.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,14 @@
* ------------------------------------------------------------------------------------------ */

import * as vscode from 'vscode';
import { SessionRepository, getSession, SessionContent, uploadSession, duplicateSession, checkSession } from './SessionRepository';
import { SessionRepository, getSession, SessionContent, uploadSession, duplicateSession, checkSession, PLANNING_AS_A_SERVICE_PLUGIN_NAME, SOLVER_PLUGIN_NAME } from './SessionRepository';
import * as path from 'path';
import { toFuzzyRelativeTime } from '../utils';
import { SessionConfiguration, saveConfiguration, SessionMode, toSessionConfiguration, CONFIGURATION_FILE } from './SessionConfiguration';
import { PDDL_PLANNER, EXECUTABLE_OR_SERVICE } from '../configuration/configuration';
import { CONF_PDDL } from '../configuration/configuration';
import { exists } from '../util/workspaceFs';
import { CONF_PLANNERS, CONF_SELECTED_PLANNER } from '../configuration/PlannersConfiguration';
import { PlanningAsAServiceProvider, SolveServicePlannerProvider } from '../configuration/plannerConfigurations';

/**
* Command for cloning a session to the local storage.
Expand Down Expand Up @@ -273,18 +275,32 @@ export class SessionSourceControl implements vscode.Disposable {
return await saveConfiguration(this.workspaceFolder.uri, this.session);
}

private static readonly SOLVER_PLUGIN = "solver";

/** Saves setting of eligible session plugins to workspace configuration. */
async saveWorkspaceSettings(): Promise<void> {
if (this.session.plugins.has(SessionSourceControl.SOLVER_PLUGIN)) {
const solver = this.session.plugins.get(SessionSourceControl.SOLVER_PLUGIN);
if (this.session.plugins.has(PLANNING_AS_A_SERVICE_PLUGIN_NAME)) {
const solver = this.session.plugins.get(PLANNING_AS_A_SERVICE_PLUGIN_NAME);
if (solver?.url !== "/plugins/featured/paas/plugin.js") { return; }

const solverUrl = solver.settings["PASURL"] + '/package';
const configuration = new PlanningAsAServiceProvider([]).createPlannerConfiguration(solverUrl);
configuration.title += ' - from session';

await vscode.workspace.getConfiguration(CONF_PDDL, this.workspaceFolder.uri)
.update(CONF_PLANNERS, [configuration], vscode.ConfigurationTarget.WorkspaceFolder);
await vscode.workspace.getConfiguration(CONF_PDDL, this.workspaceFolder.uri)
.update(CONF_SELECTED_PLANNER, configuration.title, vscode.ConfigurationTarget.WorkspaceFolder);
} else if (this.session.plugins.has(SOLVER_PLUGIN_NAME)) {
const solver = this.session.plugins.get(SOLVER_PLUGIN_NAME);
if (solver?.url !== "/plugins/solver.js") { return; }

const solverUrl = solver.settings["url"];
const solverUrl = solver.settings["url"] + "/solve";
const configuration = new SolveServicePlannerProvider([]).createPlannerConfiguration(solverUrl);
configuration.title += ' - from obsolete session';

// todo: this configuration is upgraded right away; move to the new planner configuration pattern
await vscode.workspace.getConfiguration(PDDL_PLANNER, this.workspaceFolder.uri).update(EXECUTABLE_OR_SERVICE, solverUrl + "/solve", vscode.ConfigurationTarget.WorkspaceFolder);
await vscode.workspace.getConfiguration(CONF_PDDL, this.workspaceFolder.uri)
.update(CONF_PLANNERS, [configuration], vscode.ConfigurationTarget.WorkspaceFolder);
await vscode.workspace.getConfiguration(CONF_PDDL, this.workspaceFolder.uri)
.update(CONF_SELECTED_PLANNER, configuration.title, vscode.ConfigurationTarget.WorkspaceFolder);
}
}

Expand Down
24 changes: 24 additions & 0 deletions src/test/suite/PlannerConfiguration.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import { plannersConfiguration, codePddlWorkspaceForTests } from '../../extensio
import { PlannerConfigurationScope, CONF_PLANNERS, CONF_SELECTED_PLANNER } from '../../configuration/PlannersConfiguration';
import { PDDL_PLANNER, EXECUTABLE_OR_SERVICE, EXECUTABLE_OPTIONS, CONF_PDDL } from '../../configuration/configuration';
import { fail } from 'assert';
import { PreviewPlanningAsAServiceProvider } from '../../configuration/plannerConfigurations';

suite('Planner configuration test', () => {

Expand Down Expand Up @@ -327,4 +328,27 @@ suite('Planner configuration test', () => {
expect(migratedPlanner.url).to.equal(executable);
expect(migratedPlanner.title).to.equal(executable);
});


test('Migrates deprecated planning-as-a-service configuration', async () => {
const executable = 'https://solver.planning.domains/solve';

// GIVEN
const legacyProvider = new PreviewPlanningAsAServiceProvider([]);
const legacyConfiguration = legacyProvider.createPlannerConfiguration('https://mock-as-a-service/');
await plannersConfiguration.addPlannerConfiguration(PlannerConfigurationScope.User, legacyConfiguration);
await workspace.getConfiguration(PDDL_PLANNER).update(EXECUTABLE_OR_SERVICE, executable, ConfigurationTarget.Global);

const previewConfigsBefore = plannersConfiguration.getPlanners().filter(p => p.configuration.kind === legacyProvider.kind.kind);

expect(previewConfigsBefore, 'preview configs before').to.have.length.greaterThanOrEqual(1);

// WHEN
await plannersConfiguration.migrateLegacyConfiguration();

// THEN
const previewConfigsAfter = plannersConfiguration.getPlanners().filter(p => p.configuration.kind === legacyProvider.kind.kind);
expect(previewConfigsAfter, 'preview configs after').to.have.length(previewConfigsBefore.length);
});

});

0 comments on commit 37ea303

Please sign in to comment.