@runfusion/fusion 0.0.2 → 0.0.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Runfusion
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md CHANGED
@@ -20,13 +20,30 @@
20
20
 
21
21
  ## Install
22
22
 
23
- Zero install, straight from npm:
23
+ **Zero install, straight from npm:**
24
24
 
25
25
  ```bash
26
- npx @runfusion/fusion dashboard
26
+ npx runfusion.ai
27
27
  ```
28
28
 
29
- Globally:
29
+ Boots the dashboard. Subcommands forward through (`npx runfusion.ai task list`, etc). Long form: `npx @runfusion/fusion dashboard`.
30
+
31
+ **One-line installer** (macOS & Linux — auto-picks Homebrew, falls back to npm):
32
+
33
+ ```bash
34
+ curl -fsSL https://runfusion.ai/install.sh | sh
35
+ ```
36
+
37
+ **Homebrew** (macOS & Linux):
38
+
39
+ ```bash
40
+ brew tap runfusion/fusion
41
+ brew install fusion
42
+ ```
43
+
44
+ Or as a one-liner: `brew install runfusion/fusion/fusion`.
45
+
46
+ **npm global**:
30
47
 
31
48
  ```bash
32
49
  npm install -g @runfusion/fusion
package/dist/bin.js CHANGED
@@ -46017,10 +46017,10 @@ function pushAlias(aliases, value) {
46017
46017
  if (pathRef !== normalized && pathRef.length > 0) {
46018
46018
  aliases.add(pathRef);
46019
46019
  }
46020
- const basename13 = extractPathBasename(value);
46021
- if (basename13) {
46022
- aliases.add(basename13);
46023
- const basenameSlug = slugifyAgentReference(basename13);
46020
+ const basename14 = extractPathBasename(value);
46021
+ if (basename14) {
46022
+ aliases.add(basename14);
46023
+ const basenameSlug = slugifyAgentReference(basename14);
46024
46024
  if (basenameSlug.length > 0) {
46025
46025
  aliases.add(basenameSlug);
46026
46026
  }
@@ -51110,11 +51110,43 @@ var init_terminal_service = __esm({
51110
51110
  if (this.isWindows) {
51111
51111
  ptyOptions.useConpty = false;
51112
51112
  }
51113
+ const attemptedSpawns = /* @__PURE__ */ new Set();
51114
+ const spawnAttempts = [];
51115
+ const addSpawnAttempt = (shellPath, args, reason) => {
51116
+ const key = `${shellPath}\0${args.join("\0")}`;
51117
+ if (attemptedSpawns.has(key)) return;
51118
+ attemptedSpawns.add(key);
51119
+ spawnAttempts.push({ shell: shellPath, args, reason });
51120
+ };
51121
+ addSpawnAttempt(shell, shellArgs, "primary");
51122
+ if (shellArgs.length > 0) {
51123
+ addSpawnAttempt(shell, [], "retry-without-login");
51124
+ }
51125
+ for (const allowedShell of this.getAllowedShells()) {
51126
+ if (allowedShell === shell || !existsSync17(allowedShell)) continue;
51127
+ const shellName = path.basename(allowedShell).toLowerCase().replace(".exe", "");
51128
+ const fallbackArgs = shellName === "bash" || shellName === "zsh" ? [] : [];
51129
+ addSpawnAttempt(allowedShell, fallbackArgs, "allowed-fallback");
51130
+ }
51113
51131
  let ptyProcess;
51114
- try {
51115
- ptyProcess = pty.spawn(shell, shellArgs, ptyOptions);
51116
- } catch (spawnError) {
51117
- console.error(`[createSession] PTY spawn failed:`, spawnError);
51132
+ let lastSpawnError;
51133
+ for (const attempt of spawnAttempts) {
51134
+ try {
51135
+ console.info(
51136
+ `[createSession] Spawning terminal via ${attempt.reason}: ${attempt.shell} ${attempt.args.join(" ")} in ${cwd}`
51137
+ );
51138
+ ptyProcess = pty.spawn(attempt.shell, attempt.args, ptyOptions);
51139
+ break;
51140
+ } catch (spawnError) {
51141
+ lastSpawnError = spawnError;
51142
+ console.error(
51143
+ `[createSession] PTY spawn failed (${attempt.reason}) for ${attempt.shell} ${attempt.args.join(" ")}:`,
51144
+ spawnError
51145
+ );
51146
+ }
51147
+ }
51148
+ if (!ptyProcess) {
51149
+ console.error(`[createSession] All PTY spawn attempts failed`, lastSpawnError);
51118
51150
  return {
51119
51151
  success: false,
51120
51152
  code: "pty_spawn_failed",
@@ -51393,7 +51425,7 @@ var init_terminal_service = __esm({
51393
51425
  });
51394
51426
 
51395
51427
  // ../dashboard/src/file-service.ts
51396
- import { join as join23, resolve as resolve12, relative as relative3, dirname as dirname8, basename as basename6 } from "node:path";
51428
+ import { join as join23, resolve as resolve12, relative as relative3, dirname as dirname8, basename as basename7 } from "node:path";
51397
51429
  import { readdir as readdir7, readFile as fsReadFile, writeFile as fsWriteFile, stat as stat5, copyFile as fsCopyFile, rename as fsRename, rm as fsRm, mkdir as mkdir11, access as access3 } from "node:fs/promises";
51398
51430
  async function getTaskBasePath(store, taskId) {
51399
51431
  try {
@@ -51847,7 +51879,7 @@ async function getWorkspaceFileForDownload(store, workspace, filePath) {
51847
51879
  mtime: stats.mtime,
51848
51880
  isFile: true
51849
51881
  },
51850
- fileName: basename6(resolvedPath)
51882
+ fileName: basename7(resolvedPath)
51851
51883
  };
51852
51884
  }
51853
51885
  async function getWorkspaceFolderForZip(store, workspace, dirPath) {
@@ -51875,7 +51907,7 @@ async function getWorkspaceFolderForZip(store, workspace, dirPath) {
51875
51907
  }
51876
51908
  return {
51877
51909
  absolutePath: resolvedPath,
51878
- dirName: basename6(resolvedPath)
51910
+ dirName: basename7(resolvedPath)
51879
51911
  };
51880
51912
  }
51881
51913
  async function walkDirForMarkdown(basePath, currentRelative, results) {
@@ -60432,7 +60464,7 @@ __export(pi_exports, {
60432
60464
  import { existsSync as existsSync21, readFileSync as readFileSync8 } from "node:fs";
60433
60465
  import { exec } from "node:child_process";
60434
60466
  import { promisify as promisify2 } from "node:util";
60435
- import { basename as basename7, dirname as dirname9, join as join28, relative as relative4, isAbsolute as isAbsolute6, resolve as resolve13 } from "node:path";
60467
+ import { basename as basename8, dirname as dirname9, join as join28, relative as relative4, isAbsolute as isAbsolute6, resolve as resolve13 } from "node:path";
60436
60468
  import { createAgentSession, createCodingTools, createExtensionRuntime, createReadOnlyTools, DefaultResourceLoader, DefaultPackageManager, discoverAndLoadExtensions, ModelRegistry, SessionManager, SettingsManager } from "@mariozechner/pi-coding-agent";
60437
60469
  function getSessionStateError(session) {
60438
60470
  const error = session.state?.error;
@@ -60645,7 +60677,7 @@ function hasPackageManagerSettings(settings) {
60645
60677
  return Array.isArray(settings.packages) || Array.isArray(settings.npmCommand);
60646
60678
  }
60647
60679
  function siblingAgentDir(agentDir, siblingRoot) {
60648
- if (basename7(agentDir) !== "agent") {
60680
+ if (basename8(agentDir) !== "agent") {
60649
60681
  return void 0;
60650
60682
  }
60651
60683
  return join28(dirname9(dirname9(agentDir)), siblingRoot, "agent");
@@ -87057,7 +87089,7 @@ var init_rate_limit = __esm({
87057
87089
  // ../dashboard/src/plugin-routes.ts
87058
87090
  import { Router as Router5 } from "express";
87059
87091
  import { access as access5, stat as stat8, readFile as readFile21 } from "node:fs/promises";
87060
- import { join as join41, isAbsolute as isAbsolute11, dirname as dirname13, basename as basename8 } from "node:path";
87092
+ import { join as join41, isAbsolute as isAbsolute11, dirname as dirname13, basename as basename9 } from "node:path";
87061
87093
  async function resolvePluginManifest(sourcePath) {
87062
87094
  try {
87063
87095
  await access5(sourcePath);
@@ -87081,7 +87113,7 @@ async function resolvePluginManifest(sourcePath) {
87081
87113
  } catch (err) {
87082
87114
  if (err instanceof ApiError) throw err;
87083
87115
  }
87084
- const dirName = basename8(sourcePath).toLowerCase();
87116
+ const dirName = basename9(sourcePath).toLowerCase();
87085
87117
  if (DIST_DIR_NAMES.has(dirName)) {
87086
87118
  const parentDir = dirname13(sourcePath);
87087
87119
  const parentManifestPath = join41(parentDir, "manifest.json");
@@ -124010,7 +124042,7 @@ ${body}`;
124010
124042
  const nodeId = req.query.nodeId;
