@zixt/host 0.0.8 → 0.0.9

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/index.js +144 -7
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -31,7 +31,7 @@ import { homedir } from "node:os";
31
31
  // package.json
32
32
  var package_default = {
33
33
  name: "@zixt/host",
34
- version: "0.0.8",
34
+ version: "0.0.9",
35
35
  type: "module",
36
36
  exports: {
37
37
  ".": "./src/client.ts",
@@ -15272,6 +15272,12 @@ var HostTelemetry = external_exports.object({
15272
15272
  * recovery path; this is deliberately not inferred from package version.
15273
15273
  */
15274
15274
  taskAuthorityLifecycle: external_exports.literal(true).optional(),
15275
+ /**
15276
+ * Understands structured provider-operation retry responses and can
15277
+ * wait cancellably before repeating the same logical request. Missing
15278
+ * legacy Hosts must receive the original strict refusal frame.
15279
+ */
15280
+ providerOperationGrantRetry: external_exports.literal(true).optional(),
15275
15281
  linearToolPack: external_exports.boolean().default(false),
15276
15282
  providerToolPacks: external_exports.array(ProviderToolPackCapability).max(20).superRefine((capabilities, ctx) => {
15277
15283
  const providers = capabilities.map(({ provider }) => provider);
@@ -15412,12 +15418,37 @@ var HostRequiredIntegrationSummary = external_exports.object({
15412
15418
  failedCount: external_exports.number().int().min(0),
15413
15419
  unknownCount: external_exports.number().int().min(0)
15414
15420
  });
15421
+ var HostQueuedTaskDetail = external_exports.object({
15422
+ id: TaskId,
15423
+ title: external_exports.string().min(1).max(300),
15424
+ agentName: external_exports.string().min(1).max(120),
15425
+ runnerType: RunnerType,
15426
+ placement: external_exports.enum([
15427
+ "ready_here",
15428
+ "ready_elsewhere",
15429
+ "blocked_everywhere",
15430
+ "assigned_elsewhere",
15431
+ "evaluation_unknown"
15432
+ ]),
15433
+ placementReason: external_exports.string().min(1).max(2e3),
15434
+ eligibleMachineCount: external_exports.number().int().min(0),
15435
+ /** A bounded preview; eligibleMachineCount remains exact when this is truncated. */
15436
+ eligibleMachineNames: external_exports.array(external_exports.string().min(1).max(120)).max(10),
15437
+ /** Queue timing is independent from Machine placement above. */
15438
+ queueState: external_exports.enum(["ready", "decision_pending", "waiting", "retry_due", "retry_overdue"]),
15439
+ queueReason: external_exports.string().min(1).max(2e3),
15440
+ retryAt: IsoDate2.nullable()
15441
+ });
15415
15442
  var HostWorkSummary = external_exports.object({
15416
15443
  activeTaskCount: external_exports.number().int().min(0),
15417
15444
  queuedOrgTaskCount: external_exports.number().int().min(0),
15418
15445
  queuedEligibleTaskCount: external_exports.number().int().min(0),
15446
+ /** Exact count across the full relevant queue, independent of the bounded detail preview. */
15447
+ overdueRelevantTaskCount: external_exports.number().int().min(0),
15419
15448
  /** Runner families used by queued Tasks that may target this Machine. */
15420
15449
  queuedRunnerTypes: external_exports.array(RunnerType),
15450
+ /** Bounded attention-first queue preview with exact Admin/Owner placement evidence. */
15451
+ queuedTaskDetails: external_exports.array(HostQueuedTaskDetail).max(10),
15421
15452
  eligibilityState: HostEligibilityState,
15422
15453
  eligibilityReason: external_exports.string().min(1).max(2e3)
15423
15454
  });
@@ -18133,6 +18164,30 @@ var ProviderOperationGrantRequestFrame = external_exports.discriminatedUnion("op
18133
18164
  }
18134
18165
  )
18135
18166
  ]);
18167
+ var ProviderOperationGrantFailureCode = external_exports.enum([
18168
+ "provider_timeout",
18169
+ "provider_rate_limited",
18170
+ "provider_unavailable",
18171
+ "provider_authority_rejected",
18172
+ "provider_request_rejected",
18173
+ "provider_not_found",
18174
+ "provider_invalid_response",
18175
+ "provider_issuance_unresolved",
18176
+ "provider_grant_delivery_unresolved"
18177
+ ]);
18178
+ var ProviderOperationGrantRetryCode = external_exports.enum([
18179
+ "provider_timeout",
18180
+ "provider_rate_limited",
18181
+ "provider_unavailable",
18182
+ "provider_invalid_response",
18183
+ "provider_issuance_unresolved",
18184
+ "provider_grant_delivery_unresolved"
18185
+ ]);
18186
+ var ProviderOperationGrantRetry = external_exports.object({
18187
+ code: ProviderOperationGrantRetryCode,
18188
+ /** Never earlier than the durable claim's safe reclaim boundary. */
18189
+ retryAt: IsoDate
18190
+ }).strict();
18136
18191
  var ProviderOperationGrantResultFrame = external_exports.discriminatedUnion("ok", [
18137
18192
  external_exports.object({
18138
18193
  type: external_exports.literal("provider.operation.grant.result"),
@@ -18150,7 +18205,9 @@ var ProviderOperationGrantResultFrame = external_exports.discriminatedUnion("ok"
18150
18205
  requestId: external_exports.string().min(1).max(200),
18151
18206
  ok: external_exports.literal(false),
18152
18207
  grant: external_exports.never().optional(),
18153
- error: external_exports.string().min(1).max(2e3).optional()
18208
+ error: external_exports.string().min(1).max(2e3).optional(),
18209
+ /** Sent only when the connected Host explicitly advertised support. */
18210
+ retry: ProviderOperationGrantRetry.optional()
18154
18211
  }).strict()
18155
18212
  ]);
18156
18213
  var BrowserStateFrame = external_exports.object({
@@ -19210,6 +19267,52 @@ var GithubGrantError = class extends Error {
19210
19267
  this.name = `GithubGrantError:${reason}`;
19211
19268
  }
19212
19269
  };
19270
+ async function waitForOperationGrantRetry(retryAt, signal) {
19271
+ const deadline = Date.parse(retryAt);
19272
+ if (!Number.isFinite(deadline) || signal.aborted) return false;
19273
+ if (deadline <= Date.now()) return true;
19274
+ return await new Promise((resolve13) => {
19275
+ let settled = false;
19276
+ let timer;
19277
+ const finish = (ready) => {
19278
+ if (settled) return;
19279
+ settled = true;
19280
+ if (timer) clearTimeout(timer);
19281
+ signal.removeEventListener("abort", onAbort);
19282
+ resolve13(ready);
19283
+ };
19284
+ const onAbort = () => finish(false);
19285
+ const schedule = () => {
19286
+ const remaining = deadline - Date.now();
19287
+ if (remaining <= 0) {
19288
+ finish(true);
19289
+ return;
19290
+ }
19291
+ timer = setTimeout(schedule, Math.min(remaining, 2147e6));
19292
+ timer.unref?.();
19293
+ };
19294
+ signal.addEventListener("abort", onAbort, { once: true });
19295
+ if (signal.aborted) {
19296
+ finish(false);
19297
+ return;
19298
+ }
19299
+ schedule();
19300
+ });
19301
+ }
19302
+ function operationGrantRetryCause(code) {
19303
+ if (code === "provider_timeout") return "GitHub did not answer the credential request in time";
19304
+ if (code === "provider_rate_limited") return "GitHub rate-limited the credential request";
19305
+ if (code === "provider_invalid_response") {
19306
+ return "GitHub returned an invalid credential response";
19307
+ }
19308
+ if (code === "provider_issuance_unresolved") {
19309
+ return "GitHub credential issuance is still unresolved";
19310
+ }
19311
+ if (code === "provider_grant_delivery_unresolved") {
19312
+ return "Zixt is waiting for a previously issued GitHub credential to expire before retrying delivery";
19313
+ }
19314
+ return "GitHub is temporarily unavailable for credential issuance";
19315
+ }
19213
19316
  var HostClient = class _HostClient {
19214
19317
  constructor(opts) {
19215
19318
  this.opts = opts;
@@ -19887,7 +19990,13 @@ var HostClient = class _HostClient {
19887
19990
  if (!frame.ok) {
19888
19991
  clearTimeout(waiter.timer);
19889
19992
  this.operationGrantWaiters.delete(frame.requestId);
19890
- waiter.deny(false, "refused_by_zixt", frame.error);
19993
+ waiter.deny(
19994
+ frame.retry !== void 0,
19995
+ "refused_by_zixt",
19996
+ frame.error,
19997
+ frame.retry?.retryAt,
19998
+ frame.retry?.code
19999
+ );
19891
20000
  return;
19892
20001
  }
19893
20002
  const { grant } = frame;
@@ -19977,6 +20086,7 @@ var HostClient = class _HostClient {
19977
20086
  capabilities: {
19978
20087
  ...measuredCapabilities,
19979
20088
  linearToolPack: measured.capabilities?.linearToolPack ?? false,
20089
+ providerOperationGrantRetry: true,
19980
20090
  ...workerWatchdogIsActive() ? { taskAuthorityLifecycle: true } : {}
19981
20091
  },
19982
20092
  // Evidence, not configuration: the cloud says which paths matter and
@@ -20458,9 +20568,11 @@ var HostClient = class _HostClient {
20458
20568
  throw new Error("No GitHub change was attempted; the authority grant was not received.");
20459
20569
  }
20460
20570
  const attempts = options?.maxAttempts ?? 1;
20571
+ let attemptBudget = attempts;
20572
+ let structuredRetryUsed = false;
20461
20573
  let failureReason = "no_reply_from_zixt";
20462
20574
  let failureDetail;
20463
- for (let attempt = 0; attempt < attempts; attempt++) {
20575
+ for (let attempt = 0; attempt < attemptBudget; attempt++) {
20464
20576
  if (authorityController.signal.aborted) break;
20465
20577
  const socket = this.ws;
20466
20578
  if (!socket || socket.readyState !== WebSocket.OPEN) break;
@@ -20497,7 +20609,14 @@ var HostClient = class _HostClient {
20497
20609
  addSensitiveValues(providerGrantSensitiveValues(grant));
20498
20610
  resolve13({ grant });
20499
20611
  },
20500
- deny: (retryable, reason, detail) => resolve13({ grant: null, retryable, reason, ...detail ? { detail } : {} })
20612
+ deny: (retryable, reason, detail, retryAt, retryCode) => resolve13({
20613
+ grant: null,
20614
+ retryable,
20615
+ reason,
20616
+ ...detail ? { detail } : {},
20617
+ ...retryAt ? { retryAt } : {},
20618
+ ...retryCode ? { retryCode } : {}
20619
+ })
20501
20620
  });
20502
20621
  try {
20503
20622
  socket.send(JSON.stringify(parsed.data));
@@ -20515,7 +20634,22 @@ var HostClient = class _HostClient {
20515
20634
  }
20516
20635
  failureReason = outcome.reason;
20517
20636
  failureDetail = outcome.detail;
20518
- if (!outcome.retryable) break;
20637
+ const structuredRetryAt = outcome.retryAt;
20638
+ const structuredRetryCode = outcome.retryCode;
20639
+ const structuredRetry = structuredRetryAt !== void 0 && structuredRetryCode !== void 0;
20640
+ if (structuredRetry && structuredRetryAt && structuredRetryCode) {
20641
+ if (structuredRetryUsed) break;
20642
+ structuredRetryUsed = true;
20643
+ if (attempt + 1 >= attemptBudget) attemptBudget += 1;
20644
+ emitEvent(
20645
+ "status",
20646
+ `${operationGrantRetryCause(structuredRetryCode)}. Zixt will retry automatically at ${structuredRetryAt}; no repository change was attempted.`
20647
+ );
20648
+ }
20649
+ if (!outcome.retryable || attempt + 1 >= attemptBudget) break;
20650
+ if (outcome.retryAt !== void 0 && !await waitForOperationGrantRetry(outcome.retryAt, authorityController.signal)) {
20651
+ break;
20652
+ }
20519
20653
  }
20520
20654
  throw new GithubGrantError(failureReason, failureDetail);
20521
20655
  };
@@ -27199,7 +27333,10 @@ function createGithubRepositoryCreator(input) {
27199
27333
  operation: "repository.clone_created",
27200
27334
  repositoryId: repository.repositoryId
27201
27335
  },
27202
- { maxAttempts: 1 }
27336
+ // The request only obtains fenced credential authority; it does not
27337
+ // repeat repository creation. A second transport probe is required
27338
+ // to recover a cloud commit whose volatile success frame was lost.
27339
+ { maxAttempts: 2 }
27203
27340
  ),
27204
27341
  {
27205
27342
  operation: "repository.clone_created",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zixt/host",
3
- "version": "0.0.8",
3
+ "version": "0.0.9",
4
4
  "type": "module",
5
5
  "exports": {
6
6
  ".": "./src/client.ts",