@axiom-lattice/client-sdk 4.3.4 → 4.3.7

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.
Files changed (43) hide show
  1. package/dist/__tests__/project-rooms.test.js +0 -66
  2. package/dist/__tests__/project-rooms.test.js.map +1 -1
  3. package/dist/__tests__/room-events.test.d.ts +2 -0
  4. package/dist/__tests__/room-events.test.d.ts.map +1 -0
  5. package/dist/__tests__/room-events.test.js +144 -0
  6. package/dist/__tests__/room-events.test.js.map +1 -0
  7. package/dist/__tests__/workspace-rooms.test.d.ts +2 -0
  8. package/dist/__tests__/workspace-rooms.test.d.ts.map +1 -0
  9. package/dist/__tests__/workspace-rooms.test.js +116 -0
  10. package/dist/__tests__/workspace-rooms.test.js.map +1 -0
  11. package/dist/abstract-client.d.ts +38 -1
  12. package/dist/abstract-client.d.ts.map +1 -1
  13. package/dist/abstract-client.js +56 -0
  14. package/dist/abstract-client.js.map +1 -1
  15. package/dist/client.d.ts +4 -0
  16. package/dist/client.d.ts.map +1 -1
  17. package/dist/client.js +4 -0
  18. package/dist/client.js.map +1 -1
  19. package/dist/index.d.ts +211 -50
  20. package/dist/index.d.ts.map +1 -1
  21. package/dist/index.js +359 -183
  22. package/dist/index.js.map +1 -1
  23. package/dist/index.mjs +357 -183
  24. package/dist/index.mjs.map +1 -1
  25. package/dist/project-room-hydrators.d.ts +18 -0
  26. package/dist/project-room-hydrators.d.ts.map +1 -0
  27. package/dist/project-room-hydrators.js +95 -0
  28. package/dist/project-room-hydrators.js.map +1 -0
  29. package/dist/project-rooms.d.ts +4 -51
  30. package/dist/project-rooms.d.ts.map +1 -1
  31. package/dist/project-rooms.js +5 -178
  32. package/dist/project-rooms.js.map +1 -1
  33. package/dist/room-events.d.ts +108 -0
  34. package/dist/room-events.d.ts.map +1 -0
  35. package/dist/room-events.js +127 -0
  36. package/dist/room-events.js.map +1 -0
  37. package/dist/types.d.ts +35 -1
  38. package/dist/types.d.ts.map +1 -1
  39. package/dist/workspace-rooms.d.ts +28 -0
  40. package/dist/workspace-rooms.d.ts.map +1 -0
  41. package/dist/workspace-rooms.js +68 -0
  42. package/dist/workspace-rooms.js.map +1 -0
  43. package/package.json +2 -2
