@ego-z/contracts 0.14.2 → 0.14.4
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 +1 -1
- package/src/stream.d.ts +31 -2
- package/src/thread.d.ts +27 -0
package/package.json
CHANGED
package/src/stream.d.ts
CHANGED
|
@@ -97,8 +97,37 @@ export interface AskStreamDeltaEvent {
|
|
|
97
97
|
* deltas it produced. **Live mode only** — buffered streams never emit it,
|
|
98
98
|
* so a consumer that does not opt in sees a byte-identical wire.
|
|
99
99
|
*
|
|
100
|
-
*
|
|
101
|
-
*
|
|
100
|
+
* ## Ordering guarantees
|
|
101
|
+
*
|
|
102
|
+
* 1. **Before any `tool.calling` for that iteration** — so a consumer's
|
|
103
|
+
* timeline always settles before the next thing moves.
|
|
104
|
+
* 2. **Before `done`, for every block that produced text.** Structural, not
|
|
105
|
+
* conventional: every `iteration.end` is emitted inside the orchestrator's
|
|
106
|
+
* tool loop, and `done` is emitted only after that loop returns. So a
|
|
107
|
+
* terminal block — which by definition has no following `tool.calling` and
|
|
108
|
+
* is therefore not covered by (1) — is still guaranteed resolved before the
|
|
109
|
+
* stream completes normally.
|
|
110
|
+
*
|
|
111
|
+
* ⚠️ **Neither guarantee covers the `error` path.** A turn that fails
|
|
112
|
+
* mid-iteration terminates with an `error` event, and a block that was
|
|
113
|
+
* streaming `'pending'` at that moment is never resolved.
|
|
114
|
+
*
|
|
115
|
+
* **An unresolved block at `error` is expected, not a defect.** It means
|
|
116
|
+
* what it looks like: the model was mid-thought when the turn died, and
|
|
117
|
+
* nothing — here or downstream — knows which channel that text would have
|
|
118
|
+
* belonged to. Render it as the partial thought it is. Do NOT synthesise a
|
|
119
|
+
* phase for it, and in particular do not "fix" it by promoting it to
|
|
120
|
+
* `'final'` at the error site: that presents a half-finished thought as the
|
|
121
|
+
* answer with the error hidden, which is precisely the failure this channel
|
|
122
|
+
* exists to prevent.
|
|
123
|
+
*
|
|
124
|
+
* The two terminal frames are therefore asymmetric, and anything monitoring
|
|
125
|
+
* the stream should treat them as different signals:
|
|
126
|
+
*
|
|
127
|
+
* - unresolved at `done` → **invariant violation.** (2) says this cannot
|
|
128
|
+
* happen; if it does, the loop was restructured.
|
|
129
|
+
* - unresolved at `error` → **expected.** Tells you how much text was
|
|
130
|
+
* stranded, and nothing more.
|
|
102
131
|
*
|
|
103
132
|
* `phase` is authoritative: it reports whether the orchestrator is actually
|
|
104
133
|
* going on to dispatch tools (`'thinking'`) or this was the terminal answer
|
package/src/thread.d.ts
CHANGED
|
@@ -40,6 +40,26 @@ export type MessageFailureReason =
|
|
|
40
40
|
| 'max_calls_per_turn'
|
|
41
41
|
| 'unrecoverable_error';
|
|
42
42
|
|
|
43
|
+
/**
|
|
44
|
+
* Conversation lifecycle state. Mirrors the CHECK constraint on
|
|
45
|
+
* `egoz_threads.status` (migration 054).
|
|
46
|
+
*
|
|
47
|
+
* - `'draft'` — minted by the ghosted start (`POST /egoz/conversations/draft`)
|
|
48
|
+
* before the user has typed anything. Carries the caller's
|
|
49
|
+
* init context, holds a conversation id the caller can keep,
|
|
50
|
+
* and is swept after the draft TTL if it never promotes.
|
|
51
|
+
* - `'active'` — a real conversation. Every thread created by `/ask` is born
|
|
52
|
+
* active, and a draft becomes active on its first user
|
|
53
|
+
* message. An active thread is never swept.
|
|
54
|
+
*
|
|
55
|
+
* ORTHOGONAL TO `isActive`, which means *archived* and predates this field.
|
|
56
|
+
* A draft is not an archived thread and an archived thread was never a draft;
|
|
57
|
+
* the two were deliberately not collapsed into one boolean, because the
|
|
58
|
+
* draft sweeper's delete predicate would then also match archived user
|
|
59
|
+
* conversations.
|
|
60
|
+
*/
|
|
61
|
+
export type ThreadStatus = 'draft' | 'active';
|
|
62
|
+
|
|
43
63
|
// ============================================================================
|
|
44
64
|
// Supporting shapes
|
|
45
65
|
// ============================================================================
|
|
@@ -89,6 +109,13 @@ export interface ThreadWire {
|
|
|
89
109
|
title: string | null;
|
|
90
110
|
metadata: Record<string, unknown>;
|
|
91
111
|
isActive: boolean;
|
|
112
|
+
/**
|
|
113
|
+
* Conversation lifecycle — `'draft'` (ghosted start, not yet spoken to)
|
|
114
|
+
* or `'active'`. See `ThreadStatus`; distinct from `isActive`, which
|
|
115
|
+
* means archived. Rows created before migration 054 read as `'active'`,
|
|
116
|
+
* which is what they are.
|
|
117
|
+
*/
|
|
118
|
+
status: ThreadStatus;
|
|
92
119
|
/** ISO 8601 timestamp. */
|
|
93
120
|
createdAt: string;
|
|
94
121
|
/** ISO 8601 timestamp. */
|