Skip to content

Commit 422de0f

Browse files
authored
Merge pull request #97 from jan-dolejsi/planner_troubleshooting
Planner troubleshooting
2 parents 5d2e3f3 + c3ef347 commit 422de0f

26 files changed

+494
-545
lines changed

.eslintrc.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,5 +20,5 @@ module.exports = {
2020
"no-throw-literal": "warn",
2121
"semi": "off"
2222
},
23-
ignorePatterns: ["out/"]
23+
ignorePatterns: ["out/", "dist/", "node_modules/"]
2424
};

CHANGELOG.md

Lines changed: 45 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,48 @@
11
# PDDL support - What's new?
22

3+
## [2.22.0]
4+
5+
- 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.
6+
- 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.
7+
- When planner fails, custom `PlannerProvider` can offer trouble-shooting actions e.g. start/re-start the service, authenticate, ...
8+
- 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.
9+
- Planner configuration may specify the `cwd` current working directory.
10+
11+
### Engineering work
12+
13+
In order to give planner implementers more flexibility to create the planner and handle its lifecycle, the API exposed by this extension changed to:
14+
15+
```typescript
16+
import { planner } from "pddl-workspace";
17+
import { Event } from "vscode";
18+
19+
20+
export declare interface PddlExtensionApi {
21+
pddlWorkspace: PddlWorkspace;
22+
plannerExecutableFactory: PlannerExecutableFactory;
23+
}
24+
25+
/** Creates instances of the PlannerExecutable, so other extensions could wrap them. */
26+
export declare class PlannerExecutableFactory {
27+
/**
28+
* Creates new instance of `PlannerExecutable`.
29+
* @param plannerPath planner path
30+
* @param plannerRunConfiguration run configuration
31+
* @param providerConfiguration provider configuration
32+
* @returns planner executable that VS Code will call the `plan()` method on.
33+
*/
34+
createPlannerExecutable(plannerPath: string, plannerRunConfiguration: planner.PlannerExecutableRunConfiguration,
35+
providerConfiguration: planner.ProviderConfiguration): PlannerExecutable & planner.Planner;
36+
}
37+
38+
export declare interface PlannerExecutable {
39+
/**
40+
* Event fired when the planner process exits. The value is the exit code.
41+
*/
42+
onExited: Event<number>;
43+
}
44+
```
45+
346
## 2.21.8
447

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

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

1361-
[Unreleased]: https://github.com/jan-dolejsi/vscode-pddl/compare/v2.21.0...HEAD
1404+
[Unreleased]: https://github.com/jan-dolejsi/vscode-pddl/compare/v2.22.0...HEAD
1405+
[2.22.0]:https://github.com/jan-dolejsi/vscode-pddl/compare/v2.21.0...v2.22.0
13621406
[2.21.0]:https://github.com/jan-dolejsi/vscode-pddl/compare/v2.20.0...v2.21.0
13631407
[2.20.0]:https://github.com/jan-dolejsi/vscode-pddl/compare/v2.19.0...v2.20.0
13641408
[2.19.0]:https://github.com/jan-dolejsi/vscode-pddl/compare/v2.18.0...v2.19.0

README.md

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -141,9 +141,11 @@ The planner can be invoked in the context of a currently edited PDDL file. There
141141
There are multiple scenarios supported:
142142

143143
* if command is invoked on the domain file,
144-
* and if single corresponding problem file is open, the planner will run without asking further questions
145-
* and if multiple corresponding problem files are open, the list of applicable problem files will appear and the user will select one.
146-
* if command is invoked on a problem file, the domain file (if located in the same folder) will be selected automatically.
144+
* and if single corresponding problem file exists in the same directory, the planner will run without asking further questions
145+
* 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.
146+
* 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).
147+
148+
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.
147149

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

package.json

