feat(workspace-terminal): use environment shell command
This commit is contained in:
@@ -1,5 +1,11 @@
|
||||
import * as webcontainer from '@tempfix/webcontainer__api';
|
||||
import type { IExecutionEnvironment, IFileEntry, IFileWatcher, IProcessHandle } from '../interfaces/IExecutionEnvironment.js';
|
||||
import type {
|
||||
IExecutionEnvironment,
|
||||
IFileEntry,
|
||||
IFileWatcher,
|
||||
IProcessHandle,
|
||||
IShellCommand,
|
||||
} from '../interfaces/IExecutionEnvironment.js';
|
||||
|
||||
/**
|
||||
* WebContainer-based execution environment.
|
||||
@@ -154,6 +160,14 @@ export class WebContainerEnvironment implements IExecutionEnvironment {
|
||||
};
|
||||
}
|
||||
|
||||
public getShellCommand(): IShellCommand {
|
||||
return {
|
||||
command: 'jsh',
|
||||
label: 'jsh',
|
||||
prompt: '~/',
|
||||
};
|
||||
}
|
||||
|
||||
// ============ WebContainer-specific methods ============
|
||||
|
||||
/**
|
||||
|
||||
@@ -29,6 +29,17 @@ export interface IProcessHandle {
|
||||
kill(): void;
|
||||
}
|
||||
|
||||
export interface IShellCommand {
|
||||
/** Executable to start for an interactive shell session. */
|
||||
command: string;
|
||||
/** Optional command arguments. */
|
||||
args?: string[];
|
||||
/** Optional display label for terminal tabs. */
|
||||
label?: string;
|
||||
/** Optional prompt marker used for setup commands. */
|
||||
prompt?: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* Abstract execution environment interface.
|
||||
* Implementations can target WebContainer (browser), Backend API (server), or Mock (testing).
|
||||
@@ -93,12 +104,18 @@ export interface IExecutionEnvironment {
|
||||
|
||||
/**
|
||||
* Spawn a new process
|
||||
* @param command - Command to run (e.g., 'jsh', 'node', 'npm')
|
||||
* @param command - Command to run (e.g., 'node', 'npm')
|
||||
* @param args - Optional arguments
|
||||
* @returns Process handle with I/O streams
|
||||
*/
|
||||
spawn(command: string, args?: string[]): Promise<IProcessHandle>;
|
||||
|
||||
/**
|
||||
* Return the environment-native interactive shell command.
|
||||
* Implementations should provide this when terminal shells need a specific executable.
|
||||
*/
|
||||
getShellCommand?(): IShellCommand | Promise<IShellCommand>;
|
||||
|
||||
// ============ Lifecycle ============
|
||||
|
||||
/**
|
||||
|
||||
+21
-4
@@ -12,7 +12,7 @@ import * as domtools from '@design.estate/dees-domtools';
|
||||
|
||||
import type { Terminal } from 'xterm';
|
||||
import { themeDefaultStyles } from '../../00theme.js';
|
||||
import type { IExecutionEnvironment } from '../../00group-runtime/index.js';
|
||||
import type { IExecutionEnvironment, IShellCommand } from '../../00group-runtime/index.js';
|
||||
import { WebContainerEnvironment } from '../../00group-runtime/index.js';
|
||||
import '../../00group-utility/dees-icon/dees-icon.js';
|
||||
import '../../00group-feedback/dees-actionbar/dees-actionbar.js';
|
||||
@@ -660,6 +660,22 @@ export class DeesWorkspaceTerminal extends DeesElement {
|
||||
}
|
||||
}
|
||||
|
||||
private async getShellCommand(): Promise<IShellCommand> {
|
||||
if (this.executionEnvironment && !this.executionEnvironment.ready) {
|
||||
await this.executionEnvironment.init();
|
||||
}
|
||||
|
||||
if (this.executionEnvironment?.getShellCommand) {
|
||||
return await this.executionEnvironment.getShellCommand();
|
||||
}
|
||||
|
||||
return {
|
||||
command: 'jsh',
|
||||
label: 'jsh',
|
||||
prompt: '~/',
|
||||
};
|
||||
}
|
||||
|
||||
private handleProcessExit(tabId: string, exitCode: number): void {
|
||||
const tab = this.tabManager.getTab(tabId);
|
||||
if (!tab) return;
|
||||
@@ -723,10 +739,11 @@ export class DeesWorkspaceTerminal extends DeesElement {
|
||||
* Create a new shell tab
|
||||
*/
|
||||
public async createShellTab(label?: string): Promise<string> {
|
||||
const shellCommand = await this.getShellCommand();
|
||||
const tab = this.tabManager.createTab(
|
||||
{
|
||||
type: 'shell',
|
||||
label: label || `bash ${this.tabManager.getTabCount() + 1}`,
|
||||
label: label || `${shellCommand.label || shellCommand.command} ${this.tabManager.getTabCount() + 1}`,
|
||||
closeable: this.tabManager.getTabCount() > 0, // First tab not closeable
|
||||
},
|
||||
this.isBright
|
||||
@@ -739,11 +756,11 @@ export class DeesWorkspaceTerminal extends DeesElement {
|
||||
|
||||
// Wait for DOM update then spawn shell
|
||||
await this.updateComplete;
|
||||
await this.spawnProcessForTab(tab, 'jsh');
|
||||
await this.spawnProcessForTab(tab, shellCommand.command, shellCommand.args || []);
|
||||
|
||||
// Run setup command if this is the first tab
|
||||
if (this.tabManager.getTabCount() === 1 && this.setupCommand) {
|
||||
await this.waitForPrompt(tab.terminal, '~/');
|
||||
await this.waitForPrompt(tab.terminal, shellCommand.prompt || '~/');
|
||||
if (tab.inputWriter) {
|
||||
tab.inputWriter.write(this.setupCommand);
|
||||
}
|
||||
|
||||
@@ -6,7 +6,7 @@ import type { IProcessHandle } from '../../00group-runtime/index.js';
|
||||
* Type of terminal tab based on its source/purpose
|
||||
*/
|
||||
export type TTerminalTabType =
|
||||
| 'shell' // Default interactive shell (jsh)
|
||||
| 'shell' // Environment-native interactive shell
|
||||
| 'script' // Script from package.json
|
||||
| 'package-update' // Package update process
|
||||
| 'custom'; // External process from API
|
||||
@@ -75,7 +75,7 @@ export interface ICreateTerminalTabOptions {
|
||||
/** Whether the tab can be closed (default: true for non-shell) */
|
||||
closeable?: boolean;
|
||||
|
||||
/** Command to spawn (default: 'jsh' for shell type) */
|
||||
/** Command to spawn (shell type uses the execution environment shell by default) */
|
||||
command?: string;
|
||||
|
||||
/** Command arguments */
|
||||
|
||||
Reference in New Issue
Block a user