memax-sdk 0.1.11 → 0.1.13

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.
Files changed (64) hide show
  1. package/dist/client.d.ts +4 -2
  2. package/dist/client.d.ts.map +1 -1
  3. package/dist/client.js +6 -3
  4. package/dist/client.js.map +1 -1
  5. package/dist/client.test.js +226 -1
  6. package/dist/client.test.js.map +1 -1
  7. package/dist/errors.d.ts +4 -1
  8. package/dist/errors.d.ts.map +1 -1
  9. package/dist/errors.js +7 -1
  10. package/dist/errors.js.map +1 -1
  11. package/dist/index.d.ts +2 -1
  12. package/dist/index.d.ts.map +1 -1
  13. package/dist/index.js.map +1 -1
  14. package/dist/resources/admin.d.ts +357 -0
  15. package/dist/resources/admin.d.ts.map +1 -0
  16. package/dist/resources/admin.js +168 -0
  17. package/dist/resources/admin.js.map +1 -0
  18. package/dist/resources/agent-sessions.d.ts +3 -1
  19. package/dist/resources/agent-sessions.d.ts.map +1 -1
  20. package/dist/resources/agent-sessions.js +6 -0
  21. package/dist/resources/agent-sessions.js.map +1 -1
  22. package/dist/resources/agents.d.ts +14 -0
  23. package/dist/resources/agents.d.ts.map +1 -1
  24. package/dist/resources/agents.js +21 -1
  25. package/dist/resources/agents.js.map +1 -1
  26. package/dist/resources/auth.d.ts +12 -2
  27. package/dist/resources/auth.d.ts.map +1 -1
  28. package/dist/resources/auth.js +15 -1
  29. package/dist/resources/auth.js.map +1 -1
  30. package/dist/resources/configs.d.ts +20 -1
  31. package/dist/resources/configs.d.ts.map +1 -1
  32. package/dist/resources/configs.js +25 -0
  33. package/dist/resources/configs.js.map +1 -1
  34. package/dist/resources/hubs.d.ts +22 -3
  35. package/dist/resources/hubs.d.ts.map +1 -1
  36. package/dist/resources/hubs.js +26 -4
  37. package/dist/resources/hubs.js.map +1 -1
  38. package/dist/resources/memories.d.ts +48 -7
  39. package/dist/resources/memories.d.ts.map +1 -1
  40. package/dist/resources/memories.js +67 -3
  41. package/dist/resources/memories.js.map +1 -1
  42. package/dist/resources/notifications.d.ts +75 -0
  43. package/dist/resources/notifications.d.ts.map +1 -0
  44. package/dist/resources/notifications.js +106 -0
  45. package/dist/resources/notifications.js.map +1 -0
  46. package/dist/resources/settings.d.ts +11 -3
  47. package/dist/resources/settings.d.ts.map +1 -1
  48. package/dist/resources/settings.js +10 -0
  49. package/dist/resources/settings.js.map +1 -1
  50. package/dist/resources/topics.d.ts +54 -2
  51. package/dist/resources/topics.d.ts.map +1 -1
  52. package/dist/resources/topics.js +58 -2
  53. package/dist/resources/topics.js.map +1 -1
  54. package/dist/transport.d.ts +8 -1
  55. package/dist/transport.d.ts.map +1 -1
  56. package/dist/transport.js +20 -2
  57. package/dist/transport.js.map +1 -1
  58. package/dist/types.d.ts +780 -18
  59. package/dist/types.d.ts.map +1 -1
  60. package/package.json +1 -1
  61. package/dist/resources/reviews.d.ts +0 -9
  62. package/dist/resources/reviews.d.ts.map +0 -1
  63. package/dist/resources/reviews.js +0 -16
  64. package/dist/resources/reviews.js.map +0 -1
package/dist/types.d.ts CHANGED
@@ -18,6 +18,8 @@ export interface MemaxConfig {
18
18
  maxRetries?: number;
19
19
  /** Delay between retry attempts in milliseconds */
20
20
  retryDelayMs?: number;
21
+ /** Optional hook for warning headers returned by the API transport. */
22
+ onWarning?: (warning: string) => void;
21
23
  }
22
24
  export type AskModel = "auto" | "haiku" | "sonnet";
23
25
  export type Locale = "en" | "zh";
