@granular-software/sdk 0.4.56 → 0.4.58

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/cli/index.js CHANGED
@@ -7917,12 +7917,12 @@ var ApiClient = class {
7917
7917
  targetVersionId: tag2.targetVersionId ?? tag2.targetBuildId ?? null
7918
7918
  }));
7919
7919
  }
7920
- async moveTag(tagId, targetBuildId) {
7920
+ async moveTag(tagId, targetBuildId, expectedProdBuildId) {
7921
7921
  const moved = await this.request(
7922
7922
  `/control/tags/${tagId}/move`,
7923
7923
  {
7924
7924
  method: "POST",
7925
- body: JSON.stringify({ targetBuildId })
7925
+ body: JSON.stringify({ targetBuildId, expectedProdBuildId })
7926
7926
  }
7927
7927
  );
7928
7928
  return {
@@ -7930,22 +7930,24 @@ var ApiClient = class {
7930
7930
  targetVersionId: moved.targetVersionId ?? moved.targetBuildId ?? null
7931
7931
  };
7932
7932
  }
7933
- async moveVersionTag(tagId, targetVersionId) {
7934
- return this.moveTag(tagId, targetVersionId);
7933
+ async moveVersionTag(tagId, targetVersionId, expectedProdBuildId) {
7934
+ return this.moveTag(tagId, targetVersionId, expectedProdBuildId);
7935
7935
  }
7936
- async promoteToProd(buildId) {
7936
+ async promoteToProd(buildId, expectedProdBuildId) {
7937
7937
  return this.request(
7938
7938
  `/control/builds/${buildId}/promote`,
7939
7939
  {
7940
- method: "POST"
7940
+ method: "POST",
7941
+ body: JSON.stringify({ expectedProdBuildId })
7941
7942
  }
7942
7943
  );
7943
7944
  }
7944
- async promoteVersionToProd(versionId) {
7945
+ async promoteVersionToProd(versionId, expectedProdBuildId) {
7945
7946
  return this.request(
7946
7947
  `/control/versions/${versionId}/promote`,
7947
7948
  {
7948
- method: "POST"
7949
+ method: "POST",
7950
+ body: JSON.stringify({ expectedProdBuildId })
7949
7951
  }
7950
7952
  );
7951
7953
  }
@@ -18993,7 +18995,10 @@ async function deployCommand(options = {}) {
18993
18995
  }
18994
18996
  if (options.prod) {
18995
18997
  const promoting = spinner("Promoting prod...");
18996
- await api.promoteVersionToProd(completed.buildId);
18998
+ await api.promoteVersionToProd(
18999
+ completed.buildId,
19000
+ prodTag?.targetVersionId || prodTag?.targetBuildId || null
19001
+ );
18997
19002
  promoting.succeed(
18998
19003
  ` Prod now points to ${brand.secondary(completed.buildId)}`
18999
19004
  );
@@ -25530,24 +25535,72 @@ var Granular = class _Granular {
25530
25535
  if (!tagName) {
25531
25536
  throw new Error(`${methodName}() requires \`tag\`.`);
25532
25537
  }
25533
- const user = await this.resolveConnectUser(options);
25534
- if (!Array.isArray(user.permissions) || user.permissions.length === 0) {
25538
+ const assignmentMode = options.assignmentMode ?? "ensure";
25539
+ if (assignmentMode !== "ensure" && assignmentMode !== "require-existing") {
25535
25540
  throw new Error(
25536
- `${methodName}() requires at least one permission so the SDK can ensure assignments for new users.`
25541
+ `${methodName}() received an unsupported assignmentMode: ${String(options.assignmentMode)}.`
25537
25542
  );
25538
25543
  }
25539
- const sandbox = await this.findOrCreateSandbox(ontology);
25540
- for (const profileName of user.permissions) {
25541
- const profileId = await this.ensurePermissionProfile(
25542
- sandbox.sandboxId,
25543
- profileName
25544
+ const requiredGranularId = options.granularId?.trim();
25545
+ if (assignmentMode === "require-existing" && (!requiredGranularId || options.userId || options.user)) {
25546
+ throw new Error(
25547
+ `${methodName}() with assignmentMode "require-existing" requires granularId and does not accept userId or user.`
25544
25548
  );
25545
- await this.ensureAssignment(
25546
- user.granularId,
25547
- sandbox.sandboxId,
25548
- profileId
25549
+ }
25550
+ const user = await this.resolveConnectUser(
25551
+ assignmentMode === "require-existing" ? { ...options, granularId: requiredGranularId } : options
25552
+ );
25553
+ let requiredPermissionProfileId = null;
25554
+ const sandbox = assignmentMode === "require-existing" ? { sandboxId: await this._resolveSandboxId(ontology) } : await this.findOrCreateSandbox(ontology);
25555
+ if (assignmentMode === "require-existing") {
25556
+ const assignments = await this.subjects.listAssignments(user.granularId);
25557
+ const assignment = assignments.items.find(
25558
+ (item) => item.sandboxId === sandbox.sandboxId
25549
25559
  );
25560
+ if (!assignment) {
25561
+ throw new Error(
25562
+ `${methodName}() requires an existing assignment for subject ${user.granularId} in ontology ${sandbox.sandboxId}.`
25563
+ );
25564
+ }
25565
+ const assignedPermissionProfileId = assignment.permissionProfileId?.trim();
25566
+ if (!assignedPermissionProfileId) {
25567
+ throw new Error(
25568
+ `${methodName}() found an invalid assignment without a permission profile for subject ${user.granularId} in ontology ${sandbox.sandboxId}.`
25569
+ );
25570
+ }
25571
+ const expectedPermissionProfileId = options.expectedPermissionProfileId?.trim();
25572
+ if (expectedPermissionProfileId && assignedPermissionProfileId !== expectedPermissionProfileId) {
25573
+ throw new Error(
25574
+ `${methodName}() assignment mismatch for subject ${user.granularId}: expected permission profile ${expectedPermissionProfileId}, received ${assignedPermissionProfileId}.`
25575
+ );
25576
+ }
25577
+ requiredPermissionProfileId = assignedPermissionProfileId;
25578
+ } else {
25579
+ if (!Array.isArray(user.permissions) || user.permissions.length === 0) {
25580
+ throw new Error(
25581
+ `${methodName}() requires at least one permission so the SDK can ensure assignments for new users.`
25582
+ );
25583
+ }
25584
+ for (const profileName of user.permissions) {
25585
+ const profileId = await this.ensurePermissionProfile(
25586
+ sandbox.sandboxId,
25587
+ profileName
25588
+ );
25589
+ await this.ensureAssignment(
25590
+ user.granularId,
25591
+ sandbox.sandboxId,
25592
+ profileId
25593
+ );
25594
+ }
25550
25595
  }
25596
+ const requireMatchingEnvironmentProfile = (environment2) => {
25597
+ if (requiredPermissionProfileId && environment2.permissionProfileId !== requiredPermissionProfileId) {
25598
+ throw new Error(
25599
+ `${methodName}() resolved environment ${environment2.environmentId} with permission profile ${environment2.permissionProfileId || "none"}; current assignment requires ${requiredPermissionProfileId}.`
25600
+ );
25601
+ }
25602
+ return environment2;
25603
+ };
25551
25604
  const tags = await this.request(
25552
25605
  `/control/sandboxes/${sandbox.sandboxId}/tags`
25553
25606
  );
@@ -25570,6 +25623,9 @@ var Granular = class _Granular {
25570
25623
  const resolveActive = async (operationKey) => {
25571
25624
  const query = new URLSearchParams({ tagId: tag2.tagId, slot });
25572
25625
  if (operationKey) query.set("operationKey", operationKey);
25626
+ if (requiredPermissionProfileId) {
25627
+ query.set("expectedPermissionProfileId", requiredPermissionProfileId);
25628
+ }
25573
25629
  try {
25574
25630
  const payload = await this.request(
25575
25631
  `/control/sandboxes/${encodeURIComponent(sandbox.sandboxId)}/subjects/${encodeURIComponent(user.granularId)}/active-environment?${query.toString()}`
@@ -25593,7 +25649,8 @@ var Granular = class _Granular {
25593
25649
  tagId: tag2.tagId,
25594
25650
  slot,
25595
25651
  operationKey: resetKey,
25596
- operation: resetKey ? "explicit_reset" : void 0
25652
+ operation: resetKey ? "explicit_reset" : void 0,
25653
+ expectedPermissionProfileId: requiredPermissionProfileId || void 0
25597
25654
  })
25598
25655
  }
25599
25656
  );
@@ -25603,7 +25660,7 @@ var Granular = class _Granular {
25603
25660
  const resetEnvironment = await resolveActive(resetKey);
25604
25661
  if (resetEnvironment) {
25605
25662
  return {
25606
- environment: resetEnvironment,
25663
+ environment: requireMatchingEnvironmentProfile(resetEnvironment),
25607
25664
  requestedOntology: ontology,
25608
25665
  sandboxId: sandbox.sandboxId,
25609
25666
  subjectId: user.granularId,
@@ -25619,7 +25676,7 @@ var Granular = class _Granular {
25619
25676
  const active = await resolveActive();
25620
25677
  if (active && (active.versionId === targetVersionId || options.createFreshIfOutdated !== true)) {
25621
25678
  return {
25622
- environment: active,
25679
+ environment: requireMatchingEnvironmentProfile(active),
25623
25680
  requestedOntology: ontology,
25624
25681
  sandboxId: sandbox.sandboxId,
25625
25682
  subjectId: user.granularId,
@@ -25637,7 +25694,10 @@ var Granular = class _Granular {
25637
25694
  )
25638
25695
  );
25639
25696
  if (!resetKey && currentMatches.length > 0) {
25640
- const environment2 = await activate(currentMatches[0]);
25697
+ requireMatchingEnvironmentProfile(currentMatches[0]);
25698
+ const environment2 = requireMatchingEnvironmentProfile(
25699
+ await activate(currentMatches[0])
25700
+ );
25641
25701
  return {
25642
25702
  environment: environment2,
25643
25703
  requestedOntology: ontology,
@@ -25650,7 +25710,10 @@ var Granular = class _Granular {
25650
25710
  userEnvironments.filter((environment2) => environment2.tagId === tag2.tagId)
25651
25711
  );
25652
25712
  if (outdatedMatches.length > 0 && options.createFreshIfOutdated !== true) {
25653
- const environment2 = await activate(outdatedMatches[0]);
25713
+ requireMatchingEnvironmentProfile(outdatedMatches[0]);
25714
+ const environment2 = requireMatchingEnvironmentProfile(
25715
+ await activate(outdatedMatches[0])
25716
+ );
25654
25717
  return {
25655
25718
  environment: environment2,
25656
25719
  requestedOntology: ontology,
@@ -25669,7 +25732,10 @@ var Granular = class _Granular {
25669
25732
  tagId: tag2.tagId,
25670
25733
  permissionProfileId: null
25671
25734
  });
25672
- const environment = await activate(created);
25735
+ requireMatchingEnvironmentProfile(created);
25736
+ const environment = requireMatchingEnvironmentProfile(
25737
+ await activate(created)
25738
+ );
25673
25739
  return {
25674
25740
  environment,
25675
25741
  requestedOntology: ontology,
@@ -25879,22 +25945,16 @@ var Granular = class _Granular {
25879
25945
  metadata: options?.metadata
25880
25946
  });
25881
25947
  }
25882
- /**
25883
- * Mark a session closed in the control plane. If `environment` is the connected handle for that
25884
- * `sessionId`, disconnects the WebSocket so the runtime tears down cleanly.
25885
- */
25948
+ /** End a session through the runtime, or disconnect its connected handle. */
25886
25949
  async closeSession(sessionId, environment) {
25887
25950
  if (environment && environment.sessionId === sessionId) {
25888
25951
  await environment.disconnect();
25889
25952
  return;
25890
25953
  }
25891
- await this.request(`/control/sessions/${encodeURIComponent(sessionId)}`, {
25892
- method: "PATCH",
25893
- body: JSON.stringify({
25894
- status: "closed",
25895
- lastSeenAt: (/* @__PURE__ */ new Date()).toISOString()
25896
- })
25897
- });
25954
+ await this.request(
25955
+ `/control/sessions/${encodeURIComponent(sessionId)}/close`,
25956
+ { method: "POST" }
25957
+ );
25898
25958
  }
25899
25959
  /**
25900
25960
  * Re-open a closed session in the index and connect to its existing runtime document.
@@ -28104,7 +28164,11 @@ async function tagMoveCommand(tagName, versionId) {
28104
28164
  process.exit(1);
28105
28165
  }
28106
28166
  const previousVersionId = tag2.targetVersionId || tag2.targetBuildId || null;
28107
- const moved = await api.moveVersionTag(tag2.tagId, versionId);
28167
+ const moved = await api.moveVersionTag(
28168
+ tag2.tagId,
28169
+ versionId,
28170
+ tag2.name === "prod" ? previousVersionId : void 0
28171
+ );
28108
28172
  spin.succeed(` ${tagName} now points to ${versionId}.`);
28109
28173
  console.log();
28110
28174
  keyValue({
@@ -1,4 +1,4 @@
1
- import { bM as WSClientOptions, a2 as GranularQuotaProgress, T as ToolWithHandler, f as PublishToolsResult, aO as Job, g as ToolHandler, I as InstanceToolHandler, aY as ConversationMessageInput, aZ as ConversationAppendResult, aB as EffectInfo, P as Prompt, aA as ToolInfo, aD as EffectsChangedEvent, aC as ToolsChangedEvent, D as DomainState, y as GranularOptions, ci as EnvironmentImporter, B as RecordUserOptions, U as User, H as OpenEnvironmentOptions, af as EnvironmentData, ac as BuildPolicy, cf as EnvironmentSetupSummary, W as ConversationSessionListOptions, Q as ConversationSessionInfo, L as CreateSessionOptions, bW as RecordObjectOptions, c1 as RecordObjectResult, c3 as RecordObjectsOptions, ca as RecordImport, c6 as RecordImportStatus, c9 as RecordImportItem, cb as EnvironmentRecordImportSummary, aM as EnvironmentFeedbackRecord, c as SessionHeapSnapshot, bA as SessionDocumentResult, bB as SessionCollectionListOptions, bD as SessionCollectionListResult, a_ as SessionConversationMessage, a$ as SessionTimelineEvent, bC as SessionJobListOptions, bt as SessionJobRecord, b8 as SessionArtifactListOptions, b7 as SessionArtifactRecord, b9 as SessionArtifactValidationResult, bb as SessionArtifactExecutionOptions, ba as SessionArtifactExecutionResult, bc as SessionArtifactApprovalOptions, bm as RecordManualActionInput, bo as ManualActionRecordResult, bp as ManualActionListOptions, bn as ManualActionOccurrence, br as ManualActionSuggestionOptions, bq as ManualActionSuggestion, bf as ArtifactApprovalTaskListOptions, be as ArtifactApprovalTask, bg as ArtifactApprovalDecisionInput, bh as ArtifactApprovalDecisionResult, b3 as SessionFileRecord, bs as SessionFileUploadOptions, S as SessionHeapEntry, b as SessionHeapList, bw as SessionHeapVariable, d as SessionTranscriptEntry, cM as GraphQLResult, by as RecordSearchOptions, bx as RecordSearchResult, bz as RecordMentionInput, bV as DefineRelationshipOptions, bU as RelationshipInfo, bT as ModelRef, cL as ManifestContent, b_ as EnvironmentStateUpdateInput, bY as EnvironmentStateTarget, c0 as EnvironmentStateProxy, c5 as RecordImportOptions, bI as UserEnvironmentStateOptions, bH as UserEnvironmentState, bJ as MarkUserEnvironmentReadOptions, J as AdoptEnvironmentOptions, K as ConnectOptions, cd as RunEnvironmentImporterOptions, l as OpenAIUsageSpendEvent, G as GranularSpendContext, o as RecordOpenAIUsageSpendResult, a5 as SandboxListResponse, a3 as Sandbox, a4 as CreateSandboxData, cO as DeleteResponse, a7 as PermissionProfile, a8 as CreatePermissionProfileData, ag as CreateEnvironmentData, cP as StreamEvent, cQ as StreamSubscription, cR as StreamStats, F as Subject, ab as AssignmentListResponse } from './spend-DpRRCrAr.js';
1
+ import { bM as WSClientOptions, a2 as GranularQuotaProgress, T as ToolWithHandler, f as PublishToolsResult, aO as Job, g as ToolHandler, I as InstanceToolHandler, aY as ConversationMessageInput, aZ as ConversationAppendResult, aB as EffectInfo, P as Prompt, aA as ToolInfo, aD as EffectsChangedEvent, aC as ToolsChangedEvent, D as DomainState, y as GranularOptions, ci as EnvironmentImporter, B as RecordUserOptions, U as User, H as OpenEnvironmentOptions, af as EnvironmentData, ac as BuildPolicy, cf as EnvironmentSetupSummary, W as ConversationSessionListOptions, Q as ConversationSessionInfo, L as CreateSessionOptions, bW as RecordObjectOptions, c1 as RecordObjectResult, c3 as RecordObjectsOptions, ca as RecordImport, c6 as RecordImportStatus, c9 as RecordImportItem, cb as EnvironmentRecordImportSummary, aM as EnvironmentFeedbackRecord, c as SessionHeapSnapshot, bA as SessionDocumentResult, bB as SessionCollectionListOptions, bD as SessionCollectionListResult, a_ as SessionConversationMessage, a$ as SessionTimelineEvent, bC as SessionJobListOptions, bt as SessionJobRecord, b8 as SessionArtifactListOptions, b7 as SessionArtifactRecord, b9 as SessionArtifactValidationResult, bb as SessionArtifactExecutionOptions, ba as SessionArtifactExecutionResult, bc as SessionArtifactApprovalOptions, bm as RecordManualActionInput, bo as ManualActionRecordResult, bp as ManualActionListOptions, bn as ManualActionOccurrence, br as ManualActionSuggestionOptions, bq as ManualActionSuggestion, bf as ArtifactApprovalTaskListOptions, be as ArtifactApprovalTask, bg as ArtifactApprovalDecisionInput, bh as ArtifactApprovalDecisionResult, b3 as SessionFileRecord, bs as SessionFileUploadOptions, S as SessionHeapEntry, b as SessionHeapList, bw as SessionHeapVariable, d as SessionTranscriptEntry, cM as GraphQLResult, by as RecordSearchOptions, bx as RecordSearchResult, bz as RecordMentionInput, bV as DefineRelationshipOptions, bU as RelationshipInfo, bT as ModelRef, cL as ManifestContent, b_ as EnvironmentStateUpdateInput, bY as EnvironmentStateTarget, c0 as EnvironmentStateProxy, c5 as RecordImportOptions, bI as UserEnvironmentStateOptions, bH as UserEnvironmentState, bJ as MarkUserEnvironmentReadOptions, J as AdoptEnvironmentOptions, K as ConnectOptions, cd as RunEnvironmentImporterOptions, l as OpenAIUsageSpendEvent, G as GranularSpendContext, o as RecordOpenAIUsageSpendResult, a5 as SandboxListResponse, a3 as Sandbox, a4 as CreateSandboxData, cO as DeleteResponse, a7 as PermissionProfile, a8 as CreatePermissionProfileData, ag as CreateEnvironmentData, cP as StreamEvent, cQ as StreamSubscription, cR as StreamStats, F as Subject, ab as AssignmentListResponse } from './spend-czRX7l0X.mjs';
2
2
  import * as Automerge from '@automerge/automerge';
3
3
  import { Doc } from '@automerge/automerge/slim';
4
4
 
@@ -1057,10 +1057,7 @@ declare class Granular {
1057
1057
  recordOpenAIUsageSpend(usage: OpenAIUsageSpendEvent, context?: GranularSpendContext | null, options?: {
1058
1058
  metadata?: Record<string, unknown> | null;
1059
1059
  }): Promise<RecordOpenAIUsageSpendResult>;
1060
- /**
1061
- * Mark a session closed in the control plane. If `environment` is the connected handle for that
1062
- * `sessionId`, disconnects the WebSocket so the runtime tears down cleanly.
1063
- */
1060
+ /** End a session through the runtime, or disconnect its connected handle. */
1064
1061
  closeSession(sessionId: string, environment?: EnvironmentSession | null): Promise<void>;
1065
1062
  /**
1066
1063
  * Re-open a closed session in the index and connect to its existing runtime document.
@@ -1,4 +1,4 @@
1
- import { bM as WSClientOptions, a2 as GranularQuotaProgress, T as ToolWithHandler, f as PublishToolsResult, aO as Job, g as ToolHandler, I as InstanceToolHandler, aY as ConversationMessageInput, aZ as ConversationAppendResult, aB as EffectInfo, P as Prompt, aA as ToolInfo, aD as EffectsChangedEvent, aC as ToolsChangedEvent, D as DomainState, y as GranularOptions, ci as EnvironmentImporter, B as RecordUserOptions, U as User, H as OpenEnvironmentOptions, af as EnvironmentData, ac as BuildPolicy, cf as EnvironmentSetupSummary, W as ConversationSessionListOptions, Q as ConversationSessionInfo, L as CreateSessionOptions, bW as RecordObjectOptions, c1 as RecordObjectResult, c3 as RecordObjectsOptions, ca as RecordImport, c6 as RecordImportStatus, c9 as RecordImportItem, cb as EnvironmentRecordImportSummary, aM as EnvironmentFeedbackRecord, c as SessionHeapSnapshot, bA as SessionDocumentResult, bB as SessionCollectionListOptions, bD as SessionCollectionListResult, a_ as SessionConversationMessage, a$ as SessionTimelineEvent, bC as SessionJobListOptions, bt as SessionJobRecord, b8 as SessionArtifactListOptions, b7 as SessionArtifactRecord, b9 as SessionArtifactValidationResult, bb as SessionArtifactExecutionOptions, ba as SessionArtifactExecutionResult, bc as SessionArtifactApprovalOptions, bm as RecordManualActionInput, bo as ManualActionRecordResult, bp as ManualActionListOptions, bn as ManualActionOccurrence, br as ManualActionSuggestionOptions, bq as ManualActionSuggestion, bf as ArtifactApprovalTaskListOptions, be as ArtifactApprovalTask, bg as ArtifactApprovalDecisionInput, bh as ArtifactApprovalDecisionResult, b3 as SessionFileRecord, bs as SessionFileUploadOptions, S as SessionHeapEntry, b as SessionHeapList, bw as SessionHeapVariable, d as SessionTranscriptEntry, cM as GraphQLResult, by as RecordSearchOptions, bx as RecordSearchResult, bz as RecordMentionInput, bV as DefineRelationshipOptions, bU as RelationshipInfo, bT as ModelRef, cL as ManifestContent, b_ as EnvironmentStateUpdateInput, bY as EnvironmentStateTarget, c0 as EnvironmentStateProxy, c5 as RecordImportOptions, bI as UserEnvironmentStateOptions, bH as UserEnvironmentState, bJ as MarkUserEnvironmentReadOptions, J as AdoptEnvironmentOptions, K as ConnectOptions, cd as RunEnvironmentImporterOptions, l as OpenAIUsageSpendEvent, G as GranularSpendContext, o as RecordOpenAIUsageSpendResult, a5 as SandboxListResponse, a3 as Sandbox, a4 as CreateSandboxData, cO as DeleteResponse, a7 as PermissionProfile, a8 as CreatePermissionProfileData, ag as CreateEnvironmentData, cP as StreamEvent, cQ as StreamSubscription, cR as StreamStats, F as Subject, ab as AssignmentListResponse } from './spend-DpRRCrAr.mjs';
1
+ import { bM as WSClientOptions, a2 as GranularQuotaProgress, T as ToolWithHandler, f as PublishToolsResult, aO as Job, g as ToolHandler, I as InstanceToolHandler, aY as ConversationMessageInput, aZ as ConversationAppendResult, aB as EffectInfo, P as Prompt, aA as ToolInfo, aD as EffectsChangedEvent, aC as ToolsChangedEvent, D as DomainState, y as GranularOptions, ci as EnvironmentImporter, B as RecordUserOptions, U as User, H as OpenEnvironmentOptions, af as EnvironmentData, ac as BuildPolicy, cf as EnvironmentSetupSummary, W as ConversationSessionListOptions, Q as ConversationSessionInfo, L as CreateSessionOptions, bW as RecordObjectOptions, c1 as RecordObjectResult, c3 as RecordObjectsOptions, ca as RecordImport, c6 as RecordImportStatus, c9 as RecordImportItem, cb as EnvironmentRecordImportSummary, aM as EnvironmentFeedbackRecord, c as SessionHeapSnapshot, bA as SessionDocumentResult, bB as SessionCollectionListOptions, bD as SessionCollectionListResult, a_ as SessionConversationMessage, a$ as SessionTimelineEvent, bC as SessionJobListOptions, bt as SessionJobRecord, b8 as SessionArtifactListOptions, b7 as SessionArtifactRecord, b9 as SessionArtifactValidationResult, bb as SessionArtifactExecutionOptions, ba as SessionArtifactExecutionResult, bc as SessionArtifactApprovalOptions, bm as RecordManualActionInput, bo as ManualActionRecordResult, bp as ManualActionListOptions, bn as ManualActionOccurrence, br as ManualActionSuggestionOptions, bq as ManualActionSuggestion, bf as ArtifactApprovalTaskListOptions, be as ArtifactApprovalTask, bg as ArtifactApprovalDecisionInput, bh as ArtifactApprovalDecisionResult, b3 as SessionFileRecord, bs as SessionFileUploadOptions, S as SessionHeapEntry, b as SessionHeapList, bw as SessionHeapVariable, d as SessionTranscriptEntry, cM as GraphQLResult, by as RecordSearchOptions, bx as RecordSearchResult, bz as RecordMentionInput, bV as DefineRelationshipOptions, bU as RelationshipInfo, bT as ModelRef, cL as ManifestContent, b_ as EnvironmentStateUpdateInput, bY as EnvironmentStateTarget, c0 as EnvironmentStateProxy, c5 as RecordImportOptions, bI as UserEnvironmentStateOptions, bH as UserEnvironmentState, bJ as MarkUserEnvironmentReadOptions, J as AdoptEnvironmentOptions, K as ConnectOptions, cd as RunEnvironmentImporterOptions, l as OpenAIUsageSpendEvent, G as GranularSpendContext, o as RecordOpenAIUsageSpendResult, a5 as SandboxListResponse, a3 as Sandbox, a4 as CreateSandboxData, cO as DeleteResponse, a7 as PermissionProfile, a8 as CreatePermissionProfileData, ag as CreateEnvironmentData, cP as StreamEvent, cQ as StreamSubscription, cR as StreamStats, F as Subject, ab as AssignmentListResponse } from './spend-czRX7l0X.js';
2
2
  import * as Automerge from '@automerge/automerge';
3
3
  import { Doc } from '@automerge/automerge/slim';
4
4
 
@@ -1057,10 +1057,7 @@ declare class Granular {
1057
1057
  recordOpenAIUsageSpend(usage: OpenAIUsageSpendEvent, context?: GranularSpendContext | null, options?: {
1058
1058
  metadata?: Record<string, unknown> | null;
1059
1059
  }): Promise<RecordOpenAIUsageSpendResult>;
1060
- /**
1061
- * Mark a session closed in the control plane. If `environment` is the connected handle for that
1062
- * `sessionId`, disconnects the WebSocket so the runtime tears down cleanly.
1063
- */
1060
+ /** End a session through the runtime, or disconnect its connected handle. */
1064
1061
  closeSession(sessionId: string, environment?: EnvironmentSession | null): Promise<void>;
1065
1062
  /**
1066
1063
  * Re-open a closed session in the index and connect to its existing runtime document.
package/dist/index.d.mts CHANGED
@@ -1,6 +1,6 @@
1
- export { E as Environment, a as EnvironmentSession, G as Granular, O as OntologyHandle, S as Session, W as WSClient } from './client-DL4S9uRc.mjs';
2
- import { E as EndpointMode, T as ToolWithHandler, a as EffectHandlerContext, M as ManifestEffectMetamodelSpec, R as ResolvedEffectBehaviors, S as SessionHeapEntry, b as SessionHeapList, c as SessionHeapSnapshot, P as Prompt, d as SessionTranscriptEntry } from './spend-DpRRCrAr.mjs';
3
- export { cN as APIError, A as AccessTokenProvider, J as AdoptEnvironmentOptions, bg as ArtifactApprovalDecisionInput, bh as ArtifactApprovalDecisionResult, be as ArtifactApprovalTask, bf as ArtifactApprovalTaskListOptions, bd as ArtifactApprovalTaskStatus, aa as Assignment, ab as AssignmentListResponse, al as Build, an as BuildListResponse, ac as BuildPolicy, ak as BuildStatus, C as ConditionIR, K as ConnectOptions, aV as ConversationActionSuggestion, aZ as ConversationAppendResult, aW as ConversationMessageAction, aY as ConversationMessageInput, aX as ConversationMessagePart, aP as ConversationMessageShowRefs, Q as ConversationSessionInfo, W as ConversationSessionListOptions, V as ConversationSessionListStatus, aQ as ConversationTableCell, aR as ConversationTableColumn, aU as ConversationTableProjection, aT as ConversationTableRow, aS as ConversationTableRowReference, ag as CreateEnvironmentData, a8 as CreatePermissionProfileData, a4 as CreateSandboxData, L as CreateSessionOptions, bV as DefineRelationshipOptions, cO as DeleteResponse, D as DomainState, aE as EffectHandler, aB as EffectInfo, av as EffectInvocationMetadata, au as EffectInvocationMode, aw as EffectSchema, az as EffectVersionSelector, ax as EffectWithHandler, aD as EffectsChangedEvent, af as EnvironmentData, aM as EnvironmentFeedbackRecord, ci as EnvironmentImporter, ch as EnvironmentImporterImportOptions, ah as EnvironmentListResponse, cb as EnvironmentRecordImportSummary, cg as EnvironmentSetupImporterClaim, ce as EnvironmentSetupLifecycleStatus, cf as EnvironmentSetupSummary, cc as EnvironmentSetupTriggerReason, b$ as EnvironmentStateMachineProxy, bZ as EnvironmentStateObservationInput, c0 as EnvironmentStateProxy, bY as EnvironmentStateTarget, b_ as EnvironmentStateUpdateInput, z as GranularAuth, y as GranularOptions, a1 as GranularQuotaPolicy, a2 as GranularQuotaProgress, G as GranularSpendContext, cM as GraphQLResult, aF as InstanceEffectHandler, I as InstanceToolHandler, aO as Job, aK as JobFeedbackInput, aJ as JobFeedbackMetadata, aL as JobFeedbackRecord, aH as JobFeedbackSentiment, aI as JobFeedbackToolCall, aG as JobStatus, aN as JobSubmitResult, ai as Manifest, cB as ManifestApprovalRequiredSpec, cL as ManifestContent, cC as ManifestCreatesSpec, cz as ManifestDryRunSpec, cF as ManifestEffectDeclaration, cE as ManifestEffectSchema, cl as ManifestEnumRuleSpec, cH as ManifestEventStreamDef, cG as ManifestEventTypeDef, cm as ManifestFilterBySpec, cJ as ManifestImport, aj as ManifestListResponse, cI as ManifestOperation, cy as ManifestPostConditionSpec, cj as ManifestPropertySpec, cD as ManifestRelationshipDef, cA as ManifestReverseSpec, cx as ManifestStateMachineSpec, co as ManifestStateMachineStateSpec, cw as ManifestStateMachineTransitionSpec, cq as ManifestStateTransitionActionSpec, cr as ManifestStateTransitionAssigneeSpec, cv as ManifestStateTransitionExpectedOutcomeSpec, cp as ManifestStateTransitionInputBinding, cu as ManifestStateTransitionPermissionSpec, cs as ManifestStateTransitionRelatedStateRequirementSpec, ct as ManifestStateTransitionRequirementsSpec, ck as ManifestValidationOperator, cn as ManifestValidationRuleSpec, cK as ManifestVolume, bp as ManualActionListOptions, bn as ManualActionOccurrence, bo as ManualActionRecordResult, bl as ManualActionRelatedRecord, bj as ManualActionSource, bi as ManualActionStatus, bq as ManualActionSuggestion, br as ManualActionSuggestionOptions, bk as ManualActionTarget, bJ as MarkUserEnvironmentReadOptions, x as MatchedPolicy, bT as ModelRef, N as NormalizedOpenAIUsage, i as OPENAI_MODEL_PRICING_USD_PER_MILLION, O as OpenAIModelPricing, h as OpenAITokenSpend, l as OpenAIUsageSpendEvent, H as OpenEnvironmentOptions, a7 as PermissionProfile, a9 as PermissionProfileListResponse, a6 as PermissionRules, u as PolicyOperator, v as PolicyOrigin, s as PolicyPredicateSource, w as PolicyRuleIR, q as PolicySource, ay as PublishEffectsResult, f as PublishToolsResult, a0 as QuotaLineItemFilter, Z as QuotaPeriod, Y as QuotaScopeType, _ as QuotaStatus, bN as RPCRequest, bQ as RPCRequestFromServer, bO as RPCResponse, ca as RecordImport, c9 as RecordImportItem, c7 as RecordImportItemStatus, c5 as RecordImportOptions, c8 as RecordImportStats, c6 as RecordImportStatus, c4 as RecordImportWriteMode, bm as RecordManualActionInput, bz as RecordMentionInput, bW as RecordObjectOptions, c1 as RecordObjectResult, bX as RecordObjectStateValue, c2 as RecordObjectsChunkInfo, c3 as RecordObjectsOptions, m as RecordOpenAIUsageSpendOptions, o as RecordOpenAIUsageSpendResult, by as RecordSearchOptions, bx as RecordSearchResult, B as RecordUserOptions, bU as RelationshipInfo, at as ResolvedEffectApprovalRequired, ar as ResolvedEffectDryRun, aq as ResolvedEffectPostCondition, as as ResolvedEffectReverse, cd as RunEnvironmentImporterOptions, a3 as Sandbox, a5 as SandboxListResponse, ap as SemanticVersionDiff, ao as SemanticVersionDiffEntry, bc as SessionArtifactApprovalOptions, b6 as SessionArtifactAutonomyPolicy, bb as SessionArtifactExecutionOptions, ba as SessionArtifactExecutionResult, b5 as SessionArtifactKind, b8 as SessionArtifactListOptions, b7 as SessionArtifactRecord, b4 as SessionArtifactStatus, b9 as SessionArtifactValidationResult, bB as SessionCollectionListOptions, bD as SessionCollectionListResult, a_ as SessionConversationMessage, bA as SessionDocumentResult, b1 as SessionFileKind, b3 as SessionFileRecord, b0 as SessionFileSource, b2 as SessionFileStatus, bs as SessionFileUploadOptions, bu as SessionHeapFieldType, bv as SessionHeapFieldValue, bw as SessionHeapVariable, bC as SessionJobListOptions, bt as SessionJobRecord, a$ as SessionTimelineEvent, X as SpendLineItemType, $ as SpendSummary, cP as StreamEvent, cR as StreamStats, cQ as StreamSubscription, F as Subject, bP as SyncMessage, g as ToolHandler, aA as ToolInfo, bR as ToolInvokeParams, bS as ToolResultParams, e as ToolSchema, aC as ToolsChangedEvent, U as User, bF as UserEnvironmentMessagePreview, bE as UserEnvironmentPrompt, bG as UserEnvironmentSessionState, bH as UserEnvironmentState, bI as UserEnvironmentStateOptions, am as Version, ae as VersionTag, ad as VersionTracking, bM as WSClientOptions, bK as WSDisconnectInfo, bL as WSReconnectErrorInfo, p as buildOpenAISpendEventId, k as calculateOpenAITokenSpend, j as getOpenAIModelPricing, n as normalizeOpenAIUsage, r as recordOpenAIUsageSpend, t as toGranularHttpBase } from './spend-DpRRCrAr.mjs';
1
+ export { E as Environment, a as EnvironmentSession, G as Granular, O as OntologyHandle, S as Session, W as WSClient } from './client-DFaCRSto.mjs';
2
+ import { E as EndpointMode, T as ToolWithHandler, a as EffectHandlerContext, M as ManifestEffectMetamodelSpec, R as ResolvedEffectBehaviors, S as SessionHeapEntry, b as SessionHeapList, c as SessionHeapSnapshot, P as Prompt, d as SessionTranscriptEntry } from './spend-czRX7l0X.mjs';
3
+ export { cN as APIError, A as AccessTokenProvider, J as AdoptEnvironmentOptions, bg as ArtifactApprovalDecisionInput, bh as ArtifactApprovalDecisionResult, be as ArtifactApprovalTask, bf as ArtifactApprovalTaskListOptions, bd as ArtifactApprovalTaskStatus, aa as Assignment, ab as AssignmentListResponse, al as Build, an as BuildListResponse, ac as BuildPolicy, ak as BuildStatus, C as ConditionIR, K as ConnectOptions, aV as ConversationActionSuggestion, aZ as ConversationAppendResult, aW as ConversationMessageAction, aY as ConversationMessageInput, aX as ConversationMessagePart, aP as ConversationMessageShowRefs, Q as ConversationSessionInfo, W as ConversationSessionListOptions, V as ConversationSessionListStatus, aQ as ConversationTableCell, aR as ConversationTableColumn, aU as ConversationTableProjection, aT as ConversationTableRow, aS as ConversationTableRowReference, ag as CreateEnvironmentData, a8 as CreatePermissionProfileData, a4 as CreateSandboxData, L as CreateSessionOptions, bV as DefineRelationshipOptions, cO as DeleteResponse, D as DomainState, aE as EffectHandler, aB as EffectInfo, av as EffectInvocationMetadata, au as EffectInvocationMode, aw as EffectSchema, az as EffectVersionSelector, ax as EffectWithHandler, aD as EffectsChangedEvent, af as EnvironmentData, aM as EnvironmentFeedbackRecord, ci as EnvironmentImporter, ch as EnvironmentImporterImportOptions, ah as EnvironmentListResponse, cb as EnvironmentRecordImportSummary, cg as EnvironmentSetupImporterClaim, ce as EnvironmentSetupLifecycleStatus, cf as EnvironmentSetupSummary, cc as EnvironmentSetupTriggerReason, b$ as EnvironmentStateMachineProxy, bZ as EnvironmentStateObservationInput, c0 as EnvironmentStateProxy, bY as EnvironmentStateTarget, b_ as EnvironmentStateUpdateInput, z as GranularAuth, y as GranularOptions, a1 as GranularQuotaPolicy, a2 as GranularQuotaProgress, G as GranularSpendContext, cM as GraphQLResult, aF as InstanceEffectHandler, I as InstanceToolHandler, aO as Job, aK as JobFeedbackInput, aJ as JobFeedbackMetadata, aL as JobFeedbackRecord, aH as JobFeedbackSentiment, aI as JobFeedbackToolCall, aG as JobStatus, aN as JobSubmitResult, ai as Manifest, cB as ManifestApprovalRequiredSpec, cL as ManifestContent, cC as ManifestCreatesSpec, cz as ManifestDryRunSpec, cF as ManifestEffectDeclaration, cE as ManifestEffectSchema, cl as ManifestEnumRuleSpec, cH as ManifestEventStreamDef, cG as ManifestEventTypeDef, cm as ManifestFilterBySpec, cJ as ManifestImport, aj as ManifestListResponse, cI as ManifestOperation, cy as ManifestPostConditionSpec, cj as ManifestPropertySpec, cD as ManifestRelationshipDef, cA as ManifestReverseSpec, cx as ManifestStateMachineSpec, co as ManifestStateMachineStateSpec, cw as ManifestStateMachineTransitionSpec, cq as ManifestStateTransitionActionSpec, cr as ManifestStateTransitionAssigneeSpec, cv as ManifestStateTransitionExpectedOutcomeSpec, cp as ManifestStateTransitionInputBinding, cu as ManifestStateTransitionPermissionSpec, cs as ManifestStateTransitionRelatedStateRequirementSpec, ct as ManifestStateTransitionRequirementsSpec, ck as ManifestValidationOperator, cn as ManifestValidationRuleSpec, cK as ManifestVolume, bp as ManualActionListOptions, bn as ManualActionOccurrence, bo as ManualActionRecordResult, bl as ManualActionRelatedRecord, bj as ManualActionSource, bi as ManualActionStatus, bq as ManualActionSuggestion, br as ManualActionSuggestionOptions, bk as ManualActionTarget, bJ as MarkUserEnvironmentReadOptions, x as MatchedPolicy, bT as ModelRef, N as NormalizedOpenAIUsage, i as OPENAI_MODEL_PRICING_USD_PER_MILLION, O as OpenAIModelPricing, h as OpenAITokenSpend, l as OpenAIUsageSpendEvent, H as OpenEnvironmentOptions, a7 as PermissionProfile, a9 as PermissionProfileListResponse, a6 as PermissionRules, u as PolicyOperator, v as PolicyOrigin, s as PolicyPredicateSource, w as PolicyRuleIR, q as PolicySource, ay as PublishEffectsResult, f as PublishToolsResult, a0 as QuotaLineItemFilter, Z as QuotaPeriod, Y as QuotaScopeType, _ as QuotaStatus, bN as RPCRequest, bQ as RPCRequestFromServer, bO as RPCResponse, ca as RecordImport, c9 as RecordImportItem, c7 as RecordImportItemStatus, c5 as RecordImportOptions, c8 as RecordImportStats, c6 as RecordImportStatus, c4 as RecordImportWriteMode, bm as RecordManualActionInput, bz as RecordMentionInput, bW as RecordObjectOptions, c1 as RecordObjectResult, bX as RecordObjectStateValue, c2 as RecordObjectsChunkInfo, c3 as RecordObjectsOptions, m as RecordOpenAIUsageSpendOptions, o as RecordOpenAIUsageSpendResult, by as RecordSearchOptions, bx as RecordSearchResult, B as RecordUserOptions, bU as RelationshipInfo, at as ResolvedEffectApprovalRequired, ar as ResolvedEffectDryRun, aq as ResolvedEffectPostCondition, as as ResolvedEffectReverse, cd as RunEnvironmentImporterOptions, a3 as Sandbox, a5 as SandboxListResponse, ap as SemanticVersionDiff, ao as SemanticVersionDiffEntry, bc as SessionArtifactApprovalOptions, b6 as SessionArtifactAutonomyPolicy, bb as SessionArtifactExecutionOptions, ba as SessionArtifactExecutionResult, b5 as SessionArtifactKind, b8 as SessionArtifactListOptions, b7 as SessionArtifactRecord, b4 as SessionArtifactStatus, b9 as SessionArtifactValidationResult, bB as SessionCollectionListOptions, bD as SessionCollectionListResult, a_ as SessionConversationMessage, bA as SessionDocumentResult, b1 as SessionFileKind, b3 as SessionFileRecord, b0 as SessionFileSource, b2 as SessionFileStatus, bs as SessionFileUploadOptions, bu as SessionHeapFieldType, bv as SessionHeapFieldValue, bw as SessionHeapVariable, bC as SessionJobListOptions, bt as SessionJobRecord, a$ as SessionTimelineEvent, X as SpendLineItemType, $ as SpendSummary, cP as StreamEvent, cR as StreamStats, cQ as StreamSubscription, F as Subject, bP as SyncMessage, g as ToolHandler, aA as ToolInfo, bR as ToolInvokeParams, bS as ToolResultParams, e as ToolSchema, aC as ToolsChangedEvent, U as User, bF as UserEnvironmentMessagePreview, bE as UserEnvironmentPrompt, bG as UserEnvironmentSessionState, bH as UserEnvironmentState, bI as UserEnvironmentStateOptions, am as Version, ae as VersionTag, ad as VersionTracking, bM as WSClientOptions, bK as WSDisconnectInfo, bL as WSReconnectErrorInfo, p as buildOpenAISpendEventId, k as calculateOpenAITokenSpend, j as getOpenAIModelPricing, n as normalizeOpenAIUsage, r as recordOpenAIUsageSpend, t as toGranularHttpBase } from './spend-czRX7l0X.mjs';
4
4
  export { BuildGranularAgentSystemPromptInput, GeneratedJobCodeIssue, GranularAgentExecutionCheckpoint, GranularAgentHeapSummaryOptions, GranularAgentManualActionMemorySuggestion, GranularAgentPromptCapabilities, GranularAgentReferentFocus, GranularAgentSessionContext, GranularAgentToolInfo, GranularAgentWorkflowFocus, GranularReasoningTraceChunkResult, GranularReasoningTraceOptions, HarnessContinuationDecision, HarnessControllerBudgets, HarnessProjectionOptions, HarnessPromptLike, HarnessRenderedContinuation, HarnessRenderedPrompt, HarnessTemplate, HarnessTemplateManifest, HarnessTemplateSelectionOptions, HarnessTemplateStatus, HarnessVerifierSnapshot, HarnessVerifierSnapshotInput, ReviewGeneratedJobCodeOptions, buildContinuationInstruction, buildContinuationInstructionFromTemplate, buildGranularAgentCheckpointBlock, buildGranularAgentDomainBlock, buildGranularAgentFileBlock, buildGranularAgentHeapBlock, buildGranularAgentLoopBlock, buildGranularAgentManualActionBlock, buildGranularAgentManualActionMemorySummary, buildGranularAgentReferentBlock, buildGranularAgentRuntimeImportsBlock, buildGranularAgentSessionBlock, buildGranularAgentSystemPrompt, buildGranularAgentSystemPromptFromTemplate, buildGranularAgentToolBlock, buildGranularAgentWorkflowBlock, consumeGranularReasoningOnlyChunk, consumeGranularReasoningTraceChunk, createHarnessVerifierSnapshot, evaluateContinuation, getCurrentClosureId, getDefaultHarnessTemplateId, getExclusivePromptTarget, hasOpenPrompt, hashHarnessTemplateValue, listHarnessTemplates, projectConversationReferentFocus, projectConversationReferentSummary, projectHeapSummary, projectLoopSummary, projectSessionFileSummary, projectWorkflowFocus, projectWorkflowSummary, renderContinuationInstructionFromTemplate, renderGranularAgentSystemPromptFromTemplate, resolveHarnessTemplate, reviewGeneratedJobCode, stripGranularReasoningTrace, validateHarnessTemplateManifest } from './agent-harness.mjs';
5
5
  import '@automerge/automerge';
6
6
  import '@automerge/automerge/slim';
package/dist/index.d.ts CHANGED
@@ -1,6 +1,6 @@
1
- export { E as Environment, a as EnvironmentSession, G as Granular, O as OntologyHandle, S as Session, W as WSClient } from './client-BKde5VzV.js';
2
- import { E as EndpointMode, T as ToolWithHandler, a as EffectHandlerContext, M as ManifestEffectMetamodelSpec, R as ResolvedEffectBehaviors, S as SessionHeapEntry, b as SessionHeapList, c as SessionHeapSnapshot, P as Prompt, d as SessionTranscriptEntry } from './spend-DpRRCrAr.js';
3
- export { cN as APIError, A as AccessTokenProvider, J as AdoptEnvironmentOptions, bg as ArtifactApprovalDecisionInput, bh as ArtifactApprovalDecisionResult, be as ArtifactApprovalTask, bf as ArtifactApprovalTaskListOptions, bd as ArtifactApprovalTaskStatus, aa as Assignment, ab as AssignmentListResponse, al as Build, an as BuildListResponse, ac as BuildPolicy, ak as BuildStatus, C as ConditionIR, K as ConnectOptions, aV as ConversationActionSuggestion, aZ as ConversationAppendResult, aW as ConversationMessageAction, aY as ConversationMessageInput, aX as ConversationMessagePart, aP as ConversationMessageShowRefs, Q as ConversationSessionInfo, W as ConversationSessionListOptions, V as ConversationSessionListStatus, aQ as ConversationTableCell, aR as ConversationTableColumn, aU as ConversationTableProjection, aT as ConversationTableRow, aS as ConversationTableRowReference, ag as CreateEnvironmentData, a8 as CreatePermissionProfileData, a4 as CreateSandboxData, L as CreateSessionOptions, bV as DefineRelationshipOptions, cO as DeleteResponse, D as DomainState, aE as EffectHandler, aB as EffectInfo, av as EffectInvocationMetadata, au as EffectInvocationMode, aw as EffectSchema, az as EffectVersionSelector, ax as EffectWithHandler, aD as EffectsChangedEvent, af as EnvironmentData, aM as EnvironmentFeedbackRecord, ci as EnvironmentImporter, ch as EnvironmentImporterImportOptions, ah as EnvironmentListResponse, cb as EnvironmentRecordImportSummary, cg as EnvironmentSetupImporterClaim, ce as EnvironmentSetupLifecycleStatus, cf as EnvironmentSetupSummary, cc as EnvironmentSetupTriggerReason, b$ as EnvironmentStateMachineProxy, bZ as EnvironmentStateObservationInput, c0 as EnvironmentStateProxy, bY as EnvironmentStateTarget, b_ as EnvironmentStateUpdateInput, z as GranularAuth, y as GranularOptions, a1 as GranularQuotaPolicy, a2 as GranularQuotaProgress, G as GranularSpendContext, cM as GraphQLResult, aF as InstanceEffectHandler, I as InstanceToolHandler, aO as Job, aK as JobFeedbackInput, aJ as JobFeedbackMetadata, aL as JobFeedbackRecord, aH as JobFeedbackSentiment, aI as JobFeedbackToolCall, aG as JobStatus, aN as JobSubmitResult, ai as Manifest, cB as ManifestApprovalRequiredSpec, cL as ManifestContent, cC as ManifestCreatesSpec, cz as ManifestDryRunSpec, cF as ManifestEffectDeclaration, cE as ManifestEffectSchema, cl as ManifestEnumRuleSpec, cH as ManifestEventStreamDef, cG as ManifestEventTypeDef, cm as ManifestFilterBySpec, cJ as ManifestImport, aj as ManifestListResponse, cI as ManifestOperation, cy as ManifestPostConditionSpec, cj as ManifestPropertySpec, cD as ManifestRelationshipDef, cA as ManifestReverseSpec, cx as ManifestStateMachineSpec, co as ManifestStateMachineStateSpec, cw as ManifestStateMachineTransitionSpec, cq as ManifestStateTransitionActionSpec, cr as ManifestStateTransitionAssigneeSpec, cv as ManifestStateTransitionExpectedOutcomeSpec, cp as ManifestStateTransitionInputBinding, cu as ManifestStateTransitionPermissionSpec, cs as ManifestStateTransitionRelatedStateRequirementSpec, ct as ManifestStateTransitionRequirementsSpec, ck as ManifestValidationOperator, cn as ManifestValidationRuleSpec, cK as ManifestVolume, bp as ManualActionListOptions, bn as ManualActionOccurrence, bo as ManualActionRecordResult, bl as ManualActionRelatedRecord, bj as ManualActionSource, bi as ManualActionStatus, bq as ManualActionSuggestion, br as ManualActionSuggestionOptions, bk as ManualActionTarget, bJ as MarkUserEnvironmentReadOptions, x as MatchedPolicy, bT as ModelRef, N as NormalizedOpenAIUsage, i as OPENAI_MODEL_PRICING_USD_PER_MILLION, O as OpenAIModelPricing, h as OpenAITokenSpend, l as OpenAIUsageSpendEvent, H as OpenEnvironmentOptions, a7 as PermissionProfile, a9 as PermissionProfileListResponse, a6 as PermissionRules, u as PolicyOperator, v as PolicyOrigin, s as PolicyPredicateSource, w as PolicyRuleIR, q as PolicySource, ay as PublishEffectsResult, f as PublishToolsResult, a0 as QuotaLineItemFilter, Z as QuotaPeriod, Y as QuotaScopeType, _ as QuotaStatus, bN as RPCRequest, bQ as RPCRequestFromServer, bO as RPCResponse, ca as RecordImport, c9 as RecordImportItem, c7 as RecordImportItemStatus, c5 as RecordImportOptions, c8 as RecordImportStats, c6 as RecordImportStatus, c4 as RecordImportWriteMode, bm as RecordManualActionInput, bz as RecordMentionInput, bW as RecordObjectOptions, c1 as RecordObjectResult, bX as RecordObjectStateValue, c2 as RecordObjectsChunkInfo, c3 as RecordObjectsOptions, m as RecordOpenAIUsageSpendOptions, o as RecordOpenAIUsageSpendResult, by as RecordSearchOptions, bx as RecordSearchResult, B as RecordUserOptions, bU as RelationshipInfo, at as ResolvedEffectApprovalRequired, ar as ResolvedEffectDryRun, aq as ResolvedEffectPostCondition, as as ResolvedEffectReverse, cd as RunEnvironmentImporterOptions, a3 as Sandbox, a5 as SandboxListResponse, ap as SemanticVersionDiff, ao as SemanticVersionDiffEntry, bc as SessionArtifactApprovalOptions, b6 as SessionArtifactAutonomyPolicy, bb as SessionArtifactExecutionOptions, ba as SessionArtifactExecutionResult, b5 as SessionArtifactKind, b8 as SessionArtifactListOptions, b7 as SessionArtifactRecord, b4 as SessionArtifactStatus, b9 as SessionArtifactValidationResult, bB as SessionCollectionListOptions, bD as SessionCollectionListResult, a_ as SessionConversationMessage, bA as SessionDocumentResult, b1 as SessionFileKind, b3 as SessionFileRecord, b0 as SessionFileSource, b2 as SessionFileStatus, bs as SessionFileUploadOptions, bu as SessionHeapFieldType, bv as SessionHeapFieldValue, bw as SessionHeapVariable, bC as SessionJobListOptions, bt as SessionJobRecord, a$ as SessionTimelineEvent, X as SpendLineItemType, $ as SpendSummary, cP as StreamEvent, cR as StreamStats, cQ as StreamSubscription, F as Subject, bP as SyncMessage, g as ToolHandler, aA as ToolInfo, bR as ToolInvokeParams, bS as ToolResultParams, e as ToolSchema, aC as ToolsChangedEvent, U as User, bF as UserEnvironmentMessagePreview, bE as UserEnvironmentPrompt, bG as UserEnvironmentSessionState, bH as UserEnvironmentState, bI as UserEnvironmentStateOptions, am as Version, ae as VersionTag, ad as VersionTracking, bM as WSClientOptions, bK as WSDisconnectInfo, bL as WSReconnectErrorInfo, p as buildOpenAISpendEventId, k as calculateOpenAITokenSpend, j as getOpenAIModelPricing, n as normalizeOpenAIUsage, r as recordOpenAIUsageSpend, t as toGranularHttpBase } from './spend-DpRRCrAr.js';
1
+ export { E as Environment, a as EnvironmentSession, G as Granular, O as OntologyHandle, S as Session, W as WSClient } from './client-UdGt44dF.js';
2
+ import { E as EndpointMode, T as ToolWithHandler, a as EffectHandlerContext, M as ManifestEffectMetamodelSpec, R as ResolvedEffectBehaviors, S as SessionHeapEntry, b as SessionHeapList, c as SessionHeapSnapshot, P as Prompt, d as SessionTranscriptEntry } from './spend-czRX7l0X.js';
3
+ export { cN as APIError, A as AccessTokenProvider, J as AdoptEnvironmentOptions, bg as ArtifactApprovalDecisionInput, bh as ArtifactApprovalDecisionResult, be as ArtifactApprovalTask, bf as ArtifactApprovalTaskListOptions, bd as ArtifactApprovalTaskStatus, aa as Assignment, ab as AssignmentListResponse, al as Build, an as BuildListResponse, ac as BuildPolicy, ak as BuildStatus, C as ConditionIR, K as ConnectOptions, aV as ConversationActionSuggestion, aZ as ConversationAppendResult, aW as ConversationMessageAction, aY as ConversationMessageInput, aX as ConversationMessagePart, aP as ConversationMessageShowRefs, Q as ConversationSessionInfo, W as ConversationSessionListOptions, V as ConversationSessionListStatus, aQ as ConversationTableCell, aR as ConversationTableColumn, aU as ConversationTableProjection, aT as ConversationTableRow, aS as ConversationTableRowReference, ag as CreateEnvironmentData, a8 as CreatePermissionProfileData, a4 as CreateSandboxData, L as CreateSessionOptions, bV as DefineRelationshipOptions, cO as DeleteResponse, D as DomainState, aE as EffectHandler, aB as EffectInfo, av as EffectInvocationMetadata, au as EffectInvocationMode, aw as EffectSchema, az as EffectVersionSelector, ax as EffectWithHandler, aD as EffectsChangedEvent, af as EnvironmentData, aM as EnvironmentFeedbackRecord, ci as EnvironmentImporter, ch as EnvironmentImporterImportOptions, ah as EnvironmentListResponse, cb as EnvironmentRecordImportSummary, cg as EnvironmentSetupImporterClaim, ce as EnvironmentSetupLifecycleStatus, cf as EnvironmentSetupSummary, cc as EnvironmentSetupTriggerReason, b$ as EnvironmentStateMachineProxy, bZ as EnvironmentStateObservationInput, c0 as EnvironmentStateProxy, bY as EnvironmentStateTarget, b_ as EnvironmentStateUpdateInput, z as GranularAuth, y as GranularOptions, a1 as GranularQuotaPolicy, a2 as GranularQuotaProgress, G as GranularSpendContext, cM as GraphQLResult, aF as InstanceEffectHandler, I as InstanceToolHandler, aO as Job, aK as JobFeedbackInput, aJ as JobFeedbackMetadata, aL as JobFeedbackRecord, aH as JobFeedbackSentiment, aI as JobFeedbackToolCall, aG as JobStatus, aN as JobSubmitResult, ai as Manifest, cB as ManifestApprovalRequiredSpec, cL as ManifestContent, cC as ManifestCreatesSpec, cz as ManifestDryRunSpec, cF as ManifestEffectDeclaration, cE as ManifestEffectSchema, cl as ManifestEnumRuleSpec, cH as ManifestEventStreamDef, cG as ManifestEventTypeDef, cm as ManifestFilterBySpec, cJ as ManifestImport, aj as ManifestListResponse, cI as ManifestOperation, cy as ManifestPostConditionSpec, cj as ManifestPropertySpec, cD as ManifestRelationshipDef, cA as ManifestReverseSpec, cx as ManifestStateMachineSpec, co as ManifestStateMachineStateSpec, cw as ManifestStateMachineTransitionSpec, cq as ManifestStateTransitionActionSpec, cr as ManifestStateTransitionAssigneeSpec, cv as ManifestStateTransitionExpectedOutcomeSpec, cp as ManifestStateTransitionInputBinding, cu as ManifestStateTransitionPermissionSpec, cs as ManifestStateTransitionRelatedStateRequirementSpec, ct as ManifestStateTransitionRequirementsSpec, ck as ManifestValidationOperator, cn as ManifestValidationRuleSpec, cK as ManifestVolume, bp as ManualActionListOptions, bn as ManualActionOccurrence, bo as ManualActionRecordResult, bl as ManualActionRelatedRecord, bj as ManualActionSource, bi as ManualActionStatus, bq as ManualActionSuggestion, br as ManualActionSuggestionOptions, bk as ManualActionTarget, bJ as MarkUserEnvironmentReadOptions, x as MatchedPolicy, bT as ModelRef, N as NormalizedOpenAIUsage, i as OPENAI_MODEL_PRICING_USD_PER_MILLION, O as OpenAIModelPricing, h as OpenAITokenSpend, l as OpenAIUsageSpendEvent, H as OpenEnvironmentOptions, a7 as PermissionProfile, a9 as PermissionProfileListResponse, a6 as PermissionRules, u as PolicyOperator, v as PolicyOrigin, s as PolicyPredicateSource, w as PolicyRuleIR, q as PolicySource, ay as PublishEffectsResult, f as PublishToolsResult, a0 as QuotaLineItemFilter, Z as QuotaPeriod, Y as QuotaScopeType, _ as QuotaStatus, bN as RPCRequest, bQ as RPCRequestFromServer, bO as RPCResponse, ca as RecordImport, c9 as RecordImportItem, c7 as RecordImportItemStatus, c5 as RecordImportOptions, c8 as RecordImportStats, c6 as RecordImportStatus, c4 as RecordImportWriteMode, bm as RecordManualActionInput, bz as RecordMentionInput, bW as RecordObjectOptions, c1 as RecordObjectResult, bX as RecordObjectStateValue, c2 as RecordObjectsChunkInfo, c3 as RecordObjectsOptions, m as RecordOpenAIUsageSpendOptions, o as RecordOpenAIUsageSpendResult, by as RecordSearchOptions, bx as RecordSearchResult, B as RecordUserOptions, bU as RelationshipInfo, at as ResolvedEffectApprovalRequired, ar as ResolvedEffectDryRun, aq as ResolvedEffectPostCondition, as as ResolvedEffectReverse, cd as RunEnvironmentImporterOptions, a3 as Sandbox, a5 as SandboxListResponse, ap as SemanticVersionDiff, ao as SemanticVersionDiffEntry, bc as SessionArtifactApprovalOptions, b6 as SessionArtifactAutonomyPolicy, bb as SessionArtifactExecutionOptions, ba as SessionArtifactExecutionResult, b5 as SessionArtifactKind, b8 as SessionArtifactListOptions, b7 as SessionArtifactRecord, b4 as SessionArtifactStatus, b9 as SessionArtifactValidationResult, bB as SessionCollectionListOptions, bD as SessionCollectionListResult, a_ as SessionConversationMessage, bA as SessionDocumentResult, b1 as SessionFileKind, b3 as SessionFileRecord, b0 as SessionFileSource, b2 as SessionFileStatus, bs as SessionFileUploadOptions, bu as SessionHeapFieldType, bv as SessionHeapFieldValue, bw as SessionHeapVariable, bC as SessionJobListOptions, bt as SessionJobRecord, a$ as SessionTimelineEvent, X as SpendLineItemType, $ as SpendSummary, cP as StreamEvent, cR as StreamStats, cQ as StreamSubscription, F as Subject, bP as SyncMessage, g as ToolHandler, aA as ToolInfo, bR as ToolInvokeParams, bS as ToolResultParams, e as ToolSchema, aC as ToolsChangedEvent, U as User, bF as UserEnvironmentMessagePreview, bE as UserEnvironmentPrompt, bG as UserEnvironmentSessionState, bH as UserEnvironmentState, bI as UserEnvironmentStateOptions, am as Version, ae as VersionTag, ad as VersionTracking, bM as WSClientOptions, bK as WSDisconnectInfo, bL as WSReconnectErrorInfo, p as buildOpenAISpendEventId, k as calculateOpenAITokenSpend, j as getOpenAIModelPricing, n as normalizeOpenAIUsage, r as recordOpenAIUsageSpend, t as toGranularHttpBase } from './spend-czRX7l0X.js';
4
4
  export { BuildGranularAgentSystemPromptInput, GeneratedJobCodeIssue, GranularAgentExecutionCheckpoint, GranularAgentHeapSummaryOptions, GranularAgentManualActionMemorySuggestion, GranularAgentPromptCapabilities, GranularAgentReferentFocus, GranularAgentSessionContext, GranularAgentToolInfo, GranularAgentWorkflowFocus, GranularReasoningTraceChunkResult, GranularReasoningTraceOptions, HarnessContinuationDecision, HarnessControllerBudgets, HarnessProjectionOptions, HarnessPromptLike, HarnessRenderedContinuation, HarnessRenderedPrompt, HarnessTemplate, HarnessTemplateManifest, HarnessTemplateSelectionOptions, HarnessTemplateStatus, HarnessVerifierSnapshot, HarnessVerifierSnapshotInput, ReviewGeneratedJobCodeOptions, buildContinuationInstruction, buildContinuationInstructionFromTemplate, buildGranularAgentCheckpointBlock, buildGranularAgentDomainBlock, buildGranularAgentFileBlock, buildGranularAgentHeapBlock, buildGranularAgentLoopBlock, buildGranularAgentManualActionBlock, buildGranularAgentManualActionMemorySummary, buildGranularAgentReferentBlock, buildGranularAgentRuntimeImportsBlock, buildGranularAgentSessionBlock, buildGranularAgentSystemPrompt, buildGranularAgentSystemPromptFromTemplate, buildGranularAgentToolBlock, buildGranularAgentWorkflowBlock, consumeGranularReasoningOnlyChunk, consumeGranularReasoningTraceChunk, createHarnessVerifierSnapshot, evaluateContinuation, getCurrentClosureId, getDefaultHarnessTemplateId, getExclusivePromptTarget, hasOpenPrompt, hashHarnessTemplateValue, listHarnessTemplates, projectConversationReferentFocus, projectConversationReferentSummary, projectHeapSummary, projectLoopSummary, projectSessionFileSummary, projectWorkflowFocus, projectWorkflowSummary, renderContinuationInstructionFromTemplate, renderGranularAgentSystemPromptFromTemplate, resolveHarnessTemplate, reviewGeneratedJobCode, stripGranularReasoningTrace, validateHarnessTemplateManifest } from './agent-harness.js';
5
5
  import '@automerge/automerge';
6
6
  import '@automerge/automerge/slim';
package/dist/index.js CHANGED
@@ -16628,24 +16628,72 @@ var Granular = class _Granular {
16628
16628
  if (!tagName) {
16629
16629
  throw new Error(`${methodName}() requires \`tag\`.`);
16630
16630
  }
16631
- const user = await this.resolveConnectUser(options);
16632
- if (!Array.isArray(user.permissions) || user.permissions.length === 0) {
16631
+ const assignmentMode = options.assignmentMode ?? "ensure";
16632
+ if (assignmentMode !== "ensure" && assignmentMode !== "require-existing") {
16633
16633
  throw new Error(
16634
- `${methodName}() requires at least one permission so the SDK can ensure assignments for new users.`
16634
+ `${methodName}() received an unsupported assignmentMode: ${String(options.assignmentMode)}.`
16635
16635
  );
16636
16636
  }
16637
- const sandbox = await this.findOrCreateSandbox(ontology);
16638
- for (const profileName of user.permissions) {
16639
- const profileId = await this.ensurePermissionProfile(
16640
- sandbox.sandboxId,
16641
- profileName
16637
+ const requiredGranularId = options.granularId?.trim();
16638
+ if (assignmentMode === "require-existing" && (!requiredGranularId || options.userId || options.user)) {
16639
+ throw new Error(
16640
+ `${methodName}() with assignmentMode "require-existing" requires granularId and does not accept userId or user.`
16642
16641
  );
16643
- await this.ensureAssignment(
16644
- user.granularId,
16645
- sandbox.sandboxId,
16646
- profileId
16642
+ }
16643
+ const user = await this.resolveConnectUser(
16644
+ assignmentMode === "require-existing" ? { ...options, granularId: requiredGranularId } : options
16645
+ );
16646
+ let requiredPermissionProfileId = null;
16647
+ const sandbox = assignmentMode === "require-existing" ? { sandboxId: await this._resolveSandboxId(ontology) } : await this.findOrCreateSandbox(ontology);
16648
+ if (assignmentMode === "require-existing") {
16649
+ const assignments = await this.subjects.listAssignments(user.granularId);
16650
+ const assignment = assignments.items.find(
16651
+ (item) => item.sandboxId === sandbox.sandboxId
16647
16652
  );
16653
+ if (!assignment) {
16654
+ throw new Error(
16655
+ `${methodName}() requires an existing assignment for subject ${user.granularId} in ontology ${sandbox.sandboxId}.`
16656
+ );
16657
+ }
16658
+ const assignedPermissionProfileId = assignment.permissionProfileId?.trim();
16659
+ if (!assignedPermissionProfileId) {
16660
+ throw new Error(
16661
+ `${methodName}() found an invalid assignment without a permission profile for subject ${user.granularId} in ontology ${sandbox.sandboxId}.`
16662
+ );
16663
+ }
16664
+ const expectedPermissionProfileId = options.expectedPermissionProfileId?.trim();
16665
+ if (expectedPermissionProfileId && assignedPermissionProfileId !== expectedPermissionProfileId) {
16666
+ throw new Error(
16667
+ `${methodName}() assignment mismatch for subject ${user.granularId}: expected permission profile ${expectedPermissionProfileId}, received ${assignedPermissionProfileId}.`
16668
+ );
16669
+ }
16670
+ requiredPermissionProfileId = assignedPermissionProfileId;
16671
+ } else {
16672
+ if (!Array.isArray(user.permissions) || user.permissions.length === 0) {
16673
+ throw new Error(
16674
+ `${methodName}() requires at least one permission so the SDK can ensure assignments for new users.`
16675
+ );
16676
+ }
16677
+ for (const profileName of user.permissions) {
16678
+ const profileId = await this.ensurePermissionProfile(
16679
+ sandbox.sandboxId,
16680
+ profileName
16681
+ );
16682
+ await this.ensureAssignment(
16683
+ user.granularId,
16684
+ sandbox.sandboxId,
16685
+ profileId
16686
+ );
16687
+ }
16648
16688
  }
16689
+ const requireMatchingEnvironmentProfile = (environment2) => {
16690
+ if (requiredPermissionProfileId && environment2.permissionProfileId !== requiredPermissionProfileId) {
16691
+ throw new Error(
16692
+ `${methodName}() resolved environment ${environment2.environmentId} with permission profile ${environment2.permissionProfileId || "none"}; current assignment requires ${requiredPermissionProfileId}.`
16693
+ );
16694
+ }
16695
+ return environment2;
16696
+ };
16649
16697
  const tags = await this.request(
16650
16698
  `/control/sandboxes/${sandbox.sandboxId}/tags`
16651
16699
  );
@@ -16668,6 +16716,9 @@ var Granular = class _Granular {
16668
16716
  const resolveActive = async (operationKey) => {
16669
16717
  const query = new URLSearchParams({ tagId: tag.tagId, slot });
16670
16718
  if (operationKey) query.set("operationKey", operationKey);
16719
+ if (requiredPermissionProfileId) {
16720
+ query.set("expectedPermissionProfileId", requiredPermissionProfileId);
16721
+ }
16671
16722
  try {
16672
16723
  const payload = await this.request(
16673
16724
  `/control/sandboxes/${encodeURIComponent(sandbox.sandboxId)}/subjects/${encodeURIComponent(user.granularId)}/active-environment?${query.toString()}`
@@ -16691,7 +16742,8 @@ var Granular = class _Granular {
16691
16742
  tagId: tag.tagId,
16692
16743
  slot,
16693
16744
  operationKey: resetKey,
16694
- operation: resetKey ? "explicit_reset" : void 0
16745
+ operation: resetKey ? "explicit_reset" : void 0,
16746
+ expectedPermissionProfileId: requiredPermissionProfileId || void 0
16695
16747
  })
16696
16748
  }
16697
16749
  );
@@ -16701,7 +16753,7 @@ var Granular = class _Granular {
16701
16753
  const resetEnvironment = await resolveActive(resetKey);
16702
16754
  if (resetEnvironment) {
16703
16755
  return {
16704
- environment: resetEnvironment,
16756
+ environment: requireMatchingEnvironmentProfile(resetEnvironment),
16705
16757
  requestedOntology: ontology,
16706
16758
  sandboxId: sandbox.sandboxId,
16707
16759
  subjectId: user.granularId,
@@ -16717,7 +16769,7 @@ var Granular = class _Granular {
16717
16769
  const active = await resolveActive();
16718
16770
  if (active && (active.versionId === targetVersionId || options.createFreshIfOutdated !== true)) {
16719
16771
  return {
16720
- environment: active,
16772
+ environment: requireMatchingEnvironmentProfile(active),
16721
16773
  requestedOntology: ontology,
16722
16774
  sandboxId: sandbox.sandboxId,
16723
16775
  subjectId: user.granularId,
@@ -16735,7 +16787,10 @@ var Granular = class _Granular {
16735
16787
  )
16736
16788
  );
16737
16789
  if (!resetKey && currentMatches.length > 0) {
16738
- const environment2 = await activate(currentMatches[0]);
16790
+ requireMatchingEnvironmentProfile(currentMatches[0]);
16791
+ const environment2 = requireMatchingEnvironmentProfile(
16792
+ await activate(currentMatches[0])
16793
+ );
16739
16794
  return {
16740
16795
  environment: environment2,
16741
16796
  requestedOntology: ontology,
@@ -16748,7 +16803,10 @@ var Granular = class _Granular {
16748
16803
  userEnvironments.filter((environment2) => environment2.tagId === tag.tagId)
16749
16804
  );
16750
16805
  if (outdatedMatches.length > 0 && options.createFreshIfOutdated !== true) {
16751
- const environment2 = await activate(outdatedMatches[0]);
16806
+ requireMatchingEnvironmentProfile(outdatedMatches[0]);
16807
+ const environment2 = requireMatchingEnvironmentProfile(
16808
+ await activate(outdatedMatches[0])
16809
+ );
16752
16810
  return {
16753
16811
  environment: environment2,
16754
16812
  requestedOntology: ontology,
@@ -16767,7 +16825,10 @@ var Granular = class _Granular {
16767
16825
  tagId: tag.tagId,
16768
16826
  permissionProfileId: null
16769
16827
  });
16770
- const environment = await activate(created);
16828
+ requireMatchingEnvironmentProfile(created);
16829
+ const environment = requireMatchingEnvironmentProfile(
16830
+ await activate(created)
16831
+ );
16771
16832
  return {
16772
16833
  environment,
16773
16834
  requestedOntology: ontology,
@@ -16977,22 +17038,16 @@ var Granular = class _Granular {
16977
17038
  metadata: options?.metadata
16978
17039
  });
16979
17040
  }
16980
- /**
16981
- * Mark a session closed in the control plane. If `environment` is the connected handle for that
16982
- * `sessionId`, disconnects the WebSocket so the runtime tears down cleanly.
16983
- */
17041
+ /** End a session through the runtime, or disconnect its connected handle. */
16984
17042
  async closeSession(sessionId, environment) {
16985
17043
  if (environment && environment.sessionId === sessionId) {
16986
17044
  await environment.disconnect();
16987
17045
  return;
16988
17046
  }
16989
- await this.request(`/control/sessions/${encodeURIComponent(sessionId)}`, {
16990
- method: "PATCH",
16991
- body: JSON.stringify({
16992
- status: "closed",
16993
- lastSeenAt: (/* @__PURE__ */ new Date()).toISOString()
16994
- })
16995
- });
17047
+ await this.request(
17048
+ `/control/sessions/${encodeURIComponent(sessionId)}/close`,
17049
+ { method: "POST" }
17050
+ );
16996
17051
  }
16997
17052
  /**
16998
17053
  * Re-open a closed session in the index and connect to its existing runtime document.