@morlay/ui-conversation-manager 0.0.2-alpha.5 → 0.0.2-alpha.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/dist/client.d.cts CHANGED
@@ -93,6 +93,30 @@ type Scoped<T extends object> = object & {
93
93
  readonly [ScopedBrand]: T;
94
94
  };
95
95
  //#endregion
96
+ //#region ../../../vendor/deepseek-harness/packages/util/brand/lib/types/index.d.ts
97
+ /**
98
+ * Duplicate-install-safe nominal primitive helpers.
99
+ *
100
+ * A brand makes structurally identical strings or numbers non-interchangeable
101
+ * at the type level: a `SessionId` cannot be passed where a `ToolCallId` is
102
+ * expected, and an event sequence cannot be passed as a log offset. Comparison,
103
+ * logging, and serialization retain the underlying primitive behavior.
104
+ *
105
+ * This package owns no concrete domain value and keeps no runtime identity or mutable
106
+ * state, so independently installed copies produce interchangeable values.
107
+ *
108
+ * @module @deepseek-ai/dsh-brand
109
+ */
110
+ declare const BRAND: unique symbol;
111
+ /** A string carrying a compile-time-only brand `B`. */
112
+ type Branded<B extends string> = string & {
113
+ readonly [BRAND]: B;
114
+ };
115
+ /** A number carrying a compile-time-only brand `B`. */
116
+ type BrandedNumber<B extends string> = number & {
117
+ readonly [BRAND]: B;
118
+ };
119
+ //#endregion
96
120
  //#region ../../../vendor/deepseek-harness/packages/typert/protocol/lib/types/owned-value.d.ts
97
121
  /** Generic invocation-owned values returned by synchronous Client Context resolvers. */
98
122
  /** Shared identity across independently bundled Context providers and Gateway. */
@@ -144,6 +168,19 @@ type TypertCodec = {
144
168
  readonly typeSymbol: string;
145
169
  /** Materialize and return the process-realm schema on first boundary use. */
146
170
  readonly create: () => TypertSchema;
171
+ /**
172
+ * Decode a unary result whose fields require type-specific handling.
173
+ * @param value - result reconstructed by the RPC carrier.
174
+ * @returns the validated result, retaining native byte views.
175
+ */
176
+ readonly decode?: (value: unknown) => unknown;
177
+ /**
178
+ * Project typed binary fields into RPC result attachments.
179
+ * @param value - native unary result.
180
+ * @param writeBytes - records a byte view at its result-relative path and returns its JSON placeholder.
181
+ * @returns JSON metadata with untouched JSON subtrees retained.
182
+ */
183
+ readonly encode?: (value: unknown, writeBytes: (bytes: Uint8Array, path: readonly (string | number)[]) => null) => unknown;
147
184
  } | {
148
185
  readonly mode: 'src-json';
149
186
  };
