@ego-z/contracts 0.15.5 → 0.15.7

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/README.md CHANGED
@@ -58,6 +58,30 @@ import type { AskRequestBody, AskResponseData, AskStreamEvent } from '@ego-z/con
58
58
  their generated `.d.ts` automatically — end users see the types as if
59
59
  they were declared in the SDK itself.
60
60
 
61
+ ## ⚠️ Do not pin `0.15.5`
62
+
63
+ `0.15.5` was published with a `dependencies` entry naming **itself**
64
+ (`"@ego-z/contracts": "^0.15.0"`). It is harmless while 0.15.5 is the newest
65
+ 0.15.x — npm resolves that range back to the same copy and dedupes it:
66
+
67
+ ```
68
+ `-- @ego-z/contracts@0.15.5
69
+ `-- @ego-z/contracts@0.15.5 deduped
70
+ ```
71
+
72
+ **It stops being harmless the moment a newer 0.15.x exists.** That range can
73
+ then resolve a *different* version nested underneath 0.15.5, putting two
74
+ copies of the same types in one tree — the classic "these two identical
75
+ interfaces are not assignable" failure, from a cause nobody would think to
76
+ look for.
77
+
78
+ So: **when the next patch ships, move off 0.15.5 rather than staying on it.**
79
+ Don't pin it, and don't leave a lockfile resolving to it.
80
+
81
+ The source is already fixed — the package declares no runtime dependencies at
82
+ all — so the next publish for any reason clears it. It was not worth a
83
+ version bump on its own mid-integration.
84
+
61
85
  ## When to bump
62
86
 
63
87
  - **Adding** an optional field — non-breaking, no version bump required
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ego-z/contracts",
3
- "version": "0.15.5",
3
+ "version": "0.15.7",
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": {
@@ -44,8 +44,5 @@
44
44
  },
45
45
  "devDependencies": {
46
46
  "typescript": "^5.0.0"
47
- },
48
- "dependencies": {
49
- "@ego-z/contracts": "^0.15.0"
50
47
  }
51
48
  }
package/src/ask.d.ts CHANGED
@@ -6,6 +6,7 @@
6
6
  */
7
7
 
8
8
  import type { Intent, JsonSchemaDefinition, ResponseFormat, TokenUsage } from './envelope';
9
+ import type { InitContextUi } from './draft-conv';
9
10
 
10
11
  // ============================================================================
11
12
  // /ask — request
@@ -158,6 +159,36 @@ export interface AskRequestBody {
158
159
  * 4. `Authorization` injected by `authType: 'FORWARD'`
159
160
  */
160
161
  toolHeaders?: Record<string, string>;
162
+
163
+ /**
164
+ * What the user has on screen RIGHT NOW — sent on every turn, not just
165
+ * when the conversation started.
166
+ *
167
+ * ── Why per-turn ─────────────────────────────────────────────────────
168
+ *
169
+ * `POST /conversations/draft` captures an `initContext` once, when the
170
+ * chat panel opens. That snapshot is frozen for the life of the
171
+ * conversation, so a window the user opens mid-chat is invisible to the
172
+ * agent by construction — "do that one as well" has no referent to
173
+ * resolve, and it reads as the model being obtuse when in fact it was
174
+ * never told.
175
+ *
176
+ * Send the CURRENT snapshot here and EgoZ works out what changed since
177
+ * the user's previous message. Deixis — "as well", "this one too", "the
178
+ * other one", "go back to the first" — then resolves from ordering and
179
+ * recency, with no phrase anyone has to enumerate.
180
+ *
181
+ * ── Send the full snapshot, never a delta ────────────────────────────
182
+ *
183
+ * Do not compute "what's new" client-side. A client delta needs a
184
+ * client-held baseline, and that baseline is wrong after a reload, a
185
+ * retry, or a reconnect. EgoZ holds the previous turn, so it can diff
186
+ * reliably; the client's job is only to report what it sees.
187
+ *
188
+ * Optional and additive: omit it and behaviour is exactly as before,
189
+ * with the stored `initContext` used for the whole conversation.
190
+ */
191
+ ui?: InitContextUi;
161
192
  }
162
193
 
163
194
  /**
@@ -60,7 +60,34 @@ export type InitContextAudience = 'operator' | 'customer';
60
60
 
61
61
  /** One open window in the caller's UI. */
62
62
  export interface InitContextOpenWindow {
63
- /** Epoch millis the window was opened. */
63
+ /**
64
+ * Epoch millis this window was FIRST SEEN by the client, on the CLIENT'S
65
+ * clock. Not when it was opened — most window systems have no true open
66
+ * time, and this is the honest name for what is actually knowable.
67
+ *
68
+ * ⚠️ Valid ONLY for ordering windows against each other **within a single
69
+ * snapshot**, where the values share one clock and one instant.
70
+ *
71
+ * It is NOT valid across snapshots and NOT valid against server time:
72
+ * - It is a browser clock. Comparing it to a server timestamp compares
73
+ * two clocks, so a client a few minutes off gets a silently wrong
74
+ * answer that differs per end user.
75
+ * - It is memory-only and RESETS ON PAGE RELOAD. After a refresh every
76
+ * open window carries the moment of boot, so a "what's new" rule
77
+ * built on it doesn't weaken — it inverts, and the window the user
78
+ * has been discussing since turn one becomes the newest.
79
+ *
80
+ * To detect what changed between turns, diff window IDS instead. That
81
+ * asks only "was this seen before", which no clock can corrupt.
82
+ */
83
+ firstSeenAt?: number;
84
+
85
+ /**
86
+ * @deprecated Use `firstSeenAt`. Same value, honest name — this one
87
+ * asserts an open time that the client cannot know, and that reading
88
+ * caused a real design error. Emitted alongside `firstSeenAt` for one
89
+ * minor; readers should prefer `firstSeenAt` and fall back to this.
90
+ */
64
91
  openedAt?: number;
65
92
  /**
66
93
  * Human-readable window label, e.g. `"Blue Hoodie"`. Safe to render