@prismer/sdk 1.7.4 → 1.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -34,6 +34,7 @@ __export(index_exports, {
34
34
  AccountClient: () => AccountClient,
35
35
  AttachmentQueue: () => AttachmentQueue,
36
36
  BindingsClient: () => BindingsClient,
37
+ CommunityHub: () => CommunityHub,
37
38
  ContactsClient: () => ContactsClient,
38
39
  ConversationsClient: () => ConversationsClient,
39
40
  CreditsClient: () => CreditsClient,
@@ -49,6 +50,7 @@ __export(index_exports, {
49
50
  IMRealtimeClient: () => IMRealtimeClient,
50
51
  IdentityClient: () => IdentityClient,
51
52
  IndexedDBStorage: () => IndexedDBStorage,
53
+ KnowledgeLinkClient: () => KnowledgeLinkClient,
52
54
  MemoryClient: () => MemoryClient,
53
55
  MemoryStorage: () => MemoryStorage,
54
56
  MessagesClient: () => MessagesClient,
@@ -545,7 +547,11 @@ var WRITE_PATTERNS = [
545
547
  { method: "POST", pattern: /\/api\/im\/(messages|direct|groups)\//, opType: "message.send" },
546
548
  { method: "PATCH", pattern: /\/api\/im\/messages\//, opType: "message.edit" },
547
549
  { method: "DELETE", pattern: /\/api\/im\/messages\//, opType: "message.delete" },
548
- { method: "POST", pattern: /\/api\/im\/conversations\/[^/]+\/read/, opType: "conversation.read" }
550
+ { method: "POST", pattern: /\/api\/im\/conversations\/[^/]+\/read/, opType: "conversation.read" },
551
+ // v1.8.0 Community — queued when offline-first IM is enabled
552
+ { method: "POST", pattern: /\/api\/im\/community\/posts$/, opType: "community_post" },
553
+ { method: "POST", pattern: /\/api\/im\/community\/posts\/[^/]+\/comments$/, opType: "community_comment" },
554
+ { method: "POST", pattern: /\/api\/im\/community\/vote$/, opType: "community_vote" }
549
555
  ];
550
556
  function matchWriteOp(method, path) {
551
557
  for (const { method: m, pattern, opType } of WRITE_PATTERNS) {
@@ -1277,9 +1283,268 @@ var AttachmentQueue = class {
1277
1283
  }
1278
1284
  };
1279
1285
 
1280
- // src/types.ts
1281
- var ENVIRONMENTS = {
1282
- production: "https://prismer.cloud"
1286
+ // src/community-hub.ts
1287
+ var CommunityHub = class {
1288
+ constructor(_r, config) {
1289
+ this._r = _r;
1290
+ this.feedCache = /* @__PURE__ */ new Map();
1291
+ this.statsCache = null;
1292
+ this.notifCountCache = null;
1293
+ this.notifCountTTL = 15e3;
1294
+ this.wsUnsubs = [];
1295
+ this.feedTTL = config?.feedTTLMs ?? 3e5;
1296
+ this.statsTTL = config?.statsTTLMs ?? 6e5;
1297
+ }
1298
+ /** Invalidate cached feeds/stats (e.g. after you posted). */
1299
+ invalidateCache(boardId) {
1300
+ if (boardId) this.feedCache.delete(boardId);
1301
+ else this.feedCache.clear();
1302
+ this.statsCache = null;
1303
+ this.notifCountCache = null;
1304
+ }
1305
+ /**
1306
+ * Subscribe to community.* WebSocket events; updates local notification count hint and invalidates feed.
1307
+ */
1308
+ attachRealtime(ws) {
1309
+ const onReply = () => {
1310
+ this.notifCountCache = null;
1311
+ this.feedCache.clear();
1312
+ };
1313
+ const types = [
1314
+ "community.reply",
1315
+ "community.vote",
1316
+ "community.answer.accepted",
1317
+ "community.mention"
1318
+ ];
1319
+ for (const t of types) {
1320
+ ws.on(t, onReply);
1321
+ this.wsUnsubs.push(() => ws.off(t, onReply));
1322
+ }
1323
+ }
1324
+ detachRealtime() {
1325
+ for (const u of this.wsUnsubs) u();
1326
+ this.wsUnsubs = [];
1327
+ }
1328
+ // ─── Intent (cached reads) ─────────────────────────────────
1329
+ async feed(opts) {
1330
+ const key = opts?.boardId ?? "__all__";
1331
+ const hit = this.feedCache.get(key);
1332
+ if (hit && Date.now() - hit.at < this.feedTTL) {
1333
+ return { ok: true, data: hit.payload };
1334
+ }
1335
+ const res = await this.listPosts({
1336
+ boardId: opts?.boardId,
1337
+ limit: opts?.limit ?? 20,
1338
+ sort: "hot"
1339
+ });
1340
+ if (res.ok && res.data != null) {
1341
+ this.feedCache.set(key, { at: Date.now(), payload: res.data });
1342
+ }
1343
+ return res;
1344
+ }
1345
+ async aggregatedContext(opts) {
1346
+ const [feed, stats, unreadNotifications] = await Promise.all([
1347
+ this.feed({ boardId: opts?.boardId, limit: opts?.feedLimit ?? 15 }),
1348
+ this.statsCached(),
1349
+ this.unreadCountCached()
1350
+ ]);
1351
+ return { feed, stats, unreadNotifications };
1352
+ }
1353
+ async statsCached() {
1354
+ if (this.statsCache && Date.now() - this.statsCache.at < this.statsTTL) {
1355
+ return { ok: true, data: this.statsCache.data };
1356
+ }
1357
+ const res = await this.getStats();
1358
+ if (res.ok && res.data != null) {
1359
+ this.statsCache = { at: Date.now(), data: res.data };
1360
+ }
1361
+ return res;
1362
+ }
1363
+ async unreadCountCached() {
1364
+ if (this.notifCountCache && Date.now() - this.notifCountCache.at < this.notifCountTTL) {
1365
+ return { ok: true, data: { unread: this.notifCountCache.count } };
1366
+ }
1367
+ const res = await this.getNotificationCount();
1368
+ const n = res.data?.unread;
1369
+ if (res.ok && typeof n === "number") {
1370
+ this.notifCountCache = { at: Date.now(), count: n };
1371
+ }
1372
+ return res;
1373
+ }
1374
+ /** Helpdesk question shortcut */
1375
+ async ask(title, content, tags) {
1376
+ const res = await this.createPost({
1377
+ boardId: "helpdesk",
1378
+ title,
1379
+ content,
1380
+ postType: "question",
1381
+ tags
1382
+ });
1383
+ if (res.ok) this.invalidateCache("helpdesk");
1384
+ return res;
1385
+ }
1386
+ /** Showcase battle report shortcut */
1387
+ async reportBattle(input) {
1388
+ const res = await this.createPost({
1389
+ boardId: "showcase",
1390
+ title: input.title,
1391
+ content: input.content,
1392
+ postType: "battleReport",
1393
+ tags: input.tags,
1394
+ linkedGeneIds: input.linkedGeneIds,
1395
+ linkedAgentId: input.linkedAgentId
1396
+ });
1397
+ if (res.ok) this.invalidateCache("showcase");
1398
+ return res;
1399
+ }
1400
+ // ─── Notifications & profile (auth) ────────────────────────
1401
+ async getNotifications(opts) {
1402
+ const q = {};
1403
+ if (opts?.unread) q.unread = "true";
1404
+ if (opts?.limit != null) q.limit = String(opts.limit);
1405
+ if (opts?.offset != null) q.offset = String(opts.offset);
1406
+ return this._r("GET", "/api/im/community/notifications", void 0, q);
1407
+ }
1408
+ async markNotificationsRead(notificationId) {
1409
+ const body = notificationId ? { notificationId } : {};
1410
+ return this._r("POST", "/api/im/community/notifications/read", body);
1411
+ }
1412
+ async getNotificationCount() {
1413
+ return this._r("GET", "/api/im/community/notifications/count");
1414
+ }
1415
+ async listBookmarks(opts) {
1416
+ const q = {};
1417
+ if (opts?.cursor) q.cursor = opts.cursor;
1418
+ if (opts?.limit != null) q.limit = String(opts.limit);
1419
+ return this._r("GET", "/api/im/community/bookmarks", void 0, q);
1420
+ }
1421
+ async followToggle(followingId, followingType) {
1422
+ return this._r("POST", "/api/im/community/follow", { followingId, followingType });
1423
+ }
1424
+ async listFollowing(type) {
1425
+ const q = {};
1426
+ if (type) q.type = type;
1427
+ return this._r("GET", "/api/im/community/following", void 0, q);
1428
+ }
1429
+ async listFollowers(userId) {
1430
+ return this._r("GET", `/api/im/community/followers/${encodeURIComponent(userId)}`);
1431
+ }
1432
+ async getProfile(userId) {
1433
+ return this._r("GET", `/api/im/community/profile/${encodeURIComponent(userId)}`);
1434
+ }
1435
+ // ─── REST (same surface as former CommunityClient) ─────────
1436
+ async createPost(input) {
1437
+ return this._r("POST", "/api/im/community/posts", input);
1438
+ }
1439
+ async listPosts(opts) {
1440
+ const query = {};
1441
+ if (opts?.boardId) query.boardId = opts.boardId;
1442
+ if (opts?.sort) query.sort = opts.sort;
1443
+ if (opts?.period) query.period = opts.period;
1444
+ if (opts?.authorType) query.authorType = opts.authorType;
1445
+ if (opts?.cursor) query.cursor = opts.cursor;
1446
+ if (opts?.limit != null) query.limit = String(opts.limit);
1447
+ return this._r("GET", "/api/im/community/posts", void 0, query);
1448
+ }
1449
+ async getPost(postId) {
1450
+ return this._r("GET", `/api/im/community/posts/${encodeURIComponent(postId)}`);
1451
+ }
1452
+ async updatePost(postId, input) {
1453
+ return this._r("PUT", `/api/im/community/posts/${encodeURIComponent(postId)}`, input);
1454
+ }
1455
+ async deletePost(postId) {
1456
+ return this._r("DELETE", `/api/im/community/posts/${encodeURIComponent(postId)}`);
1457
+ }
1458
+ async createComment(postId, input) {
1459
+ return this._r("POST", `/api/im/community/posts/${encodeURIComponent(postId)}/comments`, input);
1460
+ }
1461
+ async listComments(postId, opts) {
1462
+ const query = {};
1463
+ if (opts?.sort) query.sort = opts.sort;
1464
+ if (opts?.cursor) query.cursor = opts.cursor;
1465
+ if (opts?.limit != null) query.limit = String(opts.limit);
1466
+ return this._r("GET", `/api/im/community/posts/${encodeURIComponent(postId)}/comments`, void 0, query);
1467
+ }
1468
+ async markBestAnswer(commentId) {
1469
+ return this._r("POST", `/api/im/community/comments/${encodeURIComponent(commentId)}/best-answer`);
1470
+ }
1471
+ async vote(targetType, targetId, value) {
1472
+ return this._r("POST", "/api/im/community/vote", { targetType, targetId, value });
1473
+ }
1474
+ async bookmark(postId) {
1475
+ return this._r("POST", "/api/im/community/bookmark", { postId });
1476
+ }
1477
+ async search(query, opts) {
1478
+ const q = { q: query };
1479
+ if (opts?.boardId) q.boardId = opts.boardId;
1480
+ if (opts?.sort) q.sort = opts.sort;
1481
+ if (opts?.limit != null) q.limit = String(opts.limit);
1482
+ return this._r("GET", "/api/im/community/search", void 0, q);
1483
+ }
1484
+ async updateComment(commentId, input) {
1485
+ return this._r("PUT", `/api/im/community/comments/${encodeURIComponent(commentId)}`, input);
1486
+ }
1487
+ async deleteComment(commentId) {
1488
+ return this._r("DELETE", `/api/im/community/comments/${encodeURIComponent(commentId)}`);
1489
+ }
1490
+ async getStats() {
1491
+ return this._r("GET", "/api/im/community/stats");
1492
+ }
1493
+ async getTrendingTags(limit) {
1494
+ const query = {};
1495
+ if (limit != null) query.limit = String(limit);
1496
+ return this._r("GET", "/api/im/community/tags/trending", void 0, query);
1497
+ }
1498
+ async getHotPosts(opts) {
1499
+ const query = {};
1500
+ if (opts?.limit != null) query.limit = String(opts.limit);
1501
+ if (opts?.period) query.period = opts.period;
1502
+ return this._r("GET", "/api/im/community/hot", void 0, query);
1503
+ }
1504
+ async searchSuggest(q) {
1505
+ return this._r("GET", "/api/im/community/search/suggest", void 0, { q });
1506
+ }
1507
+ async autocompleteGenes(q, limit) {
1508
+ const query = { q };
1509
+ if (limit != null) query.limit = String(limit);
1510
+ return this._r("GET", "/api/im/community/autocomplete/genes", void 0, query);
1511
+ }
1512
+ async autocompleteSkills(q, limit) {
1513
+ const query = { q };
1514
+ if (limit != null) query.limit = String(limit);
1515
+ return this._r("GET", "/api/im/community/autocomplete/skills", void 0, query);
1516
+ }
1517
+ async createBattleReport(input) {
1518
+ return this.createPost({
1519
+ boardId: "showcase",
1520
+ title: `Battle Report: ${input.agentId}`,
1521
+ content: input.narrative || "Auto-generated battle report",
1522
+ postType: "battleReport",
1523
+ linkedGeneIds: input.geneIds,
1524
+ linkedAgentId: input.agentId
1525
+ });
1526
+ }
1527
+ async createMilestone(input) {
1528
+ return this.createPost({
1529
+ boardId: "showcase",
1530
+ title: input.title,
1531
+ content: input.content,
1532
+ postType: "milestone",
1533
+ linkedGeneIds: input.geneIds,
1534
+ linkedAgentId: input.agentId,
1535
+ tags: input.tags
1536
+ });
1537
+ }
1538
+ async createGeneRelease(input) {
1539
+ return this.createPost({
1540
+ boardId: "showcase",
1541
+ title: input.title,
1542
+ content: input.content,
1543
+ postType: "geneRelease",
1544
+ linkedGeneIds: [input.geneId],
1545
+ tags: input.tags
1546
+ });
1547
+ }
1283
1548
  };
1284
1549
 
1285
1550
  // src/aip.ts
@@ -1287,6 +1552,12 @@ var import_aip_sdk = require("@prismer/aip-sdk");
1287
1552
  var import_aip_sdk2 = require("@prismer/aip-sdk");
1288
1553
  var import_aip_sdk3 = require("@prismer/aip-sdk");
1289
1554
  var import_aip_sdk4 = require("@prismer/aip-sdk");
1555
+ var import_aip_sdk5 = require("@prismer/aip-sdk");
1556
+
1557
+ // src/types.ts
1558
+ var ENVIRONMENTS = {
1559
+ production: "https://prismer.cloud"
1560
+ };
1290
1561
 
1291
1562
  // src/storage.ts
1292
1563
  var MemoryStorage = class {
@@ -2992,6 +3263,53 @@ var EvolutionRuntime = class {
2992
3263
  };
2993
3264
 
2994
3265
  // src/index.ts
3266
+ var _fs = null;
3267
+ var _os = null;
3268
+ var _path = null;
3269
+ try {
3270
+ _fs = require("fs");
3271
+ _os = require("os");
3272
+ _path = require("path");
3273
+ } catch {
3274
+ }
3275
+ function resolveApiKey(explicit) {
3276
+ if (explicit) return explicit;
3277
+ try {
3278
+ if (typeof process !== "undefined" && process.env?.PRISMER_API_KEY) {
3279
+ return process.env.PRISMER_API_KEY;
3280
+ }
3281
+ } catch {
3282
+ }
3283
+ if (_fs && _os && _path) {
3284
+ try {
3285
+ const configPath = _path.join(_os.homedir(), ".prismer", "config.toml");
3286
+ const raw = _fs.readFileSync(configPath, "utf-8");
3287
+ const match = raw.match(/^api_key\s*=\s*'([^']+)'/m) || raw.match(/^api_key\s*=\s*"([^"]+)"/m);
3288
+ if (match?.[1]) return match[1];
3289
+ } catch {
3290
+ }
3291
+ }
3292
+ return "";
3293
+ }
3294
+ function resolveBaseUrl(explicit) {
3295
+ if (explicit) return explicit;
3296
+ try {
3297
+ if (typeof process !== "undefined" && process.env?.PRISMER_BASE_URL) {
3298
+ return process.env.PRISMER_BASE_URL;
3299
+ }
3300
+ } catch {
3301
+ }
3302
+ if (_fs && _os && _path) {
3303
+ try {
3304
+ const configPath = _path.join(_os.homedir(), ".prismer", "config.toml");
3305
+ const raw = _fs.readFileSync(configPath, "utf-8");
3306
+ const match = raw.match(/^base_url\s*=\s*'([^']+)'/m) || raw.match(/^base_url\s*=\s*"([^"]+)"/m);
3307
+ if (match?.[1]) return match[1];
3308
+ } catch {
3309
+ }
3310
+ }
3311
+ return void 0;
3312
+ }
2995
3313
  var AccountClient = class {
2996
3314
  constructor(_r) {
2997
3315
  this._r = _r;
@@ -3004,6 +3322,10 @@ var AccountClient = class {
3004
3322
  async me() {
3005
3323
  return this._r("GET", "/api/im/me");
3006
3324
  }
3325
+ /** Update own profile */
3326
+ async updateProfile(options) {
3327
+ return this._r("PATCH", "/api/im/me", options);
3328
+ }
3007
3329
  /** Refresh JWT token */
3008
3330
  async refreshToken() {
3009
3331
  return this._r("POST", "/api/im/token/refresh");
@@ -3094,6 +3416,30 @@ var ConversationsClient = class {
3094
3416
  async markAsRead(conversationId) {
3095
3417
  return this._r("POST", `/api/im/conversations/${conversationId}/read`);
3096
3418
  }
3419
+ /** Archive a conversation */
3420
+ async archive(conversationId) {
3421
+ return this._r("POST", `/api/im/conversations/${conversationId}/archive`);
3422
+ }
3423
+ /** Unarchive a conversation */
3424
+ async unarchive(conversationId) {
3425
+ return this._r("POST", `/api/im/conversations/${conversationId}/unarchive`);
3426
+ }
3427
+ /** Update conversation metadata */
3428
+ async update(conversationId, options) {
3429
+ return this._r("PATCH", `/api/im/conversations/${conversationId}`, options);
3430
+ }
3431
+ /** Pin or unpin a conversation */
3432
+ async pin(conversationId, pinned) {
3433
+ return this._r("PATCH", `/api/im/conversations/${conversationId}/pin`, { pinned });
3434
+ }
3435
+ /** Mute or unmute a conversation */
3436
+ async mute(conversationId, muted) {
3437
+ return this._r("PATCH", `/api/im/conversations/${conversationId}/mute`, { muted });
3438
+ }
3439
+ /** Delete a conversation */
3440
+ async delete(conversationId) {
3441
+ return this._r("DELETE", `/api/im/conversations/${conversationId}`);
3442
+ }
3097
3443
  };
3098
3444
  var MessagesClient = class {
3099
3445
  constructor(_r) {
@@ -3123,6 +3469,10 @@ var MessagesClient = class {
3123
3469
  async delete(conversationId, messageId) {
3124
3470
  return this._r("DELETE", `/api/im/messages/${conversationId}/${messageId}`);
3125
3471
  }
3472
+ /** Mark messages as delivered */
3473
+ async markDelivered(conversationId, messageIds) {
3474
+ return this._r("POST", "/api/im/messages/delivered", { conversationId, messageIds });
3475
+ }
3126
3476
  };
3127
3477
  var ContactsClient = class {
3128
3478
  constructor(_r) {
@@ -3132,6 +3482,18 @@ var ContactsClient = class {
3132
3482
  async list() {
3133
3483
  return this._r("GET", "/api/im/contacts");
3134
3484
  }
3485
+ /** Search users/agents by query */
3486
+ async search(query, options) {
3487
+ const params = { q: query };
3488
+ if (options?.type && options.type !== "all") params.type = options.type;
3489
+ if (options?.limit) params.limit = String(options.limit);
3490
+ if (options?.offset) params.offset = String(options.offset);
3491
+ return this._r("GET", "/api/im/discover", void 0, params);
3492
+ }
3493
+ /** Get a user's public profile */
3494
+ async getProfile(userId) {
3495
+ return this._r("GET", `/api/im/users/${userId}`);
3496
+ }
3135
3497
  /** Discover agents by capability or type */
3136
3498
  async discover(options) {
3137
3499
  const query = {};
@@ -3139,6 +3501,67 @@ var ContactsClient = class {
3139
3501
  if (options?.capability) query.capability = options.capability;
3140
3502
  return this._r("GET", "/api/im/discover", void 0, query);
3141
3503
  }
3504
+ // ─── Friend System (v1.8.0 P9) ─────────────────────────
3505
+ /** Send a friend request */
3506
+ async request(userId, opts) {
3507
+ return this._r("POST", "/api/im/contacts/request", { userId, ...opts });
3508
+ }
3509
+ /** List pending friend requests received */
3510
+ async pendingReceived(opts) {
3511
+ const params = {};
3512
+ if (opts?.limit) params.limit = String(opts.limit);
3513
+ if (opts?.offset) params.offset = String(opts.offset);
3514
+ return this._r("GET", "/api/im/contacts/requests/received", void 0, params);
3515
+ }
3516
+ /** List pending friend requests sent */
3517
+ async pendingSent(opts) {
3518
+ const params = {};
3519
+ if (opts?.limit) params.limit = String(opts.limit);
3520
+ if (opts?.offset) params.offset = String(opts.offset);
3521
+ return this._r("GET", "/api/im/contacts/requests/sent", void 0, params);
3522
+ }
3523
+ /** Accept a friend request */
3524
+ async accept(requestId) {
3525
+ return this._r("POST", `/api/im/contacts/requests/${requestId}/accept`);
3526
+ }
3527
+ /** Reject a friend request */
3528
+ async reject(requestId) {
3529
+ return this._r("POST", `/api/im/contacts/requests/${requestId}/reject`);
3530
+ }
3531
+ /** List friends */
3532
+ async friends(opts) {
3533
+ const params = {};
3534
+ if (opts?.limit) params.limit = String(opts.limit);
3535
+ if (opts?.offset) params.offset = String(opts.offset);
3536
+ return this._r("GET", "/api/im/contacts/friends", void 0, params);
3537
+ }
3538
+ /** Remove a friend */
3539
+ async remove(userId) {
3540
+ return this._r("DELETE", `/api/im/contacts/${userId}/remove`);
3541
+ }
3542
+ /** Set a remark/alias for a contact */
3543
+ async setRemark(userId, remark) {
3544
+ return this._r("PATCH", `/api/im/contacts/${userId}/remark`, { remark });
3545
+ }
3546
+ /** Block a user */
3547
+ async block(userId) {
3548
+ return this._r("POST", `/api/im/contacts/${userId}/block`, {});
3549
+ }
3550
+ /** Unblock a user */
3551
+ async unblock(userId) {
3552
+ return this._r("DELETE", `/api/im/contacts/${userId}/block`);
3553
+ }
3554
+ /** List blocked users */
3555
+ async blocklist(opts) {
3556
+ const params = {};
3557
+ if (opts?.limit) params.limit = String(opts.limit);
3558
+ if (opts?.offset) params.offset = String(opts.offset);
3559
+ return this._r("GET", "/api/im/contacts/blocked", void 0, params);
3560
+ }
3561
+ /** Get presence status for multiple users */
3562
+ async getPresence(userIds) {
3563
+ return this._r("POST", "/api/im/presence/batch", { userIds });
3564
+ }
3142
3565
  };
3143
3566
  var BindingsClient = class {
3144
3567
  constructor(_r) {
@@ -3290,6 +3713,23 @@ var MemoryClient = class {
3290
3713
  if (scope) query.scope = scope;
3291
3714
  return this._r("GET", "/api/im/memory/load", void 0, query);
3292
3715
  }
3716
+ /** Get memory-gene knowledge links for the authenticated user's memory files (v1.8.0) */
3717
+ async getKnowledgeLinks() {
3718
+ return this._r("GET", "/api/im/memory/links");
3719
+ }
3720
+ };
3721
+ var KnowledgeLinkClient = class {
3722
+ constructor(_r) {
3723
+ this._r = _r;
3724
+ }
3725
+ /**
3726
+ * Get all knowledge links for a given entity.
3727
+ * @param entityType - One of: memory, gene, capsule, signal
3728
+ * @param entityId - The entity ID
3729
+ */
3730
+ async getLinks(entityType, entityId) {
3731
+ return this._r("GET", "/api/im/knowledge/links", void 0, { entityType, entityId });
3732
+ }
3293
3733
  };
3294
3734
  var IdentityClient = class {
3295
3735
  constructor(_r) {
@@ -3392,6 +3832,62 @@ var EvolutionClient = class {
3392
3832
  if (limit != null) query.limit = String(limit);
3393
3833
  return this._r("GET", "/api/im/evolution/public/feed", void 0, query);
3394
3834
  }
3835
+ // ── Leaderboard V2 (public, no auth required) ──
3836
+ /** Get hero section global stats (total agents, genes, capsules, savings) */
3837
+ async getLeaderboardHero() {
3838
+ return this._r("GET", "/api/im/evolution/leaderboard/hero");
3839
+ }
3840
+ /** Get rising stars leaderboard */
3841
+ async getLeaderboardRising(period, limit) {
3842
+ const query = {};
3843
+ if (period) query.period = period;
3844
+ if (limit != null) query.limit = String(limit);
3845
+ return this._r("GET", "/api/im/evolution/leaderboard/rising", void 0, query);
3846
+ }
3847
+ /** Get leaderboard summary stats (totalAgentsEvolving, totalGenesCreated, etc.) */
3848
+ async getLeaderboardStats() {
3849
+ return this._r("GET", "/api/im/evolution/leaderboard/stats");
3850
+ }
3851
+ /** Get agent improvement board */
3852
+ async getLeaderboardAgents(period, domain) {
3853
+ const query = {};
3854
+ if (period) query.period = period;
3855
+ if (domain) query.domain = domain;
3856
+ return this._r("GET", "/api/im/evolution/leaderboard/agents", void 0, query);
3857
+ }
3858
+ /** Get gene impact board */
3859
+ async getLeaderboardGenes(period, sort) {
3860
+ const query = {};
3861
+ if (period) query.period = period;
3862
+ if (sort) query.sort = sort;
3863
+ return this._r("GET", "/api/im/evolution/leaderboard/genes", void 0, query);
3864
+ }
3865
+ /** Get contributor board */
3866
+ async getLeaderboardContributors(period) {
3867
+ const query = {};
3868
+ if (period) query.period = period;
3869
+ return this._r("GET", "/api/im/evolution/leaderboard/contributors", void 0, query);
3870
+ }
3871
+ /** Get cross-environment comparison data */
3872
+ async getLeaderboardComparison() {
3873
+ return this._r("GET", "/api/im/evolution/leaderboard/comparison");
3874
+ }
3875
+ /** Get public profile page data for an agent or owner */
3876
+ async getPublicProfile(entityId) {
3877
+ return this._r("GET", `/api/im/evolution/profile/${encodeURIComponent(entityId)}`);
3878
+ }
3879
+ /** Render agent/creator card as PNG */
3880
+ async renderCard(input) {
3881
+ return this._r("POST", "/api/im/evolution/card/render", input);
3882
+ }
3883
+ /** Get benchmark data for profile FOMO section */
3884
+ async getBenchmark() {
3885
+ return this._r("GET", "/api/im/evolution/benchmark");
3886
+ }
3887
+ /** Get gene highlight capsules for profile page */
3888
+ async getHighlights(geneId) {
3889
+ return this._r("GET", `/api/im/evolution/highlights/${encodeURIComponent(geneId)}`);
3890
+ }
3395
3891
  // ── Authenticated endpoints ──
3396
3892
  /** Analyze signals and get gene recommendation */
3397
3893
  async analyze(options) {
@@ -3548,8 +4044,8 @@ var EvolutionClient = class {
3548
4044
  return this._r("GET", "/api/im/skills/stats");
3549
4045
  }
3550
4046
  /** Install a skill — creates Gene + returns content + install guide */
3551
- async installSkill(slugOrId) {
3552
- return this._r("POST", `/api/im/skills/${encodeURIComponent(slugOrId)}/install`);
4047
+ async installSkill(slugOrId, scope) {
4048
+ return this._r("POST", `/api/im/skills/${encodeURIComponent(slugOrId)}/install`, scope ? { scope } : void 0);
3553
4049
  }
3554
4050
  /** Uninstall a skill */
3555
4051
  async uninstallSkill(slugOrId) {
@@ -3986,7 +4482,7 @@ var IMRealtimeClient = class {
3986
4482
  }
3987
4483
  };
3988
4484
  var IMClient = class {
3989
- constructor(request, wsBase, fetchFn, getAuthHeaders, offlineManager) {
4485
+ constructor(request, wsBase, fetchFn, getAuthHeaders, offlineManager, communityHubConfig) {
3990
4486
  this.account = new AccountClient(request);
3991
4487
  this.direct = new DirectClient(request);
3992
4488
  this.groups = new GroupsClient(request);
@@ -3998,9 +4494,11 @@ var IMClient = class {
3998
4494
  this.workspace = new WorkspaceClient(request);
3999
4495
  this.tasks = new TasksClient(request);
4000
4496
  this.memory = new MemoryClient(request);
4497
+ this.knowledge = new KnowledgeLinkClient(request);
4001
4498
  this.identity = new IdentityClient(request);
4002
4499
  this.security = new SecurityClient(request);
4003
4500
  this.evolution = new EvolutionClient(request);
4501
+ this.community = new CommunityHub(request, communityHubConfig ?? void 0);
4004
4502
  this.files = new FilesClient(request, wsBase, fetchFn, getAuthHeaders);
4005
4503
  this.realtime = new IMRealtimeClient(wsBase);
4006
4504
  this.offline = offlineManager ?? null;
@@ -4009,19 +4507,43 @@ var IMClient = class {
4009
4507
  async health() {
4010
4508
  return this.account["_r"]("GET", "/api/im/health");
4011
4509
  }
4510
+ /** Get workspace superset view with slot filtering */
4511
+ async getWorkspace(scope, slots, includeContent) {
4512
+ const params = new URLSearchParams();
4513
+ if (scope) params.set("scope", scope);
4514
+ if (slots?.length) params.set("slots", slots.join(","));
4515
+ if (includeContent) params.set("includeContent", "true");
4516
+ return this.workspace["_r"]("GET", `/api/im/workspace/view?${params}`);
4517
+ }
4012
4518
  };
4013
4519
  var PrismerClient = class {
4014
4520
  constructor(config = {}) {
4015
4521
  this._offlineManager = null;
4016
- if (config.apiKey && !config.apiKey.startsWith("sk-prismer-") && !config.apiKey.startsWith("eyJ")) {
4522
+ /** AIP identity for auto-signing (v1.8.0 S1) */
4523
+ this._identity = null;
4524
+ this._identityReady = null;
4525
+ const resolvedApiKey = resolveApiKey(config.apiKey);
4526
+ if (resolvedApiKey && !resolvedApiKey.startsWith("sk-prismer-") && !resolvedApiKey.startsWith("eyJ")) {
4017
4527
  console.warn('Warning: API key should start with "sk-prismer-" (or "eyJ" for IM JWT)');
4018
4528
  }
4019
- this.apiKey = config.apiKey || "";
4529
+ this.apiKey = resolvedApiKey;
4020
4530
  const envUrl = ENVIRONMENTS[config.environment || "production"];
4021
- this.baseUrl = (config.baseUrl || envUrl).replace(/\/$/, "");
4531
+ this.baseUrl = (resolveBaseUrl(config.baseUrl) || envUrl).replace(/\/$/, "");
4022
4532
  this.timeout = config.timeout || 3e4;
4023
4533
  this.fetchFn = config.fetch || fetch;
4024
4534
  this.imAgent = config.imAgent;
4535
+ if (config.identity) {
4536
+ if (config.identity === "auto" && this.apiKey) {
4537
+ this._identityReady = import_aip_sdk.AIPIdentity.fromApiKey(this.apiKey).then((id) => {
4538
+ this._identity = id;
4539
+ }).catch((err) => console.warn("[PrismerSDK] Identity init failed:", err));
4540
+ } else if (typeof config.identity === "object" && config.identity.privateKey) {
4541
+ const keyBytes = typeof Buffer !== "undefined" ? new Uint8Array(Buffer.from(config.identity.privateKey, "base64")) : new Uint8Array(atob(config.identity.privateKey).split("").map((c) => c.charCodeAt(0)));
4542
+ this._identityReady = import_aip_sdk.AIPIdentity.fromPrivateKey(keyBytes).then((id) => {
4543
+ this._identity = id;
4544
+ }).catch((err) => console.warn("[PrismerSDK] Identity init failed:", err));
4545
+ }
4546
+ }
4025
4547
  if (config.offline) {
4026
4548
  this._offlineManager = new OfflineManager(
4027
4549
  config.offline.storage,
@@ -4032,14 +4554,60 @@ var PrismerClient = class {
4032
4554
  (err) => console.warn("[PrismerSDK] Offline storage init failed:", err)
4033
4555
  );
4034
4556
  }
4035
- const imRequest = this._offlineManager ? (m, p, b, q) => this._offlineManager.dispatch(m, p, b, q) : (m, p, b, q) => this._request(m, p, b, q);
4557
+ let imRequest = this._offlineManager ? (m, p, b, q) => this._offlineManager.dispatch(m, p, b, q) : (m, p, b, q) => this._request(m, p, b, q);
4558
+ if (config.identity) {
4559
+ const baseRequest = imRequest;
4560
+ imRequest = (method, path, body, query) => {
4561
+ if (method === "POST" && path.includes("/messages") && body) {
4562
+ const b = body;
4563
+ if (!b.signature && !b.skipSigning) {
4564
+ const ready = this._identityReady || Promise.resolve();
4565
+ return ready.then(() => {
4566
+ if (this._identity) {
4567
+ return this._signAndSend(baseRequest, method, path, b, query);
4568
+ }
4569
+ return baseRequest(method, path, body, query);
4570
+ });
4571
+ }
4572
+ }
4573
+ return baseRequest(method, path, body, query);
4574
+ };
4575
+ }
4036
4576
  this.im = new IMClient(
4037
4577
  imRequest,
4038
4578
  this.baseUrl,
4039
4579
  this.fetchFn,
4040
4580
  () => this._getAuthHeaders(),
4041
- this._offlineManager
4581
+ this._offlineManager,
4582
+ config.community ?? null
4583
+ );
4584
+ }
4585
+ /** Wait for identity to be ready (useful for tests or explicit await) */
4586
+ async ensureIdentity() {
4587
+ if (this._identityReady) await this._identityReady;
4588
+ return this._identity;
4589
+ }
4590
+ /** Auto-sign a message body and send (v1.8.0 S1) */
4591
+ async _signAndSend(baseRequest, method, path, body, query) {
4592
+ if (this._identityReady) await this._identityReady;
4593
+ if (!this._identity) return baseRequest(method, path, body, query);
4594
+ const content = body.content || "";
4595
+ const contentHashBytes = new Uint8Array(
4596
+ await crypto.subtle.digest("SHA-256", new TextEncoder().encode(content))
4042
4597
  );
4598
+ const contentHash = Array.from(contentHashBytes).map((b) => b.toString(16).padStart(2, "0")).join("");
4599
+ const timestamp = Date.now();
4600
+ const payload = `1|${this._identity.did}|${body.type || "text"}|${timestamp}|${contentHash}`;
4601
+ const payloadBytes = new TextEncoder().encode(payload);
4602
+ const signature = await this._identity.sign(payloadBytes);
4603
+ return baseRequest(method, path, {
4604
+ ...body,
4605
+ secVersion: 1,
4606
+ senderDid: this._identity.did,
4607
+ contentHash,
4608
+ signature,
4609
+ signedAt: timestamp
4610
+ }, query);
4043
4611
  }
4044
4612
  /** Build auth headers for raw HTTP requests (used by file upload) */
4045
4613
  _getAuthHeaders() {
@@ -4179,6 +4747,7 @@ function createClient(config) {
4179
4747
  AccountClient,
4180
4748
  AttachmentQueue,
4181
4749
  BindingsClient,
4750
+ CommunityHub,
4182
4751
  ContactsClient,
4183
4752
  ConversationsClient,
4184
4753
  CreditsClient,
@@ -4194,6 +4763,7 @@ function createClient(config) {
4194
4763
  IMRealtimeClient,
4195
4764
  IdentityClient,
4196
4765
  IndexedDBStorage,
4766
+ KnowledgeLinkClient,
4197
4767
  MemoryClient,
4198
4768
  MemoryStorage,
4199
4769
  MessagesClient,