@granular-software/sdk 0.4.72 → 0.4.74

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.
@@ -1,5 +1,5 @@
1
- import { a as EnvironmentSession, G as Granular } from './client-p5EhOwpP.mjs';
2
- import { aI as GranularSpendContext, aD as OpenAITokenSpend, n as Prompt, h as RecordObjectOptions, i as ManifestContent, m as SessionHeapSnapshot, T as ToolWithHandler, b2 as ConnectOptions, bs as CreateEnvironmentData, aX as GranularOptions } from './spend-lJDtuAr6.mjs';
1
+ import { a as EnvironmentSession, G as Granular } from './client-6d1OsWJf.mjs';
2
+ import { aI as GranularSpendContext, aD as OpenAITokenSpend, n as Prompt, h as RecordObjectOptions, i as ManifestContent, m as SessionHeapSnapshot, T as ToolWithHandler, b2 as ConnectOptions, bs as CreateEnvironmentData, aX as GranularOptions } from './spend-DBRQOSaj.mjs';
3
3
  import { GranularAgentToolInfo, GeneratedJobCodeIssue, BuildGranularAgentSystemPromptInput, HarnessRenderedPrompt, HarnessRenderedContinuation, HarnessControllerBudgets } from './agent-harness.mjs';
4
4
  import '@automerge/automerge';
5
5
  import '@automerge/automerge/slim';
@@ -1,5 +1,5 @@
1
- import { a as EnvironmentSession, G as Granular } from './client-JCISbded.js';
2
- import { aI as GranularSpendContext, aD as OpenAITokenSpend, n as Prompt, h as RecordObjectOptions, i as ManifestContent, m as SessionHeapSnapshot, T as ToolWithHandler, b2 as ConnectOptions, bs as CreateEnvironmentData, aX as GranularOptions } from './spend-lJDtuAr6.js';
1
+ import { a as EnvironmentSession, G as Granular } from './client-DdEXINlv.js';
2
+ import { aI as GranularSpendContext, aD as OpenAITokenSpend, n as Prompt, h as RecordObjectOptions, i as ManifestContent, m as SessionHeapSnapshot, T as ToolWithHandler, b2 as ConnectOptions, bs as CreateEnvironmentData, aX as GranularOptions } from './spend-DBRQOSaj.js';
3
3
  import { GranularAgentToolInfo, GeneratedJobCodeIssue, BuildGranularAgentSystemPromptInput, HarnessRenderedPrompt, HarnessRenderedContinuation, HarnessControllerBudgets } from './agent-harness.js';
4
4
  import '@automerge/automerge';
5
5
  import '@automerge/automerge/slim';
@@ -13172,6 +13172,31 @@ var effectBehaviorsMetamodelPackage = defineMetamodelPackage({
13172
13172
  }
13173
13173
  }
13174
13174
  });
13175
+ function assertRecordSnapshotTransitionMapping(transition) {
13176
+ if (!transition)
13177
+ throw new Error("A transition commit has no authored transition context.");
13178
+ if (!transition.outcomes || !Object.keys(transition.outcomes).length) {
13179
+ throw new Error(
13180
+ "Automatic product-state mapping requires at least one declared outcome."
13181
+ );
13182
+ }
13183
+ const destinations = /* @__PURE__ */ new Map();
13184
+ for (const [key, outcome] of Object.entries(transition.outcomes)) {
13185
+ if (!outcome || typeof outcome.to !== "string" || !outcome.to) {
13186
+ throw new Error(
13187
+ `Automatic product-state mapping requires a destination for outcome ${key}.`
13188
+ );
13189
+ }
13190
+ const destination = outcome.to === "$current" ? transition.from : outcome.to;
13191
+ const previous = destinations.get(destination);
13192
+ if (previous !== void 0) {
13193
+ throw new Error(
13194
+ `Ambiguous product-state mapping for ${transition.machine}.${transition.transition}: outcomes ${previous} and ${key} both resolve to ${destination}; automatic mapping requires distinct outcome destinations.`
13195
+ );
13196
+ }
13197
+ destinations.set(destination, key);
13198
+ }
13199
+ }
13175
13200
 
