acn-client 0.13.0 → 0.14.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.d.ts CHANGED
@@ -115,17 +115,17 @@ interface AgentSearchOptions {
115
115
  skills?: string;
116
116
  /** online (default) | offline | all. Public list does not include verification_code. */
117
117
  status?: AgentSearchStatus;
118
- subnet_id?: string;
118
+ slug?: string;
119
119
  }
120
120
  /** Subnet information */
121
121
  interface SubnetInfo {
122
122
  /**
123
- * Subnet identifier. The server wire field is `subnet_id`; some
124
- * older responses may also surface `id`. Prefer `subnet_id` when
125
- * present, falling back to `id`.
123
+ * Opaque UUID identifier from the persistence layer.
126
124
  */
127
125
  id: string;
128
- /** Wire-side identifier (ADR-0003+ servers always emit this). */
126
+ /** URL-safe slug identifier (server wire field). */
127
+ slug?: string;
128
+ /** @deprecated Use `slug` instead. */
129
129
  subnet_id?: string;
130
130
  name: string;
131
131
  description?: string;
@@ -135,8 +135,16 @@ interface SubnetInfo {
135
135
  owner?: string;
136
136
  harness_url?: string;
137
137
  harness_registered?: boolean;
138
- /** ADR-0003 — parent subnet when this is a nested child. */
138
+ /**
139
+ * Deprecated — ACL V6 B6: the server no longer emits the slug.
140
+ * Use `parent_id` (UUID) instead. Kept for backward-compat parsing
141
+ * of responses from older server versions.
142
+ */
143
+ parent_slug?: string | null;
144
+ /** @deprecated Use `parent_slug` instead. */
139
145
  parent_subnet_id?: string | null;
146
+ /** ACL V6 B6 — parent subnet's opaque UUID. */
147
+ parent_id?: string | null;
140
148
  /** ADR-0003 — defaults to `'persistent'` on the server. */
141
149
  lifecycle?: SubnetLifecycle;
142
150
  /** ADR-0003 — bound task when `lifecycle === 'task_scoped'`. */
@@ -162,10 +170,10 @@ interface SubnetCreateRequest {
162
170
  metadata?: Record<string, unknown>;
163
171
  /**
164
172
  * ADR-0003 nested-subnet parent. When set, the new subnet becomes a
165
- * child of `parent_subnet_id`. Single-layer cap: the parent itself
173
+ * child of `parent_slug`. Single-layer cap: the parent itself
166
174
  * must be top-level. Immutable after creation.
167
175
  */
168
- parent_subnet_id?: string;
176
+ parent_slug?: string;
169
177
  /**
170
178
  * ADR-0003 lifecycle. Defaults to `'persistent'` when omitted.
171
179
  * `'task_scoped'` requires `linked_task_id` and the subnet
@@ -190,7 +198,7 @@ interface SubnetCreateRequest {
190
198
  /** Subnet creation response */
191
199
  interface SubnetCreateResponse {
192
200
  success: boolean;
193
- subnet_id: string;
201
+ slug: string;
194
202
  message: string;
195
203
  }
196
204
  /** Subnet join-policy values. Immutable post-creation. */
@@ -204,7 +212,7 @@ interface SubnetAllowlistEntry {
204
212
  }
205
213
  /** Response envelope for `subnetAllowlistList` (owner only). */
206
214
  interface SubnetAllowlistListResponse {
207
- subnet_id: string;
215
+ slug: string;
208
216
  entries: SubnetAllowlistEntry[];
209
217
  [key: string]: unknown;
210
218
  }
@@ -218,7 +226,7 @@ interface SubnetAllowlistListResponse {
218
226
  */
219
227
  interface SubnetJoinRequestRow {
220
228
  request_id: string;
221
- subnet_id: string;
229
+ slug: string;
222
230
  kind: 'join_request' | 'allowlist_auto' | 'invitation';
223
231
  status: 'pending' | 'approved' | 'rejected' | 'withdrawn';
224
232
  initiated_by: string;
@@ -231,13 +239,13 @@ interface SubnetJoinRequestRow {
231
239
  }
232
240
  /** Response envelope for `subnetJoinRequestList` (owner only). */
233
241
  interface SubnetJoinRequestListResponse {
234
- subnet_id: string;
242
+ slug: string;
235
243
  items: SubnetJoinRequestRow[];
236
244
  [key: string]: unknown;
237
245
  }
238
246
  /** Response envelope for `subnetInvitationList` (owner only). */
239
247
  interface SubnetInvitationListResponse {
240
- subnet_id: string;
248
+ slug: string;
241
249
  items: SubnetJoinRequestRow[];
242
250
  [key: string]: unknown;
243
251
  }
@@ -552,7 +560,7 @@ interface Task {
552
560
  required_tags?: string[];
553
561
  /** Reward in numeric form — convenience alias, equals `parseFloat(reward)`. */
554
562
  reward_amount?: number;
555
- subnet_id: string | null;
563
+ subnet_slug: string | null;
556
564
  created_at: string;
557
565
  deadline?: string | null;
558
566
  use_escrow?: boolean;
@@ -588,7 +596,7 @@ interface TaskCreateRequest {
588
596
  reward: string;
589
597
  /** Deadline in hours (1–2 160). Required. */
590
598
  deadline_hours: number;
591
- subnet_id?: string | null;
599
+ subnet_slug?: string | null;
592
600
  /** Default: "credits" */
593
601
  reward_currency?: string;
594
602
  /** Default: 1 */
@@ -856,6 +864,7 @@ interface AllowlistListResponse {
856
864
  entries: AllowlistEntry[];
857
865
  total: number;
858
866
  }
867
+ declare const KNOWN_INBOX_MESSAGE_STATUSES: readonly ["unread", "read", "processed"];
859
868
 
860
869
  /**
861
870
  * ACN HTTP Client
@@ -887,6 +896,7 @@ declare class ACNClient {
887
896
  private request;
888
897
  private get;
889
898
  private post;
899
+ private patch;
890
900
  private delete;
891
901
  /** Check if ACN server is healthy */
892
902
  health(): Promise<{
@@ -988,37 +998,37 @@ declare class ACNClient {
988
998
  subnets: SubnetInfo[];
989
999
  }>;
990
1000
  /** Get subnet by ID */
991
- getSubnet(subnetId: string): Promise<SubnetInfo>;
1001
+ getSubnet(slug: string): Promise<SubnetInfo>;
992
1002
  /**
993
1003
  * List immediate children of a subnet (ADR-0003).
994
1004
  *
995
- * Wraps `GET /api/v1/subnets/{parentSubnetId}/children`. Returns
1005
+ * Wraps `GET /api/v1/subnets/{parentSlug}/children`. Returns
996
1006
  * `SUBNET_NOT_FOUND` when the parent does not exist. Visibility
997
1007
  * matches `listSubnets` — private children you cannot see are
998
1008
  * omitted from the result set.
999
1009
  */
1000
- listChildren(parentSubnetId: string): Promise<SubnetInfo[]>;
1010
+ listChildren(parentSlug: string): Promise<SubnetInfo[]>;
1001
1011
  /**
1002
1012
  * Promote a `task_scoped` subnet to `persistent` (ADR-0003).
1003
1013
  *
1004
1014
  * Owner-only. Idempotent — promoting an already-persistent subnet
1005
1015
  * returns its current state unchanged.
1006
1016
  */
1007
- promoteSubnet(subnetId: string): Promise<SubnetInfo>;
1017
+ promoteSubnet(slug: string): Promise<SubnetInfo>;
1008
1018
  /** Delete a subnet you own (requires Agent API Key — only the owning agent can delete) */
1009
- deleteSubnet(subnetId: string): Promise<{
1019
+ deleteSubnet(slug: string): Promise<{
1010
1020
  success: boolean;
1011
1021
  }>;
1012
1022
  /** Get agents in a subnet */
1013
- getSubnetAgents(subnetId: string): Promise<{
1023
+ getSubnetAgents(slug: string): Promise<{
1014
1024
  agents: AgentInfo[];
1015
1025
  }>;
1016
1026
  /** Join agent to subnet */
1017
- joinSubnet(agentId: string, subnetId: string): Promise<{
1027
+ joinSubnet(agentId: string, slug: string): Promise<{
1018
1028
  success: boolean;
1019
1029
  }>;
1020
1030
  /** Remove agent from subnet */
1021
- leaveSubnet(agentId: string, subnetId: string): Promise<{
1031
+ leaveSubnet(agentId: string, slug: string): Promise<{
1022
1032
  success: boolean;
1023
1033
  }>;
1024
1034
  /** Get agent's subnets */
@@ -1026,7 +1036,7 @@ declare class ACNClient {
1026
1036
  subnets: string[];
1027
1037
  }>;
1028
1038
  /**
1029
- * Pre-authorise `agentId` on `subnetId`'s allowlist (owner only).
1039
+ * Pre-authorise `agentId` on `slug`'s allowlist (owner only).
1030
1040
  *
1031
1041
  * Allowlisted agents skip the approval queue: their next
1032
1042
  * `joinSubnet` lands in branch 4 (allowlist hit) and becomes an
@@ -1036,24 +1046,24 @@ declare class ACNClient {
1036
1046
  * return 409 ALREADY_ON_ALLOWLIST (raised as an error, never
1037
1047
  * silently no-op'd).
1038
1048
  */
1039
- subnetAllowlistAdd(subnetId: string, agentId: string): Promise<SubnetAllowlistEntry>;
1049
+ subnetAllowlistAdd(slug: string, agentId: string): Promise<SubnetAllowlistEntry>;
1040
1050
  /**
1041
- * Remove `agentId` from `subnetId`'s allowlist (owner only).
1051
+ * Remove `agentId` from `slug`'s allowlist (owner only).
1042
1052
  *
1043
1053
  * Idempotent — removing an entry that doesn't exist still
1044
1054
  * returns 204. Per ADR-0004 §"Allowlist mutation does not
1045
1055
  * affect agents who already joined", this does NOT revoke
1046
1056
  * membership for agents already admitted via the allowlist.
1047
1057
  */
1048
- subnetAllowlistRemove(subnetId: string, agentId: string): Promise<void>;
1058
+ subnetAllowlistRemove(slug: string, agentId: string): Promise<void>;
1049
1059
  /**
1050
- * List `subnetId`'s allowlist entries (owner only).
1060
+ * List `slug`'s allowlist entries (owner only).
1051
1061
  *
1052
1062
  * Owner-only by design — the allowlist is a privacy-sensitive
1053
1063
  * trust signal and exposing it publicly would leak relationship
1054
1064
  * metadata.
1055
1065
  */
1056
- subnetAllowlistList(subnetId: string, options?: {
1066
+ subnetAllowlistList(slug: string, options?: {
1057
1067
  limit?: number;
1058
1068
  offset?: number;
1059
1069
  }): Promise<SubnetAllowlistListResponse>;
@@ -1068,7 +1078,7 @@ declare class ACNClient {
1068
1078
  *
1069
1079
  * Optional `note` (≤500 chars) is recorded on the audit row.
1070
1080
  */
1071
- subnetJoinRequestApprove(subnetId: string, requestId: string, options?: {
1081
+ subnetJoinRequestApprove(slug: string, requestId: string, options?: {
1072
1082
  note?: string;
1073
1083
  }): Promise<SubnetJoinRequestRow>;
1074
1084
  /**
@@ -1076,7 +1086,7 @@ declare class ACNClient {
1076
1086
  *
1077
1087
  * No membership change. `subnet.join_rejected` webhook fires.
1078
1088
  */
1079
- subnetJoinRequestReject(subnetId: string, requestId: string, options?: {
1089
+ subnetJoinRequestReject(slug: string, requestId: string, options?: {
1080
1090
  note?: string;
1081
1091
  }): Promise<SubnetJoinRequestRow>;
1082
1092
  /**
@@ -1085,18 +1095,18 @@ declare class ACNClient {
1085
1095
  * Self-only — caller must be the agent who originally created
1086
1096
  * the request. `subnet.join_withdrawn` webhook fires.
1087
1097
  */
1088
- subnetJoinRequestWithdraw(subnetId: string, requestId: string, options?: {
1098
+ subnetJoinRequestWithdraw(slug: string, requestId: string, options?: {
1089
1099
  note?: string;
1090
1100
  }): Promise<SubnetJoinRequestRow>;
1091
1101
  /**
1092
- * Owner lists join_request / allowlist_auto rows for `subnetId`.
1102
+ * Owner lists join_request / allowlist_auto rows for `slug`.
1093
1103
  *
1094
1104
  * `kind` defaults to `'join_request'`; pass `'allowlist_auto'`
1095
1105
  * to inspect synthesised allowlist-hit audit rows. Server
1096
1106
  * rejects `kind='invitation'` with 400 INVALID_KIND_FILTER —
1097
1107
  * use `subnetInvitationList` instead.
1098
1108
  */
1099
- subnetJoinRequestList(subnetId: string, options?: SubnetJoinRequestListOptions): Promise<SubnetJoinRequestListResponse>;
1109
+ subnetJoinRequestList(slug: string, options?: SubnetJoinRequestListOptions): Promise<SubnetJoinRequestListResponse>;
1100
1110
  /**
1101
1111
  * Owner sends an invitation to `agentId` (or merges into a
1102
1112
  * pending join_request from the same target).
@@ -1109,7 +1119,7 @@ declare class ACNClient {
1109
1119
  *
1110
1120
  * Discriminate on `auto_resolved` to dispatch.
1111
1121
  */
1112
- subnetInvitationSend(subnetId: string, agentId: string, options?: {
1122
+ subnetInvitationSend(slug: string, agentId: string, options?: {
1113
1123
  note?: string;
1114
1124
  }): Promise<SubnetInvitationSendResponse>;
1115
1125
  /**
@@ -1120,7 +1130,7 @@ declare class ACNClient {
1120
1130
  * gains the back-reference, and `subnet.invitation_accepted`
1121
1131
  * webhook fires.
1122
1132
  */
1123
- subnetInvitationAccept(subnetId: string, requestId: string, options?: {
1133
+ subnetInvitationAccept(slug: string, requestId: string, options?: {
1124
1134
  note?: string;
1125
1135
  }): Promise<SubnetJoinRequestRow>;
1126
1136
  /**
@@ -1129,7 +1139,7 @@ declare class ACNClient {
1129
1139
  * No membership change. `subnet.invitation_rejected` webhook
1130
1140
  * fires.
1131
1141
  */
1132
- subnetInvitationReject(subnetId: string, requestId: string, options?: {
1142
+ subnetInvitationReject(slug: string, requestId: string, options?: {
1133
1143
  note?: string;
1134
1144
  }): Promise<SubnetJoinRequestRow>;
1135
1145
  /**
@@ -1139,16 +1149,16 @@ declare class ACNClient {
1139
1149
  * `withdrawn` (not `rejected`) — distinct audit token so
1140
1150
  * consumers can tell "owner gave up" from "invitee said no".
1141
1151
  */
1142
- subnetInvitationCancel(subnetId: string, requestId: string, options?: {
1152
+ subnetInvitationCancel(slug: string, requestId: string, options?: {
1143
1153
  note?: string;
1144
1154
  }): Promise<SubnetJoinRequestRow>;
1145
1155
  /**
1146
- * Owner lists invitation rows for `subnetId`.
1156
+ * Owner lists invitation rows for `slug`.
1147
1157
  *
1148
1158
  * Owner-only — invitees use `agentSubnetInvitations` for their
1149
1159
  * own cross-subnet view.
1150
1160
  */
1151
- subnetInvitationList(subnetId: string, options?: SubnetInvitationListOptions): Promise<SubnetInvitationListResponse>;
1161
+ subnetInvitationList(slug: string, options?: SubnetInvitationListOptions): Promise<SubnetInvitationListResponse>;
1152
1162
  /**
1153
1163
  * Invitee's cross-subnet pending-invitation list (self only).
1154
1164
  *
@@ -1220,6 +1230,33 @@ declare class ACNClient {
1220
1230
  }): Promise<{
1221
1231
  messages: Message[];
1222
1232
  }>;
1233
+ /**
1234
+ * Precisely acknowledge (remove) specific messages from the inbox.
1235
+ *
1236
+ * Unlike `getMessageHistory({ consume: true })` which clears the entire inbox,
1237
+ * this method removes only the messages whose `route_id` values are listed.
1238
+ *
1239
+ * @param agentId Must match the authenticated agent's ID.
1240
+ * @param routeIds List of `route_id` values to remove (up to 500).
1241
+ * @returns Number of messages actually removed.
1242
+ */
1243
+ ackInbox(agentId: string, routeIds: string[]): Promise<{
1244
+ acked: number;
1245
+ }>;
1246
+ /**
1247
+ * Update the lifecycle status of a specific inbox message.
1248
+ *
1249
+ * @param agentId Must match the authenticated agent's ID.
1250
+ * @param routeId `route_id` of the target message (from inbox listing).
1251
+ * @param status New status: `"unread"` | `"read"` | `"processed"`.
1252
+ * @returns Object with `agent_id`, `route_id`, and `status`.
1253
+ * @throws 404 (`inbox_message_not_found`) if route_id is absent from inbox.
1254
+ */
1255
+ updateInboxMessageStatus(agentId: string, routeId: string, status: string): Promise<{
1256
+ agent_id: string;
1257
+ route_id: string;
1258
+ status: string;
1259
+ }>;
1223
1260
  /**
1224
1261
  * List manifest queue entries for the authenticated agent.
1225
1262
  *
@@ -1599,7 +1636,7 @@ declare class ACNClient {
1599
1636
  * Register (or clear) an org-harness webhook URL for a subnet.
1600
1637
  * Pass `harnessUrl: null` to deregister.
1601
1638
  */
1602
- registerSubnetHarness(subnetId: string, harnessUrl: string | null, harnessSecret?: string | null): Promise<void>;
1639
+ registerSubnetHarness(slug: string, harnessUrl: string | null, harnessSecret?: string | null): Promise<void>;
1603
1640
  }
1604
1641
  /**
1605
1642
  * ACN API Error
@@ -1715,4 +1752,4 @@ declare class ACNRealtime {
1715
1752
  */
1716
1753
  declare function subscribeToACN<T = unknown>(baseUrl: string, channel: string, handler: WSEventHandler<T>): () => void;
1717
1754
 
1718
- export { ACNClient, type ACNClientOptions, ACNError, ACNRealtime, type ActivityEntry, type AgentActivity, type AgentAnalytics, type AgentInfo, type AgentJoinRequest, type AgentJoinResponse, type AgentRegisterRequest, type AgentRegisterResponse, type AgentSearchOptions, type AgentSearchResponse, type AgentSearchStatus, type AgentStatus, type AgentSubnetInvitationsResponse, type AllowlistActionResponse, type AllowlistEntry, type AllowlistListResponse, type ApiResponse, type AttentionFee, type AuditEvent, type AuditQueryOptions, type BroadcastBySkillRequest, type BroadcastByTagRequest, type BroadcastRequest, type BroadcastStrategy, type CommunicationPolicyMode, type CommunicationPolicyResponse, type CommunicationProfile, type ComponentHealth, type DashboardData, type FollowActionResponse, type FollowCheckResponse, KNOWN_PAYMENT_TASK_STATUSES, type ManifestContentResponse, type ManifestEntry, type ManifestListResponse, type ManifestMessageType, type ManifestSendRequest, type Message, type MessageType, type MetricsData, type Participation, type ParticipationListResponse, type PaymentCapability, type PaymentDiscoveryOptions, type PaymentMethod, type PaymentNetwork, type PaymentRoleStats, type PaymentStats, type PaymentTask, type PaymentTaskStatus, type PendingSessionsResponse, type SendMessageRequest, type SendMessageResponse, type SessionEntry, type SessionInviteRequest, type SessionStatus, type SubnetAllowlistEntry, type SubnetAllowlistListResponse, type SubnetChildrenListResponse, type SubnetCreateRequest, type SubnetCreateResponse, type SubnetHarnessRequest, type SubnetInfo, type SubnetInvitationListOptions, type SubnetInvitationListResponse, type SubnetInvitationSendResponse, type SubnetJoinPolicy, type SubnetJoinRequestListOptions, type SubnetJoinRequestListResponse, type SubnetJoinRequestRow, type SubnetLifecycle, type SystemHealth, type Task, type TaskAcceptResponse, type TaskCreateRequest, type TaskListOptions, type TaskListResponse, type TaskStatus, type WSConnectionOptions, type WSEventHandler, type WSEventType, type WSMessage, type WSState, subscribeToACN };
1755
+ export { ACNClient, type ACNClientOptions, ACNError, ACNRealtime, type ActivityEntry, type AgentActivity, type AgentAnalytics, type AgentInfo, type AgentJoinRequest, type AgentJoinResponse, type AgentRegisterRequest, type AgentRegisterResponse, type AgentSearchOptions, type AgentSearchResponse, type AgentSearchStatus, type AgentStatus, type AgentSubnetInvitationsResponse, type AllowlistActionResponse, type AllowlistEntry, type AllowlistListResponse, type ApiResponse, type AttentionFee, type AuditEvent, type AuditQueryOptions, type BroadcastBySkillRequest, type BroadcastByTagRequest, type BroadcastRequest, type BroadcastStrategy, type CommunicationPolicyMode, type CommunicationPolicyResponse, type CommunicationProfile, type ComponentHealth, type DashboardData, type FollowActionResponse, type FollowCheckResponse, KNOWN_INBOX_MESSAGE_STATUSES, KNOWN_PAYMENT_TASK_STATUSES, type ManifestContentResponse, type ManifestEntry, type ManifestListResponse, type ManifestMessageType, type ManifestSendRequest, type Message, type MessageType, type MetricsData, type Participation, type ParticipationListResponse, type PaymentCapability, type PaymentDiscoveryOptions, type PaymentMethod, type PaymentNetwork, type PaymentRoleStats, type PaymentStats, type PaymentTask, type PaymentTaskStatus, type PendingSessionsResponse, type SendMessageRequest, type SendMessageResponse, type SessionEntry, type SessionInviteRequest, type SessionStatus, type SubnetAllowlistEntry, type SubnetAllowlistListResponse, type SubnetChildrenListResponse, type SubnetCreateRequest, type SubnetCreateResponse, type SubnetHarnessRequest, type SubnetInfo, type SubnetInvitationListOptions, type SubnetInvitationListResponse, type SubnetInvitationSendResponse, type SubnetJoinPolicy, type SubnetJoinRequestListOptions, type SubnetJoinRequestListResponse, type SubnetJoinRequestRow, type SubnetLifecycle, type SystemHealth, type Task, type TaskAcceptResponse, type TaskCreateRequest, type TaskListOptions, type TaskListResponse, type TaskStatus, type WSConnectionOptions, type WSEventHandler, type WSEventType, type WSMessage, type WSState, subscribeToACN };
package/dist/index.js CHANGED
@@ -33,6 +33,7 @@ __export(index_exports, {
33
33
  ACNClient: () => ACNClient,
34
34
  ACNError: () => ACNError,
35
35
  ACNRealtime: () => ACNRealtime,
36
+ KNOWN_INBOX_MESSAGE_STATUSES: () => KNOWN_INBOX_MESSAGE_STATUSES,
36
37
  KNOWN_PAYMENT_TASK_STATUSES: () => KNOWN_PAYMENT_TASK_STATUSES,
37
38
  subscribeToACN: () => subscribeToACN
38
39
  });
@@ -123,6 +124,9 @@ var ACNClient = class {
123
124
  post(path, body) {
124
125
  return this.request("POST", path, { body });
125
126
  }
127
+ patch(path, body) {
128
+ return this.request("PATCH", path, { body });
129
+ }
126
130
  delete(path) {
127
131
  return this.request("DELETE", path);
128
132
  }
@@ -239,20 +243,20 @@ var ACNClient = class {
239
243
  return this.get("/api/v1/subnets");
240
244
  }
241
245
  /** Get subnet by ID */
242
- async getSubnet(subnetId) {
243
- return this.get(`/api/v1/subnets/${subnetId}`);
246
+ async getSubnet(slug) {
247
+ return this.get(`/api/v1/subnets/${slug}`);
244
248
  }
245
249
  /**
246
250
  * List immediate children of a subnet (ADR-0003).
247
251
  *
248
- * Wraps `GET /api/v1/subnets/{parentSubnetId}/children`. Returns
252
+ * Wraps `GET /api/v1/subnets/{parentSlug}/children`. Returns
249
253
  * `SUBNET_NOT_FOUND` when the parent does not exist. Visibility
250
254
  * matches `listSubnets` — private children you cannot see are
251
255
  * omitted from the result set.
252
256
  */
253
- async listChildren(parentSubnetId) {
257
+ async listChildren(parentSlug) {
254
258
  const data = await this.get(
255
- `/api/v1/subnets/${parentSubnetId}/children`
259
+ `/api/v1/subnets/${parentSlug}/children`
256
260
  );
257
261
  return data.subnets;
258
262
  }
@@ -262,16 +266,16 @@ var ACNClient = class {
262
266
  * Owner-only. Idempotent — promoting an already-persistent subnet
263
267
  * returns its current state unchanged.
264
268
  */
265
- async promoteSubnet(subnetId) {
266
- return this.post(`/api/v1/subnets/${subnetId}/promote`);
269
+ async promoteSubnet(slug) {
270
+ return this.post(`/api/v1/subnets/${slug}/promote`);
267
271
  }
268
272
  /** Delete a subnet you own (requires Agent API Key — only the owning agent can delete) */
269
- async deleteSubnet(subnetId) {
270
- return this.request("DELETE", `/api/v1/subnets/${subnetId}`);
273
+ async deleteSubnet(slug) {
274
+ return this.request("DELETE", `/api/v1/subnets/${slug}`);
271
275
  }
272
276
  /** Get agents in a subnet */
273
- async getSubnetAgents(subnetId) {
274
- return this.get(`/api/v1/subnets/${subnetId}/agents`);
277
+ async getSubnetAgents(slug) {
278
+ return this.get(`/api/v1/subnets/${slug}/agents`);
275
279
  }
276
280
  // ──────────────────────────────────────────────────────────────────────
277
281
  // Subnet membership (agent-side)
@@ -286,12 +290,12 @@ var ACNClient = class {
286
290
  // scheduled for removal. Requires ACN backend ≥ post-PR-#42.
287
291
  // ──────────────────────────────────────────────────────────────────────
288
292
  /** Join agent to subnet */
289
- async joinSubnet(agentId, subnetId) {
290
- return this.post(`/api/v1/agents/${agentId}/subnets/${subnetId}`);
293
+ async joinSubnet(agentId, slug) {
294
+ return this.post(`/api/v1/agents/${agentId}/subnets/${slug}`);
291
295
  }
292
296
  /** Remove agent from subnet */
293
- async leaveSubnet(agentId, subnetId) {
294
- return this.delete(`/api/v1/agents/${agentId}/subnets/${subnetId}`);
297
+ async leaveSubnet(agentId, slug) {
298
+ return this.delete(`/api/v1/agents/${agentId}/subnets/${slug}`);
295
299
  }
296
300
  /** Get agent's subnets */
297
301
  async getAgentSubnets(agentId) {
@@ -317,7 +321,7 @@ var ACNClient = class {
317
321
  // `/api/v1/agents/{a}/allowlist/{target}` and is unrelated).
318
322
  // ----- Allowlist (owner-only, 3 verbs) ---------------------------------
319
323
  /**
320
- * Pre-authorise `agentId` on `subnetId`'s allowlist (owner only).
324
+ * Pre-authorise `agentId` on `slug`'s allowlist (owner only).
321
325
  *
322
326
  * Allowlisted agents skip the approval queue: their next
323
327
  * `joinSubnet` lands in branch 4 (allowlist hit) and becomes an
@@ -327,35 +331,35 @@ var ACNClient = class {
327
331
  * return 409 ALREADY_ON_ALLOWLIST (raised as an error, never
328
332
  * silently no-op'd).
329
333
  */
330
- async subnetAllowlistAdd(subnetId, agentId) {
331
- return this.post(`/api/v1/subnets/${subnetId}/allowlist`, {
334
+ async subnetAllowlistAdd(slug, agentId) {
335
+ return this.post(`/api/v1/subnets/${slug}/allowlist`, {
332
336
  agent_id: agentId
333
337
  });
334
338
  }
335
339
  /**
336
- * Remove `agentId` from `subnetId`'s allowlist (owner only).
340
+ * Remove `agentId` from `slug`'s allowlist (owner only).
337
341
  *
338
342
  * Idempotent — removing an entry that doesn't exist still
339
343
  * returns 204. Per ADR-0004 §"Allowlist mutation does not
340
344
  * affect agents who already joined", this does NOT revoke
341
345
  * membership for agents already admitted via the allowlist.
342
346
  */
343
- async subnetAllowlistRemove(subnetId, agentId) {
344
- await this.delete(`/api/v1/subnets/${subnetId}/allowlist/${agentId}`);
347
+ async subnetAllowlistRemove(slug, agentId) {
348
+ await this.delete(`/api/v1/subnets/${slug}/allowlist/${agentId}`);
345
349
  }
346
350
  /**
347
- * List `subnetId`'s allowlist entries (owner only).
351
+ * List `slug`'s allowlist entries (owner only).
348
352
  *
349
353
  * Owner-only by design — the allowlist is a privacy-sensitive
350
354
  * trust signal and exposing it publicly would leak relationship
351
355
  * metadata.
352
356
  */
353
- async subnetAllowlistList(subnetId, options) {
357
+ async subnetAllowlistList(slug, options) {
354
358
  const params = {
355
359
  limit: options?.limit ?? 100,
356
360
  offset: options?.offset ?? 0
357
361
  };
358
- return this.get(`/api/v1/subnets/${subnetId}/allowlist`, params);
362
+ return this.get(`/api/v1/subnets/${slug}/allowlist`, params);
359
363
  }
360
364
  // ----- Join requests (4 verbs: 3 owner-side + 1 applicant-side) --------
361
365
  /**
@@ -369,9 +373,9 @@ var ACNClient = class {
369
373
  *
370
374
  * Optional `note` (≤500 chars) is recorded on the audit row.
371
375
  */
372
- async subnetJoinRequestApprove(subnetId, requestId, options) {
376
+ async subnetJoinRequestApprove(slug, requestId, options) {
373
377
  return this.post(
374
- `/api/v1/subnets/${subnetId}/join-requests/${requestId}/approve`,
378
+ `/api/v1/subnets/${slug}/join-requests/${requestId}/approve`,
375
379
  options?.note !== void 0 ? { note: options.note } : void 0
376
380
  );
377
381
  }
@@ -380,9 +384,9 @@ var ACNClient = class {
380
384
  *
381
385
  * No membership change. `subnet.join_rejected` webhook fires.
382
386
  */
383
- async subnetJoinRequestReject(subnetId, requestId, options) {
387
+ async subnetJoinRequestReject(slug, requestId, options) {
384
388
  return this.post(
385
- `/api/v1/subnets/${subnetId}/join-requests/${requestId}/reject`,
389
+ `/api/v1/subnets/${slug}/join-requests/${requestId}/reject`,
386
390
  options?.note !== void 0 ? { note: options.note } : void 0
387
391
  );
388
392
  }
@@ -392,29 +396,29 @@ var ACNClient = class {
392
396
  * Self-only — caller must be the agent who originally created
393
397
  * the request. `subnet.join_withdrawn` webhook fires.
394
398
  */
395
- async subnetJoinRequestWithdraw(subnetId, requestId, options) {
399
+ async subnetJoinRequestWithdraw(slug, requestId, options) {
396
400
  return this.request(
397
401
  "DELETE",
398
- `/api/v1/subnets/${subnetId}/join-requests/${requestId}`,
402
+ `/api/v1/subnets/${slug}/join-requests/${requestId}`,
399
403
  options?.note !== void 0 ? { body: { note: options.note } } : void 0
400
404
  );
401
405
  }
402
406
  /**
403
- * Owner lists join_request / allowlist_auto rows for `subnetId`.
407
+ * Owner lists join_request / allowlist_auto rows for `slug`.
404
408
  *
405
409
  * `kind` defaults to `'join_request'`; pass `'allowlist_auto'`
406
410
  * to inspect synthesised allowlist-hit audit rows. Server
407
411
  * rejects `kind='invitation'` with 400 INVALID_KIND_FILTER —
408
412
  * use `subnetInvitationList` instead.
409
413
  */
410
- async subnetJoinRequestList(subnetId, options) {
414
+ async subnetJoinRequestList(slug, options) {
411
415
  const params = {
412
416
  kind: options?.kind ?? "join_request",
413
417
  limit: options?.limit ?? 100,
414
418
  offset: options?.offset ?? 0
415
419
  };
416
420
  if (options?.status !== void 0) params.status = options.status;
417
- return this.get(`/api/v1/subnets/${subnetId}/join-requests`, params);
421
+ return this.get(`/api/v1/subnets/${slug}/join-requests`, params);
418
422
  }
419
423
  // ----- Invitations (5 + 1 verbs) ---------------------------------------
420
424
  /**
@@ -429,10 +433,10 @@ var ACNClient = class {
429
433
  *
430
434
  * Discriminate on `auto_resolved` to dispatch.
431
435
  */
432
- async subnetInvitationSend(subnetId, agentId, options) {
436
+ async subnetInvitationSend(slug, agentId, options) {
433
437
  const body = { agent_id: agentId };
434
438
  if (options?.note !== void 0) body.note = options.note;
435
- return this.post(`/api/v1/subnets/${subnetId}/invitations`, body);
439
+ return this.post(`/api/v1/subnets/${slug}/invitations`, body);
436
440
  }
437
441
  /**
438
442
  * Invitee accepts a pending invitation (CAS pending → approved).
@@ -442,9 +446,9 @@ var ACNClient = class {
442
446
  * gains the back-reference, and `subnet.invitation_accepted`
443
447
  * webhook fires.
444
448
  */
445
- async subnetInvitationAccept(subnetId, requestId, options) {
449
+ async subnetInvitationAccept(slug, requestId, options) {
446
450
  return this.post(
447
- `/api/v1/subnets/${subnetId}/invitations/${requestId}/accept`,
451
+ `/api/v1/subnets/${slug}/invitations/${requestId}/accept`,
448
452
  options?.note !== void 0 ? { note: options.note } : void 0
449
453
  );
450
454
  }
@@ -454,9 +458,9 @@ var ACNClient = class {
454
458
  * No membership change. `subnet.invitation_rejected` webhook
455
459
  * fires.
456
460
  */
457
- async subnetInvitationReject(subnetId, requestId, options) {
461
+ async subnetInvitationReject(slug, requestId, options) {
458
462
  return this.post(
459
- `/api/v1/subnets/${subnetId}/invitations/${requestId}/reject`,
463
+ `/api/v1/subnets/${slug}/invitations/${requestId}/reject`,
460
464
  options?.note !== void 0 ? { note: options.note } : void 0
461
465
  );
462
466
  }
@@ -467,26 +471,26 @@ var ACNClient = class {
467
471
  * `withdrawn` (not `rejected`) — distinct audit token so
468
472
  * consumers can tell "owner gave up" from "invitee said no".
469
473
  */
470
- async subnetInvitationCancel(subnetId, requestId, options) {
474
+ async subnetInvitationCancel(slug, requestId, options) {
471
475
  return this.request(
472
476
  "DELETE",
473
- `/api/v1/subnets/${subnetId}/invitations/${requestId}`,
477
+ `/api/v1/subnets/${slug}/invitations/${requestId}`,
474
478
  options?.note !== void 0 ? { body: { note: options.note } } : void 0
475
479
  );
476
480
  }
477
481
  /**
478
- * Owner lists invitation rows for `subnetId`.
482
+ * Owner lists invitation rows for `slug`.
479
483
  *
480
484
  * Owner-only — invitees use `agentSubnetInvitations` for their
481
485
  * own cross-subnet view.
482
486
  */
483
- async subnetInvitationList(subnetId, options) {
487
+ async subnetInvitationList(slug, options) {
484
488
  const params = {
485
489
  limit: options?.limit ?? 100,
486
490
  offset: options?.offset ?? 0
487
491
  };
488
492
  if (options?.status !== void 0) params.status = options.status;
489
- return this.get(`/api/v1/subnets/${subnetId}/invitations`, params);
493
+ return this.get(`/api/v1/subnets/${slug}/invitations`, params);
490
494
  }
491
495
  /**
492
496
  * Invitee's cross-subnet pending-invitation list (self only).
@@ -551,6 +555,31 @@ var ACNClient = class {
551
555
  if (options?.consume) params.ack = true;
552
556
  return this.get(`/api/v1/communication/history/${agentId}`, params);
553
557
  }
558
+ /**
559
+ * Precisely acknowledge (remove) specific messages from the inbox.
560
+ *
561
+ * Unlike `getMessageHistory({ consume: true })` which clears the entire inbox,
562
+ * this method removes only the messages whose `route_id` values are listed.
563
+ *
564
+ * @param agentId Must match the authenticated agent's ID.
565
+ * @param routeIds List of `route_id` values to remove (up to 500).
566
+ * @returns Number of messages actually removed.
567
+ */
568
+ async ackInbox(agentId, routeIds) {
569
+ return this.post(`/api/v1/communication/history/${agentId}/ack`, { route_ids: routeIds });
570
+ }
571
+ /**
572
+ * Update the lifecycle status of a specific inbox message.
573
+ *
574
+ * @param agentId Must match the authenticated agent's ID.
575
+ * @param routeId `route_id` of the target message (from inbox listing).
576
+ * @param status New status: `"unread"` | `"read"` | `"processed"`.
577
+ * @returns Object with `agent_id`, `route_id`, and `status`.
578
+ * @throws 404 (`inbox_message_not_found`) if route_id is absent from inbox.
579
+ */
580
+ async updateInboxMessageStatus(agentId, routeId, status) {
581
+ return this.patch(`/api/v1/communication/history/${agentId}/${routeId}`, { status });
582
+ }
554
583
  // ============================================
555
584
  // Manifest Queue (Phase 2/3)
556
585
  // ============================================
@@ -1127,8 +1156,8 @@ var ACNClient = class {
1127
1156
  * Register (or clear) an org-harness webhook URL for a subnet.
1128
1157
  * Pass `harnessUrl: null` to deregister.
1129
1158
  */
1130
- async registerSubnetHarness(subnetId, harnessUrl, harnessSecret) {
1131
- await this.request("PATCH", `/api/v1/subnets/${subnetId}/harness`, {
1159
+ async registerSubnetHarness(slug, harnessUrl, harnessSecret) {
1160
+ await this.request("PATCH", `/api/v1/subnets/${slug}/harness`, {
1132
1161
  body: {
1133
1162
  harness_url: harnessUrl,
1134
1163
  harness_secret: harnessSecret ?? null
@@ -1363,11 +1392,17 @@ var KNOWN_PAYMENT_TASK_STATUSES = [
1363
1392
  "payment_failed",
1364
1393
  "refunded"
1365
1394
  ];
1395
+ var KNOWN_INBOX_MESSAGE_STATUSES = [
1396
+ "unread",
1397
+ "read",
1398
+ "processed"
1399
+ ];
1366
1400
  // Annotate the CommonJS export names for ESM import in node:
1367
1401
  0 && (module.exports = {
1368
1402
  ACNClient,
1369
1403
  ACNError,
1370
1404
  ACNRealtime,
1405
+ KNOWN_INBOX_MESSAGE_STATUSES,
1371
1406
  KNOWN_PAYMENT_TASK_STATUSES,
1372
1407
  subscribeToACN
1373
1408
  });