@oxy.so/contracts 4.7.0 → 4.8.0

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/cjs/index.js CHANGED
@@ -37,7 +37,7 @@ exports.MAX_REALTIME_AUDIO_FRAME_BASE64_LENGTH = exports.inferenceStreamEventSch
37
37
  exports.realtimeTextDeltaEventSchema = exports.realtimeTranscriptDoneEventSchema = exports.realtimeTranscriptDeltaEventSchema = exports.realtimeTranscriptSourceSchema = exports.realtimeOutputAudioDoneEventSchema = exports.realtimeOutputAudioDeltaEventSchema = exports.realtimeResponseCreatedEventSchema = exports.realtimeInputAudioClearedEventSchema = exports.realtimeInputAudioCommittedEventSchema = exports.realtimeSpeechStoppedEventSchema = exports.realtimeSpeechStartedEventSchema = exports.realtimeItemTruncatedEventSchema = exports.realtimeItemDeletedEventSchema = exports.realtimeItemDoneEventSchema = exports.realtimeItemAddedEventSchema = exports.realtimeCommandAcceptedEventSchema = exports.realtimeSessionResumedEventSchema = exports.realtimeSessionUpdatedEventSchema = exports.realtimeSessionCreatedEventSchema = exports.realtimeClientCommandSchema = exports.realtimeSessionCloseCommandSchema = exports.realtimeSessionResumeCommandSchema = exports.realtimeResponseCancelCommandSchema = exports.realtimeResponseCreateCommandSchema = exports.realtimeInputAudioClearCommandSchema = exports.realtimeInputAudioCommitCommandSchema = exports.realtimeInputAudioAppendCommandSchema = exports.realtimeItemTruncateCommandSchema = exports.realtimeItemDeleteCommandSchema = exports.realtimeItemCreateCommandSchema = exports.realtimeSessionUpdateCommandSchema = exports.realtimeResponseParametersSchema = exports.realtimeConversationItemSchema = exports.realtimeContentPartSchema = exports.realtimeSessionRequestSchema = exports.realtimeClientMetadataSchema = exports.realtimeSessionLimitsSchema = exports.realtimeSessionConfigUpdateSchema = exports.realtimeSessionConfigSchema = exports.realtimeTranslationSchema = exports.realtimeInputTranscriptionSchema = exports.realtimeTurnDetectionSchema = exports.realtimeOutputModalitySchema = exports.realtimeAudioFormatSchema = exports.realtimeResponseIdSchema = exports.realtimeItemIdSchema = exports.realtimeCommandIdSchema = exports.MAX_REALTIME_RESUME_WINDOW_MS = exports.MAX_REALTIME_SESSION_AUDIO_BYTES = exports.MAX_REALTIME_SESSION_DURATION_MS = void 0;
38
38
  exports.BILLING_INVOICE_STATUSES = exports.accountBillingStateSchema = exports.billingProfileSchema = exports.autoRechargeSchema = exports.billingProfileStatusSchema = exports.BILLING_PROFILE_STATUSES = exports.billingModeSchema = exports.BILLING_MODES = exports.providerConnectionSchema = exports.providerConnectionStatusSchema = exports.providerConnectionValidationSchema = exports.providerCredentialCustodyStateSchema = exports.providerCredentialValidationDeploymentSchema = exports.providerCredentialValidationOperationSchema = exports.kaanaCredentialValidationOutcomeSchema = exports.kaanaCredentialValidationFailureCodeSchema = exports.kaanaCredentialValidationOutcomeStateSchema = exports.kaanaCredentialValidationTaskSchema = exports.kaanaCredentialOutcomeSchema = exports.kaanaCredentialConflictOutcomeSchema = exports.kaanaCredentialAppliedOutcomeSchema = exports.kaanaCredentialOutcomeRequestSchema = exports.kaanaCredentialRevokeOutcomeRequestSchema = exports.kaanaCredentialRotateOutcomeRequestSchema = exports.kaanaCredentialCreateOutcomeRequestSchema = exports.kaanaCredentialMutationSchema = exports.kaanaCredentialRevokeMutationSchema = exports.kaanaCredentialRotateMutationSchema = exports.kaanaCredentialCreateMutationSchema = exports.kaanaCredentialIdentitySchema = exports.kaanaCredentialOperationActionSchema = exports.kaanaCredentialOperationIdSchema = exports.kaanaCredentialHandleSchema = exports.providerConnectionScopeSchema = exports.usageRefundSchema = exports.usageRefundReasonSchema = exports.usageRefundSubjectSchema = exports.usageReceiptSchema = exports.normalizedUsageReportSchema = exports.inferenceRequestOutcomeSchema = exports.usageReservationSchema = exports.usageReservationStatusSchema = exports.usageReservationRequestSchema = exports.realtimeServerEventSchema = exports.realtimeSessionClosedEventSchema = exports.realtimeSessionCloseReasonSchema = exports.realtimeErrorEventSchema = exports.realtimeResponseDoneEventSchema = exports.realtimeResponseStatusSchema = exports.realtimeToolCallEventSchema = void 0;
