@axiom-lattice/client-sdk 4.2.1 → 4.3.1
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/__tests__/project-rooms.test.d.ts +2 -0
- package/dist/__tests__/project-rooms.test.d.ts.map +1 -0
- package/dist/__tests__/project-rooms.test.js +144 -0
- package/dist/__tests__/project-rooms.test.js.map +1 -0
- package/dist/__tests__/sse-parser.test.d.ts +2 -0
- package/dist/__tests__/sse-parser.test.d.ts.map +1 -0
- package/dist/__tests__/sse-parser.test.js +17 -0
- package/dist/__tests__/sse-parser.test.js.map +1 -0
- package/dist/client.d.ts +2 -0
- package/dist/client.d.ts.map +1 -1
- package/dist/client.js +17 -134
- package/dist/client.js.map +1 -1
- package/dist/index.d.ts +153 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +401 -131
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +399 -131
- package/dist/index.mjs.map +1 -1
- package/dist/project-rooms.d.ts +152 -0
- package/dist/project-rooms.d.ts.map +1 -0
- package/dist/project-rooms.js +240 -0
- package/dist/project-rooms.js.map +1 -0
- package/dist/sse-parser.d.ts +15 -0
- package/dist/sse-parser.d.ts.map +1 -0
- package/dist/sse-parser.js +101 -0
- package/dist/sse-parser.js.map +1 -0
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -955,7 +955,7 @@ var require_encoding = __commonJS({
|
|
|
955
955
|
}
|
|
956
956
|
});
|
|
957
957
|
}
|
|
958
|
-
TextEncoder.prototype.encode = function
|
|
958
|
+
TextEncoder.prototype.encode = function encode2(opt_string, options) {
|
|
959
959
|
opt_string = opt_string === void 0 ? "" : String(opt_string);
|
|
960
960
|
options = ToDictionary(options);
|
|
961
961
|
if (!this._do_not_flush)
|
|
@@ -1834,6 +1834,8 @@ __export(src_exports, {
|
|
|
1834
1834
|
Client: () => Client,
|
|
1835
1835
|
ExportImportClient: () => ExportImportClient,
|
|
1836
1836
|
NetworkError: () => NetworkError,
|
|
1837
|
+
ProjectRoomClientError: () => ProjectRoomClientError,
|
|
1838
|
+
ProjectRoomsClient: () => ProjectRoomsClient,
|
|
1837
1839
|
ResourcesClient: () => ResourcesClient,
|
|
1838
1840
|
ScheduleExecutionType: () => ScheduleExecutionType,
|
|
1839
1841
|
ScheduledTaskStatus: () => ScheduledTaskStatus,
|
|
@@ -2360,7 +2362,7 @@ var AbstractClient = class {
|
|
|
2360
2362
|
const query = searchParams.toString();
|
|
2361
2363
|
const response = await this.makeRequest(`/api/web-apps${query ? `?${query}` : ""}`);
|
|
2362
2364
|
return {
|
|
2363
|
-
records: response.data.records.map((
|
|
2365
|
+
records: response.data.records.map((record2) => this.hydrateAgentWebApp(record2)),
|
|
2364
2366
|
total: response.data.total
|
|
2365
2367
|
};
|
|
2366
2368
|
},
|
|
@@ -3001,19 +3003,19 @@ var AbstractClient = class {
|
|
|
3001
3003
|
if (!value || typeof value !== "object" || Array.isArray(value)) {
|
|
3002
3004
|
throw new ApiError("Invalid Agent Web App response", 500, value);
|
|
3003
3005
|
}
|
|
3004
|
-
const
|
|
3006
|
+
const record2 = value;
|
|
3005
3007
|
const hydrateDate = (field) => {
|
|
3006
|
-
const raw =
|
|
3007
|
-
const
|
|
3008
|
+
const raw = record2[field];
|
|
3009
|
+
const date2 = raw instanceof Date ? new Date(raw.getTime()) : new Date(
|
|
3008
3010
|
typeof raw === "string" || typeof raw === "number" ? raw : Number.NaN
|
|
3009
3011
|
);
|
|
3010
|
-
if (Number.isNaN(
|
|
3012
|
+
if (Number.isNaN(date2.getTime())) {
|
|
3011
3013
|
throw new ApiError(`Invalid Agent Web App ${field}`, 500, value);
|
|
3012
3014
|
}
|
|
3013
|
-
return
|
|
3015
|
+
return date2;
|
|
3014
3016
|
};
|
|
3015
3017
|
return {
|
|
3016
|
-
...
|
|
3018
|
+
...record2,
|
|
3017
3019
|
createdAt: hydrateDate("createdAt"),
|
|
3018
3020
|
updatedAt: hydrateDate("updatedAt")
|
|
3019
3021
|
};
|
|
@@ -3453,6 +3455,381 @@ var ExportImportClient = class {
|
|
|
3453
3455
|
}
|
|
3454
3456
|
};
|
|
3455
3457
|
|
|
3458
|
+
// src/sse-parser.ts
|
|
3459
|
+
var SseParseError = class extends Error {
|
|
3460
|
+
constructor(message) {
|
|
3461
|
+
super(message);
|
|
3462
|
+
this.code = "INVALID_EVENT";
|
|
3463
|
+
this.name = "SseParseError";
|
|
3464
|
+
}
|
|
3465
|
+
};
|
|
3466
|
+
async function* parseSseBody(body, options = {}) {
|
|
3467
|
+
const reader = body.getReader();
|
|
3468
|
+
const decoder = new TextDecoder();
|
|
3469
|
+
let buffer = "";
|
|
3470
|
+
let event = "";
|
|
3471
|
+
let id;
|
|
3472
|
+
let retry;
|
|
3473
|
+
let data = [];
|
|
3474
|
+
const dispatch = () => {
|
|
3475
|
+
if (data.length === 0) {
|
|
3476
|
+
event = "";
|
|
3477
|
+
id = void 0;
|
|
3478
|
+
retry = void 0;
|
|
3479
|
+
return void 0;
|
|
3480
|
+
}
|
|
3481
|
+
let parsed;
|
|
3482
|
+
try {
|
|
3483
|
+
parsed = JSON.parse(data.join("\n"));
|
|
3484
|
+
} catch {
|
|
3485
|
+
throw new SseParseError("Invalid SSE JSON");
|
|
3486
|
+
}
|
|
3487
|
+
if (options.strictJsonObject && (typeof parsed !== "object" || parsed === null || Array.isArray(parsed)))
|
|
3488
|
+
throw new SseParseError("SSE data must be an object");
|
|
3489
|
+
const result = { event, data: parsed, ...id === void 0 ? {} : { id }, ...retry === void 0 ? {} : { retry } };
|
|
3490
|
+
event = "";
|
|
3491
|
+
id = void 0;
|
|
3492
|
+
retry = void 0;
|
|
3493
|
+
data = [];
|
|
3494
|
+
return result;
|
|
3495
|
+
};
|
|
3496
|
+
const processLine = (raw) => {
|
|
3497
|
+
const line = raw.endsWith("\r") ? raw.slice(0, -1) : raw;
|
|
3498
|
+
if (line === "")
|
|
3499
|
+
return dispatch();
|
|
3500
|
+
if (line.startsWith(":"))
|
|
3501
|
+
return void 0;
|
|
3502
|
+
const separator = line.indexOf(":");
|
|
3503
|
+
const field = separator < 0 ? line : line.slice(0, separator);
|
|
3504
|
+
let value = separator < 0 ? "" : line.slice(separator + 1);
|
|
3505
|
+
if (value.startsWith(" "))
|
|
3506
|
+
value = value.slice(1);
|
|
3507
|
+
if (field === "event")
|
|
3508
|
+
event = value;
|
|
3509
|
+
else if (field === "data")
|
|
3510
|
+
data.push(value);
|
|
3511
|
+
else if (field === "id")
|
|
3512
|
+
id = value;
|
|
3513
|
+
else if (field === "retry") {
|
|
3514
|
+
const parsed = Number(value);
|
|
3515
|
+
if (!Number.isInteger(parsed) || parsed < 0 || !Number.isFinite(parsed))
|
|
3516
|
+
throw new SseParseError("Invalid SSE retry");
|
|
3517
|
+
retry = parsed;
|
|
3518
|
+
}
|
|
3519
|
+
return void 0;
|
|
3520
|
+
};
|
|
3521
|
+
try {
|
|
3522
|
+
while (true) {
|
|
3523
|
+
const chunk = await reader.read();
|
|
3524
|
+
if (chunk.done) {
|
|
3525
|
+
buffer += decoder.decode();
|
|
3526
|
+
break;
|
|
3527
|
+
}
|
|
3528
|
+
buffer += decoder.decode(chunk.value, { stream: true });
|
|
3529
|
+
let index = findLineBreak(buffer);
|
|
3530
|
+
while (index >= 0) {
|
|
3531
|
+
if (buffer[index] === "\r" && index === buffer.length - 1)
|
|
3532
|
+
break;
|
|
3533
|
+
const frame2 = processLine(buffer.slice(0, index));
|
|
3534
|
+
buffer = buffer.slice(index + lineBreakLength(buffer, index));
|
|
3535
|
+
if (frame2)
|
|
3536
|
+
yield frame2;
|
|
3537
|
+
index = findLineBreak(buffer);
|
|
3538
|
+
}
|
|
3539
|
+
}
|
|
3540
|
+
if (buffer) {
|
|
3541
|
+
const frame2 = processLine(buffer);
|
|
3542
|
+
if (frame2)
|
|
3543
|
+
yield frame2;
|
|
3544
|
+
}
|
|
3545
|
+
const frame = processLine("");
|
|
3546
|
+
if (frame)
|
|
3547
|
+
yield frame;
|
|
3548
|
+
} finally {
|
|
3549
|
+
await reader.cancel().catch(() => void 0);
|
|
3550
|
+
reader.releaseLock();
|
|
3551
|
+
}
|
|
3552
|
+
}
|
|
3553
|
+
function findLineBreak(value) {
|
|
3554
|
+
const lf = value.indexOf("\n");
|
|
3555
|
+
const cr = value.indexOf("\r");
|
|
3556
|
+
if (lf < 0)
|
|
3557
|
+
return cr;
|
|
3558
|
+
if (cr < 0)
|
|
3559
|
+
return lf;
|
|
3560
|
+
return Math.min(lf, cr);
|
|
3561
|
+
}
|
|
3562
|
+
function lineBreakLength(value, index) {
|
|
3563
|
+
return value[index] === "\r" && value[index + 1] === "\n" ? 2 : 1;
|
|
3564
|
+
}
|
|
3565
|
+
|
|
3566
|
+
// src/project-rooms.ts
|
|
3567
|
+
var ProjectRoomClientError = class extends Error {
|
|
3568
|
+
constructor(message, status, code, retryable, details) {
|
|
3569
|
+
super(message);
|
|
3570
|
+
this.status = status;
|
|
3571
|
+
this.code = code;
|
|
3572
|
+
this.retryable = retryable;
|
|
3573
|
+
this.details = details;
|
|
3574
|
+
this.name = "ProjectRoomClientError";
|
|
3575
|
+
}
|
|
3576
|
+
};
|
|
3577
|
+
var isRecord = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
|
|
3578
|
+
var date = (value, field) => {
|
|
3579
|
+
const result = value instanceof Date ? new Date(value.getTime()) : new Date(typeof value === "string" || typeof value === "number" ? value : Number.NaN);
|
|
3580
|
+
if (!Number.isFinite(result.getTime()))
|
|
3581
|
+
throw new ProjectRoomClientError(`Invalid ${field}`, 500, "INVALID_RESPONSE", false);
|
|
3582
|
+
return result;
|
|
3583
|
+
};
|
|
3584
|
+
var requiredString = (record2, field) => {
|
|
3585
|
+
if (typeof record2[field] !== "string")
|
|
3586
|
+
throw new ProjectRoomClientError(`Invalid ${field}`, 500, "INVALID_RESPONSE", false);
|
|
3587
|
+
return record2[field];
|
|
3588
|
+
};
|
|
3589
|
+
var oneOf = (value, values, field) => {
|
|
3590
|
+
if (typeof value !== "string" || !values.includes(value))
|
|
3591
|
+
throw new ProjectRoomClientError(`Invalid ${field}`, 500, "INVALID_RESPONSE", false);
|
|
3592
|
+
return value;
|
|
3593
|
+
};
|
|
3594
|
+
var messageSources = ["user", "agent", "task", "routine", "system"];
|
|
3595
|
+
var humanRoles = ["owner", "admin", "member", "viewer"];
|
|
3596
|
+
var memberStatuses = ["active", "removed"];
|
|
3597
|
+
var botRoles = ["coordinator", "specialist"];
|
|
3598
|
+
var botStatuses = ["active", "paused", "removed"];
|
|
3599
|
+
var exactKeys = (row, required, optional = []) => {
|
|
3600
|
+
if (required.some((key) => !Object.prototype.hasOwnProperty.call(row, key)) || Object.keys(row).some((key) => !required.includes(key) && !optional.includes(key)))
|
|
3601
|
+
throw new ProjectRoomClientError("Invalid Project Room response", 500, "INVALID_RESPONSE", false);
|
|
3602
|
+
};
|
|
3603
|
+
var hydrateAuthor = (value) => {
|
|
3604
|
+
const row = record(value);
|
|
3605
|
+
const type = oneOf(row.type, ["human", "bot", "system"], "author.type");
|
|
3606
|
+
if (type === "human") {
|
|
3607
|
+
exactKeys(row, ["type", "userId"]);
|
|
3608
|
+
return { type, userId: requiredString(row, "userId") };
|
|
3609
|
+
}
|
|
3610
|
+
if (type === "bot")
|
|
3611
|
+
return { type, membershipId: requiredString(row, "membershipId") };
|
|
3612
|
+
if (Object.keys(row).some((key) => key !== "type"))
|
|
3613
|
+
throw new ProjectRoomClientError("Invalid author", 500, "INVALID_RESPONSE", false);
|
|
3614
|
+
return { type };
|
|
3615
|
+
};
|
|
3616
|
+
var hydrateMentions = (value) => {
|
|
3617
|
+
if (!Array.isArray(value))
|
|
3618
|
+
throw new ProjectRoomClientError("Invalid mentions", 500, "INVALID_RESPONSE", false);
|
|
3619
|
+
return value.map((entry) => {
|
|
3620
|
+
const row = record(entry);
|
|
3621
|
+
const type = oneOf(row.type, ["bot", "team"], "mention.type");
|
|
3622
|
+
if (type === "team") {
|
|
3623
|
+
if (Object.keys(row).length !== 1)
|
|
3624
|
+
throw new ProjectRoomClientError("Invalid mention", 500, "INVALID_RESPONSE", false);
|
|
3625
|
+
return { type };
|
|
3626
|
+
}
|
|
3627
|
+
return { type, membershipId: requiredString(row, "membershipId") };
|
|
3628
|
+
});
|
|
3629
|
+
};
|
|
3630
|
+
var record = (value) => {
|
|
3631
|
+
if (!isRecord(value))
|
|
3632
|
+
throw new ProjectRoomClientError("Invalid Project Room response", 500, "INVALID_RESPONSE", false);
|
|
3633
|
+
return value;
|
|
3634
|
+
};
|
|
3635
|
+
var hydrateRoom = (value) => {
|
|
3636
|
+
const row = record(value);
|
|
3637
|
+
exactKeys(row, ["id", "tenantId", "workspaceId", "projectId", "type", "name", "createdAt", "updatedAt"]);
|
|
3638
|
+
return { id: requiredString(row, "id"), tenantId: requiredString(row, "tenantId"), workspaceId: requiredString(row, "workspaceId"), projectId: requiredString(row, "projectId"), type: oneOf(row.type, ["main"], "type"), name: requiredString(row, "name"), createdAt: date(row.createdAt, "createdAt"), updatedAt: date(row.updatedAt, "updatedAt") };
|
|
3639
|
+
};
|
|
3640
|
+
var hydrateMessage = (value) => {
|
|
3641
|
+
const row = record(value);
|
|
3642
|
+
exactKeys(row, ["id", "roomId", "author", "content", "mentions", "source", "createdAt"], ["replyToMessageId"]);
|
|
3643
|
+
const content = record(row.content);
|
|
3644
|
+
if (oneOf(content.type, ["text"], "content.type") !== "text")
|
|
3645
|
+
throw new ProjectRoomClientError("Invalid content", 500, "INVALID_RESPONSE", false);
|
|
3646
|
+
return { id: requiredString(row, "id"), roomId: requiredString(row, "roomId"), author: hydrateAuthor(row.author), content: { type: "text", text: requiredString(content, "text") }, mentions: hydrateMentions(row.mentions), ...row.replyToMessageId === void 0 ? {} : { replyToMessageId: requiredString(row, "replyToMessageId") }, source: oneOf(row.source, messageSources, "source"), createdAt: date(row.createdAt, "createdAt") };
|
|
3647
|
+
};
|
|
3648
|
+
var hydrateMember = (value) => {
|
|
3649
|
+
const row = record(value);
|
|
3650
|
+
exactKeys(row, ["id", "tenantId", "projectId", "userId", "role", "status", "joinedAt", "updatedAt"]);
|
|
3651
|
+
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") };
|
|
3652
|
+
};
|
|
3653
|
+
var hydrateBot = (value) => {
|
|
3654
|
+
const row = record(value);
|
|
3655
|
+
exactKeys(row, ["id", "tenantId", "workspaceId", "projectId", "roomId", "assistantId", "role", "title", "mentionName", "status", "roomThreadId", "joinedAt", "updatedAt"], ["responsibility"]);
|
|
3656
|
+
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") };
|
|
3657
|
+
};
|
|
3658
|
+
var iso = (value) => date(value, "date").toISOString();
|
|
3659
|
+
var hydrateDispatch = (value) => {
|
|
3660
|
+
const row = record(value);
|
|
3661
|
+
if (typeof row.success !== "boolean" || row.membershipId !== void 0 && typeof row.membershipId !== "string" || row.errorCode !== void 0 && typeof row.errorCode !== "string")
|
|
3662
|
+
throw new ProjectRoomClientError("Invalid dispatch response", 500, "INVALID_RESPONSE", false);
|
|
3663
|
+
return { success: row.success, ...row.membershipId === void 0 ? {} : { membershipId: row.membershipId }, ...row.errorCode === void 0 ? {} : { errorCode: row.errorCode } };
|
|
3664
|
+
};
|
|
3665
|
+
var encode = encodeURIComponent;
|
|
3666
|
+
var ProjectRoomsClient = class {
|
|
3667
|
+
constructor(baseURL, getHeaders) {
|
|
3668
|
+
this.baseURL = baseURL;
|
|
3669
|
+
this.getHeaders = getHeaders;
|
|
3670
|
+
this.messages = {
|
|
3671
|
+
list: async (projectId, options = {}) => {
|
|
3672
|
+
const query = new URLSearchParams();
|
|
3673
|
+
if (options.cursor) {
|
|
3674
|
+
query.set("beforeCreatedAt", iso(options.cursor.createdAt));
|
|
3675
|
+
query.set("beforeId", options.cursor.id);
|
|
3676
|
+
}
|
|
3677
|
+
if (options.limit !== void 0)
|
|
3678
|
+
query.set("limit", String(options.limit));
|
|
3679
|
+
const result = await this.request(`/api/projects/${encode(projectId)}/room/messages${query.toString() ? `?${query}` : ""}`);
|
|
3680
|
+
if (!Array.isArray(result))
|
|
3681
|
+
throw new ProjectRoomClientError("Invalid messages response", 500, "INVALID_RESPONSE", false);
|
|
3682
|
+
return result.map(hydrateMessage);
|
|
3683
|
+
},
|
|
3684
|
+
send: async (projectId, input) => {
|
|
3685
|
+
const result = await this.request(`/api/projects/${encode(projectId)}/room/messages`, { method: "POST", body: { text: input.text, mentions: input.mentions, ...input.replyToMessageId === void 0 ? {} : { replyToMessageId: input.replyToMessageId } }, headers: { "Idempotency-Key": input.idempotencyKey.trim() } });
|
|
3686
|
+
if (!Array.isArray(result.dispatch) || typeof result.replayed !== "boolean")
|
|
3687
|
+
throw new ProjectRoomClientError("Invalid send response", 500, "INVALID_RESPONSE", false);
|
|
3688
|
+
return { message: hydrateMessage(result.message), dispatch: result.dispatch.map(hydrateDispatch), replayed: result.replayed };
|
|
3689
|
+
},
|
|
3690
|
+
retry: async (projectId, messageId) => {
|
|
3691
|
+
const result = await this.request(`/api/projects/${encode(projectId)}/room/messages/${encode(messageId)}/retry`, { method: "POST", body: {} });
|
|
3692
|
+
if (!Array.isArray(result))
|
|
3693
|
+
throw new ProjectRoomClientError("Invalid retry response", 500, "INVALID_RESPONSE", false);
|
|
3694
|
+
return result.map(hydrateDispatch);
|
|
3695
|
+
}
|
|
3696
|
+
};
|
|
3697
|
+
this.members = {
|
|
3698
|
+
list: async (projectId) => this.records(`/api/projects/${encode(projectId)}/members`, hydrateMember),
|
|
3699
|
+
add: async (projectId, input) => hydrateMember(await this.request(`/api/projects/${encode(projectId)}/members`, { method: "POST", body: input })),
|
|
3700
|
+
update: async (projectId, membershipId, input) => hydrateMember(await this.request(`/api/projects/${encode(projectId)}/members/${encode(membershipId)}`, { method: "PATCH", body: { role: input.role, expectedUpdatedAt: iso(input.expectedUpdatedAt) } })),
|
|
3701
|
+
remove: async (projectId, membershipId, input) => this.request(`/api/projects/${encode(projectId)}/members/${encode(membershipId)}?expectedUpdatedAt=${encode(iso(input.expectedUpdatedAt))}`, { method: "DELETE" })
|
|
3702
|
+
};
|
|
3703
|
+
this.bots = {
|
|
3704
|
+
list: async (projectId) => this.records(`/api/projects/${encode(projectId)}/bots`, hydrateBot),
|
|
3705
|
+
add: async (projectId, input) => hydrateBot(await this.request(`/api/projects/${encode(projectId)}/bots`, { method: "POST", body: input })),
|
|
3706
|
+
update: async (projectId, membershipId, input) => hydrateBot(await this.request(`/api/projects/${encode(projectId)}/bots/${encode(membershipId)}`, { method: "PATCH", body: { ...input, expectedUpdatedAt: iso(input.expectedUpdatedAt) } })),
|
|
3707
|
+
pause: async (projectId, membershipId, input) => hydrateBot(await this.request(`/api/projects/${encode(projectId)}/bots/${encode(membershipId)}/pause`, { method: "POST", body: { expectedUpdatedAt: iso(input.expectedUpdatedAt) } })),
|
|
3708
|
+
resume: async (projectId, membershipId, input) => hydrateBot(await this.request(`/api/projects/${encode(projectId)}/bots/${encode(membershipId)}/resume`, { method: "POST", body: { expectedUpdatedAt: iso(input.expectedUpdatedAt) } })),
|
|
3709
|
+
remove: async (projectId, membershipId, input) => this.request(`/api/projects/${encode(projectId)}/bots/${encode(membershipId)}?expectedUpdatedAt=${encode(iso(input.expectedUpdatedAt))}`, { method: "DELETE" })
|
|
3710
|
+
};
|
|
3711
|
+
this.events = { connect: (projectId, options) => this.connect(projectId, options) };
|
|
3712
|
+
}
|
|
3713
|
+
async getRoom(projectId) {
|
|
3714
|
+
return hydrateRoom(await this.request(`/api/projects/${encode(projectId)}/room`));
|
|
3715
|
+
}
|
|
3716
|
+
async getRealtimeMode(projectId) {
|
|
3717
|
+
return this.request(`/api/projects/${encode(projectId)}/room/realtime-mode`);
|
|
3718
|
+
}
|
|
3719
|
+
async records(path, hydrate) {
|
|
3720
|
+
const result = await this.request(path);
|
|
3721
|
+
if (!Array.isArray(result))
|
|
3722
|
+
throw new ProjectRoomClientError("Invalid records response", 500, "INVALID_RESPONSE", false);
|
|
3723
|
+
return result.map(hydrate);
|
|
3724
|
+
}
|
|
3725
|
+
async request(path, options = {}) {
|
|
3726
|
+
const headers = { ...this.getHeaders(), ...options.headers ?? {} };
|
|
3727
|
+
const body = options.body === void 0 ? void 0 : JSON.parse(JSON.stringify(options.body));
|
|
3728
|
+
const response = await fetch(`${this.baseURL}${path}`, { method: options.method ?? "GET", headers, ...body === void 0 ? {} : { body: JSON.stringify(body) } });
|
|
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 : "Project Room request failed", response.status, typeof error?.code === "string" ? error.code : response.ok ? "INVALID_RESPONSE" : "HTTP_ERROR", error?.retryable === true, error?.details);
|
|
3733
|
+
}
|
|
3734
|
+
if (!Object.prototype.hasOwnProperty.call(payload, "data"))
|
|
3735
|
+
throw new ProjectRoomClientError("Missing response data", 500, "INVALID_RESPONSE", false);
|
|
3736
|
+
return payload.data;
|
|
3737
|
+
}
|
|
3738
|
+
connect(projectId, options) {
|
|
3739
|
+
const headers = { ...this.getHeaders(), Accept: "text/event-stream", ...options.lastEventId ? { "Last-Event-ID": options.lastEventId } : {} };
|
|
3740
|
+
let resolveOpen;
|
|
3741
|
+
let rejectOpen;
|
|
3742
|
+
const opened = new Promise((resolve, reject) => {
|
|
3743
|
+
resolveOpen = resolve;
|
|
3744
|
+
rejectOpen = reject;
|
|
3745
|
+
});
|
|
3746
|
+
const responsePromise = fetch(`${this.baseURL}/api/projects/${encode(projectId)}/room/events`, { headers, signal: options.signal }).then(async (response) => {
|
|
3747
|
+
if (!response.ok) {
|
|
3748
|
+
const payload = await response.json().catch(() => void 0);
|
|
3749
|
+
const error = payload?.error;
|
|
3750
|
+
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);
|
|
3751
|
+
}
|
|
3752
|
+
if (response.headers?.get && response.headers.get("content-type")?.split(";")[0].trim() !== "text/event-stream")
|
|
3753
|
+
throw new ProjectRoomClientError("Project Room stream has invalid content type", response.status, "INVALID_RESPONSE", false);
|
|
3754
|
+
if (!response.body)
|
|
3755
|
+
throw new ProjectRoomClientError("Project Room stream has no body", 500, "INVALID_RESPONSE", false);
|
|
3756
|
+
resolveOpen({ status: 200, ...options.lastEventId === void 0 ? {} : { lastEventId: options.lastEventId } });
|
|
3757
|
+
return response;
|
|
3758
|
+
}).catch((error) => {
|
|
3759
|
+
rejectOpen(error);
|
|
3760
|
+
throw error;
|
|
3761
|
+
});
|
|
3762
|
+
const stream = async function* () {
|
|
3763
|
+
const response = await responsePromise;
|
|
3764
|
+
const body = response.body;
|
|
3765
|
+
if (!body)
|
|
3766
|
+
throw new ProjectRoomClientError("Project Room stream has no body", 500, "INVALID_RESPONSE", false);
|
|
3767
|
+
for await (const raw of parseSseBody(body, { strictJsonObject: true })) {
|
|
3768
|
+
try {
|
|
3769
|
+
const event = raw.event;
|
|
3770
|
+
const payload = isRecord(raw.data) ? raw.data : void 0;
|
|
3771
|
+
let value = payload;
|
|
3772
|
+
if (event === "ready" || event === "resync" || event === "access.revoked") {
|
|
3773
|
+
if (!payload || Object.prototype.hasOwnProperty.call(payload, "type"))
|
|
3774
|
+
throw new ProjectRoomClientError("Invalid SSE control", 200, "INVALID_EVENT", false);
|
|
3775
|
+
value = { type: event, data: payload };
|
|
3776
|
+
} else {
|
|
3777
|
+
if (typeof payload?.type !== "string" || payload.type !== event || typeof payload.id !== "string" || raw.id !== payload.id)
|
|
3778
|
+
throw new ProjectRoomClientError("Invalid SSE business event", 200, "INVALID_EVENT", false);
|
|
3779
|
+
value = payload;
|
|
3780
|
+
}
|
|
3781
|
+
yield { event: hydrateEvent(value), ...raw.id === void 0 ? {} : { id: raw.id }, ...raw.retry === void 0 ? {} : { retry: raw.retry } };
|
|
3782
|
+
} catch (error) {
|
|
3783
|
+
if (error instanceof ProjectRoomClientError && error.code === "INVALID_EVENT")
|
|
3784
|
+
throw new ProjectRoomClientError(error.message, 400, "INVALID_EVENT", false, error.details);
|
|
3785
|
+
if (error instanceof SseParseError)
|
|
3786
|
+
throw new ProjectRoomClientError(error.message, 400, "INVALID_EVENT", false);
|
|
3787
|
+
if (error instanceof ProjectRoomClientError)
|
|
3788
|
+
throw new ProjectRoomClientError(error.message, 400, "INVALID_EVENT", false, error.details);
|
|
3789
|
+
throw new ProjectRoomClientError("Invalid SSE event", 400, "INVALID_EVENT", false);
|
|
3790
|
+
}
|
|
3791
|
+
}
|
|
3792
|
+
}();
|
|
3793
|
+
return { opened, [Symbol.asyncIterator]: () => stream };
|
|
3794
|
+
}
|
|
3795
|
+
};
|
|
3796
|
+
function hydrateEvent(value) {
|
|
3797
|
+
const row = record(value);
|
|
3798
|
+
if (row.type === "ready") {
|
|
3799
|
+
exactKeys(row, ["type", "data"]);
|
|
3800
|
+
const data2 = record(row.data);
|
|
3801
|
+
exactKeys(data2, ["epoch", "headEventId"]);
|
|
3802
|
+
if (typeof data2.epoch !== "string" || data2.headEventId !== null && typeof data2.headEventId !== "string")
|
|
3803
|
+
throw new ProjectRoomClientError("Invalid SSE control", 200, "INVALID_EVENT", false);
|
|
3804
|
+
return { type: "ready", data: { epoch: data2.epoch, headEventId: data2.headEventId } };
|
|
3805
|
+
}
|
|
3806
|
+
if (row.type === "resync" || row.type === "access.revoked") {
|
|
3807
|
+
exactKeys(row, ["type", "data"]);
|
|
3808
|
+
const data2 = record(row.data);
|
|
3809
|
+
exactKeys(data2, ["reason"]);
|
|
3810
|
+
const reasons = row.type === "resync" ? ["SERVER_RESTART", "CURSOR_EXPIRED", "SLOW_CONSUMER"] : ["PROJECT_ACCESS_REVOKED", "TOKEN_EXPIRED"];
|
|
3811
|
+
return { type: row.type, data: { reason: oneOf(data2.reason, reasons, "reason") } };
|
|
3812
|
+
}
|
|
3813
|
+
const data = record(row.data);
|
|
3814
|
+
if (row.type === "message.created")
|
|
3815
|
+
return { ...row, occurredAt: date(row.occurredAt, "occurredAt"), data: { message: hydrateMessage(data.message) } };
|
|
3816
|
+
if (row.type === "roster.changed")
|
|
3817
|
+
return { ...row, occurredAt: date(row.occurredAt, "occurredAt"), data: { change: data.change, membership: hydratePublicBot(data.membership) } };
|
|
3818
|
+
if (row.type === "membership.changed")
|
|
3819
|
+
return { ...row, occurredAt: date(row.occurredAt, "occurredAt"), data: { change: data.change, membership: hydratePublicMember(data.membership) } };
|
|
3820
|
+
if (row.type === "task.changed")
|
|
3821
|
+
return { ...row, occurredAt: date(row.occurredAt, "occurredAt"), data: { taskId: requiredString(data, "taskId"), status: data.status, ownerMembershipId: requiredString(data, "ownerMembershipId"), updatedAt: date(data.updatedAt, "updatedAt") } };
|
|
3822
|
+
throw new ProjectRoomClientError("Invalid SSE event", 200, "INVALID_EVENT", false);
|
|
3823
|
+
}
|
|
3824
|
+
function hydratePublicMember(value) {
|
|
3825
|
+
const row = record(value);
|
|
3826
|
+
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") };
|
|
3827
|
+
}
|
|
3828
|
+
function hydratePublicBot(value) {
|
|
3829
|
+
const row = record(value);
|
|
3830
|
+
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") };
|
|
3831
|
+
}
|
|
3832
|
+
|
|
3456
3833
|
// src/client.ts
|
|
3457
3834
|
var _Client = class extends AbstractClient {
|
|
3458
3835
|
/**
|
|
@@ -3468,6 +3845,7 @@ var _Client = class extends AbstractClient {
|
|
|
3468
3845
|
};
|
|
3469
3846
|
this.resources = new ResourcesClient(this.config.baseURL, () => this.getAllHeaders());
|
|
3470
3847
|
this.exportImport = new ExportImportClient(this.config, () => this.getAllHeaders());
|
|
3848
|
+
this.projectRooms = new ProjectRoomsClient(this.config.baseURL, () => this.getAllHeaders());
|
|
3471
3849
|
}
|
|
3472
3850
|
/**
|
|
3473
3851
|
* Helper method to handle fetch responses and errors
|
|
@@ -3683,41 +4061,8 @@ var _Client = class extends AbstractClient {
|
|
|
3683
4061
|
if (!response.body) {
|
|
3684
4062
|
throw new Error("Response body is null");
|
|
3685
4063
|
}
|
|
3686
|
-
const
|
|
3687
|
-
|
|
3688
|
-
let buffer = "";
|
|
3689
|
-
while (true) {
|
|
3690
|
-
const { done, value } = await reader.read();
|
|
3691
|
-
if (done)
|
|
3692
|
-
break;
|
|
3693
|
-
const chunk = decoder.decode(value, { stream: true });
|
|
3694
|
-
buffer += chunk;
|
|
3695
|
-
const lines = buffer.split("\n");
|
|
3696
|
-
buffer = lines.pop() || "";
|
|
3697
|
-
for (const line of lines) {
|
|
3698
|
-
if (line.trim().startsWith("data: ")) {
|
|
3699
|
-
try {
|
|
3700
|
-
const eventData = JSON.parse(line.trim().slice(6));
|
|
3701
|
-
onEvent(eventData);
|
|
3702
|
-
} catch (error) {
|
|
3703
|
-
console.error("Error parsing SSE data:", line, error);
|
|
3704
|
-
if (onError) {
|
|
3705
|
-
onError(
|
|
3706
|
-
error instanceof Error ? error : new Error(String(error))
|
|
3707
|
-
);
|
|
3708
|
-
}
|
|
3709
|
-
}
|
|
3710
|
-
}
|
|
3711
|
-
}
|
|
3712
|
-
}
|
|
3713
|
-
if (buffer && buffer.trim().startsWith("data: ")) {
|
|
3714
|
-
try {
|
|
3715
|
-
const eventData = JSON.parse(buffer.trim().slice(6));
|
|
3716
|
-
onEvent(eventData);
|
|
3717
|
-
} catch (error) {
|
|
3718
|
-
console.error("Error parsing SSE data:", buffer, error);
|
|
3719
|
-
}
|
|
3720
|
-
}
|
|
4064
|
+
for await (const frame of parseSseBody(response.body, { strictJsonObject: true }))
|
|
4065
|
+
onEvent(frame.data);
|
|
3721
4066
|
if (onComplete) {
|
|
3722
4067
|
onComplete();
|
|
3723
4068
|
}
|
|
@@ -3760,62 +4105,18 @@ var _Client = class extends AbstractClient {
|
|
|
3760
4105
|
const res = await fetch(`${this.config.baseURL}${path}`, { headers, signal });
|
|
3761
4106
|
if (!res.ok || !res.body)
|
|
3762
4107
|
throw new Error("Stream connection failed");
|
|
3763
|
-
|
|
3764
|
-
|
|
3765
|
-
|
|
3766
|
-
let event = "";
|
|
3767
|
-
let dataLines = [];
|
|
3768
|
-
const processLine = (rawLine) => {
|
|
3769
|
-
const line = rawLine.endsWith("\r") ? rawLine.slice(0, -1) : rawLine;
|
|
3770
|
-
if (line === "") {
|
|
3771
|
-
if (dataLines.length === 0) {
|
|
3772
|
-
event = "";
|
|
3773
|
-
return null;
|
|
3774
|
-
}
|
|
3775
|
-
const data = dataLines.join("\n");
|
|
3776
|
-
const eventName = event;
|
|
3777
|
-
event = "";
|
|
3778
|
-
dataLines = [];
|
|
3779
|
-
try {
|
|
3780
|
-
return { event: eventName, data: JSON.parse(data) };
|
|
3781
|
-
} catch {
|
|
3782
|
-
return null;
|
|
3783
|
-
}
|
|
3784
|
-
}
|
|
3785
|
-
if (line.startsWith(":"))
|
|
3786
|
-
return null;
|
|
3787
|
-
const separator = line.indexOf(":");
|
|
3788
|
-
const field = separator === -1 ? line : line.slice(0, separator);
|
|
3789
|
-
let value = separator === -1 ? "" : line.slice(separator + 1);
|
|
3790
|
-
if (value.startsWith(" "))
|
|
3791
|
-
value = value.slice(1);
|
|
3792
|
-
if (field === "event")
|
|
3793
|
-
event = value;
|
|
3794
|
-
else if (field === "data")
|
|
3795
|
-
dataLines.push(value);
|
|
3796
|
-
return null;
|
|
3797
|
-
};
|
|
3798
|
-
while (true) {
|
|
3799
|
-
const { done, value } = await reader.read();
|
|
3800
|
-
if (done) {
|
|
3801
|
-
buffer += decoder.decode();
|
|
3802
|
-
break;
|
|
4108
|
+
try {
|
|
4109
|
+
for await (const frame of parseSseBody(res.body, { strictJsonObject: true })) {
|
|
4110
|
+
yield { event: frame.event, data: frame.data };
|
|
3803
4111
|
}
|
|
3804
|
-
|
|
3805
|
-
|
|
3806
|
-
|
|
3807
|
-
|
|
3808
|
-
|
|
3809
|
-
if (parsed)
|
|
3810
|
-
yield parsed;
|
|
3811
|
-
newline = buffer.indexOf("\n");
|
|
4112
|
+
} catch (error) {
|
|
4113
|
+
if (error instanceof SseParseError) {
|
|
4114
|
+
const parseError = new Error(error.message);
|
|
4115
|
+
parseError.name = "StreamParseError";
|
|
4116
|
+
throw parseError;
|
|
3812
4117
|
}
|
|
4118
|
+
throw error;
|
|
3813
4119
|
}
|
|
3814
|
-
if (buffer.length > 0)
|
|
3815
|
-
processLine(buffer);
|
|
3816
|
-
const finalEvent = processLine("");
|
|
3817
|
-
if (finalEvent)
|
|
3818
|
-
yield finalEvent;
|
|
3819
4120
|
}
|
|
3820
4121
|
/**
|
|
3821
4122
|
* Get all headers including workspace context
|
|
@@ -3857,41 +4158,8 @@ var _Client = class extends AbstractClient {
|
|
|
3857
4158
|
if (!response.body) {
|
|
3858
4159
|
throw new Error("Response body is null");
|
|
3859
4160
|
}
|
|
3860
|
-
const
|
|
3861
|
-
|
|
3862
|
-
let buffer = "";
|
|
3863
|
-
while (true) {
|
|
3864
|
-
const { done, value } = await reader.read();
|
|
3865
|
-
if (done)
|
|
3866
|
-
break;
|
|
3867
|
-
const chunk = decoder.decode(value, { stream: true });
|
|
3868
|
-
buffer += chunk;
|
|
3869
|
-
const lines = buffer.split("\n");
|
|
3870
|
-
buffer = lines.pop() || "";
|
|
3871
|
-
for (const line of lines) {
|
|
3872
|
-
if (line.trim().startsWith("data: ")) {
|
|
3873
|
-
try {
|
|
3874
|
-
const eventData = JSON.parse(line.trim().slice(6));
|
|
3875
|
-
onEvent(eventData);
|
|
3876
|
-
} catch (error) {
|
|
3877
|
-
console.error("Error parsing SSE data:", line, error);
|
|
3878
|
-
if (onError) {
|
|
3879
|
-
onError(
|
|
3880
|
-
error instanceof Error ? error : new Error(String(error))
|
|
3881
|
-
);
|
|
3882
|
-
}
|
|
3883
|
-
}
|
|
3884
|
-
}
|
|
3885
|
-
}
|
|
3886
|
-
}
|
|
3887
|
-
if (buffer && buffer.trim().startsWith("data: ")) {
|
|
3888
|
-
try {
|
|
3889
|
-
const eventData = JSON.parse(buffer.trim().slice(6));
|
|
3890
|
-
onEvent(eventData);
|
|
3891
|
-
} catch (error) {
|
|
3892
|
-
console.error("Error parsing SSE data:", buffer, error);
|
|
3893
|
-
}
|
|
3894
|
-
}
|
|
4161
|
+
for await (const frame of parseSseBody(response.body, { strictJsonObject: true }))
|
|
4162
|
+
onEvent(frame.data);
|
|
3895
4163
|
if (onComplete) {
|
|
3896
4164
|
if (options.enableReturnStateWhenSteamCompleted) {
|
|
3897
4165
|
try {
|
|
@@ -4663,6 +4931,8 @@ function createSimpleMessageMerger() {
|
|
|
4663
4931
|
Client,
|
|
4664
4932
|
ExportImportClient,
|
|
4665
4933
|
NetworkError,
|
|
4934
|
+
ProjectRoomClientError,
|
|
4935
|
+
ProjectRoomsClient,
|
|
4666
4936
|
ResourcesClient,
|
|
4667
4937
|
ScheduleExecutionType,
|
|
4668
4938
|
ScheduledTaskStatus,
|