@arbidocs/sdk 0.3.116 → 0.3.117

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.d.cts CHANGED
@@ -1,5 +1,5 @@
1
- import { o as ConfigStore, l as CliConfig, m as CliCredentials, C as ChatSession, a5 as SkippedFile, ad as UploadResult, i as AuthHeaders, a9 as UploadBatchResult, ac as UploadOptions, aa as UploadDirectOptions, ab as UploadDirectResult, a3 as SUPPORTED_EXTENSIONS, s as DmCryptoContext } from './browser-BS_k043E.cjs';
2
- export { a as AgentStepEvent, b as Arbi, c as ArbiApiError, d as ArbiError, f as ArbiOptions, g as ArtifactEvent, h as AuthContext, j as AuthenticatedClient, k as CitationSummary, n as CommandDescriptor, p as ConnectOptions, D as DOC_TERMINAL_STATUSES, t as DocNameMap, u as DocumentListFields, v as DocumentListOrder, w as DocumentWaiter, x as DocumentWaiterOptions, F as FormattedWsMessage, L as ListAllOptions, y as ListPaginatedOptions, E as MessageLevel, G as MessageMetadataPayload, H as MessageQueuedEvent, O as OutputTokensDetails, P as ParsedSlashCommand, I as ProjectInvoicesResponse, J as ProjectUsageResponse, Q as QueryOptions, R as ReconnectOptions, K as ReconnectableWsConnection, N as ResolvedCitation, S as ResponseCompletedEvent, T as ResponseContentPartAddedEvent, U as ResponseCreatedEvent, V as ResponseFailedEvent, W as ResponseOutputItemAddedEvent, X as ResponseOutputItemDoneEvent, Y as ResponseOutputTextDeltaEvent, Z as ResponseOutputTextDoneEvent, _ as ResponseUsage, $ as SSEEvent, a0 as SSEStreamCallbacks, a1 as SSEStreamResult, a2 as SSEStreamStartData, a4 as SkillSummary, ae as UserDailyUsageResponse, af as UserInfo, ag as UserInputRequestEvent, ah as UserMessageEvent, ai as WebSocketAuthError, aj as WorkspaceChronologyOut, ak as WorkspaceContext, al as WsConnection, am as agentconfig, an as assistant, ao as authenticatedFetch, ap as buildRetrievalChunkTool, aq as buildRetrievalFullContextTool, ar as buildRetrievalTocTool, as as connectWebSocket, at as connectWithReconnect, au as consumeSSEStream, av as contacts, aw as conversations, ax as countCitations, ay as createAuthenticatedClient, az as createDocumentWaiter, aA as dm, aB as doctags, aC as documents, aD as files, aE as filterSkills, aF as formatAgentStepLabel, aG as formatFileSize, aH as formatStreamSummary, aI as formatUserName, aJ as formatWorkspaceChoices, aK as formatWsMessage, aL as generateEncryptedWorkspaceKey, aM as generateNewWorkspaceKey, aN as getErrorCode, aO as getErrorMessage, aP as getRawWorkspaceKey, aQ as health, aS as parseSSEEvents, aT as parseSlashCommand, aU as parseSlashTokenInProgress, aV as performPasswordLogin, aW as performSigningKeyLogin, aX as performSsoDeviceFlowLogin, aY as projects, aZ as requireData, a_ as requireOk, a$ as resolveAuth, b0 as resolveCitations, b1 as resolveWorkspace, b2 as responses, b3 as selectWorkspace, b4 as selectWorkspaceById, b5 as settings, b6 as streamSSE, b7 as stripCitationMarkdown, b8 as summarizeCitations, b9 as tags, bb as workspaces } from './browser-BS_k043E.cjs';
1
+ import { o as ConfigStore, l as CliConfig, m as CliCredentials, C as ChatSession, a6 as SkippedFile, ae as UploadResult, i as AuthHeaders, aa as UploadBatchResult, ad as UploadOptions, ab as UploadDirectOptions, ac as UploadDirectResult, a4 as SUPPORTED_EXTENSIONS, s as DmCryptoContext } from './browser-CxTSIAhf.cjs';
2
+ export { a as AgentStepEvent, b as Arbi, c as ArbiApiError, d as ArbiError, f as ArbiOptions, g as ArtifactEvent, h as AuthContext, j as AuthenticatedClient, k as CitationSummary, n as CommandDescriptor, p as ConnectOptions, D as DOC_TERMINAL_STATUSES, t as DocNameMap, u as DocumentListFields, v as DocumentListOrder, w as DocumentWaiter, x as DocumentWaiterOptions, F as FormattedWsMessage, L as ListAllOptions, y as ListPaginatedOptions, E as MessageLevel, G as MessageMetadataPayload, H as MessageQueuedEvent, O as OutputTokensDetails, P as ParsedSlashCommand, I as ProjectInvoicesResponse, J as ProjectUsageResponse, Q as QueryOptions, R as ReconnectOptions, K as ReconnectableWsConnection, N as ResolvedCitation, S as ResolvedRecipient, T as ResponseCompletedEvent, U as ResponseContentPartAddedEvent, V as ResponseCreatedEvent, W as ResponseFailedEvent, X as ResponseOutputItemAddedEvent, Y as ResponseOutputItemDoneEvent, Z as ResponseOutputTextDeltaEvent, _ as ResponseOutputTextDoneEvent, $ as ResponseUsage, a0 as SSEEvent, a1 as SSEStreamCallbacks, a2 as SSEStreamResult, a3 as SSEStreamStartData, a5 as SkillSummary, af as UserDailyUsageResponse, ag as UserInfo, ah as UserInputRequestEvent, ai as UserMessageEvent, aj as WebSocketAuthError, ak as WorkspaceChronologyOut, al as WorkspaceContext, am as WsConnection, an as agentconfig, ao as assistant, ap as authenticatedFetch, aq as buildRetrievalChunkTool, ar as buildRetrievalFullContextTool, as as buildRetrievalTocTool, at as connectWebSocket, au as connectWithReconnect, av as consumeSSEStream, aw as contacts, ax as conversations, ay as countCitations, az as createAuthenticatedClient, aA as createDocumentWaiter, aB as dm, aC as doctags, aD as documents, aE as files, aF as filterSkills, aG as formatAgentStepLabel, aH as formatFileSize, aI as formatStreamSummary, aJ as formatUserName, aK as formatWorkspaceChoices, aL as formatWsMessage, aM as generateEncryptedWorkspaceKey, aN as generateNewWorkspaceKey, aO as getErrorCode, aP as getErrorMessage, aQ as getRawWorkspaceKey, aR as health, aT as parseSSEEvents, aU as parseSlashCommand, aV as parseSlashTokenInProgress, aW as performPasswordLogin, aX as performSigningKeyLogin, aY as performSsoDeviceFlowLogin, aZ as projects, a_ as requireData, a$ as requireOk, b0 as resolveAuth, b1 as resolveCitations, b2 as resolveWorkspace, b3 as responses, b4 as selectWorkspace, b5 as selectWorkspaceById, b6 as settings, b7 as streamSSE, b8 as stripCitationMarkdown, b9 as summarizeCitations, ba as tags, bc as workspaces } from './browser-CxTSIAhf.cjs';
3
3
  import { SessionStorageProvider, ArbiClient, components } from '@arbidocs/client';
