appback-remoteagent 0.21.0 → 0.21.1

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.
@@ -1,5 +1,6 @@
1
1
  import os from "node:os";
2
2
  import path from "node:path";
3
+ import process from "node:process";
3
4
  import { fileURLToPath } from "node:url";
4
5
  const CHILD_ENV_BLOCKED_PREFIXES = ["TELEGRAM_"];
5
6
  export function buildProviderEnv(extraEnv) {
@@ -15,11 +16,20 @@ export function buildProviderEnv(extraEnv) {
15
16
  env.DATA_DIR = dataDir;
16
17
  env.REMOTEAGENT_DATA_DIR = dataDir;
17
18
  env.REMOTEAGENT_SECRET_BIN = resolveSecretHelperPath();
19
+ env.PATH = buildRuntimePath(env.PATH);
18
20
  if (extraEnv) {
19
21
  Object.assign(env, extraEnv);
20
22
  }
21
23
  return env;
22
24
  }
25
+ export function buildRuntimePath(existingPath = process.env.PATH, nodeExecutable = process.execPath, homeDir = os.homedir()) {
26
+ const entries = [
27
+ path.dirname(nodeExecutable),
28
+ path.join(homeDir, ".local", "bin"),
29
+ ...(existingPath ?? "").split(path.delimiter),
30
+ ].filter(Boolean);
31
+ return [...new Set(entries)].join(path.delimiter);
32
+ }
23
33
  function resolveSecretHelperPath() {
24
34
  const adapterDir = path.dirname(fileURLToPath(import.meta.url));
25
35
  return path.resolve(adapterDir, "..", "secret-helper.js");
package/dist/index.js CHANGED
@@ -19,6 +19,7 @@ import { BotPollingStateService } from "./services/bot-polling-state-service.js"
19
19
  import { ProviderRecoveryService } from "./services/provider-recovery-service.js";
20
20
  import { computePolicyPollIntervalMs, computeRecentMessageRanks } from "./services/polling-policy.js";
21
21
  import { terminateAllSpawnedExecutions } from "./adapters/windows-shell.js";
22
+ import { buildProviderEnv } from "./adapters/runtime-env.js";
22
23
  import { setTelegramCommandMenu } from "./telegram-command-menu.js";
23
24
  import { buildBotInfoFromIdentity, buildFallbackBotInfo } from "./telegram-bot-identity.js";
24
25
  const execFileAsync = promisify(execFile);
@@ -528,9 +529,12 @@ function commandExists(command) {
528
529
  return fs.existsSync(trimmed);
529
530
  }
530
531
  if (process.platform === "win32") {
531
- return spawnSync("where", [trimmed], { stdio: "ignore" }).status === 0;
532
+ return spawnSync("where", [trimmed], { stdio: "ignore", env: buildProviderEnv() }).status === 0;
532
533
  }
533
- return spawnSync("sh", ["-lc", 'command -v "$0" >/dev/null 2>&1', trimmed], { stdio: "ignore" }).status === 0;
534
+ return spawnSync("sh", ["-lc", 'command -v "$0" >/dev/null 2>&1', trimmed], {
535
+ stdio: "ignore",
536
+ env: buildProviderEnv(),
537
+ }).status === 0;
534
538
  }
535
539
  async function acquireProcessLock(dataDir) {
536
540
  await fsp.mkdir(dataDir, { recursive: true });
@@ -3,6 +3,7 @@ import os from "node:os";
3
3
  import path from "node:path";
4
4
  import process from "node:process";
5
5
  import { spawn } from "node:child_process";
6
+ import { buildProviderEnv } from "../adapters/runtime-env.js";
6
7
  export class ProviderSetupService {
7
8
  timeoutMs;
8
9
  isProviderAvailable;
@@ -224,10 +225,7 @@ export class ProviderSetupService {
224
225
  return new Promise((resolve, reject) => {
225
226
  const child = spawn(launcher.file, launcher.args, {
226
227
  cwd: process.cwd(),
227
- env: {
228
- ...process.env,
229
- ...extraEnv,
230
- },
228
+ env: buildProviderEnv(extraEnv),
231
229
  });
232
230
  let stdout = "";
233
231
  let stderr = "";
@@ -32,6 +32,8 @@ remoteagent-start
32
32
  sudo systemctl restart remoteagent
33
33
  ```
34
34
 
35
+ Provider install, login, and execution commands automatically prepend the directory of the Node executable running RemoteAgent and `~/.local/bin` to their child-process `PATH`. This keeps `/install codex`, `/install claude`, and `/login` working when RemoteAgent runs under systemd with Node installed through nvm, even if the service itself was started with a minimal system PATH.
36
+
35
37
  ## Secret migration
36
38
 
37
39
  RemoteAgent `/secret` values belong to the installation, not to an individual agent session. They are stored under `~/.remoteagent/managed/secrets.json`.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "appback-remoteagent",
3
- "version": "0.21.0",
3
+ "version": "0.21.1",
4
4
  "description": "Personal installable session server for continuing local AI work across PC and Telegram",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -9,6 +9,7 @@ import {
9
9
  registerTelegramBot,
10
10
  waitForTelegramOwner,
11
11
  } from "../dist/services/cli-config-service.js";
12
+ import { buildProviderEnv, buildRuntimePath } from "../dist/adapters/runtime-env.js";
12
13
  import { exportSecrets, importSecrets } from "../dist/services/secret-transfer-service.js";
13
14
 
14
15
  const root = await fs.mkdtemp(path.join(os.tmpdir(), "remoteagent-cli-selftest-"));
@@ -19,6 +20,23 @@ const selectedBundlePath = path.join(root, "selected-transfer.ra-secrets");
19
20
  const passphrase = "correct-horse-battery-staple";
20
21
 
21
22
  try {
23
+ const expectedNodeBin = path.join(root, "nvm", "bin");
24
+ const expectedHome = path.join(root, "home");
25
+ const runtimePath = buildRuntimePath(
26
+ ["/usr/local/bin", "/usr/bin", "/usr/bin"].join(path.delimiter),
27
+ path.join(expectedNodeBin, "node"),
28
+ expectedHome,
29
+ ).split(path.delimiter);
30
+ assert.deepEqual(runtimePath, [
31
+ expectedNodeBin,
32
+ path.join(expectedHome, ".local", "bin"),
33
+ "/usr/local/bin",
34
+ "/usr/bin",
35
+ ]);
36
+ const providerEnv = buildProviderEnv();
37
+ assert.equal(providerEnv.PATH?.split(path.delimiter)[0], path.dirname(process.execPath));
38
+ assert.ok(providerEnv.PATH?.split(path.delimiter).includes(path.join(os.homedir(), ".local", "bin")));
39
+
22
40
  const binDir = path.join(root, "bin");
23
41
  const curlArgsPath = path.join(root, "curl-args.txt");
24
42
  const curlUpdateCallsPath = path.join(root, "curl-update-calls.txt");