@adelie/server 0.5.10 → 0.6.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.
package/dist/index.js CHANGED
@@ -8,7 +8,7 @@ import {
8
8
  } from "./chunk-GO6G445C.js";
9
9
  import {
10
10
  TICKET_SLUG_PATTERN
11
- } from "./chunk-ZKT7QPDY.js";
11
+ } from "./chunk-JHADMFBF.js";
12
12
  import {
13
13
  MachinesRepo
14
14
  } from "./chunk-HMTT2PX4.js";
@@ -3687,7 +3687,7 @@ import { DEFAULT_PROJECT_ID as DEFAULT_PROJECT_ID3, DEFAULT_PROJECT_NAME as DEFA
3687
3687
 
3688
3688
  // src/ifaces.json
3689
3689
  var ifaces_default = {
3690
- hash: "9809bda47442f2926149a29a0296ba3565733013ea8bc46dab8e7d57d9b52f39",
3690
+ hash: "9429b591770e4b849cef3ce6aad180b25daa499877cfb837bd62f0f0cc00df83",
3691
3691
  ifaces: {
3692
3692
  "@adelie/server#Access": {
3693
3693
  name: "Access",
@@ -20235,6 +20235,21 @@ var ifaces_default = {
20235
20235
  }
20236
20236
  }
20237
20237
  }
20238
+ },
20239
+ readEntry: {
20240
+ params: [
20241
+ {
20242
+ data: "string"
20243
+ },
20244
+ {
20245
+ data: "string"
20246
+ }
20247
+ ],
20248
+ returns: {
20249
+ promise: {
20250
+ data: "undefined|string"
20251
+ }
20252
+ }
20238
20253
  }
20239
20254
  },
20240
20255
  slots: {}
@@ -20299,6 +20314,21 @@ var ifaces_default = {
20299
20314
  }
20300
20315
  }
20301
20316
  },