4
4
 
5
5
  /**
package/dist/index.d.ts CHANGED
@@ -1,5 +1,5 @@
1
- import { o as ConfigStore, l as CliConfig, m as CliCredentials, C as ChatSession, a5 as SkippedFile, ad as UploadResult, i as AuthHeaders, a9 as UploadBatchResult, ac as UploadOptions, aa as UploadDirectOptions, ab as UploadDirectResult, a3 as SUPPORTED_EXTENSIONS, s as DmCryptoContext } from './browser-BS_k043E.js';
2
- export { a as AgentStepEvent, b as Arbi, c as ArbiApiError, d as ArbiError, f as ArbiOptions, g as ArtifactEvent, h as AuthContext, j as AuthenticatedClient, k as CitationSummary, n as CommandDescriptor, p as ConnectOptions, D as DOC_TERMINAL_STATUSES, t as DocNameMap, u as DocumentListFields, v as DocumentListOrder, w as DocumentWaiter, x as DocumentWaiterOptions, F as FormattedWsMessage, L as ListAllOptions, y as ListPaginatedOptions, E as MessageLevel, G as MessageMetadataPayload, H as MessageQueuedEvent, O as OutputTokensDetails, P as ParsedSlashCommand, I as ProjectInvoicesResponse, J as ProjectUsageResponse, Q as QueryOptions, R as ReconnectOptions, K as ReconnectableWsConnection, N as ResolvedCitation, S as ResponseCompletedEvent, T as ResponseContentPartAddedEvent, U as ResponseCreatedEvent, V as ResponseFailedEvent, W as ResponseOutputItemAddedEvent, X as ResponseOutputItemDoneEvent, Y as ResponseOutputTextDeltaEvent, Z as ResponseOutputTextDoneEvent, _ as ResponseUsage, $ as SSEEvent, a0 as SSEStreamCallbacks, a1 as SSEStreamResult, a2 as SSEStreamStartData, a4 as SkillSummary, ae as UserDailyUsageResponse, af as UserInfo, ag as UserInputRequestEvent, ah as UserMessageEvent, ai as WebSocketAuthError, aj as WorkspaceChronologyOut, ak as WorkspaceContext, al as WsConnection, am as agentconfig, an as assistant, ao as authenticatedFetch, ap as buildRetrievalChunkTool, aq as buildRetrievalFullContextTool, ar as buildRetrievalTocTool, as as connectWebSocket, at as connectWithReconnect, au as consumeSSEStream, av as contacts, aw as conversations, ax as countCitations, ay as createAuthenticatedClient, az as createDocumentWaiter, aA as dm, aB as doctags, aC as documents, aD as files, aE as filterSkills, aF as formatAgentStepLabel, aG as formatFileSize, aH as formatStreamSummary, aI as formatUserName, aJ as formatWorkspaceChoices, aK as formatWsMessage, aL as generateEncryptedWorkspaceKey, aM as generateNewWorkspaceKey, aN as getErrorCode, aO as getErrorMessage, aP as getRawWorkspaceKey, aQ as health, aS as parseSSEEvents, aT as parseSlashCommand, aU as parseSlashTokenInProgress, aV as performPasswordLogin, aW as performSigningKeyLogin, aX as performSsoDeviceFlowLogin, aY as projects, aZ as requireData, a_ as requireOk, a$ as resolveAuth, b0 as resolveCitations, b1 as resolveWorkspace, b2 as responses, b3 as selectWorkspace, b4 as selectWorkspaceById, b5 as settings, b6 as streamSSE, b7 as stripCitationMarkdown, b8 as summarizeCitations, b9 as tags, bb as workspaces } from './browser-BS_k043E.js';
1
+ import { o as ConfigStore, l as CliConfig, m as CliCredentials, C as ChatSession, a6 as SkippedFile, ae as UploadResult, i as AuthHeaders, aa as UploadBatchResult, ad as UploadOptions, ab as UploadDirectOptions, ac as UploadDirectResult, a4 as SUPPORTED_EXTENSIONS, s as DmCryptoContext } from './browser-CxTSIAhf.js';
2
+ export { a as AgentStepEvent, b as Arbi, c as ArbiApiError, d as ArbiError, f as ArbiOptions, g as ArtifactEvent, h as AuthContext, j as AuthenticatedClient, k as CitationSummary, n as CommandDescriptor, p as ConnectOptions, D as DOC_TERMINAL_STATUSES, t as DocNameMap, u as DocumentListFields, v as DocumentListOrder, w as DocumentWaiter, x as DocumentWaiterOptions, F as FormattedWsMessage, L as ListAllOptions, y as ListPaginatedOptions, E as MessageLevel, G as MessageMetadataPayload, H as MessageQueuedEvent, O as OutputTokensDetails, P as ParsedSlashCommand, I as ProjectInvoicesResponse, J as ProjectUsageResponse, Q as QueryOptions, R as ReconnectOptions, K as ReconnectableWsConnection, N as ResolvedCitation, S as ResolvedRecipient, T as ResponseCompletedEvent, U as ResponseContentPartAddedEvent, V as ResponseCreatedEvent, W as ResponseFailedEvent, X as ResponseOutputItemAddedEvent, Y as ResponseOutputItemDoneEvent, Z as ResponseOutputTextDeltaEvent, _ as ResponseOutputTextDoneEvent, $ as ResponseUsage, a0 as SSEEvent, a1 as SSEStreamCallbacks, a2 as SSEStreamResult, a3 as SSEStreamStartData, a5 as SkillSummary, af as UserDailyUsageResponse, ag as UserInfo, ah as UserInputRequestEvent, ai as UserMessageEvent, aj as WebSocketAuthError, ak as WorkspaceChronologyOut, al as WorkspaceContext, am as WsConnection, an as agentconfig, ao as assistant, ap as authenticatedFetch, aq as buildRetrievalChunkTool, ar as buildRetrievalFullContextTool, as as buildRetrievalTocTool, at as connectWebSocket, au as connectWithReconnect, av as consumeSSEStream, aw as contacts, ax as conversations, ay as countCitations, az as createAuthenticatedClient, aA as createDocumentWaiter, aB as dm, aC as doctags, aD as documents, aE as files, aF as filterSkills, aG as formatAgentStepLabel, aH as formatFileSize, aI as formatStreamSummary, aJ as formatUserName, aK as formatWorkspaceChoices, aL as formatWsMessage, aM as generateEncryptedWorkspaceKey, aN as generateNewWorkspaceKey, aO as getErrorCode, aP as getErrorMessage, aQ as getRawWorkspaceKey, aR as health, aT as parseSSEEvents, aU as parseSlashCommand, aV as parseSlashTokenInProgress, aW as performPasswordLogin, aX as performSigningKeyLogin, aY as performSsoDeviceFlowLogin, aZ as projects, a_ as requireData, a$ as requireOk, b0 as resolveAuth, b1 as resolveCitations, b2 as resolveWorkspace, b3 as responses, b4 as selectWorkspace, b5 as selectWorkspaceById, b6 as settings, b7 as streamSSE, b8 as stripCitationMarkdown, b9 as summarizeCitations, ba as tags, bc as workspaces } from './browser-CxTSIAhf.js';
3
3
  import { SessionStorageProvider, ArbiClient, components } from '@arbidocs/client';
4
4
 
5
5
  /**
package/dist/index.js CHANGED
@@ -5620,9 +5620,53 @@ __export(dm_exports, {
5620
5620
  listDecryptedDMs: () => listDecryptedDMs,
5621
5621
  markRead: () => markRead,
5622
5622
  requestWorkspaceAccess: () => requestWorkspaceAccess,
5623
+ resolveRecipient: () => resolveRecipient,
5623
5624
  sendDM: () => sendDM,
5624
5625
  sendEncryptedDM: () => sendEncryptedDM
5625
5626
  });
5627
+
5628
+ // src/operations/agents.ts
5629
+ var agents_exports = {};
5630
+ __export(agents_exports, {
5631
+ createAgent: () => createAgent,
5632
+ deleteAgents: () => deleteAgents,
5633
+ getAgentConfig: () => getAgentConfig,
5634
+ listAgentWorkspaces: () => listAgentWorkspaces,
5635
+ listAgents: () => listAgents
5636
+ });
5637
+ async function listAgents(arbi) {
5638
+ return requireData(await arbi.fetch.GET("/v1/agents"), "Failed to fetch agents");
5639
+ }
5640
+ async function createAgent(arbi, name) {
5641
+ const body = { name };
5642
+ return requireData(await arbi.fetch.POST("/v1/agents", { body }), "Failed to create agent");
5643
+ }
5644
+ async function getAgentConfig(arbi, agentExtId) {
5645
+ return requireData(
5646
+ await arbi.fetch.GET("/v1/agents/{agent_ext_id}/config", {
5647
+ params: { path: { agent_ext_id: agentExtId } }
5648
+ }),
5649
+ "Failed to fetch agent config"
5650
+ );
5651
+ }
5652
+ async function listAgentWorkspaces(arbi, agentExtId) {
5653
+ return requireData(
5654
+ await arbi.fetch.GET("/v1/agents/{agent_ext_id}/workspaces", {
5655
+ params: { path: { agent_ext_id: agentExtId } }
5656
+ }),
5657
+ "Failed to fetch agent workspaces"
5658
+ );
5659
+ }
5660
+ async function deleteAgents(arbi, agentExtIds) {
5661
+ return requireData(
5662
+ await arbi.fetch.DELETE("/v1/agents", {
5663
+ body: { agent_ext_ids: agentExtIds }
5664
+ }),
5665
+ "Failed to delete agents"
5666
+ );
5667
+ }
5668
+
5669
+ // src/operations/dm.ts
5626
5670
  function createDmCryptoContext(arbi, signingPrivateKeyBytes, userExtId) {
5627
5671
  const ed25519PublicKey = signingPrivateKeyBytes.slice(32, 64);
5628
5672
  const encryptionKeypair = arbi.crypto.deriveEncryptionKeypairFromSigning({
@@ -5685,6 +5729,37 @@ async function listActivity(arbi, options) {
5685
5729
  "Failed to fetch activity"
5686
5730
  );
5687
5731
  }
5732
+ async function resolveRecipient(arbi, ref) {
5733
+ const isEmail = ref.includes("@");
5734
+ const matchKey = isEmail ? "email" : "external_id";
5735
+ const contacts = await listContacts(arbi);
5736
+ const contactMatch = contacts.find(
5737
+ (c2) => isEmail ? c2.email === ref : c2.user?.external_id === ref || c2.external_id === ref
5738
+ );
5739
+ if (contactMatch?.user?.encryption_public_key) {
5740
+ return {
5741
+ extId: contactMatch.user.external_id,
5742
+ pubKey: contactMatch.user.encryption_public_key
5743
+ };
5744
+ }
5745
+ try {
5746
+ const agents = await listAgents(arbi);
5747
+ const agentMatch = agents.find((a2) => a2[matchKey] === ref);
5748
+ if (agentMatch?.encryption_public_key) {
5749
+ return { extId: agentMatch.external_id, pubKey: agentMatch.encryption_public_key };
5750
+ }
5751
+ } catch {
5752
+ }
5753
+ try {
5754
+ const wsUsers = await listWorkspaceUsers(arbi);
5755
+ const wsMatch = wsUsers.find((wu) => wu.user[matchKey] === ref);
5756
+ if (wsMatch?.user.encryption_public_key) {
5757
+ return { extId: wsMatch.user.external_id, pubKey: wsMatch.user.encryption_public_key };
5758
+ }
5759
+ } catch {
5760
+ }
5761
+ return null;
5762
+ }
5688
5763
  async function sendEncryptedDM(arbi, messages, crypto) {
5689
5764
  const encrypted = await Promise.all(
5690
5765
  messages.map(async (msg) => ({
@@ -5881,47 +5956,6 @@ async function getFileContent(auth, fileId) {
5881
5956
  });
5882
5957
  }
5883
5958
 
5884
- // src/operations/agents.ts
5885
- var agents_exports = {};
5886
- __export(agents_exports, {
5887
- createAgent: () => createAgent,
5888
- deleteAgents: () => deleteAgents,
5889
- getAgentConfig: () => getAgentConfig,
5890
- listAgentWorkspaces: () => listAgentWorkspaces,
5891
- listAgents: () => listAgents
5892
- });
5893
- async function listAgents(arbi) {
5894
- return requireData(await arbi.fetch.GET("/v1/agents"), "Failed to fetch agents");
5895
- }
5896
- async function createAgent(arbi, name) {
5897
- const body = { name };
5898
- return requireData(await arbi.fetch.POST("/v1/agents", { body }), "Failed to create agent");
5899
- }
5900
- async function getAgentConfig(arbi, agentExtId) {
5901
- return requireData(
5902
- await arbi.fetch.GET("/v1/agents/{agent_ext_id}/config", {
5903
- params: { path: { agent_ext_id: agentExtId } }
5904
- }),
5905
- "Failed to fetch agent config"
5906
- );
5907
- }
5908
- async function listAgentWorkspaces(arbi, agentExtId) {
5909
- return requireData(
5910
- await arbi.fetch.GET("/v1/agents/{agent_ext_id}/workspaces", {
5911
- params: { path: { agent_ext_id: agentExtId } }
5912
- }),
5913
- "Failed to fetch agent workspaces"
5914
- );
5915
- }
5916
- async function deleteAgents(arbi, agentExtIds) {
5917
- return requireData(
5918
- await arbi.fetch.DELETE("/v1/agents", {
5919
- body: { agent_ext_ids: agentExtIds }
5920
- }),
5921
- "Failed to delete agents"
5922
- );
5923
- }
5924
-
5925
5959
  // src/operations/sessions.ts
5926
5960
  var sessions_exports = {};
5927
5961
  __export(sessions_exports, {
@@ -6057,6 +6091,7 @@ var Arbi = class {
6057
6091
  client = null;
6058
6092
  loginResult = null;
6059
6093
  currentWorkspaceId = null;
6094
+ dmCryptoContext = null;
6060
6095
  options;
6061
6096
  constructor(options) {
6062
6097
  this.options = options;
@@ -6143,6 +6178,7 @@ var Arbi = class {
6143
6178
  }
6144
6179
  this.loginResult = null;
6145
6180
  this.currentWorkspaceId = null;
6181
+ this.dmCryptoContext = null;
6146
6182
  }
6147
6183
  // ── Accessors ─────────────────────────────────────────────────────────
6148
6184
  /** Get the underlying ArbiClient (throws if not initialized). */
