@wix/ditto-codegen-public 1.0.441 → 1.0.443
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/out.js +484 -49
- package/package.json +2 -2
package/dist/out.js
CHANGED
|
@@ -544,7 +544,15 @@ var require_context = __commonJS({
|
|
|
544
544
|
var types_1 = require_types_impl();
|
|
545
545
|
var dotenv_1 = __importDefault2(require_main());
|
|
546
546
|
var path_12 = __importDefault2(require("path"));
|
|
547
|
+
var provisioned = {
|
|
548
|
+
CODEGEN_JOB_DELIVERY: process.env.CODEGEN_JOB_DELIVERY,
|
|
549
|
+
CODEGEN_JOB_FETCH_PORT: process.env.CODEGEN_JOB_FETCH_PORT
|
|
550
|
+
};
|
|
547
551
|
dotenv_1.default.config({ path: path_12.default.join(__dirname, "../.env"), override: true });
|
|
552
|
+
for (const [key, value] of Object.entries(provisioned)) {
|
|
553
|
+
if (value?.trim())
|
|
554
|
+
process.env[key] = value;
|
|
555
|
+
}
|
|
548
556
|
var HistoryManager = class {
|
|
549
557
|
constructor() {
|
|
550
558
|
this.history = [];
|
|
@@ -11032,7 +11040,7 @@ var require_CodeGenService = __commonJS({
|
|
|
11032
11040
|
"dist/services/CodeGenService.js"(exports2) {
|
|
11033
11041
|
"use strict";
|
|
11034
11042
|
Object.defineProperty(exports2, "__esModule", { value: true });
|
|
11035
|
-
exports2.CodeGenService = exports2.JobsSortOrder = exports2.TaskKind = exports2.Status = void 0;
|
|
11043
|
+
exports2.CodeGenService = exports2.FETCH_TIMEOUT_MS = exports2.REQUEST_TIMEOUT_MS = exports2.JobsSortOrder = exports2.TaskKind = exports2.Status = void 0;
|
|
11036
11044
|
exports2.createCodeGenErrorHandler = createCodeGenErrorHandler;
|
|
11037
11045
|
var http_client_1 = require_index_node();
|
|
11038
11046
|
var http_1 = require_http_impl();
|
|
@@ -11116,6 +11124,14 @@ var require_CodeGenService = __commonJS({
|
|
|
11116
11124
|
}
|
|
11117
11125
|
};
|
|
11118
11126
|
}
|
|
11127
|
+
exports2.REQUEST_TIMEOUT_MS = 12e4;
|
|
11128
|
+
exports2.FETCH_TIMEOUT_MS = 3e4;
|
|
11129
|
+
function isNotFound(error) {
|
|
11130
|
+
return http_client_1.HttpClient.isHttpError(error) && error.response?.status === 404;
|
|
11131
|
+
}
|
|
11132
|
+
function mapRequest(req, fn) {
|
|
11133
|
+
return typeof req === "function" ? (ctx) => fn(req(ctx)) : fn(req);
|
|
11134
|
+
}
|
|
11119
11135
|
var CodeGenService = class {
|
|
11120
11136
|
constructor(projectId, httpClient) {
|
|
11121
11137
|
this.projectId = projectId;
|
|
@@ -11126,15 +11142,16 @@ var require_CodeGenService = __commonJS({
|
|
|
11126
11142
|
this.setAccessToken(token);
|
|
11127
11143
|
return token;
|
|
11128
11144
|
};
|
|
11129
|
-
this.request = async (req) => {
|
|
11145
|
+
this.request = async (req, timeout) => {
|
|
11146
|
+
const build = () => this.withTimeout(this.withAuth(req), timeout);
|
|
11130
11147
|
try {
|
|
11131
|
-
return await this.httpClient.request(
|
|
11148
|
+
return await this.httpClient.request(build());
|
|
11132
11149
|
} catch (err) {
|
|
11133
11150
|
if (!this.isUnauthorized(err))
|
|
11134
11151
|
throw err;
|
|
11135
11152
|
logger_12.logger.warn("[CodeGenService] 401 received, refreshing token and retrying once");
|
|
11136
11153
|
await this.refreshAccessToken();
|
|
11137
|
-
return await this.httpClient.request(
|
|
11154
|
+
return await this.httpClient.request(build());
|
|
11138
11155
|
}
|
|
11139
11156
|
};
|
|
11140
11157
|
this.fetchPendingJobs = async () => {
|
|
@@ -11145,10 +11162,19 @@ var require_CodeGenService = __commonJS({
|
|
|
11145
11162
|
paging: { limit: 1 },
|
|
11146
11163
|
sortOrder: types_1.JobsSortOrder.CREATED_AT_ASC
|
|
11147
11164
|
} : void 0;
|
|
11148
|
-
const resp = await this.request((0, http_1.listProjectJobs)(filtered ?? { projectId: this.projectId }));
|
|
11165
|
+
const resp = await this.request((0, http_1.listProjectJobs)(filtered ?? { projectId: this.projectId }), exports2.FETCH_TIMEOUT_MS);
|
|
11149
11166
|
const jobs = resp.data?.jobs ?? [];
|
|
11150
11167
|
return filtered ? jobs : jobs.filter(this.shouldProcessJob);
|
|
11151
11168
|
};
|
|
11169
|
+
this.findJob = async (jobId) => {
|
|
11170
|
+
try {
|
|
11171
|
+
return await this.getJob(jobId, exports2.FETCH_TIMEOUT_MS);
|
|
11172
|
+
} catch (error) {
|
|
11173
|
+
if (isNotFound(error))
|
|
11174
|
+
return null;
|
|
11175
|
+
throw error;
|
|
11176
|
+
}
|
|
11177
|
+
};
|
|
11152
11178
|
this.shouldProcessJob = (job) => {
|
|
11153
11179
|
if (job.status !== types_1.Status.PENDING)
|
|
11154
11180
|
return false;
|
|
@@ -11279,11 +11305,11 @@ var require_CodeGenService = __commonJS({
|
|
|
11279
11305
|
}
|
|
11280
11306
|
}));
|
|
11281
11307
|
};
|
|
11282
|
-
this.getJob = async (jobId) => {
|
|
11308
|
+
this.getJob = async (jobId, timeout) => {
|
|
11283
11309
|
const resp = await this.request((0, http_1.getJob)({
|
|
11284
11310
|
projectId: this.projectId,
|
|
11285
11311
|
jobId
|
|
11286
|
-
}));
|
|
11312
|
+
}), timeout);
|
|
11287
11313
|
return resp.data?.job ?? null;
|
|
11288
11314
|
};
|
|
11289
11315
|
this.runContext = (ctx) => ({
|
|
@@ -11329,6 +11355,7 @@ var require_CodeGenService = __commonJS({
|
|
|
11329
11355
|
const serverUrl = process.env.CODEGEN_SERVER_BASE_URL || "https://manage.wix.com";
|
|
11330
11356
|
this.httpClient = (0, http_client_1.createHttpClient)({
|
|
11331
11357
|
baseURL: serverUrl,
|
|
11358
|
+
timeout: exports2.REQUEST_TIMEOUT_MS,
|
|
11332
11359
|
errorHandler: createCodeGenErrorHandler(() => this.httpClient)
|
|
11333
11360
|
});
|
|
11334
11361
|
}
|
|
@@ -11346,14 +11373,16 @@ var require_CodeGenService = __commonJS({
|
|
|
11346
11373
|
return error.response?.status === 401;
|
|
11347
11374
|
}
|
|
11348
11375
|
withAuth(req) {
|
|
11349
|
-
|
|
11350
|
-
|
|
11351
|
-
|
|
11352
|
-
|
|
11353
|
-
|
|
11354
|
-
}
|
|
11355
|
-
}
|
|
11356
|
-
|
|
11376
|
+
return mapRequest(req, (r) => ({
|
|
11377
|
+
...r,
|
|
11378
|
+
headers: {
|
|
11379
|
+
...r.headers ?? {},
|
|
11380
|
+
authorization: `Bearer ${this.accessToken}`
|
|
11381
|
+
}
|
|
11382
|
+
}));
|
|
11383
|
+
}
|
|
11384
|
+
withTimeout(req, timeout) {
|
|
11385
|
+
return timeout === void 0 ? req : mapRequest(req, (r) => ({ ...r, timeout }));
|
|
11357
11386
|
}
|
|
11358
11387
|
};
|
|
11359
11388
|
exports2.CodeGenService = CodeGenService;
|
|
@@ -14682,6 +14711,31 @@ For ANY use of a Wix Stores API (products, variants, inventory, collections/cate
|
|
|
14682
14711
|
}
|
|
14683
14712
|
});
|
|
14684
14713
|
|
|
14714
|
+
// ../codegen-common-logic/dist/rules/vertical-installation.js
|
|
14715
|
+
var require_vertical_installation = __commonJS({
|
|
14716
|
+
"../codegen-common-logic/dist/rules/vertical-installation.js"(exports2) {
|
|
14717
|
+
"use strict";
|
|
14718
|
+
Object.defineProperty(exports2, "__esModule", { value: true });
|
|
14719
|
+
exports2.VERTICAL_INSTALLATION_RULES = void 0;
|
|
14720
|
+
exports2.VERTICAL_INSTALLATION_RULES = `# Vertical Installation Rules
|
|
14721
|
+
|
|
14722
|
+
Code written against a Wix app this site doesn't have compiles, saves, and then does nothing.
|
|
14723
|
+
|
|
14724
|
+
For ANY use of a Wix vertical SDK (Stores, eCommerce, Bookings, Restaurants, Pricing Plans, Gift Cards, Blog, Events, Portfolio, Members Area, Forms, Loyalty Program, Donations):
|
|
14725
|
+
|
|
14726
|
+
1. **You MUST invoke the \`wix-site-installed-apps\` skill before your FIRST write of any kind** \u2014 not merely before the vertical code itself. The build workflow tells you to write each piece as soon as it is ready, so a dashboard shell written before you reach the vertical part is still work rule 2 will make you undo. Name the apps this request needs, by product name; ask in one call and reuse the answer.
|
|
14727
|
+
2. **If any app comes back \`installed: false\`, STOP. Write no code at all** \u2014 not for that app, and not for the rest of the request either. Your reply is **one** short message to the site owner, naming the app and which parts of the request you did not attempt, and nothing else. Write the outcome, never the mechanism: no rule, no skill, no check or verdict, no app id or endpoint, and no sentence announcing that you are stopping \u2014 the user doesn't know what any of that is, and reading it as an error is the likeliest outcome. \\"Wix Events isn't installed on your site, so I couldn't build the upcoming-events page. Install Wix Events from your dashboard, then ask again and I'll build it.\\" \u2014 that shape, once. **If you have already created or modified files in this session, undo those changes before replying \u2014 path by path, naming each file you wrote, never a bulk revert of the working tree (\`git clean\`, \`git checkout .\`, \`git reset --hard\`, or any "discard all changes"), which also destroys work that was there before you** \u2014 a half-built app that saves is worse than either outcome this rule chooses between.
|
|
14728
|
+
3. **Do not soften rule 2.** No partial build, no stub, no CMS collection standing in for the app, no "for when they install it" path, and no offering to build the parts that would work. The site owner installs the app, then asks again. **Where the OUTPUT MESSAGE instruction says to build the feature and list installing a dependent app as a "next step", this rule wins** \u2014 for a missing app there is no build, so there is no next step to list against it.
|
|
14729
|
+
4. **\`installed: null\`, or the check itself failing: build, and say the app may need installing.** A verdict you can't trust never stops anything. The exception is a \`null\` carrying \`"reason":"not-installable"\` \u2014 the check refuses that name because there is no app behind it to install: build, and name nothing. Some plain \`null\`s are platform features with nothing to install either \u2014 contacts, coupons, automations and triggered emails, login and logged-in-only gating \u2014 so build and name nothing for those too.
|
|
14730
|
+
5. **This outranks the plan.** A blueprint summary or extension description naming a missing app was written without knowing the site; rule 2 wins, and your reply says which planned parts you left unbuilt.
|
|
14731
|
+
6. **Never install an app** \u2014 it adds pages, a cart, and checkout to the user's live site.
|
|
14732
|
+
|
|
14733
|
+
CMS is exempt: \`wix-site-data-collection\` installs it, so CMS work is never blocked and CMS is never named as missing.
|
|
14734
|
+
|
|
14735
|
+
Two names answer nothing: **"Wix CMS"** (the published id is a variant nobody can install) and **"Wix eCommerce"** (cart and checkout have no standalone install \u2014 they arrive with a catalog app). The check refuses both, answering \`installed: null\` with \`"reason":"not-installable"\`, so asking is harmless but decides nothing. For an eCommerce feature, gate on the catalog app it needs instead \u2014 Wix Stores, Wix Bookings, or the specific Wix Restaurants app \u2014 and never tell the user to install eCommerce or CMS.`;
|
|
14736
|
+
}
|
|
14737
|
+
});
|
|
14738
|
+
|
|
14685
14739
|
// ../codegen-common-logic/dist/rules/index.js
|
|
14686
14740
|
var require_rules = __commonJS({
|
|
14687
14741
|
"../codegen-common-logic/dist/rules/index.js"(exports2) {
|
|
@@ -14705,6 +14759,7 @@ var require_rules = __commonJS({
|
|
|
14705
14759
|
Object.defineProperty(exports2, "__esModule", { value: true });
|
|
14706
14760
|
__exportStar2(require_site_data_layer(), exports2);
|
|
14707
14761
|
__exportStar2(require_stores_catalog_version(), exports2);
|
|
14762
|
+
__exportStar2(require_vertical_installation(), exports2);
|
|
14708
14763
|
}
|
|
14709
14764
|
});
|
|
14710
14765
|
|
|
@@ -14718,6 +14773,10 @@ var require_site_environment = __commonJS({
|
|
|
14718
14773
|
exports2.SITE_ENVIRONMENT_IDENTITY = "You generate code for the user's own live Wix site \u2014 to the user it's just their site, not a separate app they're aware of. Your changes are saved and applied to the site automatically; there is no separate release step.";
|
|
14719
14774
|
exports2.SITE_CODEGEN_RULES = [
|
|
14720
14775
|
{ filename: "site-data-layer-rules.md", content: rules_1.SITE_DATA_LAYER_RULES },
|
|
14776
|
+
{
|
|
14777
|
+
filename: "vertical-installation-rules.md",
|
|
14778
|
+
content: rules_1.VERTICAL_INSTALLATION_RULES
|
|
14779
|
+
},
|
|
14721
14780
|
{
|
|
14722
14781
|
filename: "stores-catalog-version-rules.md",
|
|
14723
14782
|
content: rules_1.STORES_CATALOG_VERSION_RULES
|
|
@@ -16508,11 +16567,13 @@ var require_utils9 = __commonJS({
|
|
|
16508
16567
|
"dist/utils.js"(exports2) {
|
|
16509
16568
|
"use strict";
|
|
16510
16569
|
Object.defineProperty(exports2, "__esModule", { value: true });
|
|
16511
|
-
exports2.errorStack = void 0;
|
|
16570
|
+
exports2.errorStack = exports2.delay = void 0;
|
|
16512
16571
|
exports2.serializeError = serializeError;
|
|
16513
16572
|
exports2.updateAllRunningTasks = updateAllRunningTasks;
|
|
16514
16573
|
var types_1 = require_types_impl();
|
|
16515
16574
|
var codeGenerationService_12 = require_codeGenerationService();
|
|
16575
|
+
var delay = (milliseconds) => new Promise((resolve) => setTimeout(resolve, milliseconds));
|
|
16576
|
+
exports2.delay = delay;
|
|
16516
16577
|
var errorStack = (error) => error instanceof Error ? error.stack ?? error.message : String(error);
|
|
16517
16578
|
exports2.errorStack = errorStack;
|
|
16518
16579
|
function serializeError(error) {
|
|
@@ -23760,7 +23821,7 @@ var require_skills_installer = __commonJS({
|
|
|
23760
23821
|
const nested = discoverSkills((0, path_12.join)(packageRoot, "skills"));
|
|
23761
23822
|
return nested.length > 0 ? nested : discoverSkills(packageRoot);
|
|
23762
23823
|
}
|
|
23763
|
-
var
|
|
23824
|
+
var delay = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
|
|
23764
23825
|
async function applySkillsOverride(outputPath, log) {
|
|
23765
23826
|
const skillsOverride = process.env.SKILLS_OVERRIDE_BRANCH;
|
|
23766
23827
|
if (!skillsOverride) {
|
|
@@ -23806,7 +23867,7 @@ var require_skills_installer = __commonJS({
|
|
|
23806
23867
|
});
|
|
23807
23868
|
const deadline = Date.now() + timeoutMs;
|
|
23808
23869
|
while (Date.now() < deadline) {
|
|
23809
|
-
await
|
|
23870
|
+
await delay(intervalMs);
|
|
23810
23871
|
state = inspect(state.candidates);
|
|
23811
23872
|
if (state.ready) {
|
|
23812
23873
|
log.info("[Skills] Skills became available", { present: state.present });
|
|
@@ -24213,6 +24274,367 @@ var require_plugin_artifacts = __commonJS({
|
|
|
24213
24274
|
}
|
|
24214
24275
|
});
|
|
24215
24276
|
|
|
24277
|
+
// dist/fetch-scheduler.js
|
|
24278
|
+
var require_fetch_scheduler = __commonJS({
|
|
24279
|
+
"dist/fetch-scheduler.js"(exports2) {
|
|
24280
|
+
"use strict";
|
|
24281
|
+
Object.defineProperty(exports2, "__esModule", { value: true });
|
|
24282
|
+
exports2.FetchScheduler = exports2.MAX_AWAITED_JOB_IDS = exports2.MAX_MISSING_JOB_RECHECKS = exports2.ERROR_BACKOFF_MS = exports2.POST_JOB_INTERVAL_MS = exports2.MIN_FETCH_INTERVAL_MS = void 0;
|
|
24283
|
+
var logger_12 = require_logger();
|
|
24284
|
+
var utils_12 = require_utils9();
|
|
24285
|
+
exports2.MIN_FETCH_INTERVAL_MS = 1e3;
|
|
24286
|
+
exports2.POST_JOB_INTERVAL_MS = 3e3;
|
|
24287
|
+
exports2.ERROR_BACKOFF_MS = 5e3;
|
|
24288
|
+
exports2.MAX_MISSING_JOB_RECHECKS = 3;
|
|
24289
|
+
exports2.MAX_AWAITED_JOB_IDS = 4;
|
|
24290
|
+
var FetchScheduler = class {
|
|
24291
|
+
constructor(deps) {
|
|
24292
|
+
this.deps = deps;
|
|
24293
|
+
this.cycle = null;
|
|
24294
|
+
this.checkAgain = false;
|
|
24295
|
+
this.stopped = false;
|
|
24296
|
+
this.nextFetchNotBefore = 0;
|
|
24297
|
+
this.interval = 0;
|
|
24298
|
+
this.awaitedJobIds = /* @__PURE__ */ new Map();
|
|
24299
|
+
}
|
|
24300
|
+
start() {
|
|
24301
|
+
this.stopped = false;
|
|
24302
|
+
}
|
|
24303
|
+
/** A cycle already inside runJob is NOT awaited. A caller that needs exclusivity must
|
|
24304
|
+
* not start another runner until that cycle settles. */
|
|
24305
|
+
stop() {
|
|
24306
|
+
this.stopped = true;
|
|
24307
|
+
}
|
|
24308
|
+
/** Records the nudge and makes sure a cycle is running. It does not wait for the
|
|
24309
|
+
* fetch. A caller held on a slow socket times out and reads that as "machine down",
|
|
24310
|
+
* so retrying is ours to do, not theirs. */
|
|
24311
|
+
nudge(jobId) {
|
|
24312
|
+
if (this.stopped)
|
|
24313
|
+
return;
|
|
24314
|
+
if (jobId) {
|
|
24315
|
+
this.awaitedJobIds.delete(jobId);
|
|
24316
|
+
if (this.awaitedJobIds.size >= exports2.MAX_AWAITED_JOB_IDS) {
|
|
24317
|
+
this.awaitedJobIds.delete(this.awaitedJobIds.keys().next().value);
|
|
24318
|
+
}
|
|
24319
|
+
this.awaitedJobIds.set(jobId, exports2.MAX_MISSING_JOB_RECHECKS);
|
|
24320
|
+
}
|
|
24321
|
+
if (this.cycle) {
|
|
24322
|
+
this.checkAgain = true;
|
|
24323
|
+
return;
|
|
24324
|
+
}
|
|
24325
|
+
this.cycle = this.runUntilIdle().catch((error) => logger_12.logger.error("[JobFetch] Cycle aborted", { error: (0, utils_12.errorStack)(error) }));
|
|
24326
|
+
}
|
|
24327
|
+
async runUntilIdle() {
|
|
24328
|
+
try {
|
|
24329
|
+
do {
|
|
24330
|
+
await this.runSingleJobCycle();
|
|
24331
|
+
} while (this.checkAgain && !this.stopped);
|
|
24332
|
+
} finally {
|
|
24333
|
+
this.cycle = null;
|
|
24334
|
+
}
|
|
24335
|
+
}
|
|
24336
|
+
async runSingleJobCycle() {
|
|
24337
|
+
await this.throttle();
|
|
24338
|
+
if (this.stopped)
|
|
24339
|
+
return;
|
|
24340
|
+
this.checkAgain = false;
|
|
24341
|
+
const due = await this.findRunnableJob();
|
|
24342
|
+
if (!due)
|
|
24343
|
+
return;
|
|
24344
|
+
this.checkAgain = true;
|
|
24345
|
+
if (this.stopped)
|
|
24346
|
+
return;
|
|
24347
|
+
await this.attemptJob(due);
|
|
24348
|
+
}
|
|
24349
|
+
async findRunnableJob() {
|
|
24350
|
+
let jobs;
|
|
24351
|
+
try {
|
|
24352
|
+
jobs = await this.deps.fetchPendingJobs();
|
|
24353
|
+
} catch (error) {
|
|
24354
|
+
this.recordDebt("Fetch failed", error);
|
|
24355
|
+
return null;
|
|
24356
|
+
}
|
|
24357
|
+
this.schedule(exports2.MIN_FETCH_INTERVAL_MS);
|
|
24358
|
+
logger_12.logger.info("[JobFetch] Fetched pending jobs", { count: jobs.length });
|
|
24359
|
+
for (const job of jobs) {
|
|
24360
|
+
if (job.id)
|
|
24361
|
+
this.awaitedJobIds.delete(job.id);
|
|
24362
|
+
}
|
|
24363
|
+
if (jobs.length > 0)
|
|
24364
|
+
return jobs[0];
|
|
24365
|
+
if (this.awaitedJobIds.size === 0)
|
|
24366
|
+
return null;
|
|
24367
|
+
try {
|
|
24368
|
+
return await this.claimNudgedJob();
|
|
24369
|
+
} catch (error) {
|
|
24370
|
+
this.recordDebt("Nudged job lookup failed", error);
|
|
24371
|
+
return null;
|
|
24372
|
+
}
|
|
24373
|
+
}
|
|
24374
|
+
async attemptJob(job) {
|
|
24375
|
+
try {
|
|
24376
|
+
await this.deps.runJob(job);
|
|
24377
|
+
this.schedule(exports2.POST_JOB_INTERVAL_MS);
|
|
24378
|
+
} catch (error) {
|
|
24379
|
+
this.recordDebt("Job run failed", error);
|
|
24380
|
+
}
|
|
24381
|
+
}
|
|
24382
|
+
/** A nudged job the list did not return. Read it by key, which does not wait on the
|
|
24383
|
+
* index. A key read is still a replica read, so a job the server does not know about
|
|
24384
|
+
* yet keeps a small budget of re-checks instead of one answer settling it. */
|
|
24385
|
+
async claimNudgedJob() {
|
|
24386
|
+
for (const jobId of [...this.awaitedJobIds.keys()]) {
|
|
24387
|
+
if (this.stopped)
|
|
24388
|
+
return null;
|
|
24389
|
+
const job = await this.deps.findJob(jobId);
|
|
24390
|
+
if (job) {
|
|
24391
|
+
this.awaitedJobIds.delete(jobId);
|
|
24392
|
+
if (this.deps.canRunJob(job))
|
|
24393
|
+
return job;
|
|
24394
|
+
continue;
|
|
24395
|
+
}
|
|
24396
|
+
const rechecksLeft = this.awaitedJobIds.get(jobId);
|
|
24397
|
+
if (rechecksLeft === void 0)
|
|
24398
|
+
continue;
|
|
24399
|
+
if (rechecksLeft > 0) {
|
|
24400
|
+
this.awaitedJobIds.set(jobId, rechecksLeft - 1);
|
|
24401
|
+
this.checkAgain = true;
|
|
24402
|
+
} else {
|
|
24403
|
+
this.awaitedJobIds.delete(jobId);
|
|
24404
|
+
logger_12.logger.warn("[JobFetch] Nudged job does not exist", { jobId });
|
|
24405
|
+
}
|
|
24406
|
+
}
|
|
24407
|
+
return null;
|
|
24408
|
+
}
|
|
24409
|
+
schedule(intervalMs) {
|
|
24410
|
+
this.interval = intervalMs;
|
|
24411
|
+
this.nextFetchNotBefore = Date.now() + intervalMs;
|
|
24412
|
+
}
|
|
24413
|
+
/** Nobody else will retry. We already answered the caller 200. */
|
|
24414
|
+
recordDebt(what, error) {
|
|
24415
|
+
logger_12.logger.error(`[JobFetch] ${what}`, { error: (0, utils_12.errorStack)(error) });
|
|
24416
|
+
this.checkAgain = true;
|
|
24417
|
+
this.schedule(exports2.ERROR_BACKOFF_MS);
|
|
24418
|
+
}
|
|
24419
|
+
async throttle() {
|
|
24420
|
+
const wait = Math.min(this.nextFetchNotBefore - Date.now(), this.interval);
|
|
24421
|
+
if (wait > 0)
|
|
24422
|
+
await (0, utils_12.delay)(wait);
|
|
24423
|
+
}
|
|
24424
|
+
};
|
|
24425
|
+
exports2.FetchScheduler = FetchScheduler;
|
|
24426
|
+
}
|
|
24427
|
+
});
|
|
24428
|
+
|
|
24429
|
+
// dist/nudge-listener-server.js
|
|
24430
|
+
var require_nudge_listener_server = __commonJS({
|
|
24431
|
+
"dist/nudge-listener-server.js"(exports2) {
|
|
24432
|
+
"use strict";
|
|
24433
|
+
Object.defineProperty(exports2, "__esModule", { value: true });
|
|
24434
|
+
exports2.NudgeListenerServer = exports2.BIND_RETRY_DELAY_MS = exports2.BIND_RETRIES = exports2.MAX_LOGGED_PATH_LENGTH = exports2.JOB_ID_PATTERN = exports2.JOB_FETCH_PATH = exports2.JOB_FETCH_PORT = void 0;
|
|
24435
|
+
var node_http_1 = require("node:http");
|
|
24436
|
+
var logger_12 = require_logger();
|
|
24437
|
+
var utils_12 = require_utils9();
|
|
24438
|
+
var fetch_scheduler_1 = require_fetch_scheduler();
|
|
24439
|
+
exports2.JOB_FETCH_PORT = 52402;
|
|
24440
|
+
exports2.JOB_FETCH_PATH = "/_wix/codegen/fetch-jobs";
|
|
24441
|
+
exports2.JOB_ID_PATTERN = /^[A-Za-z0-9_-]{1,64}$/;
|
|
24442
|
+
exports2.MAX_LOGGED_PATH_LENGTH = 128;
|
|
24443
|
+
exports2.BIND_RETRIES = 5;
|
|
24444
|
+
exports2.BIND_RETRY_DELAY_MS = 300;
|
|
24445
|
+
var NudgeListenerServer = class {
|
|
24446
|
+
constructor(deps, port = exports2.JOB_FETCH_PORT) {
|
|
24447
|
+
this.port = port;
|
|
24448
|
+
this.server = null;
|
|
24449
|
+
this.stopped = false;
|
|
24450
|
+
this.scheduler = new fetch_scheduler_1.FetchScheduler(deps);
|
|
24451
|
+
}
|
|
24452
|
+
async start() {
|
|
24453
|
+
this.stopped = false;
|
|
24454
|
+
this.scheduler.start();
|
|
24455
|
+
await this.listen();
|
|
24456
|
+
if (this.stopped) {
|
|
24457
|
+
await this.stop();
|
|
24458
|
+
throw new Error("Nudge listener was stopped while binding");
|
|
24459
|
+
}
|
|
24460
|
+
logger_12.logger.info("[JobFetch] Endpoint listening", {
|
|
24461
|
+
port: this.boundPort(),
|
|
24462
|
+
path: exports2.JOB_FETCH_PATH
|
|
24463
|
+
});
|
|
24464
|
+
this.scheduler.nudge();
|
|
24465
|
+
}
|
|
24466
|
+
/** Closes the socket and stops the scheduler; a cycle already inside runJob is NOT
|
|
24467
|
+
* awaited. A caller that needs exclusivity must not start another runner until that
|
|
24468
|
+
* cycle settles. */
|
|
24469
|
+
async stop() {
|
|
24470
|
+
this.stopped = true;
|
|
24471
|
+
this.scheduler.stop();
|
|
24472
|
+
const server = this.server;
|
|
24473
|
+
if (!server)
|
|
24474
|
+
return;
|
|
24475
|
+
this.server = null;
|
|
24476
|
+
server.removeAllListeners("error");
|
|
24477
|
+
server.on("error", (error) => logger_12.logger.warn("[JobFetch] Endpoint error while closing", {
|
|
24478
|
+
error: (0, utils_12.errorStack)(error)
|
|
24479
|
+
}));
|
|
24480
|
+
server.closeAllConnections();
|
|
24481
|
+
await new Promise((resolve) => server.close(() => resolve()));
|
|
24482
|
+
}
|
|
24483
|
+
boundPort() {
|
|
24484
|
+
const address = this.server?.address();
|
|
24485
|
+
return address && typeof address === "object" ? address.port : null;
|
|
24486
|
+
}
|
|
24487
|
+
/** The agent is restarted in a tight `while true` loop, so a bind can land before
|
|
24488
|
+
* the previous process has released the port. Falling straight back to poll there
|
|
24489
|
+
* would strand the machine on the slow path for the whole session. */
|
|
24490
|
+
async listen() {
|
|
24491
|
+
for (let attempt = 0; ; attempt++) {
|
|
24492
|
+
try {
|
|
24493
|
+
return await this.listenOnce();
|
|
24494
|
+
} catch (error) {
|
|
24495
|
+
const inUse = error?.code === "EADDRINUSE" && attempt < exports2.BIND_RETRIES;
|
|
24496
|
+
if (!inUse)
|
|
24497
|
+
throw error;
|
|
24498
|
+
await (0, utils_12.delay)(exports2.BIND_RETRY_DELAY_MS);
|
|
24499
|
+
}
|
|
24500
|
+
}
|
|
24501
|
+
}
|
|
24502
|
+
listenOnce() {
|
|
24503
|
+
return new Promise((resolve, reject) => {
|
|
24504
|
+
const server = (0, node_http_1.createServer)((req, res) => {
|
|
24505
|
+
try {
|
|
24506
|
+
this.handleRequest(req, res);
|
|
24507
|
+
} catch (error) {
|
|
24508
|
+
logger_12.logger.error("[JobFetch] Request handler failed", {
|
|
24509
|
+
error: (0, utils_12.errorStack)(error)
|
|
24510
|
+
});
|
|
24511
|
+
if (res.headersSent)
|
|
24512
|
+
res.destroy();
|
|
24513
|
+
else
|
|
24514
|
+
this.respond(res, 500, { error: "request failed" });
|
|
24515
|
+
}
|
|
24516
|
+
});
|
|
24517
|
+
server.once("error", reject);
|
|
24518
|
+
server.listen(this.port, "0.0.0.0", () => {
|
|
24519
|
+
server.removeListener("error", reject);
|
|
24520
|
+
server.on("error", (error) => {
|
|
24521
|
+
logger_12.logger.error("[JobFetch] Endpoint failed after binding, exiting", {
|
|
24522
|
+
error: (0, utils_12.errorStack)(error)
|
|
24523
|
+
});
|
|
24524
|
+
process.exit(1);
|
|
24525
|
+
});
|
|
24526
|
+
this.server = server;
|
|
24527
|
+
resolve();
|
|
24528
|
+
});
|
|
24529
|
+
});
|
|
24530
|
+
}
|
|
24531
|
+
handleRequest(req, res) {
|
|
24532
|
+
const url = new URL((req.url ?? "").replace(/^\/+/, "/"), "http://localhost");
|
|
24533
|
+
const path = url.pathname.replace(/\/+$/, "");
|
|
24534
|
+
if (req.method !== "GET" || path !== exports2.JOB_FETCH_PATH) {
|
|
24535
|
+
logger_12.logger.warn("[JobFetch] Rejected request", {
|
|
24536
|
+
method: req.method,
|
|
24537
|
+
path: url.pathname.slice(0, exports2.MAX_LOGGED_PATH_LENGTH)
|
|
24538
|
+
});
|
|
24539
|
+
this.respond(res, 404, { error: "not found" });
|
|
24540
|
+
return;
|
|
24541
|
+
}
|
|
24542
|
+
const nudgedId = url.searchParams.get("jobId");
|
|
24543
|
+
const usable = nudgedId === null || exports2.JOB_ID_PATTERN.test(nudgedId);
|
|
24544
|
+
if (!usable) {
|
|
24545
|
+
logger_12.logger.warn("[JobFetch] Nudge carried an unusable jobId", {
|
|
24546
|
+
length: nudgedId.length
|
|
24547
|
+
});
|
|
24548
|
+
}
|
|
24549
|
+
const jobId = usable ? nudgedId ?? void 0 : void 0;
|
|
24550
|
+
this.scheduler.nudge(jobId);
|
|
24551
|
+
logger_12.logger.info("[JobFetch] Nudge accepted", { jobId });
|
|
24552
|
+
this.respond(res, 200, { accepted: true });
|
|
24553
|
+
}
|
|
24554
|
+
respond(res, status, body) {
|
|
24555
|
+
res.writeHead(status, {
|
|
24556
|
+
"Content-Type": "application/json",
|
|
24557
|
+
// A cached response would turn every nudge into a no-op.
|
|
24558
|
+
"Cache-Control": "no-store"
|
|
24559
|
+
});
|
|
24560
|
+
res.end(JSON.stringify(body));
|
|
24561
|
+
}
|
|
24562
|
+
};
|
|
24563
|
+
exports2.NudgeListenerServer = NudgeListenerServer;
|
|
24564
|
+
}
|
|
24565
|
+
});
|
|
24566
|
+
|
|
24567
|
+
// dist/job-fetching.js
|
|
24568
|
+
var require_job_fetching = __commonJS({
|
|
24569
|
+
"dist/job-fetching.js"(exports2) {
|
|
24570
|
+
"use strict";
|
|
24571
|
+
Object.defineProperty(exports2, "__esModule", { value: true });
|
|
24572
|
+
exports2.JobDeliveryMode = void 0;
|
|
24573
|
+
exports2.getJobDeliveryMode = getJobDeliveryMode;
|
|
24574
|
+
exports2.getJobFetchPort = getJobFetchPort;
|
|
24575
|
+
exports2.startJobFetching = startJobFetching;
|
|
24576
|
+
var nudge_listener_server_12 = require_nudge_listener_server();
|
|
24577
|
+
var logger_12 = require_logger();
|
|
24578
|
+
var utils_12 = require_utils9();
|
|
24579
|
+
var JobDeliveryMode;
|
|
24580
|
+
(function(JobDeliveryMode2) {
|
|
24581
|
+
JobDeliveryMode2["POLL"] = "poll";
|
|
24582
|
+
JobDeliveryMode2["PUSH"] = "push";
|
|
24583
|
+
})(JobDeliveryMode || (exports2.JobDeliveryMode = JobDeliveryMode = {}));
|
|
24584
|
+
var DEFAULT_MODE = JobDeliveryMode.POLL;
|
|
24585
|
+
function getJobDeliveryMode() {
|
|
24586
|
+
const mode = process.env.CODEGEN_JOB_DELIVERY?.trim().toLowerCase();
|
|
24587
|
+
const supported = Object.values(JobDeliveryMode).find((candidate) => candidate === mode);
|
|
24588
|
+
if (supported)
|
|
24589
|
+
return supported;
|
|
24590
|
+
if (mode) {
|
|
24591
|
+
logger_12.logger.warn("[Startup] Unrecognized CODEGEN_JOB_DELIVERY, using default", {
|
|
24592
|
+
mode,
|
|
24593
|
+
default: DEFAULT_MODE
|
|
24594
|
+
});
|
|
24595
|
+
}
|
|
24596
|
+
return DEFAULT_MODE;
|
|
24597
|
+
}
|
|
24598
|
+
var MIN_PORT = 1;
|
|
24599
|
+
var MAX_PORT = 65535;
|
|
24600
|
+
function getJobFetchPort() {
|
|
24601
|
+
const configured = process.env.CODEGEN_JOB_FETCH_PORT;
|
|
24602
|
+
if (configured === void 0)
|
|
24603
|
+
return nudge_listener_server_12.JOB_FETCH_PORT;
|
|
24604
|
+
const port = /^\s*\d+\s*$/.test(configured) ? Number(configured) : NaN;
|
|
24605
|
+
if (Number.isInteger(port) && port >= MIN_PORT && port <= MAX_PORT)
|
|
24606
|
+
return port;
|
|
24607
|
+
logger_12.logger.warn("[Startup] Unusable CODEGEN_JOB_FETCH_PORT, using default", {
|
|
24608
|
+
port: configured,
|
|
24609
|
+
default: nudge_listener_server_12.JOB_FETCH_PORT
|
|
24610
|
+
});
|
|
24611
|
+
return nudge_listener_server_12.JOB_FETCH_PORT;
|
|
24612
|
+
}
|
|
24613
|
+
async function startJobFetching(deps) {
|
|
24614
|
+
const mode = getJobDeliveryMode();
|
|
24615
|
+
logger_12.logger.info("[Startup] Job delivery mode", { mode });
|
|
24616
|
+
if (mode === JobDeliveryMode.POLL) {
|
|
24617
|
+
return deps.runPollLoop();
|
|
24618
|
+
}
|
|
24619
|
+
try {
|
|
24620
|
+
await deps.nudgeListenerServer.start();
|
|
24621
|
+
} catch (error) {
|
|
24622
|
+
try {
|
|
24623
|
+
await deps.nudgeListenerServer.stop();
|
|
24624
|
+
} catch (stopError) {
|
|
24625
|
+
logger_12.logger.error("[Startup] Closing the half-started listener failed", {
|
|
24626
|
+
error: (0, utils_12.errorStack)(stopError)
|
|
24627
|
+
});
|
|
24628
|
+
}
|
|
24629
|
+
logger_12.logger.error("[Startup] Push delivery unavailable, falling back to poll", {
|
|
24630
|
+
error: (0, utils_12.errorStack)(error)
|
|
24631
|
+
});
|
|
24632
|
+
return deps.runPollLoop();
|
|
24633
|
+
}
|
|
24634
|
+
}
|
|
24635
|
+
}
|
|
24636
|
+
});
|
|
24637
|
+
|
|
24216
24638
|
// dist/index.js
|
|
24217
24639
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
24218
24640
|
exports.processJob = processJob;
|
|
@@ -24241,61 +24663,67 @@ var subagent_tool_logger_1 = require_subagent_tool_logger();
|
|
|
24241
24663
|
var plugin_artifacts_1 = require_plugin_artifacts();
|
|
24242
24664
|
var config_1 = require_config();
|
|
24243
24665
|
var environments_1 = require_environments();
|
|
24244
|
-
var plugin_host_1 = require_plugin_host();
|
|
24245
24666
|
var utils_1 = require_utils9();
|
|
24667
|
+
var job_fetching_1 = require_job_fetching();
|
|
24668
|
+
var nudge_listener_server_1 = require_nudge_listener_server();
|
|
24669
|
+
var plugin_host_1 = require_plugin_host();
|
|
24670
|
+
var utils_2 = require_utils9();
|
|
24246
24671
|
var sessionId = process.env.CODEGEN_SESSION_ID || (0, crypto_1.randomUUID)();
|
|
24247
24672
|
process.env.CODEGEN_SESSION_ID = sessionId;
|
|
24248
24673
|
(0, logger_1.initLogger)(sessionId);
|
|
24249
24674
|
var jobCancellationMonitor = new job_cancellation_monitor_1.JobCancellationMonitor(codeGenerationService_1.codeGenerationService);
|
|
24250
24675
|
var jobTimeoutMonitor = new job_timeout_monitor_1.JobTimeoutMonitor(codeGenerationService_1.codeGenerationService);
|
|
24251
|
-
var
|
|
24676
|
+
var POLL_LOG_PREFIX = "[Loop]";
|
|
24677
|
+
var PUSH_LOG_PREFIX = "[JobFetch]";
|
|
24252
24678
|
var ACTIVE_JOB_SLEEP_MS = 1e3;
|
|
24253
24679
|
var NO_JOBS_SLEEP_MS = 5e3;
|
|
24254
24680
|
var POST_JOB_SLEEP_MS = 3e3;
|
|
24681
|
+
var runPendingJob = async (job, logPrefix) => {
|
|
24682
|
+
const redactAgentData = (payload) => payload?.agentData ? { ...payload, agentData: Object.keys(payload.agentData) } : payload;
|
|
24683
|
+
logger_1.logger.info("Job details", {
|
|
24684
|
+
job: {
|
|
24685
|
+
...job,
|
|
24686
|
+
tasks: job.tasks?.map((task) => ({
|
|
24687
|
+
...task,
|
|
24688
|
+
input: redactAgentData(task.input),
|
|
24689
|
+
payload: redactAgentData(task.payload)
|
|
24690
|
+
}))
|
|
24691
|
+
}
|
|
24692
|
+
});
|
|
24693
|
+
if (!job.id) {
|
|
24694
|
+
throw new ditto_codegen_types_1.MissingJobIdError();
|
|
24695
|
+
}
|
|
24696
|
+
const jobId = job.id;
|
|
24697
|
+
logger_1.logger.info(`${logPrefix} Selected job`, { jobId });
|
|
24698
|
+
const freshToken = await codeGenerationService_1.codeGenerationService.refreshAccessToken();
|
|
24699
|
+
(0, config_1.setCurrentAccessToken)(freshToken);
|
|
24700
|
+
await codeGenerationService_1.codeGenerationService.markJobAsRuninng(jobId);
|
|
24701
|
+
await processJob(job);
|
|
24702
|
+
await codeGenerationService_1.codeGenerationService.markJobAsCompleted(jobId);
|
|
24703
|
+
logger_1.logger.info(`${logPrefix} Processed job`, { jobId });
|
|
24704
|
+
};
|
|
24255
24705
|
var alwaysOnLoop = async () => {
|
|
24256
24706
|
while (true) {
|
|
24257
24707
|
try {
|
|
24258
24708
|
if (context_1.ctx.hasActiveJobs()) {
|
|
24259
24709
|
console.log(`[Loop] Local active job in progress. Sleeping ${ACTIVE_JOB_SLEEP_MS}ms`);
|
|
24260
|
-
await delay(ACTIVE_JOB_SLEEP_MS);
|
|
24710
|
+
await (0, utils_1.delay)(ACTIVE_JOB_SLEEP_MS);
|
|
24261
24711
|
continue;
|
|
24262
24712
|
}
|
|
24263
24713
|
const jobs = await codeGenerationService_1.codeGenerationService.fetchPendingJobs();
|
|
24264
24714
|
console.log("[Loop] Fetched pending jobs", { count: jobs.length });
|
|
24265
24715
|
if (jobs.length === 0) {
|
|
24266
24716
|
console.log("[Loop] No pending jobs, sleeping");
|
|
24267
|
-
await delay(NO_JOBS_SLEEP_MS);
|
|
24717
|
+
await (0, utils_1.delay)(NO_JOBS_SLEEP_MS);
|
|
24268
24718
|
continue;
|
|
24269
24719
|
}
|
|
24270
|
-
|
|
24271
|
-
|
|
24272
|
-
logger_1.logger.info("Job details", {
|
|
24273
|
-
job: {
|
|
24274
|
-
...job,
|
|
24275
|
-
tasks: job.tasks?.map((task) => ({
|
|
24276
|
-
...task,
|
|
24277
|
-
input: redactAgentData(task.input),
|
|
24278
|
-
payload: redactAgentData(task.payload)
|
|
24279
|
-
}))
|
|
24280
|
-
}
|
|
24281
|
-
});
|
|
24282
|
-
if (!job.id) {
|
|
24283
|
-
throw new ditto_codegen_types_1.MissingJobIdError();
|
|
24284
|
-
}
|
|
24285
|
-
const jobId = job.id;
|
|
24286
|
-
logger_1.logger.info("[Loop] Selected job", { jobId });
|
|
24287
|
-
const freshToken = await codeGenerationService_1.codeGenerationService.refreshAccessToken();
|
|
24288
|
-
(0, config_1.setCurrentAccessToken)(freshToken);
|
|
24289
|
-
await codeGenerationService_1.codeGenerationService.markJobAsRuninng(jobId);
|
|
24290
|
-
await processJob(job);
|
|
24291
|
-
await codeGenerationService_1.codeGenerationService.markJobAsCompleted(jobId);
|
|
24292
|
-
logger_1.logger.info("[Loop] Processed job", { jobId });
|
|
24293
|
-
await delay(POST_JOB_SLEEP_MS);
|
|
24720
|
+
await runPendingJob(jobs[0], POLL_LOG_PREFIX);
|
|
24721
|
+
await (0, utils_1.delay)(POST_JOB_SLEEP_MS);
|
|
24294
24722
|
} catch (loopError) {
|
|
24295
24723
|
logger_1.logger.error("Polling loop encountered an error. Will continue after backoff:", {
|
|
24296
24724
|
error: loopError instanceof Error ? loopError.message : String(loopError)
|
|
24297
24725
|
});
|
|
24298
|
-
await delay(NO_JOBS_SLEEP_MS);
|
|
24726
|
+
await (0, utils_1.delay)(NO_JOBS_SLEEP_MS);
|
|
24299
24727
|
}
|
|
24300
24728
|
context_1.ctx.resetJobs();
|
|
24301
24729
|
}
|
|
@@ -24333,7 +24761,13 @@ async function main(ctx) {
|
|
|
24333
24761
|
metasiteId: ctx.metasiteId
|
|
24334
24762
|
});
|
|
24335
24763
|
await initOpenCode();
|
|
24336
|
-
|
|
24764
|
+
const nudgeListenerServer = new nudge_listener_server_1.NudgeListenerServer({
|
|
24765
|
+
fetchPendingJobs: () => codeGenerationService_1.codeGenerationService.fetchPendingJobs(),
|
|
24766
|
+
findJob: (jobId) => codeGenerationService_1.codeGenerationService.findJob(jobId),
|
|
24767
|
+
canRunJob: (job) => codeGenerationService_1.codeGenerationService.shouldProcessJob(job),
|
|
24768
|
+
runJob: (job) => runPendingJob(job, PUSH_LOG_PREFIX)
|
|
24769
|
+
}, (0, job_fetching_1.getJobFetchPort)());
|
|
24770
|
+
await (0, job_fetching_1.startJobFetching)({ runPollLoop: alwaysOnLoop, nudgeListenerServer });
|
|
24337
24771
|
}
|
|
24338
24772
|
var getFirstTask = (job) => {
|
|
24339
24773
|
return job.tasks?.[0];
|
|
@@ -24377,7 +24811,7 @@ async function reportPreDispatchFailure(jobId, error) {
|
|
|
24377
24811
|
});
|
|
24378
24812
|
try {
|
|
24379
24813
|
await codeGenerationService_1.codeGenerationService.markJobAsFailed(jobId, codegenError);
|
|
24380
|
-
await (0,
|
|
24814
|
+
await (0, utils_2.updateAllRunningTasks)(jobId, CodeGenService_1.Status.FAILED, codegenError);
|
|
24381
24815
|
} catch (reportError) {
|
|
24382
24816
|
logger_1.logger.error("[Job] Could not mark the job failed", {
|
|
24383
24817
|
jobId,
|
|
@@ -24444,6 +24878,7 @@ async function processJob(job) {
|
|
|
24444
24878
|
} finally {
|
|
24445
24879
|
jobCancellationMonitor.stop();
|
|
24446
24880
|
jobTimeoutMonitor.stop();
|
|
24881
|
+
context_1.ctx.resetJobs();
|
|
24447
24882
|
}
|
|
24448
24883
|
});
|
|
24449
24884
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@wix/ditto-codegen-public",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.443",
|
|
4
4
|
"description": "AI-powered Wix CLI app generator - standalone executable",
|
|
5
5
|
"scripts": {
|
|
6
6
|
"build": "node build.mjs",
|
|
@@ -29,5 +29,5 @@
|
|
|
29
29
|
"esbuild": "^0.27.2",
|
|
30
30
|
"vitest": "^4.0.16"
|
|
31
31
|
},
|
|
32
|
-
"falconPackageHash": "
|
|
32
|
+
"falconPackageHash": "da26fbed4274b90d804fbf1672491b33c4725d7a18de167c461deb2f"
|
|
33
33
|
}
|