From 032de904c62c5cab1a5e34906dc8169c1f394a24 Mon Sep 17 00:00:00 2001 From: Sam Atkins Date: Tue, 2 Apr 2024 16:42:50 +0100 Subject: [PATCH 1/3] Report platform name when running on Puter --- src/main_puter.js | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main_puter.js b/src/main_puter.js index 5fc4e42..ccd99ff 100644 --- a/src/main_puter.js +++ b/src/main_puter.js @@ -69,6 +69,7 @@ window.main_shell = async () => { config, puterSDK, externs: new Context({ puterSDK }), platform: new Context({ + name: 'puter', filesystem: CreateFilesystemProvider({ puterSDK }), drivers: CreateDriversProvider({ puterSDK }), env: CreateEnvProvider({ config }), From 3029cc1450e612f93844f5232b0f84244d2fc27e Mon Sep 17 00:00:00 2001 From: Sam Atkins Date: Wed, 3 Apr 2024 13:59:45 +0100 Subject: [PATCH 2/3] Use correct variable for API Origin Previously we were reading `config.source` and then removing the trailing slash. However, this doesn't include the port, which we use when running locally. `config['puter.api_origin']` is actually what we want, which does have the port if it's set, and doesn't include the trailing slash either. --- src/main_puter.js | 5 +---- src/puter-shell/main.js | 5 +---- 2 files changed, 2 insertions(+), 8 deletions(-) diff --git a/src/main_puter.js b/src/main_puter.js index ccd99ff..b27faf4 100644 --- a/src/main_puter.js +++ b/src/main_puter.js @@ -58,10 +58,7 @@ window.main_shell = async () => { if ( config['puter.auth.token'] ) { await puterSDK.setAuthToken(config['puter.auth.token']); } - const source_without_trailing_slash = - (config.source && config.source.replace(/\/$/, '')) - || 'https://api.puter.com'; - await puterSDK.setAPIOrigin(source_without_trailing_slash); + await puterSDK.setAPIOrigin(config['puter.api_origin']); const ptt = new XDocumentPTT(); await launchPuterShell(new Context({ diff --git a/src/puter-shell/main.js b/src/puter-shell/main.js index 8ccbf54..6c5675e 100644 --- a/src/puter-shell/main.js +++ b/src/puter-shell/main.js @@ -76,10 +76,7 @@ export const launchPuterShell = async (ctx) => { const sdkv2 = globalThis.puter; if ( ctx.platform.name !== 'node' ) { await sdkv2.setAuthToken(config['puter.auth.token']); - const source_without_trailing_slash = - (config.source && config.source.replace(/\/$/, '')) - || 'https://api.puter.com'; - await sdkv2.setAPIOrigin(source_without_trailing_slash); + await sdkv2.setAPIOrigin(config['puter.api_origin']); } // const commandProvider = new BuiltinCommandProvider(); From 2219ccba07063a772a186029a5bc79eea1c4a2b3 Mon Sep 17 00:00:00 2001 From: Sam Atkins Date: Tue, 2 Apr 2024 16:43:37 +0100 Subject: [PATCH 3/3] WIP: Add a PuterAppCommandProvider for launching apps from the terminal --- src/puter-shell/main.js | 3 + .../providers/PuterAppCommandProvider.js | 69 +++++++++++++++++++ 2 files changed, 72 insertions(+) create mode 100644 src/puter-shell/providers/PuterAppCommandProvider.js 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; + } +}