@prismer/sdk 2.0.4 → 2.0.6
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.js +241 -38
- package/dist/index.d.mts +303 -10
- package/dist/index.d.ts +303 -10
- package/dist/index.js +137 -38
- package/dist/index.mjs +136 -38
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -32,6 +32,7 @@ var index_exports = {};
|
|
|
32
32
|
__export(index_exports, {
|
|
33
33
|
AIPIdentity: () => import_aip_sdk.AIPIdentity,
|
|
34
34
|
AccountClient: () => AccountClient,
|
|
35
|
+
AgentsClient: () => AgentsClient,
|
|
35
36
|
AssetsClient: () => AssetsClient,
|
|
36
37
|
AttachmentQueue: () => AttachmentQueue,
|
|
37
38
|
BindingsClient: () => BindingsClient,
|
|
@@ -3451,6 +3452,44 @@ function resolveBaseUrl(explicit) {
|
|
|
3451
3452
|
}
|
|
3452
3453
|
return void 0;
|
|
3453
3454
|
}
|
|
3455
|
+
function generateIdempotencyKey() {
|
|
3456
|
+
try {
|
|
3457
|
+
if (typeof crypto !== "undefined" && typeof crypto.randomUUID === "function") {
|
|
3458
|
+
return crypto.randomUUID();
|
|
3459
|
+
}
|
|
3460
|
+
} catch {
|
|
3461
|
+
}
|
|
3462
|
+
return "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, (c) => {
|
|
3463
|
+
const r = Math.random() * 16 | 0;
|
|
3464
|
+
return (c === "x" ? r : r & 3 | 8).toString(16);
|
|
3465
|
+
});
|
|
3466
|
+
}
|
|
3467
|
+
function buildSendPayload(content, options) {
|
|
3468
|
+
const key = options?.idempotencyKey ?? generateIdempotencyKey();
|
|
3469
|
+
const isBlocks = Array.isArray(content);
|
|
3470
|
+
const body = {
|
|
3471
|
+
// For ContentBlock[] inputs, populate `content` as a fallback summary
|
|
3472
|
+
// (server's legacy `content` column stays compatible during the 6-sprint
|
|
3473
|
+
// double-write window from §4.6); the SOT is `contentBlocks`.
|
|
3474
|
+
content: isBlocks ? "" : content,
|
|
3475
|
+
type: options?.type ?? "text",
|
|
3476
|
+
metadata: options?.metadata,
|
|
3477
|
+
attachments: options?.attachments,
|
|
3478
|
+
parentId: options?.parentId,
|
|
3479
|
+
quotedMessageId: options?.quotedMessageId,
|
|
3480
|
+
idempotencyKey: key
|
|
3481
|
+
};
|
|
3482
|
+
if (isBlocks) {
|
|
3483
|
+
body.contentBlocks = content;
|
|
3484
|
+
} else if (options?.contentBlocks) {
|
|
3485
|
+
body.contentBlocks = options.contentBlocks;
|
|
3486
|
+
}
|
|
3487
|
+
return {
|
|
3488
|
+
body,
|
|
3489
|
+
opts: { headers: { "X-Idempotency-Key": key } },
|
|
3490
|
+
key
|
|
3491
|
+
};
|
|
3492
|
+
}
|
|
3454
3493
|
var AccountClient = class {
|
|
3455
3494
|
constructor(_r) {
|
|
3456
3495
|
this._r = _r;
|
|
@@ -3493,16 +3532,17 @@ var DirectClient = class {
|
|
|
3493
3532
|
constructor(_r) {
|
|
3494
3533
|
this._r = _r;
|
|
3495
3534
|
}
|
|
3496
|
-
/**
|
|
3535
|
+
/**
|
|
3536
|
+
* Send a direct message to a user.
|
|
3537
|
+
*
|
|
3538
|
+
* v2.0 §4.6 — `content` may now be a `ContentBlock[]` for multimodal sends.
|
|
3539
|
+
* v2.0 §3.0.2 Gap A-④ — when `options.idempotencyKey` is omitted, the SDK
|
|
3540
|
+
* generates a UUID per call and stamps it into the `X-Idempotency-Key`
|
|
3541
|
+
* header. Pass the same key across retries to trigger server dedup.
|
|
3542
|
+
*/
|
|
3497
3543
|
async send(userId, content, options) {
|
|
3498
|
-
|
|
3499
|
-
|
|
3500
|
-
type: options?.type ?? "text",
|
|
3501
|
-
metadata: options?.metadata,
|
|
3502
|
-
attachments: options?.attachments,
|
|
3503
|
-
parentId: options?.parentId,
|
|
3504
|
-
quotedMessageId: options?.quotedMessageId
|
|
3505
|
-
});
|
|
3544
|
+
const { body, opts } = buildSendPayload(content, options);
|
|
3545
|
+
return this._r("POST", `/api/im/direct/${userId}/messages`, body, void 0, opts);
|
|
3506
3546
|
}
|
|
3507
3547
|
/** Get direct message history with a user */
|
|
3508
3548
|
async getMessages(userId, options) {
|
|
@@ -3528,16 +3568,15 @@ var GroupsClient = class {
|
|
|
3528
3568
|
async get(groupId) {
|
|
3529
3569
|
return this._r("GET", `/api/im/groups/${groupId}`);
|
|
3530
3570
|
}
|
|
3531
|
-
/**
|
|
3571
|
+
/**
|
|
3572
|
+
* Send a message to a group.
|
|
3573
|
+
*
|
|
3574
|
+
* v2.0 §4.6 — `content` may now be a `ContentBlock[]` for multimodal sends.
|
|
3575
|
+
* v2.0 §3.0.2 Gap A-④ — auto-generates `X-Idempotency-Key` per call.
|
|
3576
|
+
*/
|
|
3532
3577
|
async send(groupId, content, options) {
|
|
3533
|
-
|
|
3534
|
-
|
|
3535
|
-
type: options?.type ?? "text",
|
|
3536
|
-
metadata: options?.metadata,
|
|
3537
|
-
attachments: options?.attachments,
|
|
3538
|
-
parentId: options?.parentId,
|
|
3539
|
-
quotedMessageId: options?.quotedMessageId
|
|
3540
|
-
});
|
|
3578
|
+
const { body, opts } = buildSendPayload(content, options);
|
|
3579
|
+
return this._r("POST", `/api/im/groups/${groupId}/messages`, body, void 0, opts);
|
|
3541
3580
|
}
|
|
3542
3581
|
/** Get group message history */
|
|
3543
3582
|
async getMessages(groupId, options) {
|
|
@@ -3607,16 +3646,23 @@ var MessagesClient = class {
|
|
|
3607
3646
|
constructor(_r) {
|
|
3608
3647
|
this._r = _r;
|
|
3609
3648
|
}
|
|
3610
|
-
/**
|
|
3649
|
+
/**
|
|
3650
|
+
* Send a message to a conversation.
|
|
3651
|
+
*
|
|
3652
|
+
* v2.0 §4.6 — `content` may now be a `ContentBlock[]` for multimodal sends.
|
|
3653
|
+
* The SDK serialises ContentBlock[] into `body.contentBlocks` (preferred
|
|
3654
|
+
* path) while still writing a string `content` for legacy renderers during
|
|
3655
|
+
* the §4.6 6-sprint double-read window.
|
|
3656
|
+
*
|
|
3657
|
+
* v2.0 §3.0.2 Gap A-④ — when `options.idempotencyKey` is omitted, the SDK
|
|
3658
|
+
* auto-generates `crypto.randomUUID()` per call and includes it as the
|
|
3659
|
+
* `X-Idempotency-Key` HTTP header. The server applies UNIQUE
|
|
3660
|
+
* `(conversationId, idempotencyKey)` dedup; pass the same key across
|
|
3661
|
+
* retries to safely re-send.
|
|
3662
|
+
*/
|
|
3611
3663
|
async send(conversationId, content, options) {
|
|
3612
|
-
|
|
3613
|
-
|
|
3614
|
-
type: options?.type ?? "text",
|
|
3615
|
-
metadata: options?.metadata,
|
|
3616
|
-
attachments: options?.attachments,
|
|
3617
|
-
parentId: options?.parentId,
|
|
3618
|
-
quotedMessageId: options?.quotedMessageId
|
|
3619
|
-
});
|
|
3664
|
+
const { body, opts } = buildSendPayload(content, options);
|
|
3665
|
+
return this._r("POST", `/api/im/messages/${conversationId}`, body, void 0, opts);
|
|
3620
3666
|
}
|
|
3621
3667
|
/** Get message history for a conversation */
|
|
3622
3668
|
async getHistory(conversationId, options) {
|
|
@@ -4154,6 +4200,46 @@ var EvolutionSkillsClient = class {
|
|
|
4154
4200
|
return this._r("POST", `/api/im/skills/${encodeURIComponent(skillId)}/star`);
|
|
4155
4201
|
}
|
|
4156
4202
|
};
|
|
4203
|
+
var AgentsClient = class {
|
|
4204
|
+
constructor(_r) {
|
|
4205
|
+
this._r = _r;
|
|
4206
|
+
}
|
|
4207
|
+
async spec(agentId, workspaceId) {
|
|
4208
|
+
const query = workspaceId ? { workspaceId } : void 0;
|
|
4209
|
+
return this._r("GET", `/api/im/agents/${encodeURIComponent(agentId)}/spec`, void 0, query);
|
|
4210
|
+
}
|
|
4211
|
+
async snapshot(agentId, options) {
|
|
4212
|
+
return this._r("POST", `/api/im/agents/${encodeURIComponent(agentId)}/snapshot`, options ?? {});
|
|
4213
|
+
}
|
|
4214
|
+
async snapshots(agentId, options) {
|
|
4215
|
+
const query = {};
|
|
4216
|
+
if (options?.cursor) query.cursor = options.cursor;
|
|
4217
|
+
if (options?.limit != null) query.limit = String(options.limit);
|
|
4218
|
+
return this._r("GET", `/api/im/agents/${encodeURIComponent(agentId)}/snapshots`, void 0, query);
|
|
4219
|
+
}
|
|
4220
|
+
async restore(agentId, options) {
|
|
4221
|
+
return this._r("POST", `/api/im/agents/${encodeURIComponent(agentId)}/restore`, options);
|
|
4222
|
+
}
|
|
4223
|
+
async publish(agentId, options) {
|
|
4224
|
+
return this._r("POST", `/api/im/agents/${encodeURIComponent(agentId)}/publish`, options ?? {});
|
|
4225
|
+
}
|
|
4226
|
+
async listPacks(options) {
|
|
4227
|
+
const query = {};
|
|
4228
|
+
if (options?.q) query.q = options.q;
|
|
4229
|
+
if (options?.curatedQuality) query.curatedQuality = options.curatedQuality;
|
|
4230
|
+
if (options?.license) query.license = options.license;
|
|
4231
|
+
if (options?.publisherDid) query.publisherDid = options.publisherDid;
|
|
4232
|
+
if (options?.cursor) query.cursor = options.cursor;
|
|
4233
|
+
if (options?.limit != null) query.limit = String(options.limit);
|
|
4234
|
+
return this._r("GET", "/api/im/agent-packs", void 0, query);
|
|
4235
|
+
}
|
|
4236
|
+
async forkPack(packIdOrSlug, options) {
|
|
4237
|
+
return this._r("POST", `/api/im/agent-packs/${encodeURIComponent(packIdOrSlug)}/fork`, options);
|
|
4238
|
+
}
|
|
4239
|
+
async deletePack(packIdOrSlug) {
|
|
4240
|
+
return this._r("DELETE", `/api/im/agent-packs/${encodeURIComponent(packIdOrSlug)}`);
|
|
4241
|
+
}
|
|
4242
|
+
};
|
|
4157
4243
|
var EvolutionClient = class {
|
|
4158
4244
|
constructor(_r) {
|
|
4159
4245
|
this._r = _r;
|
|
@@ -5394,6 +5480,7 @@ var IMClient = class {
|
|
|
5394
5480
|
this.knowledge = new KnowledgeLinkClient(request);
|
|
5395
5481
|
this.identity = new IdentityClient(request);
|
|
5396
5482
|
this.security = new SecurityClient(request);
|
|
5483
|
+
this.agents = new AgentsClient(request);
|
|
5397
5484
|
this.evolution = new EvolutionClient(request);
|
|
5398
5485
|
this.community = new CommunityHub(request, communityHubConfig ?? void 0);
|
|
5399
5486
|
this.files = new FilesClient(request, wsBase, fetchFn, getAuthHeaders);
|
|
@@ -5459,6 +5546,9 @@ var PrismerClient = class {
|
|
|
5459
5546
|
if (config.offline) {
|
|
5460
5547
|
this._offlineManager = new OfflineManager(
|
|
5461
5548
|
config.offline.storage,
|
|
5549
|
+
// OfflineManager has a 4-arg RequestFn signature (legacy); the 5th
|
|
5550
|
+
// opts param is dropped on the offline path until OfflineManager is
|
|
5551
|
+
// upgraded. Online path forwards opts (see below).
|
|
5462
5552
|
(m, p, b, q) => this._request(m, p, b, q),
|
|
5463
5553
|
config.offline
|
|
5464
5554
|
);
|
|
@@ -5466,23 +5556,28 @@ var PrismerClient = class {
|
|
|
5466
5556
|
(err) => console.warn("[PrismerSDK] Offline storage init failed:", err)
|
|
5467
5557
|
);
|
|
5468
5558
|
}
|
|
5469
|
-
let imRequest = this._offlineManager ? (m, p, b, q
|
|
5559
|
+
let imRequest = this._offlineManager ? (m, p, b, q, _opts) => (
|
|
5560
|
+
// Offline path: opts dropped (manager doesn't forward headers yet).
|
|
5561
|
+
// Idempotency key is also stamped into the body JSON, so server-side
|
|
5562
|
+
// dedup still works via the JSON field even without the header.
|
|
5563
|
+
this._offlineManager.dispatch(m, p, b, q)
|
|
5564
|
+
) : (m, p, b, q, opts) => this._request(m, p, b, q, opts);
|
|
5470
5565
|
if (config.identity) {
|
|
5471
5566
|
const baseRequest = imRequest;
|
|
5472
|
-
imRequest = (method, path, body, query) => {
|
|
5567
|
+
imRequest = (method, path, body, query, opts) => {
|
|
5473
5568
|
if (method === "POST" && path.includes("/messages") && body) {
|
|
5474
5569
|
const b = body;
|
|
5475
5570
|
if (!b.signature && !b.skipSigning) {
|
|
5476
5571
|
const ready = this._identityReady || Promise.resolve();
|
|
5477
5572
|
return ready.then(() => {
|
|
5478
5573
|
if (this._identity) {
|
|
5479
|
-
return this._signAndSend(baseRequest, method, path, b, query);
|
|
5574
|
+
return this._signAndSend(baseRequest, method, path, b, query, opts);
|
|
5480
5575
|
}
|
|
5481
|
-
return baseRequest(method, path, body, query);
|
|
5576
|
+
return baseRequest(method, path, body, query, opts);
|
|
5482
5577
|
});
|
|
5483
5578
|
}
|
|
5484
5579
|
}
|
|
5485
|
-
return baseRequest(method, path, body, query);
|
|
5580
|
+
return baseRequest(method, path, body, query, opts);
|
|
5486
5581
|
};
|
|
5487
5582
|
}
|
|
5488
5583
|
this.im = new IMClient(
|
|
@@ -5504,9 +5599,9 @@ var PrismerClient = class {
|
|
|
5504
5599
|
return this._identity;
|
|
5505
5600
|
}
|
|
5506
5601
|
/** Auto-sign a message body and send (v1.8.0 S1) */
|
|
5507
|
-
async _signAndSend(baseRequest, method, path, body, query) {
|
|
5602
|
+
async _signAndSend(baseRequest, method, path, body, query, opts) {
|
|
5508
5603
|
if (this._identityReady) await this._identityReady;
|
|
5509
|
-
if (!this._identity) return baseRequest(method, path, body, query);
|
|
5604
|
+
if (!this._identity) return baseRequest(method, path, body, query, opts);
|
|
5510
5605
|
const content = body.content || "";
|
|
5511
5606
|
const contentHashBytes = new Uint8Array(
|
|
5512
5607
|
await crypto.subtle.digest("SHA-256", new TextEncoder().encode(content))
|
|
@@ -5523,7 +5618,7 @@ var PrismerClient = class {
|
|
|
5523
5618
|
contentHash,
|
|
5524
5619
|
signature,
|
|
5525
5620
|
signedAt: timestamp
|
|
5526
|
-
}, query);
|
|
5621
|
+
}, query, opts);
|
|
5527
5622
|
}
|
|
5528
5623
|
/** Build auth headers for raw HTTP requests (used by file upload) */
|
|
5529
5624
|
_getAuthHeaders() {
|
|
@@ -5581,7 +5676,7 @@ var PrismerClient = class {
|
|
|
5581
5676
|
// --------------------------------------------------------------------------
|
|
5582
5677
|
// Internal request helper
|
|
5583
5678
|
// --------------------------------------------------------------------------
|
|
5584
|
-
async _request(method, path, body, query, _isRetry) {
|
|
5679
|
+
async _request(method, path, body, query, opts, _isRetry) {
|
|
5585
5680
|
const controller = new AbortController();
|
|
5586
5681
|
const timeoutId = setTimeout(() => controller.abort(), this.timeout);
|
|
5587
5682
|
try {
|
|
@@ -5596,6 +5691,9 @@ var PrismerClient = class {
|
|
|
5596
5691
|
if (this.imAgent) {
|
|
5597
5692
|
headers["X-IM-Agent"] = this.imAgent;
|
|
5598
5693
|
}
|
|
5694
|
+
if (opts?.headers) {
|
|
5695
|
+
for (const [k, v] of Object.entries(opts.headers)) headers[k] = v;
|
|
5696
|
+
}
|
|
5599
5697
|
const init = { method, headers, signal: controller.signal };
|
|
5600
5698
|
if (body !== void 0) {
|
|
5601
5699
|
headers["Content-Type"] = "application/json";
|
|
@@ -5605,10 +5703,10 @@ var PrismerClient = class {
|
|
|
5605
5703
|
const data = await response.json();
|
|
5606
5704
|
if (response.status === 401 && this.apiKey.startsWith("eyJ") && !_isRetry && !path.includes("/token/refresh")) {
|
|
5607
5705
|
try {
|
|
5608
|
-
const refreshRes = await this._request("POST", "/api/im/token/refresh", void 0, void 0, true);
|
|
5706
|
+
const refreshRes = await this._request("POST", "/api/im/token/refresh", void 0, void 0, void 0, true);
|
|
5609
5707
|
if (refreshRes?.ok && refreshRes?.data?.token) {
|
|
5610
5708
|
this.apiKey = refreshRes.data.token;
|
|
5611
|
-
return this._request(method, path, body, query, true);
|
|
5709
|
+
return this._request(method, path, body, query, opts, true);
|
|
5612
5710
|
}
|
|
5613
5711
|
} catch {
|
|
5614
5712
|
}
|
|
@@ -5702,6 +5800,7 @@ function createClient(config) {
|
|
|
5702
5800
|
0 && (module.exports = {
|
|
5703
5801
|
AIPIdentity,
|
|
5704
5802
|
AccountClient,
|
|
5803
|
+
AgentsClient,
|
|
5705
5804
|
AssetsClient,
|
|
5706
5805
|
AttachmentQueue,
|
|
5707
5806
|
BindingsClient,
|
package/dist/index.mjs
CHANGED
|
@@ -3382,6 +3382,44 @@ function resolveBaseUrl(explicit) {
|
|
|
3382
3382
|
}
|
|
3383
3383
|
return void 0;
|
|
3384
3384
|
}
|
|
3385
|
+
function generateIdempotencyKey() {
|
|
3386
|
+
try {
|
|
3387
|
+
if (typeof crypto !== "undefined" && typeof crypto.randomUUID === "function") {
|
|
3388
|
+
return crypto.randomUUID();
|
|
3389
|
+
}
|
|
3390
|
+
} catch {
|
|
3391
|
+
}
|
|
3392
|
+
return "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, (c) => {
|
|
3393
|
+
const r = Math.random() * 16 | 0;
|
|
3394
|
+
return (c === "x" ? r : r & 3 | 8).toString(16);
|
|
3395
|
+
});
|
|
3396
|
+
}
|
|
3397
|
+
function buildSendPayload(content, options) {
|
|
3398
|
+
const key = options?.idempotencyKey ?? generateIdempotencyKey();
|
|
3399
|
+
const isBlocks = Array.isArray(content);
|
|
3400
|
+
const body = {
|
|
3401
|
+
// For ContentBlock[] inputs, populate `content` as a fallback summary
|
|
3402
|
+
// (server's legacy `content` column stays compatible during the 6-sprint
|
|
3403
|
+
// double-write window from §4.6); the SOT is `contentBlocks`.
|
|
3404
|
+
content: isBlocks ? "" : content,
|
|
3405
|
+
type: options?.type ?? "text",
|
|
3406
|
+
metadata: options?.metadata,
|
|
3407
|
+
attachments: options?.attachments,
|
|
3408
|
+
parentId: options?.parentId,
|
|
3409
|
+
quotedMessageId: options?.quotedMessageId,
|
|
3410
|
+
idempotencyKey: key
|
|
3411
|
+
};
|
|
3412
|
+
if (isBlocks) {
|
|
3413
|
+
body.contentBlocks = content;
|
|
3414
|
+
} else if (options?.contentBlocks) {
|
|
3415
|
+
body.contentBlocks = options.contentBlocks;
|
|
3416
|
+
}
|
|
3417
|
+
return {
|
|
3418
|
+
body,
|
|
3419
|
+
opts: { headers: { "X-Idempotency-Key": key } },
|
|
3420
|
+
key
|
|
3421
|
+
};
|
|
3422
|
+
}
|
|
3385
3423
|
var AccountClient = class {
|
|
3386
3424
|
constructor(_r) {
|
|
3387
3425
|
this._r = _r;
|
|
@@ -3424,16 +3462,17 @@ var DirectClient = class {
|
|
|
3424
3462
|
constructor(_r) {
|
|
3425
3463
|
this._r = _r;
|
|
3426
3464
|
}
|
|
3427
|
-
/**
|
|
3465
|
+
/**
|
|
3466
|
+
* Send a direct message to a user.
|
|
3467
|
+
*
|
|
3468
|
+
* v2.0 §4.6 — `content` may now be a `ContentBlock[]` for multimodal sends.
|
|
3469
|
+
* v2.0 §3.0.2 Gap A-④ — when `options.idempotencyKey` is omitted, the SDK
|
|
3470
|
+
* generates a UUID per call and stamps it into the `X-Idempotency-Key`
|
|
3471
|
+
* header. Pass the same key across retries to trigger server dedup.
|
|
3472
|
+
*/
|
|
3428
3473
|
async send(userId, content, options) {
|
|
3429
|
-
|
|
3430
|
-
|
|
3431
|
-
type: options?.type ?? "text",
|
|
3432
|
-
metadata: options?.metadata,
|
|
3433
|
-
attachments: options?.attachments,
|
|
3434
|
-
parentId: options?.parentId,
|
|
3435
|
-
quotedMessageId: options?.quotedMessageId
|
|
3436
|
-
});
|
|
3474
|
+
const { body, opts } = buildSendPayload(content, options);
|
|
3475
|
+
return this._r("POST", `/api/im/direct/${userId}/messages`, body, void 0, opts);
|
|
3437
3476
|
}
|
|
3438
3477
|
/** Get direct message history with a user */
|
|
3439
3478
|
async getMessages(userId, options) {
|
|
@@ -3459,16 +3498,15 @@ var GroupsClient = class {
|
|
|
3459
3498
|
async get(groupId) {
|
|
3460
3499
|
return this._r("GET", `/api/im/groups/${groupId}`);
|
|
3461
3500
|
}
|
|
3462
|
-
/**
|
|
3501
|
+
/**
|
|
3502
|
+
* Send a message to a group.
|
|
3503
|
+
*
|
|
3504
|
+
* v2.0 §4.6 — `content` may now be a `ContentBlock[]` for multimodal sends.
|
|
3505
|
+
* v2.0 §3.0.2 Gap A-④ — auto-generates `X-Idempotency-Key` per call.
|
|
3506
|
+
*/
|
|
3463
3507
|
async send(groupId, content, options) {
|
|
3464
|
-
|
|
3465
|
-
|
|
3466
|
-
type: options?.type ?? "text",
|
|
3467
|
-
metadata: options?.metadata,
|
|
3468
|
-
attachments: options?.attachments,
|
|
3469
|
-
parentId: options?.parentId,
|
|
3470
|
-
quotedMessageId: options?.quotedMessageId
|
|
3471
|
-
});
|
|
3508
|
+
const { body, opts } = buildSendPayload(content, options);
|
|
3509
|
+
return this._r("POST", `/api/im/groups/${groupId}/messages`, body, void 0, opts);
|
|
3472
3510
|
}
|
|
3473
3511
|
/** Get group message history */
|
|
3474
3512
|
async getMessages(groupId, options) {
|
|
@@ -3538,16 +3576,23 @@ var MessagesClient = class {
|
|
|
3538
3576
|
constructor(_r) {
|
|
3539
3577
|
this._r = _r;
|
|
3540
3578
|
}
|
|
3541
|
-
/**
|
|
3579
|
+
/**
|
|
3580
|
+
* Send a message to a conversation.
|
|
3581
|
+
*
|
|
3582
|
+
* v2.0 §4.6 — `content` may now be a `ContentBlock[]` for multimodal sends.
|
|
3583
|
+
* The SDK serialises ContentBlock[] into `body.contentBlocks` (preferred
|
|
3584
|
+
* path) while still writing a string `content` for legacy renderers during
|
|
3585
|
+
* the §4.6 6-sprint double-read window.
|
|
3586
|
+
*
|
|
3587
|
+
* v2.0 §3.0.2 Gap A-④ — when `options.idempotencyKey` is omitted, the SDK
|
|
3588
|
+
* auto-generates `crypto.randomUUID()` per call and includes it as the
|
|
3589
|
+
* `X-Idempotency-Key` HTTP header. The server applies UNIQUE
|
|
3590
|
+
* `(conversationId, idempotencyKey)` dedup; pass the same key across
|
|
3591
|
+
* retries to safely re-send.
|
|
3592
|
+
*/
|
|
3542
3593
|
async send(conversationId, content, options) {
|
|
3543
|
-
|
|
3544
|
-
|
|
3545
|
-
type: options?.type ?? "text",
|
|
3546
|
-
metadata: options?.metadata,
|
|
3547
|
-
attachments: options?.attachments,
|
|
3548
|
-
parentId: options?.parentId,
|
|
3549
|
-
quotedMessageId: options?.quotedMessageId
|
|
3550
|
-
});
|
|
3594
|
+
const { body, opts } = buildSendPayload(content, options);
|
|
3595
|
+
return this._r("POST", `/api/im/messages/${conversationId}`, body, void 0, opts);
|
|
3551
3596
|
}
|
|
3552
3597
|
/** Get message history for a conversation */
|
|
3553
3598
|
async getHistory(conversationId, options) {
|
|
@@ -4085,6 +4130,46 @@ var EvolutionSkillsClient = class {
|
|
|
4085
4130
|
return this._r("POST", `/api/im/skills/${encodeURIComponent(skillId)}/star`);
|
|
4086
4131
|
}
|
|
4087
4132
|
};
|
|
4133
|
+
var AgentsClient = class {
|
|
4134
|
+
constructor(_r) {
|
|
4135
|
+
this._r = _r;
|
|
4136
|
+
}
|
|
4137
|
+
async spec(agentId, workspaceId) {
|
|
4138
|
+
const query = workspaceId ? { workspaceId } : void 0;
|
|
4139
|
+
return this._r("GET", `/api/im/agents/${encodeURIComponent(agentId)}/spec`, void 0, query);
|
|
4140
|
+
}
|
|
4141
|
+
async snapshot(agentId, options) {
|
|
4142
|
+
return this._r("POST", `/api/im/agents/${encodeURIComponent(agentId)}/snapshot`, options ?? {});
|
|
4143
|
+
}
|
|
4144
|
+
async snapshots(agentId, options) {
|
|
4145
|
+
const query = {};
|
|
4146
|
+
if (options?.cursor) query.cursor = options.cursor;
|
|
4147
|
+
if (options?.limit != null) query.limit = String(options.limit);
|
|
4148
|
+
return this._r("GET", `/api/im/agents/${encodeURIComponent(agentId)}/snapshots`, void 0, query);
|
|
4149
|
+
}
|
|
4150
|
+
async restore(agentId, options) {
|
|
4151
|
+
return this._r("POST", `/api/im/agents/${encodeURIComponent(agentId)}/restore`, options);
|
|
4152
|
+
}
|
|
4153
|
+
async publish(agentId, options) {
|
|
4154
|
+
return this._r("POST", `/api/im/agents/${encodeURIComponent(agentId)}/publish`, options ?? {});
|
|
4155
|
+
}
|
|
4156
|
+
async listPacks(options) {
|
|
4157
|
+
const query = {};
|
|
4158
|
+
if (options?.q) query.q = options.q;
|
|
4159
|
+
if (options?.curatedQuality) query.curatedQuality = options.curatedQuality;
|
|
4160
|
+
if (options?.license) query.license = options.license;
|
|
4161
|
+
if (options?.publisherDid) query.publisherDid = options.publisherDid;
|
|
4162
|
+
if (options?.cursor) query.cursor = options.cursor;
|
|
4163
|
+
if (options?.limit != null) query.limit = String(options.limit);
|
|
4164
|
+
return this._r("GET", "/api/im/agent-packs", void 0, query);
|
|
4165
|
+
}
|
|
4166
|
+
async forkPack(packIdOrSlug, options) {
|
|
4167
|
+
return this._r("POST", `/api/im/agent-packs/${encodeURIComponent(packIdOrSlug)}/fork`, options);
|
|
4168
|
+
}
|
|
4169
|
+
async deletePack(packIdOrSlug) {
|
|
4170
|
+
return this._r("DELETE", `/api/im/agent-packs/${encodeURIComponent(packIdOrSlug)}`);
|
|
4171
|
+
}
|
|
4172
|
+
};
|
|
4088
4173
|
var EvolutionClient = class {
|
|
4089
4174
|
constructor(_r) {
|
|
4090
4175
|
this._r = _r;
|
|
@@ -5325,6 +5410,7 @@ var IMClient = class {
|
|
|
5325
5410
|
this.knowledge = new KnowledgeLinkClient(request);
|
|
5326
5411
|
this.identity = new IdentityClient(request);
|
|
5327
5412
|
this.security = new SecurityClient(request);
|
|
5413
|
+
this.agents = new AgentsClient(request);
|
|
5328
5414
|
this.evolution = new EvolutionClient(request);
|
|
5329
5415
|
this.community = new CommunityHub(request, communityHubConfig ?? void 0);
|
|
5330
5416
|
this.files = new FilesClient(request, wsBase, fetchFn, getAuthHeaders);
|
|
@@ -5390,6 +5476,9 @@ var PrismerClient = class {
|
|
|
5390
5476
|
if (config.offline) {
|
|
5391
5477
|
this._offlineManager = new OfflineManager(
|
|
5392
5478
|
config.offline.storage,
|
|
5479
|
+
// OfflineManager has a 4-arg RequestFn signature (legacy); the 5th
|
|
5480
|
+
// opts param is dropped on the offline path until OfflineManager is
|
|
5481
|
+
// upgraded. Online path forwards opts (see below).
|
|
5393
5482
|
(m, p, b, q) => this._request(m, p, b, q),
|
|
5394
5483
|
config.offline
|
|
5395
5484
|
);
|
|
@@ -5397,23 +5486,28 @@ var PrismerClient = class {
|
|
|
5397
5486
|
(err) => console.warn("[PrismerSDK] Offline storage init failed:", err)
|
|
5398
5487
|
);
|
|
5399
5488
|
}
|
|
5400
|
-
let imRequest = this._offlineManager ? (m, p, b, q
|
|
5489
|
+
let imRequest = this._offlineManager ? (m, p, b, q, _opts) => (
|
|
5490
|
+
// Offline path: opts dropped (manager doesn't forward headers yet).
|
|
5491
|
+
// Idempotency key is also stamped into the body JSON, so server-side
|
|
5492
|
+
// dedup still works via the JSON field even without the header.
|
|
5493
|
+
this._offlineManager.dispatch(m, p, b, q)
|
|
5494
|
+
) : (m, p, b, q, opts) => this._request(m, p, b, q, opts);
|
|
5401
5495
|
if (config.identity) {
|
|
5402
5496
|
const baseRequest = imRequest;
|
|
5403
|
-
imRequest = (method, path, body, query) => {
|
|
5497
|
+
imRequest = (method, path, body, query, opts) => {
|
|
5404
5498
|
if (method === "POST" && path.includes("/messages") && body) {
|
|
5405
5499
|
const b = body;
|
|
5406
5500
|
if (!b.signature && !b.skipSigning) {
|
|
5407
5501
|
const ready = this._identityReady || Promise.resolve();
|
|
5408
5502
|
return ready.then(() => {
|
|
5409
5503
|
if (this._identity) {
|
|
5410
|
-
return this._signAndSend(baseRequest, method, path, b, query);
|
|
5504
|
+
return this._signAndSend(baseRequest, method, path, b, query, opts);
|
|
5411
5505
|
}
|
|
5412
|
-
return baseRequest(method, path, body, query);
|
|
5506
|
+
return baseRequest(method, path, body, query, opts);
|
|
5413
5507
|
});
|
|
5414
5508
|
}
|
|
5415
5509
|
}
|
|
5416
|
-
return baseRequest(method, path, body, query);
|
|
5510
|
+
return baseRequest(method, path, body, query, opts);
|
|
5417
5511
|
};
|
|
5418
5512
|
}
|
|
5419
5513
|
this.im = new IMClient(
|
|
@@ -5435,9 +5529,9 @@ var PrismerClient = class {
|
|
|
5435
5529
|
return this._identity;
|
|
5436
5530
|
}
|
|
5437
5531
|
/** Auto-sign a message body and send (v1.8.0 S1) */
|
|
5438
|
-
async _signAndSend(baseRequest, method, path, body, query) {
|
|
5532
|
+
async _signAndSend(baseRequest, method, path, body, query, opts) {
|
|
5439
5533
|
if (this._identityReady) await this._identityReady;
|
|
5440
|
-
if (!this._identity) return baseRequest(method, path, body, query);
|
|
5534
|
+
if (!this._identity) return baseRequest(method, path, body, query, opts);
|
|
5441
5535
|
const content = body.content || "";
|
|
5442
5536
|
const contentHashBytes = new Uint8Array(
|
|
5443
5537
|
await crypto.subtle.digest("SHA-256", new TextEncoder().encode(content))
|
|
@@ -5454,7 +5548,7 @@ var PrismerClient = class {
|
|
|
5454
5548
|
contentHash,
|
|
5455
5549
|
signature,
|
|
5456
5550
|
signedAt: timestamp
|
|
5457
|
-
}, query);
|
|
5551
|
+
}, query, opts);
|
|
5458
5552
|
}
|
|
5459
5553
|
/** Build auth headers for raw HTTP requests (used by file upload) */
|
|
5460
5554
|
_getAuthHeaders() {
|
|
@@ -5512,7 +5606,7 @@ var PrismerClient = class {
|
|
|
5512
5606
|
// --------------------------------------------------------------------------
|
|
5513
5607
|
// Internal request helper
|
|
5514
5608
|
// --------------------------------------------------------------------------
|
|
5515
|
-
async _request(method, path, body, query, _isRetry) {
|
|
5609
|
+
async _request(method, path, body, query, opts, _isRetry) {
|
|
5516
5610
|
const controller = new AbortController();
|
|
5517
5611
|
const timeoutId = setTimeout(() => controller.abort(), this.timeout);
|
|
5518
5612
|
try {
|
|
@@ -5527,6 +5621,9 @@ var PrismerClient = class {
|
|
|
5527
5621
|
if (this.imAgent) {
|
|
5528
5622
|
headers["X-IM-Agent"] = this.imAgent;
|
|
5529
5623
|
}
|
|
5624
|
+
if (opts?.headers) {
|
|
5625
|
+
for (const [k, v] of Object.entries(opts.headers)) headers[k] = v;
|
|
5626
|
+
}
|
|
5530
5627
|
const init = { method, headers, signal: controller.signal };
|
|
5531
5628
|
if (body !== void 0) {
|
|
5532
5629
|
headers["Content-Type"] = "application/json";
|
|
@@ -5536,10 +5633,10 @@ var PrismerClient = class {
|
|
|
5536
5633
|
const data = await response.json();
|
|
5537
5634
|
if (response.status === 401 && this.apiKey.startsWith("eyJ") && !_isRetry && !path.includes("/token/refresh")) {
|
|
5538
5635
|
try {
|
|
5539
|
-
const refreshRes = await this._request("POST", "/api/im/token/refresh", void 0, void 0, true);
|
|
5636
|
+
const refreshRes = await this._request("POST", "/api/im/token/refresh", void 0, void 0, void 0, true);
|
|
5540
5637
|
if (refreshRes?.ok && refreshRes?.data?.token) {
|
|
5541
5638
|
this.apiKey = refreshRes.data.token;
|
|
5542
|
-
return this._request(method, path, body, query, true);
|
|
5639
|
+
return this._request(method, path, body, query, opts, true);
|
|
5543
5640
|
}
|
|
5544
5641
|
} catch {
|
|
5545
5642
|
}
|
|
@@ -5632,6 +5729,7 @@ function createClient(config) {
|
|
|
5632
5729
|
export {
|
|
5633
5730
|
AIPIdentity,
|
|
5634
5731
|
AccountClient,
|
|
5732
|
+
AgentsClient,
|
|
5635
5733
|
AssetsClient,
|
|
5636
5734
|
AttachmentQueue,
|
|
5637
5735
|
BindingsClient,
|