@kubb/studio 5.9.3 → 5.9.5
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/README.md +2 -2
- package/dist/index.cjs +131 -79
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +2 -2
- package/dist/index.js +134 -82
- package/dist/index.js.map +1 -1
- package/dist/{protocol-gXoAXvT3.d.ts → protocol-ixLkhvRJ.d.ts} +21 -2
- package/dist/protocol.cjs +4 -0
- package/dist/protocol.cjs.map +1 -1
- package/dist/protocol.d.ts +2 -2
- package/dist/protocol.js +3 -1
- package/dist/protocol.js.map +1 -1
- package/package.json +4 -4
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { t as __name } from "./rolldown-runtime-CRm0XQPb.js";
|
|
2
|
-
import {
|
|
2
|
+
import { M as PublishedSnapshot, V as SnapshotUploadMetadata, a as AgentConnectInfo, c as ConfigEdit, l as ConfigEditOutcome, o as AgentPermissions, w as InstalledExtensions } from "./protocol-ixLkhvRJ.js";
|
|
3
3
|
import { Config, Hookable, KubbHooks } from "@kubb/core";
|
|
4
4
|
//#region src/connect.d.ts
|
|
5
5
|
/**
|
|
@@ -46,7 +46,7 @@ declare global {
|
|
|
46
46
|
* A finished command and what it did, such as `applied 2/3 edits to kubb.config.ts`.
|
|
47
47
|
*/
|
|
48
48
|
'studio:command': [ctx: {
|
|
49
|
-
command: 'generate' | 'saveConfig' | 'readFiles';
|
|
49
|
+
command: 'generate' | 'saveConfig' | 'readFiles' | 'readInput';
|
|
50
50
|
info: string;
|
|
51
51
|
}];
|
|
52
52
|
/**
|
package/dist/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import "./rolldown-runtime-CRm0XQPb.js";
|
|
2
|
-
import { AGENT_INSTANCE_HEADER, AGENT_SOCKET_PATH, AgentCloseCode, GENERATION_GONE_MESSAGE, MAX_PAGE_LINES, MAX_SNAPSHOT_BYTES, generationEventTypes } from "./protocol.js";
|
|
2
|
+
import { AGENT_INSTANCE_HEADER, AGENT_SOCKET_PATH, AgentCloseCode, GENERATION_GONE_MESSAGE, MAX_PAGE_LINES, MAX_SNAPSHOT_BYTES, NO_INPUT_MESSAGE, READ_NOT_ALLOWED_MESSAGE, generationEventTypes } from "./protocol.js";
|
|
3
3
|
import { createRequire } from "node:module";
|
|
4
4
|
import { createHash, hash, randomUUID } from "node:crypto";
|
|
5
5
|
import { mkdir, mkdtemp, readFile, rm, writeFile } from "node:fs/promises";
|
|
@@ -12,9 +12,10 @@ import { existsSync } from "node:fs";
|
|
|
12
12
|
import { Diagnostics, Hookable, cacheStorage, createKubb, fsStorage, getInputKind, isPackageName, memoryStorage, readInstalledPackages, resolveCacheDir, resolveMeta } from "@kubb/core";
|
|
13
13
|
import { RpcTarget, newWebSocketRpcSession } from "capnweb";
|
|
14
14
|
import { detectCodeFormat, parseExpression, parseModule } from "magicast";
|
|
15
|
-
import {
|
|
15
|
+
import { stripVTControlCharacters } from "node:util";
|
|
16
|
+
import { ast } from "@kubb/ast";
|
|
16
17
|
import { ofetch } from "ofetch";
|
|
17
|
-
import {
|
|
18
|
+
import { gzipSync } from "node:zlib";
|
|
18
19
|
//#region ../../internals/utils/src/casing.ts
|
|
19
20
|
/**
|
|
20
21
|
* Shared implementation for camelCase and PascalCase conversion.
|
|
@@ -152,10 +153,18 @@ function getElapsedMs(hrStart) {
|
|
|
152
153
|
}
|
|
153
154
|
//#endregion
|
|
154
155
|
//#region package.json
|
|
155
|
-
var version = "5.9.
|
|
156
|
+
var version = "5.9.5";
|
|
156
157
|
//#endregion
|
|
157
158
|
//#region src/resolveConfig.ts
|
|
158
159
|
/**
|
|
160
|
+
* Turns the JSON config Studio sends back into live Kubb objects.
|
|
161
|
+
*
|
|
162
|
+
* A plugin or adapter instance carries closures (`parse`, `getImports`, ...) that cannot survive
|
|
163
|
+
* JSON, so both sides pass options over the wire and the factory is re-invoked here with the merged
|
|
164
|
+
* result. Only packages {@link isAllowedPlugin} accepts are resolved this way, never an arbitrary
|
|
165
|
+
* module the payload names.
|
|
166
|
+
*/
|
|
167
|
+
/**
|
|
159
168
|
* Imports a package, falling back to how the user's project would resolve it.
|
|
160
169
|
*
|
|
161
170
|
* `import()` resolves from this file, so a linked or globally installed Studio (`pnpm link`,
|
|
@@ -234,8 +243,9 @@ function isAllowedPlugin({ packageName, extensions }) {
|
|
|
234
243
|
return KUBB_PLUGIN_SPECIFIER.test(packageName) || extensions.get(packageName)?.manifest.kind === "plugin";
|
|
235
244
|
}
|
|
236
245
|
/**
|
|
237
|
-
* Dynamically imports
|
|
238
|
-
* {@link isAllowedPlugin}
|
|
246
|
+
* Dynamically imports an extension package and returns its factory. Callers check
|
|
247
|
+
* {@link isAllowedPlugin} or derive the package from a disk instance first, so an arbitrary module
|
|
248
|
+
* never reaches `import()`.
|
|
239
249
|
*
|
|
240
250
|
* Packages must be pre-installed in the Docker image at build time via the `KUBB_PACKAGES`
|
|
241
251
|
* build ARG, no runtime installation is possible in the distroless container.
|
|
@@ -243,13 +253,9 @@ function isAllowedPlugin({ packageName, extensions }) {
|
|
|
243
253
|
* Resolution order: the manifest's `export`, else the camelCase named export the package name
|
|
244
254
|
* implies (e.g. `pluginTs`), then the default export.
|
|
245
255
|
*
|
|
246
|
-
* @throws if the package
|
|
256
|
+
* @throws if the package cannot be imported or exports no callable factory.
|
|
247
257
|
*/
|
|
248
|
-
async function
|
|
249
|
-
if (!isAllowedPlugin({
|
|
250
|
-
packageName,
|
|
251
|
-
extensions
|
|
252
|
-
})) throw new Error(`Plugin "${packageName}" is not an installed Kubb plugin. Studio loads @kubb/plugin-* packages and installed packages that ship a kubb-extension.json with kind "plugin".`);
|
|
258
|
+
async function loadFactory({ packageName, extensions }) {
|
|
253
259
|
let mod;
|
|
254
260
|
try {
|
|
255
261
|
mod = await importFromProject(packageName);
|
|
@@ -268,7 +274,7 @@ async function loadPluginFactory({ packageName, extensions }) {
|
|
|
268
274
|
}
|
|
269
275
|
/**
|
|
270
276
|
* Resolves each plugin entry by dynamically importing its package and calling its factory with the
|
|
271
|
-
* provided options.
|
|
277
|
+
* provided options. Only packages {@link isAllowedPlugin} accepts are loaded.
|
|
272
278
|
*
|
|
273
279
|
* @example
|
|
274
280
|
* ```ts
|
|
@@ -282,7 +288,11 @@ async function loadPluginFactory({ packageName, extensions }) {
|
|
|
282
288
|
*/
|
|
283
289
|
async function resolvePlugins({ plugins, extensions = /* @__PURE__ */ new Map() }) {
|
|
284
290
|
return Promise.all(plugins.map(async ({ name, options }) => {
|
|
285
|
-
|
|
291
|
+
if (!isAllowedPlugin({
|
|
292
|
+
packageName: name,
|
|
293
|
+
extensions
|
|
294
|
+
})) throw new Error(`Plugin "${name}" is not an installed Kubb plugin. Studio loads @kubb/plugin-* packages and installed packages that ship a kubb-extension.json with kind "plugin".`);
|
|
295
|
+
return (await loadFactory({
|
|
286
296
|
packageName: name,
|
|
287
297
|
extensions
|
|
288
298
|
}))(options ?? {});
|
|
@@ -430,13 +440,12 @@ async function mergePlugins({ diskPlugins, studioPlugins, extensions = /* @__PUR
|
|
|
430
440
|
async function rebuildExtension({ disk, studioOptions, kind, extensions }) {
|
|
431
441
|
if (!studioOptions || !Object.keys(studioOptions).length) return disk;
|
|
432
442
|
const { name } = resolveMeta(disk);
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
443
|
+
return (await loadFactory({
|
|
444
|
+
packageName: [...extensions.values()].find(({ manifest }) => manifest.kind === kind && manifest.name === name)?.package ?? `@kubb/${kind}-${name}`,
|
|
445
|
+
extensions
|
|
446
|
+
}).catch((cause) => {
|
|
436
447
|
throw new Error(`The ${kind} "${name}" is not an installed Kubb extension, so Studio cannot change its options. Edit it in the config file.`, { cause });
|
|
437
|
-
});
|
|
438
|
-
if (typeof factory !== "function") throw new Error(`The ${kind} "${name}" is not an installed Kubb extension, so Studio cannot change its options. Edit it in the config file.`);
|
|
439
|
-
return factory(mergeOptions(disk.options ?? {}, studioOptions));
|
|
448
|
+
}))(mergeOptions(disk.options ?? {}, studioOptions));
|
|
440
449
|
}
|
|
441
450
|
/**
|
|
442
451
|
* Merges Studio-provided adapter option overrides into the disk config's adapter, see {@link rebuildExtension}.
|
|
@@ -1075,7 +1084,10 @@ function relativeStoragePath({ root, filePath }) {
|
|
|
1075
1084
|
* The content fingerprint Studio compares snapshots by. Agent runs and CI uploads must agree on it.
|
|
1076
1085
|
*/
|
|
1077
1086
|
const hashOf = (content) => createHash("sha1").update(content).digest("hex").slice(0, 16);
|
|
1078
|
-
|
|
1087
|
+
/**
|
|
1088
|
+
* The bytes `entries` keep on disk: output, written files, and kept input.
|
|
1089
|
+
*/
|
|
1090
|
+
const totalBytes = (entries) => entries.reduce((sum, { output, disk, inputBytes }) => sum + output.bytes + (disk?.bytes ?? 0) + (inputBytes ?? 0), 0);
|
|
1079
1091
|
function positiveNumber(value) {
|
|
1080
1092
|
const parsed = Number(value);
|
|
1081
1093
|
return value && Number.isFinite(parsed) && parsed > 0 ? parsed : void 0;
|
|
@@ -1118,7 +1130,11 @@ async function generate({ config, hooks, signal, allowExec }) {
|
|
|
1118
1130
|
hooks,
|
|
1119
1131
|
signal
|
|
1120
1132
|
});
|
|
1121
|
-
|
|
1133
|
+
let input = null;
|
|
1134
|
+
const unhook = kubb.hooks.hook("kubb:build:end", (ctx) => {
|
|
1135
|
+
if (ctx.config === kubb.config) input = kubb.driver.inputNode;
|
|
1136
|
+
});
|
|
1137
|
+
const result = await kubb.generate().finally(unhook);
|
|
1122
1138
|
if (!result.success) throw generationFailure(result.diagnostics);
|
|
1123
1139
|
const { storage, root } = kubb.config;
|
|
1124
1140
|
return {
|
|
@@ -1127,7 +1143,8 @@ async function generate({ config, hooks, signal, allowExec }) {
|
|
|
1127
1143
|
paths: new Set(result.files.map((file) => relativeStoragePath({
|
|
1128
1144
|
root,
|
|
1129
1145
|
filePath: file.path
|
|
1130
|
-
})))
|
|
1146
|
+
}))),
|
|
1147
|
+
input
|
|
1131
1148
|
};
|
|
1132
1149
|
}
|
|
1133
1150
|
/**
|
|
@@ -1208,6 +1225,33 @@ function createGenerationStore({ storage, maxCount, maxMb, ttlMs, now = Date.now
|
|
|
1208
1225
|
return {
|
|
1209
1226
|
keep,
|
|
1210
1227
|
drop,
|
|
1228
|
+
/**
|
|
1229
|
+
* Keeps the `InputNode` of `jobId` and returns its size in bytes, or 0 when it keeps none. A ref schema loses
|
|
1230
|
+
* the copy of its target, which `input.schemas` holds: with it, a large spec outgrows what `JSON.stringify` can return.
|
|
1231
|
+
*/
|
|
1232
|
+
async keepInput({ jobId, input, maxSetMb }) {
|
|
1233
|
+
if (!input) return 0;
|
|
1234
|
+
let json;
|
|
1235
|
+
try {
|
|
1236
|
+
json = JSON.stringify(ast.transform(input, { schema: (node) => node.type === "ref" && node.schema ? {
|
|
1237
|
+
...node,
|
|
1238
|
+
schema: void 0
|
|
1239
|
+
} : void 0 }));
|
|
1240
|
+
} catch {
|
|
1241
|
+
return 0;
|
|
1242
|
+
}
|
|
1243
|
+
const bytes = Buffer.byteLength(json);
|
|
1244
|
+
if (bytes > maxSetMb * MB) return 0;
|
|
1245
|
+
await storage.writeItem(`${dirOf(jobId)}input.json`, json);
|
|
1246
|
+
return bytes;
|
|
1247
|
+
},
|
|
1248
|
+
/**
|
|
1249
|
+
* The input `keepInput` kept for `jobId`, or `undefined` when there is none.
|
|
1250
|
+
*/
|
|
1251
|
+
async readInput(jobId) {
|
|
1252
|
+
const stored = await storage.readItem(`${dirOf(jobId)}input.json`);
|
|
1253
|
+
return stored === null ? void 0 : JSON.parse(stored);
|
|
1254
|
+
},
|
|
1211
1255
|
get: async (jobId) => (await load()).find((generation) => generation.jobId === jobId && isLive(generation)),
|
|
1212
1256
|
async add(generation) {
|
|
1213
1257
|
const current = await load();
|
|
@@ -1431,7 +1475,6 @@ function createGenerationStream(hooks, jobId) {
|
|
|
1431
1475
|
return {
|
|
1432
1476
|
stream,
|
|
1433
1477
|
close,
|
|
1434
|
-
dispose: () => fail(),
|
|
1435
1478
|
fail
|
|
1436
1479
|
};
|
|
1437
1480
|
}
|
|
@@ -1564,29 +1607,29 @@ var Agent = class extends RpcTarget {
|
|
|
1564
1607
|
});
|
|
1565
1608
|
throw new Error(message);
|
|
1566
1609
|
}
|
|
1567
|
-
|
|
1610
|
+
#assertConnected() {
|
|
1568
1611
|
if (!this.#session.info) throw new Error("Studio must call connect() before any other command");
|
|
1569
|
-
|
|
1570
|
-
|
|
1612
|
+
}
|
|
1613
|
+
#logCommand(command, info) {
|
|
1614
|
+
return emit(this.#options.hooks, "studio:command", {
|
|
1571
1615
|
command,
|
|
1572
1616
|
info
|
|
1573
1617
|
});
|
|
1574
|
-
return value;
|
|
1575
1618
|
}
|
|
1576
|
-
async #readConfigFileView() {
|
|
1619
|
+
async #readConfigFileView(source) {
|
|
1577
1620
|
if (!this.#permissions.allowConfigEdit) return void 0;
|
|
1578
1621
|
try {
|
|
1579
|
-
return readConfig(await
|
|
1622
|
+
return readConfig(await source);
|
|
1580
1623
|
} catch (error) {
|
|
1581
1624
|
await this.#warn({ message: `Could not read ${this.#options.configFile}: ${getErrorMessage(error)}` });
|
|
1582
1625
|
return;
|
|
1583
1626
|
}
|
|
1584
1627
|
}
|
|
1585
|
-
async #installedExtensions() {
|
|
1586
|
-
const
|
|
1628
|
+
async #installedExtensions(source = read(this.#options.configFile)) {
|
|
1629
|
+
const imports = await source.then(readImports, () => []);
|
|
1587
1630
|
const installed = await readInstalledPackages({
|
|
1588
1631
|
root: this.#options.root,
|
|
1589
|
-
packages: [...
|
|
1632
|
+
packages: [...imports, ...BUILT_IN_PACKAGES],
|
|
1590
1633
|
resolveFrom: ["kubb"]
|
|
1591
1634
|
});
|
|
1592
1635
|
return new Map(installed.flatMap(({ package: name, version, manifest }) => version !== void 0 && manifest ? [[name, {
|
|
@@ -1597,11 +1640,12 @@ var Agent = class extends RpcTarget {
|
|
|
1597
1640
|
}
|
|
1598
1641
|
async connect(info) {
|
|
1599
1642
|
this.#session.info = info;
|
|
1600
|
-
const { configPath, root, version: version$1, loadConfig } = this.#options;
|
|
1643
|
+
const { configPath, root, version: version$1, loadConfig, configFile } = this.#options;
|
|
1644
|
+
const source = read(configFile);
|
|
1601
1645
|
const [config, file, extensions] = await Promise.all([
|
|
1602
1646
|
loadConfig(),
|
|
1603
|
-
this.#readConfigFileView(),
|
|
1604
|
-
this.#installedExtensions()
|
|
1647
|
+
this.#readConfigFileView(source),
|
|
1648
|
+
this.#installedExtensions(source)
|
|
1605
1649
|
]);
|
|
1606
1650
|
this.#session.connected.resolve(info);
|
|
1607
1651
|
return {
|
|
@@ -1654,11 +1698,13 @@ var Agent = class extends RpcTarget {
|
|
|
1654
1698
|
result,
|
|
1655
1699
|
stop: () => {
|
|
1656
1700
|
controller.abort(/* @__PURE__ */ new Error("Generation canceled"));
|
|
1657
|
-
stream.
|
|
1701
|
+
stream.fail();
|
|
1658
1702
|
}
|
|
1659
1703
|
});
|
|
1660
1704
|
}
|
|
1705
|
+
/** Runs one job and keeps its output, and its input with `allowRead`, for later reads. */
|
|
1661
1706
|
async #runGeneration(input, controller) {
|
|
1707
|
+
this.#assertConnected();
|
|
1662
1708
|
if (this.#session.closed) throw new Error("Connection is closed");
|
|
1663
1709
|
if (this.#session.active) return this.#refuse({ message: "A generation is already in progress, please wait for it to finish" });
|
|
1664
1710
|
const settled = Promise.withResolvers();
|
|
@@ -1670,13 +1716,10 @@ var Agent = class extends RpcTarget {
|
|
|
1670
1716
|
let root = this.#options.root;
|
|
1671
1717
|
try {
|
|
1672
1718
|
if (this.#sandbox) root = await mkdtemp(path.join(tmpdir(), "kubb-job-"));
|
|
1673
|
-
return await this.#
|
|
1674
|
-
|
|
1675
|
-
|
|
1676
|
-
|
|
1677
|
-
root,
|
|
1678
|
-
signal: controller.signal
|
|
1679
|
-
})
|
|
1719
|
+
return await this.#generate({
|
|
1720
|
+
input,
|
|
1721
|
+
root,
|
|
1722
|
+
signal: controller.signal
|
|
1680
1723
|
});
|
|
1681
1724
|
} finally {
|
|
1682
1725
|
if (root !== this.#options.root) await Promise.all([rm(root, {
|
|
@@ -1747,37 +1790,36 @@ var Agent = class extends RpcTarget {
|
|
|
1747
1790
|
files,
|
|
1748
1791
|
maxSetMb: this.#limits.maxMb
|
|
1749
1792
|
});
|
|
1793
|
+
const inputBytes = await this.#generations.keepInput({
|
|
1794
|
+
jobId,
|
|
1795
|
+
input: this.#permissions.allowRead ? files.input : null,
|
|
1796
|
+
maxSetMb: this.#limits.maxMb
|
|
1797
|
+
});
|
|
1750
1798
|
if (!output.paths.length && Object.keys(output.hashes).length) await this.#warn({ message: "Kept only the hashes of this generation: its output is too large to keep" });
|
|
1751
1799
|
await this.#generations.add({
|
|
1752
1800
|
jobId,
|
|
1753
1801
|
output,
|
|
1754
|
-
disk
|
|
1802
|
+
disk,
|
|
1803
|
+
inputBytes
|
|
1755
1804
|
});
|
|
1805
|
+
await this.#logCommand("generate", `${activePlugins.length} plugin${activePlugins.length === 1 ? "" : "s"}, ${this.#permissions.allowWrite ? "written to disk" : "in memory"}${studioInput !== void 0 ? ", from a Studio spec" : ""}`);
|
|
1756
1806
|
return {
|
|
1757
|
-
|
|
1758
|
-
|
|
1759
|
-
|
|
1760
|
-
|
|
1761
|
-
|
|
1762
|
-
disk: disk ? { hashes: disk.hashes } : void 0
|
|
1763
|
-
},
|
|
1764
|
-
info: `${activePlugins.length} plugin${activePlugins.length === 1 ? "" : "s"}, ${this.#permissions.allowWrite ? "written to disk" : "in memory"}${studioInput !== void 0 ? ", from a Studio spec" : ""}`
|
|
1807
|
+
status: "success",
|
|
1808
|
+
files: [...files.paths],
|
|
1809
|
+
fileCount: files.paths.size,
|
|
1810
|
+
hashes: output.hashes,
|
|
1811
|
+
disk: disk ? { hashes: disk.hashes } : void 0
|
|
1765
1812
|
};
|
|
1766
1813
|
}
|
|
1767
|
-
saveConfig(input) {
|
|
1768
|
-
|
|
1769
|
-
command: "saveConfig",
|
|
1770
|
-
run: () => this.#saveConfig(input)
|
|
1771
|
-
});
|
|
1772
|
-
}
|
|
1773
|
-
async #saveConfig(input) {
|
|
1814
|
+
async saveConfig(input) {
|
|
1815
|
+
this.#assertConnected();
|
|
1774
1816
|
const { configPath, configFile } = this.#options;
|
|
1775
1817
|
if (!Array.isArray(input.edits)) {
|
|
1776
1818
|
await this.#warn({ message: "Ignored save: the message carried no edits" });
|
|
1777
|
-
return {
|
|
1819
|
+
return {
|
|
1778
1820
|
outcomes: [],
|
|
1779
1821
|
changed: false
|
|
1780
|
-
}
|
|
1822
|
+
};
|
|
1781
1823
|
}
|
|
1782
1824
|
const edits = input.edits;
|
|
1783
1825
|
const refuse = (reason) => ({
|
|
@@ -1790,9 +1832,9 @@ var Agent = class extends RpcTarget {
|
|
|
1790
1832
|
});
|
|
1791
1833
|
if (!this.#permissions.allowConfigEdit) {
|
|
1792
1834
|
await this.#warn({ message: "Ignored save: editing kubb.config.ts was not granted" });
|
|
1793
|
-
return
|
|
1835
|
+
return refuse("the agent was not granted permission to edit kubb.config.ts");
|
|
1794
1836
|
}
|
|
1795
|
-
if (this.#session.active) return
|
|
1837
|
+
if (this.#session.active) return refuse("a generation is in progress");
|
|
1796
1838
|
try {
|
|
1797
1839
|
const { outcomes, changed } = await writeConfigEdits({
|
|
1798
1840
|
filePath: configFile,
|
|
@@ -1800,27 +1842,40 @@ var Agent = class extends RpcTarget {
|
|
|
1800
1842
|
extensions: await this.#installedExtensions()
|
|
1801
1843
|
});
|
|
1802
1844
|
const applied = outcomes.filter((outcome) => outcome.applied).length;
|
|
1845
|
+
await this.#logCommand("saveConfig", `applied ${applied}/${outcomes.length} edits to ${configPath}`);
|
|
1803
1846
|
return {
|
|
1804
|
-
|
|
1805
|
-
|
|
1806
|
-
changed
|
|
1807
|
-
},
|
|
1808
|
-
info: `applied ${applied}/${outcomes.length} edits to ${configPath}`
|
|
1847
|
+
outcomes,
|
|
1848
|
+
changed
|
|
1809
1849
|
};
|
|
1810
1850
|
} catch (error) {
|
|
1811
1851
|
await emit(this.#options.hooks, "studio:error", { error: toError(error) });
|
|
1812
|
-
return
|
|
1852
|
+
return refuse(getErrorMessage(error));
|
|
1813
1853
|
}
|
|
1814
1854
|
}
|
|
1815
|
-
|
|
1816
|
-
|
|
1817
|
-
|
|
1818
|
-
|
|
1855
|
+
/**
|
|
1856
|
+
* Returns the Kubb AST a kept job parsed its spec into. Refused without `allowRead`.
|
|
1857
|
+
*/
|
|
1858
|
+
async readInput(input) {
|
|
1859
|
+
this.#assertConnected();
|
|
1860
|
+
if (!this.#permissions.allowRead) return this.#refuse({
|
|
1861
|
+
message: READ_NOT_ALLOWED_MESSAGE,
|
|
1862
|
+
permission: "allowRead"
|
|
1819
1863
|
});
|
|
1864
|
+
if (typeof input.jobId !== "string" || !input.jobId) return this.#refuse({ message: "The request must name a job" });
|
|
1865
|
+
const generation = await this.#generations.get(input.jobId);
|
|
1866
|
+
if (!generation) return this.#refuse({ message: GENERATION_GONE_MESSAGE });
|
|
1867
|
+
const kept = generation.inputBytes ? await this.#generations.readInput(input.jobId) : void 0;
|
|
1868
|
+
if (!kept) return this.#refuse({ message: NO_INPUT_MESSAGE });
|
|
1869
|
+
await this.#logCommand("readInput", "read the API input");
|
|
1870
|
+
return { input: kept };
|
|
1820
1871
|
}
|
|
1821
|
-
|
|
1872
|
+
/**
|
|
1873
|
+
* Returns the requested files of a kept job, one page of lines at a time. Refused without `allowRead`.
|
|
1874
|
+
*/
|
|
1875
|
+
async readFiles(input) {
|
|
1876
|
+
this.#assertConnected();
|
|
1822
1877
|
if (!this.#permissions.allowRead) return this.#refuse({
|
|
1823
|
-
message:
|
|
1878
|
+
message: READ_NOT_ALLOWED_MESSAGE,
|
|
1824
1879
|
permission: "allowRead"
|
|
1825
1880
|
});
|
|
1826
1881
|
if (!Array.isArray(input.paths) || typeof input.jobId !== "string" || !input.jobId) return this.#refuse({ message: "The request must name a job and carry paths" });
|
|
@@ -1838,10 +1893,8 @@ var Agent = class extends RpcTarget {
|
|
|
1838
1893
|
cursor: input.cursor,
|
|
1839
1894
|
limit: input.limit
|
|
1840
1895
|
});
|
|
1841
|
-
|
|
1842
|
-
|
|
1843
|
-
info: `read ${Object.keys(result.files).length}/${paths.length} requested file${paths.length === 1 ? "" : "s"}`
|
|
1844
|
-
};
|
|
1896
|
+
await this.#logCommand("readFiles", `read ${Object.keys(result.files).length}/${paths.length} requested file${paths.length === 1 ? "" : "s"}`);
|
|
1897
|
+
return result;
|
|
1845
1898
|
}
|
|
1846
1899
|
};
|
|
1847
1900
|
const openWebSocketRpc = ({ url, token, instanceId, agent }) => {
|
|
@@ -2132,7 +2185,6 @@ async function pairAgent({ onCode, onRetry, maxAttempts = 1, ...options }) {
|
|
|
2132
2185
|
}
|
|
2133
2186
|
//#endregion
|
|
2134
2187
|
//#region src/snapshot.ts
|
|
2135
|
-
const gzipAsync = promisify(gzip);
|
|
2136
2188
|
const UPLOAD_TIMEOUT_MS = 12e4;
|
|
2137
2189
|
const BUNDLED_DEPENDENCIES = ["@kubb/plugin-barrel"];
|
|
2138
2190
|
/**
|
|
@@ -2252,7 +2304,7 @@ async function createSnapshotPackage({ files, packageInfo }) {
|
|
|
2252
2304
|
Buffer.alloc((512 - bytes.length % 512) % 512)
|
|
2253
2305
|
];
|
|
2254
2306
|
});
|
|
2255
|
-
return
|
|
2307
|
+
return gzipSync(Buffer.concat([...chunks, Buffer.alloc(1024)]));
|
|
2256
2308
|
} finally {
|
|
2257
2309
|
await rm(root, {
|
|
2258
2310
|
recursive: true,
|