@kubb/studio 5.11.2 → 5.11.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/dist/index.d.cts CHANGED
@@ -1,4 +1,4 @@
1
- import { D as InstalledExtensions, P as PublishedSnapshot, W as SnapshotUploadMetadata, a as AgentConnectInfo, c as AgentPermissions, d as ConfigEditOutcome, s as AgentPermission, u as ConfigEdit } from "./protocol-BUZ91Gd4.cjs";
1
+ import { D as InstalledExtensions, P as PublishedSnapshot, W as SnapshotUploadMetadata, a as AgentConnectInfo, c as AgentPermissions, d as ConfigEditOutcome, s as AgentPermission, u as ConfigEdit } from "./protocol-DpxvWX9E.cjs";
2
2
  import { Config, Hookable, KubbHooks } from "@kubb/core";
3
3
  //#region src/connect.d.ts
4
4
  /**
package/dist/index.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { D as InstalledExtensions, P as PublishedSnapshot, W as SnapshotUploadMetadata, a as AgentConnectInfo, c as AgentPermissions, d as ConfigEditOutcome, s as AgentPermission, u as ConfigEdit } from "./protocol-BUZ91Gd4.js";
1
+ import { D as InstalledExtensions, P as PublishedSnapshot, W as SnapshotUploadMetadata, a as AgentConnectInfo, c as AgentPermissions, d as ConfigEditOutcome, s as AgentPermission, u as ConfigEdit } from "./protocol-DpxvWX9E.js";
2
2
  import { Config, Hookable, KubbHooks } from "@kubb/core";
3
3
  //#region src/connect.d.ts
4
4
  /**
package/dist/index.js CHANGED
@@ -1,4 +1,4 @@
1
- import { AGENT_INSTANCE_HEADER, AGENT_SOCKET_PATH, AgentCloseCode, AgentMessage, AgentPermission, FileSource, MAX_PAGE_LINES, MAX_SNAPSHOT_BYTES, generationEventTypes } from "./protocol.js";
1
+ import { AGENT_INSTANCE_HEADER, AGENT_SOCKET_PATH, AgentCloseCode, AgentMessage, AgentPermission, FileSource, MAX_SNAPSHOT_BYTES, generationEventTypes } from "./protocol.js";
2
2
  import { createRequire } from "node:module";
3
3
  import { createHash, hash, randomUUID } from "node:crypto";
4
4
  import { mkdir, mkdtemp, readFile, rm, writeFile } from "node:fs/promises";
@@ -175,7 +175,7 @@ function getElapsedMs(hrStart) {
175
175
  }
176
176
  //#endregion
177
177
  //#region package.json
178
- var version = "5.11.2";
178
+ var version = "5.11.3";
179
179
  //#endregion
180
180
  //#region src/resolveConfig.ts
181
181
  /**
@@ -1449,6 +1449,33 @@ async function listDisk({ root, outputPath, maxFiles }) {
1449
1449
  paths: new Set(paths)
1450
1450
  };
1451
1451
  }
1452
+ async function readDiskFiles({ files: disk, paths, cursor = 0, limit }) {
1453
+ const files = {};
1454
+ const pages = {};
1455
+ await inParallel({
1456
+ items: paths.filter((path) => disk.paths.has(path)),
1457
+ limit: READ_CONCURRENCY,
1458
+ run: async (path) => {
1459
+ const content = await disk.storage.readItem(resolve(disk.root, path));
1460
+ if (content === null) return;
1461
+ if (limit === void 0) {
1462
+ files[path] = content;
1463
+ return;
1464
+ }
1465
+ const lines = content.split(/\r\n|\r|\n/);
1466
+ const end = Math.min(cursor + limit, lines.length);
1467
+ files[path] = lines.slice(cursor, end).join("\n");
1468
+ pages[path] = {
1469
+ nextCursor: end < lines.length ? end : null,
1470
+ totalLines: lines.length
1471
+ };
1472
+ }
1473
+ });
1474
+ return limit === void 0 ? { files } : {
1475
+ files,
1476
+ pages
1477
+ };
1478
+ }
1452
1479
  /**
1453
1480
  * Keeps recent generations by job id in `storage`, with an index next to them so a store on disk
1454
1481
  * survives a restart. A generation is only ever looked up by its job id, so on a pooled sandbox one
@@ -1998,23 +2025,7 @@ var Agent = class extends RpcTarget {
1998
2025
  maxFiles: DISK_SNAPSHOT_MAX_FILES
1999
2026
  });
2000
2027
  if (!files) return void 0;
2001
- const jobId = randomUUID();
2002
- const output = await this.#generations.keep({
2003
- jobId,
2004
- source: FileSource.OUTPUT,
2005
- files,
2006
- maxSetMb: this.#limits.maxSnapshotMb,
2007
- normalize: false
2008
- });
2009
- await this.#generations.add({
2010
- jobId,
2011
- output
2012
- });
2013
- return {
2014
- jobId,
2015
- files: output.paths,
2016
- hashes: output.hashes
2017
- };
2028
+ return { files: [...files.paths] };
2018
2029
  }
2019
2030
  startGeneration(input) {
2020
2031
  const stream = createGenerationStream(this.#options.hooks, input.jobId);
@@ -2041,7 +2052,7 @@ var Agent = class extends RpcTarget {
2041
2052
  severity: "error",
2042
2053
  message: "Connection is closed"
2043
2054
  });
2044
- if (this.#session.active) return this.#refuse({ message: "A generation is already in progress, please wait for it to finish" });
2055
+ if (this.#session.active) return this.#refuse({ message: AgentMessage.GENERATION_IN_PROGRESS });
2045
2056
  const settled = Promise.withResolvers();
2046
2057
  this.#session.active = {
2047
2058
  jobId: input.jobId,
@@ -2072,7 +2083,7 @@ var Agent = class extends RpcTarget {
2072
2083
  async #generate({ input, root, signal }) {
2073
2084
  const { jobId, config: patch } = input;
2074
2085
  const studioInput = this.#sandbox ? patch?.input : void 0;
2075
- if (this.#sandbox && (typeof studioInput !== "string" || !studioInput.trim() || getInputKind(studioInput) !== "inline")) return this.#refuse({ message: "A sandbox agent generates only from the OpenAPI document content Studio sends, not from a file path or URL" });
2086
+ if (this.#sandbox && (typeof studioInput !== "string" || !studioInput.trim() || getInputKind(studioInput) !== "inline")) return this.#refuse({ message: AgentMessage.SANDBOX_INPUT_ONLY });
2076
2087
  const [config, extensions] = await Promise.all([this.#options.loadConfig(), this.#installedExtensions()]);
2077
2088
  const [plugins, adapter, parsers] = await Promise.all([
2078
2089
  mergePlugins({
@@ -2205,7 +2216,7 @@ var Agent = class extends RpcTarget {
2205
2216
  message: AgentMessage.READ_AST_NOT_ALLOWED,
2206
2217
  permission: AgentPermission.READ_AST
2207
2218
  });
2208
- if (typeof input.jobId !== "string" || !input.jobId) return this.#refuse({ message: "The request must name a job" });
2219
+ if (typeof input.jobId !== "string" || !input.jobId) return this.#refuse({ message: AgentMessage.JOB_REQUIRED });
2209
2220
  const generation = await this.#generations.get(input.jobId);
2210
2221
  if (!generation) return this.#refuse({ message: AgentMessage.GENERATION_GONE });
2211
2222
  const kept = generation.inputBytes ? await this.#generations.readInput(input.jobId) : void 0;
@@ -2222,14 +2233,32 @@ var Agent = class extends RpcTarget {
2222
2233
  message: AgentMessage.READ_NOT_ALLOWED,
2223
2234
  permission: AgentPermission.READ
2224
2235
  });
2225
- if (!Array.isArray(input.paths) || typeof input.jobId !== "string" || !input.jobId) return this.#refuse({ message: "The request must name a job and carry paths" });
2236
+ if (!Array.isArray(input.paths) || typeof input.jobId !== "string" || !input.jobId || !["generation", "currentDisk"].includes(input.jobType)) return this.#refuse({ message: AgentMessage.FILE_REQUEST_INVALID });
2226
2237
  const { paths } = input;
2227
- if (paths.length > 50) return this.#refuse({ message: `At most 50 paths may be requested at once` });
2238
+ if (paths.length > 50) return this.#refuse({ message: AgentMessage.TOO_MANY_FILES });
2239
+ if (!isValidPage(input)) return this.#refuse({ message: AgentMessage.INVALID_PAGE });
2240
+ if (input.jobType === "currentDisk") {
2241
+ if (this.#sandbox) return this.#refuse({ message: AgentMessage.SANDBOX_DISK_UNAVAILABLE });
2242
+ const config = await this.#options.loadConfig();
2243
+ const disk = await listDisk({
2244
+ root: this.#options.root,
2245
+ outputPath: config.output.path,
2246
+ maxFiles: DISK_SNAPSHOT_MAX_FILES
2247
+ });
2248
+ if (!disk) return this.#refuse({ message: AgentMessage.GENERATION_GONE });
2249
+ const result = await readDiskFiles({
2250
+ files: disk,
2251
+ paths,
2252
+ cursor: input.cursor,
2253
+ limit: input.limit
2254
+ });
2255
+ await this.#logCommand("readFiles", `read ${Object.keys(result.files).length}/${paths.length} requested file${paths.length === 1 ? "" : "s"}`);
2256
+ return result;
2257
+ }
2228
2258
  const generation = await this.#generations.get(input.jobId);
2229
2259
  if (!generation) return this.#refuse({ message: AgentMessage.GENERATION_GONE });
2230
- if (!isValidPage(input)) return this.#refuse({ message: `The cursor must be a whole line from 0 and come with a limit of 1 to ${MAX_PAGE_LINES} lines` });
2231
2260
  const source = input.source === FileSource.DISK ? FileSource.DISK : FileSource.OUTPUT;
2232
- if (!generation[source]) return this.#refuse({ message: "This agent kept no snapshot of the files on disk for that job" });
2261
+ if (!generation[source]) return this.#refuse({ message: AgentMessage.NO_DISK_SNAPSHOT });
2233
2262
  const result = await this.#generations.read({
2234
2263
  generation,
2235
2264
  source,
@@ -2250,15 +2279,15 @@ var Agent = class extends RpcTarget {
2250
2279
  permission: AgentPermission.READ
2251
2280
  });
2252
2281
  const { jobId, path, base, cursor = 0, limit } = input;
2253
- if (typeof jobId !== "string" || !jobId || typeof path !== "string" || !path || typeof base?.jobId !== "string" || !base.jobId) return this.#refuse({ message: "The request must name a job, a base, and a path" });
2282
+ if (typeof jobId !== "string" || !jobId || typeof path !== "string" || !path || typeof base?.jobId !== "string" || !base.jobId) return this.#refuse({ message: AgentMessage.DIFF_REQUEST_INVALID });
2254
2283
  if (!isValidPage({
2255
2284
  cursor,
2256
2285
  limit
2257
- })) return this.#refuse({ message: `The cursor must be a whole line from 0 and come with a limit of 1 to ${MAX_PAGE_LINES} lines` });
2286
+ })) return this.#refuse({ message: AgentMessage.INVALID_PAGE });
2258
2287
  const [generation, baseGeneration] = await Promise.all([this.#generations.get(jobId), this.#generations.get(base.jobId)]);
2259
2288
  if (!generation || !baseGeneration) return this.#refuse({ message: AgentMessage.GENERATION_GONE });
2260
2289
  const baseSource = base.source === FileSource.DISK ? FileSource.DISK : FileSource.OUTPUT;
2261
- if (!baseGeneration[baseSource]) return this.#refuse({ message: "This agent kept no snapshot of the files on disk for that job" });
2290
+ if (!baseGeneration[baseSource]) return this.#refuse({ message: AgentMessage.NO_DISK_SNAPSHOT });
2262
2291
  const [after, before] = await Promise.all([this.#generations.read({
2263
2292
  generation,
2264
2293
  source: FileSource.OUTPUT,
@@ -2269,7 +2298,7 @@ var Agent = class extends RpcTarget {
2269
2298
  paths: [path]
2270
2299
  })]);
2271
2300
  const afterContent = after.files[path];
2272
- if (afterContent === void 0 && path in generation.output.hashes) return this.#refuse({ message: "This agent kept only the hashes of that job" });
2301
+ if (afterContent === void 0 && path in generation.output.hashes) return this.#refuse({ message: AgentMessage.HASHES_ONLY });
2273
2302
  const beforeContent = before.files[path];
2274
2303
  if (beforeContent === void 0) return {
2275
2304
  hunks: [],