@@ -6198,6 +6234,16 @@ var Arbi = class {
6198
6234
  };
6199
6235
  // ── User (account-scoped usage) ───────────────────────────────────────
6200
6236
  user = {
6237
+ /**
6238
+ * The authenticated user's identity from the current session
6239
+ * (`external_id` + `email`), established at login. Returns `null` when not
6240
+ * logged in. This is the canonical "who am I" accessor — DM direction and
6241
+ * ownership checks read it instead of re-deriving identity per call.
6242
+ */
6243
+ identity: () => {
6244
+ const state = this.requireClient().session.getState();
6245
+ return state.userExtId && state.userEmail ? { externalId: state.userExtId, email: state.userEmail } : null;
6246
+ },
6201
6247
  /** Today's deployment-wide credit spend for the current user. */
6202
6248
  usageToday: () => getUserUsageToday(this.requireClient())
6203
6249
  };
@@ -6381,9 +6427,76 @@ var Arbi = class {
6381
6427
  groupByStatus: groupContactsByStatus
6382
6428
  };
6383
6429
  // ── Direct Messages ───────────────────────────────────────────────────
6430
+ /**
6431
+ * Build (and cache) the DM crypto context for the current session.
6432
+ *
6433
+ * Derives the user's curve25519 keypair from the stored signing key and pairs
6434
+ * it with their external_id — everything `list()`/`send()` need to encrypt and
6435
+ * decrypt. Cached for the session and cleared on logout. Consumers never touch
6436
+ * this: it's an internal of the `dm` surface.
6437
+ */
6438
+ async requireDmCrypto() {
6439
+ if (this.dmCryptoContext) return this.dmCryptoContext;
6440
+ const client = this.requireClient();
6441
+ const session = await client.storage.getSession();
6442
+ if (!session) {
6443
+ throw new ArbiError("Not authenticated \u2014 no session available for DM encryption");
6444
+ }
6445
+ const userExtId = client.session.getState().userExtId;
6446
+ if (!userExtId) {
6447
+ throw new ArbiError("No user identity in session \u2014 cannot set up DM encryption");
6448
+ }
6449
+ this.dmCryptoContext = createDmCryptoContext(client, session.signingPrivateKey, userExtId);
6450
+ return this.dmCryptoContext;
6451
+ }
6384
6452
  dm = {
6385
- list: () => listDMs(this.requireClient()),
6386
- send: (messages) => sendDM(this.requireClient(), messages),
6453
+ /**
6454
+ * List direct messages, newest first, with content already **decrypted**.
6455
+ * (A message that can't be decrypted comes back as `[Decryption failed]`.)
6456
+ */
6457
+ list: async () => listDecryptedDMs(this.requireClient(), await this.requireDmCrypto()),
6458
+ /**
6459
+ * Send an E2E-encrypted DM to a recipient (email or `usr-`/`agt-` id).
6460
+ * Resolves the recipient's public key and encrypts internally — the caller
6461
+ * passes plaintext and never handles keys or ciphertext.
6462
+ */
6463
+ send: async (recipient, text) => {
6464
+ const client = this.requireClient();
6465
+ const resolved = await resolveRecipient(client, recipient);
6466
+ if (!resolved) {
6467
+ throw new ArbiError(
6468
+ `Could not resolve DM recipient "${recipient}" (not a known contact, agent, or workspace member)`
6469
+ );
6470
+ }
6471
+ return sendEncryptedDM(
6472
+ client,
6473
+ [
6474
+ {
6475
+ recipient_ext_id: resolved.extId,
6476
+ content: text,
6477
+ recipient_encryption_public_key: resolved.pubKey
6478
+ }
6479
+ ],
6480
+ await this.requireDmCrypto()
6481
+ );
6482
+ },
6483
+ /**
6484
+ * Send to a recipient whose external_id + public key are already known
6485
+ * (e.g. from a message's `sender`), skipping directory resolution.
6486
+ */
6487
+ sendTo: async (recipientExtId, recipientPublicKey, text) => sendEncryptedDM(
6488
+ this.requireClient(),
6489
+ [
6490
+ {
6491
+ recipient_ext_id: recipientExtId,
6492
+ content: text,
6493
+ recipient_encryption_public_key: recipientPublicKey
6494
+ }
6495
+ ],
6496
+ await this.requireDmCrypto()
6497
+ ),
6498
+ /** Resolve a recipient reference to `{ extId, pubKey }` (contacts → agents → workspace). */
6499
+ resolveRecipient: (recipient) => resolveRecipient(this.requireClient(), recipient),
6387
6500
  markRead: (messageIds) => markRead(this.requireClient(), messageIds),
6388
6501
  delete: (messageIds) => deleteDMs(this.requireClient(), messageIds),
6389
6502
  /** List the current user's durable activity feed (never unread; excluded from DMs). */