@ego-z/contracts 0.15.10 → 0.15.11

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ego-z/contracts",
3
- "version": "0.15.10",
3
+ "version": "0.15.11",
4
4
  "description": "Wire-format type contracts shared between EgoZ backend, SDK, MCP and console. Type-only — no runtime artifacts.",
5
5
  "types": "./src/index.d.ts",
6
6
  "exports": {
package/src/ask.d.ts CHANGED
@@ -6,7 +6,7 @@
6
6
  */
7
7
 
8
8
  import type { Intent, JsonSchemaDefinition, ResponseFormat, TokenUsage } from './envelope';
9
- import type { InitContextItem, InitContextUi } from './draft-conv';
9
+ import type { InitContextItem, InitContextItemAccepted, InitContextUi } from './draft-conv';
10
10
  import type { AskQuestionSet } from './questions';
11
11
 
12
12
  // ============================================================================
@@ -346,4 +346,23 @@ export interface AskResponseData {
346
346
  */
347
347
  memoryInjected?: boolean;
348
348
  memoryProposed?: boolean;
349
+ /**
350
+ * What EgoZ actually accepted from `AskRequestBody.contextItems` this
351
+ * turn, in the order the agent saw them.
352
+ *
353
+ * Present whenever the request carried `contextItems` — including as an
354
+ * empty array, meaning "you sent a list and nothing in it was accepted".
355
+ *
356
+ * ⚠️ ABSENT MEANS THE REQUEST CARRIED NO `contextItems`. It never means
357
+ * "none were accepted". A consumer that reads absence as rejection
358
+ * reports a failure that did not happen; one that reads an empty array as
359
+ * absence reports a success that did not either.
360
+ *
361
+ * Render this — not the list you sent — anywhere you show the user what
362
+ * was shared with the agent. See `InitContextItemAccepted` for why the
363
+ * two can differ and how to join them.
364
+ *
365
+ * Additive: consumers that ignore it are unaffected.
366
+ */
367
+ contextItemsAccepted?: InitContextItemAccepted[];
349
368
  }
@@ -93,13 +93,74 @@ export interface InitContextItem {
93
93
  label?: string;
94
94
 
95
95
  /**
96
- * A short description of the item. Optional, and truncated rather than
97
- * rejected if long — but keep it to what the thing IS, not its full
98
- * record. Everything here displaces conversation from the context window.
96
+ * A short description of the item. Optional but keep it to what the
97
+ * thing IS, not its full record. Everything here displaces conversation
98
+ * from the context window.
99
+ *
100
+ * ⚠️ AN OVER-LONG EXCERPT IS DROPPED, NOT TRUNCATED, and the item still
101
+ * rides without it. Unlike every other cap here, which truncates or
102
+ * rejects.
103
+ *
104
+ * Because you resolve the item yourself, this is sometimes prose
105
+ * (`"£45, in stock"`) and sometimes an ADDRESS the agent will act on
106
+ * (`"projects/api/deploy.sh"`). Shortening prose loses a few words;
107
+ * shortening an address does not produce an invalid address, it produces
108
+ * a **different valid one**, which the agent then reads and reports on
109
+ * with no error anywhere. Nothing server-side can tell the two apart —
110
+ * `kind` is opaque and never resolved — so one behaviour covers both and
111
+ * it is the safe one.
112
+ *
113
+ * `contextItemsAccepted` on the response tells you when it happened.
99
114
  */
100
115
  excerpt?: string;
101
116
  }
102
117
 
118
+ /**
119
+ * One entry in the response's `contextItemsAccepted` receipt — what EgoZ
120
+ * actually took from a `contextItems` you sent.
121
+ *
122
+ * ── Why a receipt exists at all ──────────────────────────────────────────
123
+ *
124
+ * Acceptance is LOSSY BY DESIGN, in three ways you cannot observe from the
125
+ * caller: an over-long list is truncated from the end, an item with no
126
+ * `label` is dropped individually, and an over-long `excerpt` is dropped
127
+ * while its item rides on. Each is the right behaviour — none of them should
128
+ * fail a user's turn — but each means the list you sent is not necessarily
129
+ * the list the agent saw.
130
+ *
131
+ * So if you display "what was shared with the agent" anywhere, render THIS,
132
+ * not the list you sent. Rendering your own list produces a display that is
133
+ * confident and wrong in exactly the cases that matter.
134
+ *
135
+ * ⚠️ AN ITEM MISSING FROM THE RECEIPT WAS NOT ACCEPTED. Absence is the only
136
+ * channel that reports the list truncation and the labelless drop, so a
137
+ * consumer that treats this as best-effort or partially populated silently
138
+ * goes back to claiming delivery it cannot verify.
139
+ *
140
+ * Match entries to your own items on `kind` + `id`. Do NOT fall back to
141
+ * matching on `label` — labels are deliberately not unique, so that join is
142
+ * usually right, and "usually right" is the failure this field exists to
143
+ * remove. Render an unmatched entry as unmatched instead.
144
+ */
145
+ export interface InitContextItemAccepted {
146
+ /** Echo of the item's `kind`. Still never rendered into the prompt. */
147
+ kind?: string;
148
+ /** Echo of the item's `id`. */
149
+ id?: string;
150
+ /** The label the agent saw. Always present — a labelless item is dropped. */
151
+ label: string;
152
+ /**
153
+ * The item was accepted but its `excerpt` was not — it exceeded the cap
154
+ * and was dropped rather than truncated (see `InitContextItem.excerpt`).
155
+ *
156
+ * Absent means the excerpt survived, or there was never one to carry.
157
+ * Distinguishing those two is not what this flag is for: it exists so a
158
+ * "shared with the agent" display can say the agent got a NAME and no
159
+ * detail, instead of implying it got both.
160
+ */
161
+ excerptOmitted?: boolean;
162
+ }
163
+
103
164
  /** One open window in the caller's UI. */
104
165
  export interface InitContextOpenWindow {
105
166
  /**
package/src/stream.d.ts CHANGED
@@ -13,6 +13,7 @@
13
13
 
14
14
  import type { Intent, TokenUsage } from './envelope';
15
15
  import type { AskQuestionSet } from './questions';
16
+ import type { InitContextItemAccepted } from './draft-conv';
16
17
 
17
18
  /**
18
19
  * Discriminated union of every event the streaming `/ask` endpoint emits.
@@ -352,6 +353,21 @@ export interface AskStreamDoneEvent {
352
353
  */
353
354
  memoryInjected?: boolean;
354
355
  memoryProposed?: boolean;
356
+ /**
357
+ * What EgoZ accepted from this turn's `contextItems`. Same semantics +
358
+ * shape as `AskResponseData.contextItemsAccepted` — surfaced on the
359
+ * terminal event so streaming consumers can render "what was shared"
360
+ * without parsing the final payload separately.
361
+ *
362
+ * On the terminal frame rather than mid-stream for the same reason as
363
+ * `questionSet`: it describes the settled turn, and a consumer would
364
+ * discard every earlier variant anyway.
365
+ *
366
+ * ⚠️ Absent means the request carried no `contextItems` — never that none
367
+ * were accepted. An empty array is the second thing, and they must not be
368
+ * collapsed by anything relaying this frame.
369
+ */
370
+ contextItemsAccepted?: InitContextItemAccepted[];
355
371
  }
356
372
 
357
373
  export interface AskStreamErrorEvent {