@granular-software/sdk 0.4.67 → 0.4.69

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/index.mjs CHANGED
@@ -20409,6 +20409,258 @@ var Granular = class _Granular {
20409
20409
  }
20410
20410
  };
20411
20411
 
20412
+ // src/environment-setup.ts
20413
+ var EnvironmentSetupTerminalError = class extends Error {
20414
+ constructor(setup) {
20415
+ super(
20416
+ setup?.errorMessage?.trim() || "Environment setup failed before all records were imported."
20417
+ );
20418
+ this.name = "EnvironmentSetupTerminalError";
20419
+ }
20420
+ };
20421
+ function environmentSetupFailedError(setup) {
20422
+ return new EnvironmentSetupTerminalError(setup);
20423
+ }
20424
+ function environmentSetupAbortError() {
20425
+ const error = new Error("Environment setup polling was aborted.");
20426
+ error.name = "AbortError";
20427
+ return error;
20428
+ }
20429
+ function throwIfAborted(signal) {
20430
+ if (signal.aborted) {
20431
+ throw environmentSetupAbortError();
20432
+ }
20433
+ }
20434
+ function abortableSleep(ms, signal) {
20435
+ return new Promise((resolve, reject) => {
20436
+ if (signal.aborted) {
20437
+ reject(environmentSetupAbortError());
20438
+ return;
20439
+ }
20440
+ const timeout = setTimeout(() => {
20441
+ signal.removeEventListener("abort", abort);
20442
+ resolve();
20443
+ }, ms);
20444
+ const abort = () => {
20445
+ clearTimeout(timeout);
20446
+ signal.removeEventListener("abort", abort);
20447
+ reject(environmentSetupAbortError());
20448
+ };
20449
+ signal.addEventListener("abort", abort, { once: true });
20450
+ });
20451
+ }
20452
+ function setupIsRunning(setup) {
20453
+ return setup?.lifecycleStatus === "running";
20454
+ }
20455
+ function setupHasFailed(setup) {
20456
+ return setup?.lifecycleStatus === "failed";
20457
+ }
20458
+ function hasRecordFailures(setup) {
20459
+ return Boolean(
20460
+ setup && (setup.failedRecords > 0 || setup.canceledRecords > 0)
20461
+ );
20462
+ }
20463
+ function setupHasTerminalLifecycleFailure(setup) {
20464
+ return setupHasFailed(setup);
20465
+ }
20466
+ function importsAreActive(summary) {
20467
+ return Boolean(
20468
+ summary && (summary.awaitingRecords > 0 || summary.activeImports > 0)
20469
+ );
20470
+ }
20471
+ function numericRetryAfter(value) {
20472
+ return typeof value === "number" && Number.isFinite(value) ? Math.max(0, Math.round(value)) : null;
20473
+ }
20474
+ function environmentSetupTimeoutError(maxDurationMs) {
20475
+ return new Error(`Environment setup timed out after ${maxDurationMs}ms.`);
20476
+ }
20477
+ function environmentSetupProgressFromResponse(environment, response, retryAfterMs) {
20478
+ const readiness = response.readiness;
20479
+ const nextEnvironment = {
20480
+ ...environment,
20481
+ ...response.environment || {}
20482
+ };
20483
+ const explicitReady = typeof readiness?.ready === "boolean" ? readiness.ready : typeof response.ready === "boolean" ? response.ready : void 0;
20484
+ const hasResponseSetup = Object.prototype.hasOwnProperty.call(
20485
+ response,
20486
+ "setup"
20487
+ );
20488
+ const hasReadinessSetup = readiness !== null && typeof readiness === "object" && Object.prototype.hasOwnProperty.call(readiness, "setup");
20489
+ const hasEnvironmentSetup = response.environment !== null && typeof response.environment === "object" && Object.prototype.hasOwnProperty.call(response.environment, "setup");
20490
+ const setup = hasResponseSetup ? response.setup ?? null : hasReadinessSetup ? readiness?.setup ?? null : hasEnvironmentSetup ? response.environment?.setup ?? null : explicitReady === true ? null : nextEnvironment.setup ?? null;
20491
+ nextEnvironment.setup = setup;
20492
+ const summary = response.summary ?? readiness?.summary ?? null;
20493
+ const retry = [
20494
+ retryAfterMs,
20495
+ response.retryAfterMs,
20496
+ readiness?.retryAfterMs
20497
+ ].find((value) => typeof value === "number" && Number.isFinite(value));
20498
+ const recordFailures = hasRecordFailures(setup) || hasRecordFailures(summary);
20499
+ return {
20500
+ environment: nextEnvironment,
20501
+ setup,
20502
+ summary,
20503
+ ready: explicitReady !== false && !setupIsRunning(setup) && !setupHasFailed(setup) && (explicitReady === true || !recordFailures) && !importsAreActive(summary),
20504
+ retryAfterMs: numericRetryAfter(retry)
20505
+ };
20506
+ }
20507
+ function environmentSetupProgressFromError(environment, error) {
20508
+ if (!error || typeof error !== "object") return null;
20509
+ const candidate = error;
20510
+ if (candidate.status !== 503 && candidate.status !== 202 || typeof candidate.body !== "string") {
20511
+ return null;
20512
+ }
20513
+ try {
20514
+ const response = JSON.parse(candidate.body);
20515
+ const explicitReady = response?.readiness?.ready ?? (typeof response?.ready === "boolean" ? response.ready : void 0);
20516
+ if (candidate.status === 202) {
20517
+ const progress = environmentSetupProgressFromResponse(
20518
+ environment,
20519
+ response,
20520
+ numericRetryAfter(candidate.retryAfterMs)
20521
+ );
20522
+ return explicitReady === void 0 ? { ...progress, ready: false } : progress;
20523
+ }
20524
+ return explicitReady === false ? environmentSetupProgressFromResponse(
20525
+ environment,
20526
+ response,
20527
+ numericRetryAfter(candidate.retryAfterMs)
20528
+ ) : null;
20529
+ } catch {
20530
+ return null;
20531
+ }
20532
+ }
20533
+ function defaultTransientError(error) {
20534
+ if (!error) return false;
20535
+ const status = typeof error === "object" ? error.status : void 0;
20536
+ if (typeof status === "number") {
20537
+ return status === 408 || status === 425 || status === 429 || status >= 500;
20538
+ }
20539
+ const message = error instanceof Error ? error.message : String(error);
20540
+ return /failed to fetch|network error|network connection lost|connection (?:reset|closed|refused)|econnreset|socket hang up|socket connection was closed unexpectedly|dns|timed out/i.test(
20541
+ message
20542
+ );
20543
+ }
20544
+ async function pollEnvironmentSetup(input) {
20545
+ const maxAttempts = Math.max(1, input.maxAttempts ?? 3);
20546
+ const maxDurationMs = Math.max(1, input.maxDurationMs ?? 12e4);
20547
+ const sleep2 = input.sleep || ((ms, signal2) => abortableSleep(ms, signal2 || new AbortController().signal));
20548
+ const now = input.now || (() => Date.now());
20549
+ const isTransientError = input.isTransientError || defaultTransientError;
20550
+ const internalController = input.signal ? null : new AbortController();
20551
+ const signal = input.signal || internalController.signal;
20552
+ const startedAt = now();
20553
+ let currentEnvironment = input.environment;
20554
+ let transientFailures = 0;
20555
+ let attempt = 0;
20556
+ const waitForNextAttempt = async (requestedDelayMs) => {
20557
+ throwIfAborted(signal);
20558
+ const remainingMs = maxDurationMs - Math.max(0, now() - startedAt);
20559
+ if (remainingMs <= 0) {
20560
+ throw environmentSetupTimeoutError(maxDurationMs);
20561
+ }
20562
+ await sleep2(Math.min(Math.max(0, requestedDelayMs), remainingMs), signal);
20563
+ throwIfAborted(signal);
20564
+ };
20565
+ const requestWithinDeadline = async (requestAttempt) => {
20566
+ throwIfAborted(signal);
20567
+ const remainingMs = maxDurationMs - Math.max(0, now() - startedAt);
20568
+ if (remainingMs <= 0) {
20569
+ throw environmentSetupTimeoutError(maxDurationMs);
20570
+ }
20571
+ const requestController = new AbortController();
20572
+ let timeoutHandle = null;
20573
+ let abortHandler = null;
20574
+ const requestPromise = Promise.resolve().then(
20575
+ () => input.request(requestAttempt, requestController.signal)
20576
+ );
20577
+ const timeoutPromise = new Promise((_, reject) => {
20578
+ if (!Number.isFinite(remainingMs)) return;
20579
+ timeoutHandle = setTimeout(
20580
+ () => {
20581
+ reject(environmentSetupTimeoutError(maxDurationMs));
20582
+ requestController.abort();
20583
+ },
20584
+ Math.max(1, Math.ceil(remainingMs))
20585
+ );
20586
+ });
20587
+ const abortPromise = new Promise((_, reject) => {
20588
+ abortHandler = () => {
20589
+ requestController.abort();
20590
+ reject(environmentSetupAbortError());
20591
+ };
20592
+ signal.addEventListener("abort", abortHandler, { once: true });
20593
+ });
20594
+ try {
20595
+ return await Promise.race([requestPromise, timeoutPromise, abortPromise]);
20596
+ } finally {
20597
+ if (timeoutHandle !== null) {
20598
+ clearTimeout(timeoutHandle);
20599
+ }
20600
+ if (abortHandler !== null) {
20601
+ signal.removeEventListener("abort", abortHandler);
20602
+ }
20603
+ }
20604
+ };
20605
+ while (true) {
20606
+ throwIfAborted(signal);
20607
+ if (now() - startedAt >= maxDurationMs) {
20608
+ throw environmentSetupTimeoutError(maxDurationMs);
20609
+ }
20610
+ attempt += 1;
20611
+ try {
20612
+ const progress = environmentSetupProgressFromResponse(
20613
+ currentEnvironment,
20614
+ await requestWithinDeadline(attempt)
20615
+ );
20616
+ throwIfAborted(signal);
20617
+ currentEnvironment = progress.environment;
20618
+ input.onProgress?.(progress);
20619
+ if (setupHasTerminalLifecycleFailure(progress.setup) && !progress.ready) {
20620
+ throw environmentSetupFailedError(progress.setup);
20621
+ }
20622
+ if (progress.ready) return progress.environment;
20623
+ transientFailures = 0;
20624
+ await waitForNextAttempt(
20625
+ progress.retryAfterMs ?? input.pollIntervalMs ?? 1e3
20626
+ );
20627
+ } catch (error) {
20628
+ throwIfAborted(signal);
20629
+ if (error instanceof EnvironmentSetupTerminalError) {
20630
+ throw error;
20631
+ }
20632
+ const pending = environmentSetupProgressFromError(
20633
+ currentEnvironment,
20634
+ error
20635
+ );
20636
+ if (pending) {
20637
+ currentEnvironment = pending.environment;
20638
+ input.onProgress?.(pending);
20639
+ if (setupHasTerminalLifecycleFailure(pending.setup) && !pending.ready) {
20640
+ throw environmentSetupFailedError(pending.setup);
20641
+ }
20642
+ if (pending.ready) return pending.environment;
20643
+ transientFailures = 0;
20644
+ await waitForNextAttempt(
20645
+ pending.retryAfterMs ?? input.pollIntervalMs ?? 1e3
20646
+ );
20647
+ continue;
20648
+ }
20649
+ if (!isTransientError(error) || transientFailures + 1 >= maxAttempts) {
20650
+ throw error;
20651
+ }
20652
+ transientFailures += 1;
20653
+ input.onRetry?.({ attempt: transientFailures, error });
20654
+ const retryAfterMs = numericRetryAfter(
20655
+ error && typeof error === "object" ? error.retryAfterMs : null
20656
+ );
20657
+ await waitForNextAttempt(
20658
+ retryAfterMs ?? (input.retryDelayMs ?? 1500) * transientFailures
20659
+ );
20660
+ }
20661
+ }
20662
+ }
20663
+
20412
20664
  // src/record-snapshot-projection.ts