39
39
  exports.catalogEventSchema = exports.catalogToolSchema = exports.auditEventSchema = exports.auditResultSchema = exports.policyDecisionSchema = exports.capabilityTicketClaimsSchema = exports.automationDefinitionSchema = exports.automationDataFlowSchema = exports.automationActorSelectionSchema = exports.automationTriggerSchema = exports.delegationGrantSchema = exports.capabilityCoordinatorSchema = exports.executionAuthorizationRefSchema = exports.capabilityCatalogBindingSchema = exports.grantLimitSchema = exports.toolGrantOverrideSchema = exports.resourceRefSchema = exports.actorRefSchema = exports.capabilityPackageSchema = exports.autonomyLevelSchema = exports.CAPABILITY_PACKAGES = exports.AUTONOMY_LEVELS = exports.productEntitlementSchema = exports.costCenterSpendSchema = exports.costCenterSchema = exports.costCenterStatusSchema = exports.COST_CENTER_STATUSES = exports.payAsYouGoEntitlementSchema = exports.productPlanSchema = exports.planAllowanceSchema = exports.LIVE_PRODUCT_PLAN_STATUSES = exports.productPlanStatusSchema = exports.PRODUCT_PLAN_STATUSES = exports.reconciliationReportSchema = exports.reconciliationRunSchema = exports.reconciliationDiscrepancySchema = exports.reconciliationRunStatusSchema = exports.RECONCILIATION_RUN_STATUSES = exports.reconciliationDiscrepancyKindSchema = exports.RECONCILIATION_DISCREPANCY_KINDS = exports.autoRechargeAttemptSchema = exports.autoRechargeStatusSchema = exports.AUTO_RECHARGE_STATUSES = exports.externalPaymentSchema = exports.externalPaymentKindSchema = exports.EXTERNAL_PAYMENT_KINDS = exports.externalPaymentProviderSchema = exports.EXTERNAL_PAYMENT_PROVIDERS = exports.billingInvoiceSchema = exports.billingInvoiceStatusSchema = void 0;