@@ -31,6 +33,9 @@ export interface PushOptions {
31
33
  source?: string;
32
34
  /** Agent identity: "claude-code", "cursor", "copilot", etc. Auto-set by hooks/MCP. */
33
35
  sourceAgent?: string;
36
+ /** Human collaboration credit, not actor identity. */
37
+ assistedByAgent?: string;
38
+ initiationType?: "human_direct" | "human_requested_agent" | "agent_proactive" | "agent_automatic" | "import" | "unknown";
34
39
  sourcePath?: string;
35
40
  contentType?: string;
36
41
  projectContext?: Record<string, string>;
@@ -42,8 +47,12 @@ export interface RecallOptions {
42
47
  limit?: number;
43
48
  kind?: MemoryKind;
44
49
  tags?: string[];
50
+ /** Restrict results to memories in this topic. */
51
+ topicId?: string;
45
52
  source?: string;
46
53
  includeArchived?: boolean;
54
+ /** Skip reranking. Useful for faster results or debugging scoring. */
55
+ noRerank?: boolean;
47
56
  workingDir?: string;
48
57
  projectContext?: Record<string, string>;
49
58
  /** Active hub ranking hint. Recall still searches every hub the token can access. */
@@ -53,8 +62,12 @@ export interface AskOptions {
53
62
  limit?: number;
54
63
  model?: AskModel;
55
64
  locale?: Locale;
65
+ /** Skip reranking for source retrieval. */
66
+ noRerank?: boolean;
56
67
  /** Active hub ranking hint for Ask retrieval. Ask still searches every hub the token can access. */
57
68
  hubId?: string;
69
+ /** Restrict ask retrieval to memories in this topic. */
70
+ topicId?: string;
58
71
  }
59
72
  export interface ListMemoriesOptions {
60
73
  limit?: number;
@@ -64,6 +77,7 @@ export interface ListMemoriesOptions {
64
77
  createdAfter?: string;
65
78
  actor?: string;
66
79
  hubId?: string;
80
+ topicId?: string;
67
81
  }
68
82
  export interface MemoryActorCounts {
69
83
  [actor: string]: number;
@@ -89,6 +103,8 @@ export interface Memory {
89
103
  pinned: boolean;
90
104
  source: string;
91
105
  source_agent?: string;
106
+ assisted_by_agent?: string;
107
+ provenance?: MemoryProvenance;
92
108
  source_path?: string;
93
109
  hub_reason?: string;
94
110
  original_file_ref?: string;
@@ -105,6 +121,59 @@ export interface Memory {
105
121
  hub_name?: string;
106
122
  agent_display_name?: string;
107
123
  agent_icon?: string;
124
+ /** Server-resolved dream-delta signals. See MemoryLifecycle docs. */
125
+ lifecycle?: MemoryLifecycle;
126
+ }
127
+ export interface MemoryProvenance {
128
+ created_by_type: "human" | "agent";
129
+ created_by_slug?: string;
130
+ created_by_display_name?: string;
131
+ created_via?: string;
132
+ assisted_by_agent?: string;
133
+ initiation_type: "human_direct" | "human_requested_agent" | "agent_proactive" | "agent_automatic" | "import" | "unknown";
134
+ attribution_source?: string;
135
+ }
136
+ /**
137
+ * MemoryLifecycle — durable dream-delta signals for memory rows + detail.
138
+ *
139
+ * Two fields with distinct scopes:
140
+ * - pending_dream_action drives scan surfaces (row breadcrumb tint).
141
+ * Scoped to the viewer's last visit of the memory's current topic;
142
+ * server returns null after the viewer visits.
143
+ * - dream_history drives the memory detail provenance strip. Up to 10
144
+ * most recent dream actions, unscoped, durable. Empty array on list
145
+ * reads; populated only on detail reads.
146
+ */
147
+ export interface MemoryLifecycle {
148
+ pending_dream_action: DreamActionRef | null;
149
+ dream_history: DreamActionRef[];
150
+ }
151
+ /**
152
+ * DreamActionRef — client-facing shape of a dream action.
153
+ *
154
+ * from_topic / to_topic are nullable — historical rows (pre-migration 069)
155
+ * stay null and UI renders verb + reason without lineage.
156
+ */
157
+ export interface DreamActionRef {
158
+ run_id: string;
159
+ action_type: "organize" | "merge" | "archive" | "restructure";
160
+ at: string;
161
+ from_topic: DreamTopicRef | null;
162
+ to_topic: DreamTopicRef | null;
163
+ reason?: string;
164
+ }
165
+ export interface DreamTopicRef {
166
+ id: string;
167
+ name: string;
168
+ /**
169
+ * Lucide icon name at the time the reference was resolved (e.g.
170
+ * "folder", "code"). Empty/undefined when the topic has no icon.
171
+ * Server uses the scoped topic join, so this field is never present
172
+ * when the topic is out of the viewer's scope (whole ref is null in
173
+ * that case). UI chips render `icon + name` to keep topic identity
174
+ * consistent across row breadcrumb, dream history, and hover card.
175
+ */
176
+ icon?: string;
108
177
  }
109
178
  export interface MemoryUpdateInput {
110
179
  title?: string;
@@ -113,6 +182,113 @@ export interface MemoryUpdateInput {
113
182
  tags?: string[];
114
183
  }
115
184
  export type ShareMemoryResult = Memory;
185
+ /**
186
+ * Reason a batch-move request skipped a given memory id.
187
+ * - `not_owned`: the caller does not own this memory (team-hub shared content).
188
+ * - `not_found`: the id does not exist or has been deleted.
189
+ * - `already_at_target`: the memory's current hub + topic already matches.
190
+ * - `source_delete_forbidden`: the caller owns the memory but lacks
191
+ * authority to remove it from its current hub. Move is semantically
192
+ * delete-from-source + create-in-destination, so the source hub's
193
+ * `contributor_delete_policy` must be honored. Emitted only for
194
+ * cross-hub moves; same-hub topic reassignments skip the check.
195
+ */
196
+ export type BatchMoveSkipReason = "not_owned" | "not_found" | "already_at_target" | "source_delete_forbidden";
197
+ export interface BatchMoveSkippedMemory {
198
+ id: string;
199
+ reason: BatchMoveSkipReason;
200
+ }
201
+ /**
202
+ * Structured response from `POST /v1/memories/batch-move`.
203
+ *
204
+ * `moved` is the count of memories actually reassigned in this request.
205
+ * `skipped` lists every input id that was not moved, with a reason code.
206
+ * Consumers should treat any `moved > 0` as partial success and surface
207
+ * skipped counts to the user so they know why fewer moved than requested.
208
+ */
209
+ export interface BatchMoveResult {
210
+ moved: number;
211
+ skipped: BatchMoveSkippedMemory[];
212
+ }
213
+ /**
214
+ * Reason a batch-delete request skipped a given memory id.
215
+ * - `not_owned`: the caller does not own the memory and does not hold a
216
+ * hub role + contributor_delete_policy that covers it. Single code for
217
+ * both "wrong owner, no hub context" and "hub member but policy forbids."
218
+ * - `not_found`: the id does not exist at request time. Covers unknown
219
+ * ids AND the race where a row is removed concurrently between
220
+ * accessibility load and the actual DELETE.
221
+ * - `delete_failed`: a store-level error occurred while attempting to
222
+ * delete this id (postgres transient error, object-store failure).
223
+ * Distinguished from `not_found` so clients can retry infra issues
224
+ * without blaming the user. Server logs the underlying error.
225
+ */
226
+ export type BatchDeleteSkipReason = "not_owned" | "not_found" | "delete_failed";
227
+ export interface BatchDeleteSkippedMemory {
228
+ id: string;
229
+ reason: BatchDeleteSkipReason;
230
+ }
231
+ /**
232
+ * Structured response from `POST /v1/memories/batch-delete`.
233
+ *
234
+ * `deleted` is the count of memories actually removed in this request.
235
+ * `skipped` lists every input id that was not deleted, with a reason.
236
+ *
237
+ * Partial-success semantics: `deleted > 0` with non-empty `skipped` is a
238
+ * normal, intentional outcome — the server commits what it can and
239
+ * reports the rest. Clients should surface the partial count to the user.
240
+ *
241
+ * Full-skip semantics: `deleted === 0` can happen for three different
242
+ * reasons (all-not_owned, all-not_found, all-delete_failed). Clients
243
+ * should inspect `skipped[].reason` to pick appropriate copy rather than
244
+ * showing one generic error for all three. `not_found` in particular is
245
+ * usually the user's desired end state (the memory is gone) and should
246
+ * be treated as effective success.
247
+ */
248
+ export interface BatchDeleteResult {
249
+ deleted: number;
250
+ skipped: BatchDeleteSkippedMemory[];
251
+ }
252
+ /**
253
+ * Skip reasons for `POST /v1/configs/batch-delete`. The agent config reason
254
+ * set is deliberately narrower than `BatchDeleteSkipReason`:
255
+ *
256
+ * - `not_found`: the config id does not resolve for the caller. The server
257
+ * collapses "unknown id", "already deleted", and "owned by another user"
258
+ * into this single reason because the SQL WHERE clause makes them
259
+ * indistinguishable without an extra round-trip, and all three map to
260
+ * idempotent success on the client (the user's target state is reached).
261
+ * - `delete_failed`: the tombstone insert or the DELETE itself returned an
262
+ * error mid-batch. Distinguished from `not_found` so the client can
263
+ * retry infra failures and roll back the optimistic list removal.
264
+ *
265
+ * There is deliberately no `not_owned` — the agent config store enforces
266
+ * ownership via the WHERE clause, so the web hook's catch branch does not
267
+ * need to handle a permission-style reason. Keeping the union narrow means
268
+ * dead code (e.g. a `forgetDenied` toast branch) would be caught at
269
+ * compile time.
270
+ */
271
+ export type AgentConfigDeleteSkipReason = "not_found" | "delete_failed";
272
+ export interface AgentConfigDeleteSkippedItem {
273
+ id: string;
274
+ reason: AgentConfigDeleteSkipReason;
275
+ }
276
+ /**
277
+ * Structured response from `POST /v1/configs/batch-delete`.
278
+ *
279
+ * Shares the same shape as `BatchDeleteResult` (deleted count + skipped
280
+ * array) but narrows the reason union to the agent-config taxonomy. The
281
+ * server always returns 200 with this body in the ApiResponse envelope —
282
+ * 4xx/5xx are reserved for full-request failures.
283
+ *
284
+ * Partial-success is the default: `deleted > 0` with non-empty `skipped`
285
+ * means the server committed what it could and reports the rest so the
286
+ * client can surface a partial-success toast.
287
+ */
288
+ export interface AgentConfigBatchDeleteResult {
289
+ deleted: number;
290
+ skipped: AgentConfigDeleteSkippedItem[];
291
+ }
116
292
  export interface MemoryAttachment {
117
293
  id: string;
118
294
  memory_id: string;
@@ -122,8 +298,28 @@ export interface MemoryAttachment {
122
298
  content_type: string;
123
299
  size_bytes: number;
124
300
  sha256: string;
301
+ /** Width in pixels. Present only for images that decoded successfully
302
+ * at upload time. Use with `height` to reserve layout space and
303
+ * avoid CLS when rendering inline previews. */
304
+ width?: number | null;
305
+ /** Height in pixels. See `width`. */
306
+ height?: number | null;
307
+ /** True when the signed view endpoint may serve this attachment
308
+ * with Content-Disposition: inline. Clients should require BOTH
309
+ * this flag AND a raster content_type before rendering via
310
+ * <img src> — defense in depth against partially-migrated rows. */
311
+ inline_eligible?: boolean;
125
312
  created_at: string;
126
313
  }
314
+ /** Short-lived signed URL for rendering an attachment inline. Caller
315
+ * passes this straight to <img src>. Reuse within the TTL window is
316
+ * expected — the same image renders across inbox modal, memory
317
+ * detail, and lightbox without re-signing. */
318
+ export interface AttachmentViewURL {
319
+ url: string;
320
+ /** Unix seconds UTC. Clients should refresh shortly before expiry. */
321
+ expires_at: number;
322
+ }
127
323
  export interface FileRef {
128
324
  object_key: string;
129
325
  filename: string;
@@ -324,7 +520,7 @@ export interface DeletedAgentSession {
324
520
  content_hash?: string;
325
521
  content_expires_at?: string;
326
522
  }
327
- export type SessionSyncAction = "unchanged" | "push" | "pull" | "conflict" | "delete_local";
523
+ export type SessionSyncAction = "unchanged" | "push" | "pull" | "diverged" | "tombstone_diverged" | "delete_local";
328
524
  export interface SessionSyncPlanAction {
329
525
  action: SessionSyncAction;
330
526
  agent: string;
@@ -334,8 +530,28 @@ export interface SessionSyncPlanAction {
334
530
  session_id?: string;
335
531
  cloud_hash?: string;
336
532
  cloud_updated_at?: string;
533
+ cloud_version?: number;
337
534
  version?: number;
338
535
  }
536
+ /** Request to atomically resolve a diverged session. */
537
+ export interface ResolveDivergenceRequest {
538
+ agent: string;
539
+ file_path: string;
540
+ scope: Scope;
541
+ device_id: string;
542
+ local_file_ref?: FileRef;
543
+ local_content_hash: string;
544
+ expected_cloud_version: number;
545
+ expected_cloud_hash: string;
546
+ resolution: "keep_local" | "keep_cloud";
547
+ }
548
+ /** Response from a successful divergence resolution. */
549
+ export interface ResolveDivergenceResponse {
550
+ winner: "local" | "cloud";
551
+ snapshot_id: string;
552
+ snapshot_device: string;
553
+ new_version: number;
554
+ }
339
555
  export interface SessionSyncManifestEntry {
340
556
  agent: string;
341
557
  file_path: string;
@@ -390,8 +606,12 @@ export interface User {
390
606
  name: string;
391
607
  email: string;
392
608
  plan: string;
609
+ personal_plan_id: string;
393
610
  display_name?: string;
394
611
  avatar_url?: string;
612
+ can_create_hub?: boolean;
613
+ created_at?: string;
614
+ updated_at?: string;
395
615
  }
396
616
  export interface Usage {
397
617
  user_id: string;
@@ -401,6 +621,56 @@ export interface Usage {
401
621
  recall_count: number;
402
622
  ask_count: number;
403
623
  }
624
+ /** Plan scope distinguishes personal plans (assigned to users) from hub plans (assigned to team hubs). */
625
+ export type PlanScope = "personal" | "hub";
626
+ export interface PlanDefinition {
627
+ id: string;
628
+ scope: PlanScope;
629
+ display_name: string;
630
+ tier_order: number;
631
+ entitlement_rank: number;
632
+ monthly_price_cents: number;
633
+ memory_limit: number;
634
+ push_limit: number;
635
+ recall_limit: number;
636
+ ask_limit: number;
637
+ ask_model: "haiku" | "sonnet";
638
+ dreams_enabled: boolean;
639
+ review_inbox: boolean;
640
+ max_team_hubs: number;
641
+ max_owned_free_team_hubs: number;
642
+ max_hub_members: number | null;
643
+ seat_minimum: number;
644
+ seat_billed: boolean;
645
+ rate_limit_rpm: number;
646
+ rate_limit_heavy_rpm: number;
647
+ rate_limit_light_rpm: number;
648
+ features: Record<string, unknown>;
649
+ active: boolean;
650
+ created_at: string;
651
+ updated_at: string;
652
+ }
653
+ export interface UserLimits {
654
+ plan_id: string;
655
+ plan_display_name: string;
656
+ memory_limit: number;
657
+ push_limit: number;
658
+ recall_limit: number;
659
+ ask_limit: number;
660
+ ask_model: string;
661
+ dreams_enabled: boolean;
662
+ review_inbox: boolean;
663
+ max_team_hubs: number;
664
+ rate_limit_rpm: number;
665
+ rate_limit_heavy_rpm: number;
666
+ rate_limit_light_rpm: number;
667
+ }
668
+ /** Enriched usage response with plan limits. Backward-compatible with Usage. */
669
+ export interface UsageWithLimits extends Usage {
670
+ limits: UserLimits;
671
+ plan: string;
672
+ plan_display_name: string;
673
+ }
404
674
  export interface MeResponse {
405
675
  user: User;
406
676
  connected_providers?: AuthProviderName[];
@@ -412,6 +682,7 @@ export interface MeResponse {
412
682
  };
413
683
  role: HubRole;
414
684
  }>;
685
+ /** Basic usage from /v1/auth/me. For enriched usage with limits, use settings.usage(). */
415
686
  usage?: Usage;
416
687
  }
417
688
  export interface AuthTokenPair {
@@ -561,8 +832,32 @@ export interface HubInvite {
561
832
  invite_url?: string;
562
833
  expires_at: string;
563
834
  accepted_by?: string | null;
835
+ /**
836
+ * When present, the invite is addressed to a specific existing
837
+ * user. The server writes this field when `createInvite` is
838
+ * called with an `invitee` that resolves to an account. Link-only
839
+ * invites (the legacy copy-link flow) leave this null / omitted.
840
+ */
841
+ invitee_user_id?: string | null;
842
+ /** The email the admin typed. Set for email invites alongside invitee_user_id (if resolved). */
843
+ invitee_email?: string | null;
844
+ /** When the email job was last submitted to the queue. Enqueue time, not confirmed delivery. */
845
+ email_enqueued_at?: string | null;
564
846
  created_at: string;
565
847
  }
848
+ /**
849
+ * HubInviteeInput is the addressed-recipient shape accepted by
850
+ * `hubs.createInvite`. Exactly one of `user_id` or `email` should be
851
+ * set; when both are present the server prefers `user_id`.
852
+ *
853
+ * Unknown emails / user ids do not fail the request — they fall
854
+ * through to a link-only invite so the admin can forward the URL
855
+ * manually.
856
+ */
857
+ export interface HubInviteeInput {
858
+ user_id?: string;
859
+ email?: string;
860
+ }
566
861
  export interface HubOwnershipTransfer {
567
862
  id: string;
568
863
  hub_id: string;
@@ -579,7 +874,6 @@ export interface HubUpdateParams {
579
874
  name?: string;
580
875
  icon?: string;
581
876
  accent?: HubAccent;
582
- slug?: string;
583
877
  allow_contributor_topics?: boolean;
584
878
  allow_contributor_dreams?: boolean;
585
879
  contributor_delete_policy?: ContributorDeletePolicy;
@@ -627,6 +921,14 @@ export interface InviteAcceptResult {
627
921
  hub: Hub;
628
922
  role: HubRole;
629
923
  }
924
+ export interface DevFlagsSettings {
925
+ mockDreams: boolean;
926
+ mockDreaming: boolean;
927
+ mockEmptyInbox: boolean;
928
+ mockProUser: boolean;
929
+ debuggerEnabled: boolean;
930
+ skipRerank: boolean;
931
+ }
630
932
  export interface Settings {
631
933
  dreams_enabled: boolean;
632
934
  dreams_merge_enabled: boolean;
@@ -636,10 +938,24 @@ export interface Settings {
636
938
  dreams_similarity_threshold: number;
637
939
  dreams_staleness_days: number;
638
940
  hub_header_aurora_mode?: "none" | "signature" | "time";
941
+ dev_flags?: DevFlagsSettings;
639
942
  notifications_enabled: boolean;
640
943
  theme: string;
641
944
  [key: string]: unknown;
642
945
  }
946
+ export interface SettingsUpdateInput {
947
+ dreams_enabled?: boolean;
948
+ dreams_merge_enabled?: boolean;
949
+ dreams_archive_enabled?: boolean;
950
+ dreams_organize_enabled?: boolean;
951
+ dreams_excluded_kinds?: MemoryKind[];
952
+ dreams_similarity_threshold?: number;
953
+ dreams_staleness_days?: number;
954
+ hub_header_aurora_mode?: "none" | "signature" | "time";
955
+ dev_flags?: Partial<DevFlagsSettings>;
956
+ notifications_enabled?: boolean;
957
+ theme?: string;
958
+ }
643
959
  export interface Topic {
644
960
  id: string;
645
961
  owner_id: string;
@@ -654,6 +970,24 @@ export interface Topic {
654
970
  created_at: string;
655
971
  updated_at: string;
656
972
  activity_summary?: TopicActivitySummary;
973
+ /** Server-resolved dream-activity aggregate scoped to viewer's last
974
+ * visit of this topic. Clears when viewer calls topics.markVisit. */
975
+ lifecycle?: TopicLifecycle;
976
+ }
977
+ export interface TopicLifecycle {
978
+ delta_since_visit: TopicDeltaSummary | null;
979
+ }
980
+ /**
981
+ * TopicDeltaSummary — aggregate of dream actions touching this topic
982
+ * since the viewer's last visit. Counts are non-overlapping:
983
+ * - added: new inbound from unassigned (from_topic = null, to_topic = this)
984
+ * - reorganized: inter-topic moves involving this topic
985
+ */
986
+ export interface TopicDeltaSummary {
987
+ since_visit_at: string;
988
+ run_ids: string[];
989
+ added: number;
990
+ reorganized: number;
657
991
  }
658
992
  export interface TopicActivityContributor {
659
993
  user_id: string;
@@ -691,6 +1025,20 @@ export interface TopicUpdateParams {
691
1025
  parent_id?: string | null;
692
1026
  pinned?: boolean;
693
1027
  }
1028
+ /**
1029
+ * TopicUpdateErrorCode enumerates the domain-specific error codes the server
1030
+ * can return from PATCH /v1/topics/{id} when a `parent_id` change is
1031
+ * rejected. The SDK surfaces these as MemaxError.code on a rejected update
1032
+ * so the caller can map them to user-facing toasts.
1033
+ *
1034
+ * Note on `invalid_parent`: the server collapses two cases under this code —
1035
+ * (a) the parent id does not exist, and (b) the parent exists but lives in a
1036
+ * different hub. The client cannot tell them apart without a cross-hub read,
1037
+ * and collapsing avoids leaking hub existence across tenants. If a future
1038
+ * admin-tooling use case needs the split, introduce a separate
1039
+ * `cross_hub_parent` code at that point.
1040
+ */
1041
+ export type TopicUpdateErrorCode = "invalid_parent" | "cycle_detected" | "max_depth_subtree" | "max_depth" | "duplicate_name";
694
1042
  export interface TopicReorderOperation {
695
1043
  topic_id: string;
696
1044
  position: number;
@@ -704,8 +1052,40 @@ export interface TopicMemoriesResponse {
704
1052
  export type DreamRunMode = "maintenance" | "bootstrap";
705
1053
  export type DreamRunStatus = "running" | "completed" | "failed";
706
1054
  export type DreamActionType = "merge" | "contradiction" | "archive" | "organize" | "restructure";
707
- export type ReviewType = "contradiction" | "stale" | "proposal" | "low_confidence";
708
- export type ReviewStatus = "pending" | "resolved" | "dismissed";
1055
+ /**
1056
+ * ReviewTopicRef is the shared topic-pointer shape used by enriched
1057
+ * topic_merge and topic_restructure notification payloads. Mirrors
1058
+ * model.ReviewTopicRef on the server. The "Review" prefix is a
1059
+ * historical holdover from the legacy /v1/reviews surface retired in
1060
+ * Phase 6; the type is still reused verbatim by the notification
1061
+ * payloads for review_topic_merge and review_topic_restructure.
1062
+ */
1063
+ export interface ReviewTopicRef {
1064
+ id: string;
1065
+ name: string;
1066
+ memory_count?: number;
1067
+ }
1068
+ /**
1069
+ * Payload shape for notifications with kind = "review_topic_merge".
1070
+ * The merge resolve action collapses every entry in source_topics into
1071
+ * target_topic via the server's MergeTopics primitive. source_topics
1072
+ * never includes target_topic — the dream restructure writer filters
1073
+ * it out at write time.
1074
+ */
1075
+ export interface ReviewTopicMergePayload {
1076
+ target_topic: ReviewTopicRef;
1077
+ source_topics: ReviewTopicRef[];
1078
+ reason: string;
1079
+ }
1080
+ /**
1081
+ * Payload shape for notifications with kind = "review_topic_restructure".
1082
+ * The apply resolve action reparents child_topic under parent_topic.
1083
+ */
1084
+ export interface ReviewTopicRestructurePayload {
1085
+ parent_topic: ReviewTopicRef;
1086
+ child_topic: ReviewTopicRef;
1087
+ reason: string;
1088
+ }
709
1089
  export interface DreamRun {
710
1090
  id: string;
711
1091
  owner_id?: string;
@@ -756,32 +1136,345 @@ export interface DreamAction {
756
1136
  similarity: number;
757
1137
  created_at: string;
758
1138
  }
1139
+ export interface DreamLatestRunSummary {
1140
+ merged: number;
1141
+ contradictions_found: number;
1142
+ archived: number;
1143
+ organized: number;
1144
+ restructured: number;
1145
+ }
1146
+ export interface DreamPendingReviewSummary {
1147
+ contradictions: number;
1148
+ topic_merges: number;
1149
+ topic_restructures: number;
1150
+ total: number;
1151
+ }
1152
+ export interface DreamIntelligenceSummary {
1153
+ latest_run?: DreamLatestRunSummary;
1154
+ pending_review: DreamPendingReviewSummary;
1155
+ }
759
1156
  export interface DreamReport {
760
1157
  has_run: boolean;
761
1158
  message?: string;
762
1159
  run?: DreamRun;
763
1160
  actions?: DreamAction[];
764
- pending_reviews?: number;
1161
+ intelligence: DreamIntelligenceSummary;
765
1162
  }
766
- export interface Review {
1163
+ /**
1164
+ * NotificationAudience is the routing enum for notifications:
1165
+ *
1166
+ * - `hub` — reserved for future hub-wide announcements
1167
+ * (no producer in Phase 3b)
1168
+ * - `hub_member` — scoped to members of a specific hub; the
1169
+ * default for review notifications
1170
+ * - `user` — addressed to a specific user regardless of
1171
+ * hub membership; used for dream receipts, hub
1172
+ * invites, system notices
1173
+ */
1174
+ export type NotificationAudience = "hub" | "hub_member" | "user";
1175
+ /**
1176
+ * NotificationStatus is the lifecycle state machine. Read state
1177
+ * lives in `seen_at`, not here: a row can be `status="pending"`
1178
+ * with `seen_at` set, meaning "surfaced but not yet acted on".
1179
+ *
1180
+ * Transitions:
1181
+ * - pending → resolved : every /resolve action (including dismiss)
1182
+ * - pending → dismissed : /dismiss on a receipt row only
1183
+ * - pending → expired : nightly sweep on receipts past expires_at
1184
+ */
1185
+ export type NotificationStatus = "pending" | "resolved" | "dismissed" | "expired";
1186
+ /**
1187
+ * NotificationResolution records which /resolve action actually ran
1188
+ * on a decision row. Non-empty only when status=resolved. Mirrors
1189
+ * the server's notification_resolution Postgres enum.
1190
+ */
1191
+ export type NotificationResolution = "kept_a" | "kept_b" | "kept_both" | "merged" | "kept_separate" | "applied" | "kept" | "dismissed" | "accepted" | "declined";
1192
+ /**
1193
+ * NotificationKind is the open set of kinds the inbox framework
1194
+ * will grow over Phase 3–5. Typed as a union rather than a closed
1195
+ * enum so future scaffold kinds don't require a client bump to
1196
+ * decode a response.
1197
+ */
1198
+ export type NotificationKind = "review_contradiction" | "review_topic_merge" | "review_topic_restructure" | "review_stale" | "review_low_confidence" | "dream_run_completed" | "hub_invite" | "hub_invite_accepted" | "hub_invite_declined" | "hub_invite_declined_by_you" | "hub_member_joined" | "hub_ownership_transfer" | "hub_ownership_transferred" | "system_notice" | "gift_invite_link" | (string & {});
1199
+ /**
1200
+ * Notification is the wire shape for a single row returned by
1201
+ * /v1/notifications. Payload shape varies by `kind` — consumers
1202
+ * do a type switch on `kind` before decoding `payload`.
1203
+ */
1204
+ export interface Notification {
767
1205
  id: string;
768
- owner_id: string;
1206
+ audience: NotificationAudience;
1207
+ /** Required when audience in (hub, hub_member). */
769
1208
  hub_id?: string;
770
- review_type: ReviewType;
771
- status: ReviewStatus;
772
- memory_ids: string[];
773
- dream_run_id?: string;
774
- title: string;
775
- description: string;
776
- similarity: number;
777
- resolution?: ReviewResolution;
1209
+ /** Required when audience = user. */
1210
+ recipient_user_id?: string;
1211
+ /** Optional narrowing for hub_member audience. */
1212
+ hub_member_role?: string;
1213
+ kind: NotificationKind;
1214
+ status: NotificationStatus;
1215
+ /** Set only on resolved decision rows. */
1216
+ resolution?: NotificationResolution;
1217
+ priority: number;
1218
+ source_kind: string;
1219
+ source_id?: string;
1220
+ /**
1221
+ * Per-kind payload. Shape varies:
1222
+ * - review_contradiction → ReviewContradictionPayload
1223
+ * - review_topic_merge → ReviewTopicMergePayload
1224
+ * - review_topic_restructure → ReviewTopicRestructurePayload
1225
+ * - dream_run_completed → DreamRunCompletedPayload
1226
+ * - hub_invite → HubInvitePayload
1227
+ * - other kinds → opaque
1228
+ */
1229
+ payload?: Record<string, unknown>;
778
1230
  created_at: string;
779
- memories: Memory[];
1231
+ expires_at?: string;
1232
+ resolved_at?: string;
1233
+ seen_at?: string;
780
1234
  }
781
- export type ReviewResolution = "keep_a" | "keep_b" | "keep_both" | "dismiss";
782
- export interface ReviewResolutionResult {
1235
+ /**
1236
+ * NotificationKindCount is the per-kind slice of the summary shape.
1237
+ * Both fields are always present, even when zero, per plan §4.4.
1238
+ */
1239
+ export interface NotificationKindCount {
1240
+ pending: number;
1241
+ unseen: number;
1242
+ }
1243
+ /**
1244
+ * NotificationSummary is the response shape for
1245
+ * GET /v1/notifications/summary. Plan §4.4 canonical shape. The
1246
+ * badge dot reads `needs_action_pending`; the Updates header reads
1247
+ * `updates_pending`; the unseen emphasis reads `updates_unseen`;
1248
+ * the settings > dreams contradictions counter reads
1249
+ * `by_kind.review_contradiction.pending`. Every supported kind is
1250
+ * pre-populated with zero counts so consumers can iterate
1251
+ * `by_kind[kind]` without null-checking.
1252
+ */
1253
+ export interface NotificationSummary {
1254
+ needs_action_pending: number;
1255
+ updates_pending: number;
1256
+ updates_unseen: number;
1257
+ by_kind: Record<string, NotificationKindCount>;
1258
+ }
1259
+ /**
1260
+ * NotificationListQuery is the query surface for GET /v1/notifications.
1261
+ * All fields optional; defaults match the server behavior:
1262
+ * - status defaults to "pending"
1263
+ * - limit defaults to 50, max 500
1264
+ */
1265
+ export interface NotificationListQuery {
1266
+ hub?: string;
1267
+ status?: NotificationStatus;
1268
+ /** Repeatable. Narrows to one or more kinds. */
1269
+ kind?: NotificationKind[];
1270
+ /** Repeatable. Only meaningful with status=resolved. */
1271
+ resolution?: NotificationResolution[];
1272
+ unseenOnly?: boolean;
1273
+ /** RFC3339 lower bound on created_at. */
1274
+ since?: string;
1275
+ /** 1..500; default 50. */
1276
+ limit?: number;
1277
+ /** Opaque RFC3339 cursor from a previous list response. */
1278
+ cursor?: string;
1279
+ }
1280
+ /**
1281
+ * NotificationListResponse is the paginated list response shape.
1282
+ */
1283
+ export interface NotificationListResponse {
1284
+ notifications: Notification[];
1285
+ next_cursor?: string;
1286
+ has_more: boolean;
1287
+ }
1288
+ /**
1289
+ * NotificationBulkQuery is the body shape for the bulk seen/dismiss
1290
+ * endpoints. Decision kinds are refused with
1291
+ * `400 bulk_not_allowed_for_decision_kind`.
1292
+ */
1293
+ export interface NotificationBulkQuery {
1294
+ hub?: string;
1295
+ kinds: NotificationKind[];
1296
+ /** RFC3339 lower bound on created_at. */
1297
+ since?: string;
1298
+ }
1299
+ export interface NotificationBulkResult {
1300
+ affected: number;
1301
+ }
1302
+ /**
1303
+ * NotificationResolveAction is the closed set of actions the
1304
+ * /v1/notifications/{id}/resolve endpoint accepts. Kept in lockstep
1305
+ * with the per-kind allow-list in the server notifications handler.
1306
+ */
1307
+ export type NotificationResolveAction = "keep_a" | "keep_b" | "keep_both" | "merge" | "keep_separate" | "apply" | "keep" | "accept" | "decline" | "dismiss";
1308
+ export interface NotificationResolveResult {
783
1309
  status: string;
784
1310
  action: string;
1311
+ resolution: string;
1312
+ }
1313
+ /**
1314
+ * ReviewContradictionPayload is the notification payload shape for
1315
+ * kind = "review_contradiction". Carries lightweight memory refs so
1316
+ * the inbox row can render without a /v1/memories round-trip.
1317
+ */
1318
+ export interface ReviewContradictionPayload {
1319
+ memory_a: ReviewMemoryRef;
1320
+ memory_b: ReviewMemoryRef;
1321
+ similarity: number;
1322
+ reason: string;
1323
+ }
1324
+ /**
1325
+ * ReviewMemoryRef is the lightweight memory pointer used by
1326
+ * review notification payloads.
1327
+ */
1328
+ export interface ReviewMemoryRef {
1329
+ id: string;
1330
+ title: string;
1331
+ }
1332
+ /**
1333
+ * DreamRunCompletedPayload is the payload for kind =
1334
+ * "dream_run_completed". Produced at the end of a successful dream
1335
+ * run, including clean runs with zero counts.
1336
+ *
1337
+ * memories_scanned is embedded here (not read from the active hub's
1338
+ * dream report) because dream_run_completed is a user-audience
1339
+ * notification that can render while the user is browsing an
1340
+ * unrelated hub. Clients MUST read the scan count from the payload,
1341
+ * never from the active hub's dreamReport — see the Phase 4 bar-fix
1342
+ * commit for the original cross-hub leak bug.
1343
+ */
1344
+ export interface DreamRunCompletedPayload {
1345
+ run_id: string;
1346
+ mode: string;
1347
+ counts: DreamRunCounts;
1348
+ memories_scanned: number;
1349
+ finished_at: string;
1350
+ report?: string;
1351
+ touched_topic_ids?: string[];
1352
+ }
1353
+ /**
1354
+ * DreamRunCounts is the per-phase outcome counts embedded in a
1355
+ * dream_run_completed payload.
1356
+ */
1357
+ export interface DreamRunCounts {
1358
+ merged: number;
1359
+ archived: number;
1360
+ organized: number;
1361
+ contradictions: number;
1362
+ restructures: number;
1363
+ }
1364
+ /**
1365
+ * HubInvitePayload is the payload for kind = "hub_invite".
1366
+ */
1367
+ export interface HubInvitePayload {
1368
+ hub: HubInviteHubRef;
1369
+ inviter: HubInviteInviterRef;
1370
+ role: string;
1371
+ expires_at: string;
1372
+ }
1373
+ export interface HubInviteHubRef {
1374
+ id: string;
1375
+ name: string;
1376
+ icon?: string;
1377
+ accent?: string;
1378
+ }
1379
+ export interface HubInviteInviterRef {
1380
+ id: string;
1381
+ display?: string;
1382
+ avatar_url?: string;
1383
+ }
1384
+ /**
1385
+ * HubMemberJoinedPayload is the payload for kind = "hub_member_joined".
1386
+ * Fired to the hub owner when a user accepts an invite.
1387
+ */
1388
+ export interface HubMemberJoinedPayload {
1389
+ hub: HubInviteHubRef;
1390
+ member: HubMemberRef;
1391
+ role: string;
1392
+ }
1393
+ export interface HubMemberRef {
1394
+ id: string;
1395
+ display?: string;
1396
+ avatar_url?: string;
1397
+ }
1398
+ /**
1399
+ * HubInviteAcceptedPayload is the payload for kind =
1400
+ * "hub_invite_accepted" — the invitee's self-receipt after a
1401
+ * successful accept. Renders as "You joined {hub}". Fan-out target
1402
+ * is the invitee themself, not the hub owner (the owner's receipt
1403
+ * is `hub_member_joined`). Both receipts exist so each side of the
1404
+ * accept reads their own view of the same event.
1405
+ */
1406
+ export interface HubInviteAcceptedPayload {
1407
+ hub: HubInviteHubRef;
1408
+ role: string;
1409
+ }
1410
+ /**
1411
+ * HubInviteDeclinedPayload is the payload for kind =
1412
+ * "hub_invite_declined" — fan-out to the original inviter (the
1413
+ * admin who created the invite, via `invite.invited_by`), telling
1414
+ * them their invitee declined. Renders as "{invitee} declined
1415
+ * your invite to {hub}".
1416
+ */
1417
+ export interface HubInviteDeclinedPayload {
1418
+ hub: HubInviteHubRef;
1419
+ invitee: HubMemberRef;
1420
+ }
1421
+ /**
1422
+ * HubInviteDeclinedByYouPayload is the payload for kind =
1423
+ * "hub_invite_declined_by_you" — the invitee's self-receipt after
1424
+ * a decline. Renders as "You declined {hub}". Lives in the Updates
1425
+ * bucket so the invitee has a durable self-oriented record of the
1426
+ * decline.
1427
+ */
1428
+ export interface HubInviteDeclinedByYouPayload {
1429
+ hub: HubInviteHubRef;
1430
+ }
1431
+ /**
1432
+ * SystemNoticePayload is the payload for kind = "system_notice".
1433
+ * Used for product announcements and billing notices. Phase 5 ships
1434
+ * the renderer + types only; producers land alongside the individual
1435
+ * features that emit them.
1436
+ */
1437
+ export interface SystemNoticePayload {
1438
+ title: string;
1439
+ body: string;
1440
+ link?: string;
1441
+ link_text?: string;
1442
+ }
1443
+ /**
1444
+ * GiftInviteLinkPayload is the payload for kind = "gift_invite_link".
1445
+ * Phase 5 ships the renderer only; the gift / referral producer lands
1446
+ * alongside the gift feature.
1447
+ */
1448
+ export interface GiftInviteLinkPayload {
1449
+ sender: HubInviteInviterRef;
1450
+ hub?: HubInviteHubRef;
1451
+ token: string;
1452
+ url?: string;
1453
+ expires_at: string;
1454
+ }
1455
+ /**
1456
+ * HubOwnershipTransferPayload is the payload for kind =
1457
+ * "hub_ownership_transfer". Addressed to the transfer target so the
1458
+ * inbox shows a decision row with accept / decline actions. The
1459
+ * source_id on the notification row is the transfer id, so there is
1460
+ * exactly one pending notification per transfer.
1461
+ */
1462
+ export interface HubOwnershipTransferPayload {
1463
+ hub: HubInviteHubRef;
1464
+ initiator: HubMemberRef;
1465
+ role?: string;
1466
+ expires_at: string;
1467
+ }
1468
+ /**
1469
+ * HubOwnershipTransferredPayload is the payload for kind =
1470
+ * "hub_ownership_transferred" — a receipt fired to both sides of an
1471
+ * accepted ownership handoff. Clients should render recipient-aware
1472
+ * copy from the current user id versus `new_owner.id`.
1473
+ */
1474
+ export interface HubOwnershipTransferredPayload {
1475
+ hub: HubInviteHubRef;
1476
+ new_owner: HubMemberRef;
1477
+ old_owner: HubMemberRef;
785
1478
  }
786
1479
  export interface ConnectedAgent {
787
1480
  id: string;
@@ -797,13 +1490,82 @@ export interface ConnectedAgentWithStats extends ConnectedAgent {
797
1490
  key_count: number;
798
1491
  config_count: number;
799
1492
  memory_count: number;
1493
+ needs_reconnect?: boolean;
800
1494
  last_active_at: string | null;
1495
+ last_operation?: string | null;
1496
+ last_activity_summary?: string | null;
1497
+ last_observed_at?: string | null;
801
1498
  }
802
1499
  export interface ConnectedAgentUpdate {
803
1500
  displayName?: string;
804
1501
  icon?: string;
805
1502
  }
1503
+ /**
1504
+ * Skip reasons for `DELETE /v1/auth/api-keys/{id}`.
1505
+ *
1506
+ * - `not_found`: the key id did not match a row the caller owns.
1507
+ * Unknown id, already revoked, or belongs to another user (the
1508
+ * SQL WHERE clause makes these indistinguishable). Client treats
1509
+ * as idempotent success — the user's target state is reached.
1510
+ * - `revoke_failed`: the DELETE returned a store-level error. Server
1511
+ * still has the key; client rolls back the optimistic removal
1512
+ * and surfaces retry copy.
1513
+ */
1514
+ export type ApiKeyRevokeSkipReason = "not_found" | "revoke_failed";
1515
+ export interface ApiKeyRevokeSkippedItem {
1516
+ id: string;
1517
+ reason: ApiKeyRevokeSkipReason;
1518
+ }
1519
+ /**
1520
+ * Structured response from `DELETE /v1/auth/api-keys/{id}`.
1521
+ *
1522
+ * Always 200 — 4xx/5xx are reserved for full-request failures (bad
1523
+ * path, missing auth). Partial-success semantics mirror
1524
+ * `memories.batchDelete` and `configs.batchDelete`: `revoked: false`
1525
+ * with a non-empty `skipped` array is a normal outcome, and clients
1526
+ * branch on the reason to distinguish idempotent success
1527
+ * (`not_found`) from rollback + retry (`revoke_failed`).
1528
+ */
1529
+ export interface ApiKeyRevokeResult {
1530
+ revoked: boolean;
1531
+ skipped: ApiKeyRevokeSkippedItem[];
1532
+ }
1533
+ /**
1534
+ * Skip reasons for `DELETE /v1/agents/{slug}`.
1535
+ *
1536
+ * - `not_found`: `GetConnectedAgent` did not resolve for the caller.
1537
+ * Unknown slug or another user's agent. Client treats this as
1538
+ * idempotent success — the user's target state is reached.
1539
+ * - `cascade_failed`: the atomic delete tx (revoke keys + tombstone
1540
+ * configs + delete agent row) returned an error. Server still has
1541
+ * the agent; client must roll back the optimistic removal and
1542
+ * surface an inline retry hint.
1543
+ */
1544
+ export type AgentDisconnectSkipReason = "not_found" | "cascade_failed";
1545
+ export interface AgentDisconnectSkippedItem {
1546
+ id: string;
1547
+ reason: AgentDisconnectSkipReason;
1548
+ }
1549
+ /**
1550
+ * Structured response from `DELETE /v1/agents/{slug}`.
1551
+ *
1552
+ * Always 200 — 4xx/5xx are reserved for full-request failures (bad
1553
+ * path, auth). Partial-success semantics: `disconnected: false` with a
1554
+ * non-empty `skipped` array is a normal outcome; clients branch on the
1555
+ * reason to choose between silent success (`not_found`) and rollback
1556
+ * + retry (`cascade_failed`).
1557
+ *
1558
+ * `keys_revoked` / `configs_tombstoned` are pre-query counts — they
1559
+ * describe what the cascade is about to clean up, not the exact exec
1560
+ * RowsAffected. This matches the memory-move pattern of reporting the
1561
+ * user-visible outcome rather than raw DB stats, and gives the web
1562
+ * hook enough data to render "Disconnected claude-code — revoked 3
1563
+ * keys, forgot 12 configs" without waiting for a refetch.
1564
+ */
806
1565
  export interface DisconnectAgentResult {
807
1566
  disconnected: boolean;
1567
+ keys_revoked: number;
1568
+ configs_tombstoned: number;
1569
+ skipped: AgentDisconnectSkippedItem[];
808
1570
  }
809
1571
  //# sourceMappingURL=types.d.ts.map