Skip to content

Commit

Permalink
Merge pull request #97 from jan-dolejsi/planner_troubleshooting
Browse files Browse the repository at this point in the history
Planner troubleshooting
  • Loading branch information
jan-dolejsi authored Mar 14, 2021
2 parents 5d2e3f3 + c3ef347 commit 422de0f
Show file tree
Hide file tree
Showing 26 changed files with 494 additions and 545 deletions.
2 changes: 1 addition & 1 deletion .eslintrc.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,5 +20,5 @@ module.exports = {
"no-throw-literal": "warn",
"semi": "off"
},
ignorePatterns: ["out/"]
ignorePatterns: ["out/", "dist/", "node_modules/"]
};
46 changes: 45 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,48 @@
# PDDL support - What's new?

## [2.22.0]

- When one or two PDDL files (i.e. domain and/or problem) are selected in the File Explorer and the context menu includes the _PDDL: Run the planner and display the plan_ command. This is extra helpful, when the domain and problem files are in different folders.
- When planner fails, the correct 're-configure planner' action is used (currently it opens the Overview Page). Till now, the UI was offering an obsolete planner re-configuration option.
- When planner fails, custom `PlannerProvider` can offer trouble-shooting actions e.g. start/re-start the service, authenticate, ...
- Planning servers (those planner configurations that populate the `url` property), may also specify the `path` property, which is assumed to be a program/script that starts the service that serves the `url`. The extension now offers to start the service.
- Planner configuration may specify the `cwd` current working directory.

### Engineering work

In order to give planner implementers more flexibility to create the planner and handle its lifecycle, the API exposed by this extension changed to:

```typescript
import { planner } from "pddl-workspace";
import { Event } from "vscode";


export declare interface PddlExtensionApi {
pddlWorkspace: PddlWorkspace;
plannerExecutableFactory: PlannerExecutableFactory;
}

/** Creates instances of the PlannerExecutable, so other extensions could wrap them. */
export declare class PlannerExecutableFactory {
/**
* Creates new instance of `PlannerExecutable`.
* @param plannerPath planner path
* @param plannerRunConfiguration run configuration
* @param providerConfiguration provider configuration
* @returns planner executable that VS Code will call the `plan()` method on.
*/
createPlannerExecutable(plannerPath: string, plannerRunConfiguration: planner.PlannerExecutableRunConfiguration,
providerConfiguration: planner.ProviderConfiguration): PlannerExecutable & planner.Planner;
}

export declare interface PlannerExecutable {
/**
* Event fired when the planner process exits. The value is the exit code.
*/
onExited: Event<number>;
}
```

## 2.21.8

- replaced the planner output target icon for the search debugger
Expand Down Expand Up @@ -1358,7 +1401,8 @@ Note for open source contributors: all notable changes to the "pddl" extension w