40
- exports.decisionAnswersMatch = exports.decisionFitsGateway = exports.decisionInputBudget = exports.decisionFailureSchema = exports.decisionSuccessSchema = exports.decisionResultSchema = exports.decisionAnswerSchema = exports.decisionRequestSchema = exports.decisionInputSchema = exports.decisionQuestionSchema = exports.decisionEffortSchema = exports.inboxInferenceStreamEventSchema = exports.inboxThreadSummaryResponseSchema = exports.inboxSmartRepliesResponseSchema = exports.inboxNaturalSearchResponseSchema = exports.inboxInferenceTextResponseSchema = exports.inboxMessageInferenceParamsSchema = exports.inboxNaturalSearchRequestSchema = exports.inboxDailyBriefRequestSchema = exports.inboxComposeRequestSchema = exports.emailAgentContextSchema = exports.emailContextMessageSchema = exports.emailContextMailboxSchema = exports.emailContextAddressSchema = exports.resolveCatalogInvocation = exports.matchCatalogInvocation = exports.findOverlappingCatalogInvocations = exports.catalogInvocationTemplatesEquivalent = exports.catalogInvocationsOverlap = exports.catalogInvocationPathParameters = exports.normalizedAppEventSchema = exports.catalogRegistrationSchema = exports.appCapabilityCatalogSchema = void 0;
40
+ exports.scopedInferenceRequestSchema = exports.canonicalScopedExecutionJson = exports.scopedExecutionSchema = exports.scopedExecutionAudienceSchema = exports.SCOPED_REQUEST_ENVELOPE_VERSION = exports.SCOPED_EXECUTION_CONTRACT_VERSION = exports.decisionAnswersMatch = exports.decisionFitsGateway = exports.decisionInputBudget = exports.decisionFailureSchema = exports.decisionSuccessSchema = exports.decisionResultSchema = exports.decisionAnswerSchema = exports.decisionRequestSchema = exports.decisionInputSchema = exports.decisionQuestionSchema = exports.decisionEffortSchema = exports.inboxInferenceStreamEventSchema = exports.inboxThreadSummaryResponseSchema = exports.inboxSmartRepliesResponseSchema = exports.inboxNaturalSearchResponseSchema = exports.inboxInferenceTextResponseSchema = exports.inboxMessageInferenceParamsSchema = exports.inboxNaturalSearchRequestSchema = exports.inboxDailyBriefRequestSchema = exports.inboxComposeRequestSchema = exports.emailAgentContextSchema = exports.emailContextMessageSchema = exports.emailContextMailboxSchema = exports.emailContextAddressSchema = exports.resolveCatalogInvocation = exports.matchCatalogInvocation = exports.findOverlappingCatalogInvocations = exports.catalogInvocationTemplatesEquivalent = exports.catalogInvocationsOverlap = exports.catalogInvocationPathParameters = exports.normalizedAppEventSchema = exports.catalogRegistrationSchema = exports.appCapabilityCatalogSchema = void 0;
41
41
  var accountGraph_1 = require("./accountGraph");
42
42
  Object.defineProperty(exports, "ACCOUNT_KINDS", { enumerable: true, get: function () { return accountGraph_1.ACCOUNT_KINDS; } });
43
43
  Object.defineProperty(exports, "accountKindSchema", { enumerable: true, get: function () { return accountGraph_1.accountKindSchema; } });