20413
20665
  function stableValue(value) {
20414
20666
  if (Array.isArray(value)) return value.map(stableValue);
@@ -23692,6 +23944,6 @@ function calculateOpenAITokenSpend(model, rawUsage) {
23692
23944
  };
23693
23945
  }
23694
23946
 
23695
- export { Environment, EnvironmentSession, GRANULAR_FEED_DIAGNOSTIC_EVENT, Granular, OPENAI_MODEL_PRICING_USD_PER_MILLION, OntologyHandle, Session, SessionFeedController, WSClient, buildContinuationInstruction, buildContinuationInstructionFromTemplate, buildGranularAgentCheckpointBlock, buildGranularAgentDomainBlock, buildGranularAgentFileBlock, buildGranularAgentHeapBlock, buildGranularAgentLoopBlock, buildGranularAgentManualActionBlock, buildGranularAgentManualActionMemorySummary, buildGranularAgentReferentBlock, buildGranularAgentRuntimeImportsBlock, buildGranularAgentSessionBlock, buildGranularAgentSystemPrompt, buildGranularAgentSystemPromptFromTemplate, buildGranularAgentToolBlock, buildGranularAgentWorkflowBlock, buildOpenAISpendEventId, buildSessionTranscript, buildSessionTranscriptFromFeedItems, calculateOpenAITokenSpend, canonicalizeCommitValue, changedRecordSnapshots, consumeGranularReasoningOnlyChunk, consumeGranularReasoningTraceChunk, createFeedPublisher, createHarnessVerifierSnapshot, defineEffect, defineProjection, defineStateMachine, emitFeedDiagnostic, emitFeedDiagnosticToDefaultSink, emptyFeedSnapshot, evaluateContinuation, evaluateValidationRule, extractPromptTokens, getCurrentClosureId, getDefaultHarnessTemplateId, getExclusivePromptTarget, getOpenAIModelPricing, hasCanonicalSessionFeedActivation, hasOpenPrompt, hashHarnessTemplateValue, invokeRegisteredEffect, isCanonicalSessionFeedDocument, isGraphQLMutationDocument, isLocalApiUrl, listHarnessTemplates, mergeFeedItemsBySequence, normalizeEffectBehaviors, normalizeFeedDiagnostic, normalizeFeedDiagnosticKind, normalizeFeedPage, normalizeOpenAIUsage, normalizePrompt, normalizePromptChoiceOption, normalizePromptText, normalizePromptType, orderTransientFeedItems, projectConversationReferentFocus, projectConversationReferentSummary, projectHeapSummary, projectLoopSummary, projectRecordSnapshotMutation, projectSessionFileSummary, projectWorkflowFocus, projectWorkflowSummary, readSessionFeedSnapshot, recordOpenAIUsageSpend, renderContinuationInstructionFromTemplate, renderGranularAgentSystemPromptFromTemplate, resolveApiUrl, resolveAuthTokenForApiUrl, resolveHarnessTemplate, resolveJobPresentation, resolvePromptAnswer, reviewGeneratedJobCode, scorePromptChoiceMatch, stripGranularReasoningTrace, toGranularHttpBase, validateHarnessTemplateManifest, validateProjectionResult, validationRuleFailureMessage };
23947
+ export { Environment, EnvironmentSession, GRANULAR_FEED_DIAGNOSTIC_EVENT, Granular, OPENAI_MODEL_PRICING_USD_PER_MILLION, OntologyHandle, Session, SessionFeedController, WSClient, buildContinuationInstruction, buildContinuationInstructionFromTemplate, buildGranularAgentCheckpointBlock, buildGranularAgentDomainBlock, buildGranularAgentFileBlock, buildGranularAgentHeapBlock, buildGranularAgentLoopBlock, buildGranularAgentManualActionBlock, buildGranularAgentManualActionMemorySummary, buildGranularAgentReferentBlock, buildGranularAgentRuntimeImportsBlock, buildGranularAgentSessionBlock, buildGranularAgentSystemPrompt, buildGranularAgentSystemPromptFromTemplate, buildGranularAgentToolBlock, buildGranularAgentWorkflowBlock, buildOpenAISpendEventId, buildSessionTranscript, buildSessionTranscriptFromFeedItems, calculateOpenAITokenSpend, canonicalizeCommitValue, changedRecordSnapshots, consumeGranularReasoningOnlyChunk, consumeGranularReasoningTraceChunk, createFeedPublisher, createHarnessVerifierSnapshot, defineEffect, defineProjection, defineStateMachine, emitFeedDiagnostic, emitFeedDiagnosticToDefaultSink, emptyFeedSnapshot, environmentSetupProgressFromError, environmentSetupProgressFromResponse, evaluateContinuation, evaluateValidationRule, extractPromptTokens, getCurrentClosureId, getDefaultHarnessTemplateId, getExclusivePromptTarget, getOpenAIModelPricing, hasCanonicalSessionFeedActivation, hasOpenPrompt, hashHarnessTemplateValue, invokeRegisteredEffect, isCanonicalSessionFeedDocument, isGraphQLMutationDocument, isLocalApiUrl, listHarnessTemplates, mergeFeedItemsBySequence, normalizeEffectBehaviors, normalizeFeedDiagnostic, normalizeFeedDiagnosticKind, normalizeFeedPage, normalizeOpenAIUsage, normalizePrompt, normalizePromptChoiceOption, normalizePromptText, normalizePromptType, orderTransientFeedItems, pollEnvironmentSetup, projectConversationReferentFocus, projectConversationReferentSummary, projectHeapSummary, projectLoopSummary, projectRecordSnapshotMutation, projectSessionFileSummary, projectWorkflowFocus, projectWorkflowSummary, readSessionFeedSnapshot, recordOpenAIUsageSpend, renderContinuationInstructionFromTemplate, renderGranularAgentSystemPromptFromTemplate, resolveApiUrl, resolveAuthTokenForApiUrl, resolveHarnessTemplate, resolveJobPresentation, resolvePromptAnswer, reviewGeneratedJobCode, scorePromptChoiceMatch, stripGranularReasoningTrace, toGranularHttpBase, validateHarnessTemplateManifest, validateProjectionResult, validationRuleFailureMessage };
23696
23948
  //# sourceMappingURL=index.mjs.map
23697
23949
  //# sourceMappingURL=index.mjs.map