20317
+ readEntry: {
20318
+ params: [
20319
+ {
20320
+ data: "string"
20321
+ },
20322
+ {
20323
+ data: "string"
20324
+ }
20325
+ ],
20326
+ returns: {
20327
+ promise: {
20328
+ data: "undefined|string"
20329
+ }
20330
+ }
20331
+ },
20302
20332
  assignToAgent: {
20303
20333
  params: [
20304
20334
  {
@@ -32454,6 +32484,16 @@ function scheduledRateAt(provider, modelId, rates, at) {
32454
32484
  function optStr(v) {
32455
32485
  return typeof v === "string" && v !== "" ? v : void 0;
32456
32486
  }
32487
+ function groupApiKey(pool, provider, baseUrl) {
32488
+ const target = baseUrl ?? "";
32489
+ const keys = /* @__PURE__ */ new Set();
32490
+ for (const row of pool) {
32491
+ if (row.provider !== provider) continue;
32492
+ if ((row.baseUrl ?? "") !== target) continue;
32493
+ if (row.apiKey !== void 0) keys.add(row.apiKey);
32494
+ }
32495
+ return keys.size === 1 ? [...keys][0] : void 0;
32496
+ }
32457
32497
  function toCommandPolicyRuleDtos(rules) {
32458
32498
  return rules.map((r) => ({
32459
32499
  name: r.name,
@@ -33267,6 +33307,24 @@ var ProjectConfigService = class {
33267
33307
  const hadModelScopeGroup = prevModels.some(
33268
33308
  (model) => model.provider === MODELSCOPE_PROVIDER_ID
33269
33309
  );
33310
+ const baseUrlOf = (entry) => {
33311
+ if (entry.baseUrl === null) return void 0;
33312
+ if (entry.baseUrl !== void 0) return entry.baseUrl;
33313
+ const ref = entry.renamedFrom ?? { provider: entry.provider, modelId: entry.modelId };
33314
+ return optStr(prevModels.find((m) => entryMatches(m, ref.provider, ref.modelId))?.base_url);
33315
+ };
33316
+ const keyPool = [
33317
+ ...prevModels.map((m) => ({
33318
+ provider: optStr(m.provider) ?? "",
33319
+ baseUrl: optStr(m.base_url),
33320
+ apiKey: optStr(m.api_key)
33321
+ })),
33322
+ ...req.models.filter((entry) => !entry.clearApiKey && entry.apiKey !== void 0).map((entry) => ({
33323
+ provider: entry.provider,
33324
+ baseUrl: baseUrlOf(entry),
33325
+ apiKey: entry.apiKey
33326
+ }))
33327
+ ];
33270
33328
  for (const entry of req.models) {
33271
33329
  if (!unroutableVendorModel(entry.provider, entry.modelId, entry.clientType)) continue;
33272
33330
  if (prevModels.some((m) => entryMatches(m, entry.provider, entry.modelId))) continue;
@@ -33356,6 +33414,13 @@ var ProjectConfigService = class {
33356
33414
  next2.api_key = entry.apiKey;
33357
33415
  next2.created_at = (/* @__PURE__ */ new Date()).toISOString();
33358
33416
  if (entry.provider === MODELSCOPE_PROVIDER_ID) clearModelScopeProviderAuthToken = true;
33417
+ } else if (!entry.clearApiKey && next2.api_key === void 0 && catalogEntryFor(entry.provider, entry.modelId) !== void 0) {
33418
+ const borrowed = groupApiKey(keyPool, entry.provider, baseUrlOf(entry));
33419
+ if (borrowed !== void 0) {
33420
+ next2.api_key = borrowed;
33421
+ next2.created_at = (/* @__PURE__ */ new Date()).toISOString();
33422
+ if (entry.provider === MODELSCOPE_PROVIDER_ID) clearModelScopeProviderAuthToken = true;
33423
+ }
33359
33424
  }
33360
33425
  if (entry.baseUrl === null) delete next2.base_url;
33361
33426
  else if (entry.baseUrl !== void 0) next2.base_url = entry.baseUrl;
@@ -53948,6 +54013,14 @@ var UserVaultService = class {
53948
54013
  await saveUserVault(this.root, userId, next);
53949
54014
  return maskTable(next);
53950
54015
  }
54016
+ /**
54017
+ * One entry's plaintext, for a caller that writes it into another file on this server (the
54018
+ * model credential; see the mechanism). A key the account does not have is `undefined` rather
54019
+ * than an empty string, so the caller can name the failure.
54020
+ */
54021
+ async readEntry(userId, key2) {
54022
+ return (await loadUserVault(this.root, userId))[key2];
54023
+ }
53951
54024
  /** Copy named user-level entries into one Agent's vault (see the module doc: a copy, not a link). */
53952
54025
  async assignToAgent(userId, projectId, agentId, keys) {
53953
54026
  const wanted = [...new Set(keys)];
@@ -55454,6 +55527,25 @@ function modelsRoutes(deps) {
55454
55527
  modelConfigChanged(deps, projectId);
55455
55528
  return c.json(res);
55456
55529
  });
55530
+ app.post("/assign-user-key", async (c) => {
55531
+ const projectId = requireValidId(c, "projectId");
55532
+ deps.access.requireProjectOwner(c.var.user.userId, projectId);
55533
+ const body = await readJson(c);
55534
+ const provider = requireString(body, "provider", {
55535
+ minLen: 1,
55536
+ maxLen: 64,
55537
+ label: "provider"
55538
+ });
55539
+ const key2 = requireString(body, "key", { minLen: 1, maxLen: 128, label: "key" });
55540
+ const value = await deps.userVault.readEntry(c.var.user.userId, key2);
55541
+ if (value === void 0) {
55542
+ throw badRequest(`Not in your user vault: ${key2}.`);
55543
+ }
55544
+ const applied = await deps.projectConfigService.setGroupApiKey(projectId, provider, value);
55545
+ if (applied > 0) modelConfigChanged(deps, projectId);
55546
+ const res = { applied };
55547
+ return c.json(res);
55548
+ });
55457
55549
  app.get("/balance", async (c) => {
55458
55550
  const projectId = requireValidId(c, "projectId");
55459
55551
  deps.access.requireProjectAccess(c.var.user.userId, projectId);
@@ -57919,7 +58011,8 @@ var SessionApiRoutes = class {
57919
58011
  channels,
57920
58012
  machines: this.machines,
57921
58013
  projectConfigService,
57922
- sessionsRepo
58014
+ sessionsRepo,
58015
+ userVault: this.userVault
57923
58016
  };
57924
58017
  const modelDeps = {
57925
58018
  channels,
@@ -57927,7 +58020,8 @@ var SessionApiRoutes = class {
57927
58020
  machines: this.machines,
57928
58021
  projectConfigService,
57929
58022
  access,
57930
- sessionsRepo
58023
+ sessionsRepo,
58024
+ userVault: this.userVault
57931
58025
  };
57932
58026
  this.modelOauthCallbackRoutes = modelOAuthCallbackRoutes(modelOAuthDeps);
57933
58027
  this.modelsRoutes = modelsRoutes(modelDeps);