@whittlelabs/sifter 0.41.2 → 0.42.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (3) hide show
  1. package/bin.js +294 -15
  2. package/bin.js.map +4 -4
  3. package/package.json +1 -1
package/bin.js CHANGED
@@ -9636,6 +9636,7 @@ var require_canonicalise = __commonJS({
9636
9636
  description: workflow.description ?? null,
9637
9637
  ownerClass: opts.ownerClass,
9638
9638
  ownerId: opts.ownerId,
9639
+ ...opts.visibility !== void 0 ? { visibility: opts.visibility } : {},
9639
9640
  retainPublishedVersions: workflow.retain?.publishedVersions ?? null,
9640
9641
  ...opts.publish !== void 0 ? { publish: opts.publish } : {},
9641
9642
  nodes,
@@ -9802,7 +9803,15 @@ var require_seed_workflows = __commonJS({
9802
9803
  for (const workflow of opts.workflows) {
9803
9804
  let ownerClass;
9804
9805
  let ownerId;
9805
- if ("service" in workflow.owner) {
9806
+ let visibility;
9807
+ if ("platform" in workflow.owner) {
9808
+ if (!opts.platformOrgId) {
9809
+ throw new errors_1.SeedWorkflowsError(workflow.name, "seedWorkflows: a platform workflow needs platformOrgId, the Whittle Labs org id");
9810
+ }
9811
+ ownerClass = "org";
9812
+ ownerId = opts.platformOrgId;
9813
+ visibility = "published";
9814
+ } else if ("service" in workflow.owner) {
9806
9815
  ownerClass = "service";
9807
9816
  ownerId = workflow.owner.service;
9808
9817
  } else {
@@ -9814,6 +9823,8 @@ var require_seed_workflows = __commonJS({
9814
9823
  ownerId = orgId;
9815
9824
  }
9816
9825
  const opts2 = { ownerClass, ownerId };
9826
+ if (visibility !== void 0)
9827
+ opts2.visibility = visibility;
9817
9828
  if (opts.env !== void 0)
9818
9829
  opts2.env = opts.env;
9819
9830
  if (opts.publish !== void 0)
@@ -9822,6 +9833,7 @@ var require_seed_workflows = __commonJS({
9822
9833
  logger.info(`seeding workflow ${workflow.name}`, {
9823
9834
  ownerClass,
9824
9835
  ownerId,
9836
+ ...visibility !== void 0 ? { visibility } : {},
9825
9837
  nodes: body2.nodes.length,
9826
9838
  transitions: body2.transitions.length
9827
9839
  });
@@ -52579,7 +52591,7 @@ var require_ajvProvider_ZaoO9afR = __commonJS({
52579
52591
  };
52580
52592
  exports3.default = formatLimitPlugin;
52581
52593
  }));
52582
- var require_dist8 = /* @__PURE__ */ require_chunk.__commonJSMin(((exports3, module3) => {
52594
+ var require_dist9 = /* @__PURE__ */ require_chunk.__commonJSMin(((exports3, module3) => {
52583
52595
  Object.defineProperty(exports3, "__esModule", { value: true });
52584
52596
  const formats_1 = require_formats();
52585
52597
  const limit_1 = require_limit();
@@ -52614,7 +52626,7 @@ var require_ajvProvider_ZaoO9afR = __commonJS({
52614
52626
  var import_ajv = require_ajv();
52615
52627
  var import__2019 = require__2019();
52616
52628
  var import__2020 = require__2020();
52617
- var import_dist = /* @__PURE__ */ require_chunk.__toESM(require_dist8(), 1);
52629
+ var import_dist = /* @__PURE__ */ require_chunk.__toESM(require_dist9(), 1);
52618
52630
  var addFormats = import_dist.default;
52619
52631
  function createDefaultAjvInstance(engineClass) {
52620
52632
  const ajv = new engineClass({
@@ -68366,6 +68378,28 @@ var require_client2 = __commonJS({
68366
68378
  shift: shift ?? null
68367
68379
  };
68368
68380
  }
68381
+ /**
68382
+ * Open the subscriber's hint stream (`GET /api/my/jobs/stream`, whittlelabs
68383
+ * ADR 0137) and hand back the raw response for @whittlelabs/realtime's
68384
+ * reader. Authenticated as every call, a 401 retried once with a refreshed
68385
+ * token. Naming the shift makes the open stream its check-in.
68386
+ */
68387
+ async openHintStream(options = {}) {
68388
+ const qs = options.shift ? `?shift=${encodeURIComponent(options.shift)}` : "";
68389
+ const url = `${this.baseUrl}/api/my/jobs/stream${qs}`;
68390
+ const headers = async (forceRefresh) => ({
68391
+ ...await this.buildHeaders(forceRefresh),
68392
+ Accept: "text/event-stream",
68393
+ ...options.lastEventId ? { "Last-Event-ID": options.lastEventId } : {}
68394
+ });
68395
+ let response = await fetch(url, { headers: await headers(false), signal: options.signal });
68396
+ if (response.status === 401 && this.getAccessToken) {
68397
+ await response.body?.cancel().catch(() => void 0);
68398
+ response = await fetch(url, { headers: await headers(true), signal: options.signal });
68399
+ }
68400
+ this.onResponse?.(response);
68401
+ return response;
68402
+ }
68369
68403
  // ── HTTP plumbing ────────────────────────────────────────────────
68370
68404
  /**
68371
68405
  * Every call's one reader. `readJsonResponse` refuses to parse a reply that
@@ -68391,12 +68425,181 @@ var require_client2 = __commonJS({
68391
68425
  }
68392
68426
  });
68393
68427
 
68428
+ // ../../packages/realtime-client/dist/reader.js
68429
+ var require_reader = __commonJS({
68430
+ "../../packages/realtime-client/dist/reader.js"(exports2) {
68431
+ "use strict";
68432
+ Object.defineProperty(exports2, "__esModule", { value: true });
68433
+ exports2.StreamSilentError = exports2.RESYNC = void 0;
68434
+ exports2.readEventStream = readEventStream;
68435
+ exports2.connectStream = connectStream;
68436
+ exports2.RESYNC = "resync";
68437
+ async function* readEventStream(body2, options = {}) {
68438
+ const reader = body2.getReader();
68439
+ const decoder = new TextDecoder();
68440
+ let buffer = "";
68441
+ try {
68442
+ for (; ; ) {
68443
+ const { value, done } = await readWithin(reader, options.silenceMs);
68444
+ if (done)
68445
+ return;
68446
+ buffer = (buffer + decoder.decode(value, { stream: true })).replace(/\r\n|\r(?!$)/g, "\n");
68447
+ let boundary;
68448
+ while ((boundary = buffer.indexOf("\n\n")) !== -1) {
68449
+ const block = buffer.slice(0, boundary);
68450
+ buffer = buffer.slice(boundary + 2);
68451
+ const message = parseBlock(block);
68452
+ if (message)
68453
+ yield message;
68454
+ }
68455
+ }
68456
+ } finally {
68457
+ await reader.cancel().catch(() => void 0);
68458
+ }
68459
+ }
68460
+ function parseBlock(block) {
68461
+ let id = null;
68462
+ let event = "message";
68463
+ const data = [];
68464
+ for (const line of block.split("\n")) {
68465
+ if (line === "" || line.startsWith(":"))
68466
+ continue;
68467
+ const colon = line.indexOf(":");
68468
+ const field = colon === -1 ? line : line.slice(0, colon);
68469
+ let value = colon === -1 ? "" : line.slice(colon + 1);
68470
+ if (value.startsWith(" "))
68471
+ value = value.slice(1);
68472
+ if (field === "data")
68473
+ data.push(value);
68474
+ else if (field === "event")
68475
+ event = value;
68476
+ else if (field === "id")
68477
+ id = value;
68478
+ }
68479
+ return data.length === 0 ? null : { id, event, data: data.join("\n") };
68480
+ }
68481
+ async function readWithin(reader, silenceMs) {
68482
+ if (silenceMs === void 0)
68483
+ return reader.read();
68484
+ let timer;
68485
+ try {
68486
+ return await Promise.race([
68487
+ reader.read(),
68488
+ new Promise((_, reject) => {
68489
+ timer = setTimeout(() => reject(new StreamSilentError(silenceMs)), silenceMs);
68490
+ })
68491
+ ]);
68492
+ } finally {
68493
+ clearTimeout(timer);
68494
+ }
68495
+ }
68496
+ var StreamSilentError = class extends Error {
68497
+ constructor(silenceMs) {
68498
+ super(`The stream sent nothing for ${silenceMs}ms`);
68499
+ this.name = "StreamSilentError";
68500
+ }
68501
+ };
68502
+ exports2.StreamSilentError = StreamSilentError;
68503
+ function connectStream(options) {
68504
+ const silenceMs = options.silenceMs ?? 45e3;
68505
+ const minMs = options.retry?.minMs ?? 1e3;
68506
+ const maxMs = options.retry?.maxMs ?? 3e4;
68507
+ const sleep = options.sleep ?? abortableSleep;
68508
+ const random = options.random ?? Math.random;
68509
+ const controller = new AbortController();
68510
+ let lastEventId = null;
68511
+ let failures = 0;
68512
+ let status = null;
68513
+ const report = (next) => {
68514
+ if (next === status)
68515
+ return;
68516
+ status = next;
68517
+ options.onStatus?.(next);
68518
+ };
68519
+ const run2 = async () => {
68520
+ while (!controller.signal.aborted) {
68521
+ try {
68522
+ const res = await options.open({ lastEventId }, controller.signal);
68523
+ if (res.status >= 400 && res.status < 500 && res.status !== 408 && res.status !== 429) {
68524
+ await res.body?.cancel().catch(() => void 0);
68525
+ report("stopped");
68526
+ return;
68527
+ }
68528
+ if (!res.ok || !res.body) {
68529
+ await res.body?.cancel().catch(() => void 0);
68530
+ throw new Error(`stream answered ${res.status}`);
68531
+ }
68532
+ report("live");
68533
+ const openedAt = Date.now();
68534
+ for await (const message of readEventStream(res.body, { silenceMs })) {
68535
+ if (controller.signal.aborted)
68536
+ return;
68537
+ if (message.id !== null)
68538
+ lastEventId = message.id;
68539
+ options.onMessage(message);
68540
+ }
68541
+ if (controller.signal.aborted)
68542
+ return;
68543
+ if (Date.now() - openedAt >= minMs) {
68544
+ failures = 0;
68545
+ continue;
68546
+ }
68547
+ } catch {
68548
+ if (controller.signal.aborted)
68549
+ return;
68550
+ }
68551
+ failures += 1;
68552
+ report("reconnecting");
68553
+ const ceiling = Math.min(maxMs, minMs * 2 ** (failures - 1));
68554
+ await sleep(Math.max(minMs / 2, random() * ceiling), controller.signal).catch(() => void 0);
68555
+ }
68556
+ };
68557
+ void run2();
68558
+ return { close: () => controller.abort() };
68559
+ }
68560
+ function abortableSleep(ms, signal) {
68561
+ return new Promise((resolve, reject) => {
68562
+ if (signal.aborted)
68563
+ return reject(signal.reason);
68564
+ const timer = setTimeout(resolve, ms);
68565
+ signal.addEventListener("abort", () => {
68566
+ clearTimeout(timer);
68567
+ reject(signal.reason);
68568
+ }, { once: true });
68569
+ });
68570
+ }
68571
+ }
68572
+ });
68573
+
68574
+ // ../../packages/realtime-client/dist/index.js
68575
+ var require_dist6 = __commonJS({
68576
+ "../../packages/realtime-client/dist/index.js"(exports2) {
68577
+ "use strict";
68578
+ Object.defineProperty(exports2, "__esModule", { value: true });
68579
+ exports2.StreamSilentError = exports2.RESYNC = exports2.readEventStream = exports2.connectStream = void 0;
68580
+ var reader_1 = require_reader();
68581
+ Object.defineProperty(exports2, "connectStream", { enumerable: true, get: function() {
68582
+ return reader_1.connectStream;
68583
+ } });
68584
+ Object.defineProperty(exports2, "readEventStream", { enumerable: true, get: function() {
68585
+ return reader_1.readEventStream;
68586
+ } });
68587
+ Object.defineProperty(exports2, "RESYNC", { enumerable: true, get: function() {
68588
+ return reader_1.RESYNC;
68589
+ } });
68590
+ Object.defineProperty(exports2, "StreamSilentError", { enumerable: true, get: function() {
68591
+ return reader_1.StreamSilentError;
68592
+ } });
68593
+ }
68594
+ });
68595
+
68394
68596
  // ../../packages/jobs/dist/subscribe.js
68395
68597
  var require_subscribe = __commonJS({
68396
68598
  "../../packages/jobs/dist/subscribe.js"(exports2) {
68397
68599
  "use strict";
68398
68600
  Object.defineProperty(exports2, "__esModule", { value: true });
68399
68601
  exports2.subscribe = subscribe;
68602
+ var realtime_client_1 = require_dist6();
68400
68603
  var response_1 = require_response();
68401
68604
  var NULL_LOGGER = {
68402
68605
  debug: () => {
@@ -68493,6 +68696,8 @@ var require_subscribe = __commonJS({
68493
68696
  return outcome;
68494
68697
  }
68495
68698
  var STOPPED = Symbol("stopped");
68699
+ var STREAMING_POLL_MS = 3e5;
68700
+ var HINT_JITTER_MS = 250;
68496
68701
  var DECLINE_WINDOW = 25;
68497
68702
  var DECLINED_MEMORY = 1e3;
68498
68703
  function subscribe(opts) {
@@ -68503,6 +68708,12 @@ var require_subscribe = __commonJS({
68503
68708
  let stopped = true;
68504
68709
  let session = 0;
68505
68710
  let pollTimer = null;
68711
+ let nextPollAt = Infinity;
68712
+ let polling = false;
68713
+ let pollAgain = false;
68714
+ let hintStream = null;
68715
+ let streamLive = false;
68716
+ let streamSupported = opts.stream ?? true;
68506
68717
  let inflight = 0;
68507
68718
  let resolvedPoolIds = [];
68508
68719
  const controllers = /* @__PURE__ */ new Map();
@@ -68655,13 +68866,50 @@ var require_subscribe = __commonJS({
68655
68866
  maxConcurrency,
68656
68867
  ...shift ? { shiftId: shift.id } : {}
68657
68868
  });
68869
+ openHintStream(mySession);
68658
68870
  schedulePoll(pollIntervalMs);
68659
68871
  }
68872
+ function openHintStream(mySession) {
68873
+ if (!streamSupported || typeof opts.jobsClient.openHintStream !== "function")
68874
+ return;
68875
+ hintStream = (0, realtime_client_1.connectStream)({
68876
+ open: ({ lastEventId }, signal) => opts.jobsClient.openHintStream({ ...shift ? { shift: shift.id } : {}, lastEventId, signal }),
68877
+ onMessage: (message) => {
68878
+ if (stopped || mySession !== session)
68879
+ return;
68880
+ if (message.event === "jobs.available" && (holds.size > 0 || inflight >= maxConcurrency))
68881
+ return;
68882
+ pollSoon(Math.random() * HINT_JITTER_MS);
68883
+ },
68884
+ onStatus: (status) => {
68885
+ if (mySession !== session)
68886
+ return;
68887
+ streamLive = status === "live";
68888
+ if (status === "stopped") {
68889
+ streamSupported = false;
68890
+ hintStream = null;
68891
+ logger.debug?.("Jobs offers no hint stream; polling instead");
68892
+ }
68893
+ if (!streamLive)
68894
+ pollSoon(pollIntervalMs);
68895
+ }
68896
+ });
68897
+ }
68898
+ function closeHintStream() {
68899
+ hintStream?.close();
68900
+ hintStream = null;
68901
+ streamLive = false;
68902
+ }
68660
68903
  async function startShift() {
68661
68904
  if (!shiftsSupported)
68662
68905
  return;
68663
68906
  try {
68907
+ const previous = shift?.id;
68664
68908
  shift = await opts.jobsClient.startShift();
68909
+ if (hintStream && shift.id !== previous) {
68910
+ closeHintStream();
68911
+ openHintStream(session);
68912
+ }
68665
68913
  } catch (err2) {
68666
68914
  if (isFatal(err2) || isUnavailable(err2) || isRateLimited(err2))
68667
68915
  throw err2;
@@ -68717,6 +68965,8 @@ var require_subscribe = __commonJS({
68717
68965
  clearTimeout(pollTimer);
68718
68966
  pollTimer = null;
68719
68967
  }
68968
+ nextPollAt = Infinity;
68969
+ closeHintStream();
68720
68970
  wakeStartup?.();
68721
68971
  }
68722
68972
  async function stop2(options = {}) {
@@ -68751,15 +69001,41 @@ var require_subscribe = __commonJS({
68751
69001
  }
68752
69002
  function schedulePoll(delayMs) {
68753
69003
  const mySession = session;
68754
- const checkInMs = shift ? shift.lapseAfterSeconds * 1e3 / 4 : Infinity;
69004
+ const checkInMs = shift && !streamLive ? shift.lapseAfterSeconds * 1e3 / 4 : Infinity;
69005
+ const ms = Math.min(delayMs, checkInMs);
69006
+ if (pollTimer !== null)
69007
+ clearTimeout(pollTimer);
69008
+ nextPollAt = Date.now() + ms;
68755
69009
  pollTimer = setTimeout(() => {
69010
+ pollTimer = null;
69011
+ nextPollAt = Infinity;
68756
69012
  void poll(mySession);
68757
- }, Math.min(delayMs, checkInMs));
69013
+ }, ms);
69014
+ }
69015
+ function pollSoon(delayMs) {
69016
+ if (stopped)
69017
+ return;
69018
+ if (polling) {
69019
+ pollAgain = true;
69020
+ return;
69021
+ }
69022
+ if (nextPollAt <= Date.now() + delayMs)
69023
+ return;
69024
+ schedulePoll(delayMs);
68758
69025
  }
68759
69026
  async function poll(mySession) {
68760
69027
  if (stopped || mySession !== session)
68761
69028
  return;
68762
- let nextPollMs = pollIntervalMs;
69029
+ polling = true;
69030
+ pollAgain = false;
69031
+ try {
69032
+ await pollOnce(mySession);
69033
+ } finally {
69034
+ polling = false;
69035
+ }
69036
+ }
69037
+ async function pollOnce(mySession) {
69038
+ let nextPollMs = streamLive ? STREAMING_POLL_MS : pollIntervalMs;
68763
69039
  try {
68764
69040
  const paused = holds.size > 0;
68765
69041
  const free = maxConcurrency - inflight;
@@ -68800,6 +69076,8 @@ var require_subscribe = __commonJS({
68800
69076
  inflight++;
68801
69077
  void runOnce(job).finally(() => {
68802
69078
  inflight--;
69079
+ if (streamLive)
69080
+ pollSoon(0);
68803
69081
  });
68804
69082
  }
68805
69083
  }
@@ -68816,8 +69094,9 @@ var require_subscribe = __commonJS({
68816
69094
  logger.error("poll failed", { error: err2 instanceof Error ? err2.message : String(err2) });
68817
69095
  }
68818
69096
  }
68819
- if (!stopped && mySession === session)
68820
- schedulePoll(nextPollMs);
69097
+ if (stopped || mySession !== session)
69098
+ return;
69099
+ schedulePoll(pollAgain ? Math.min(nextPollMs, Math.random() * HINT_JITTER_MS) : nextPollMs);
68821
69100
  }
68822
69101
  async function runOnce(available) {
68823
69102
  let dispatch;
@@ -68944,7 +69223,7 @@ var require_subscribe = __commonJS({
68944
69223
  });
68945
69224
 
68946
69225
  // ../../packages/jobs/dist/index.js
68947
- var require_dist6 = __commonJS({
69226
+ var require_dist7 = __commonJS({
68948
69227
  "../../packages/jobs/dist/index.js"(exports2) {
68949
69228
  "use strict";
68950
69229
  Object.defineProperty(exports2, "__esModule", { value: true });
@@ -69300,7 +69579,7 @@ var require_probes = __commonJS({
69300
69579
  var path_1 = __importDefault(require("path"));
69301
69580
  var yaml_1 = require_dist5();
69302
69581
  var keep_1 = require_dist4();
69303
- var jobs_1 = require_dist6();
69582
+ var jobs_1 = require_dist7();
69304
69583
  var scaffold_1 = require_scaffold();
69305
69584
  var loader_1 = require_loader();
69306
69585
  var codex_1 = require_codex();
@@ -74184,7 +74463,7 @@ var require_shuttle = __commonJS({
74184
74463
  exports2.resolveAuth = resolveAuth;
74185
74464
  var os_1 = require("os");
74186
74465
  var path_1 = require("path");
74187
- var jobs_1 = require_dist6();
74466
+ var jobs_1 = require_dist7();
74188
74467
  var self_update_1 = require_self_update();
74189
74468
  var decommission_1 = require_decommission();
74190
74469
  var loom_1 = require_dist();
@@ -75479,7 +75758,7 @@ var require_bundle_assets = __commonJS({
75479
75758
  });
75480
75759
 
75481
75760
  // ../../packages/shuttle/dist/index.js
75482
- var require_dist7 = __commonJS({
75761
+ var require_dist8 = __commonJS({
75483
75762
  "../../packages/shuttle/dist/index.js"(exports2) {
75484
75763
  "use strict";
75485
75764
  Object.defineProperty(exports2, "__esModule", { value: true });
@@ -75710,14 +75989,14 @@ var require_dist7 = __commonJS({
75710
75989
  });
75711
75990
 
75712
75991
  // src/bin.ts
75713
- var import_shuttle2 = __toESM(require_dist7());
75992
+ var import_shuttle2 = __toESM(require_dist8());
75714
75993
 
75715
75994
  // src/brand.ts
75716
75995
  var import_path = require("path");
75717
75996
  var import_promises = require("fs/promises");
75718
75997
  var import_yaml = __toESM(require_dist5());
75719
- var import_shuttle = __toESM(require_dist7());
75720
- var buildVersion = true ? "0.41.2" : pkg.version;
75998
+ var import_shuttle = __toESM(require_dist8());
75999
+ var buildVersion = true ? "0.42.1" : pkg.version;
75721
76000
  var AGENT_EXECUTORS = ["claude-code", "codex", "copilot"];
75722
76001
  var sifterBrand = {
75723
76002
  product: {