@aiden-ade/sandbox-agent 0.1.9 → 0.1.11

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.
Files changed (2) hide show
  1. package/dist/index.cjs +146 -25
  2. package/package.json +12 -11
package/dist/index.cjs CHANGED
@@ -11142,7 +11142,7 @@ var WSClient = class {
11142
11142
  };
11143
11143
 
11144
11144
  // src/version.ts
11145
- var AGENT_VERSION = "0.1.9";
11145
+ var AGENT_VERSION = "0.1.11";
11146
11146
 
11147
11147
  // src/sandbox.ts
11148
11148
  async function runSandbox(config) {
@@ -11324,23 +11324,64 @@ var import_node_crypto = require("crypto");
11324
11324
  var import_node_os = require("os");
11325
11325
  var import_node_path = require("path");
11326
11326
  var import_node_child_process = require("child_process");
11327
- var CONFIG_PATH = process.env.AIDEN_AGENT_CONFIG_PATH ?? (0, import_node_path.join)((0, import_node_os.homedir)(), ".aiden", "agent", "config.json");
11327
+ var PRODUCTION_API_URL = "https://api.aiden-platform.com";
11328
+ var PRODUCTION_WS_URL = "wss://ws.aiden-platform.com";
11329
+ var LOCAL_API_URL = "http://localhost:8400";
11330
+ var LOCAL_WS_URL = "ws://localhost:8401";
11331
+ function getConfigPath() {
11332
+ return process.env.AIDEN_AGENT_CONFIG_PATH ?? (0, import_node_path.join)((0, import_node_os.homedir)(), ".aiden", "agent", "config.json");
11333
+ }
11334
+ function getEndpointDefaultsPath() {
11335
+ return process.env.AIDEN_AGENT_ENDPOINTS_PATH ?? (0, import_node_path.join)((0, import_node_path.dirname)(getConfigPath()), "endpoints.json");
11336
+ }
11328
11337
  function readConfig() {
11329
- if (!(0, import_node_fs.existsSync)(CONFIG_PATH)) return {};
11330
- return JSON.parse((0, import_node_fs.readFileSync)(CONFIG_PATH, "utf8"));
11338
+ const configPath = getConfigPath();
11339
+ if (!(0, import_node_fs.existsSync)(configPath)) return {};
11340
+ return JSON.parse((0, import_node_fs.readFileSync)(configPath, "utf8"));
11341
+ }
11342
+ function readEndpointDefaults() {
11343
+ const endpointsPath = getEndpointDefaultsPath();
11344
+ if (!(0, import_node_fs.existsSync)(endpointsPath)) return {};
11345
+ try {
11346
+ return JSON.parse((0, import_node_fs.readFileSync)(endpointsPath, "utf8"));
11347
+ } catch {
11348
+ return {};
11349
+ }
11331
11350
  }
11332
11351
  function writeConfig(config) {
11333
- (0, import_node_fs.mkdirSync)((0, import_node_path.dirname)(CONFIG_PATH), { recursive: true, mode: 448 });
11334
- (0, import_node_fs.writeFileSync)(CONFIG_PATH, JSON.stringify(config, null, 2), { mode: 384 });
11352
+ const configPath = getConfigPath();
11353
+ (0, import_node_fs.mkdirSync)((0, import_node_path.dirname)(configPath), { recursive: true, mode: 448 });
11354
+ (0, import_node_fs.writeFileSync)(configPath, JSON.stringify(config, null, 2), { mode: 384 });
11335
11355
  }
11336
11356
  function removeConfig() {
11337
- if ((0, import_node_fs.existsSync)(CONFIG_PATH)) (0, import_node_fs.rmSync)(CONFIG_PATH, { force: true });
11357
+ const configPath = getConfigPath();
11358
+ if ((0, import_node_fs.existsSync)(configPath)) (0, import_node_fs.rmSync)(configPath, { force: true });
11338
11359
  }
11339
11360
  function argValue(args, name) {
11340
11361
  const index = args.indexOf(name);
11341
11362
  if (index === -1) return void 0;
11342
11363
  return args[index + 1];
11343
11364
  }
11365
+ function resolveEndpointProfile(args) {
11366
+ const profile = argValue(args, "--profile") ?? process.env.AIDEN_AGENT_PROFILE;
11367
+ if (!profile) return "production";
11368
+ if (profile === "production" || profile === "prod") return "production";
11369
+ if (profile === "local" || profile === "dev") return "local";
11370
+ throw new Error("Unsupported endpoint profile. Use --profile production or --profile local.");
11371
+ }
11372
+ function resolveEndpoints(args, stored = {}) {
11373
+ const requestedProfile = resolveEndpointProfile(args);
11374
+ const profileApiUrl = requestedProfile === "local" ? LOCAL_API_URL : PRODUCTION_API_URL;
11375
+ const profileWsUrl = requestedProfile === "local" ? LOCAL_WS_URL : PRODUCTION_WS_URL;
11376
+ const endpointDefaults = readEndpointDefaults();
11377
+ const apiUrl = argValue(args, "--api-url") ?? process.env.AIDEN_API_URL ?? stored.apiUrl ?? endpointDefaults.apiUrl ?? profileApiUrl;
11378
+ const wsUrl = argValue(args, "--ws-url") ?? process.env.AIDEN_WS_URL ?? stored.wsUrl ?? endpointDefaults.wsUrl ?? profileWsUrl;
11379
+ const endpointProfile = apiUrl === profileApiUrl && wsUrl === profileWsUrl ? requestedProfile : apiUrl === endpointDefaults.apiUrl && wsUrl === endpointDefaults.wsUrl && endpointDefaults.endpointProfile ? endpointDefaults.endpointProfile : "custom";
11380
+ return { apiUrl, wsUrl, endpointProfile };
11381
+ }
11382
+ function isLocalEndpoint(url2) {
11383
+ return Boolean(url2 && /^(https?|wss?):\/\/(localhost|127\.0\.0\.1)(:\d+)?(\/|$)/.test(url2));
11384
+ }
11344
11385
  function getLocalApiPort(args, stored) {
11345
11386
  const raw = argValue(args, "--local-api-port") ?? process.env.AIDEN_AGENT_LOCAL_API_PORT;
11346
11387
  if (raw) return Number.parseInt(raw, 10);
@@ -11449,15 +11490,20 @@ var RuntimePresenter = class {
11449
11490
  }
11450
11491
  };
11451
11492
  async function setupDaemon(args) {
11452
- const apiUrl = argValue(args, "--api-url") ?? process.env.AIDEN_API_URL ?? "http://localhost:8400";
11453
- const wsUrl = argValue(args, "--ws-url") ?? process.env.AIDEN_WS_URL ?? "ws://localhost:8401";
11493
+ const { apiUrl, wsUrl, endpointProfile } = resolveEndpoints(args);
11454
11494
  const teamId = argValue(args, "--team") ?? process.env.AIDEN_TEAM_ID;
11455
11495
  const setupToken = argValue(args, "--setup-token") ?? process.env.AIDEN_RUNTIME_SETUP_TOKEN;
11456
11496
  const token = argValue(args, "--token") ?? process.env.AIDEN_SETUP_TOKEN;
11457
11497
  const displayName = argValue(args, "--name") ?? (0, import_node_os.hostname)();
11458
11498
  const legacyLocalMachineId = argValue(args, "--legacy-local-machine-id") ?? process.env.AIDEN_LEGACY_LOCAL_MACHINE_ID;
11499
+ const scope = argValue(args, "--scope") ?? process.env.AIDEN_RUNTIME_SCOPE ?? "team";
11500
+ if (scope !== "team" && scope !== "user") {
11501
+ throw new Error("setup --scope must be either 'team' or 'user'");
11502
+ }
11459
11503
  if (!setupToken && (!teamId || !token)) {
11460
- throw new Error("setup requires --setup-token <token> or --team <team-id> and --token <aiden PAT>");
11504
+ throw new Error(
11505
+ "setup requires --setup-token <token> or --team <team-id> and --token <aiden PAT>.\nFor normal setup, copy the setup token from Aiden and run: aiden-agent setup --setup-token <token>\nFor browser authorization, run: aiden-agent login"
11506
+ );
11461
11507
  }
11462
11508
  const response = await fetch(`${apiUrl}/public/runtimes${setupToken ? "/register-with-setup-token" : ""}`, {
11463
11509
  method: "POST",
@@ -11475,8 +11521,8 @@ async function setupDaemon(args) {
11475
11521
  managementKind: "user_managed",
11476
11522
  hostKind: "daemon",
11477
11523
  lifecycle: "durable",
11478
- ownerType: "team",
11479
- visibility: "team",
11524
+ ownerType: scope,
11525
+ visibility: scope,
11480
11526
  capabilities: discoverCapabilities(),
11481
11527
  metadata: {
11482
11528
  platform: (0, import_node_os.platform)(),
@@ -11492,6 +11538,7 @@ async function setupDaemon(args) {
11492
11538
  writeConfig({
11493
11539
  apiUrl,
11494
11540
  wsUrl,
11541
+ endpointProfile,
11495
11542
  teamId,
11496
11543
  runtimeId: body.runtime.id,
11497
11544
  runtimeToken: body.runtimeToken,
@@ -11499,11 +11546,10 @@ async function setupDaemon(args) {
11499
11546
  localApiToken: (0, import_node_crypto.randomBytes)(24).toString("hex"),
11500
11547
  displayName: body.runtime.displayName ?? displayName
11501
11548
  });
11502
- console.info("[aiden-agent] Runtime registered", { runtimeId: body.runtime.id, configPath: CONFIG_PATH });
11549
+ console.info("[aiden-agent] Runtime registered", { runtimeId: body.runtime.id, configPath: getConfigPath() });
11503
11550
  }
11504
11551
  async function loginWithDeviceCode(args) {
11505
- const apiUrl = argValue(args, "--api-url") ?? process.env.AIDEN_API_URL ?? "http://localhost:8400";
11506
- const wsUrl = argValue(args, "--ws-url") ?? process.env.AIDEN_WS_URL ?? "ws://localhost:8401";
11552
+ const { apiUrl, wsUrl, endpointProfile } = resolveEndpoints(args);
11507
11553
  const displayName = argValue(args, "--name") ?? (0, import_node_os.hostname)();
11508
11554
  const maxPolls = Number.parseInt(argValue(args, "--max-polls") ?? "300", 10);
11509
11555
  const start = await fetch(`${apiUrl}/public/runtimes/device-authorizations`, {
@@ -11542,6 +11588,7 @@ async function loginWithDeviceCode(args) {
11542
11588
  writeConfig({
11543
11589
  apiUrl,
11544
11590
  wsUrl,
11591
+ endpointProfile,
11545
11592
  teamId: body.runtime.teamId ?? void 0,
11546
11593
  runtimeId: body.runtime.id,
11547
11594
  runtimeToken: body.runtimeToken,
@@ -11549,7 +11596,7 @@ async function loginWithDeviceCode(args) {
11549
11596
  localApiToken: (0, import_node_crypto.randomBytes)(24).toString("hex"),
11550
11597
  displayName: body.runtime.displayName ?? displayName
11551
11598
  });
11552
- console.info("[aiden-agent] Runtime registered", { runtimeId: body.runtime.id, configPath: CONFIG_PATH });
11599
+ console.info("[aiden-agent] Runtime registered", { runtimeId: body.runtime.id, configPath: getConfigPath() });
11553
11600
  return;
11554
11601
  }
11555
11602
  throw new Error("device authorization timed out before approval");
@@ -11708,9 +11755,20 @@ async function startDaemon(args) {
11708
11755
  res.writeHead(404, { "content-type": "application/json" }).end(JSON.stringify({ error: "Not found" }));
11709
11756
  });
11710
11757
  await new Promise((resolve2, reject) => {
11711
- localServer.once("error", reject);
11758
+ const onError = (error) => {
11759
+ clearInterval(heartbeat);
11760
+ socket.disconnect();
11761
+ if (error.code === "EADDRINUSE") {
11762
+ reject(new Error(
11763
+ `local daemon API port ${localApiPort} is already in use. Another aiden-agent daemon may already be running; use \`aiden-agent status\` or stop the existing daemon before starting a new one.`
11764
+ ));
11765
+ return;
11766
+ }
11767
+ reject(error);
11768
+ };
11769
+ localServer.once("error", onError);
11712
11770
  localServer.listen(localApiPort, "127.0.0.1", () => {
11713
- localServer.off("error", reject);
11771
+ localServer.off("error", onError);
11714
11772
  const address = localServer.address();
11715
11773
  if (address && typeof address === "object") localApiPort = address.port;
11716
11774
  pushLog(`local_api listening port=${localApiPort}`);
@@ -11783,17 +11841,27 @@ async function revokeRuntimeToken(args) {
11783
11841
  }
11784
11842
  function logoutDaemon() {
11785
11843
  removeConfig();
11786
- console.info("[aiden-agent] Runtime config removed", { configPath: CONFIG_PATH });
11844
+ console.info("[aiden-agent] Runtime config removed", { configPath: getConfigPath() });
11787
11845
  }
11788
11846
  function printStatus() {
11789
11847
  const config = readConfig();
11848
+ const configured = Boolean(config.runtimeId && config.runtimeToken && config.wsUrl);
11849
+ const warnings = [];
11850
+ if ((isLocalEndpoint(config.apiUrl) || isLocalEndpoint(config.wsUrl)) && config.endpointProfile !== "local") {
11851
+ warnings.push("Configured endpoint points at localhost. Use --profile local only for local development.");
11852
+ }
11790
11853
  console.info(JSON.stringify({
11791
- configured: Boolean(config.runtimeId && config.runtimeToken && config.wsUrl),
11854
+ mode: "runtime",
11855
+ configured,
11792
11856
  runtimeId: config.runtimeId ?? null,
11857
+ apiUrl: config.apiUrl ?? null,
11793
11858
  wsUrl: config.wsUrl ?? null,
11859
+ endpointProfile: config.endpointProfile ?? null,
11794
11860
  localApiPort: config.localApiPort ?? null,
11795
11861
  hasLocalApiToken: Boolean(config.localApiToken),
11796
- configPath: CONFIG_PATH
11862
+ configPath: getConfigPath(),
11863
+ note: configured ? "Durable runtime config is present. Start it with: aiden-agent daemon" : "No durable runtime configured. Cloud sandbox sessions are launched by Aiden with session env vars and do not appear in this local config.",
11864
+ warnings
11797
11865
  }, null, 2));
11798
11866
  }
11799
11867
  async function printDoctor(args = []) {
@@ -11821,16 +11889,61 @@ async function printDoctor(args = []) {
11821
11889
  }
11822
11890
  console.info(JSON.stringify({
11823
11891
  version: AGENT_VERSION,
11824
- configPath: CONFIG_PATH,
11892
+ configPath: getConfigPath(),
11825
11893
  configured: Boolean(config.runtimeId && config.runtimeToken && config.wsUrl),
11826
11894
  runtimeId: config.runtimeId ?? null,
11895
+ apiUrl: config.apiUrl ?? null,
11827
11896
  wsUrl: config.wsUrl ?? null,
11897
+ endpointProfile: config.endpointProfile ?? null,
11898
+ warnings: (isLocalEndpoint(config.apiUrl) || isLocalEndpoint(config.wsUrl)) && config.endpointProfile !== "local" ? ["Configured endpoint points at localhost. Use --profile local only for local development."] : [],
11828
11899
  synced,
11829
11900
  syncError,
11830
11901
  capabilities
11831
11902
  }, null, 2));
11832
11903
  }
11833
11904
 
11905
+ // src/cli-help.ts
11906
+ var HELP_TEXT = `Aiden agent CLI
11907
+
11908
+ Usage:
11909
+ aiden-agent <command> [options]
11910
+
11911
+ Commands:
11912
+ setup Register this computer with a setup token from Aiden
11913
+ login Register this computer through browser authorization
11914
+ daemon Start the durable runtime daemon
11915
+ status Show local runtime configuration without secrets
11916
+ doctor Check local CLI capabilities
11917
+ logout Remove local runtime configuration
11918
+ token Rotate or revoke the configured runtime token
11919
+ run-session Internal: run one ephemeral sandbox/session from AIDEN_* env vars
11920
+
11921
+ Common flows:
11922
+ aiden-agent login
11923
+ aiden-agent setup --setup-token <token>
11924
+ aiden-agent setup --setup-token <token> --scope user
11925
+ aiden-agent daemon
11926
+
11927
+ Local development:
11928
+ aiden-agent login --profile local
11929
+ aiden-agent setup --profile local --setup-token <token>
11930
+ `;
11931
+ function hasRunSessionEnv(env) {
11932
+ return Boolean(
11933
+ env.AIDEN_WS_URL && env.AIDEN_SESSION_ID && env.AIDEN_TASK_ID && env.AIDEN_SESSION_TOKEN && env.AIDEN_TASK !== void 0
11934
+ );
11935
+ }
11936
+ function resolveCommand(args, env) {
11937
+ const [command, ...commandArgs] = args;
11938
+ if (!command) {
11939
+ return { command: hasRunSessionEnv(env) ? "run-session" : "help", commandArgs: [] };
11940
+ }
11941
+ if (command === "help" || command === "--help" || command === "-h") {
11942
+ return { command: "help", commandArgs };
11943
+ }
11944
+ return { command, commandArgs };
11945
+ }
11946
+
11834
11947
  // src/index.ts
11835
11948
  async function runSessionFromEnv() {
11836
11949
  const wsUrl = process.env.AIDEN_WS_URL;
@@ -11849,7 +11962,9 @@ async function runSessionFromEnv() {
11849
11962
  const effortLevel = process.env.AIDEN_EFFORT_LEVEL || void 0;
11850
11963
  const providerSessionId = process.env.AIDEN_PROVIDER_SESSION_ID || void 0;
11851
11964
  if (!wsUrl || !sessionId || !taskId || !sessionToken || task == null) {
11852
- throw new Error("Missing required env vars: AIDEN_WS_URL, AIDEN_SESSION_ID, AIDEN_TASK_ID, AIDEN_SESSION_TOKEN, AIDEN_TASK");
11965
+ throw new Error(
11966
+ "run-session is an internal Aiden sandbox/session command and must be launched by Aiden with session env vars. Missing required env vars: AIDEN_WS_URL, AIDEN_SESSION_ID, AIDEN_TASK_ID, AIDEN_SESSION_TOKEN, AIDEN_TASK"
11967
+ );
11853
11968
  }
11854
11969
  console.info("[aiden-agent] Starting", { sessionId, taskId, projectPath, backendKind, agentId, mode, model, version: AGENT_VERSION });
11855
11970
  await runSandbox({
@@ -11877,7 +11992,11 @@ async function main() {
11877
11992
  `);
11878
11993
  return;
11879
11994
  }
11880
- const [command = "run-session", ...commandArgs] = process.argv.slice(2);
11995
+ const { command, commandArgs } = resolveCommand(process.argv.slice(2), process.env);
11996
+ if (command === "help") {
11997
+ process.stdout.write(HELP_TEXT);
11998
+ return;
11999
+ }
11881
12000
  if (command === "setup") {
11882
12001
  await setupDaemon(commandArgs);
11883
12002
  return;
@@ -11914,7 +12033,9 @@ async function main() {
11914
12033
  await runSessionFromEnv();
11915
12034
  return;
11916
12035
  }
11917
- throw new Error(`Unknown command: ${command}`);
12036
+ throw new Error(`Unknown command: ${command}
12037
+
12038
+ ${HELP_TEXT}`);
11918
12039
  }
11919
12040
  main().catch((error) => {
11920
12041
  console.error("[aiden-agent] Fatal error:", error instanceof Error ? error.message : error);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@aiden-ade/sandbox-agent",
3
- "version": "0.1.9",
3
+ "version": "0.1.11",
4
4
  "type": "module",
5
5
  "bin": {
6
6
  "aiden-agent": "./dist/index.cjs"
@@ -11,21 +11,22 @@
11
11
  "publishConfig": {
12
12
  "access": "public"
13
13
  },
14
+ "scripts": {
15
+ "build": "tsup",
16
+ "dev": "tsx src/index.ts",
17
+ "prepack": "pnpm build",
18
+ "test": "vitest run",
19
+ "type-check": "tsc --noEmit"
20
+ },
14
21
  "dependencies": {},
15
22
  "devDependencies": {
23
+ "@aiden/agent-core": "workspace:*",
24
+ "@aiden/shared": "workspace:*",
16
25
  "socket.io-client": "^4.8.0",
17
26
  "socket.io": "^4.8.0",
18
27
  "@types/node": "^22.0.0",
19
28
  "tsup": "^8.5.1",
20
29
  "tsx": "^4.19.0",
21
- "typescript": "~5.9.3",
22
- "@aiden/shared": "0.1.0",
23
- "@aiden/agent-core": "0.1.0"
24
- },
25
- "scripts": {
26
- "build": "tsup",
27
- "dev": "tsx src/index.ts",
28
- "test": "vitest run",
29
- "type-check": "tsc --noEmit"
30
+ "typescript": "~5.9.3"
30
31
  }
31
- }
32
+ }