@@ -180,7 +217,7 @@ interface InvocationDescriptor {
180
217
  readonly method: string;
181
218
  /** Service member invoked when the exported method name is an alias. */
182
219
  readonly implementation?: string;
183
- /** Absent for unary calls; stream calls validate and deliver every yielded item. */
220
+ /** Absent for unary calls; stream calls deliver every yielded item as the Host produced it. */
184
221
  readonly mode?: 'stream';
185
222
  /** Receiver selection mode. */
186
223
  readonly invocation: {
@@ -200,6 +237,16 @@ interface InvocationDescriptor {
200
237
  };
201
238
  /** Ordered business parameters. */
202
239
  readonly parameters: readonly InvocationParameterDescriptor[];
240
+ /**
241
+ * Client-to-Host items of the same logical stream, generated from the `In`
242
+ * type argument of the method's `RemoteStream<Out, In>` return type; absent
243
+ * when `In` is `never`. The method reads the items through
244
+ * `RemoteInvocation.uplink()`, so nothing enters the parameter list.
245
+ */
246
+ readonly uplink?: {
247
+ /** Codec validating every uplink item before `uplink()` delivers it. */
248
+ readonly codec: TypertCodec;
249
+ };
203
250
  /** Transport cancellation injected after business parameters instead of entering wire args. */
204
251
  readonly cancellation?: {
205
252
  /** Reserved final Host method parameter. */
@@ -210,6 +257,56 @@ interface InvocationDescriptor {
210
257
  /** Source declaration used only for diagnostics. */
211
258
  readonly sourceLocation?: InvocationSourceLocation;
212
259
  }
260
+ /**
261
+ * Opaque identity of one Peer: a party admitted to this Host by the connection
262
+ * layer. "Peer" is a connection-layer word; the browser application keeps the
263
+ * word "Client".
264
+ */
265
+ type PeerId = Branded<'PeerId'>;
266
+ /**
267
+ * One Peer's session on this Host. Connection owns it: `ctx` is the Cordis
268
+ * scope that owns connection-lifetime registrations and is disposed with the
269
+ * Peer. Who the Peer is and what it may do are not recorded here.
270
+ */
271
+ interface PeerScope {
272
+ readonly id: PeerId;
273
+ readonly ctx: Context;
274
+ /**
275
+ * Tear down every registration made through `ctx`.
276
+ * @returns settles once the scope has quiesced; racing calls share one completion.
277
+ */
278
+ dispose(): Promise<void>;
279
+ }
280
+ /**
281
+ * The context of one Remote call, reachable inside the receiving method as
282
+ * `this.ctx.invocation`. The Gateway derives the receiver from a Context that
283
+ * carries it, so no parameter is injected and nothing crosses the wire.
284
+ */
285
+ interface RemoteInvocation {
286
+ readonly request: {
287
+ readonly namespace: string;
288
+ readonly method: string;
289
+ readonly args: Readonly<Record<string, unknown>>;
290
+ };
291
+ /** Cordis service key of the receiving Service. */
292
+ readonly service: string;
293
+ /** Peer the call speaks for; an in-process carrier speaks for the operator. */
294
+ readonly peer: PeerScope;
295
+ /** Carrier cancellation: Client cancel, socket close, or an uplink failure. */
296
+ readonly signal: AbortSignal;
297
+ /**
298
+ * The Client's uplink items for this call. Available once; a second call
299
+ * throws. With an uplink codec on the descriptor every item is decoded to
300
+ * `In`; without one items arrive as `unknown` after a JSON-safety check.
301
+ * Iteration ends when the Client ends its uplink; when the method finishes
302
+ * its downlink the Gateway calls the iterator's `return()` and unread items
303
+ * are dropped. `In` is the caller's assertion: the runtime decodes by the
304
+ * descriptor and does not cross-check it.
305
+ * @template In - item type the caller reads; the descriptor codec decides what arrives.
306
+ * @returns the single-consumer uplink iterable.
307
+ */
308
+ uplink<In = unknown>(): AsyncIterable<In>;
309
+ }
213
310
  /** Generated Host contract selected explicitly by a Client assembly. */
214
311
  interface TypertRemoteContribution {
215
312
  /** npm package that owns the Remote methods. */
@@ -423,6 +520,12 @@ interface TypertRegistryContract {
423
520
  declare module '@deepseek-ai/cordis' {
424
521
  interface Context {
425
522
  typert: TypertRegistryContract;
523
+ /**
524
+ * The Remote call this Context was derived for, or `undefined` on a
525
+ * Context no Remote call derived. A Service method reads it as
526
+ * `this.ctx.invocation`.
527
+ */
528
+ readonly invocation: RemoteInvocation | undefined;
426
529
  }
427
530
  }
428
531
  //#endregion
@@ -451,30 +554,6 @@ declare abstract class TypertRemoteService<out T = never> extends Service<T> {
451
554
  protected constructor(ctx: Context, serviceKey: string, options?: TypertGatewayBindingOptions);
452
555
  }
453
556
  //#endregion
454
- //#region ../../../vendor/deepseek-harness/packages/util/brand/lib/types/index.d.ts
455
- /**
456
- * Duplicate-install-safe nominal primitive helpers.
457
- *
458
- * A brand makes structurally identical strings or numbers non-interchangeable
459
- * at the type level: a `SessionId` cannot be passed where a `ToolCallId` is
460
- * expected, and an event sequence cannot be passed as a log offset. Comparison,
461
- * logging, and serialization retain the underlying primitive behavior.
462
- *
463
- * This package owns no concrete domain value and keeps no runtime identity or mutable
464
- * state, so independently installed copies produce interchangeable values.
465
- *
466
- * @module @deepseek-ai/dsh-brand
467
- */
468
- declare const BRAND: unique symbol;
469
- /** A string carrying a compile-time-only brand `B`. */
470
- type Branded<B extends string> = string & {
471
- readonly [BRAND]: B;
472
- };
473
- /** A number carrying a compile-time-only brand `B`. */
474
- type BrandedNumber<B extends string> = number & {
475
- readonly [BRAND]: B;
476
- };
477
- //#endregion
478
557
  //#region ../../../vendor/deepseek-harness/packages/attachment/attachment/lib/types/error.d.ts
479
558
  declare const ATTACHMENT_ERROR_CODES: readonly ["TOO_MANY_IMAGES", "IMAGES_TOO_LARGE", "UNSUPPORTED_IMAGE_TYPE", "INVALID_IMAGE_BASE64", "INVALID_IMAGE", "IMAGE_TYPE_MISMATCH", "IMAGE_TOO_LARGE", "IMAGE_TOO_MANY_PIXELS", "IMAGE_DIMENSION_TOO_LARGE", "INVALID_FILE_BASE64", "INVALID_ATTACHMENT_REF", "ATTACHMENT_CORRUPT", "ATTACHMENT_WRITE_FAILED", "ATTACHMENT_NOT_FOUND", "ATTACHMENT_READ_FAILED", "ATTACHMENT_PROJECTION_UNSUPPORTED", "ATTACHMENT_FILES_UNSUPPORTED"];
480
559
  /** Stable attachment failure codes used for protocol error routing. */
@@ -837,98 +916,84 @@ interface AssistantProviderMetadata {
837
916
  interface ModelMessageSource extends AssistantProviderMetadata {
838
917
  kind: 'model';
839
918
  }
840
- /** Required source of a user-role message carrying one tool result. */
919
+ /** Required source of a tool-role message carrying one tool result. */
841
920
  interface ToolMessageSource {
842
921
  kind: 'tool';
843
922
  callId: ToolCallId;
844
923
  }
845
- /** One named contribution to a `snapshot`-form context, in assembly order. */
846
- interface ContextSnapshotSection {
847
- /** The contributing subsystem's name. */
848
- readonly name: string;
849
- /** That contribution's model-facing text, exactly as assembled. */
850
- readonly text: string;
924
+ /** Required source of a system-role message produced by the system-prompt plugin. */
925
+ interface SystemPromptMessageSource {
926
+ kind: 'system-prompt';
851
927
  }
852
928
  /**
853
- * Producer-declared {@link ContextForm} and the fields that form requires,
854
- * mixed into the source types that carry one.
855
- *
856
- * Discriminated by `form` so a producer cannot select a form without the
857
- * fields needed to present it: a `notice` must record its one-line
858
- * account, a `snapshot` its sections. Omitting `form` stays valid — an
859
- * undeclared context is the documented default.
860
- */
861
- type ContextFormed = {
862
- readonly form?: never;
863
- } | {
864
- readonly form: 'instructions';
865
- } | {
866
- readonly form: 'catalog';
867
- } | {
868
- readonly form: 'snapshot';
869
- /** The named contributions this snapshot assembled, in order. */
870
- readonly sections: readonly ContextSnapshotSection[];
871
- } | {
872
- readonly form: 'notice';
873
- /** One-line account of what happened, shown without expanding the row. */
874
- readonly summary: string;
875
- } | {
876
- readonly form: 'relay';
877
- } | {
878
- readonly form: 'recall';
879
- };
880
- /**
881
- * Where a message (or injected content) came from.
882
- * Merge-extensible sum type — plugins add their own `kind`s.
929
+ * Where a message (or injected content) came from, in the harness's own
930
+ * vocabulary. Merge-extensible sum type — each producer declares its own
931
+ * `kind` in its own module; there is no shared catch-all `plugin` kind.
932
+ * Model and tool sources answer their role messages; user messages carry any
933
+ * producer's kind, and consumers fall through unknown kinds.
883
934
  */
884
935
  interface MessageSourceMap {
885
936
  user: {
886
937
  kind: 'user';
887
938
  };
888
- plugin: {
889
- kind: 'plugin';
890
- plugin: string;
891
- } & ContextFormed;
892
939
  model: ModelMessageSource;
893
940
  tool: ToolMessageSource;
941
+ 'system-prompt': SystemPromptMessageSource;
894
942
  }
895
943
  /** Any known message source, derived from {@link MessageSourceMap}; switch on `kind` and fall through unknowns (merge-extensible). */
896
944
  type MessageSource = MessageSourceMap[keyof MessageSourceMap];
897
- /** One immutable message representation shared by delivery, durable history, and model requests. */
898
- interface Message {
945
+ /** Shared immutable fields of every conversation message. */
946
+ interface MessageBase {
899
947
  /** Stable identity preserved across every representation boundary. */
900
948
  readonly id: MessageId;
901
- /** Provider-neutral conversation role. */
902
- readonly role: 'system' | 'user' | 'assistant';
903
949
  /** Exact model-facing blocks. */
904
- readonly content: ContentBlock[];
905
- /** Required source fields supplied by the producer. */
950
+ readonly content: readonly ContentBlock[];
951
+ /** Required source fields supplied by the producer.
952
+ * @persistenceSource user developer
953
+ */
906
954
  readonly source: MessageSource;
907
955
  }
908
- /** A user-role specialization of the one shared message representation. */
909
- interface UserMessage extends Message {
956
+ /** A rendered system prompt attributed to the system-prompt producer; empty content sends no prompt. */
957
+ interface SystemMessage extends MessageBase {
958
+ readonly role: 'system';
959
+ readonly source: MessageSourceMap['system-prompt'];
960
+ }
961
+ /** Incremental agent session changes in conversation order, currently tool additions and removals. */
962
+ interface DeveloperMessage extends MessageBase {
963
+ readonly role: 'developer';
964
+ }
965
+ /** A user-role specialization of the shared message representation. */
966
+ interface UserMessage extends MessageBase {
910
967
  readonly role: 'user';
911
968
  }
912
969
  /** A model-produced assistant specialization of the shared message representation. */
913
- interface AssistantMessage extends Message {
970
+ interface AssistantMessage extends MessageBase {
914
971
  readonly role: 'assistant';
915
972
  readonly source: ModelMessageSource;
916
973
  }
917
- /**
918
- * A system-role specialization of the shared message representation: one
919
- * rendered system prompt attributed to the plugin that assembled it. Empty
920
- * `content` means "no system prompt" and projects to no wire message.
921
- */
922
- interface SystemMessage extends Message {
923
- readonly role: 'system';
924
- readonly source: MessageSourceMap['plugin'];
925
- }
926
- /** A tool-result specialization whose model-facing block retains call correlation. */
927
- interface ToolResultMessage extends Message {
928
- readonly role: 'user';
929
- readonly content: [ToolResultBlock];
974
+ /** A first-class tool-role message carrying the result of one tool invocation. */
975
+ interface ToolResultMessage extends MessageBase {
976
+ readonly role: 'tool';
930
977
  readonly source: ToolMessageSource;
978
+ /** Provider-issued id of the tool call this message answers. */
979
+ readonly toolCallId: ToolCallId;
980
+ /** Whether the tool invocation failed. */
981
+ readonly isError?: boolean;
931
982
  }
983
+ /**
984
+ * The conversation messages persisted by Session, keyed by role. This map is
985
+ * closed because every model-visible role must have a durable Session event
986
+ * and an adapter projection.
987
+ */
988
+ interface MessageRoleMap {
989
+ system: SystemMessage;
990
+ developer: DeveloperMessage;
991
+ user: UserMessage;
992
+ assistant: AssistantMessage;
993
+ tool: ToolResultMessage;
994
+ }
995
+ /** Any persisted conversation message, discriminated by its `role`. */
996
+ type Message = MessageRoleMap[keyof MessageRoleMap];
932
997
  //#endregion
933
998
  //#region ../../../vendor/deepseek-harness/packages/llm/llm/lib/types/types.d.ts
934
999
  declare module '@deepseek-ai/cordis' {
@@ -1013,16 +1078,27 @@ interface ToolCallBlock {
1013
1078
  /** Raw JSON string as produced by the model. */
1014
1079
  arguments: string;
1015
1080
  }
1016
- /** The result of a tool invocation, sent back to the model. */
1017
- interface ToolResultBlock {
1018
- type: 'tool-result';
1019
- toolCallId: ToolCallId;
1020
- content: ContentBlock[];
1021
- isError?: boolean;
1081
+ /** Activates a tool definition from the developer event's referenced request header. */
1082
+ interface ToolAdditionBlock {
1083
+ type: 'tool-addition';
1084
+ /** Name of exactly one tool in the referenced historical header. */
1085
+ toolName: string;
1086
+ /**
1087
+ * Reserved against inline definitions; the historical request header owns the schema.
1088
+ * @persistenceReserved
1089
+ */
1090
+ tool?: never;
1091
+ }
1092
+ /** Records the dynamic removal of a tool identified by its session-local name. */
1093
+ interface ToolRemovalBlock {
1094
+ type: 'tool-removal';
1095
+ toolName: string;
1022
1096
  }
1023
1097
  /**
1024
1098
  * Merge-extensible content blocks keyed by `type`. New core blocks must land
1025
- * with adapter, UI, and compaction support.
1099
+ * with adapter, UI, and compaction support. Developer tool-change blocks are
1100
+ * reserved for Session V4 persistence; providers and UI reject them until
1101
+ * their producers and consumers are implemented together.
1026
1102
  */
1027
1103
  interface ContentBlockMap {
1028
1104
  'text': TextBlock;
@@ -1030,7 +1106,8 @@ interface ContentBlockMap {
1030
1106
  'image': ImageBlock;
1031
1107
  'file': FileBlock;
1032
1108
  'tool-call': ToolCallBlock;
1033
- 'tool-result': ToolResultBlock;
1109
+ 'tool-addition': ToolAdditionBlock;
1110
+ 'tool-removal': ToolRemovalBlock;
1034
1111
  }
1035
1112
  /** The block `type` tag vocabulary; widens as plugins add entries to {@link ContentBlockMap}. */
1036
1113
  type ContentBlockType = keyof ContentBlockMap;
@@ -1329,11 +1406,26 @@ type StreamChunk = {
1329
1406
  * it from this package.
1330
1407
  */
1331
1408
  interface ToolSchema {
1409
+ /**
1410
+ * Requests deferred loading of the tool definition into model context,
1411
+ * independently of whether a tool-addition block records the tool.
1412
+ * Uses Anthropic's defer_loading terminology.
1413
+ */
1414
+ deferLoading?: true;
1332
1415
  name: string;
1333
1416
  description: string;
1334
1417
  /** JSON Schema object for the arguments. */
1335
1418
  parameters: Record<string, unknown>;
1336
1419
  }
1420
+ /** User input for one LLM request; it has no durable Session identity or source. */
1421
+ interface RequestUserInput {
1422
+ readonly role: 'user';
1423
+ readonly content: UserMessage['content'];
1424
+ readonly id?: never;
1425
+ readonly source?: never;
1426
+ }
1427
+ /** A durable conversation message or a user input used only for one request. */
1428
+ type RequestMessage = Message | RequestUserInput;
1337
1429
  /** A single model request, fully assembled. */
1338
1430
  interface GenerateOptions {
1339
1431
  /** Registered provider route selecting the adapter instance. */
@@ -1345,9 +1437,9 @@ interface GenerateOptions {
1345
1437
  * Ordered conversation messages, exactly as the provider sees them. A
1346
1438
  * loop-built request passes the derived history (dsh-agent-loop), whose
1347
1439
  * leading system-role message carries the system prompt; a hand-built
1348
- * one-shot passes any list.
1440
+ * one-shot may include identity-free user inputs.
1349
1441
  */
1350
- messages: Message[];
1442
+ messages: RequestMessage[];
1351
1443
  /**
1352
1444
  * System prompt text for one-shot callers; adapters map it to the provider's
1353
1445
  * system slot ahead of `messages`. Loop-built requests leave it undefined.
@@ -1396,6 +1488,16 @@ declare namespace Binary {
1396
1488
  /** String/symbol keyed dictionary type. */
1397
1489
  type Dict<T = any, K extends string | symbol = string> = { [key in K]: T; };
1398
1490
  //#endregion
1491
+ //#region ../../../vendor/deepseek-harness/vendor/cosmokit/lib/types/volatile.d.ts
1492
+ /** Shared config references used by schema validators and plugin runtimes. */
1493
+ /** Recursively readonly data returned by a volatile config reference. */
1494
+ type VolatileSnapshot<T> = T extends object ? { readonly [K in keyof T]: VolatileSnapshot<T[K]>; } : T;
1495
+ /** A stable reference; keep the reference, or capture its value for one operation only. */
1496
+ interface Volatile<T> {
1497
+ /** @returns the current immutable snapshot, including undefined for an absent value. */
1498
+ get(): VolatileSnapshot<T>;
1499
+ }
1500
+ //#endregion
1399
1501
  //#region ../../../node_modules/.pnpm/@standard-schema+spec@1.1.0/node_modules/@standard-schema/spec/dist/index.d.ts
1400
1502
  /** The Standard Typed interface. This is a base type extended by other specs. */
1401
1503
  interface StandardTypedV1<Input = unknown, Output = Input> {
@@ -1478,9 +1580,9 @@ declare const kSchema: unique symbol;
1478
1580
  declare global {
1479
1581
  namespace Schemastery {
1480
1582
  /** Convert primitive constructors, constants, and existing schemas into a schema type. */
1481
- type From<X> = X extends string | number | boolean ? Schema<X> : X extends Schema ? X : X extends typeof String ? Schema<string> : X extends typeof Number ? Schema<number> : X extends typeof Boolean ? Schema<boolean> : X extends typeof Function ? Schema<Function, (...args: any[]) => any> : X extends Constructor<infer S> ? Schema<S> : never;
1482
- type TypeS1<X> = X extends Schema<infer S, unknown> ? S : never;
1483
- type Inverse<X> = X extends Schema<any, infer Y> ? (arg: Y) => void : never;
1583
+ type From<X> = X extends string | number | boolean ? Schema<X> : X extends Schema<any, any, SchemaMode> ? X : X extends typeof String ? Schema<string> : X extends typeof Number ? Schema<number> : X extends typeof Boolean ? Schema<boolean> : X extends typeof Function ? Schema<Function, (...args: any[]) => any> : X extends Constructor<infer S> ? Schema<S> : never;
1584
+ type TypeS1<X> = X extends Schema<infer S, infer _T, infer _M> ? S : never;
1585
+ type Inverse<X> = X extends Schema<infer _S, infer T, infer M> ? (arg: SchemaOutput<T, M>) => void : never;
1484
1586
  /** Input type accepted by a schema-like value. */
1485
1587
  type TypeS<X> = TypeS1<From<X>>;
1486
1588
  /** Output type returned by a schema-like value after validation. */
@@ -1488,7 +1590,7 @@ declare global {
1488
1590
  /** Resolver callback used by custom schema types registered with `Schema.extend()`. */
1489
1591
  type Resolve = (data: any, schema: Schema, options: Options, strict?: boolean) => [any, any?];
1490
1592
  /** Input type accepted by one schema in an intersection. */
1491
- type IntersectS<X> = From<X> extends Schema<infer S, unknown> ? S : never;
1593
+ type IntersectS<X> = From<X> extends Schema<infer S, infer _T, infer _M> ? S : never;
1492
1594
  /** Output type returned by one schema in an intersection. */
1493
1595
  type IntersectT<X> = Inverse<From<X>> extends ((arg: infer T) => void) ? T : never;
1494
1596
  type TupleS<X extends readonly any[]> = X extends readonly [infer L, ...infer R] ? [TypeS<L>?, ...TupleS<R>] : any[];
@@ -1543,8 +1645,8 @@ declare global {
1543
1645
  dict<X, Y extends Schema<any, string> = Schema<string>>(inner: X, sKey?: Y): Schema<Dict<TypeS<X>, TypeS<Y>>, Dict<TypeT<X>, TypeT<Y>>>;
1544
1646
  /** Accept tuple arrays where each index matches the corresponding schema. */
1545
1647
  tuple<const X extends readonly any[]>(list: X): Schema<TupleS<X>, TupleT<X>>;
1546
- /** Accept plain objects whose declared properties match the schema dictionary. */
1547
- object<X extends Dict>(dict: X): Schema<ObjectS<X>, ObjectT<X>>;
1648
+ /** Accept plain objects; infer fields from the dictionary, not the enclosing schema's output type. */
1649
+ object<X extends Dict>(dict: X): Schema<ObjectS<NoInfer<X>>, ObjectT<NoInfer<X>>>;
1548
1650
  /** Accept values matching at least one schema in `list`. */
1549
1651
  union<const X>(list: readonly X[]): Schema<TypeS<X>, TypeT<X>>;
1550
1652
  /** Accept values matching every schema in `list`, merging object outputs. */
@@ -1552,7 +1654,7 @@ declare global {
1552
1654
  /** Validate with `inner`, then convert the result with `callback`. */
1553
1655
  transform<X, T>(inner: X, callback: (value: TypeS<X>, options: Schemastery.Options) => T, preserve?: boolean): Schema<TypeS<X>, T>;
1554
1656
  /** Defer construction of a recursive schema until validation or serialization. */
1555
- lazy<X extends Schema>(callback: () => X): X;
1657
+ lazy<X extends Schema<any, any, SchemaMode>>(callback: () => X): X;
1556
1658
  ValidationError: typeof ValidationError;
1557
1659
  }
1558
1660
  /** Runtime validation options shared by all schema calls. */
@@ -1568,6 +1670,8 @@ declare global {
1568
1670
  interface Meta<T = any> {
1569
1671
  default?: T extends {} ? Partial<T> : T;
1570
1672
  required?: boolean;
1673
+ /** Parse this node as a stable config reference; its type and UI metadata remain unchanged. */
1674
+ volatile?: boolean;
1571
1675
  disabled?: boolean;
1572
1676
  collapse?: boolean;
1573
1677
  badges?: {
@@ -1591,9 +1695,9 @@ declare global {
1591
1695
  }
1592
1696
  }
1593
1697
  /** Callable schema instance that validates input and returns normalized output. */
1594
- interface Schemastery<S = any, T = S> {
1595
- (data?: S | null, options?: Schemastery.Options): T;
1596
- new (data?: S | null, options?: Schemastery.Options): T;
1698
+ interface Schemastery<S = any, T = S, Mode extends SchemaMode = 'plain'> {
1699
+ (data?: S | null, options?: Schemastery.Options): SchemaOutput<T, Mode>;
1700
+ new (data?: S | null, options?: Schemastery.Options): SchemaOutput<T, Mode>;
1597
1701
  [kSchema]: true;
1598
1702
  uid: number;
1599
1703
  meta: Schemastery.Meta<T>;
@@ -1613,49 +1717,54 @@ declare global {
1613
1717
  /** Format this schema as a compact TypeScript-like type string. */
1614
1718
  toString(inline?: boolean): string;
1615
1719
  /** Serialize this schema, preserving shared and recursive references. */
1616
- toJSON(): Schema<S, T>;
1720
+ toJSON(): Schema<S, T, Mode>;
1617
1721
  /** Mark nullable input as invalid unless a default supplies a fallback. */
1618
- required(value?: boolean): Schema<S, T>;
1722
+ required<R extends boolean = true>(value?: R): Schema<S, T, SetRequired<Mode, R>>;
1723
+ /**
1724
+ * Parse this config field as a stable reference containing immutable data.
1725
+ * @returns a schema whose output supports get(), including when the field is absent.
1726
+ */
1727
+ volatile(): Schema<NoInfer<S>, NoInfer<T>, Mode extends 'defined' | 'volatile-defined' ? 'volatile-defined' : 'volatile'>;
1619
1728
  /** Hide this schema node from UI renderers. */
1620
- hidden(value?: boolean): Schema<S, T>;
1729
+ hidden(value?: boolean): Schema<S, T, Mode>;
1621
1730
  /** Return the default value instead of throwing when validation fails. */
1622
- loose(value?: boolean): Schema<S, T>;
1731
+ loose(value?: boolean): Schema<S, T, Mode>;
1623
1732
  /** Attach a renderer role and optional role-specific metadata. */
1624
- role(text: string, extra?: any): Schema<S, T>;
1733
+ role(text: string, extra?: any): Schema<S, T, Mode>;
1625
1734
  /** Attach an external documentation link. */
1626
- link(link: string): Schema<S, T>;
1735
+ link(link: string): Schema<S, T, Mode>;
1627
1736
  /** Set the fallback value used for nullable input. */
1628
- default(value: T): Schema<S, T>;
1737
+ default(value: T | NoInfer<Partial<S>>): Schema<S, T, SetRequired<Mode, true>>;
1629
1738
  /** Attach an auxiliary comment for documentation or form UIs. */
1630
- comment(text: string): Schema<S, T>;
1739
+ comment(text: string): Schema<S, T, Mode>;
1631
1740
  /** Attach a localized or plain description for documentation or form UIs. */
1632
- description(text: string): Schema<S, T>;
1741
+ description(text: string): Schema<S, T, Mode>;
1633
1742
  /** Mark this schema node as disabled for form UIs. */
1634
- disabled(value?: boolean): Schema<S, T>;
1743
+ disabled(value?: boolean): Schema<S, T, Mode>;
1635
1744
  /** Request collapsed rendering for nested form UIs. */
1636
- collapse(value?: boolean): Schema<S, T>;
1745
+ collapse(value?: boolean): Schema<S, T, Mode>;
1637
1746
  /** Add a deprecated badge to this schema node. */
1638
- deprecated(): Schema<S, T>;
1747
+ deprecated(): Schema<S, T, Mode>;
1639
1748
  /** Add an experimental badge to this schema node. */
1640
- experimental(): Schema<S, T>;
1749
+ experimental(): Schema<S, T, Mode>;
1641
1750
  /** Require strings to match a regular expression. */
1642
- pattern(regexp: RegExp): Schema<S, T>;
1751
+ pattern(regexp: RegExp): Schema<S, T, Mode>;
1643
1752
  /** Set an inclusive maximum for numbers or collection lengths. */
1644
- max(value: number): Schema<S, T>;
1753
+ max(value: number): Schema<S, T, Mode>;
1645
1754
  /** Set an inclusive minimum for numbers or collection lengths. */
1646
- min(value: number): Schema<S, T>;
1755
+ min(value: number): Schema<S, T, Mode>;
1647
1756
  /** Set the numeric increment constraint. */
1648
- step(value: number): Schema<S, T>;
1757
+ step(value: number): Schema<S, T, Mode>;
1649
1758
  /** Add or replace an object property schema. */
1650
- set(key: string, value: Schema): Schema<S, T>;
1759
+ set(key: string, value: Schema): Schema<S, T, Mode>;
1651
1760
  /** Append a tuple, union, or intersection member schema. */
1652
- push(value: Schema): Schema<S, T>;
1761
+ push(value: Schema): Schema<S, T, Mode>;
1653
1762
  /** Remove values equal to schema defaults from normalized output. */
1654
1763
  simplify(value?: any): any;
1655
1764
  /** Return a schema clone with descriptions merged from locale messages. */
1656
- i18n(messages: Dict): Schema<S, T>;
1765
+ i18n(messages: Dict): Schema<S, T, Mode>;
1657
1766
  /** Attach arbitrary metadata consumed by form renderers and downstream tools. */
1658
- extra<K extends keyof Schemastery.Meta>(key: K, value: Schemastery.Meta[K]): Schema<S, T>;
1767
+ extra<K extends keyof Schemastery.Meta>(key: K, value: Schemastery.Meta[K]): Schema<S, T, Mode>;
1659
1768
  }
1660
1769
  }
1661
1770
  declare class ValidationError extends TypeError {
@@ -1664,7 +1773,10 @@ declare class ValidationError extends TypeError {
1664
1773
  constructor(message: string, options: Schemastery.Options);
1665
1774
  static is(error: any): error is ValidationError;
1666
1775
  }
1667
- type Schema<S = any, T = S> = Schemastery<S, T>;
1776
+ type SchemaMode = 'plain' | 'defined' | 'volatile' | 'volatile-defined';
1777
+ type SchemaOutput<T, M extends SchemaMode> = M extends 'volatile' ? Volatile<T | undefined> : M extends 'volatile-defined' ? Volatile<T> : T;
1778
+ type SetRequired<M extends SchemaMode, R extends boolean> = M extends 'volatile' | 'volatile-defined' ? R extends true ? 'volatile-defined' : 'volatile' : R extends true ? 'defined' : 'plain';
1779
+ type Schema<S = any, T = S, Mode extends SchemaMode = 'plain'> = Schemastery<S, T, Mode>;
1668
1780
  declare const Schema: Schemastery.Static;
1669
1781
  //#endregion
1670
1782
  //#region ../../../vendor/deepseek-harness/packages/llm/llm/lib/types/retry-policy.d.ts
@@ -1753,8 +1865,8 @@ declare module '@deepseek-ai/cordis' {
1753
1865
  * process-local {@link markAgentLoopRequest} identity and arrives deep-frozen
1754
1866
  * (mutation throws): its content is a pure function of the session log (the
1755
1867
  * reconstructability Agent Note), so listeners read it, never rewrite it.
1756
- * Hand-built calls do not carry that marker; their messages already obey
1757
- * the immutable creation contract.
1868
+ * Hand-built calls do not carry that marker; callers own their request
1869
+ * inputs and must keep them unchanged until the stream settles.
1758
1870
  * @mode waterfall
1759
1871
  */
1760
1872
  'llm/stream'(this: LlmRuntime, options: GenerateOptions, next: () => AsyncIterable<StreamChunk>): AsyncIterable<StreamChunk>;
@@ -2134,7 +2246,7 @@ declare function SessionLogOffset(value: number): SessionLogOffset;
2134
2246
  * immutable prior-generation, and current fast-path rules are recorded in
2135
2247
  * `.agents/notes/implemented/architecture/2026-08-31-released-session-format-migrations.md`.
2136
2248
  */
2137
- declare const SESSION_FORMAT_VERSION = 3;
2249
+ declare const SESSION_FORMAT_VERSION = 4;
2138
2250
  /**
2139
2251
  * Immutable validated storage metadata, kept outside the conversation event log.
2140
2252
  */
@@ -2186,8 +2298,8 @@ interface CreateSessionOptions {
2186
2298
  readonly seed?: readonly SessionEvent[];
2187
2299
  /**
2188
2300
  * Exact fork-inherited prefix length when `meta.isSeeded` is true. The
2189
- * constructor seed is exactly this inherited prefix; the constructor
2190
- * appends the child-owned tagged marker at the cut.
2301
+ * constructor appends the child-owned tagged marker at the cut unless
2302
+ * the seed already includes it followed by child-owned fork closers.
2191
2303
  */
2192
2304
  readonly inheritedEventCount?: SessionLogOffset;
2193
2305
  /**
@@ -2279,6 +2391,15 @@ interface TurnEndReasonMap {
2279
2391
  interrupted: {
2280
2392
  kind: 'interrupted';
2281
2393
  };
2394
+ /**
2395
+ * Fork-seed construction closed a turn that was still open at the fork
2396
+ * boundary in the source session. Only fork seeds carry this marker — the
2397
+ * loop never emits it — and the source events before the boundary remain
2398
+ * intact in the child.
2399
+ */
2400
+ forked: {
2401
+ kind: 'forked';
2402
+ };
2282
2403
  }
2283
2404
  /** The union over {@link TurnEndReasonMap} — why a turn ended; plugins extend it by merging variants into the map. */
2284
2405
  type TurnEndReason = TurnEndReasonMap[keyof TurnEndReasonMap];
@@ -2295,6 +2416,10 @@ interface EpochHeader {
2295
2416
  adapterDefaults?: LlmCallConfigAdapterDefaults;
2296
2417
  /** Assembled tool schemas; absent for a tool-less request. */
2297
2418
  tools?: ToolSchema[];
2419
+ /** Retired request text; system prompts belong to system/message events.
2420
+ * @persistenceReserved
2421
+ */
2422
+ system?: never;
2298
2423
  }
2299
2424
  /** Registration-bound metadata for one resolved model route. */
2300
2425
  interface RequestContext {
@@ -2362,6 +2487,14 @@ interface SessionEventMap {
2362
2487
  * project their `content` verbatim; `source` tells them apart.
2363
2488
  */
2364
2489
  'user/message': UserMessage;
2490
+ /** An incremental agent session change admitted at the named turn and step. */
2491
+ 'developer/message': {
2492
+ turn: number;
2493
+ step: number;
2494
+ message: DeveloperMessage;
2495
+ /** Earlier request/header defining every tool addition; required exactly when additions are present. */
2496
+ headerSeq?: SessionSeq;
2497
+ };
2365
2498
  /**
2366
2499
  * The rendered system prompt on the model-visible surface. The loop appends
2367
2500
  * the first one as surface node 0 before the step's first `user/message`.
@@ -2439,7 +2572,7 @@ interface SessionEventMap {
2439
2572
  message: ToolResultMessage;
2440
2573
  /**
2441
2574
  * Optional failure identity and raw user-facing reason, outside model content;
2442
- * allowed only when the tool-result block has `isError: true`.
2575
+ * allowed only when the message has `isError: true`.
2443
2576
  */
2444
2577
  error?: {
2445
2578
  name: string;
@@ -2466,19 +2599,21 @@ interface SessionEventMap {
2466
2599
  */
2467
2600
  'request/context': RequestContext;
2468
2601
  /**
2469
- * Marks the end of a constructor seed. Events before it have smaller seq
2470
- * values and came from the seed (resume, fork, or replay); this lifecycle
2471
- * produced none of them. This log-only event is the durable projection of
2472
- * {@link Session.firstLiveSeq}.
2602
+ * Separates inherited or restored history from later lifecycle-owned work.
2603
+ * This log-only marker need not be at {@link Session.firstLiveSeq}: a fork
2604
+ * seed can already contain its tagged marker and child-owned synthetic
2605
+ * closers before construction.
2473
2606
  *
2474
2607
  * A fresh fork child owns one `{ inherited: true }` marker at its exact
2475
2608
  * inherited-prefix cut, even when that prefix ends in an ancestor marker.
2476
- * The last tagged marker is the current Session's cut; untagged markers keep
2477
- * ordinary restore and replay lifecycle boundaries.
2609
+ * `buildForkSeed` appends that marker before any synthetic closers; the
2610
+ * `Session` constructor supplies it when given only the inherited prefix.
2611
+ * The last tagged marker is the current Session's cut; untagged markers
2612
+ * keep ordinary restore and replay lifecycle boundaries.
2478
2613
  *
2479
- * `Session`'s constructor is the only legitimate writer. The invariant
2480
- * companion deliberately constrains nothing here, so a plugin appending one
2481
- * would silently classify every live bracket before it as seed history.
2614
+ * Only the `Session` constructor and `buildForkSeed` may create this marker.
2615
+ * The invariant companion deliberately constrains nothing here, so a plugin
2616
+ * appending one would silently classify every live bracket before it as seed history.
2482
2617
  *
2483
2618
  * An owner of a standalone open/close bracket (`compaction/start` …
2484
2619
  * `compaction/end`) reads it because seed history and live work are otherwise
@@ -2499,7 +2634,7 @@ type SessionEventType = keyof SessionEventMap;
2499
2634
  * event types may carry {@link SurfaceOp}; system, user, and tool events may also cite
2500
2635
  * earlier sources through {@link SessionEvent.sourceEventSeqs}.
2501
2636
  */
2502
- type SurfaceEventType = 'system/message' | 'user/message' | 'assistant/message' | 'tool/result';
2637
+ type SurfaceEventType = 'system/message' | 'developer/message' | 'user/message' | 'assistant/message' | 'tool/result';
2503
2638
  /**
2504
2639
  * How a session event entered the ordered surface. Only valid on
2505
2640
  * {@link SurfaceEventType} events.
@@ -2695,29 +2830,25 @@ declare class Session {
2695
2830
  /** The session identity, derived from its durable header's single copy. */
2696
2831
  get id(): SessionId;
2697
2832
  /**
2698
- * The first seq appended IN THIS PROCESS: the length of the constructor
2699
- * seed (0 without one). Events with smaller seq values entered through
2700
- * construction — replay, fork, or resume — and were never published on the
2701
- * `session/event` firehose (constructor seeds do not emit). This offset marks
2702
- * the constructor-input boundary for lifecycle ownership and persistence
2703
- * adoption; consumers that need complete canonical history still start at
2704
- * seq 0. Distinct from {@link inheritedEventCount}, the DURABLE
2705
- * fork-lineage cut: a resumed session's constructor seed is its full stored
2706
- * log, while the inherited count keeps the original fork value — this field is the
2707
- * in-process construction fact.
2833
+ * The constructor seed length (0 without one), before any marker appended
2834
+ * during construction. Seed events never publish on `session/event`. A
2835
+ * marker appended before the store attaches occupies this seq without
2836
+ * publishing either; otherwise this seq is available for the next append.
2708
2837
  *
2709
- * Not persisted itself: a seeded session projects it into the log as the
2710
- * `session/end-seed` event, which is what a consumer reading STORED history
2711
- * reads. Locate the LAST such event, not necessarily one at this seq — a
2712
- * seed already ending in one is not re-marked, so reopening an untouched
2713
- * session leaves that event at a smaller seq than `firstLiveSeq`. Prefer
2714
- * this field in-process: it is exact before the marker reaches storage.
2715
- *
2716
- * When this lifecycle appends the marker, it occupies this seq before the
2717
- * store attaches and therefore does not publish either. Otherwise this seq
2718
- * holds an ordinary published write.
2838
+ * This in-process offset is not persisted. A fork seed can already contain
2839
+ * the child's inherited marker and synthetic closers, so its child-owned
2840
+ * history starts at {@link inheritedEventCount}, before this offset. A
2841
+ * resumed Session's seed contains its full stored log, while its inherited
2842
+ * count keeps the durable fork cut. Consumers needing complete canonical
2843
+ * history start at seq 0.
2719
2844
  */
2720
2845
  readonly firstLiveSeq: SessionLogOffset;
2846
+ /**
2847
+ * First event produced for this object lifecycle. A new fork includes its
2848
+ * child-owned seed marker and closers; a restored Session starts after its
2849
+ * complete stored prefix. This in-process capture offset is not persisted.
2850
+ */
2851
+ readonly firstLifecycleSeq: SessionLogOffset;
2721
2852
  /**
2722
2853
  * Create a detached session by validating and snapshotting borrowed seed
2723
2854
  * events and storage metadata.
@@ -3005,10 +3136,12 @@ declare class SessionStore extends Service {
3005
3136
  */
3006
3137
  list(): Session[];
3007
3138
  /**
3008
- * Create a live child session from a stable prefix of a live source.
3139
+ * Create a live child session from an exact prefix of a live source.
3009
3140
  * `boundary` is an inclusive source event seq; omitted means the source's
3010
- * current last event. The selected slice may end with a between-turn event
3011
- * but must not end inside an open turn.
3141
+ * current last event. An open tail receives synthetic tool results and
3142
+ * step/turn closers with the forked cause. Closed steps and turns remain
3143
+ * unchanged, including any failed tool calls already missing results.
3144
+ * `inheritedEventCount` counts only copied source events, excluding these closers.
3012
3145
  *
3013
3146
  * @param source - Live source session object or id.
3014
3147
  * @param boundary - Inclusive source event seq to fork through; omitted means
@@ -3019,11 +3152,36 @@ declare class SessionStore extends Service {
3019
3152
  * @returns The created live child session.
3020
3153
  */
3021
3154
  fork(source: SessionForkSource, boundary?: SessionSeq, childSessionId?: SessionId): Session;
3022
- private _forkSeed;
3155
+ private _forkBoundary;
3023
3156
  private _resolveForkSource;
3024
3157
  }
3025
3158
  //#endregion
3026
3159
  //#region src/client/controller.d.ts
3160
+ /** 一行会话:标题、origin、最后活动时间、归档标记与工作区归属都由 host 给出。 */
3161
+ interface SessionRowRecord {
3162
+ sessionId: string;
3163
+ title: string | null;
3164
+ origin: string | null;
3165
+ cwd: string | null;
3166
+ createdAt: number;
3167
+ updatedAt: number;
3168
+ archived: boolean;
3169
+ workspace: string | null;
3170
+ }
3171
+ /** 列表请求:搜索、子代理过滤与分页都在后端做(前端分页等于每次拉全量)。 */
3172
+ interface SessionRowsQuery {
3173
+ query?: string;
3174
+ includeSubagents?: boolean;
3175
+ page?: number;
3176
+ pageSize?: number;
3177
+ }
3178
+ interface SessionRowsPage {
3179
+ items: SessionRowRecord[];
3180
+ /** 过滤后的总数(分页前),页面据此算页数。 */
3181
+ total: number;
3182
+ page: number;
3183
+ pageSize: number;
3184
+ }
3027
3185
  /** 时间范围的语义键(与 session-rdb `./usage` 的 `UsageRangeKey` 镜像)。 */
3028
3186
  type UsageRangeKey = "all" | "day" | "week" | "7d" | "30d" | "90d";
3029
3187
  /** 活动计数(与 session-rdb `./usage` 的回报结构镜像):轮次 / 步骤 / 用户输入 / 工具调用。 */
@@ -3083,6 +3241,8 @@ interface ConversationManagerGcResult {
3083
3241
  }
3084
3242
  /** 页面从注入面拿到的动作(属性语法:页面解构后直接调用,不绑 this)。 */
3085
3243
  interface ConversationManagerFace {
3244
+ /** 管理面自己的列表:完整语料(含归档),标题与最后活动时间随行给出;搜索与分页都在后端。 */
3245
+ listRows: (query?: SessionRowsQuery) => Promise<SessionRowsPage>;
3086
3246
  archive: (sessionId: SessionId) => Promise<void>;
3087
3247
  unarchive: (sessionId: SessionId) => Promise<void>;
3088
3248
  remove: (sessionId: SessionId) => Promise<void>;
@@ -3101,6 +3261,7 @@ declare class ConversationManagerController {
3101
3261
  private readonly ports;
3102
3262
  readonly face: ConversationManagerFace;
3103
3263
  constructor(ports: ConversationManagerPorts);
3264
+ private loadRows;
3104
3265
  private remove;
3105
3266
  private exportZip;
3106
3267
  private importZip;