@hasna-internal/kai-session 0.1.1-rc.2

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.
@@ -0,0 +1,458 @@
1
+ import type { Branded } from '@hasna-internal/kai-brand';
2
+ import type { AssistantMessage, CallId, LlmCallConfig, LlmCallConfigAdapterDefaults, LlmFailure, StreamChunk, TokenUsage, ToolResultMessage, ToolSchema, UserMessage } from '@hasna-internal/kai-llm';
3
+ import type { JsonValue } from './json.ts';
4
+ export type { JsonValue } from './json.ts';
5
+ /** Identifies one session in the store (and its persistence artifacts). */
6
+ export type SessionId = Branded<'SessionId'>;
7
+ /**
8
+ * Brand a string as a {@link SessionId}.
9
+ * @param id - the raw session id string.
10
+ * @returns the same string, branded (a compile-time cast — no runtime cost).
11
+ */
12
+ export declare function SessionId(id: string): SessionId;
13
+ /**
14
+ * The on-disk session format version, stamped into every newly-written {@link SessionHeader}
15
+ * and enforced by every persistence backend on load. The single source of truth for the
16
+ * version — write sites and the load-time check all read it.
17
+ * While the harness is unreleased it is pinned at `0`: no compatibility is
18
+ * implied, incompatible logs are rejected, and no migration is provided.
19
+ *
20
+ * The version is a single monotonic integer with no major/minor split. Whether
21
+ * a bump is needed is decided by what the WRITER emits, never by what a newer
22
+ * reader can accept: bump exactly when an older runtime could no longer handle
23
+ * a new log with full semantic correctness ("parses without error" is not
24
+ * correctness — silently skipping content that shapes reconstruction is a
25
+ * wrong read). Only structural changes reach that bar: the header shape, the
26
+ * {@link SessionEvent} envelope, core event semantics, or the surface
27
+ * mechanism (the {@link SurfaceEventType} set and {@link SurfaceOp} variants).
28
+ * Adding an ordinary event type does not bump — the per-event
29
+ * {@link SessionEvent.ignorable} guard covers vocabulary growth instead. When
30
+ * in doubt, bump: a near-identity upgrade step is almost free, a missed bump
31
+ * makes older runtimes read new logs wrong silently. The full mechanism
32
+ * (upgrade-step chain, in-memory view conversion, migrate-on-continue) is
33
+ * recorded in the session-log-version-mechanism Agent Note
34
+ * (`.agents/notes/implemented/architecture/2026-08-10-session-log-version-mechanism.md`).
35
+ */
36
+ export declare const SESSION_FORMAT_VERSION = 0;
37
+ /**
38
+ * Immutable validated storage metadata, kept outside the conversation event log.
39
+ */
40
+ export interface SessionHeader {
41
+ /**
42
+ * On-disk format version, stamped from {@link SESSION_FORMAT_VERSION} when the
43
+ * session is created. A persistence backend rejects any other version on load
44
+ * (no migration — see the constant).
45
+ */
46
+ readonly version: number;
47
+ /** The session's id (mirrors the {@link Session}'s id). */
48
+ readonly id: SessionId;
49
+ /** Non-negative safe-integer Unix epoch milliseconds when the session was created. */
50
+ readonly createdAt: number;
51
+ /** Absolute working directory the session was created in (if any). */
52
+ readonly cwd?: string;
53
+ /** The session this one was forked from (seed lineage), if any. */
54
+ readonly parentSession?: SessionId;
55
+ /**
56
+ * How many leading events were inherited through a seed. Persisting this
57
+ * boundary lets resume and replay distinguish parent history from child work.
58
+ */
59
+ readonly seedLength?: number;
60
+ /**
61
+ * Coarse product classification for a session created as a subagent child.
62
+ * This is presentation metadata, not proof that the child is continuable.
63
+ */
64
+ readonly origin?: 'subagent';
65
+ /**
66
+ * Delegation depth: absent (zero) for a top-level session, parent depth + 1
67
+ * for a subagent child. Persisted so a recursion budget survives restart and
68
+ * resume — a runtime-only depth would reset a resumed child to top-level.
69
+ */
70
+ readonly delegationDepth?: number;
71
+ /**
72
+ * Id of the agent preset this session's agent was composed from, when the
73
+ * deployment composes per session. Durable because the preset decides the
74
+ * session's tools and prompt: a resume that restored a different composition
75
+ * would replay history the model can no longer act on.
76
+ */
77
+ readonly agentPreset?: string;
78
+ }
79
+ /**
80
+ * Options for creating a {@link Session} via the store. `seed` replays/forks
81
+ * an existing event log; `meta` carries the caller-supplied storage fields the
82
+ * store folds into a {@link SessionHeader}.
83
+ */
84
+ export interface CreateSessionOptions {
85
+ /** Initial replay or fork history supplied at construction. */
86
+ readonly seed?: readonly SessionEvent[];
87
+ /**
88
+ * Storage metadata read once before publication. `seedLength` is explicit
89
+ * because a resumed seed contains the full stored log, not only its inherited prefix.
90
+ */
91
+ readonly meta?: {
92
+ readonly cwd?: string;
93
+ readonly parentSession?: SessionId;
94
+ readonly createdAt?: number;
95
+ readonly seedLength?: number;
96
+ readonly origin?: 'subagent';
97
+ readonly delegationDepth?: number;
98
+ readonly agentPreset?: string;
99
+ };
100
+ }
101
+ /**
102
+ * Fresh storage values transferred to {@link SessionStore.prepare} without a
103
+ * second serialization copy. Callers retain no mutable aliases.
104
+ */
105
+ export interface RestoredSessionOptions {
106
+ /** Fresh detached storage events to validate and freeze in place. */
107
+ readonly seed: SessionEvent[];
108
+ /** Fresh detached storage metadata to validate and freeze in place. */
109
+ readonly meta: SessionHeader;
110
+ /** Select the persistence ownership-transfer path. */
111
+ readonly seedSource: 'persistence';
112
+ }
113
+ /** Inputs accepted while constructing an unpublished Session. */
114
+ export type PrepareSessionOptions = (CreateSessionOptions & {
115
+ readonly seedSource?: undefined;
116
+ }) | RestoredSessionOptions;
117
+ /** Why an active agent driver was cancelled. */
118
+ export type AgentCancelCause = {
119
+ readonly kind: 'user';
120
+ } | {
121
+ readonly kind: 'parent';
122
+ } | {
123
+ readonly kind: 'hook';
124
+ readonly reason: string;
125
+ } | {
126
+ readonly kind: 'disposed';
127
+ };
128
+ /** Durable cancellation cause, including imports whose original coarse record carried no cause. */
129
+ export type TurnEndCancelCause = AgentCancelCause | {
130
+ readonly kind: 'legacy';
131
+ };
132
+ /**
133
+ * Why a turn ended. Merge-extensible sum type.
134
+ */
135
+ export interface TurnEndReasonMap {
136
+ completed: {
137
+ kind: 'completed';
138
+ };
139
+ /** A cancellation request interrupted the live turn. */
140
+ aborted: {
141
+ kind: 'aborted';
142
+ reason: TurnEndCancelCause;
143
+ };
144
+ blocked: {
145
+ kind: 'blocked';
146
+ };
147
+ /**
148
+ * The turn failed. `error` is always a structured failure: the `LlmError`
149
+ * facts verbatim, or `{ message: errorChain(error), code: 'UNKNOWN' }`
150
+ * flattened from any other error.
151
+ */
152
+ error: {
153
+ kind: 'error';
154
+ error: LlmFailure;
155
+ };
156
+ /** At least one step reached its output-token ceiling, even if a plugin continued the turn. */
157
+ 'max-tokens': {
158
+ kind: 'max-tokens';
159
+ };
160
+ /**
161
+ * A persistence backend closed a crash-orphaned turn on reload. The loop never
162
+ * emits this marker, and the events recorded before the crash remain intact.
163
+ */
164
+ interrupted: {
165
+ kind: 'interrupted';
166
+ };
167
+ }
168
+ /** The union over {@link TurnEndReasonMap} — why a turn ended; plugins extend it by merging variants into the map. */
169
+ export type TurnEndReason = TurnEndReasonMap[keyof TurnEndReasonMap];
170
+ /**
171
+ * One entry in an agent's todo list — the unit of the `todo/write`
172
+ * {@link SessionEventMap} event's whole-list snapshot.
173
+ *
174
+ * Deliberately minimal: a human-readable `content` line and a three-state
175
+ * `status`. No id, priority, or `activeForm` — the list is replaced wholesale
176
+ * on every write (last-write-wins), so entries need no stable identity. The
177
+ * three statuses describe the complete portable lifecycle needed by model and
178
+ * UI consumers.
179
+ */
180
+ export interface TodoItem {
181
+ /** What this task is — a short imperative line shown in the UI. */
182
+ content: string;
183
+ /** Lifecycle state. `in_progress` marks a task being worked now; parallel work may mark several. */
184
+ status: 'pending' | 'in_progress' | 'completed';
185
+ }
186
+ /**
187
+ * Logged request state outside derived history: call config, system prompt, and
188
+ * tools. The latest full `request/header` snapshot reconstructs it; canonical
189
+ * empty optional fields are absent.
190
+ */
191
+ export interface EpochHeader {
192
+ /** The conversation's call configuration (provider, model, reasoning effort, and sampling scalars). */
193
+ config: LlmCallConfig;
194
+ /** Effective config fields materialized from the exact adapter rather than proposed by a caller. */
195
+ adapterDefaults?: LlmCallConfigAdapterDefaults;
196
+ /** Rendered system prompt text; absent for a system-less request. */
197
+ system?: string;
198
+ /** Assembled tool schemas; absent for a tool-less request. */
199
+ tools?: ToolSchema[];
200
+ }
201
+ /** Registration-bound metadata for one resolved model route. */
202
+ export interface RequestContext {
203
+ /** Registered provider route the metadata belongs to. */
204
+ provider: string;
205
+ /** Provider-owned model id the metadata belongs to. */
206
+ model: string;
207
+ /** Maximum combined request and response context in tokens, when advertised. */
208
+ contextWindow?: number;
209
+ }
210
+ /**
211
+ * Why a `request/header` snapshot was appended: `'initial'` — the log's first
212
+ * header (a new conversation); `'resume'` — a loop instance's first request
213
+ * over a log that already has header events (process restart, fork seed);
214
+ * `'change'` — a later request used a different header.
215
+ */
216
+ export type RequestHeaderReason = 'initial' | 'resume' | 'change';
217
+ /**
218
+ * The merge-extensible, append-only source of truth for an agent interaction.
219
+ * Message history is derived from this log. Every event is lossless JSON and
220
+ * sequence numbers stay contiguous, including raw chunks, so persistence can
221
+ * store the canonical log verbatim.
222
+ */
223
+ export interface SessionEventMap {
224
+ /**
225
+ * Opens turn `turn` before the loop claims queued input or runs pre-step.
226
+ * Rejection, empty input, cancellation, or failure may close it with no
227
+ * step; otherwise the following identified `user/message` event or batch
228
+ * records the messages entering the step.
229
+ */
230
+ 'turn/start': {
231
+ turn: number;
232
+ };
233
+ /**
234
+ * Closes turn `turn` with the {@link TurnEndReason} that ended it. A turn
235
+ * with no entered step has no `step/start` or `step/end`. The loop does not await a
236
+ * flush at turn boundaries: `dsh-session-checkpoint-policy` owns the
237
+ * per-request durability checkpoint, and consumers that read storage after
238
+ * `whenIdle()` flush themselves. Success commits the turn; rejection is
239
+ * reported live and does not prevent later work.
240
+ */
241
+ 'turn/end': {
242
+ turn: number;
243
+ reason: TurnEndReason;
244
+ };
245
+ /** Opens step `step` of turn `turn` — one model call plus the tool executions it requested. */
246
+ 'step/start': {
247
+ turn: number;
248
+ step: number;
249
+ };
250
+ /** Closes step `step` of turn `turn`. */
251
+ 'step/end': {
252
+ turn: number;
253
+ step: number;
254
+ };
255
+ /**
256
+ * A user-role message on the model-visible surface: a direct human prompt
257
+ * (the queued message claimed for this turn), a synthetic `agent.inject()`
258
+ * context (file-change notices, subdir AGENTS.md, skill content, cron
259
+ * notifications, …), or an entered goal continuation round. All three
260
+ * project their `content` verbatim; `source` tells them apart.
261
+ */
262
+ 'user/message': UserMessage;
263
+ /** Raw stream chunk — token-level replay fidelity. */
264
+ 'assistant/chunk': {
265
+ turn: number;
266
+ step: number;
267
+ chunk: StreamChunk;
268
+ };
269
+ /**
270
+ * Assembled assistant message for one step (derived history uses this).
271
+ * Carries the step's `usage` when the adapter reported token accounting, so
272
+ * the model output and its accounting travel together (there is no separate
273
+ * usage record). `usage` is absent when the adapter reported none. A turn
274
+ * cancelled mid-stream finalizes its delivered text/reasoning prefix as this
275
+ * event with `interrupted: true`; undispatched tool calls are absent. The
276
+ * marker distinguishes that prefix without re-deriving interruption from turn
277
+ * boundaries. An aborted turn with no such event streamed no visible content.
278
+ */
279
+ 'assistant/message': {
280
+ turn: number;
281
+ step: number;
282
+ message: AssistantMessage;
283
+ usage?: TokenUsage;
284
+ interrupted?: true;
285
+ };
286
+ /**
287
+ * The model requested one tool invocation: `name` with the raw `arguments`
288
+ * JSON string exactly as the model produced it (unparsed). `callId` pairs the
289
+ * call with its `tool/result`.
290
+ */
291
+ 'tool/call': {
292
+ turn: number;
293
+ step: number;
294
+ callId: CallId;
295
+ name: string;
296
+ arguments: string;
297
+ };
298
+ /**
299
+ * A completed tool call's model-facing result, optional internal failure
300
+ * identity, and optional tool-private `meta` presentation payload. `meta` is
301
+ * opaque to the core (the producing tool owns its shape and reads it back in
302
+ * `presentResult`) but MUST be JSON-serializable: `Session.append`
303
+ * runtime-validates all event data with `isJsonValue`, so a non-serializable
304
+ * `meta` is rejected at the source, and the durable log reproduces the
305
+ * identical card on replay. Absent
306
+ * unless the tool attaches one (e.g. `dsh-tool-fs` carries its result-time
307
+ * contextual diff here).
308
+ */
309
+ 'tool/result': {
310
+ turn: number;
311
+ step: number;
312
+ message: ToolResultMessage;
313
+ error?: {
314
+ name: string;
315
+ code: string;
316
+ };
317
+ meta?: JsonValue;
318
+ };
319
+ /** Whole-list snapshot; latest write wins on replay. Log-only UI state; never derived history. */
320
+ 'todo/write': {
321
+ todos: TodoItem[];
322
+ };
323
+ /**
324
+ * Full header for the next request, appended inside its step before dispatch.
325
+ * It is log-only; the latest snapshot reconstructs the request header.
326
+ */
327
+ 'request/header': {
328
+ header: EpochHeader;
329
+ reason: RequestHeaderReason;
330
+ };
331
+ /**
332
+ * Route metadata for the next request, logged only when the route or capacity
333
+ * changes. It does not participate in request reconstruction or header equality.
334
+ */
335
+ 'request/context': RequestContext;
336
+ /**
337
+ * Marks the end of a constructor seed. Events before it have smaller seq
338
+ * values and came from the seed (resume, fork, or replay); this lifecycle
339
+ * produced none of them. This log-only event is the durable projection of
340
+ * {@link Session.firstLiveSeq}. Its payload is empty — position and `time`
341
+ * carry the meaning.
342
+ *
343
+ * Locate the LAST one in stored history. A seed already ending in one is not
344
+ * re-marked, so reopening an untouched session does not grow its log per
345
+ * pickup and the event need not be at the current `firstLiveSeq`.
346
+ *
347
+ * `Session`'s constructor is the only legitimate writer. The invariant
348
+ * companion deliberately constrains nothing here, so a plugin appending one
349
+ * would silently classify every live bracket before it as seed history.
350
+ *
351
+ * An owner of a standalone open/close bracket (`compaction/start` …
352
+ * `compaction/end`) reads it because seed history and live work are otherwise
353
+ * byte-identical: an unmatched opening marker before this event belongs to
354
+ * an ended lifecycle, whatever ended it. NOT a liveness signal about other
355
+ * writers — a concurrently live session holds its own boundary elsewhere,
356
+ * so tolerating concurrent writers needs a signal beyond the log.
357
+ */
358
+ 'session/end-seed': Record<string, never>;
359
+ }
360
+ /** The appendable event-type keys of {@link SessionEventMap}, plugin-merged extensions included. */
361
+ export type SessionEventType = keyof SessionEventMap;
362
+ /**
363
+ * The subset of {@link SessionEventType} values whose events produce LLM
364
+ * messages and are eligible to appear on the ordered surface. Only these
365
+ * event types may carry {@link SurfaceOp} and {@link SessionEvent.sourceEventSeqs}.
366
+ */
367
+ export type SurfaceEventType = 'user/message' | 'assistant/message' | 'tool/result';
368
+ /**
369
+ * A {@link SessionEvent} that is **on** the ordered surface — its
370
+ * `surfaceOp` is guaranteed present (mandatory), narrowed from a
371
+ * surface-eligible {@link SessionEvent} by checking both `type` and
372
+ * `surfaceOp` at runtime.
373
+ *
374
+ * Use the `isSurfaceEvent` type guard (in `surface.ts`) to narrow a
375
+ * `SessionEvent` to this type.
376
+ */
377
+ export type SurfaceEvent = SessionEvent<SurfaceEventType> & {
378
+ surfaceOp: SurfaceOp;
379
+ };
380
+ /**
381
+ * How a session event entered the ordered surface. Only valid on
382
+ * {@link SurfaceEventType} events.
383
+ *
384
+ * - `'append'`: added to the tail — normal path for user/assistant/tool
385
+ * messages.
386
+ * - `{ op: 'replace', start, end }`: replaces surface nodes from `start`
387
+ * (inclusive) through `end` (inclusive) with this node. Both must exist as
388
+ * surface nodes in the current surface. `start === end` replaces a single
389
+ * node. The node's {@link SessionEvent.sourceEventSeqs} must include every
390
+ * shadowed surface node. Used by compaction; any surface-replacing producer
391
+ * may use it.
392
+ */
393
+ export type SurfaceOp = 'append' | {
394
+ op: 'replace';
395
+ start: number;
396
+ end: number;
397
+ };
398
+ /**
399
+ * Surface placement and cited source-event seqs for {@link Session.append}. Required on
400
+ * message-producing events and forbidden on log-only events.
401
+ */
402
+ export interface SurfaceIntent {
403
+ surfaceOp: SurfaceOp;
404
+ /**
405
+ * Complete set of known source-event seqs. `assistant/message` may use a
406
+ * present empty array for a known empty provider stream; when the field is
407
+ * absent, the event does not record which earlier events produced the message.
408
+ * Other surface events require a non-empty set when this field is present.
409
+ */
410
+ sourceEventSeqs?: number[];
411
+ }
412
+ /**
413
+ * One immutable entry in the session log.
414
+ *
415
+ * A proper discriminated union over `type` (not independent `type`/`data`
416
+ * unions), so `switch (event.type)` narrows `event.data` without casts.
417
+ *
418
+ * The {@link sourceEventSeqs} and {@link surfaceOp} fields are conditional:
419
+ * they only exist on {@link SurfaceEventType} variants (`user/message`,
420
+ * `assistant/message`, `tool/result`).
421
+ * Non-surface events (boundary markers, chunks, usage, errors) never carry
422
+ * surface metadata — the compiler enforces this at `Session.append()`
423
+ * call sites.
424
+ */
425
+ export type SessionEvent<T extends SessionEventType = SessionEventType> = {
426
+ [K in SessionEventType]: {
427
+ type: K;
428
+ /** Monotonic sequence number within the session. */
429
+ seq: number;
430
+ /** Unix epoch milliseconds. */
431
+ time: number;
432
+ data: SessionEventMap[K];
433
+ /**
434
+ * Marks an event a reader may safely skip when it does not recognize
435
+ * `type`. Absent means required: a reader meeting an unrecognized type
436
+ * without this marker MUST refuse to reconstruct the session instead of
437
+ * silently dropping the event, because an unrecognized required event may
438
+ * change how the rest of the log is interpreted. A writer sets `true` only
439
+ * on purely informational records whose loss cannot affect reconstruction;
440
+ * defaulting to required means a forgotten marker over-refuses (an
441
+ * inconvenience) rather than silently resuming a gutted session.
442
+ */
443
+ ignorable?: true;
444
+ } & (K extends SurfaceEventType ? {
445
+ /**
446
+ * Seq numbers of earlier events that this event cites as sources
447
+ * (e.g. the `assistant/chunk` seqs that built an `assistant/message`,
448
+ * or the surface nodes shadowed by a compaction replace node). An
449
+ * `assistant/message` may carry a present empty array for a known empty
450
+ * provider stream; when the field is absent, the event does not record which
451
+ * earlier events produced the message.
452
+ */
453
+ sourceEventSeqs?: number[];
454
+ /** How this event entered the surface; absent for non-surface events. */
455
+ surfaceOp?: SurfaceOp;
456
+ } : object);
457
+ }[T];
458
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1,33 @@
1
+ /**
2
+ * Brand a string as a {@link SessionId}.
3
+ * @param id - the raw session id string.
4
+ * @returns the same string, branded (a compile-time cast — no runtime cost).
5
+ */
6
+ export function SessionId(id) {
7
+ return id;
8
+ }
9
+ /**
10
+ * The on-disk session format version, stamped into every newly-written {@link SessionHeader}
11
+ * and enforced by every persistence backend on load. The single source of truth for the
12
+ * version — write sites and the load-time check all read it.
13
+ * While the harness is unreleased it is pinned at `0`: no compatibility is
14
+ * implied, incompatible logs are rejected, and no migration is provided.
15
+ *
16
+ * The version is a single monotonic integer with no major/minor split. Whether
17
+ * a bump is needed is decided by what the WRITER emits, never by what a newer
18
+ * reader can accept: bump exactly when an older runtime could no longer handle
19
+ * a new log with full semantic correctness ("parses without error" is not
20
+ * correctness — silently skipping content that shapes reconstruction is a
21
+ * wrong read). Only structural changes reach that bar: the header shape, the
22
+ * {@link SessionEvent} envelope, core event semantics, or the surface
23
+ * mechanism (the {@link SurfaceEventType} set and {@link SurfaceOp} variants).
24
+ * Adding an ordinary event type does not bump — the per-event
25
+ * {@link SessionEvent.ignorable} guard covers vocabulary growth instead. When
26
+ * in doubt, bump: a near-identity upgrade step is almost free, a missed bump
27
+ * makes older runtimes read new logs wrong silently. The full mechanism
28
+ * (upgrade-step chain, in-memory view conversion, migrate-on-continue) is
29
+ * recorded in the session-log-version-mechanism Agent Note
30
+ * (`.agents/notes/implemented/architecture/2026-08-10-session-log-version-mechanism.md`).
31
+ */
32
+ export const SESSION_FORMAT_VERSION = 0;
33
+ //# sourceMappingURL=types.js.map
package/package.json ADDED
@@ -0,0 +1,60 @@
1
+ {
2
+ "name": "@hasna-internal/kai-session",
3
+ "description": "Event-sourced session store for the DeepSeek Harness",
4
+ "version": "0.1.1-rc.2",
5
+ "publishConfig": {
6
+ "access": "public"
7
+ },
8
+ "repository": {
9
+ "type": "git",
10
+ "url": "git+https://github.com/deepseek-ai/deepseek-harness.git",
11
+ "directory": "packages/core/session"
12
+ },
13
+ "type": "module",
14
+ "main": "lib/index.js",
15
+ "types": "lib/types/index.d.ts",
16
+ "exports": {
17
+ ".": {
18
+ "types": "./lib/types/index.d.ts",
19
+ "default": "./lib/index.js"
20
+ },
21
+ "./invariant": {
22
+ "types": "./lib/types/invariant.d.ts",
23
+ "default": "./lib/invariant.js"
24
+ },
25
+ "./types": {
26
+ "types": "./lib/types/types.d.ts",
27
+ "default": "./lib/types/types.js"
28
+ },
29
+ "./src/*": "./src/*",
30
+ "./package.json": "./package.json",
31
+ "./surface": {
32
+ "types": "./lib/types/surface.d.ts",
33
+ "default": "./lib/types/surface.js"
34
+ }
35
+ },
36
+ "files": [
37
+ "lib/index.js",
38
+ "lib/invariant.js",
39
+ "lib/types/**/*.js",
40
+ "lib/types/**/*.d.ts"
41
+ ],
42
+ "license": "MIT",
43
+ "peerDependencies": {
44
+ "@hasna-internal/kai-llm": "^0.1.1-rc.2",
45
+ "@hasna-internal/kai-scope": "^0.1.1-rc.2",
46
+ "@hasna-internal/kai-typert-protocol": "^0.1.1-rc.2",
47
+ "@deepseek-ai/cordis": "^4.0.1",
48
+ "@hasna-internal/kai-brand": "^0.1.1-rc.2",
49
+ "@hasna-internal/kai-invariants": "^0.1.1-rc.2"
50
+ },
51
+ "devDependencies": {
52
+ "@hasna-internal/kai-brand": "^0.1.1-rc.2",
53
+ "@hasna-internal/kai-llm": "^0.1.1-rc.2",
54
+ "@hasna-internal/kai-typert-registry": "^0.1.1-rc.2",
55
+ "@hasna-internal/kai-typert-protocol": "^0.1.1-rc.2",
56
+ "@hasna-internal/kai-invariants": "^0.1.1-rc.2",
57
+ "@hasna-internal/kai-scope": "^0.1.1-rc.2",
58
+ "@deepseek-ai/cordis": "^4.0.1"
59
+ }
60
+ }