13176
13201
  // src/commit.ts
13177
13202
  var MAX_PROJECTION_CHANGES = 1e3;
@@ -13730,6 +13755,11 @@ async function invokeRegisteredEffect(effectMap, request, options = {}) {
13730
13755
  `Transition effect ${request.effectKey} has no resolved transition context; customer code was not invoked`
13731
13756
  );
13732
13757
  }
13758
+ if (commitRequired && declaration?.kind === "transition" && declaration.outcomeSelection === "product_state") {
13759
+ assertRecordSnapshotTransitionMapping(
13760
+ request.context?.invocation?.transition
13761
+ );
13762
+ }
13733
13763
  const idempotencyKey = commitRequired ? await resolveInvocationIdempotencyKey(request) : request.context?.idempotencyKey;
13734
13764
  let commitStarted = false;
13735
13765
  let commitPromise = null;
@@ -15108,7 +15138,7 @@ function buildMachineTypes(classSummary, machine) {
15108
15138
  ];
15109
15139
  }
15110
15140
  function buildMachineMethods(classSummary, machine) {
15111
- const stateName = stateTypeName(classSummary.name, machine.name);
15141
+ const stateName2 = stateTypeName(classSummary.name, machine.name);
15112
15142
  const transitionName = transitionTypeName(classSummary.name, machine.name);
15113
15143
  pathTypeName(classSummary.name, machine.name);
15114
15144
  const docsPrefix = `${classSummary.name}.${machine.name}`;
@@ -15118,12 +15148,12 @@ function buildMachineMethods(classSummary, machine) {
15118
15148
  docs: [`Get the current ${docsPrefix} state.`],
15119
15149
  static: false,
15120
15150
  params: [],
15121
- returnType: `Promise<${stateName} | null>`,
15151
+ returnType: `Promise<${stateName2} | null>`,
15122
15152
  runtime: {
15123
15153
  kind: "state_machine",
15124
15154
  machineName: machine.name,
15125
15155
  className: classSummary.name,
15126
- stateTypeName: stateName,
15156
+ stateTypeName: stateName2,
15127
15157
  transitionTypeName: transitionName,
15128
15158
  operation: "get_current"
15129
15159
  }
@@ -15134,13 +15164,13 @@ function buildMachineMethods(classSummary, machine) {
15134
15164
  `Reach a ${docsPrefix} state through the shortest allowed transition path.`
15135
15165
  ],
15136
15166
  static: false,
15137
- params: [{ name: "target", type: stateName }],
15167
+ params: [{ name: "target", type: stateName2 }],
15138
15168
  returnType: `Promise<${toPascalCase2(classSummary.name)}>`,
15139
15169
  runtime: {
15140
15170
  kind: "state_machine",
15141
15171
  machineName: machine.name,
15142
15172
  className: classSummary.name,
15143
- stateTypeName: stateName,
15173
+ stateTypeName: stateName2,
15144
15174
  transitionTypeName: transitionName,
15145
15175
  operation: "reach"
15146
15176
  }
@@ -15155,7 +15185,7 @@ function buildMachineMethods(classSummary, machine) {
15155
15185
  kind: "state_machine",
15156
15186
  machineName: machine.name,
15157
15187
  className: classSummary.name,
15158
- stateTypeName: stateName,
15188
+ stateTypeName: stateName2,
15159
15189
  transitionTypeName: transitionName,
15160
15190
  operation: "list_transitions"
15161
15191
  }
@@ -15165,12 +15195,12 @@ function buildMachineMethods(classSummary, machine) {
15165
15195
  docs: [`List reachable states for ${docsPrefix} from the current state.`],
15166
15196
  static: false,
15167
15197
  params: [],
15168
- returnType: `Promise<${stateName}[]>`,
15198
+ returnType: `Promise<${stateName2}[]>`,
15169
15199
  runtime: {
15170
15200
  kind: "state_machine",
15171
15201
  machineName: machine.name,
15172
15202
  className: classSummary.name,
15173
- stateTypeName: stateName,
15203
+ stateTypeName: stateName2,
15174
15204
  transitionTypeName: transitionName,
15175
15205
  operation: "list_reachable_states"
15176
15206
  }
@@ -15185,7 +15215,7 @@ function buildMachineMethods(classSummary, machine) {
15185
15215
  kind: "state_machine",
15186
15216
  machineName: machine.name,
15187
15217
  className: classSummary.name,
15188
- stateTypeName: stateName,
15218
+ stateTypeName: stateName2,
15189
15219
  transitionTypeName: transitionName,
15190
15220
  operation: "is_final"
15191
15221
  }
@@ -15196,13 +15226,13 @@ function buildMachineMethods(classSummary, machine) {
15196
15226
  `List shortest transition paths from the current ${docsPrefix} state to a target state.`
15197
15227
  ],
15198
15228
  static: false,
15199
- params: [{ name: "target", type: stateName }],
15200
- returnType: `Promise<Array<{ states: ${stateName}[]; transitions: ${transitionName}[] }>>`,
15229
+ params: [{ name: "target", type: stateName2 }],
15230
+ returnType: `Promise<Array<{ states: ${stateName2}[]; transitions: ${transitionName}[] }>>`,
15201
15231
  runtime: {
15202
15232
  kind: "state_machine",
15203
15233
  machineName: machine.name,
15204
15234
  className: classSummary.name,
15205
- stateTypeName: stateName,
15235
+ stateTypeName: stateName2,
15206
15236
  transitionTypeName: transitionName,
15207
15237
  operation: "paths_to"
15208
15238
  }
@@ -15226,7 +15256,7 @@ function buildMachineMethods(classSummary, machine) {
15226
15256
  kind: "state_machine",
15227
15257
  machineName: machine.name,
15228
15258
  className: classSummary.name,
15229
- stateTypeName: stateName,
15259
+ stateTypeName: stateName2,
15230
15260
  transitionTypeName: transitionName,
15231
15261
  operation: "reach",
15232
15262
  targetState: stateNameValue,
@@ -15245,7 +15275,7 @@ function buildMachineMethods(classSummary, machine) {
15245
15275
  kind: "state_machine",
15246
15276
  machineName: machine.name,
15247
15277
  className: classSummary.name,
15248
- stateTypeName: stateName,
15278
+ stateTypeName: stateName2,
15249
15279
  transitionTypeName: transitionName,
15250
15280
  operation: "prepare_reach",
15251
15281
  targetState: stateNameValue,
@@ -15258,7 +15288,7 @@ function buildMachineMethods(classSummary, machine) {
15258
15288
  kind: "state_machine",
15259
15289
  machineName: machine.name,
15260
15290
  className: classSummary.name,
15261
- stateTypeName: stateName,
15291
+ stateTypeName: stateName2,
15262
15292
  transitionTypeName: transitionName,
15263
15293
  operation: "prepare_create_reach",
15264
15294
  targetState: stateNameValue,
@@ -16426,13 +16456,15 @@ var Environment = class _Environment {
16426
16456
  _apiEndpoint;
16427
16457
  _tokenProvider;
16428
16458
  _beforeMutationSend;
16429
- constructor(granular, envData, apiKey, apiEndpoint, tokenProvider, beforeMutationSend) {
16459
+ _graphqlIdempotencyKey;
16460
+ constructor(granular, envData, apiKey, apiEndpoint, tokenProvider, beforeMutationSend, graphqlIdempotencyKey) {
16430
16461
  this.granular = granular;
16431
16462
  this.envData = envData;
16432
16463
  this._apiKey = apiKey;
16433
16464
  this._apiEndpoint = apiEndpoint;
16434
16465
  this._tokenProvider = tokenProvider;
16435
16466
  this._beforeMutationSend = beforeMutationSend;
16467
+ this._graphqlIdempotencyKey = graphqlIdempotencyKey;
16436
16468
  }
16437
16469
  /** The environment ID */
16438
16470
  get environmentId() {
@@ -16714,8 +16746,8 @@ var Environment = class _Environment {
16714
16746
  * `await env.recordState({ className: "spend_request", id, machine: "lifecycle", state: "policy_review", source: "customer_backend" })`
16715
16747
  */
16716
16748
  state(target) {
16717
- const observe = async (machineName, stateName, input = {}) => {
16718
- const observedState = input.observedState || input.state || stateName;
16749
+ const observe = async (machineName, stateName2, input = {}) => {
16750
+ const observedState = input.observedState || input.state || stateName2;
16719
16751
  if (!observedState) {
16720
16752
  throw new Error("State observation requires a target state");
16721
16753
  }
@@ -16741,7 +16773,7 @@ var Environment = class _Environment {
16741
16773
  {
16742
16774
  get: (_machineTarget, stateProperty) => {
16743
16775
  if (stateProperty === "to") {
16744
- return (stateName, input) => observe(machineProperty, stateName, input || {});
16776
+ return (stateName2, input) => observe(machineProperty, stateName2, input || {});
16745
16777
  }
16746
16778
  if (typeof stateProperty !== "string") return void 0;
16747
16779
  return (input) => observe(
@@ -16975,11 +17007,13 @@ var Environment = class _Environment {
16975
17007
  if (this._beforeMutationSend && isGraphQLMutationDocument(query)) {
16976
17008
  this._beforeMutationSend?.();
16977
17009
  }
17010
+ const idempotencyKey = this._graphqlIdempotencyKey?.(query, variables);
16978
17011
  const response = await fetch(this._apiEndpoint, {
16979
17012
  method: "POST",
16980
17013
  headers: {
16981
17014
  "Content-Type": "application/json",
16982
- Authorization: `Bearer ${authToken}`
17015
+ Authorization: `Bearer ${authToken}`,
17016
+ ...idempotencyKey ? { "Idempotency-Key": idempotencyKey } : {}
16983
17017
  },
16984
17018
  body: JSON.stringify({
16985
17019
  environmentId: this.environmentId,
@@ -17034,6 +17068,11 @@ var Environment = class _Environment {
17034
17068
  classNames: options.classNames?.length ? options.classNames : []
17035
17069
  }
17036
17070
  );
17071
+ if (response.errors?.length) {
17072
+ throw new Error(
17073
+ `Record search failed: ${response.errors.map((error) => error.message).join("; ")}`
17074
+ );
17075
+ }
17037
17076
  const seen = /* @__PURE__ */ new Set();
17038
17077
  const results = (response.data?.record_search || []).flatMap((entry) => {
17039
17078
  const className = entry.className?.trim();
@@ -18548,6 +18587,7 @@ var Granular = class _Granular {
18548
18587
  onUnexpectedClose;
18549
18588
  onReconnectError;
18550
18589
  effectHostUrl;
18590
+ graphqlIdempotencyKey;
18551
18591
  debugHttp = process.env.GRANULAR_DEBUG_HTTP === "1";
18552
18592
  /** Sandbox-level effect registry: sandboxId → (effectKey@selector → ToolWithHandler) */
18553
18593
  sandboxEffects = /* @__PURE__ */ new Map();
@@ -18577,6 +18617,7 @@ var Granular = class _Granular {
18577
18617
  this.onUnexpectedClose = options.onUnexpectedClose;
18578
18618
  this.onReconnectError = options.onReconnectError;
18579
18619
  this.effectHostUrl = options.effectHostUrl;
18620
+ this.graphqlIdempotencyKey = options.graphqlIdempotencyKey;
18580
18621
  this.httpUrl = this.apiUrl.replace(/^wss:\/\//, "https://").replace(/^ws:\/\//, "http://").replace(/\/ws$/, "");
18581
18622
  }
18582
18623
  /**
@@ -19592,7 +19633,9 @@ var Granular = class _Granular {
19592
19633
  envData,
19593
19634
  this.apiKey,
19594
19635
  graphqlEndpoint,
19595
- this.tokenProvider
19636
+ this.tokenProvider,
19637
+ void 0,
19638
+ this.graphqlIdempotencyKey
19596
19639
  );
19597
19640
  }
19598
19641
  async bindWebSocketEnvironmentSession(environment, clientId, session, transportOptions = {}) {