open-agents-ai 0.184.32 → 0.184.33

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.js +90 -12
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -67254,15 +67254,46 @@ function listJobs() {
67254
67254
  }
67255
67255
  return jobs;
67256
67256
  }
67257
- function checkAuth(req, res) {
67258
- const apiKey = process.env["OA_API_KEY"];
67259
- if (!apiKey)
67260
- return true;
67257
+ function resolveAuth(req) {
67261
67258
  const authHeader = req.headers["authorization"];
67262
- if (!authHeader || authHeader !== `Bearer ${apiKey}`) {
67259
+ const token = authHeader?.startsWith("Bearer ") ? authHeader.slice(7) : null;
67260
+ const multiKeys = process.env["OA_API_KEYS"];
67261
+ if (multiKeys) {
67262
+ if (!token)
67263
+ return { authenticated: false, scope: "read" };
67264
+ for (const entry of multiKeys.split(",")) {
67265
+ const [key, scope, user] = entry.trim().split(":");
67266
+ if (key === token) {
67267
+ return { authenticated: true, scope: scope || "admin", user: user || void 0 };
67268
+ }
67269
+ }
67270
+ return { authenticated: false, scope: "read" };
67271
+ }
67272
+ const singleKey = process.env["OA_API_KEY"];
67273
+ if (!singleKey)
67274
+ return { authenticated: true, scope: "admin" };
67275
+ if (token === singleKey)
67276
+ return { authenticated: true, scope: "admin" };
67277
+ return { authenticated: false, scope: "read" };
67278
+ }
67279
+ function checkAuth(req, res, requiredScope = "read") {
67280
+ const scopeLevel = { read: 1, run: 2, admin: 3 };
67281
+ const auth = resolveAuth(req);
67282
+ if (!auth.authenticated) {
67263
67283
  jsonResponse(res, 401, { error: "Unauthorized", message: "Invalid or missing Bearer token" });
67264
67284
  return false;
67265
67285
  }
67286
+ if (scopeLevel[auth.scope] < scopeLevel[requiredScope]) {
67287
+ jsonResponse(res, 403, {
67288
+ error: "Forbidden",
67289
+ message: `Scope '${auth.scope}' insufficient \u2014 requires '${requiredScope}'`,
67290
+ scope: auth.scope,
67291
+ required: requiredScope
67292
+ });
67293
+ return false;
67294
+ }
67295
+ req._authUser = auth.user;
67296
+ req._authScope = auth.scope;
67266
67297
  return true;
67267
67298
  }
67268
67299
  function handleHealth(res) {
@@ -67534,7 +67565,20 @@ async function handleV1Run(req, res) {
67534
67565
  }
67535
67566
  const id = `job-${randomBytes16(3).toString("hex")}`;
67536
67567
  const dir = jobsDir2();
67537
- const repoRoot = resolve35(process.cwd());
67568
+ const workingDir = requestBody["working_directory"];
67569
+ const isolate = requestBody["isolate"] === true;
67570
+ let cwd4;
67571
+ if (workingDir) {
67572
+ cwd4 = resolve35(workingDir);
67573
+ } else if (isolate) {
67574
+ const wsDir = join71(dir, "..", "workspaces", id);
67575
+ mkdirSync26(wsDir, { recursive: true });
67576
+ cwd4 = wsDir;
67577
+ } else {
67578
+ cwd4 = resolve35(process.cwd());
67579
+ }
67580
+ const authUser = req._authUser || "anonymous";
67581
+ const authScope = req._authScope || "admin";
67538
67582
  const job = {
67539
67583
  id,
67540
67584
  pid: 0,
@@ -67542,14 +67586,39 @@ async function handleV1Run(req, res) {
67542
67586
  status: "running",
67543
67587
  startedAt: (/* @__PURE__ */ new Date()).toISOString()
67544
67588
  };
67589
+ job.user = authUser;
67590
+ job.scope = authScope;
67591
+ job.cwd = cwd4;
67592
+ job.isolate = isolate;
67545
67593
  const oaBin = process.argv[1] || "oa";
67546
67594
  const args = [task, "--json"];
67547
67595
  const modelArg = requestBody["model"];
67548
67596
  if (modelArg)
67549
67597
  args.push("--model", modelArg);
67598
+ const maxTurns = requestBody["max_turns"];
67599
+ if (maxTurns && maxTurns > 0)
67600
+ args.push("--max-turns", String(maxTurns));
67601
+ const timeout = requestBody["timeout_s"];
67602
+ if (timeout && timeout > 0)
67603
+ args.push("--timeout", String(timeout));
67604
+ const runEnv = {
67605
+ ...process.env,
67606
+ OA_JOB_ID: id,
67607
+ __OPEN_AGENTS_NO_AUTO_RUN: "",
67608
+ OA_RUN_USER: authUser,
67609
+ OA_RUN_SCOPE: authScope
67610
+ };
67611
+ const customEnv = requestBody["env"];
67612
+ if (customEnv && typeof customEnv === "object") {
67613
+ for (const [k, v] of Object.entries(customEnv)) {
67614
+ if (k.startsWith("OA_") && typeof v === "string") {
67615
+ runEnv[k] = v;
67616
+ }
67617
+ }
67618
+ }
67550
67619
  const child = spawn21("node", [oaBin, ...args], {
67551
- cwd: repoRoot,
67552
- env: { ...process.env, OA_JOB_ID: id, __OPEN_AGENTS_NO_AUTO_RUN: "" },
67620
+ cwd: cwd4,
67621
+ env: runEnv,
67553
67622
  stdio: ["ignore", "pipe", "pipe"],
67554
67623
  detached: true
67555
67624
  });
@@ -67829,7 +67898,12 @@ async function handleRequest(req, res, ollamaUrl, verbose) {
67829
67898
  return;
67830
67899
  }
67831
67900
  if (pathname.startsWith("/v1/")) {
67832
- if (!checkAuth(req, res)) {
67901
+ const isWrite = method === "POST" || method === "PUT" || method === "PATCH" || method === "DELETE";
67902
+ const isRun = pathname === "/v1/run" || pathname.startsWith("/v1/runs");
67903
+ const isConfigWrite = pathname.startsWith("/v1/config") && isWrite;
67904
+ const isCommand = pathname.startsWith("/v1/commands") && method === "POST";
67905
+ const requiredScope = isConfigWrite ? "admin" : isRun || isCommand ? "run" : "read";
67906
+ if (!checkAuth(req, res, requiredScope)) {
67833
67907
  status = 401;
67834
67908
  return;
67835
67909
  }
@@ -67956,11 +68030,15 @@ function startApiServer(options = {}) {
67956
68030
  `);
67957
68031
  process.stderr.write(` Ollama proxy: ${ollamaUrl}
67958
68032
  `);
67959
- if (process.env["OA_API_KEY"]) {
67960
- process.stderr.write(` Auth: Bearer token required for /v1/* endpoints
68033
+ if (process.env["OA_API_KEYS"]) {
68034
+ const keyCount = process.env["OA_API_KEYS"].split(",").length;
68035
+ process.stderr.write(` Auth: ${keyCount} scoped key(s) (read/run/admin)
68036
+ `);
68037
+ } else if (process.env["OA_API_KEY"]) {
68038
+ process.stderr.write(` Auth: single Bearer token (admin scope)
67961
68039
  `);
67962
68040
  } else {
67963
- process.stderr.write(` Auth: disabled (set OA_API_KEY to enable)
68041
+ process.stderr.write(` Auth: disabled (set OA_API_KEY or OA_API_KEYS to enable)
67964
68042
  `);
67965
68043
  }
67966
68044
  process.stderr.write(`
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "open-agents-ai",
3
- "version": "0.184.32",
3
+ "version": "0.184.33",
4
4
  "description": "AI coding agent powered by open-source models (Ollama/vLLM) \u2014 interactive TUI with agentic tool-calling loop",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",