@@ -793,3 +793,11 @@ Object.defineProperty(exports, "decisionFailureSchema", { enumerable: true, get:
793
793
  Object.defineProperty(exports, "decisionInputBudget", { enumerable: true, get: function () { return decisions_1.decisionInputBudget; } });
794
794
  Object.defineProperty(exports, "decisionFitsGateway", { enumerable: true, get: function () { return decisions_1.decisionFitsGateway; } });
795
795
  Object.defineProperty(exports, "decisionAnswersMatch", { enumerable: true, get: function () { return decisions_1.decisionAnswersMatch; } });
796
+ var scopedExecution_1 = require("./inference/scopedExecution");
797
+ Object.defineProperty(exports, "SCOPED_EXECUTION_CONTRACT_VERSION", { enumerable: true, get: function () { return scopedExecution_1.SCOPED_EXECUTION_CONTRACT_VERSION; } });
798
+ Object.defineProperty(exports, "SCOPED_REQUEST_ENVELOPE_VERSION", { enumerable: true, get: function () { return scopedExecution_1.SCOPED_REQUEST_ENVELOPE_VERSION; } });
799
+ Object.defineProperty(exports, "scopedExecutionAudienceSchema", { enumerable: true, get: function () { return scopedExecution_1.scopedExecutionAudienceSchema; } });
800
+ Object.defineProperty(exports, "scopedExecutionSchema", { enumerable: true, get: function () { return scopedExecution_1.scopedExecutionSchema; } });
801
+ Object.defineProperty(exports, "canonicalScopedExecutionJson", { enumerable: true, get: function () { return scopedExecution_1.canonicalScopedExecutionJson; } });
802
+ var request_2 = require("./inference/request");
803
+ Object.defineProperty(exports, "scopedInferenceRequestSchema", { enumerable: true, get: function () { return request_2.scopedInferenceRequestSchema; } });
@@ -1,4 +1,7 @@
1
1
  "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.modelCatalogueEntrySchema = exports.catalogueServingProviderSummarySchema = exports.cataloguePublisherSummarySchema = exports.routingProfileSchema = exports.routingProfileCandidateSchema = exports.modelDeploymentSchema = exports.inferenceProviderSchema = exports.modelRevisionSchema = exports.catalogueModelSchema = exports.modelPublisherSchema = exports.modelSafetyMetadataSchema = exports.modelEvaluationResultSchema = exports.modelDeprecationSchema = exports.commercialPermissionSchema = exports.availabilityScopeSchema = exports.inferenceDataPolicySchema = exports.modelProvenanceSchema = exports.modelLicenseSchema = exports.modelCapabilitiesSchema = exports.modelRealtimeCapabilitiesSchema = exports.realtimeSessionTransportSchema = exports.realtimeSessionKindSchema = exports.inferenceApiFormatSchema = exports.modelPowerClassSchema = exports.powerLevelSchema = exports.reasoningEffortSchema = exports.inferenceModalitySchema = void 0;
4
+ const scopedExecution_1 = require("./scopedExecution");
2
5
  /**
3
6
  * The canonical model catalogue.
4
7
  *
@@ -27,8 +30,6 @@
27
30
  *
28
31
  * Decided in: docs/adr/0008-catalogue-concept-separation.md.
29
32
  */
30
- Object.defineProperty(exports, "__esModule", { value: true });
31
- exports.modelCatalogueEntrySchema = exports.catalogueServingProviderSummarySchema = exports.cataloguePublisherSummarySchema = exports.routingProfileSchema = exports.routingProfileCandidateSchema = exports.modelDeploymentSchema = exports.inferenceProviderSchema = exports.modelRevisionSchema = exports.catalogueModelSchema = exports.modelPublisherSchema = exports.modelSafetyMetadataSchema = exports.modelEvaluationResultSchema = exports.modelDeprecationSchema = exports.commercialPermissionSchema = exports.availabilityScopeSchema = exports.inferenceDataPolicySchema = exports.modelProvenanceSchema = exports.modelLicenseSchema = exports.modelCapabilitiesSchema = exports.modelRealtimeCapabilitiesSchema = exports.realtimeSessionTransportSchema = exports.realtimeSessionKindSchema = exports.inferenceApiFormatSchema = exports.modelPowerClassSchema = exports.powerLevelSchema = exports.reasoningEffortSchema = exports.inferenceModalitySchema = void 0;
32
33
  const zod_1 = require("zod");
33
34
  const identifiers_1 = require("./identifiers");
34
35
  const priceVersion_1 = require("./priceVersion");
@@ -491,6 +492,8 @@ exports.modelDeploymentSchema = zod_1.z
491
492
  /** See `version.ts`: exchanged with the data plane on its own. */
492
493
  schemaVersion: zod_1.z.literal(2),
493
494
  deploymentId: identifiers_1.deploymentIdSchema,
495
+ /** Restrictive audience; never an eligibility approval. */
496
+ scopedExecution: scopedExecution_1.scopedExecutionAudienceSchema.optional(),
494
497
  provider: identifiers_1.inferenceProviderSlugSchema,
495
498
  /** Always revision-pinned: a deployment serves specific weights. */
496
499
  modelReference: identifiers_1.modelReferenceSchema,
@@ -25,9 +25,10 @@
25
25
  * docs/adr/0017-authorized-routes-in-the-envelope.md.
26
26
  */
27
27
  Object.defineProperty(exports, "__esModule", { value: true });
28
- exports.inferenceRequestSchema = exports.inferenceAudioOutputParametersSchema = exports.inferenceSpeechParametersSchema = exports.clientRequestMetadataSchema = exports.inferenceReasoningSchema = exports.responseFormatSchema = exports.toolChoiceSchema = exports.toolDefinitionSchema = exports.samplingParametersSchema = exports.inferenceInputSchema = exports.inferenceMessageSchema = exports.inferenceMessageRoleSchema = exports.inferenceToolCallSchema = exports.inferenceContentPartSchema = exports.inferenceContentSourceSchema = void 0;
28
+ exports.scopedInferenceRequestSchema = exports.inferenceRequestSchema = exports.inferenceAudioOutputParametersSchema = exports.inferenceSpeechParametersSchema = exports.clientRequestMetadataSchema = exports.inferenceReasoningSchema = exports.responseFormatSchema = exports.toolChoiceSchema = exports.toolDefinitionSchema = exports.samplingParametersSchema = exports.inferenceInputSchema = exports.inferenceMessageSchema = exports.inferenceMessageRoleSchema = exports.inferenceToolCallSchema = exports.inferenceContentPartSchema = exports.inferenceContentSourceSchema = void 0;
29
29
  const decisions_1 = require("./decisions");
30
30
  const zod_1 = require("zod");
31
+ const scopedExecution_1 = require("./scopedExecution");
31
32
  const attribution_1 = require("./attribution");
32
33
  const catalogue_1 = require("./catalogue");
33
34
  const identifiers_1 = require("./identifiers");
@@ -354,6 +355,8 @@ exports.inferenceRequestSchema = zod_1.z
354
355
  .object({
355
356
  /** See `version.ts`: this is the Oxy→data-plane request envelope. */
356
357
  schemaVersion: zod_1.z.literal(2),
358
+ /** Recognized so v2 refuses rather than silently stripping a restriction. */
359
+ scopedExecution: scopedExecution_1.scopedExecutionSchema.optional(),
357
360
  attribution: attribution_1.inferenceAttributionSchema,
358
361
  target: routingPolicy_1.routingTargetSchema,
359
362
  modality: catalogue_1.inferenceModalitySchema,
@@ -408,6 +411,8 @@ exports.inferenceRequestSchema = zod_1.z
408
411
  authorizedRoutes: zod_1.z.array(routingPolicy_1.authorizedRouteSchema).min(1).optional(),
409
412
  })
410
413
  .superRefine((request, ctx) => {
414
+ if (request.scopedExecution !== undefined)
415
+ ctx.addIssue({ code: zod_1.z.ZodIssueCode.custom, path: ["scopedExecution"], message: "Scoped execution requires envelope v3." });
411
416
  if (request.input.format === "decisions" || request.client.apiFormat === "decisions") {
412
417
  const exactModel = request.target.kind === "model" && request.target.modelReference.includes('@');
413
418
  const foreignRoute = request.authorizedRoutes?.some((route) => request.target.kind !== "model" || route.modelReference !== request.target.modelReference || route.substitution !== "same_model");
@@ -537,3 +542,30 @@ exports.inferenceRequestSchema = zod_1.z
537
542
  });
538
543
  }
539
544
  });