Lines changed: 17 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
"description": "Planning Domain Description Language support",
55
"author": "Jan Dolejsi",
66
"license": "MIT",
7-
"version": "2.21.8",
7+
"version": "2.22.0",
88
"publisher": "jan-dolejsi",
99
"engines": {
1010
"vscode": "^1.50.0",
@@ -469,6 +469,11 @@
469469
}
470470
],
471471
"explorer/context": [
472+
{
473+
"command": "pddl.planAndDisplayResult",
474+
"when": "resourceLangId == pddl",
475+
"group": "navigation"
476+
},
472477
{
473478
"command": "pddl.plan.compareNormalized",
474479
"when": "viewItem != folder && resourceLangId == plan",
@@ -703,6 +708,10 @@
703708
"type": "string",
704709
"description": "Path to a local executable."
705710
},
711+
"cwd": {
712+
"type": "string",
713+
"description": "Current working directory (optional). Normally, the extension sets the cwd of the process to the directory containing he domain or the problem."
714+
},
706715
"syntax": {
707716
"type": "string",
708717
"description": "Command-line syntax structure.",
@@ -998,22 +1007,23 @@
9981007
"test": "npm run test:unit && npm run test:integration"
9991008
},
10001009
"dependencies": {
1001-
"ai-planning-val": "^2.6.2",
1010+
"ai-planning-val": "^2.7.1",
10021011
"await-notify": "^1.0.1",
10031012
"body-parser": "^1.19.0",
1004-
"events": "^3.1.0",
1013+
"events": "^3.3.0",
10051014
"express": "^4.17.1",
1006-
"jsonc-parser": "^2.2.1",
1015+
"jsonc-parser": "^3.0.0",
10071016
"open": "^7.0.2",
1008-
"pddl-gantt": "^1.5.5",
1009-
"pddl-workspace": "^6.3.0",
1017+
"pddl-gantt": "^1.5.6",
1018+
"pddl-planning-service-client": "0.0.1",
1019+
"pddl-workspace": "^7.0.0",
10101020
"request": "^2.88.2",
10111021
"semver": "^7.1.3",
10121022
"tree-kill": "^1.2.2",
10131023
"vscode-debugadapter": "1.38.0",
10141024
"vscode-debugprotocol": "1.38.0",
10151025
"vscode-extension-telemetry-wrapper": "^0.5.0",
1016-
"vscode-uri": "^2.1.1"
1026+
"vscode-uri": "^3.0.2"
10171027
},
10181028
"devDependencies": {
10191029
"@types/adm-zip": "^0.4.32",

src/configuration/PlannersConfiguration.ts

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ import { PddlWorkspace, planner } from 'pddl-workspace';
1212
import { CommandPlannerProvider, SolveServicePlannerProvider, RequestServicePlannerProvider, ExecutablePlannerProvider, Popf, JavaPlannerProvider, Lpg } from './plannerConfigurations';
1313
import { CONF_PDDL, PDDL_PLANNER, EXECUTABLE_OR_SERVICE, EXECUTABLE_OPTIONS } from './configuration';
1414
import { instrumentOperationAsVsCodeCommand } from 'vscode-extension-telemetry-wrapper';
15-
import { showError, jsonNodeToRange, fileExists, isHttp } from '../utils';
15+
import { showError, jsonNodeToRange, fileOrFolderExists, isHttp } from '../utils';
1616

1717
export const CONF_PLANNERS = "planners";
1818
export const CONF_SELECTED_PLANNER = "selectedPlanner";
@@ -45,7 +45,7 @@ export class PlannersConfiguration {
4545
private plannerSelector: StatusBarItem | undefined;
4646
private plannerOutputSelector: StatusBarItem | undefined;
4747

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

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

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

166166
const target = this.toConfigurationTarget(scope);
@@ -212,8 +212,8 @@ export class PlannersConfiguration {
212212
[
213213
new ExecutablePlannerProvider(),
214214
new CommandPlannerProvider(),
215-
new SolveServicePlannerProvider(),
216-
new RequestServicePlannerProvider(),
215+
new SolveServicePlannerProvider(this.context.subscriptions),
216+
new RequestServicePlannerProvider(this.context.subscriptions),
217217
new Popf(),
218218
new Lpg(),
219219
new JavaPlannerProvider(),
@@ -546,11 +546,11 @@ export class PlannersConfiguration {
546546

547547
async toDocumentAndRange(setting: { fileUri: Uri | undefined; settingRootPath: (string | number)[] }, index?: number): Promise<{ settingsDoc: TextDocument; range: Range } | undefined> {
548548
if (!setting.fileUri) { return undefined; }
549-
const exists = await fileExists(setting.fileUri);
549+
const exists = await fileOrFolderExists(setting.fileUri);
550550
if (!exists) { return undefined; }
551551
const settingsText = await workspace.fs.readFile(setting.fileUri);
552552
const settingsRoot = parseTree(settingsText.toString());
553-
553+
if (!settingsRoot) { return undefined; }
554554
let path = setting.settingRootPath.concat([CONF_PDDL + '.' + CONF_PLANNERS]);
555555
if (index !== undefined) {
556556
path = path.concat([index]);

src/configuration/configuration.ts

Lines changed: 0 additions & 83 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,6 @@ const PARSER_SERVICE_AUTHENTICATION_S_TOKEN = PDDL_PARSER + '.serviceAuthenticat
2222

2323
export const PDDL_PLANNER = 'pddlPlanner';
2424
export const PLANNER_EXECUTABLE_OR_SERVICE = PDDL_PLANNER + '.' + EXECUTABLE_OR_SERVICE;
25-
const PLANNER_EXECUTABLE_OPTIONS = PDDL_PLANNER + '.' + EXECUTABLE_OPTIONS;
2625
const PLANNER_SERVICE_AUTHENTICATION_REFRESH_TOKEN = PDDL_PLANNER + '.serviceAuthenticationRefreshToken';
2726
const PLANNER_SERVICE_AUTHENTICATION_ACCESS_TOKEN = PDDL_PLANNER + '.serviceAuthenticationAccessToken';
2827
const PLANNER_SERVICE_AUTHENTICATION_S_TOKEN = PDDL_PLANNER + '.serviceAuthenticationSToken';
@@ -245,88 +244,6 @@ export class PddlConfiguration {
245244
configuration.update(PLANNER_SERVICE_AUTHENTICATION_S_TOKEN, stoken, target);
246245
}
247246

248-
/**
249-
* @deprecated
250-
*/
251-
async getPlannerPath(workingFolder?: Uri): Promise<string | undefined> {
252-
let plannerPath = workspace.getConfiguration(PDDL_PLANNER, workingFolder).get<string>(EXECUTABLE_OR_SERVICE);
253-
254-
if (!plannerPath) {
255-
plannerPath = await this.askNewPlannerPath();
256-
}
257-
258-
return plannerPath; // this may be 'undefined', if the user canceled
259-
}
260-
261-
/**
262-
* @deprecated
263-
*/
264-
async askNewPlannerPath(): Promise<string | undefined> {
265-
const existingValue = workspace.getConfiguration(PDDL_PLANNER, null).get<string>(EXECUTABLE_OR_SERVICE);
266-
267-
let newPlannerPath = await window.showInputBox({
268-
prompt: "Enter PDDL planner path local command or web service URL",
269-
placeHolder: `planner.exe OR java -jar c:\\planner.jar OR http://solver.planning.domains/solve`,
270-
value: existingValue,
271-
ignoreFocusOut: true
272-
});
273-
274-
if (newPlannerPath) {
275-
276-
newPlannerPath = newPlannerPath.trim().replace(/\\/g, '/');
277-
278-
// todo: validate that this planner actually works by sending a dummy request to it
279-
280-
const newPlannerScope = await this.askConfigurationScope();
281-
282-
if (!newPlannerScope) { return undefined; }
283-
const configurationToUpdate = this.getConfigurationForScope(newPlannerScope);
284-
if (!configurationToUpdate) { return undefined; }
285-
286-
if (!isHttp(newPlannerPath)) {
287-
this.askPlannerSyntax(newPlannerScope);
288-
}
289-
290-
// Update the value in the target
291-
configurationToUpdate.update(PLANNER_EXECUTABLE_OR_SERVICE, newPlannerPath, newPlannerScope.target);
292-
}
293-
294-
return newPlannerPath;
295-
}
296-
297-
/**
298-
* @deprecated
299-
*/
300-
async askPlannerSyntax(scope: ScopeQuickPickItem): Promise<string | undefined> {
301-
const existingValue = workspace.getConfiguration().get<string>(PLANNER_EXECUTABLE_OPTIONS);
302-
303-
const newPlannerOptions = await window.showInputBox({
304-
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].",
305-
placeHolder: `$(planner) $(options) $(domain) $(problem)`,
306-
value: existingValue,
307-
ignoreFocusOut: true
308-
});
309-
310-
if (newPlannerOptions) {
311-
// todo: validate that this planner actually works by sending a dummy request to it
312-
313-
const configurationToUpdate = this.getConfigurationForScope(scope);
314-
if (!configurationToUpdate) { return undefined; }
315-
316-
// Update the value in the target
317-
configurationToUpdate.update(PLANNER_EXECUTABLE_OPTIONS, newPlannerOptions, scope.target);
318-
}
319-
320-
return newPlannerOptions;
321-
}
322-
323-
/**
324-
* @deprecated
325-
*/
326-
getPlannerSyntax(): string | undefined {
327-
return workspace.getConfiguration().get<string>(PLANNER_EXECUTABLE_OPTIONS);
328-
}
329-
330247
getValueSeqPath(): string | undefined {
331248
const configuredPath = workspace.getConfiguration().get<string>(PLANNER_VALUE_SEQ_PATH);
332249
return ensureAbsoluteGlobalStoragePath(configuredPath, this.context);

0 commit comments

Comments
 (0)