124011
124043
  if (nodeId) {
124012
124044
  const { CentralCore: CentralCore2 } = await Promise.resolve().then(() => (init_src(), src_exports));
124013
- const central = new CentralCore2();
124045
+ const central = new CentralCore2(store.getFusionDir());
124014
124046
  await central.init();
124015
124047
  const localNodes = await central.listNodes();
124016
124048
  const localNode = localNodes.find((n) => n.type === "local");
@@ -124037,6 +124069,9 @@ ${body}`;
124037
124069
  headers,
124038
124070
  signal: AbortSignal.timeout(3e4)
124039
124071
  });
124072
+ if (proxyRes.status === 401 && !node.apiKey) {
124073
+ throw unauthorized("Remote node rejected directory browse request. Configure an apiKey for that node in Fusion settings.");
124074
+ }
124040
124075
  const body = Buffer.from(await proxyRes.arrayBuffer());
124041
124076
  const skipHeaders = /* @__PURE__ */ new Set(["connection", "keep-alive", "transfer-encoding", "upgrade"]);
124042
124077
  for (const [key, value] of proxyRes.headers.entries()) {
@@ -133089,9 +133124,9 @@ var init_port_prompt = __esm({
133089
133124
 
133090
133125
  // src/commands/provider-settings.ts
133091
133126
  import { existsSync as existsSync31, readFileSync as readFileSync11, writeFileSync as writeFileSync2, mkdirSync as mkdirSync6 } from "node:fs";
133092
- import { join as join46, dirname as dirname16, basename as basename9 } from "node:path";
133127
+ import { join as join46, dirname as dirname16, basename as basename10 } from "node:path";
133093
133128
  function siblingAgentDir2(agentDir, siblingRoot) {
133094
- if (basename9(agentDir) !== "agent") {
133129
+ if (basename10(agentDir) !== "agent") {
133095
133130
  return void 0;
133096
133131
  }
133097
133132
  return join46(dirname16(dirname16(agentDir)), siblingRoot, "agent");
@@ -135731,10 +135766,10 @@ async function runTaskCreate(descriptionArg, attachFiles, depends, projectName)
135731
135766
  console.log(` Path: .fusion/tasks/${task.id}/`);
135732
135767
  if (attachFiles && attachFiles.length > 0) {
135733
135768
  const { readFile: readFile24 } = await import("node:fs/promises");
135734
- const { basename: basename13, extname, resolve: resolve29 } = await import("node:path");
135769
+ const { basename: basename14, extname, resolve: resolve29 } = await import("node:path");
135735
135770
  for (const filePath of attachFiles) {
135736
135771
  const resolvedPath = resolve29(filePath);
135737
- const filename = basename13(resolvedPath);
135772
+ const filename = basename14(resolvedPath);
135738
135773
  const ext = extname(filename).toLowerCase();
135739
135774
  const mimeType = MIME_TYPES[ext];
135740
135775
  if (!mimeType) {
@@ -135980,10 +136015,10 @@ async function runTaskMerge(id, projectName) {
135980
136015
  }
135981
136016
  async function runTaskAttach(id, filePath, projectName) {
135982
136017
  const { readFile: readFile24 } = await import("node:fs/promises");
135983
- const { basename: basename13, extname } = await import("node:path");
136018
+ const { basename: basename14, extname } = await import("node:path");
135984
136019
  const { resolve: resolve29 } = await import("node:path");
135985
136020
  const resolvedPath = resolve29(filePath);
135986
- const filename = basename13(resolvedPath);
136021
+ const filename = basename14(resolvedPath);
135987
136022
  const ext = extname(filename).toLowerCase();
135988
136023
  const mimeType = MIME_TYPES[ext];
135989
136024
  if (!mimeType) {
@@ -138204,7 +138239,7 @@ __export(project_exports, {
138204
138239
  runProjectSetDefault: () => runProjectSetDefault,
138205
138240
  runProjectShow: () => runProjectShow
138206
138241
  });
138207
- import { resolve as resolve25, isAbsolute as isAbsolute13, relative as relative11, basename as basename10 } from "node:path";
138242
+ import { resolve as resolve25, isAbsolute as isAbsolute13, relative as relative11, basename as basename11 } from "node:path";
138208
138243
  import { existsSync as existsSync38, statSync as statSync9 } from "node:fs";
138209
138244
  import { createInterface as createInterface7 } from "node:readline/promises";
138210
138245
  function formatDisplayPath(projectPath) {
@@ -138212,7 +138247,7 @@ function formatDisplayPath(projectPath) {
138212
138247
  if (rel && !rel.startsWith("..") && rel !== "") {
138213
138248
  return rel;
138214
138249
  }
138215
- return basename10(projectPath) || ".";
138250
+ return basename11(projectPath) || ".";
138216
138251
  }
138217
138252
  function formatLastActivity2(timestamp) {
138218
138253
  if (!timestamp) return "never";
@@ -138362,7 +138397,7 @@ async function runProjectAdd(name, path4, options = {}) {
138362
138397
  }
138363
138398
  }
138364
138399
  if (!projectName) {
138365
- const suggested = basename10(absolutePath2);
138400
+ const suggested = basename11(absolutePath2);
138366
138401
  projectName = await rl.question(` Project name [${suggested}]: `);
138367
138402
  projectName = projectName.trim() || suggested;
138368
138403
  }
@@ -138651,7 +138686,7 @@ __export(init_exports, {
138651
138686
  runInit: () => runInit
138652
138687
  });
138653
138688
  import { existsSync as existsSync39, mkdirSync as mkdirSync7, writeFileSync as writeFileSync3, readFileSync as readFileSync15 } from "node:fs";
138654
- import { join as join54, resolve as resolve26, basename as basename11 } from "node:path";
138689
+ import { join as join54, resolve as resolve26, basename as basename12 } from "node:path";
138655
138690
  import { exec as exec11 } from "node:child_process";
138656
138691
  import { promisify as promisify13 } from "node:util";
138657
138692
  async function runInit(options = {}) {
@@ -138767,7 +138802,7 @@ async function detectProjectName(dir2) {
138767
138802
  }
138768
138803
  } catch {
138769
138804
  }
138770
- return basename11(dir2) || "my-project";
138805
+ return basename12(dir2) || "my-project";
138771
138806
  }
138772
138807
  async function addLocalStorageToGitignore(cwd) {
138773
138808
  const gitignorePath = join54(cwd, ".gitignore");
@@ -139949,7 +139984,7 @@ __export(native_patch_exports, {
139949
139984
  isTerminalAvailable: () => isTerminalAvailable,
139950
139985
  setupNativeResolution: () => setupNativeResolution
139951
139986
  });
139952
- import { join as join57, basename as basename12, dirname as dirname19 } from "node:path";
139987
+ import { join as join57, basename as basename13, dirname as dirname19 } from "node:path";
139953
139988
  import { existsSync as existsSync43, copyFileSync, mkdirSync as mkdirSync10, symlinkSync, rmSync as rmSync3, lstatSync as lstatSync2, readlinkSync } from "node:fs";
139954
139989
  import { tmpdir as tmpdir3 } from "node:os";
139955
139990
  function findStagedNativeDir2() {
@@ -139999,7 +140034,7 @@ function setupNativeResolution() {
139999
140034
  const tmpRoot = join57(tmpdir3(), `fn-bunfs-${process.pid}`);
140000
140035
  const fnDir = join57(tmpRoot, "fn");
140001
140036
  const prebuildsDir = join57(fnDir, "prebuilds");
140002
- const platformDir = join57(prebuildsDir, basename12(nativeDir));
140037
+ const platformDir = join57(prebuildsDir, basename13(nativeDir));
140003
140038
  try {
140004
140039
  cleanupStaleBunfsLinks();
140005
140040
  mkdirSync10(platformDir, { recursive: true });