Add file column to worker table and enable file path launching

This commit is contained in:
Nariman Jelveh
2025-08-03 18:24:02 -07:00
parent 80ccb2d48b
commit 8f18a841b3
8 changed files with 92 additions and 5 deletions
+1
View File
@@ -285,6 +285,7 @@
<tr>
<th><input type="checkbox" class="select-all-workers" style="width: 20px; height: 20px; margin-left:3px;"></th>
<th class="sort th-name" data-column="name" style="padding-left: 10px !important;">Worker<span class="sort-arrow sort-arrow-desc"></span><span class="sort-arrow sort-arrow-asc"></span></th>
<th class="sort th-file" data-column="file">File<span class="sort-arrow sort-arrow-desc"></span><span class="sort-arrow sort-arrow-asc"></span></th>
<th class="sort th-created sorted" data-column="created_at">Created<span class="sort-arrow sort-arrow-desc" style="display:inline;"></span><span class="sort-arrow sort-arrow-asc"></span></th>
<th></th>
</tr>
+16
View File
@@ -220,6 +220,7 @@ function generate_worker_card(worker) {
<input type="checkbox" class="worker-checkbox" data-worker-name="${worker.name}">
</td>
<td style="font-family: monospace; font-size: 14px; vertical-align: middle;">${worker.name}</td>
<td style="font-family: monospace; font-size: 14px; vertical-align: middle;"><span class="file-path" data-file-path="${html_encode(worker.file_path)}">${worker.file_path}</span></td>
<td style="font-size: 14px; vertical-align: middle;">${worker.created_at}</td>
<td style="vertical-align: middle;"><img class="options-icon options-icon-worker" data-worker-name="${worker.name}" src="./img/options.svg"></td>
</tr>
@@ -373,4 +374,19 @@ async function attempt_delete_worker(worker_name) {
}
}
$(document).on('click', '.file-path', function (e) {
e.preventDefault();
e.stopPropagation();
e.stopImmediatePropagation();
const file_path = $(this).attr('data-file-path');
if(file_path){
puter.ui.launchApp({
name: 'editor',
file_paths: [file_path],
});
}
})
export default init_workers;
+61 -4
View File
@@ -48,7 +48,8 @@ export class ExecService extends Service {
}
// This method is exposed to apps via IPCService.
async launchApp ({ app_name, args, pseudonym }, { ipc_context, msg_id } = {}) {
async launchApp ({ app_name, args, pseudonym, file_paths }, { ipc_context, msg_id } = {}) {
console.log('launchApp', { app_name, args, pseudonym, file_paths });
const app = ipc_context?.caller?.app;
const process = ipc_context?.caller?.process;
@@ -68,8 +69,8 @@ export class ExecService extends Service {
Object.assign(params, provider());
}
// The "body" of this method is in a separate file
const child_process = await launch_app({
// Handle file paths if provided and caller is in godmode
let launch_options = {
launched_by_exec_service: true,
name: app_name,
pseudonym,
@@ -80,7 +81,63 @@ export class ExecService extends Service {
...(connection ? {
parent_pseudo_id: connection.backward.uuid,
} : {}),
});
};
// Check if file_paths are provided and caller has godmode permissions
if (file_paths && Array.isArray(file_paths) && file_paths.length > 0 && process) {
console.log('file_paths', file_paths);
try {
// Get caller app info to check godmode status
const caller_app_name = process.name;
const caller_app_info = await window.get_apps(caller_app_name);
// Check if caller is in godmode
if (caller_app_info && caller_app_info.godmode === 1) {
this.log.info(`⚠️ GODMODE app ${caller_app_name} launching ${app_name} with files:`, file_paths);
// Get target app info to create file signatures
const target_app_info = await puter.apps.get(app_name);
// For the first file, create a file signature and set it up like opening a file
if (file_paths.length > 0) {
const first_file_path = file_paths[0];
try {
// Get file stats to verify it exists
const file_stat = await puter.fs.stat(first_file_path);
// Create file signature for the target app
const file_signature_result = await puter.fs.sign(target_app_info.uuid, {
path: first_file_path,
action: 'write'
});
// Set up launch options with file information
launch_options.file_signature = file_signature_result.items;
launch_options.file_path = first_file_path;
launch_options.token = file_signature_result.token;
// Add all file paths to args for the target app
launch_options.args.file_paths = file_paths;
} catch (file_error) {
this.log.warn(`Failed to process file ${first_file_path}:`, file_error);
// Continue with launch but without file signature
}
}
} else {
console.log(`⚠️ App ${caller_app_name} attempted to launch ${app_name} with files but does not have godmode permissions`);
// Continue with normal launch, ignoring file_paths
}
} catch (error) {
console.log('Error checking godmode permissions:', error);
// Continue with normal launch
}
}
// The "body" of this method is in a separate file
const child_process = await launch_app(launch_options);
const send_child_launched_msg = (...a) => {
if ( ! process ) return;
+14 -1
View File
@@ -1047,7 +1047,19 @@ class UI extends EventListener {
// Returns a Promise<AppConnection>
launchApp = async function launchApp(app_name, args, callback) {
let pseudonym = undefined;
if ( app_name.includes('#(as)') ) {
let file_paths = undefined;
// Handle case where app_name is an options object
if (typeof app_name === 'object' && app_name !== null) {
const options = app_name;
app_name = options.name || options.app_name;
file_paths = options.file_paths;
args = args || options.args;
callback = callback || options.callback;
pseudonym = options.pseudonym;
}
if ( app_name && app_name.includes('#(as)') ) {
[app_name, pseudonym] = app_name.split('#(as)');
}
const app_info = await this.#ipc_stub({
@@ -1055,6 +1067,7 @@ class UI extends EventListener {
callback,
parameters: {
app_name,
file_paths,
pseudonym,
args,
},