diff --git a/src/puter-shell/main.js b/src/puter-shell/main.js index 6c5675e..bef08d6 100644 --- a/src/puter-shell/main.js +++ b/src/puter-shell/main.js @@ -35,6 +35,7 @@ import { BetterReader } from 'dev-pty'; import { MultiWriter } from '../ansi-shell/ioutil/MultiWriter.js'; import { CompositeCommandProvider } from './providers/CompositeCommandProvider.js'; import { ScriptCommandProvider } from './providers/ScriptCommandProvider.js'; +import { PuterAppCommandProvider } from './providers/PuterAppCommandProvider.js'; const argparser_registry = { [SimpleArgParser.name]: SimpleArgParser @@ -82,6 +83,8 @@ export const launchPuterShell = async (ctx) => { // const commandProvider = new BuiltinCommandProvider(); const commandProvider = new CompositeCommandProvider([ new BuiltinCommandProvider(), + // PuterAppCommandProvider is only usable on Puter + ...(ctx.platform.name === 'puter' ? [new PuterAppCommandProvider()] : []), new ScriptCommandProvider(), ]); diff --git a/src/puter-shell/providers/PuterAppCommandProvider.js b/src/puter-shell/providers/PuterAppCommandProvider.js new file mode 100644 index 0000000..c72cbe3 --- /dev/null +++ b/src/puter-shell/providers/PuterAppCommandProvider.js @@ -0,0 +1,69 @@ +/* + * Copyright (C) 2024 Puter Technologies Inc. + * + * This file is part of Phoenix Shell. + * + * Phoenix Shell is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ +const BUILTIN_APPS = [ + 'explorer', +]; + +function launch(name, path) { + return { + name, + path, + // TODO: Parameters and options? + async execute(ctx) { + console.log(`%cTrying to launch app: ${name}`, 'color:green'); + const args = {}; // TODO: Passed-in parameters and options would go here + await puter.ui.launchApp(name, args); + } + }; +} + +export class PuterAppCommandProvider { + + async lookup (id) { + // Built-in apps will not be returned by the fetch query below, so we handle them separately. + if (BUILTIN_APPS.includes(id)) { + return launch(id, 'Built-in Puter app'); + } + + const request = await fetch(`${puter.APIOrigin}/drivers/call`, { + "headers": { + "Content-Type": "application/json", + "Authorization": `Bearer ${puter.authToken}`, + }, + "body": JSON.stringify({ interface: 'puter-apps', method: 'read', args: { id: { name: id } } }), + "method": "POST", + }); + + const { success, result } = await request.json(); + + if (!success) return; + + const { name, index_url } = result; + return launch(name, index_url); + } + + // Only a single Puter app can match a given name + async lookupAll (...a) { + const result = await this.lookup(...a); + if ( result ) { + return [ result ]; + } + return undefined; + } +}