@wix/ditto-codegen-public 1.0.441 → 1.0.442

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/out.js +454 -49
  2. 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(this.withAuth(req));
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(this.withAuth(req));
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
- const authHeader = { authorization: `Bearer ${this.accessToken}` };
11350
- if (typeof req === "function") {
11351
- return (ctx) => {
11352
- const r = req(ctx);
11353
- return { ...r, headers: { ...r.headers ?? {}, ...authHeader } };
11354
- };
11355
- }
11356
- return { ...req, headers: { ...req.headers ?? {}, ...authHeader } };
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;
@@ -16508,11 +16537,13 @@ var require_utils9 = __commonJS({
16508
16537
  "dist/utils.js"(exports2) {
16509
16538
  "use strict";
16510
16539
  Object.defineProperty(exports2, "__esModule", { value: true });
16511
- exports2.errorStack = void 0;
16540
+ exports2.errorStack = exports2.delay = void 0;
16512
16541
  exports2.serializeError = serializeError;
16513
16542
  exports2.updateAllRunningTasks = updateAllRunningTasks;
16514
16543
  var types_1 = require_types_impl();
16515
16544
  var codeGenerationService_12 = require_codeGenerationService();
16545
+ var delay = (milliseconds) => new Promise((resolve) => setTimeout(resolve, milliseconds));
16546
+ exports2.delay = delay;
16516
16547
  var errorStack = (error) => error instanceof Error ? error.stack ?? error.message : String(error);
16517
16548
  exports2.errorStack = errorStack;
16518
16549
  function serializeError(error) {
@@ -23760,7 +23791,7 @@ var require_skills_installer = __commonJS({
23760
23791
  const nested = discoverSkills((0, path_12.join)(packageRoot, "skills"));
23761
23792
  return nested.length > 0 ? nested : discoverSkills(packageRoot);
23762
23793
  }
23763
- var delay2 = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
23794
+ var delay = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
23764
23795
  async function applySkillsOverride(outputPath, log) {
23765
23796
  const skillsOverride = process.env.SKILLS_OVERRIDE_BRANCH;
23766
23797
  if (!skillsOverride) {
@@ -23806,7 +23837,7 @@ var require_skills_installer = __commonJS({
23806
23837
  });
23807
23838
  const deadline = Date.now() + timeoutMs;
23808
23839
  while (Date.now() < deadline) {
23809
- await delay2(intervalMs);
23840
+ await delay(intervalMs);
23810
23841
  state = inspect(state.candidates);
23811
23842
  if (state.ready) {
23812
23843
  log.info("[Skills] Skills became available", { present: state.present });
@@ -24213,6 +24244,367 @@ var require_plugin_artifacts = __commonJS({
24213
24244
  }
24214
24245
  });
24215
24246
 
24247
+ // dist/fetch-scheduler.js
24248
+ var require_fetch_scheduler = __commonJS({
24249
+ "dist/fetch-scheduler.js"(exports2) {
24250
+ "use strict";
24251
+ Object.defineProperty(exports2, "__esModule", { value: true });
24252
+ 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;
24253
+ var logger_12 = require_logger();
24254
+ var utils_12 = require_utils9();
24255
+ exports2.MIN_FETCH_INTERVAL_MS = 1e3;
24256
+ exports2.POST_JOB_INTERVAL_MS = 3e3;
24257
+ exports2.ERROR_BACKOFF_MS = 5e3;
24258
+ exports2.MAX_MISSING_JOB_RECHECKS = 3;
24259
+ exports2.MAX_AWAITED_JOB_IDS = 4;
24260
+ var FetchScheduler = class {
24261
+ constructor(deps) {
24262
+ this.deps = deps;
24263
+ this.cycle = null;
24264
+ this.checkAgain = false;
24265
+ this.stopped = false;
24266
+ this.nextFetchNotBefore = 0;
24267
+ this.interval = 0;
24268
+ this.awaitedJobIds = /* @__PURE__ */ new Map();
24269
+ }
24270
+ start() {
24271
+ this.stopped = false;
24272
+ }
24273
+ /** A cycle already inside runJob is NOT awaited. A caller that needs exclusivity must
24274
+ * not start another runner until that cycle settles. */
24275
+ stop() {
24276
+ this.stopped = true;
24277
+ }
24278
+ /** Records the nudge and makes sure a cycle is running. It does not wait for the
24279
+ * fetch. A caller held on a slow socket times out and reads that as "machine down",
24280
+ * so retrying is ours to do, not theirs. */
24281
+ nudge(jobId) {
24282
+ if (this.stopped)
24283
+ return;
24284
+ if (jobId) {
24285
+ this.awaitedJobIds.delete(jobId);
24286
+ if (this.awaitedJobIds.size >= exports2.MAX_AWAITED_JOB_IDS) {
24287
+ this.awaitedJobIds.delete(this.awaitedJobIds.keys().next().value);
24288
+ }
24289
+ this.awaitedJobIds.set(jobId, exports2.MAX_MISSING_JOB_RECHECKS);
24290
+ }
24291
+ if (this.cycle) {
24292
+ this.checkAgain = true;
24293
+ return;
24294
+ }
24295
+ this.cycle = this.runUntilIdle().catch((error) => logger_12.logger.error("[JobFetch] Cycle aborted", { error: (0, utils_12.errorStack)(error) }));
24296
+ }
24297
+ async runUntilIdle() {
24298
+ try {
24299
+ do {
24300
+ await this.runSingleJobCycle();
24301
+ } while (this.checkAgain && !this.stopped);
24302
+ } finally {
24303
+ this.cycle = null;
24304
+ }
24305
+ }
24306
+ async runSingleJobCycle() {
24307
+ await this.throttle();
24308
+ if (this.stopped)
24309
+ return;
24310
+ this.checkAgain = false;
24311
+ const due = await this.findRunnableJob();
24312
+ if (!due)
24313
+ return;
24314
+ this.checkAgain = true;
24315
+ if (this.stopped)
24316
+ return;
24317
+ await this.attemptJob(due);
24318
+ }
24319
+ async findRunnableJob() {
24320
+ let jobs;
24321
+ try {
24322
+ jobs = await this.deps.fetchPendingJobs();
24323
+ } catch (error) {
24324
+ this.recordDebt("Fetch failed", error);
24325
+ return null;
24326
+ }
24327
+ this.schedule(exports2.MIN_FETCH_INTERVAL_MS);
24328
+ logger_12.logger.info("[JobFetch] Fetched pending jobs", { count: jobs.length });
24329
+ for (const job of jobs) {
24330
+ if (job.id)
24331
+ this.awaitedJobIds.delete(job.id);
24332
+ }
24333
+ if (jobs.length > 0)
24334
+ return jobs[0];
24335
+ if (this.awaitedJobIds.size === 0)
24336
+ return null;
24337
+ try {
24338
+ return await this.claimNudgedJob();
24339
+ } catch (error) {
24340
+ this.recordDebt("Nudged job lookup failed", error);
24341
+ return null;
24342
+ }
24343
+ }
24344
+ async attemptJob(job) {
24345
+ try {
24346
+ await this.deps.runJob(job);
24347
+ this.schedule(exports2.POST_JOB_INTERVAL_MS);
24348
+ } catch (error) {
24349
+ this.recordDebt("Job run failed", error);
24350
+ }
24351
+ }
24352
+ /** A nudged job the list did not return. Read it by key, which does not wait on the
24353
+ * index. A key read is still a replica read, so a job the server does not know about
24354
+ * yet keeps a small budget of re-checks instead of one answer settling it. */
24355
+ async claimNudgedJob() {
24356
+ for (const jobId of [...this.awaitedJobIds.keys()]) {
24357
+ if (this.stopped)
24358
+ return null;
24359
+ const job = await this.deps.findJob(jobId);
24360
+ if (job) {
24361
+ this.awaitedJobIds.delete(jobId);
24362
+ if (this.deps.canRunJob(job))
24363
+ return job;
24364
+ continue;
24365
+ }
24366
+ const rechecksLeft = this.awaitedJobIds.get(jobId);
24367
+ if (rechecksLeft === void 0)
24368
+ continue;
24369
+ if (rechecksLeft > 0) {
24370
+ this.awaitedJobIds.set(jobId, rechecksLeft - 1);
24371
+ this.checkAgain = true;
24372
+ } else {
24373
+ this.awaitedJobIds.delete(jobId);
24374
+ logger_12.logger.warn("[JobFetch] Nudged job does not exist", { jobId });
24375
+ }
24376
+ }
24377
+ return null;
24378
+ }
24379
+ schedule(intervalMs) {
24380
+ this.interval = intervalMs;
24381
+ this.nextFetchNotBefore = Date.now() + intervalMs;
24382
+ }
24383
+ /** Nobody else will retry. We already answered the caller 200. */
24384
+ recordDebt(what, error) {
24385
+ logger_12.logger.error(`[JobFetch] ${what}`, { error: (0, utils_12.errorStack)(error) });
24386
+ this.checkAgain = true;
24387
+ this.schedule(exports2.ERROR_BACKOFF_MS);
24388
+ }
24389
+ async throttle() {
24390
+ const wait = Math.min(this.nextFetchNotBefore - Date.now(), this.interval);
24391
+ if (wait > 0)
24392
+ await (0, utils_12.delay)(wait);
24393
+ }
24394
+ };
24395
+ exports2.FetchScheduler = FetchScheduler;
24396
+ }
24397
+ });
24398
+
24399
+ // dist/nudge-listener-server.js
24400
+ var require_nudge_listener_server = __commonJS({
24401
+ "dist/nudge-listener-server.js"(exports2) {
24402
+ "use strict";
24403
+ Object.defineProperty(exports2, "__esModule", { value: true });
24404
+ 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;
24405
+ var node_http_1 = require("node:http");
24406
+ var logger_12 = require_logger();
24407
+ var utils_12 = require_utils9();
24408
+ var fetch_scheduler_1 = require_fetch_scheduler();
24409
+ exports2.JOB_FETCH_PORT = 52402;
24410
+ exports2.JOB_FETCH_PATH = "/_wix/codegen/fetch-jobs";
24411
+ exports2.JOB_ID_PATTERN = /^[A-Za-z0-9_-]{1,64}$/;
24412
+ exports2.MAX_LOGGED_PATH_LENGTH = 128;
24413
+ exports2.BIND_RETRIES = 5;
24414
+ exports2.BIND_RETRY_DELAY_MS = 300;
24415
+ var NudgeListenerServer = class {
24416
+ constructor(deps, port = exports2.JOB_FETCH_PORT) {
24417
+ this.port = port;
24418
+ this.server = null;
24419
+ this.stopped = false;
24420
+ this.scheduler = new fetch_scheduler_1.FetchScheduler(deps);
24421
+ }
24422
+ async start() {
24423
+ this.stopped = false;
24424
+ this.scheduler.start();
24425
+ await this.listen();
24426
+ if (this.stopped) {
24427
+ await this.stop();
24428
+ throw new Error("Nudge listener was stopped while binding");
24429
+ }
24430
+ logger_12.logger.info("[JobFetch] Endpoint listening", {
24431
+ port: this.boundPort(),
24432
+ path: exports2.JOB_FETCH_PATH
24433
+ });
24434
+ this.scheduler.nudge();
24435
+ }
24436
+ /** Closes the socket and stops the scheduler; a cycle already inside runJob is NOT
24437
+ * awaited. A caller that needs exclusivity must not start another runner until that
24438
+ * cycle settles. */
24439
+ async stop() {
24440
+ this.stopped = true;
24441
+ this.scheduler.stop();
24442
+ const server = this.server;
24443
+ if (!server)
24444
+ return;
24445
+ this.server = null;
24446
+ server.removeAllListeners("error");
24447
+ server.on("error", (error) => logger_12.logger.warn("[JobFetch] Endpoint error while closing", {
24448
+ error: (0, utils_12.errorStack)(error)
24449
+ }));
24450
+ server.closeAllConnections();
24451
+ await new Promise((resolve) => server.close(() => resolve()));
24452
+ }
24453
+ boundPort() {
24454
+ const address = this.server?.address();
24455
+ return address && typeof address === "object" ? address.port : null;
24456
+ }
24457
+ /** The agent is restarted in a tight `while true` loop, so a bind can land before
24458
+ * the previous process has released the port. Falling straight back to poll there
24459
+ * would strand the machine on the slow path for the whole session. */
24460
+ async listen() {
24461
+ for (let attempt = 0; ; attempt++) {
24462
+ try {
24463
+ return await this.listenOnce();
24464
+ } catch (error) {
24465
+ const inUse = error?.code === "EADDRINUSE" && attempt < exports2.BIND_RETRIES;
24466
+ if (!inUse)
24467
+ throw error;
24468
+ await (0, utils_12.delay)(exports2.BIND_RETRY_DELAY_MS);
24469
+ }
24470
+ }
24471
+ }
24472
+ listenOnce() {
24473
+ return new Promise((resolve, reject) => {
24474
+ const server = (0, node_http_1.createServer)((req, res) => {
24475
+ try {
24476
+ this.handleRequest(req, res);
24477
+ } catch (error) {
24478
+ logger_12.logger.error("[JobFetch] Request handler failed", {
24479
+ error: (0, utils_12.errorStack)(error)
24480
+ });
24481
+ if (res.headersSent)
24482
+ res.destroy();
24483
+ else
24484
+ this.respond(res, 500, { error: "request failed" });
24485
+ }
24486
+ });
24487
+ server.once("error", reject);
24488
+ server.listen(this.port, "0.0.0.0", () => {
24489
+ server.removeListener("error", reject);
24490
+ server.on("error", (error) => {
24491
+ logger_12.logger.error("[JobFetch] Endpoint failed after binding, exiting", {
24492
+ error: (0, utils_12.errorStack)(error)
24493
+ });
24494
+ process.exit(1);
24495
+ });
24496
+ this.server = server;
24497
+ resolve();
24498
+ });
24499
+ });
24500
+ }
24501
+ handleRequest(req, res) {
24502
+ const url = new URL((req.url ?? "").replace(/^\/+/, "/"), "http://localhost");
24503
+ const path = url.pathname.replace(/\/+$/, "");
24504
+ if (req.method !== "GET" || path !== exports2.JOB_FETCH_PATH) {
24505
+ logger_12.logger.warn("[JobFetch] Rejected request", {
24506
+ method: req.method,
24507
+ path: url.pathname.slice(0, exports2.MAX_LOGGED_PATH_LENGTH)
24508
+ });
24509
+ this.respond(res, 404, { error: "not found" });
24510
+ return;
24511
+ }
24512
+ const nudgedId = url.searchParams.get("jobId");
24513
+ const usable = nudgedId === null || exports2.JOB_ID_PATTERN.test(nudgedId);
24514
+ if (!usable) {
24515
+ logger_12.logger.warn("[JobFetch] Nudge carried an unusable jobId", {
24516
+ length: nudgedId.length
24517
+ });
24518
+ }
24519
+ const jobId = usable ? nudgedId ?? void 0 : void 0;
24520
+ this.scheduler.nudge(jobId);
24521
+ logger_12.logger.info("[JobFetch] Nudge accepted", { jobId });
24522
+ this.respond(res, 200, { accepted: true });
24523
+ }
24524
+ respond(res, status, body) {
24525
+ res.writeHead(status, {
24526
+ "Content-Type": "application/json",
24527
+ // A cached response would turn every nudge into a no-op.
24528
+ "Cache-Control": "no-store"
24529
+ });
24530
+ res.end(JSON.stringify(body));
24531
+ }
24532
+ };
24533
+ exports2.NudgeListenerServer = NudgeListenerServer;
24534
+ }
24535
+ });
24536
+
24537
+ // dist/job-fetching.js
24538
+ var require_job_fetching = __commonJS({
24539
+ "dist/job-fetching.js"(exports2) {
24540
+ "use strict";
24541
+ Object.defineProperty(exports2, "__esModule", { value: true });
24542
+ exports2.JobDeliveryMode = void 0;
24543
+ exports2.getJobDeliveryMode = getJobDeliveryMode;
24544
+ exports2.getJobFetchPort = getJobFetchPort;
24545
+ exports2.startJobFetching = startJobFetching;
24546
+ var nudge_listener_server_12 = require_nudge_listener_server();
24547
+ var logger_12 = require_logger();
24548
+ var utils_12 = require_utils9();
24549
+ var JobDeliveryMode;
24550
+ (function(JobDeliveryMode2) {
24551
+ JobDeliveryMode2["POLL"] = "poll";
24552
+ JobDeliveryMode2["PUSH"] = "push";
24553
+ })(JobDeliveryMode || (exports2.JobDeliveryMode = JobDeliveryMode = {}));
24554
+ var DEFAULT_MODE = JobDeliveryMode.POLL;
24555
+ function getJobDeliveryMode() {
24556
+ const mode = process.env.CODEGEN_JOB_DELIVERY?.trim().toLowerCase();
24557
+ const supported = Object.values(JobDeliveryMode).find((candidate) => candidate === mode);
24558
+ if (supported)
24559
+ return supported;
24560
+ if (mode) {
24561
+ logger_12.logger.warn("[Startup] Unrecognized CODEGEN_JOB_DELIVERY, using default", {
24562
+ mode,
24563
+ default: DEFAULT_MODE
24564
+ });
24565
+ }
24566
+ return DEFAULT_MODE;
24567
+ }
24568
+ var MIN_PORT = 1;
24569
+ var MAX_PORT = 65535;
24570
+ function getJobFetchPort() {
24571
+ const configured = process.env.CODEGEN_JOB_FETCH_PORT;
24572
+ if (configured === void 0)
24573
+ return nudge_listener_server_12.JOB_FETCH_PORT;
24574
+ const port = /^\s*\d+\s*$/.test(configured) ? Number(configured) : NaN;
24575
+ if (Number.isInteger(port) && port >= MIN_PORT && port <= MAX_PORT)
24576
+ return port;
24577
+ logger_12.logger.warn("[Startup] Unusable CODEGEN_JOB_FETCH_PORT, using default", {
24578
+ port: configured,
24579
+ default: nudge_listener_server_12.JOB_FETCH_PORT
24580
+ });
24581
+ return nudge_listener_server_12.JOB_FETCH_PORT;
24582
+ }
24583
+ async function startJobFetching(deps) {
24584
+ const mode = getJobDeliveryMode();
24585
+ logger_12.logger.info("[Startup] Job delivery mode", { mode });
24586
+ if (mode === JobDeliveryMode.POLL) {
24587
+ return deps.runPollLoop();
24588
+ }
24589
+ try {
24590
+ await deps.nudgeListenerServer.start();
24591
+ } catch (error) {
24592
+ try {
24593
+ await deps.nudgeListenerServer.stop();
24594
+ } catch (stopError) {
24595
+ logger_12.logger.error("[Startup] Closing the half-started listener failed", {
24596
+ error: (0, utils_12.errorStack)(stopError)
24597
+ });
24598
+ }
24599
+ logger_12.logger.error("[Startup] Push delivery unavailable, falling back to poll", {
24600
+ error: (0, utils_12.errorStack)(error)
24601
+ });
24602
+ return deps.runPollLoop();
24603
+ }
24604
+ }
24605
+ }
24606
+ });
24607
+
24216
24608
  // dist/index.js
24217
24609
  Object.defineProperty(exports, "__esModule", { value: true });
24218
24610
  exports.processJob = processJob;
@@ -24241,61 +24633,67 @@ var subagent_tool_logger_1 = require_subagent_tool_logger();
24241
24633
  var plugin_artifacts_1 = require_plugin_artifacts();
24242
24634
  var config_1 = require_config();
24243
24635
  var environments_1 = require_environments();
24244
- var plugin_host_1 = require_plugin_host();
24245
24636
  var utils_1 = require_utils9();
24637
+ var job_fetching_1 = require_job_fetching();
24638
+ var nudge_listener_server_1 = require_nudge_listener_server();
24639
+ var plugin_host_1 = require_plugin_host();
24640
+ var utils_2 = require_utils9();
24246
24641
  var sessionId = process.env.CODEGEN_SESSION_ID || (0, crypto_1.randomUUID)();
24247
24642
  process.env.CODEGEN_SESSION_ID = sessionId;
24248
24643
  (0, logger_1.initLogger)(sessionId);
24249
24644
  var jobCancellationMonitor = new job_cancellation_monitor_1.JobCancellationMonitor(codeGenerationService_1.codeGenerationService);
24250
24645
  var jobTimeoutMonitor = new job_timeout_monitor_1.JobTimeoutMonitor(codeGenerationService_1.codeGenerationService);
24251
- var delay = (milliseconds) => new Promise((resolve) => setTimeout(resolve, milliseconds));
24646
+ var POLL_LOG_PREFIX = "[Loop]";
24647
+ var PUSH_LOG_PREFIX = "[JobFetch]";
24252
24648
  var ACTIVE_JOB_SLEEP_MS = 1e3;
24253
24649
  var NO_JOBS_SLEEP_MS = 5e3;
24254
24650
  var POST_JOB_SLEEP_MS = 3e3;
24651
+ var runPendingJob = async (job, logPrefix) => {
24652
+ const redactAgentData = (payload) => payload?.agentData ? { ...payload, agentData: Object.keys(payload.agentData) } : payload;
24653
+ logger_1.logger.info("Job details", {
24654
+ job: {
24655
+ ...job,
24656
+ tasks: job.tasks?.map((task) => ({
24657
+ ...task,
24658
+ input: redactAgentData(task.input),
24659
+ payload: redactAgentData(task.payload)
24660
+ }))
24661
+ }
24662
+ });
24663
+ if (!job.id) {
24664
+ throw new ditto_codegen_types_1.MissingJobIdError();
24665
+ }
24666
+ const jobId = job.id;
24667
+ logger_1.logger.info(`${logPrefix} Selected job`, { jobId });
24668
+ const freshToken = await codeGenerationService_1.codeGenerationService.refreshAccessToken();
24669
+ (0, config_1.setCurrentAccessToken)(freshToken);
24670
+ await codeGenerationService_1.codeGenerationService.markJobAsRuninng(jobId);
24671
+ await processJob(job);
24672
+ await codeGenerationService_1.codeGenerationService.markJobAsCompleted(jobId);
24673
+ logger_1.logger.info(`${logPrefix} Processed job`, { jobId });
24674
+ };
24255
24675
  var alwaysOnLoop = async () => {
24256
24676
  while (true) {
24257
24677
  try {
24258
24678
  if (context_1.ctx.hasActiveJobs()) {
24259
24679
  console.log(`[Loop] Local active job in progress. Sleeping ${ACTIVE_JOB_SLEEP_MS}ms`);
24260
- await delay(ACTIVE_JOB_SLEEP_MS);
24680
+ await (0, utils_1.delay)(ACTIVE_JOB_SLEEP_MS);
24261
24681
  continue;
24262
24682
  }
24263
24683
  const jobs = await codeGenerationService_1.codeGenerationService.fetchPendingJobs();
24264
24684
  console.log("[Loop] Fetched pending jobs", { count: jobs.length });
24265
24685
  if (jobs.length === 0) {
24266
24686
  console.log("[Loop] No pending jobs, sleeping");
24267
- await delay(NO_JOBS_SLEEP_MS);
24687
+ await (0, utils_1.delay)(NO_JOBS_SLEEP_MS);
24268
24688
  continue;
24269
24689
  }
24270
- const job = jobs[0];
24271
- const redactAgentData = (payload) => payload?.agentData ? { ...payload, agentData: Object.keys(payload.agentData) } : payload;
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);
24690
+ await runPendingJob(jobs[0], POLL_LOG_PREFIX);
24691
+ await (0, utils_1.delay)(POST_JOB_SLEEP_MS);
24294
24692
  } catch (loopError) {
24295
24693
  logger_1.logger.error("Polling loop encountered an error. Will continue after backoff:", {
24296
24694
  error: loopError instanceof Error ? loopError.message : String(loopError)
24297
24695
  });
24298
- await delay(NO_JOBS_SLEEP_MS);
24696
+ await (0, utils_1.delay)(NO_JOBS_SLEEP_MS);
24299
24697
  }
24300
24698
  context_1.ctx.resetJobs();
24301
24699
  }
@@ -24333,7 +24731,13 @@ async function main(ctx) {
24333
24731
  metasiteId: ctx.metasiteId
24334
24732
  });
24335
24733
  await initOpenCode();
24336
- await alwaysOnLoop();
24734
+ const nudgeListenerServer = new nudge_listener_server_1.NudgeListenerServer({
24735
+ fetchPendingJobs: () => codeGenerationService_1.codeGenerationService.fetchPendingJobs(),
24736
+ findJob: (jobId) => codeGenerationService_1.codeGenerationService.findJob(jobId),
24737
+ canRunJob: (job) => codeGenerationService_1.codeGenerationService.shouldProcessJob(job),
24738
+ runJob: (job) => runPendingJob(job, PUSH_LOG_PREFIX)
24739
+ }, (0, job_fetching_1.getJobFetchPort)());
24740
+ await (0, job_fetching_1.startJobFetching)({ runPollLoop: alwaysOnLoop, nudgeListenerServer });
24337
24741
  }
24338
24742
  var getFirstTask = (job) => {
24339
24743
  return job.tasks?.[0];
@@ -24377,7 +24781,7 @@ async function reportPreDispatchFailure(jobId, error) {
24377
24781
  });
24378
24782
  try {
24379
24783
  await codeGenerationService_1.codeGenerationService.markJobAsFailed(jobId, codegenError);
24380
- await (0, utils_1.updateAllRunningTasks)(jobId, CodeGenService_1.Status.FAILED, codegenError);
24784
+ await (0, utils_2.updateAllRunningTasks)(jobId, CodeGenService_1.Status.FAILED, codegenError);
24381
24785
  } catch (reportError) {
24382
24786
  logger_1.logger.error("[Job] Could not mark the job failed", {
24383
24787
  jobId,
@@ -24444,6 +24848,7 @@ async function processJob(job) {
24444
24848
  } finally {
24445
24849
  jobCancellationMonitor.stop();
24446
24850
  jobTimeoutMonitor.stop();
24851
+ context_1.ctx.resetJobs();
24447
24852
  }
24448
24853
  });
24449
24854
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@wix/ditto-codegen-public",
3
- "version": "1.0.441",
3
+ "version": "1.0.442",
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": "b04a4f2857569aa9b70fbf2fc57a6b3c7db84e442334799481a9cc6c"
32
+ "falconPackageHash": "19c7b1e106b5b7a1aa3bc62b9fc8ebae4ce01f8641d5971c6e7138c3"
33
33
  }