@granular-software/sdk 0.4.6 → 0.4.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.mjs CHANGED
@@ -4474,6 +4474,18 @@ var Session = class {
4474
4474
  this.setupEventHandlers();
4475
4475
  this.setupToolInvokeHandler();
4476
4476
  }
4477
+ extractDomainRevisionFromDoc(doc) {
4478
+ const domain = doc?.domain;
4479
+ const active = domain?.active;
4480
+ if (typeof active === "string" && active.trim()) {
4481
+ return active;
4482
+ }
4483
+ const nestedRevision = active?.domainRevision;
4484
+ if (typeof nestedRevision === "string" && nestedRevision.trim()) {
4485
+ return nestedRevision;
4486
+ }
4487
+ return null;
4488
+ }
4477
4489
  buildLegacyEffectContext() {
4478
4490
  return {
4479
4491
  effectClientId: this.clientId,
@@ -4481,6 +4493,8 @@ var Session = class {
4481
4493
  environmentId: "",
4482
4494
  sessionId: "",
4483
4495
  user: {
4496
+ granularId: "",
4497
+ userId: "",
4484
4498
  subjectId: ""
4485
4499
  }
4486
4500
  };
@@ -4566,7 +4580,14 @@ var Session = class {
4566
4580
  * execute locally and return the result to the sandbox.
4567
4581
  */
4568
4582
  async submitJob(code, domainRevision) {
4569
- const revision = domainRevision || this.currentDomainRevision || this.client.doc?.domain?.active || void 0;
4583
+ let revision = domainRevision || this.currentDomainRevision || this.extractDomainRevisionFromDoc(this.client.doc) || void 0;
4584
+ if (!revision) {
4585
+ try {
4586
+ const summary = await this.getDomain();
4587
+ revision = summary.activeDomainRevision || this.extractDomainRevisionFromDoc(this.client.doc) || void 0;
4588
+ } catch {
4589
+ }
4590
+ }
4570
4591
  if (!revision) {
4571
4592
  throw new Error("No domain revision available. Register live effects or ensure the build schema is activated.");
4572
4593
  }
@@ -4691,7 +4712,13 @@ var Session = class {
4691
4712
  * Get the current domain state and available tools
4692
4713
  */
4693
4714
  async getDomain() {
4694
- return this.client.call("domain.getSummary", {});
4715
+ const summary = await this.client.call("domain.getSummary", {});
4716
+ if (summary.activeDomainRevision) {
4717
+ this.currentDomainRevision = summary.activeDomainRevision;
4718
+ } else {
4719
+ this.currentDomainRevision = this.extractDomainRevisionFromDoc(this.client.doc);
4720
+ }
4721
+ return summary;
4695
4722
  }
4696
4723
  /**
4697
4724
  * Fetch a domain package part from the backend (no fallback).
@@ -4909,6 +4936,7 @@ import { ${allImports} } from "./sandbox-tools";
4909
4936
  }
4910
4937
  setupEventHandlers() {
4911
4938
  this.client.on("sync", (doc) => {
4939
+ this.currentDomainRevision = this.extractDomainRevisionFromDoc(doc);
4912
4940
  this.emit("sync", doc);
4913
4941
  this.checkForToolChanges();
4914
4942
  });
@@ -5175,6 +5203,29 @@ function normalizeHeapSnapshot(raw) {
5175
5203
  updatedAt: typeof heap.updatedAt === "number" ? heap.updatedAt : Date.now()
5176
5204
  };
5177
5205
  }
5206
+ function normalizeSubject(subject) {
5207
+ const granularId = subject.granularId || subject.subjectId;
5208
+ const userId = subject.userId || subject.identityId || granularId;
5209
+ return {
5210
+ ...subject,
5211
+ granularId,
5212
+ userId,
5213
+ subjectId: granularId,
5214
+ identityId: subject.identityId || userId
5215
+ };
5216
+ }
5217
+ function normalizeUser(user) {
5218
+ const granularId = user.granularId || user.subjectId;
5219
+ const userId = user.userId || user.identityId || granularId;
5220
+ return {
5221
+ ...user,
5222
+ granularId,
5223
+ userId,
5224
+ subjectId: granularId,
5225
+ identityId: user.identityId || userId,
5226
+ permissions: Array.isArray(user.permissions) ? user.permissions : []
5227
+ };
5228
+ }
5178
5229
  var Environment = class _Environment extends Session {
5179
5230
  envData;
5180
5231
  _apiKey;
@@ -5197,6 +5248,10 @@ var Environment = class _Environment extends Session {
5197
5248
  get subjectId() {
5198
5249
  return this.envData.subjectId;
5199
5250
  }
5251
+ /** Internal Granular user identifier for this environment */
5252
+ get granularId() {
5253
+ return this.envData.subjectId;
5254
+ }
5200
5255
  /** The permission profile ID */
5201
5256
  get permissionProfileId() {
5202
5257
  return this.envData.permissionProfileId;
@@ -5994,7 +6049,7 @@ var Granular = class {
5994
6049
  * Records/upserts a user and prepares them for sandbox connections
5995
6050
  *
5996
6051
  * @param options - User options
5997
- * @returns The user object to pass to connect()
6052
+ * @returns The recorded user with both `userId` and `granularId`
5998
6053
  *
5999
6054
  * @example
6000
6055
  * ```typescript
@@ -6006,21 +6061,61 @@ var Granular = class {
6006
6061
  * ```
6007
6062
  */
6008
6063
  async recordUser(options) {
6009
- const subject = await this.request("/control/subjects", {
6064
+ const subject = normalizeSubject(await this.request("/control/subjects", {
6010
6065
  method: "POST",
6011
6066
  body: JSON.stringify({
6012
6067
  identityId: options.userId,
6013
6068
  name: options.name,
6014
6069
  email: options.email
6015
6070
  })
6016
- });
6017
- return {
6071
+ }));
6072
+ return normalizeUser({
6073
+ granularId: subject.granularId,
6074
+ userId: options.userId,
6018
6075
  subjectId: subject.subjectId,
6019
- identityId: options.userId,
6020
- name: options.name,
6021
- email: options.email,
6076
+ identityId: subject.identityId,
6077
+ name: options.name || subject.name || void 0,
6078
+ email: options.email || subject.email || void 0,
6022
6079
  permissions: options.permissions || []
6023
- };
6080
+ });
6081
+ }
6082
+ async resolveConnectUser(options) {
6083
+ if (options.user) {
6084
+ const user = normalizeUser(options.user);
6085
+ return {
6086
+ granularId: user.granularId,
6087
+ userId: user.userId,
6088
+ name: options.name || user.name,
6089
+ email: options.email || user.email,
6090
+ permissions: options.permissions || user.permissions
6091
+ };
6092
+ }
6093
+ if (options.userId) {
6094
+ const user = await this.recordUser({
6095
+ userId: options.userId,
6096
+ name: options.name,
6097
+ email: options.email,
6098
+ permissions: options.permissions
6099
+ });
6100
+ return {
6101
+ granularId: user.granularId,
6102
+ userId: user.userId,
6103
+ name: user.name,
6104
+ email: user.email,
6105
+ permissions: options.permissions || user.permissions
6106
+ };
6107
+ }
6108
+ if (options.granularId) {
6109
+ const subject = await this.subjects.get(options.granularId);
6110
+ return {
6111
+ granularId: subject.granularId,
6112
+ userId: subject.userId,
6113
+ name: options.name || subject.name || void 0,
6114
+ email: options.email || subject.email || void 0,
6115
+ permissions: options.permissions || []
6116
+ };
6117
+ }
6118
+ throw new Error("connect() requires either userId, granularId, or a user object returned by recordUser().");
6024
6119
  }
6025
6120
  /**
6026
6121
  * Connect to a sandbox and establish a real-time environment session.
@@ -6034,14 +6129,10 @@ var Granular = class {
6034
6129
  *
6035
6130
  * @example
6036
6131
  * ```typescript
6037
- * const user = await granular.recordUser({
6038
- * userId: 'user_123',
6039
- * permissions: ['agent'],
6040
- * });
6041
- *
6042
6132
  * const environment = await granular.connect({
6043
6133
  * sandbox: 'my-sandbox',
6044
- * user,
6134
+ * userId: 'user_123',
6135
+ * permissions: ['agent'],
6045
6136
  * });
6046
6137
  *
6047
6138
  * await granular.registerEffect('my-sandbox', {
@@ -6062,13 +6153,14 @@ var Granular = class {
6062
6153
  */
6063
6154
  async connect(options) {
6064
6155
  const clientId = options.clientId || `client_${Date.now()}`;
6156
+ const user = await this.resolveConnectUser(options);
6065
6157
  const sandbox = await this.findOrCreateSandbox(options.sandbox);
6066
- for (const profileName of options.user.permissions) {
6158
+ for (const profileName of user.permissions) {
6067
6159
  const profileId = await this.ensurePermissionProfile(sandbox.sandboxId, profileName);
6068
- await this.ensureAssignment(options.user.subjectId, sandbox.sandboxId, profileId);
6160
+ await this.ensureAssignment(user.granularId, sandbox.sandboxId, profileId);
6069
6161
  }
6070
6162
  const envData = await this.environments.create(sandbox.sandboxId, {
6071
- subjectId: options.user.subjectId,
6163
+ subjectId: user.granularId,
6072
6164
  permissionProfileId: null
6073
6165
  });
6074
6166
  await this.activateEnvironment(envData.environmentId);
@@ -6501,7 +6593,7 @@ var Granular = class {
6501
6593
  get subjects() {
6502
6594
  return {
6503
6595
  get: async (subjectId) => {
6504
- return this.request(`/control/subjects/${subjectId}`);
6596
+ return normalizeSubject(await this.request(`/control/subjects/${subjectId}`));
6505
6597
  },
6506
6598
  listAssignments: async (subjectId) => {
6507
6599
  return this.request(`/control/subjects/${subjectId}/assignments`);
@@ -6514,17 +6606,17 @@ var Granular = class {
6514
6606
  get users() {
6515
6607
  return {
6516
6608
  create: async (data) => {
6517
- return this.request("/control/subjects", {
6609
+ return normalizeSubject(await this.request("/control/subjects", {
6518
6610
  method: "POST",
6519
6611
  body: JSON.stringify({
6520
6612
  identityId: data.id,
6521
6613
  name: data.name,
6522
6614
  email: data.email
6523
6615
  })
6524
- });
6616
+ }));
6525
6617
  },
6526
6618
  get: async (id) => {
6527
- return this.request(`/control/subjects/${id}`);
6619
+ return normalizeSubject(await this.request(`/control/subjects/${id}`));
6528
6620
  }
6529
6621
  };
6530
6622
  }