@ego-z/contracts 0.11.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/LICENSE +201 -0
- package/NOTICE +10 -0
- package/README.md +87 -0
- package/package.json +46 -0
- package/src/api-key.d.ts +155 -0
- package/src/ask.d.ts +244 -0
- package/src/envelope.d.ts +66 -0
- package/src/index.d.ts +94 -0
- package/src/mcp-connection.d.ts +49 -0
- package/src/mcp-token.d.ts +158 -0
- package/src/personality.d.ts +283 -0
- package/src/rag.d.ts +188 -0
- package/src/search.d.ts +23 -0
- package/src/stream.d.ts +202 -0
- package/src/tenant.d.ts +222 -0
- package/src/thread.d.ts +248 -0
- package/src/tool.d.ts +269 -0
- package/src/user-memory.d.ts +226 -0
package/src/tool.d.ts
ADDED
|
@@ -0,0 +1,269 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @ego-z/contracts — `/egoz/tools/*` + `/egoz/mcp-admin/tools/*` wire types.
|
|
3
|
+
*
|
|
4
|
+
* Three independent consumers used to hand-mirror these shapes:
|
|
5
|
+
* - the backend (`modules/tool/interfaces.ts`)
|
|
6
|
+
* - the MCP server (`egoz-mcp/src/backend-client.ts` — `BackendTool`)
|
|
7
|
+
* - the console (`console/src/types/models.ts` — `Tool`)
|
|
8
|
+
* Each drift was one rename away from a silent runtime bug — the same
|
|
9
|
+
* shape of failure that produced the `answer === undefined` regression
|
|
10
|
+
* on `/ask`. Phase 9.1 unifies them under `ToolWire`.
|
|
11
|
+
*
|
|
12
|
+
* **Wire shape vs. backend in-process shape.** Timestamps are typed as
|
|
13
|
+
* `string` here because that's what JSON serialization produces (Fastify
|
|
14
|
+
* calls `Date.prototype.toJSON()` on the way out). The backend's
|
|
15
|
+
* in-process `Tool` type re-exports `ToolWire` and its formatter now
|
|
16
|
+
* emits ISO strings to match — no consumer of `tool.createdAt` in the
|
|
17
|
+
* backend treats it as a `Date`, so there's no plumbing cost.
|
|
18
|
+
*/
|
|
19
|
+
|
|
20
|
+
// ============================================================================
|
|
21
|
+
// Locked vocabularies
|
|
22
|
+
// ============================================================================
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* What kind of upstream API this tool wraps. Locked because the
|
|
26
|
+
* orchestrator branches on it (REST → fetch, GRAPHQL → POST gql_query).
|
|
27
|
+
* Adding a value is a one-edit change across backend + MCP + console
|
|
28
|
+
* because they all reference `ToolType` from this file.
|
|
29
|
+
*/
|
|
30
|
+
export type ToolType = 'REST' | 'GRAPHQL';
|
|
31
|
+
|
|
32
|
+
/** HTTP method for REST tools. Locked — the backend allows only these. */
|
|
33
|
+
export type ToolHttpMethod = 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE';
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* How the tool authenticates upstream.
|
|
37
|
+
* - `'FORWARD'` — EgoZ injects the caller's `authToken` into the
|
|
38
|
+
* outbound request as `Authorization: Bearer …`.
|
|
39
|
+
* - `'NONE'` — no auth header is injected; tool-static `headers`
|
|
40
|
+
* are still applied.
|
|
41
|
+
*/
|
|
42
|
+
export type ToolAuthType = 'FORWARD' | 'NONE';
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* Provenance of the tool definition.
|
|
46
|
+
* - `'manual'` — created in the Console.
|
|
47
|
+
* - `'mcp'` — created via the MCP server (Cursor / 3rd-party MCP
|
|
48
|
+
* client). Mutating an `mcp` tool from the Console
|
|
49
|
+
* requires an explicit override.
|
|
50
|
+
*/
|
|
51
|
+
export type ToolSource = 'manual' | 'mcp';
|
|
52
|
+
|
|
53
|
+
// ============================================================================
|
|
54
|
+
// JSON Schema (recursive, for tool input/output shapes)
|
|
55
|
+
// ============================================================================
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* Recursive JSON Schema fragment used by tool `inputSchema` /
|
|
59
|
+
* `outputSchema`. Distinct from `JsonSchemaDefinition` in `envelope.d.ts`
|
|
60
|
+
* (which is the narrow root-must-be-object shape used for `/ask`'s
|
|
61
|
+
* `responseFormat: 'json_object'`).
|
|
62
|
+
*
|
|
63
|
+
* Intentionally narrow vs. the full JSON Schema 2020-12 surface — only
|
|
64
|
+
* what EgoZ's LLM-side adapter actually consumes. Adding a field here
|
|
65
|
+
* requires updating the adapter in `modules/tool/index.ts` in the
|
|
66
|
+
* same PR.
|
|
67
|
+
*/
|
|
68
|
+
export interface JsonSchemaWire {
|
|
69
|
+
type: string;
|
|
70
|
+
properties?: Record<string, JsonSchemaPropertyWire>;
|
|
71
|
+
required?: string[];
|
|
72
|
+
additionalProperties?: boolean;
|
|
73
|
+
items?: JsonSchemaWire;
|
|
74
|
+
description?: string;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
export interface JsonSchemaPropertyWire {
|
|
78
|
+
type: string;
|
|
79
|
+
description?: string;
|
|
80
|
+
enum?: string[];
|
|
81
|
+
items?: JsonSchemaPropertyWire;
|
|
82
|
+
properties?: Record<string, JsonSchemaPropertyWire>;
|
|
83
|
+
required?: string[];
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
// ============================================================================
|
|
87
|
+
// ToolWire — the canonical row shape
|
|
88
|
+
// ============================================================================
|
|
89
|
+
|
|
90
|
+
/**
|
|
91
|
+
* Wire-format Tool row. Returned by every `/egoz/tools/*` and
|
|
92
|
+
* `/egoz/mcp-admin/tools/*` response that produces a Tool.
|
|
93
|
+
*
|
|
94
|
+
* Backend in-process `Tool` is an alias of this type — including the
|
|
95
|
+
* `tenantId` field, which is on the row even though the API caller
|
|
96
|
+
* never sends it (it's derived from API key / JWT context on the
|
|
97
|
+
* request side, but echoed on responses for audit).
|
|
98
|
+
*/
|
|
99
|
+
export interface ToolWire {
|
|
100
|
+
id: string;
|
|
101
|
+
/**
|
|
102
|
+
* Owning tenant. Present on every response for audit; the request
|
|
103
|
+
* side never carries it (the backend derives tenant from the API
|
|
104
|
+
* key context).
|
|
105
|
+
*/
|
|
106
|
+
tenantId: string;
|
|
107
|
+
toolName: string;
|
|
108
|
+
toolDescription: string;
|
|
109
|
+
apiEndpoint: string;
|
|
110
|
+
toolType: ToolType;
|
|
111
|
+
httpMethod: ToolHttpMethod;
|
|
112
|
+
inputSchema: JsonSchemaWire;
|
|
113
|
+
outputSchema: JsonSchemaWire;
|
|
114
|
+
headers: Record<string, string>;
|
|
115
|
+
authType: ToolAuthType;
|
|
116
|
+
retryAttempts: number;
|
|
117
|
+
retryDelayMs: number;
|
|
118
|
+
enabled: boolean;
|
|
119
|
+
/** GraphQL query/mutation string. Required when `toolType === 'GRAPHQL'`. */
|
|
120
|
+
gqlQuery: string | null;
|
|
121
|
+
/** Example input values for LLM reference. */
|
|
122
|
+
exampleInput: Record<string, unknown> | null;
|
|
123
|
+
/** Example output values for LLM reference. */
|
|
124
|
+
exampleOutput: Record<string, unknown> | null;
|
|
125
|
+
/** Total LLM-initiated invocations (denormalized counter). */
|
|
126
|
+
callCount: number;
|
|
127
|
+
successCount: number;
|
|
128
|
+
failureCount: number;
|
|
129
|
+
/**
|
|
130
|
+
* ISO 8601 timestamp of the most recent invocation. `null` when the
|
|
131
|
+
* tool has never been called. The backend in-process formatter
|
|
132
|
+
* emits ISO strings here so wire and runtime shapes agree.
|
|
133
|
+
*/
|
|
134
|
+
lastCalledAt: string | null;
|
|
135
|
+
source: ToolSource;
|
|
136
|
+
/**
|
|
137
|
+
* Lowercase header-name allowlist. Headers from the inbound `/ask`
|
|
138
|
+
* request whose name matches an entry are forwarded verbatim to
|
|
139
|
+
* the tool endpoint. Empty array (default) = no inbound header is
|
|
140
|
+
* forwarded — preserves the original safe behavior.
|
|
141
|
+
*
|
|
142
|
+
* Forbidden names (`Cookie`, `Host`, `Authorization`, …) are
|
|
143
|
+
* stripped defensively at execution time even if accidentally
|
|
144
|
+
* listed here.
|
|
145
|
+
*/
|
|
146
|
+
forwardHeaders: string[];
|
|
147
|
+
/**
|
|
148
|
+
* Hard cap on how many times this tool may be EXECUTED inside a
|
|
149
|
+
* single `/ask` turn. Dedup cache hits don't count — only real
|
|
150
|
+
* upstream calls. When exceeded, the orchestrator returns a
|
|
151
|
+
* synthetic refusal message to the LLM. Range 1-50, default 5
|
|
152
|
+
* (Phase 5 / Layer 2).
|
|
153
|
+
*/
|
|
154
|
+
maxCallsPerTurn: number;
|
|
155
|
+
/** ISO 8601 timestamp. */
|
|
156
|
+
createdAt: string;
|
|
157
|
+
/** ISO 8601 timestamp. */
|
|
158
|
+
updatedAt: string;
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
// ============================================================================
|
|
162
|
+
// Request bodies (what the client SENDS)
|
|
163
|
+
// ============================================================================
|
|
164
|
+
|
|
165
|
+
/**
|
|
166
|
+
* Wire body of `POST /egoz/tools`. Notable absences:
|
|
167
|
+
* - `tenantId` — derived from API key context / JWT.
|
|
168
|
+
* - `enabled` — new tools are always created `enabled: true`.
|
|
169
|
+
* - counters / `lastCalledAt` — server-managed.
|
|
170
|
+
* - timestamps — server-managed.
|
|
171
|
+
*/
|
|
172
|
+
export interface ToolCreateBody {
|
|
173
|
+
toolName: string;
|
|
174
|
+
toolDescription: string;
|
|
175
|
+
apiEndpoint: string;
|
|
176
|
+
toolType?: ToolType;
|
|
177
|
+
httpMethod?: ToolHttpMethod;
|
|
178
|
+
inputSchema: JsonSchemaWire;
|
|
179
|
+
outputSchema?: JsonSchemaWire;
|
|
180
|
+
headers?: Record<string, string>;
|
|
181
|
+
authType?: ToolAuthType;
|
|
182
|
+
retryAttempts?: number;
|
|
183
|
+
retryDelayMs?: number;
|
|
184
|
+
/** GraphQL query/mutation. Required when `toolType === 'GRAPHQL'`. */
|
|
185
|
+
gqlQuery?: string;
|
|
186
|
+
exampleInput?: Record<string, unknown>;
|
|
187
|
+
exampleOutput?: Record<string, unknown>;
|
|
188
|
+
/** Provenance. Defaults to `'manual'`. */
|
|
189
|
+
source?: ToolSource;
|
|
190
|
+
forwardHeaders?: string[];
|
|
191
|
+
/** Per-turn execution cap (1-50, default 5). */
|
|
192
|
+
maxCallsPerTurn?: number;
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
/**
|
|
196
|
+
* Wire body of `PUT /egoz/tools/:toolId`. Every field is optional —
|
|
197
|
+
* unspecified fields are left untouched (`COALESCE` semantics).
|
|
198
|
+
* `toolId` lives in the URL, not the body; `tenantId` is derived
|
|
199
|
+
* from the auth context.
|
|
200
|
+
*/
|
|
201
|
+
export interface ToolUpdateBody {
|
|
202
|
+
toolName?: string;
|
|
203
|
+
toolDescription?: string;
|
|
204
|
+
apiEndpoint?: string;
|
|
205
|
+
toolType?: ToolType;
|
|
206
|
+
httpMethod?: ToolHttpMethod;
|
|
207
|
+
inputSchema?: JsonSchemaWire;
|
|
208
|
+
outputSchema?: JsonSchemaWire;
|
|
209
|
+
headers?: Record<string, string>;
|
|
210
|
+
authType?: ToolAuthType;
|
|
211
|
+
retryAttempts?: number;
|
|
212
|
+
retryDelayMs?: number;
|
|
213
|
+
enabled?: boolean;
|
|
214
|
+
gqlQuery?: string;
|
|
215
|
+
exampleInput?: Record<string, unknown>;
|
|
216
|
+
exampleOutput?: Record<string, unknown>;
|
|
217
|
+
source?: ToolSource;
|
|
218
|
+
forwardHeaders?: string[];
|
|
219
|
+
maxCallsPerTurn?: number;
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
// ============================================================================
|
|
223
|
+
// Response data shapes (carried inside `EgozApiResponse.data`)
|
|
224
|
+
// ============================================================================
|
|
225
|
+
|
|
226
|
+
export interface ToolListResponseData {
|
|
227
|
+
tools: ToolWire[];
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
export interface ToolGetResponseData {
|
|
231
|
+
tool: ToolWire;
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
// ============================================================================
|
|
235
|
+
// MCP-admin tool preview (`POST /egoz/mcp-admin/tools/:name/preview`)
|
|
236
|
+
// ============================================================================
|
|
237
|
+
|
|
238
|
+
/**
|
|
239
|
+
* Single field diff entry for a tool-upsert preview. `oldValue` is
|
|
240
|
+
* `undefined` on a fresh create.
|
|
241
|
+
*/
|
|
242
|
+
export interface ToolPreviewDiffEntry {
|
|
243
|
+
field: string;
|
|
244
|
+
oldValue: unknown;
|
|
245
|
+
newValue: unknown;
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
/**
|
|
249
|
+
* Response payload of the MCP "preview before upsert" endpoint.
|
|
250
|
+
*
|
|
251
|
+
* - `action` — what an unforced PUT would do.
|
|
252
|
+
* - `requiresForce` — true when overwriting a `'manual'` tool
|
|
253
|
+
* from MCP; the upsert refuses without
|
|
254
|
+
* `force: true`.
|
|
255
|
+
* - `existingSource` — provenance of the row that would be
|
|
256
|
+
* overwritten; null on a fresh create.
|
|
257
|
+
* - `validationErrors` — flat strings; empty array means the body
|
|
258
|
+
* is valid as-is.
|
|
259
|
+
* - `diff` — only the fields that would change.
|
|
260
|
+
*/
|
|
261
|
+
export interface ToolPreview {
|
|
262
|
+
toolName: string;
|
|
263
|
+
action: 'create' | 'update' | 'noop';
|
|
264
|
+
exists: boolean;
|
|
265
|
+
requiresForce: boolean;
|
|
266
|
+
existingSource: ToolSource | null;
|
|
267
|
+
validationErrors: string[];
|
|
268
|
+
diff: ToolPreviewDiffEntry[];
|
|
269
|
+
}
|
|
@@ -0,0 +1,226 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @ego-z/contracts — `/egoz/tenants/:tenantId/learning/*` wire types
|
|
3
|
+
* (Phase 15 / exURM — per-end-user learning).
|
|
4
|
+
*
|
|
5
|
+
* The Console calls this surface **Learning**; the backend domain is
|
|
6
|
+
* `user-memory` (table `egoz_user_memory`). One HYBRID row shape covers both
|
|
7
|
+
* kinds via a `kind` discriminator:
|
|
8
|
+
* - `profile` — a structured attribute (`attrKey` = `content`, e.g.
|
|
9
|
+
* `size` = `38`). Always injected when approved.
|
|
10
|
+
* - `memory` — a free-text snippet (`attrKey` null), embedded server-side
|
|
11
|
+
* and similarity-retrieved. The `embedding` itself NEVER crosses the wire.
|
|
12
|
+
*
|
|
13
|
+
* GOVERNANCE (locked): review-before-use. Rows land `status: 'pending'`; only
|
|
14
|
+
* `'approved'` rows are ever injected into an `/ask` prompt. Opt-in per tenant
|
|
15
|
+
* (`learning_enabled`, default false); no capture under no-store.
|
|
16
|
+
*
|
|
17
|
+
* ── Admin routes (all guarded by tenant-owner auth) ─────────────────────────
|
|
18
|
+
* GET /egoz/tenants/:tenantId/learning/users
|
|
19
|
+
* → LearningUsersResponseData (roster + pending badge total + flag)
|
|
20
|
+
* GET /egoz/tenants/:tenantId/learning/users/:externalUserId?status=
|
|
21
|
+
* → LearningUserFactsResponseData (profile + memories, one flat list)
|
|
22
|
+
* PATCH /egoz/tenants/:tenantId/learning/facts/:factId
|
|
23
|
+
* body UpdateUserMemoryFactBody → UserMemoryFactResponseData
|
|
24
|
+
* POST /egoz/tenants/:tenantId/learning/facts/:factId/approve
|
|
25
|
+
* → UserMemoryFactResponseData
|
|
26
|
+
* POST /egoz/tenants/:tenantId/learning/facts/:factId/reject
|
|
27
|
+
* → UserMemoryFactResponseData
|
|
28
|
+
* DELETE /egoz/tenants/:tenantId/learning/facts/:factId
|
|
29
|
+
* → UserMemoryFactResponseData (the deleted row, for optimistic UI)
|
|
30
|
+
* DELETE /egoz/tenants/:tenantId/learning/users/:externalUserId
|
|
31
|
+
* → ForgetUserResponseData (right-to-be-forgotten)
|
|
32
|
+
* GET /egoz/tenants/:tenantId/learning/analytics
|
|
33
|
+
* → LearningAnalyticsResponseData (per-tenant adoption summary)
|
|
34
|
+
* (the on/off toggle reuses the existing tenant-config update with
|
|
35
|
+
* `learningEnabled` — no dedicated route here.)
|
|
36
|
+
*
|
|
37
|
+
* **Versioning.** Additive new family → minor bump (0.5.3 → 0.6.0).
|
|
38
|
+
*/
|
|
39
|
+
|
|
40
|
+
// ============================================================================
|
|
41
|
+
// Locked vocabularies (mirror DB CHECK constraints — migration 042)
|
|
42
|
+
// ============================================================================
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* Hybrid discriminator (mirrors `egoz_user_memory.kind` CHECK, migration 042).
|
|
46
|
+
* - `profile` — structured attribute, always injected when approved.
|
|
47
|
+
* - `memory` — free-text snippet, embedded + similarity-retrieved.
|
|
48
|
+
* Adding a value requires a migration + this type in lockstep.
|
|
49
|
+
*/
|
|
50
|
+
export type UserMemoryKind = 'profile' | 'memory';
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* Review lifecycle (mirrors `egoz_user_memory.status` CHECK, migration 042).
|
|
54
|
+
* Only `'approved'` is ever read on the `/ask` path.
|
|
55
|
+
*/
|
|
56
|
+
export type UserMemoryStatus = 'pending' | 'approved' | 'rejected';
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* Provenance (mirrors `egoz_user_memory.source` CHECK, migration 042).
|
|
60
|
+
* `'agent_tool'` = proposed by the built-in `remember_fact` tool (MVP; the
|
|
61
|
+
* only source until a manual-add path lands).
|
|
62
|
+
*/
|
|
63
|
+
export type UserMemorySource = 'agent_tool';
|
|
64
|
+
|
|
65
|
+
// ============================================================================
|
|
66
|
+
// UserMemoryWire — the canonical row shape
|
|
67
|
+
// ============================================================================
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* Wire-format learned-fact row. Returned by the learning detail + mutation
|
|
71
|
+
* endpoints. The `embedding` column is intentionally omitted — it never
|
|
72
|
+
* crosses the wire.
|
|
73
|
+
*/
|
|
74
|
+
export interface UserMemoryWire {
|
|
75
|
+
id: string;
|
|
76
|
+
tenantId: string;
|
|
77
|
+
/** The opaque end-user scope key from `/ask` (`externalUserId`). */
|
|
78
|
+
externalUserId: string;
|
|
79
|
+
kind: UserMemoryKind;
|
|
80
|
+
/**
|
|
81
|
+
* The attribute name for `kind: 'profile'` (e.g. `'size'`); `null` for
|
|
82
|
+
* `kind: 'memory'`.
|
|
83
|
+
*/
|
|
84
|
+
attrKey: string | null;
|
|
85
|
+
/** The attribute value (`profile`) or the memory snippet (`memory`). */
|
|
86
|
+
content: string;
|
|
87
|
+
status: UserMemoryStatus;
|
|
88
|
+
source: UserMemorySource;
|
|
89
|
+
/** Thread that produced this fact (audit); `null` when unknown / no-store. */
|
|
90
|
+
originThreadId: string | null;
|
|
91
|
+
/** Message that produced this fact (audit); `null` when unknown / no-store. */
|
|
92
|
+
originMessageId: string | null;
|
|
93
|
+
/** Optional model-reported confidence in `[0, 1]`; `null` when not given. */
|
|
94
|
+
confidence: number | null;
|
|
95
|
+
/** ISO 8601 timestamp. */
|
|
96
|
+
createdAt: string;
|
|
97
|
+
/** ISO 8601 timestamp. */
|
|
98
|
+
updatedAt: string;
|
|
99
|
+
/** ISO 8601 timestamp; `null` until reviewed (approved/rejected/edited). */
|
|
100
|
+
reviewedAt: string | null;
|
|
101
|
+
/** User id who reviewed; `null` while pending. */
|
|
102
|
+
reviewedBy: string | null;
|
|
103
|
+
/**
|
|
104
|
+
* Whether the Presidio pass flagged any PII/PHI in this fact's text at
|
|
105
|
+
* propose time (Phase C). The review UI shows an amber "possible PII" chip
|
|
106
|
+
* when true so the owner scrutinises before approving. Absent/false when
|
|
107
|
+
* none found or Presidio isn't configured. Additive — older consumers ignore it.
|
|
108
|
+
*/
|
|
109
|
+
piiFlagged?: boolean;
|
|
110
|
+
/**
|
|
111
|
+
* The distinct PII/PHI entity TYPES Presidio flagged (e.g. `'PERSON'`,
|
|
112
|
+
* `'EMAIL_ADDRESS'`, `'US_SSN'`), strongest-confidence first. Types only —
|
|
113
|
+
* never the matched text. Empty/absent when `piiFlagged` is false. Shown in
|
|
114
|
+
* the chip's tooltip. Additive.
|
|
115
|
+
*/
|
|
116
|
+
piiEntities?: string[];
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
// ============================================================================
|
|
120
|
+
// Roster summary — one row per external user
|
|
121
|
+
// ============================================================================
|
|
122
|
+
|
|
123
|
+
/**
|
|
124
|
+
* Per-end-user roster entry for the Learning list screen. Aggregated over that
|
|
125
|
+
* user's `egoz_user_memory` rows — no per-fact fetch needed for the table.
|
|
126
|
+
*/
|
|
127
|
+
export interface UserMemoryUserSummaryWire {
|
|
128
|
+
externalUserId: string;
|
|
129
|
+
/** Count of `status: 'approved'` facts (profile + memory). */
|
|
130
|
+
approvedCount: number;
|
|
131
|
+
/** Count of `status: 'pending'` facts — drives the review badge. */
|
|
132
|
+
pendingCount: number;
|
|
133
|
+
/**
|
|
134
|
+
* Most recent learning activity for this user (max `created_at` across
|
|
135
|
+
* their facts), ISO 8601; `null` if somehow empty. Labelled "Last activity"
|
|
136
|
+
* in the UI — it is fact activity, not a true last-seen from threads.
|
|
137
|
+
*/
|
|
138
|
+
lastActivityAt: string | null;
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
// ============================================================================
|
|
142
|
+
// Request bodies (what the client SENDS)
|
|
143
|
+
// ============================================================================
|
|
144
|
+
|
|
145
|
+
/**
|
|
146
|
+
* Body of `PATCH …/learning/facts/:factId`. Owner edits a proposed/approved
|
|
147
|
+
* fact before or after approving it. Both fields optional (partial update);
|
|
148
|
+
* `attrKey` only meaningful for `kind: 'profile'`.
|
|
149
|
+
*/
|
|
150
|
+
export interface UpdateUserMemoryFactBody {
|
|
151
|
+
content?: string;
|
|
152
|
+
attrKey?: string | null;
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
// ============================================================================
|
|
156
|
+
// Response data shapes (carried inside `EgozApiResponse.data`)
|
|
157
|
+
// ============================================================================
|
|
158
|
+
|
|
159
|
+
/**
|
|
160
|
+
* `GET …/learning/users`. The roster plus the flag state (so the list screen
|
|
161
|
+
* can render the on/off Switch without a second call) and the tenant-wide
|
|
162
|
+
* pending total for the sidebar badge.
|
|
163
|
+
*/
|
|
164
|
+
export interface LearningUsersResponseData {
|
|
165
|
+
/** Current per-tenant opt-in state (`egoz_tenant_configs.learning_enabled`). */
|
|
166
|
+
learningEnabled: boolean;
|
|
167
|
+
/** Sum of `pendingCount` across all users — the sidebar/nav badge. */
|
|
168
|
+
totalPending: number;
|
|
169
|
+
users: UserMemoryUserSummaryWire[];
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
/**
|
|
173
|
+
* `GET …/learning/users/:externalUserId`. All of the user's facts as one flat
|
|
174
|
+
* list — partition client-side: review queue = `status === 'pending'`;
|
|
175
|
+
* approved profile = `kind === 'profile' && status === 'approved'`; approved
|
|
176
|
+
* memories = `kind === 'memory' && status === 'approved'`. When the request
|
|
177
|
+
* carried `?status=`, `facts` is pre-filtered to that status.
|
|
178
|
+
*/
|
|
179
|
+
export interface LearningUserFactsResponseData {
|
|
180
|
+
externalUserId: string;
|
|
181
|
+
facts: UserMemoryWire[];
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
/**
|
|
185
|
+
* Returned by every single-fact mutation (`PATCH`, `approve`, `reject`,
|
|
186
|
+
* `DELETE …/facts/:factId`) — the affected row for optimistic UI reconciliation.
|
|
187
|
+
* On delete this is the row as it was just before removal.
|
|
188
|
+
*/
|
|
189
|
+
export interface UserMemoryFactResponseData {
|
|
190
|
+
fact: UserMemoryWire;
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
/**
|
|
194
|
+
* `DELETE …/learning/users/:externalUserId` (right-to-be-forgotten). Reports
|
|
195
|
+
* how many facts were purged so the UI can confirm.
|
|
196
|
+
*/
|
|
197
|
+
export interface ForgetUserResponseData {
|
|
198
|
+
externalUserId: string;
|
|
199
|
+
deletedCount: number;
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
/**
|
|
203
|
+
* `GET …/learning/analytics` (Phase C). Per-tenant learning adoption summary —
|
|
204
|
+
* single-query aggregates over `egoz_user_memory`, scoped to the tenant. Powers
|
|
205
|
+
* the Console analytics stat tiles.
|
|
206
|
+
*/
|
|
207
|
+
export interface LearningAnalyticsResponseData {
|
|
208
|
+
/** Current per-tenant opt-in state (`egoz_tenant_configs.learning_enabled`). */
|
|
209
|
+
learningEnabled: boolean;
|
|
210
|
+
/** Distinct external users that have ≥1 learned fact. */
|
|
211
|
+
totalUsers: number;
|
|
212
|
+
/** Fact counts by review status. */
|
|
213
|
+
facts: {
|
|
214
|
+
total: number;
|
|
215
|
+
pending: number;
|
|
216
|
+
approved: number;
|
|
217
|
+
rejected: number;
|
|
218
|
+
};
|
|
219
|
+
/** Fact counts by kind (profile vs semantic memory). */
|
|
220
|
+
byKind: {
|
|
221
|
+
profile: number;
|
|
222
|
+
memory: number;
|
|
223
|
+
};
|
|
224
|
+
/** Facts whose text the Presidio pass flagged for possible PII/PHI. */
|
|
225
|
+
piiFlaggedCount: number;
|
|
226
|
+
}
|