Check [Keep a Changelog](http://keepachangelog.com/) for recommendations on how to structure this file.

[Unreleased]: https://github.com/jan-dolejsi/vscode-pddl/compare/v2.21.0...HEAD
[Unreleased]: https://github.com/jan-dolejsi/vscode-pddl/compare/v2.22.0...HEAD
[2.22.0]:https://github.com/jan-dolejsi/vscode-pddl/compare/v2.21.0...v2.22.0
[2.21.0]:https://github.com/jan-dolejsi/vscode-pddl/compare/v2.20.0...v2.21.0
[2.20.0]:https://github.com/jan-dolejsi/vscode-pddl/compare/v2.19.0...v2.20.0
[2.19.0]:https://github.com/jan-dolejsi/vscode-pddl/compare/v2.18.0...v2.19.0
Expand Down
8 changes: 5 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -141,9 +141,11 @@ The planner can be invoked in the context of a currently edited PDDL file. There
There are multiple scenarios supported:

* if command is invoked on the domain file,
* and if single corresponding problem file is open, the planner will run without asking further questions
* and if multiple corresponding problem files are open, the list of applicable problem files will appear and the user will select one.
* if command is invoked on a problem file, the domain file (if located in the same folder) will be selected automatically.
* and if single corresponding problem file exists in the same directory, the planner will run without asking further questions
* and if multiple corresponding problem files exist in the same directory, the list of applicable problem files will appear and the user will select one.
* if command is invoked on a problem file, the domain file (if located in the same folder) will be selected automatically (as long as it is unique).

To invoke the planner on domain/problem pair that are located in different directories, multi-select them both on the File Explorer tree and select the _PDDL: Run the planner and visualize the plan_ option from the context menu.

Domain, problem and plan/happenings files correspond to each other, if:

Expand Down
24 changes: 17 additions & 7 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.21.8",
"version": "2.22.0",
"publisher": "jan-dolejsi",
"engines": {
"vscode": "^1.50.0",
Expand Down Expand Up @@ -469,6 +469,11 @@
}
],
"explorer/context": [
{
"command": "pddl.planAndDisplayResult",
"when": "resourceLangId == pddl",
"group": "navigation"
},
{
"command": "pddl.plan.compareNormalized",
"when": "viewItem != folder && resourceLangId == plan",
Expand Down Expand Up @@ -703,6 +708,10 @@
"type": "string",
"description": "Path to a local executable."
},
"cwd": {
"type": "string",
"description": "Current working directory (optional). Normally, the extension sets the cwd of the process to the directory containing he domain or the problem."
},
"syntax": {
"type": "string",
"description": "Command-line syntax structure.",
Expand Down Expand Up @@ -998,22 +1007,23 @@
"test": "npm run test:unit && npm run test:integration"
},
"dependencies": {
"ai-planning-val": "^2.6.2",
"ai-planning-val": "^2.7.1",
"await-notify": "^1.0.1",
"body-parser": "^1.19.0",
"events": "^3.1.0",
"events": "^3.3.0",
"express": "^4.17.1",
"jsonc-parser": "^2.2.1",
"jsonc-parser": "^3.0.0",
"open": "^7.0.2",
"pddl-gantt": "^1.5.5",
"pddl-workspace": "^6.3.0",
"pddl-gantt": "^1.5.6",
"pddl-planning-service-client": "0.0.1",
"pddl-workspace": "^7.0.0",
"request": "^2.88.2",
"semver": "^7.1.3",
"tree-kill": "^1.2.2",
"vscode-debugadapter": "1.38.0",
"vscode-debugprotocol": "1.38.0",
"vscode-extension-telemetry-wrapper": "^0.5.0",
"vscode-uri": "^2.1.1"
"vscode-uri": "^3.0.2"
},
"devDependencies": {
"@types/adm-zip": "^0.4.32",
Expand Down
18 changes: 9 additions & 9 deletions src/configuration/PlannersConfiguration.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import { PddlWorkspace, planner } from 'pddl-workspace';
import { CommandPlannerProvider, SolveServicePlannerProvider, RequestServicePlannerProvider, ExecutablePlannerProvider, Popf, JavaPlannerProvider, Lpg } from './plannerConfigurations';
import { CONF_PDDL, PDDL_PLANNER, EXECUTABLE_OR_SERVICE, EXECUTABLE_OPTIONS } from './configuration';
import { instrumentOperationAsVsCodeCommand } from 'vscode-extension-telemetry-wrapper';
import { showError, jsonNodeToRange, fileExists, isHttp } from '../utils';
import { showError, jsonNodeToRange, fileOrFolderExists, isHttp } from '../utils';

export const CONF_PLANNERS = "planners";
export const CONF_SELECTED_PLANNER = "selectedPlanner";
Expand Down Expand Up @@ -45,7 +45,7 @@ export class PlannersConfiguration {
private plannerSelector: StatusBarItem | undefined;
private plannerOutputSelector: StatusBarItem | undefined;

constructor(context: ExtensionContext, private pddlWorkspace: PddlWorkspace) {
constructor(private context: ExtensionContext, private pddlWorkspace: PddlWorkspace) {
context.subscriptions.push(instrumentOperationAsVsCodeCommand(PDDL_ADD_PLANNER, () => this.createPlannerConfiguration().catch(showError)));
context.subscriptions.push(instrumentOperationAsVsCodeCommand(PDDL_GET_SELECTED_PLANNER, () => this.getSelectedPlanner()?.configuration));
context.subscriptions.push(instrumentOperationAsVsCodeCommand(PDDL_SELECT_PLANNER, async () => (await this.selectPlanner())?.configuration));
Expand Down Expand Up @@ -116,7 +116,7 @@ export class PlannersConfiguration {
}

const plannerProvider = this.pddlWorkspace.getPlannerRegistrar()
.getPlannerProvider({ kind: plannerConfiguration.configuration.kind });
.getPlannerProvider(new planner.PlannerKind(plannerConfiguration.configuration.kind));

if (!plannerProvider) {
new Error(`Planner provider for '${plannerConfiguration.configuration.kind}' is not currently available. Are you missing an extension?`);
Expand Down Expand Up @@ -159,8 +159,8 @@ export class PlannersConfiguration {
const config = workspace.getConfiguration(PDDL_PLANNER, workspaceFolder);
const migratedPlanner = isHttp(legacyPlanner)
? legacyPlanner.endsWith('/solve')
? new SolveServicePlannerProvider().createPlannerConfiguration(legacyPlanner)
: new RequestServicePlannerProvider().createPlannerConfiguration(legacyPlanner)
? new SolveServicePlannerProvider([]).createPlannerConfiguration(legacyPlanner)
: new RequestServicePlannerProvider([]).createPlannerConfiguration(legacyPlanner)
: new CommandPlannerProvider().createPlannerConfiguration(legacyPlanner, legacySyntax);

const target = this.toConfigurationTarget(scope);
Expand Down Expand Up @@ -212,8 +212,8 @@ export class PlannersConfiguration {
[
new ExecutablePlannerProvider(),
new CommandPlannerProvider(),
new SolveServicePlannerProvider(),
new RequestServicePlannerProvider(),
new SolveServicePlannerProvider(this.context.subscriptions),
new RequestServicePlannerProvider(this.context.subscriptions),
new Popf(),
new Lpg(),
new JavaPlannerProvider(),
Expand Down Expand Up @@ -546,11 +546,11 @@ export class PlannersConfiguration {

async toDocumentAndRange(setting: { fileUri: Uri | undefined; settingRootPath: (string | number)[] }, index?: number): Promise<{ settingsDoc: TextDocument; range: Range } | undefined> {
if (!setting.fileUri) { return undefined; }
const exists = await fileExists(setting.fileUri);
const exists = await fileOrFolderExists(setting.fileUri);
if (!exists) { return undefined; }
const settingsText = await workspace.fs.readFile(setting.fileUri);
const settingsRoot = parseTree(settingsText.toString());

if (!settingsRoot) { return undefined; }
let path = setting.settingRootPath.concat([CONF_PDDL + '.' + CONF_PLANNERS]);
if (index !== undefined) {
path = path.concat([index]);
Expand Down
83 changes: 0 additions & 83 deletions src/configuration/configuration.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@ const PARSER_SERVICE_AUTHENTICATION_S_TOKEN = PDDL_PARSER + '.serviceAuthenticat

export const PDDL_PLANNER = 'pddlPlanner';
export const PLANNER_EXECUTABLE_OR_SERVICE = PDDL_PLANNER + '.' + EXECUTABLE_OR_SERVICE;
const PLANNER_EXECUTABLE_OPTIONS = PDDL_PLANNER + '.' + EXECUTABLE_OPTIONS;
const PLANNER_SERVICE_AUTHENTICATION_REFRESH_TOKEN = PDDL_PLANNER + '.serviceAuthenticationRefreshToken';
const PLANNER_SERVICE_AUTHENTICATION_ACCESS_TOKEN = PDDL_PLANNER + '.serviceAuthenticationAccessToken';
const PLANNER_SERVICE_AUTHENTICATION_S_TOKEN = PDDL_PLANNER + '.serviceAuthenticationSToken';
Expand Down Expand Up @@ -245,88 +244,6 @@ export class PddlConfiguration {
configuration.update(PLANNER_SERVICE_AUTHENTICATION_S_TOKEN, stoken, target);
}

/**
* @deprecated
*/
async getPlannerPath(workingFolder?: Uri): Promise<string | undefined> {
let plannerPath = workspace.getConfiguration(PDDL_PLANNER, workingFolder).get<string>(EXECUTABLE_OR_SERVICE);

if (!plannerPath) {
plannerPath = await this.askNewPlannerPath();
}

return plannerPath; // this may be 'undefined', if the user canceled
}

/**
* @deprecated
*/
async askNewPlannerPath(): Promise<string | undefined> {
const existingValue = workspace.getConfiguration(PDDL_PLANNER, null).get<string>(EXECUTABLE_OR_SERVICE);

let newPlannerPath = await window.showInputBox({
prompt: "Enter PDDL planner path local command or web service URL",
placeHolder: `planner.exe OR java -jar c:\\planner.jar OR http://solver.planning.domains/solve`,
value: existingValue,
ignoreFocusOut: true
});

if (newPlannerPath) {

newPlannerPath = newPlannerPath.trim().replace(/\\/g, '/');

// todo: validate that this planner actually works by sending a dummy request to it

const newPlannerScope = await this.askConfigurationScope();

if (!newPlannerScope) { return undefined; }
const configurationToUpdate = this.getConfigurationForScope(newPlannerScope);
if (!configurationToUpdate) { return undefined; }

if (!isHttp(newPlannerPath)) {
this.askPlannerSyntax(newPlannerScope);
}

// Update the value in the target
configurationToUpdate.update(PLANNER_EXECUTABLE_OR_SERVICE, newPlannerPath, newPlannerScope.target);
}

return newPlannerPath;
}

/**
* @deprecated
*/
async askPlannerSyntax(scope: ScopeQuickPickItem): Promise<string | undefined> {
const existingValue = workspace.getConfiguration().get<string>(PLANNER_EXECUTABLE_OPTIONS);

const newPlannerOptions = await window.showInputBox({
prompt: "In case you use command line switches and options, override the default syntax. For more info, see (the wiki)[https://github.com/jan-dolejsi/vscode-pddl/wiki/Configuring-the-PDDL-planner].",
placeHolder: `$(planner) $(options) $(domain) $(problem)`,
value: existingValue,
ignoreFocusOut: true
});

if (newPlannerOptions) {
// todo: validate that this planner actually works by sending a dummy request to it

const configurationToUpdate = this.getConfigurationForScope(scope);
if (!configurationToUpdate) { return undefined; }

// Update the value in the target
configurationToUpdate.update(PLANNER_EXECUTABLE_OPTIONS, newPlannerOptions, scope.target);
}

return newPlannerOptions;
}

/**
* @deprecated
*/
getPlannerSyntax(): string | undefined {
return workspace.getConfiguration().get<string>(PLANNER_EXECUTABLE_OPTIONS);
}

getValueSeqPath(): string | undefined {
const configuredPath = workspace.getConfiguration().get<string>(PLANNER_VALUE_SEQ_PATH);
return ensureAbsoluteGlobalStoragePath(configuredPath, this.context);
Expand Down
Loading

0 comments on commit 422de0f

Please sign in to comment.