545
+ /** Explicit restrictive generation: old v2 receivers reject this version whole. */
546
+ exports.scopedInferenceRequestSchema = exports.inferenceRequestSchema.innerType()
547
+ .extend({ schemaVersion: zod_1.z.literal(scopedExecution_1.SCOPED_REQUEST_ENVELOPE_VERSION), scopedExecution: scopedExecution_1.scopedExecutionSchema })
548
+ .superRefine((request, ctx) => {
549
+ const { scopedExecution: scope, ...base } = request;
550
+ const legacy = exports.inferenceRequestSchema.safeParse({ ...base, schemaVersion: 2 });
551
+ if (!legacy.success)
552
+ for (const issue of legacy.error.issues)
553
+ ctx.addIssue(issue);
554
+ const principal = request.attribution.principal;
555
+ const route = request.authorizedRoutes?.[0];
556
+ if (request.input.format !== "decisions" || request.client.apiFormat !== "decisions" ||
557
+ scope.requestId !== request.attribution.requestId ||
558
+ scope.idempotencyKey !== request.idempotencyKey ||
559
+ scope.principal.accountId !== principal.billing.accountId ||
560
+ scope.principal.applicationId !== principal.applicationId ||
561
+ scope.principal.credentialId !== principal.credentialId ||
562
+ scope.principal.environment !== principal.environment ||
563
+ scope.policy.routingPolicyId !== request.routingPolicy.routingPolicyId ||
564
+ scope.policy.policyVersion !== request.routingPolicy.policyVersion ||
565
+ request.authorizedRoutes?.length !== 1 || route?.customerProviderCredential !== undefined ||
566
+ route?.deploymentId !== scope.deploymentId || route?.provider !== scope.provider ||
567
+ route?.modelReference !== scope.modelReference ||
568
+ request.target.kind !== "model" || request.target.modelReference !== scope.modelReference) {
569
+ ctx.addIssue({ code: zod_1.z.ZodIssueCode.custom, path: ["scopedExecution"], message: "Scoped execution must restrict the exact attributed decisions request and one platform route." });
570
+ }
571
+ });
@@ -0,0 +1,87 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.scopedExecutionSchema = exports.scopedExecutionAudienceSchema = exports.SCOPED_REQUEST_ENVELOPE_VERSION = exports.SCOPED_EXECUTION_CONTRACT_VERSION = void 0;
4
+ exports.canonicalScopedExecutionJson = canonicalScopedExecutionJson;
5
+ const zod_1 = require("zod");
6
+ const identifiers_1 = require("./identifiers");
7
+ const money_1 = require("./money");
8
+ /** Explicit extension negotiation; never replaces the legacy 3.5 handshake. */
9
+ exports.SCOPED_EXECUTION_CONTRACT_VERSION = "3.6.0";
10
+ /** Scoped only; normal envelope v2 and metadata 3.5 remain unchanged. */
11
+ exports.SCOPED_REQUEST_ENVELOPE_VERSION = 3;
12
+ const identity = zod_1.z.string().min(1).max(256);
13
+ const sha256 = zod_1.z.string().regex(/^[0-9a-f]{64}$/);
14
+ const maxCost = money_1.exactDecimalSchema.refine((value) => {
15
+ if (!money_1.exactDecimalSchema.safeParse(value).success)
16
+ return false;
17
+ const [whole, fraction = ""] = value.split(".");
18
+ const units = BigInt(whole) * 1000000000000n + BigInt(fraction.padEnd(12, "0"));
19
+ return units > 0n && units <= 10000000000n;
20
+ }, "scoped cost must be positive and at most 0.01 USD");
21
+ /** Restriction only: none of these identities grants catalogue eligibility. */
22
+ exports.scopedExecutionAudienceSchema = zod_1.z
23
+ .object({
24
+ permitId: identity,
25
+ idempotencyKey: identifiers_1.idempotencyKeySchema,
26
+ fixtureSha256: sha256,
27
+ expiresAt: zod_1.z.string().datetime(),
28
+ principal: zod_1.z
29
+ .object({
30
+ accountId: identity,
31
+ applicationId: identity,
32
+ credentialId: identity,
33
+ environment: identifiers_1.inferenceEnvironmentSchema,
34
+ })
35
+ .strict(),
36
+ policy: zod_1.z
37
+ .object({
38
+ routingPolicyId: zod_1.z.string().min(1).max(128),
39
+ policyVersion: zod_1.z.number().int().positive().safe(),
40
+ })
41
+ .strict(),
42
+ deploymentId: identifiers_1.deploymentIdSchema,
43
+ provider: identifiers_1.inferenceProviderSlugSchema,
44
+ keyId: identity,
45
+ modelReference: identifiers_1.modelReferenceSchema.refine((value) => value.includes("@"), "must pin a revision"),
46
+ upstreamModelId: identity,
47
+ priceVersionId: identity,
48
+ providerRateCardVersionId: identity,
49
+ providerSourceVersion: identity,
50
+ maxCostUsd: maxCost,
51
+ })
52
+ .strict();
53
+ exports.scopedExecutionSchema = exports.scopedExecutionAudienceSchema
54
+ .extend({
55
+ requestId: identifiers_1.requestIdSchema,
56
+ snapshotId: identity,
57
+ catalogueEvidenceHash: sha256,
58
+ })
59
+ .strict();
60
+ /**
61
+ * Canonical JSON wire bytes: recursive UTF-16 key order, JSON string/number
62
+ * encoding, arrays in order, no whitespace. Hash the whole signed input, not a
63
+ * reparsed/defaulted decision. Reject non-JSON values rather than dropping them.
64
+ */
65
+ function canonicalScopedExecutionJson(value) {
66
+ if (value === null || typeof value === "string" || typeof value === "boolean")
67
+ return JSON.stringify(value);
68
+ if (typeof value === "number" && Number.isFinite(value))
69
+ return JSON.stringify(value);
70
+ if (Array.isArray(value)) {
71
+ const entries = Array.from(value, (entry, index) => {
72
+ if (!(index in value))
73
+ throw new Error("Scoped execution requires dense JSON arrays.");
74
+ return canonicalScopedExecutionJson(entry);
75
+ });
76
+ return `[${entries.join(",")}]`;
77
+ }
78
+ if (typeof value === "object" &&
79
+ value !== null &&
80
+ Object.getPrototypeOf(value) === Object.prototype) {
81
+ const entries = Object.keys(value)
82
+ .sort()
83
+ .map((key) => `${JSON.stringify(key)}:${canonicalScopedExecutionJson(value[key])}`);
84
+ return `{${entries.join(",")}}`;
85
+ }
86
+ throw new Error("Scoped execution requires JSON wire values.");
87
+ }