Skip to content

Commit 2f79d0b

Browse files
committed
wip
1 parent 4423b3b commit 2f79d0b

File tree

6 files changed

+90
-18
lines changed

6 files changed

+90
-18
lines changed

extensions/positron-supervisor/src/KallichoreSession.ts

Lines changed: 15 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -330,18 +330,21 @@ export class KallichoreSession implements JupyterLanguageRuntimeSession {
330330
this._kernelSpec = kernelSpec;
331331
const varActions = await this.buildEnvVarActions(false);
332332

333-
// Prepare the working directory; use the workspace root if available,
334-
// otherwise the home directory
335-
let workingDir = vscode.workspace.workspaceFolders?.[0].uri.fsPath || os.homedir();
336-
337-
// If we have a notebook URI, use its parent directory as the working
338-
// directory instead. Note that not all notebooks have valid on-disk
339-
// URIs since they may be transient or not yet saved; for these, we fall
340-
// back to the workspace root or home directory.
341-
if (this.metadata.notebookUri?.fsPath) {
342-
const notebookPath = this.metadata.notebookUri.fsPath;
343-
if (fs.existsSync(notebookPath)) {
344-
workingDir = path.dirname(notebookPath);
333+
let workingDir = this.metadata.workingDirectory;
334+
335+
if (!workingDir) {
336+
// Use the workspace root if available, otherwise the home directory
337+
workingDir = vscode.workspace.workspaceFolders?.[0].uri.fsPath || os.homedir();
338+
339+
// If we have a notebook URI, use its parent directory as the working
340+
// directory instead. Note that not all notebooks have valid on-disk
341+
// URIs since they may be transient or not yet saved; for these, we fall
342+
// back to the workspace root or home directory.
343+
if (this.metadata.notebookUri?.fsPath) {
344+
const notebookPath = this.metadata.notebookUri.fsPath;
345+
if (fs.existsSync(notebookPath)) {
346+
workingDir = path.dirname(notebookPath);
347+
}
345348
}
346349
}
347350

src/positron-dts/positron.d.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -540,6 +540,9 @@ declare module 'positron' {
540540

541541
/** The URI of the notebook document associated with the session, if any */
542542
readonly notebookUri?: vscode.Uri;
543+
544+
/** The starting working directory of the session, if any */
545+
readonly workingDirectory?: string;
543546
}
544547

545548
/**

src/vs/workbench/contrib/notebook/browser/notebook.contribution.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,10 @@ import { IModelService } from '../../../../editor/common/services/model.js';
1515
import { ILanguageSelection, ILanguageService } from '../../../../editor/common/languages/language.js';
1616
import { ITextModelContentProvider, ITextModelService } from '../../../../editor/common/services/resolverService.js';
1717
import * as nls from '../../../../nls.js';
18+
// --- Start Positron ---
19+
// eslint-disable-next-line no-duplicate-imports
20+
import { ConfigurationScope } from '../../../../platform/configuration/common/configurationRegistry.js';
21+
// --- End Positron ---
1822
import { Extensions, IConfigurationPropertySchema, IConfigurationRegistry } from '../../../../platform/configuration/common/configurationRegistry.js';
1923
import { SyncDescriptor } from '../../../../platform/instantiation/common/descriptors.js';
2024
import { InstantiationType, registerSingleton } from '../../../../platform/instantiation/common/extensions.js';
@@ -1311,6 +1315,12 @@ configurationRegistry.registerConfiguration({
13111315
type: 'string',
13121316
default: '',
13131317
tags: ['notebookLayout']
1318+
},
1319+
[NotebookSetting.workingDirectory]: {
1320+
markdownDescription: nls.localize('notebook.workingDirectory', "Default working directory for notebook kernels. Supports variables like `${workspaceFolder}`. When empty, uses the notebook file's directory."),
1321+
type: 'string',
1322+
default: '',
1323+
scope: ConfigurationScope.RESOURCE
13141324
}
13151325
}
13161326
});

src/vs/workbench/contrib/notebook/common/notebookCommon.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1065,6 +1065,7 @@ export const NotebookSetting = {
10651065
outputBackupSizeLimit: 'notebook.backup.sizeLimit',
10661066
multiCursor: 'notebook.multiCursor.enabled',
10671067
markupFontFamily: 'notebook.markup.fontFamily',
1068+
workingDirectory: 'notebook.workingDirectory',
10681069
} as const;
10691070

10701071
export const enum CellStatusbarAlignment {

src/vs/workbench/services/runtimeSession/common/runtimeSession.ts

Lines changed: 58 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,9 @@ import { INotificationService, Severity } from '../../../../platform/notificatio
2727
import { localize } from '../../../../nls.js';
2828
import { UiClientInstance } from '../../languageRuntime/common/languageRuntimeUiClient.js';
2929
import { IWorkbenchEnvironmentService } from '../../environment/common/environmentService.js';
30+
import { IConfigurationResolverService } from '../../configurationResolver/common/configurationResolver.js';
31+
import { IWorkspaceContextService } from '../../../../platform/workspace/common/workspace.js';
32+
import { NotebookSetting } from '../../../contrib/notebook/common/notebookCommon.js';
3033

3134
/**
3235
* The maximum number of active sessions a user can have running at a time.
@@ -170,7 +173,9 @@ export class RuntimeSessionService extends Disposable implements IRuntimeSession
170173
@IExtensionService private readonly _extensionService: IExtensionService,
171174
@IStorageService private readonly _storageService: IStorageService,
172175
@IUpdateService private readonly _updateService: IUpdateService,
173-
@IWorkbenchEnvironmentService private readonly _environmentService: IWorkbenchEnvironmentService
176+
@IWorkbenchEnvironmentService private readonly _environmentService: IWorkbenchEnvironmentService,
177+
@IConfigurationResolverService private readonly _configurationResolverService: IConfigurationResolverService,
178+
@IWorkspaceContextService private readonly _workspaceContextService: IWorkspaceContextService
174179
) {
175180

176181
super();
@@ -387,6 +392,44 @@ export class RuntimeSessionService extends Disposable implements IRuntimeSession
387392
return Array.from(this._activeSessionsBySessionId.values());
388393
}
389394

395+
/**
396+
* Resolves the working directory configuration with variable substitution.
397+
*
398+
* @param notebookUri The URI of the notebook, if any, for resource-scoped configuration
399+
* @returns The resolved working directory or undefined if not configured
400+
*/
401+
private async resolveWorkingDirectory(notebookUri?: URI): Promise<string | undefined> {
402+
// Get the working directory configuration
403+
const configValue = this._configurationService.getValue<string>(
404+
NotebookSetting.workingDirectory,
405+
notebookUri ? { resource: notebookUri } : {}
406+
);
407+
408+
// If no configuration value is set, return undefined
409+
if (!configValue || configValue.trim() === '') {
410+
return undefined;
411+
}
412+
413+
// Get the workspace folder for variable resolution
414+
const workspaceFolder = notebookUri
415+
? this._workspaceContextService.getWorkspaceFolder(notebookUri)
416+
: this._workspaceContextService.getWorkspace().folders[0];
417+
418+
try {
419+
// Resolve variables in the configuration value
420+
const resolvedValue = await this._configurationResolverService.resolveAsync(
421+
workspaceFolder || undefined,
422+
configValue
423+
);
424+
425+
return resolvedValue;
426+
} catch (error) {
427+
// Log the error and return the original value as fallback
428+
this._logService.warn(`Failed to resolve working directory variables in '${configValue}':`, error);
429+
return configValue;
430+
}
431+
}
432+
390433
/**
391434
* Select a session for the provided runtime.
392435
*
@@ -466,6 +509,9 @@ export class RuntimeSessionService extends Disposable implements IRuntimeSession
466509
}
467510
}
468511

512+
// Resolve the working directory configuration
513+
const workingDirectory = await this.resolveWorkingDirectory(notebookUri);
514+
469515
// Wait for the selected runtime to start.
470516
await this.startNewRuntimeSession(
471517
runtime.runtimeId,
@@ -474,7 +520,8 @@ export class RuntimeSessionService extends Disposable implements IRuntimeSession
474520
notebookUri,
475521
source,
476522
startMode,
477-
true
523+
true,
524+
workingDirectory
478525
);
479526
}
480527

@@ -567,6 +614,7 @@ export class RuntimeSessionService extends Disposable implements IRuntimeSession
567614
* @param source The source of the request to start the runtime.
568615
* @param startMode The mode in which to start the runtime.
569616
* @param activate Whether to activate/focus the session after it is started.
617+
* @param workingDirectory The working directory to use for the session, if any.
570618
*/
571619
async startNewRuntimeSession(
572620
runtimeId: string,
@@ -575,7 +623,8 @@ export class RuntimeSessionService extends Disposable implements IRuntimeSession
575623
notebookUri: URI | undefined,
576624
source: string,
577625
startMode = RuntimeStartMode.Starting,
578-
activate: boolean): Promise<string> {
626+
activate: boolean,
627+
workingDirectory?: string): Promise<string> {
579628
// See if we are already starting the requested session. If we
580629
// are, return the promise that resolves when the session is ready to
581630
// use. This makes it possible for multiple requests to start the same
@@ -611,7 +660,7 @@ export class RuntimeSessionService extends Disposable implements IRuntimeSession
611660
this._logService.info(
612661
`Starting session for language runtime ` +
613662
`${formatLanguageRuntimeMetadata(languageRuntime)} (Source: ${source})`);
614-
return this.doCreateRuntimeSession(languageRuntime, sessionName, sessionMode, source, startMode, activate, notebookUri);
663+
return this.doCreateRuntimeSession(languageRuntime, sessionName, sessionMode, source, startMode, activate, notebookUri, workingDirectory);
615664
}
616665

617666
/**
@@ -1486,7 +1535,7 @@ export class RuntimeSessionService extends Disposable implements IRuntimeSession
14861535
}
14871536
}
14881537

1489-
return this.doCreateRuntimeSession(metadata, metadata.runtimeName, sessionMode, source, RuntimeStartMode.Starting, activate, notebookUri);
1538+
return this.doCreateRuntimeSession(metadata, metadata.runtimeName, sessionMode, source, RuntimeStartMode.Starting, activate, notebookUri, undefined);
14901539
}
14911540

14921541
/**
@@ -1499,6 +1548,7 @@ export class RuntimeSessionService extends Disposable implements IRuntimeSession
14991548
* @param startMode The mode in which to start the runtime.
15001549
* @param activate Whether to activate/focus the session after it is started.
15011550
* @param notebookDocument The notebook document to attach to the session, if any.
1551+
* @param workingDirectory The working directory to use for the session, if any.
15021552
*
15031553
* Returns a promise that resolves with the session ID when the runtime is
15041554
* ready to use.
@@ -1509,7 +1559,8 @@ export class RuntimeSessionService extends Disposable implements IRuntimeSession
15091559
source: string,
15101560
startMode: RuntimeStartMode,
15111561
activate: boolean,
1512-
notebookUri?: URI): Promise<string> {
1562+
notebookUri?: URI,
1563+
workingDirectory?: string): Promise<string> {
15131564
this.setStartingSessionMaps(sessionMode, runtimeMetadata, notebookUri);
15141565

15151566
// Create a promise that resolves when the runtime is ready to use, if there isn't already one.
@@ -1539,6 +1590,7 @@ export class RuntimeSessionService extends Disposable implements IRuntimeSession
15391590
sessionId,
15401591
sessionMode,
15411592
notebookUri,
1593+
workingDirectory,
15421594
createdTimestamp: Date.now(),
15431595
startReason: source
15441596
};

src/vs/workbench/services/runtimeSession/common/runtimeSessionService.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,9 @@ export interface IRuntimeSessionMetadata {
8585
/** The notebook associated with the session, if any */
8686
readonly notebookUri: URI | undefined;
8787

88+
/** The starting working directory of the session, if any */
89+
readonly workingDirectory?: string;
90+
8891
/**
8992
* A timestamp (in milliseconds since the Epoch) representing the time at
9093
* which the runtime session was created.

0 commit comments

Comments
 (0)