package/dist/index.mjs CHANGED
@@ -2132,6 +2132,52 @@ var AbstractClient = class {
2132
2132
  /**
2133
2133
  * A2A API keys namespace for managing A2A API keys
2134
2134
  */
2135
+ /** Open API surface helpers (capability catalog for the key picker). */
2136
+ this.open = {
2137
+ /**
2138
+ * Fetch the grantable capability catalog for the current tenant.
2139
+ * Drives the key-management grants picker.
2140
+ */
2141
+ catalog: async () => {
2142
+ const response = await this.makeRequest("/api/open/catalog");
2143
+ return response.data;
2144
+ },
2145
+ /**
2146
+ * Fetch what a key exposes (MCP tools + A2A agent cards).
2147
+ * @param id - Key identifier
2148
+ */
2149
+ exposure: async (id) => {
2150
+ const response = await this.makeRequest(`/api/keys/${id}/exposure`);
2151
+ return response.data;
2152
+ },
2153
+ /**
2154
+ * Query the tenant's Open audit log (newest first).
2155
+ * @param params - Optional credential/domain/status/time filters and pagination
2156
+ */
2157
+ auditLogs: async (params) => {
2158
+ const searchParams = new URLSearchParams();
2159
+ if (params?.credentialId)
2160
+ searchParams.set("credentialId", params.credentialId);
2161
+ if (params?.domain)
2162
+ searchParams.set("domain", params.domain);
2163
+ if (params?.status)
2164
+ searchParams.set("status", params.status);
2165
+ if (params?.from)
2166
+ searchParams.set("from", params.from);
2167
+ if (params?.to)
2168
+ searchParams.set("to", params.to);
2169
+ if (params?.limit !== void 0)
2170
+ searchParams.set("limit", String(params.limit));
2171
+ if (params?.offset !== void 0)
2172
+ searchParams.set("offset", String(params.offset));
2173
+ const qs = searchParams.toString();
2174
+ const response = await this.makeRequest(`/api/open/audit${qs ? `?${qs}` : ""}`);
2175
+ return response.data.records;
2176
+ }
2177
+ };
2178
+ /**
2179
+ * @deprecated Use {@link open} / `/api/keys`; kept as a compatibility alias.
2180
+ */
2135
2181
  this.a2aKeys = {
2136
2182
  /**
2137
2183
  * Lists A2A API keys, optionally filtered by tenant
@@ -2161,6 +2207,16 @@ var AbstractClient = class {
2161
2207
  const response = await this.makeRequest("/api/a2a/keys", { method: "POST", body: input });
2162
2208
  return response.data;
2163
2209
  },
2210
+ /**
2211
+ * Updates mutable fields (label, project, assistants, grants) of an existing key.
2212
+ * @param id - Key identifier
2213
+ * @param input - Fields to update (only provided fields change)
2214
+ * @returns A promise that resolves to the updated key record
2215
+ */
2216
+ update: async (id, input) => {
2217
+ const response = await this.makeRequest(`/api/a2a/keys/${id}`, { method: "PATCH", body: input });
2218
+ return response.data;
2219
+ },
2164
2220
  /**
2165
2221
  * Permanently deletes an A2A API key
2166
2222
  * @param id - Key identifier
@@ -2336,7 +2392,7 @@ var AbstractClient = class {
2336
2392
  const query = searchParams.toString();
2337
2393
  const response = await this.makeRequest(`/api/web-apps${query ? `?${query}` : ""}`);
2338
2394
  return {
2339
- records: response.data.records.map((record2) => this.hydrateAgentWebApp(record2)),
2395
+ records: response.data.records.map((record3) => this.hydrateAgentWebApp(record3)),
2340
2396
  total: response.data.total
2341
2397
  };
2342
2398
  },
@@ -2977,19 +3033,19 @@ var AbstractClient = class {
2977
3033
  if (!value || typeof value !== "object" || Array.isArray(value)) {
2978
3034
  throw new ApiError("Invalid Agent Web App response", 500, value);
2979
3035
  }
2980
- const record2 = value;
3036
+ const record3 = value;
2981
3037
  const hydrateDate = (field) => {
2982
- const raw = record2[field];
2983
- const date2 = raw instanceof Date ? new Date(raw.getTime()) : new Date(
3038
+ const raw = record3[field];
3039
+ const date3 = raw instanceof Date ? new Date(raw.getTime()) : new Date(
2984
3040
  typeof raw === "string" || typeof raw === "number" ? raw : Number.NaN
2985
3041
  );
2986
- if (Number.isNaN(date2.getTime())) {
3042
+ if (Number.isNaN(date3.getTime())) {
2987
3043
  throw new ApiError(`Invalid Agent Web App ${field}`, 500, value);
2988
3044
  }
2989
- return date2;
3045
+ return date3;
2990
3046
  };
2991
3047
  return {
2992
- ...record2,
3048
+ ...record3,
2993
3049
  createdAt: hydrateDate("createdAt"),
2994
3050
  updatedAt: hydrateDate("updatedAt")
2995
3051
  };
@@ -3429,115 +3485,7 @@ var ExportImportClient = class {
3429
3485
  }
3430
3486
  };
3431
3487
 
3432
- // src/sse-parser.ts
3433
- var SseParseError = class extends Error {
3434
- constructor(message) {
3435
- super(message);
3436
- this.code = "INVALID_EVENT";
3437
- this.name = "SseParseError";
3438
- }
3439
- };
3440
- async function* parseSseBody(body, options = {}) {
3441
- const reader = body.getReader();
3442
- const decoder = new TextDecoder();
3443
- let buffer = "";
3444
- let event = "";
3445
- let id;
3446
- let retry;
3447
- let data = [];
3448
- const dispatch = () => {
3449
- if (data.length === 0) {
3450
- event = "";
3451
- id = void 0;
3452
- retry = void 0;
3453
- return void 0;
3454
- }
3455
- let parsed;
3456
- try {
3457
- parsed = JSON.parse(data.join("\n"));
3458
- } catch {
3459
- throw new SseParseError("Invalid SSE JSON");
3460
- }
3461
- if (options.strictJsonObject && (typeof parsed !== "object" || parsed === null || Array.isArray(parsed)))
3462
- throw new SseParseError("SSE data must be an object");
3463
- const result = { event, data: parsed, ...id === void 0 ? {} : { id }, ...retry === void 0 ? {} : { retry } };
3464
- event = "";
3465
- id = void 0;
3466
- retry = void 0;
3467
- data = [];
3468
- return result;
3469
- };
3470
- const processLine = (raw) => {
3471
- const line = raw.endsWith("\r") ? raw.slice(0, -1) : raw;
3472
- if (line === "")
3473
- return dispatch();
3474
- if (line.startsWith(":"))
3475
- return void 0;
3476
- const separator = line.indexOf(":");
3477
- const field = separator < 0 ? line : line.slice(0, separator);
3478
- let value = separator < 0 ? "" : line.slice(separator + 1);
3479
- if (value.startsWith(" "))
3480
- value = value.slice(1);
3481
- if (field === "event")
3482
- event = value;
3483
- else if (field === "data")
3484
- data.push(value);
3485
- else if (field === "id")
3486
- id = value;
3487
- else if (field === "retry") {
3488
- const parsed = Number(value);
3489
- if (!Number.isInteger(parsed) || parsed < 0 || !Number.isFinite(parsed))
3490
- throw new SseParseError("Invalid SSE retry");
3491
- retry = parsed;
3492
- }
3493
- return void 0;
3494
- };
3495
- try {
3496
- while (true) {
3497
- const chunk = await reader.read();
3498
- if (chunk.done) {
3499
- buffer += decoder.decode();
3500
- break;
3501
- }
3502
- buffer += decoder.decode(chunk.value, { stream: true });
3503
- let index = findLineBreak(buffer);
3504
- while (index >= 0) {
3505
- if (buffer[index] === "\r" && index === buffer.length - 1)
3506
- break;
3507
- const frame2 = processLine(buffer.slice(0, index));
3508
- buffer = buffer.slice(index + lineBreakLength(buffer, index));
3509
- if (frame2)
3510
- yield frame2;
3511
- index = findLineBreak(buffer);
3512
- }
3513
- }
3514
- if (buffer) {
3515
- const frame2 = processLine(buffer);
3516
- if (frame2)
3517
- yield frame2;
3518
- }
3519
- const frame = processLine("");
3520
- if (frame)
3521
- yield frame;
3522
- } finally {
3523
- await reader.cancel().catch(() => void 0);
3524
- reader.releaseLock();
3525
- }
3526
- }
3527
- function findLineBreak(value) {
3528
- const lf = value.indexOf("\n");
3529
- const cr = value.indexOf("\r");
3530
- if (lf < 0)
3531
- return cr;
3532
- if (cr < 0)
3533
- return lf;
3534
- return Math.min(lf, cr);
3535
- }
3536
- function lineBreakLength(value, index) {
3537
- return value[index] === "\r" && value[index + 1] === "\n" ? 2 : 1;
3538
- }
3539
-
3540
- // src/project-rooms.ts
3488
+ // src/project-room-hydrators.ts
3541
3489
  var ProjectRoomClientError = class extends Error {
3542
3490
  constructor(message, status, code, retryable, details) {
3543
3491
  super(message);
@@ -3555,10 +3503,10 @@ var date = (value, field) => {
3555
3503
  throw new ProjectRoomClientError(`Invalid ${field}`, 500, "INVALID_RESPONSE", false);
3556
3504
  return result;
3557
3505
  };
3558
- var requiredString = (record2, field) => {
3559
- if (typeof record2[field] !== "string")
3506
+ var requiredString = (record3, field) => {
3507
+ if (typeof record3[field] !== "string")
3560
3508
  throw new ProjectRoomClientError(`Invalid ${field}`, 500, "INVALID_RESPONSE", false);
3561
- return record2[field];
3509
+ return record3[field];
3562
3510
  };
3563
3511
  var oneOf = (value, values, field) => {
3564
3512
  if (typeof value !== "string" || !values.includes(value))
@@ -3621,21 +3569,31 @@ var hydrateMessage = (value) => {
3621
3569
  };
3622
3570
  var hydrateMember = (value) => {
3623
3571
  const row = record(value);
3624
- exactKeys(row, ["id", "tenantId", "projectId", "userId", "role", "status", "joinedAt", "updatedAt"]);
3625
- return { id: requiredString(row, "id"), tenantId: requiredString(row, "tenantId"), projectId: requiredString(row, "projectId"), userId: requiredString(row, "userId"), role: oneOf(row.role, humanRoles, "role"), status: oneOf(row.status, memberStatuses, "status"), joinedAt: date(row.joinedAt, "joinedAt"), updatedAt: date(row.updatedAt, "updatedAt") };
3572
+ exactKeys(row, ["id", "tenantId", "projectId", "userId", "role", "status", "joinedAt", "updatedAt"], ["name"]);
3573
+ return { id: requiredString(row, "id"), tenantId: requiredString(row, "tenantId"), projectId: requiredString(row, "projectId"), userId: requiredString(row, "userId"), ...row.name === void 0 ? {} : { name: requiredString(row, "name") }, role: oneOf(row.role, humanRoles, "role"), status: oneOf(row.status, memberStatuses, "status"), joinedAt: date(row.joinedAt, "joinedAt"), updatedAt: date(row.updatedAt, "updatedAt") };
3626
3574
  };
3627
3575
  var hydrateBot = (value) => {
3628
3576
  const row = record(value);
3629
3577
  exactKeys(row, ["id", "tenantId", "workspaceId", "projectId", "roomId", "assistantId", "role", "title", "mentionName", "status", "roomThreadId", "joinedAt", "updatedAt"], ["responsibility"]);
3630
3578
  return { id: requiredString(row, "id"), tenantId: requiredString(row, "tenantId"), workspaceId: requiredString(row, "workspaceId"), projectId: requiredString(row, "projectId"), roomId: requiredString(row, "roomId"), assistantId: requiredString(row, "assistantId"), role: oneOf(row.role, botRoles, "role"), title: requiredString(row, "title"), ...row.responsibility === void 0 ? {} : { responsibility: requiredString(row, "responsibility") }, mentionName: requiredString(row, "mentionName"), status: oneOf(row.status, botStatuses, "status"), roomThreadId: requiredString(row, "roomThreadId"), joinedAt: date(row.joinedAt, "joinedAt"), updatedAt: date(row.updatedAt, "updatedAt") };
3631
3579
  };
3632
- var iso = (value) => date(value, "date").toISOString();
3633
3580
  var hydrateDispatch = (value) => {
3634
3581
  const row = record(value);
3635
3582
  if (typeof row.success !== "boolean" || row.membershipId !== void 0 && typeof row.membershipId !== "string" || row.errorCode !== void 0 && typeof row.errorCode !== "string")
3636
3583
  throw new ProjectRoomClientError("Invalid dispatch response", 500, "INVALID_RESPONSE", false);
3637
3584
  return { success: row.success, ...row.membershipId === void 0 ? {} : { membershipId: row.membershipId }, ...row.errorCode === void 0 ? {} : { errorCode: row.errorCode } };
3638
3585
  };
3586
+ function hydratePublicMember(value) {
3587
+ const row = record(value);
3588
+ return { id: requiredString(row, "id"), userId: requiredString(row, "userId"), role: row.role, status: row.status, joinedAt: date(row.joinedAt, "joinedAt"), updatedAt: date(row.updatedAt, "updatedAt") };
3589
+ }
3590
+ function hydratePublicBot(value) {
3591
+ const row = record(value);
3592
+ return { id: requiredString(row, "id"), role: row.role, title: requiredString(row, "title"), ...row.responsibility === void 0 ? {} : { responsibility: row.responsibility }, mentionName: requiredString(row, "mentionName"), status: row.status, joinedAt: date(row.joinedAt, "joinedAt"), updatedAt: date(row.updatedAt, "updatedAt") };
3593
+ }
3594
+
3595
+ // src/project-rooms.ts
3596
+ var iso = (value) => date(value, "date").toISOString();
3639
3597
  var encode = encodeURIComponent;
3640
3598
  var ProjectRoomsClient = class {
3641
3599
  constructor(baseURL, getHeaders) {
@@ -3666,6 +3624,9 @@ var ProjectRoomsClient = class {
3666
3624
  if (!Array.isArray(result))
3667
3625
  throw new ProjectRoomClientError("Invalid retry response", 500, "INVALID_RESPONSE", false);
3668
3626
  return result.map(hydrateDispatch);
3627
+ },
3628
+ markRead: async (projectId) => {
3629
+ await this.request(`/api/projects/${encode(projectId)}/room/read-state`, { method: "POST", body: {} });
3669
3630
  }
3670
3631
  };
3671
3632
  this.members = {
@@ -3682,14 +3643,10 @@ var ProjectRoomsClient = class {
3682
3643
  resume: async (projectId, membershipId, input) => hydrateBot(await this.request(`/api/projects/${encode(projectId)}/bots/${encode(membershipId)}/resume`, { method: "POST", body: { expectedUpdatedAt: iso(input.expectedUpdatedAt) } })),
3683
3644
  remove: async (projectId, membershipId, input) => this.request(`/api/projects/${encode(projectId)}/bots/${encode(membershipId)}?expectedUpdatedAt=${encode(iso(input.expectedUpdatedAt))}`, { method: "DELETE" })
3684
3645
  };
3685
- this.events = { connect: (projectId, options) => this.connect(projectId, options) };
3686
3646
  }
3687
3647
  async getRoom(projectId) {
3688
3648
  return hydrateRoom(await this.request(`/api/projects/${encode(projectId)}/room`));
3689
3649
  }
3690
- async getRealtimeMode(projectId) {
3691
- return this.request(`/api/projects/${encode(projectId)}/room/realtime-mode`);
3692
- }
3693
3650
  async records(path, hydrate) {
3694
3651
  const result = await this.request(path);
3695
3652
  if (!Array.isArray(result))
@@ -3709,25 +3666,286 @@ var ProjectRoomsClient = class {
3709
3666
  throw new ProjectRoomClientError("Missing response data", 500, "INVALID_RESPONSE", false);
3710
3667
  return payload.data;
3711
3668
  }
3712
- connect(projectId, options) {
3713
- const headers = { ...this.getHeaders(), Accept: "text/event-stream", ...options.lastEventId ? { "Last-Event-ID": options.lastEventId } : {} };
3669
+ };
3670
+
3671
+ // src/workspace-rooms.ts
3672
+ var isRecord2 = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
3673
+ var record2 = (value) => {
3674
+ if (!isRecord2(value))
3675
+ throw new ProjectRoomClientError("Invalid workspace rooms response", 500, "INVALID_RESPONSE", false);
3676
+ return value;
3677
+ };
3678
+ var requiredString2 = (row, field) => {
3679
+ if (typeof row[field] !== "string")
3680
+ throw new ProjectRoomClientError(`Invalid ${field}`, 500, "INVALID_RESPONSE", false);
3681
+ return row[field];
3682
+ };
3683
+ var date2 = (value, field) => {
3684
+ const result = value instanceof Date ? new Date(value.getTime()) : new Date(typeof value === "string" ? value : Number.NaN);
3685
+ if (!Number.isFinite(result.getTime()))
3686
+ throw new ProjectRoomClientError(`Invalid ${field}`, 500, "INVALID_RESPONSE", false);
3687
+ return result;
3688
+ };
3689
+ var hydrateProject = (value) => {
3690
+ const row = record2(value);
3691
+ return {
3692
+ id: requiredString2(row, "id"),
3693
+ tenantId: requiredString2(row, "tenantId"),
3694
+ workspaceId: requiredString2(row, "workspaceId"),
3695
+ name: requiredString2(row, "name"),
3696
+ ...row.description === void 0 ? {} : { description: requiredString2(row, "description") },
3697
+ ...row.config === void 0 ? {} : { config: row.config },
3698
+ ...row.kind === void 0 ? {} : { kind: requiredString2(row, "kind") },
3699
+ createdAt: date2(row.createdAt, "createdAt"),
3700
+ updatedAt: date2(row.updatedAt, "updatedAt")
3701
+ };
3702
+ };
3703
+ var hydrateEntry = (value) => {
3704
+ const row = record2(value);
3705
+ const names = row.participantNames;
3706
+ if (!Array.isArray(names) || names.some((n) => typeof n !== "string"))
3707
+ throw new ProjectRoomClientError("Invalid participantNames", 500, "INVALID_RESPONSE", false);
3708
+ if (typeof row.participantCount !== "number" || typeof row.unreadCount !== "number")
3709
+ throw new ProjectRoomClientError("Invalid room entry counts", 500, "INVALID_RESPONSE", false);
3710
+ return {
3711
+ project: hydrateProject(row.project),
3712
+ room: hydrateRoom(row.room),
3713
+ ...row.lastMessage === void 0 ? {} : { lastMessage: hydrateMessage(row.lastMessage) },
3714
+ participantCount: row.participantCount,
3715
+ participantNames: names,
3716
+ ...row.displayName === void 0 ? {} : { displayName: requiredString2(row, "displayName") },
3717
+ ...row.isPublic === void 0 ? {} : { isPublic: row.isPublic === true },
3718
+ unreadCount: row.unreadCount
3719
+ };
3720
+ };
3721
+ var WorkspaceRoomsClient = class {
3722
+ constructor(baseURL, getHeaders) {
3723
+ this.baseURL = baseURL;
3724
+ this.getHeaders = getHeaders;
3725
+ }
3726
+ /** Lists the user's rooms in a workspace with last message and unread count. */
3727
+ async list(workspaceId) {
3728
+ const response = await fetch(`${this.baseURL}/api/workspaces/${encodeURIComponent(workspaceId)}/rooms`, { headers: this.getHeaders() });
3729
+ const payload = await response.json().catch(() => void 0);
3730
+ if (!response.ok || !payload?.success) {
3731
+ const error = payload?.error;
3732
+ throw new ProjectRoomClientError(typeof error?.message === "string" ? error.message : "Workspace rooms request failed", response.status, typeof error?.code === "string" ? error.code : response.ok ? "INVALID_RESPONSE" : "HTTP_ERROR", error?.retryable === true, error?.details);
3733
+ }
3734
+ if (!payload.data || !Array.isArray(payload.data.rooms))
3735
+ throw new ProjectRoomClientError("Invalid workspace rooms response", 500, "INVALID_RESPONSE", false);
3736
+ return payload.data.rooms.map(hydrateEntry);
3737
+ }
3738
+ };
3739
+
3740
+ // src/sse-parser.ts
3741
+ var SseParseError = class extends Error {
3742
+ constructor(message) {
3743
+ super(message);
3744
+ this.code = "INVALID_EVENT";
3745
+ this.name = "SseParseError";
3746
+ }
3747
+ };
3748
+ async function* parseSseBody(body, options = {}) {
3749
+ const reader = body.getReader();
3750
+ const decoder = new TextDecoder();
3751
+ let buffer = "";
3752
+ let event = "";
3753
+ let id;
3754
+ let retry;
3755
+ let data = [];
3756
+ const dispatch = () => {
3757
+ if (data.length === 0) {
3758
+ event = "";
3759
+ id = void 0;
3760
+ retry = void 0;
3761
+ return void 0;
3762
+ }
3763
+ let parsed;
3764
+ try {
3765
+ parsed = JSON.parse(data.join("\n"));
3766
+ } catch {
3767
+ throw new SseParseError("Invalid SSE JSON");
3768
+ }
3769
+ if (options.strictJsonObject && (typeof parsed !== "object" || parsed === null || Array.isArray(parsed)))
3770
+ throw new SseParseError("SSE data must be an object");
3771
+ const result = { event, data: parsed, ...id === void 0 ? {} : { id }, ...retry === void 0 ? {} : { retry } };
3772
+ event = "";
3773
+ id = void 0;
3774
+ retry = void 0;
3775
+ data = [];
3776
+ return result;
3777
+ };
3778
+ const processLine = (raw) => {
3779
+ const line = raw.endsWith("\r") ? raw.slice(0, -1) : raw;
3780
+ if (line === "")
3781
+ return dispatch();
3782
+ if (line.startsWith(":"))
3783
+ return void 0;
3784
+ const separator = line.indexOf(":");
3785
+ const field = separator < 0 ? line : line.slice(0, separator);
3786
+ let value = separator < 0 ? "" : line.slice(separator + 1);
3787
+ if (value.startsWith(" "))
3788
+ value = value.slice(1);
3789
+ if (field === "event")
3790
+ event = value;
3791
+ else if (field === "data")
3792
+ data.push(value);
3793
+ else if (field === "id")
3794
+ id = value;
3795
+ else if (field === "retry") {
3796
+ const parsed = Number(value);
3797
+ if (!Number.isInteger(parsed) || parsed < 0 || !Number.isFinite(parsed))
3798
+ throw new SseParseError("Invalid SSE retry");
3799
+ retry = parsed;
3800
+ }
3801
+ return void 0;
3802
+ };
3803
+ try {
3804
+ while (true) {
3805
+ const chunk = await reader.read();
3806
+ if (chunk.done) {
3807
+ buffer += decoder.decode();
3808
+ break;
3809
+ }
3810
+ buffer += decoder.decode(chunk.value, { stream: true });
3811
+ let index = findLineBreak(buffer);
3812
+ while (index >= 0) {
3813
+ if (buffer[index] === "\r" && index === buffer.length - 1)
3814
+ break;
3815
+ const frame2 = processLine(buffer.slice(0, index));
3816
+ buffer = buffer.slice(index + lineBreakLength(buffer, index));
3817
+ if (frame2)
3818
+ yield frame2;
3819
+ index = findLineBreak(buffer);
3820
+ }
3821
+ }
3822
+ if (buffer) {
3823
+ const frame2 = processLine(buffer);
3824
+ if (frame2)
3825
+ yield frame2;
3826
+ }
3827
+ const frame = processLine("");
3828
+ if (frame)
3829
+ yield frame;
3830
+ } finally {
3831
+ await reader.cancel().catch(() => void 0);
3832
+ reader.releaseLock();
3833
+ }
3834
+ }
3835
+ function findLineBreak(value) {
3836
+ const lf = value.indexOf("\n");
3837
+ const cr = value.indexOf("\r");
3838
+ if (lf < 0)
3839
+ return cr;
3840
+ if (cr < 0)
3841
+ return lf;
3842
+ return Math.min(lf, cr);
3843
+ }
3844
+ function lineBreakLength(value, index) {
3845
+ return value[index] === "\r" && value[index + 1] === "\n" ? 2 : 1;
3846
+ }
3847
+
3848
+ // src/room-events.ts
3849
+ var invalidFrame = (message) => new ProjectRoomClientError(message, 200, "INVALID_EVENT", false);
3850
+ var requiredString3 = (row, field) => {
3851
+ if (typeof row[field] !== "string")
3852
+ throw invalidFrame(`Invalid ${field}`);
3853
+ return row[field];
3854
+ };
3855
+ var oneOf2 = (value, values, field) => {
3856
+ if (typeof value !== "string" || !values.includes(value))
3857
+ throw invalidFrame(`Invalid ${field}`);
3858
+ return value;
3859
+ };
3860
+ var hydrateScope = (value) => {
3861
+ if (!isRecord(value))
3862
+ throw invalidFrame("Invalid scope");
3863
+ return { tenantId: requiredString3(value, "tenantId"), roomId: requiredString3(value, "roomId"), projectId: requiredString3(value, "projectId") };
3864
+ };
3865
+ var hydrateControl = (event, payload) => {
3866
+ if (event === "ready") {
3867
+ if (typeof payload.epoch !== "string" || payload.headEventId !== null && typeof payload.headEventId !== "string" || Object.keys(payload).some((key) => key !== "epoch" && key !== "headEventId"))
3868
+ throw invalidFrame("Invalid SSE control");
3869
+ return { type: "ready", data: { epoch: payload.epoch, headEventId: payload.headEventId } };
3870
+ }
3871
+ if (Object.keys(payload).some((key) => key !== "reason"))
3872
+ throw invalidFrame("Invalid SSE control");
3873
+ if (event === "resync")
3874
+ return { type: "resync", data: { reason: oneOf2(payload.reason, ["SERVER_RESTART", "CURSOR_EXPIRED", "SLOW_CONSUMER"], "reason") } };
3875
+ return { type: "access.revoked", data: { reason: oneOf2(payload.reason, ["PROJECT_ACCESS_REVOKED", "TOKEN_EXPIRED", "CONNECTION_SUPERSEDED"], "reason") } };
3876
+ };
3877
+ var ROOM_SCOPED_TYPES = ["message.created", "roster.changed", "membership.changed", "task.changed"];
3878
+ function hydrateWorkspaceFrame(raw) {
3879
+ const payload = isRecord(raw.data) ? raw.data : void 0;
3880
+ if (raw.event === "ready" || raw.event === "resync" || raw.event === "access.revoked") {
3881
+ if (!payload || Object.prototype.hasOwnProperty.call(payload, "type"))
3882
+ throw invalidFrame("Invalid SSE control");
3883
+ return hydrateControl(raw.event, payload);
3884
+ }
3885
+ if (typeof payload?.type !== "string" || payload.type !== raw.event || typeof payload.id !== "string" || raw.id !== payload.id)
3886
+ throw invalidFrame("Invalid SSE business event");
3887
+ const occurredAt = date(payload.occurredAt, "occurredAt");
3888
+ const scope = payload.scope === void 0 ? void 0 : hydrateScope(payload.scope);
3889
+ const roomScoped = ROOM_SCOPED_TYPES.includes(payload.type);
3890
+ if (roomScoped && scope === void 0)
3891
+ throw invalidFrame("Invalid SSE business event scope");
3892
+ const data = payload.data;
3893
+ if (payload.type === "message.created") {
3894
+ if (!isRecord(data))
3895
+ throw invalidFrame("Invalid SSE business event data");
3896
+ return { type: payload.type, id: payload.id, occurredAt, scope, data: { message: hydrateMessage(data.message) } };
3897
+ }
3898
+ if (payload.type === "roster.changed") {
3899
+ if (!isRecord(data))
3900
+ throw invalidFrame("Invalid SSE business event data");
3901
+ return { type: payload.type, id: payload.id, occurredAt, scope, data: { change: requiredString3(data, "change"), membership: hydratePublicBot(data.membership) } };
3902
+ }
3903
+ if (payload.type === "membership.changed") {
3904
+ if (!isRecord(data))
3905
+ throw invalidFrame("Invalid SSE business event data");
3906
+ return { type: payload.type, id: payload.id, occurredAt, scope, data: { change: requiredString3(data, "change"), membership: hydratePublicMember(data.membership) } };
3907
+ }
3908
+ if (payload.type === "task.changed") {
3909
+ if (!isRecord(data))
3910
+ throw invalidFrame("Invalid SSE business event data");
3911
+ return { type: payload.type, id: payload.id, occurredAt, scope, data: { taskId: requiredString3(data, "taskId"), status: requiredString3(data, "status"), ownerMembershipId: requiredString3(data, "ownerMembershipId"), updatedAt: date(data.updatedAt, "updatedAt") } };
3912
+ }
3913
+ if (payload.type === "read.changed") {
3914
+ if (!isRecord(data))
3915
+ throw invalidFrame("Invalid SSE business event data");
3916
+ return { type: payload.type, id: payload.id, occurredAt, data: { projectId: requiredString3(data, "projectId"), roomId: requiredString3(data, "roomId"), lastReadAt: date(data.lastReadAt, "lastReadAt") } };
3917
+ }
3918
+ if (payload.type === "membership.affected") {
3919
+ if (!isRecord(data))
3920
+ throw invalidFrame("Invalid SSE business event data");
3921
+ return { type: payload.type, id: payload.id, occurredAt, data: { change: oneOf2(data.change, ["added", "removed", "role_changed"], "change"), projectId: requiredString3(data, "projectId"), roomId: requiredString3(data, "roomId") } };
3922
+ }
3923
+ return { type: payload.type, id: payload.id, occurredAt, data: payload.data, ...scope === void 0 ? {} : { scope } };
3924
+ }
3925
+ var RoomEventsClient = class {
3926
+ constructor(baseURL, getHeaders) {
3927
+ this.baseURL = baseURL;
3928
+ this.getHeaders = getHeaders;
3929
+ }
3930
+ connect(workspaceId, options) {
3931
+ const headers = { ...this.getHeaders(), Accept: "text/event-stream" };
3714
3932
  let resolveOpen;
3715
3933
  let rejectOpen;
3716
3934
  const opened = new Promise((resolve, reject) => {
3717
3935
  resolveOpen = resolve;
3718
3936
  rejectOpen = reject;
3719
3937
  });
3720
- const responsePromise = fetch(`${this.baseURL}/api/projects/${encode(projectId)}/room/events`, { headers, signal: options.signal }).then(async (response) => {
3938
+ const responsePromise = fetch(`${this.baseURL}/api/workspaces/${encodeURIComponent(workspaceId)}/room-events`, { headers, signal: options.signal }).then(async (response) => {
3721
3939
  if (!response.ok) {
3722
3940
  const payload = await response.json().catch(() => void 0);
3723
3941
  const error = payload?.error;
3724
- throw new ProjectRoomClientError(typeof error?.message === "string" ? error.message : "Project Room stream failed", response.status, typeof error?.code === "string" ? error.code : "HTTP_ERROR", error?.retryable === true, error?.details);
3942
+ throw new ProjectRoomClientError(typeof error?.message === "string" ? error.message : "Workspace room events stream failed", response.status, typeof error?.code === "string" ? error.code : "HTTP_ERROR", error?.retryable === true, error?.details);
3725
3943
  }
3726
3944
  if (response.headers?.get && response.headers.get("content-type")?.split(";")[0].trim() !== "text/event-stream")
3727
- throw new ProjectRoomClientError("Project Room stream has invalid content type", response.status, "INVALID_RESPONSE", false);
3945
+ throw new ProjectRoomClientError("Workspace room events stream has invalid content type", response.status, "INVALID_RESPONSE", false);
3728
3946
  if (!response.body)
3729
- throw new ProjectRoomClientError("Project Room stream has no body", 500, "INVALID_RESPONSE", false);
3730
- resolveOpen({ status: 200, ...options.lastEventId === void 0 ? {} : { lastEventId: options.lastEventId } });
3947
+ throw new ProjectRoomClientError("Workspace room events stream has no body", 500, "INVALID_RESPONSE", false);
3948
+ resolveOpen({ status: 200 });
3731
3949
  return response;
3732
3950
  }).catch((error) => {
3733
3951
  rejectOpen(error);
@@ -3737,22 +3955,10 @@ var ProjectRoomsClient = class {
3737
3955
  const response = await responsePromise;
3738
3956
  const body = response.body;
3739
3957
  if (!body)
3740
- throw new ProjectRoomClientError("Project Room stream has no body", 500, "INVALID_RESPONSE", false);
3958
+ throw new ProjectRoomClientError("Workspace room events stream has no body", 500, "INVALID_RESPONSE", false);
3741
3959
  for await (const raw of parseSseBody(body, { strictJsonObject: true })) {
3742
3960
  try {
3743
- const event = raw.event;
3744
- const payload = isRecord(raw.data) ? raw.data : void 0;
3745
- let value = payload;
3746
- if (event === "ready" || event === "resync" || event === "access.revoked") {
3747
- if (!payload || Object.prototype.hasOwnProperty.call(payload, "type"))
3748
- throw new ProjectRoomClientError("Invalid SSE control", 200, "INVALID_EVENT", false);
3749
- value = { type: event, data: payload };
3750
- } else {
3751
- if (typeof payload?.type !== "string" || payload.type !== event || typeof payload.id !== "string" || raw.id !== payload.id)
3752
- throw new ProjectRoomClientError("Invalid SSE business event", 200, "INVALID_EVENT", false);
3753
- value = payload;
3754
- }
3755
- yield { event: hydrateEvent(value), ...raw.id === void 0 ? {} : { id: raw.id }, ...raw.retry === void 0 ? {} : { retry: raw.retry } };
3961
+ yield { event: hydrateWorkspaceFrame(raw), ...raw.id === void 0 ? {} : { id: raw.id }, ...raw.retry === void 0 ? {} : { retry: raw.retry } };
3756
3962
  } catch (error) {
3757
3963
  if (error instanceof ProjectRoomClientError && error.code === "INVALID_EVENT")
3758
3964
  throw new ProjectRoomClientError(error.message, 400, "INVALID_EVENT", false, error.details);
@@ -3767,42 +3973,6 @@ var ProjectRoomsClient = class {
3767
3973
  return { opened, [Symbol.asyncIterator]: () => stream };
3768
3974
  }
3769
3975
  };
3770
- function hydrateEvent(value) {
3771
- const row = record(value);
3772
- if (row.type === "ready") {
3773
- exactKeys(row, ["type", "data"]);
3774
- const data2 = record(row.data);
3775
- exactKeys(data2, ["epoch", "headEventId"]);
3776
- if (typeof data2.epoch !== "string" || data2.headEventId !== null && typeof data2.headEventId !== "string")
3777
- throw new ProjectRoomClientError("Invalid SSE control", 200, "INVALID_EVENT", false);
3778
- return { type: "ready", data: { epoch: data2.epoch, headEventId: data2.headEventId } };
3779
- }
3780
- if (row.type === "resync" || row.type === "access.revoked") {
3781
- exactKeys(row, ["type", "data"]);
3782
- const data2 = record(row.data);
3783
- exactKeys(data2, ["reason"]);
3784
- const reasons = row.type === "resync" ? ["SERVER_RESTART", "CURSOR_EXPIRED", "SLOW_CONSUMER"] : ["PROJECT_ACCESS_REVOKED", "TOKEN_EXPIRED"];
3785
- return { type: row.type, data: { reason: oneOf(data2.reason, reasons, "reason") } };
3786
- }
3787
- const data = record(row.data);
3788
- if (row.type === "message.created")
3789
- return { ...row, occurredAt: date(row.occurredAt, "occurredAt"), data: { message: hydrateMessage(data.message) } };
3790
- if (row.type === "roster.changed")
3791
- return { ...row, occurredAt: date(row.occurredAt, "occurredAt"), data: { change: data.change, membership: hydratePublicBot(data.membership) } };
3792
- if (row.type === "membership.changed")
3793
- return { ...row, occurredAt: date(row.occurredAt, "occurredAt"), data: { change: data.change, membership: hydratePublicMember(data.membership) } };
3794
- if (row.type === "task.changed")
3795
- return { ...row, occurredAt: date(row.occurredAt, "occurredAt"), data: { taskId: requiredString(data, "taskId"), status: data.status, ownerMembershipId: requiredString(data, "ownerMembershipId"), updatedAt: date(data.updatedAt, "updatedAt") } };
3796
- throw new ProjectRoomClientError("Invalid SSE event", 200, "INVALID_EVENT", false);
3797
- }
3798
- function hydratePublicMember(value) {
3799
- const row = record(value);
3800
- return { id: requiredString(row, "id"), userId: requiredString(row, "userId"), role: row.role, status: row.status, joinedAt: date(row.joinedAt, "joinedAt"), updatedAt: date(row.updatedAt, "updatedAt") };
3801
- }
3802
- function hydratePublicBot(value) {
3803
- const row = record(value);
3804
- return { id: requiredString(row, "id"), role: row.role, title: requiredString(row, "title"), ...row.responsibility === void 0 ? {} : { responsibility: row.responsibility }, mentionName: requiredString(row, "mentionName"), status: row.status, joinedAt: date(row.joinedAt, "joinedAt"), updatedAt: date(row.updatedAt, "updatedAt") };
3805
- }
3806
3976
 
3807
3977
  // src/client.ts
3808
3978
  var _Client = class extends AbstractClient {
@@ -3820,6 +3990,8 @@ var _Client = class extends AbstractClient {
3820
3990
  this.resources = new ResourcesClient(this.config.baseURL, () => this.getAllHeaders());
3821
3991
  this.exportImport = new ExportImportClient(this.config, () => this.getAllHeaders());
3822
3992
  this.projectRooms = new ProjectRoomsClient(this.config.baseURL, () => this.getAllHeaders());
3993
+ this.workspaceRooms = new WorkspaceRoomsClient(this.config.baseURL, () => this.getAllHeaders());
3994
+ this.roomEvents = new RoomEventsClient(this.config.baseURL, () => this.getAllHeaders());
3823
3995
  }
3824
3996
  /**
3825
3997
  * Helper method to handle fetch responses and errors
@@ -5016,11 +5188,13 @@ export {
5016
5188
  ProjectRoomClientError,
5017
5189
  ProjectRoomsClient,
5018
5190
  ResourcesClient,
5191
+ RoomEventsClient,
5019
5192
  RuntimeAxiomClient,
5020
5193
  ScheduleExecutionType,
5021
5194
  ScheduledTaskStatus,
5022
5195
  WeChatClient,
5023
5196
  WorkspaceClient,
5197
+ WorkspaceRoomsClient,
5024
5198
  createSimpleMessageMerger
5025
5199
  };
5026
5200
  //# sourceMappingURL=index.mjs.map