@artenx/dshb 0.1.15 → 0.1.17

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.
@@ -1,6 +1,5 @@
1
1
  import { SessionInstructionSnapshot, SessionInstructionSnapshotStore, WorkspaceInstructionStore } from "./workspace-instructions.js";
2
2
  import { Context, Service } from "@deepseek-ai/cordis";
3
- import { FileAttachmentRef, ImageAttachmentRef } from "@deepseek-ai/dsh-attachment";
4
3
  //#region ../../node_modules/@deepseek-ai/dsh-brand/lib/types/index.d.ts
5
4
  /**
6
5
  * Duplicate-install-safe nominal primitive helpers.
@@ -35,6 +34,7 @@ interface TypertOwnedValue<Value> extends Disposable {
35
34
  declare const LOOKUP_HOST: unique symbol;
36
35
  declare const LOOKUP_WIRE: unique symbol;
37
36
  declare const CONTEXT_WIRE: unique symbol;
37
+ declare const RESOURCE_ID: unique symbol;
38
38
  /** Type-level association between a Host object and its wire identity. */
39
39
  interface TypertLookup<Host, Wire> {
40
40
  readonly [LOOKUP_HOST]: Host;
@@ -54,6 +54,21 @@ type TypertContextWire<ContextType> = ContextType extends TypertContext<infer Wi
54
54
  interface TypertLookupMap {}
55
55
  /** Merge-extensible scoped Context declarations. */
56
56
  interface TypertContextMap {}
57
+ /** Type-level association between a resource kind and its identity type. */
58
+ interface TypertResource<Id> {
59
+ readonly [RESOURCE_ID]: Id;
60
+ }
61
+ /** Extract the identity type associated with one resource declaration. */
62
+ type TypertResourceId<Resource> = Resource extends TypertResource<infer Id> ? Id : never;
63
+ /**
64
+ * Merge-extensible resource kinds whose identities a Remote call or forwarded
65
+ * event may carry. The package that owns an identity type declares its kind;
66
+ * the value is that kind's identity type, a string type such as a branded id.
67
+ * `global` names the built-in identity-less resource and is never a kind here.
68
+ */
69
+ interface TypertResourceMap {}
70
+ /** One declared resource kind. */
71
+ type TypertResourceKind = Extract<keyof TypertResourceMap, string>;
57
72
  /** Awaitable disposer returned by Cordis-owned Typert registrations. */
58
73
  type TypertDisposer = () => Promise<void>;
59
74
  type StringKeyOf<Value> = Extract<keyof Value, string>;
@@ -67,31 +82,31 @@ interface TypertSchema<Output = unknown> {
67
82
  parse(value: unknown): Output;
68
83
  }
69
84
  /** Codec attached to one invocation parameter or result. */
70
- type TypertCodec = {
85
+ type TypertCodec<Value = unknown> = (TypertRemoteValue<Value> & {
71
86
  readonly mode: 'strict';
72
87
  readonly typeSymbol: string;
73
- /** Materialize and return the process-realm schema on first boundary use. */
74
- readonly create: () => TypertSchema;
75
88
  /**
76
89
  * Decode a unary result whose fields require type-specific handling.
77
90
  * @param value - result reconstructed by the RPC carrier.
78
91
  * @returns the validated result, retaining native byte views.
79
92
  */
80
- readonly decode?: (value: unknown) => unknown;
93
+ readonly decode?: ((value: unknown) => unknown) | undefined;
81
94
  /**
82
95
  * Project typed binary fields into RPC result attachments.
83
96
  * @param value - native unary result.
84
97
  * @param writeBytes - records a byte view at its result-relative path and returns its JSON placeholder.
85
98
  * @returns JSON metadata with untouched JSON subtrees retained.
86
99
  */
87
- readonly encode?: (value: unknown, writeBytes: (bytes: Uint8Array, path: readonly (string | number)[]) => null) => unknown;
88
- } | {
100
+ readonly encode?: ((value: unknown, writeBytes: (bytes: Uint8Array, path: readonly (string | number)[]) => null) => unknown) | undefined;
101
+ }) | {
89
102
  readonly mode: 'src-json';
90
103
  };
91
104
  /** One ordered business parameter in a Remote invocation. */
92
105
  interface InvocationParameterDescriptor {
93
106
  /** Source-level parameter name. */
94
107
  readonly name: string;
108
+ /** Source parameter documentation, independent of JSON Schema support. */
109
+ readonly description?: string;
95
110
  /** Required key in the wire `args` object. */
96
111
  readonly wire: string;
97
112
  /** Whether the value is JSON or requires a registered Host lookup. */
@@ -158,6 +173,8 @@ interface InvocationDescriptor {
158
173
  };
159
174
  /** Codec for the unary result or each yielded stream item. */
160
175
  readonly result: TypertCodec;
176
+ /** Source-owned method documentation; ordinary methods need not have JSDoc. */
177
+ readonly description?: string;
161
178
  /** Source declaration used only for diagnostics. */
162
179
  readonly sourceLocation?: InvocationSourceLocation;
163
180
  }
@@ -168,19 +185,46 @@ interface InvocationDescriptor {
168
185
  */
169
186
  type PeerId = Branded<'PeerId'>;
170
187
  /**
171
- * One Peer's session on this Host. Connection owns it: `ctx` is the Cordis
188
+ * Merge-extensible caller identities. Each driver declares its own entry.
189
+ * Every entry is a JSON value with a unique literal `kind`, carries no
190
+ * credential, and is safe to persist in a Session log.
191
+ */
192
+ interface PrincipalMap {
193
+ /** The local user who owns this Host. */
194
+ owner: {
195
+ readonly kind: 'owner';
196
+ };
197
+ }
198
+ /** One caller identity; the authorization layer reads only this. */
199
+ type Principal = PrincipalMap[keyof PrincipalMap];
200
+ /**
201
+ * One Peer's session on this Host. Its creator owns it: `ctx` is the Cordis
172
202
  * scope that owns connection-lifetime registrations and is disposed with the
173
- * Peer. Who the Peer is and what it may do are not recorded here.
203
+ * Peer, and `principal` is the caller identity fixed when the Peer was created.
174
204
  */
175
205
  interface PeerScope {
176
206
  readonly id: PeerId;
207
+ /** Connection-lifetime registrations; disposed with the Peer. */
177
208
  readonly ctx: Context;
209
+ /** Caller identity fixed at creation by in-process Host code; no wire field can set it. */
210
+ readonly principal: Principal;
211
+ /** Aborted once the Peer is disposed; Remote streams that speak for the Peer end with it. */
212
+ readonly signal: AbortSignal;
213
+ /** Whether the Peer may open a forwarded-event stream; this does not grant business permissions. */
214
+ readonly interactions: 'answer' | 'none';
178
215
  /**
179
216
  * Tear down every registration made through `ctx`.
180
217
  * @returns settles once the scope has quiesced; racing calls share one completion.
181
218
  */
182
219
  dispose(): Promise<void>;
183
220
  }
221
+ /** Carrier capacity for buffered uplink frames of one logical stream. */
222
+ interface RemoteUplinkWindow {
223
+ /** Maximum complete encoded frame bytes waiting for the Host consumer. */
224
+ readonly maxBytes: number;
225
+ /** UTF-8 envelope bytes added to a compact JSON item with a present value field. */
226
+ readonly frameOverheadBytes: number;
227
+ }
184
228
  /**
185
229
  * The context of one Remote call, reachable inside the receiving method as
186
230
  * `this.ctx.invocation`. The Gateway derives the receiver from a Context that
@@ -194,10 +238,12 @@ interface RemoteInvocation {
194
238
  };
195
239
  /** Cordis service key of the receiving Service. */
196
240
  readonly service: string;
197
- /** Peer the call speaks for; an in-process carrier speaks for the operator. */
241
+ /** Peer the call speaks for; every carrier names it explicitly. */
198
242
  readonly peer: PeerScope;
199
243
  /** Carrier cancellation: Client cancel, socket close, or an uplink failure. */
200
244
  readonly signal: AbortSignal;
245
+ /** Carrier frame capacity; absent when the carrier imposes no encoded-frame inbox limit. */
246
+ readonly uplinkWindow?: RemoteUplinkWindow | undefined;
201
247
  /**
202
248
  * The Client's uplink items for this call. Available once; a second call
203
249
  * throws. With an uplink codec on the descriptor every item is decoded to
@@ -218,18 +264,33 @@ interface TypertRemoteContribution {
218
264
  /** Consumer-side invocation descriptors generated from that package. */
219
265
  readonly descriptors: readonly InvocationDescriptor[];
220
266
  }
267
+ /** Generated parser and optional lossless tool-schema projection of one Remote value. */
268
+ interface TypertRemoteValue<Value = unknown> {
269
+ /** Materialize the generated parser without loading the owning Service. */
270
+ readonly create: () => TypertSchema<Value>;
271
+ /** Source-owned value documentation, independent of tool projection support. */
272
+ readonly description?: string | undefined;
273
+ /** Present when the value is representable in the tool-schema subset without losing constraints; may be derived lazily. */
274
+ readonly jsonSchema?: Readonly<Record<string, unknown>> | undefined;
275
+ /** Projection failure for consumers that require JSON Schema; parsing remains available. */
276
+ readonly jsonSchemaError?: string | undefined;
277
+ }
221
278
  /**
222
279
  * Resolve one validated wire identity, synchronously or asynchronously.
223
280
  * @param id - validated wire identity.
224
281
  * @returns the Host object, or `undefined` when unavailable.
225
282
  */
226
283
  type TypertLookupResolver<Host = unknown, Wire = unknown> = (id: Wire) => Host | undefined | Promise<Host | undefined>;
284
+ /** Resource kinds whose identity type is a wire identity; every kind for a type-erased provider. */
285
+ type TypertResourceKindFor<Wire> = unknown extends Wire ? TypertResourceKind : { [Kind in TypertResourceKind]: [Wire] extends [TypertResourceId<TypertResourceMap[Kind]>] ? Kind : never; }[TypertResourceKind];
227
286
  /** Runtime provider for one declared Host object lookup. */
228
287
  interface TypertLookupProvider<Host = unknown, Wire = unknown> {
229
288
  /** Source parameter name recognized by the SRC weak parser. */
230
289
  readonly parameter: string;
231
290
  /** Wire field replacing the Host object parameter. */
232
291
  readonly wire: string;
292
+ /** Resource kind the wire identity names; a parameter of this lookup carries that resource. */
293
+ readonly resource?: TypertResourceKindFor<Wire>;
233
294
  /** Canonical Host type symbol used by strict generation. */
234
295
  readonly hostTypeSymbol: string;
235
296
  /** Canonical wire type symbol used by strict generation. */
@@ -260,6 +321,8 @@ interface TypertHostContextAdapter<Wire = unknown> {
260
321
  readonly wire: string;
261
322
  /** Canonical wire type symbol used by strict generation. */
262
323
  readonly wireTypeSymbol: string;
324
+ /** Resource kind the wire identity names; a call scoped to this Context carries that resource. */
325
+ readonly resource?: TypertResourceKindFor<Wire>;
263
326
  /**
264
327
  * Resolve a validated wire identity to a live Host Context.
265
328
  * @param id - validated wire identity.
@@ -286,7 +349,7 @@ interface TypertClientContextAdapter<Wire = unknown> {
286
349
  }
287
350
  /** Notification emitted after a Typert runtime registry changes. */
288
351
  interface TypertRegistryChange {
289
- readonly kind: 'local' | 'remote' | 'lookup' | 'host-context' | 'client-context';
352
+ readonly kind: 'local' | 'remote' | 'lookup' | 'host-context' | 'client-context' | 'resource';
290
353
  readonly key: string;
291
354
  }
292
355
  /** Listener for one Typert runtime registry. */
@@ -396,7 +459,7 @@ interface TypertContextRegistry {
396
459
  */
397
460
  registerClient<K extends StringKeyOf<TypertContextMap>>(key: K, adapter: TypertClientContextAdapter<TypertContextWire<TypertContextMap[K]>>): TypertDisposer;
398
461
  /**
399
- * Look up a Host Context adapter.
462
+ * Look up a Host Context adapter; a configured resolver keeps the adapter's declaration and `resource`.
400
463
  * @param key - descriptor Context key.
401
464
  * @returns the adapter, or `undefined` when absent.
402
465
  */
@@ -414,12 +477,49 @@ interface TypertContextRegistry {
414
477
  */
415
478
  subscribe(listener: TypertRegistryListener): TypertDisposer;
416
479
  }
480
+ /** Default wire field of one resource kind. */
481
+ interface TypertResourceDeclaration {
482
+ /** Top-level or first-object wire field holding one identity of the kind. */
483
+ readonly field: string;
484
+ }
485
+ /** One registered resource kind with its default wire field. */
486
+ interface TypertResourceEntry extends TypertResourceDeclaration {
487
+ /** Registered resource kind. */
488
+ readonly kind: string;
489
+ }
490
+ /** Runtime registry of resource kinds' default wire fields. */
491
+ interface TypertResourceRegistry {
492
+ /**
493
+ * Register one kind's default wire field for the calling fiber. Only the
494
+ * domain that owns the kind registers it.
495
+ * @param kind - merge-declared resource kind.
496
+ * @param declaration - the kind's default wire field.
497
+ * @returns disposer withdrawing the exact registration.
498
+ * @throws Error when the kind is already registered or is `global`, the built-in resource kind.
499
+ */
500
+ register(kind: TypertResourceKind, declaration: TypertResourceDeclaration): TypertDisposer;
501
+ /**
502
+ * Look up one kind's declaration.
503
+ * @param kind - resource kind.
504
+ * @returns the live declaration, or `undefined` when unregistered.
505
+ */
506
+ get(kind: string): TypertResourceDeclaration | undefined;
507
+ /** @returns a registration-order snapshot of registered kinds with their fields. */
508
+ entries(): readonly TypertResourceEntry[];
509
+ /**
510
+ * Observe later resource-kind changes.
511
+ * @param listener - synchronous contained observer.
512
+ * @returns disposer for this subscription.
513
+ */
514
+ subscribe(listener: TypertRegistryListener): TypertDisposer;
515
+ }
417
516
  /** Minimal Typert runtime consumed through dependency inversion. */
418
517
  interface TypertRegistryContract {
419
518
  readonly local: TypertLocalRegistry;
420
519
  readonly remotes: TypertRemoteRegistry;
421
520
  readonly lookups: TypertLookupRegistry;
422
521
  readonly contexts: TypertContextRegistry;
522
+ readonly resources: TypertResourceRegistry;
423
523
  }
424
524
  declare module '@deepseek-ai/cordis' {
425
525
  interface Context {
@@ -453,11 +553,318 @@ declare abstract class TypertRemoteService<out T = never> extends Service<T> {
453
553
  * Register the Service and bind the same key to Typert Gateway.
454
554
  * @param ctx - owning Cordis Context.
455
555
  * @param serviceKey - exact Cordis service key and default wire namespace.
456
- * @param options - optional distinct wire namespace.
556
+ * @param options - optional wire namespace.
457
557
  */
458
558
  protected constructor(ctx: Context, serviceKey: string, options?: TypertGatewayBindingOptions);
459
559
  }
460
560
  //#endregion
561
+ //#region ../../node_modules/@deepseek-ai/dsh-attachment/lib/types/error.d.ts
562
+ 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"];
563
+ /** Stable attachment failure codes used for protocol error routing. */
564
+ type AttachmentErrorCode = typeof ATTACHMENT_ERROR_CODES[number];
565
+ /**
566
+ * Stable failures suitable for host RPC error mapping.
567
+ *
568
+ * Deliberately re-implements the `HarnessError` shape instead of extending it:
569
+ * the base lives in `@deepseek-ai/dsh-llm`, which itself depends on this
570
+ * package (`ImageBlock` references `ImageAttachmentRef`), so sharing the base
571
+ * would create a dependency cycle. Consumers route on `code`, never on the
572
+ * prototype chain, so the shapes stay interchangeable at the wire boundary.
573
+ */
574
+ declare class AttachmentError extends Error {
575
+ /** Stable machine-routing failure code. */
576
+ readonly code: AttachmentErrorCode;
577
+ /**
578
+ * @param message - human-readable failure description without raw bytes or host paths.
579
+ * @param code - stable machine-routing code.
580
+ * @param options - optional chained cause.
581
+ */
582
+ constructor(message: string, code: AttachmentErrorCode, options?: ErrorOptions);
583
+ }
584
+ //#endregion
585
+ //#region ../../node_modules/@deepseek-ai/dsh-attachment/lib/types/brand.d.ts
586
+ /** Opaque content-addressed identifier for one immutable attachment object. */
587
+ type AttachmentId = Branded<'AttachmentId'>;
588
+ /**
589
+ * Brand a validated storage identifier.
590
+ * @param value - backend-produced opaque identifier.
591
+ * @returns the branded identifier.
592
+ */
593
+ declare function AttachmentId(value: string): AttachmentId;
594
+ /** Opaque deterministic identity for one request-image transformation. */
595
+ type ImageVariantId = Branded<'ImageVariantId'>;
596
+ /**
597
+ * Brand a validated request-image transformation identifier.
598
+ * @param value - attachment-provider-produced opaque identifier.
599
+ * @returns the branded identifier.
600
+ */
601
+ declare function ImageVariantId(value: string): ImageVariantId;
602
+ //#endregion
603
+ //#region ../../node_modules/@deepseek-ai/dsh-attachment/lib/types/types.d.ts
604
+ /** Raster image formats accepted by the version-one attachment path. */
605
+ type ImageMediaType = 'image/png' | 'image/jpeg' | 'image/webp' | 'image/gif';
606
+ /** Durable, serializable reference to one immutable normalized image. */
607
+ interface ImageAttachmentRef {
608
+ /** Opaque storage identifier; never a filesystem path or bearer URL. */
609
+ attachmentId: AttachmentId;
610
+ /** Media type verified from the stored bytes. */
611
+ mediaType: ImageMediaType;
612
+ /** Exact encoded byte length. */
613
+ bytes: number;
614
+ /** Intrinsic encoded width in pixels. */
615
+ width: number;
616
+ /** Intrinsic encoded height in pixels. */
617
+ height: number;
618
+ /** Optional display name stripped of local path information. */
619
+ name?: string;
620
+ /**
621
+ * Input dimensions after applying EXIF orientation and before normalization
622
+ * scaling. Present only when normalization reduced the image.
623
+ */
624
+ originalDimensions?: {
625
+ width: number;
626
+ height: number;
627
+ };
628
+ }
629
+ /**
630
+ * Durable, serializable reference to one verbatim stored file. Files are
631
+ * stored byte-for-byte with no normalization; `attachmentId` is the sha256
632
+ * digest of exactly those bytes.
633
+ */
634
+ interface FileAttachmentRef {
635
+ /** Opaque content-addressed storage identifier; never a filesystem path or bearer URL. */
636
+ attachmentId: AttachmentId;
637
+ /** Sanitized display filename, also the stored object's leaf name. */
638
+ name: string;
639
+ /** Exact byte length. */
640
+ bytes: number;
641
+ }
642
+ /** Base64-encoded file upload accompanying one wire request. */
643
+ interface EncodedFileAttachment {
644
+ /** Canonical base64 encoding of the file bytes. */
645
+ data: string;
646
+ /** Optional display name; it is never interpreted as a path. */
647
+ name?: string;
648
+ }
649
+ /** Request to durably commit one file verbatim. */
650
+ interface SaveFileAttachment {
651
+ data: Uint8Array;
652
+ /** Optional browser/provider display name; it is never interpreted as a path. */
653
+ name?: string;
654
+ }
655
+ /** Request to durably commit one file from bounded byte chunks. */
656
+ interface SaveFileStreamAttachment {
657
+ /** Exact file bytes in order; providers must not retain the complete sequence in memory. */
658
+ data: AsyncIterable<Uint8Array>;
659
+ /** Optional cancellation for source reads and storage writes. */
660
+ signal?: AbortSignal;
661
+ /** Optional browser/provider display name; it is never interpreted as a path. */
662
+ name?: string;
663
+ }
664
+ /** Deployment-resolved limits used by upload admission and request buffering. */
665
+ interface ImageAttachmentLimits {
666
+ maxImageBytes: number;
667
+ maxImagesPerMessage: number;
668
+ maxMessageImageBytes: number;
669
+ maxImagePixels: number;
670
+ /** Maximum intrinsic width and maximum intrinsic height in pixels for one image. */
671
+ maxImageDimension: number;
672
+ mediaTypes: readonly ImageMediaType[];
673
+ }
674
+ /**
675
+ * Browser-submitted prompt content accepted by Host prompt endpoints; the
676
+ * accepting Host promotes image parts to durable references through
677
+ * `ctx.attachments.admitPromptContent()` before any message is created, so a wire caller can
678
+ * never cite an attachment it did not upload.
679
+ */
680
+ type PromptContentPart = {
681
+ readonly type: 'text';
682
+ readonly text: string;
683
+ } | {
684
+ readonly type: 'image';
685
+ readonly mediaType: ImageMediaType;
686
+ readonly data: string;
687
+ readonly name?: string;
688
+ };
689
+ /** Host prompt content whose file receipts are resolved and whose image bytes await admission. */
690
+ type AttachmentAdmissionPart = PromptContentPart | {
691
+ readonly type: 'file';
692
+ readonly attachment: FileAttachmentRef;
693
+ };
694
+ /** Host-admitted prompt content with every attachment represented by its durable reference. */
695
+ type AdmittedPromptContentPart = {
696
+ readonly type: 'text';
697
+ readonly text: string;
698
+ } | {
699
+ readonly type: 'image';
700
+ readonly attachment: ImageAttachmentRef;
701
+ } | {
702
+ readonly type: 'file';
703
+ readonly attachment: FileAttachmentRef;
704
+ };
705
+ /** Request to validate and durably commit one image. */
706
+ interface SaveImageAttachment {
707
+ data: Uint8Array;
708
+ /** Caller-declared media type, checked against fully decoded bytes. */
709
+ mediaType: ImageMediaType;
710
+ /** Optional browser/provider display name; it is never interpreted as a path. */
711
+ name?: string;
712
+ }
713
+ /** Stored image bytes returned after reference and digest verification. */
714
+ interface StoredImageAttachment {
715
+ ref: ImageAttachmentRef;
716
+ data: Uint8Array;
717
+ }
718
+ /** Deterministic request-image target selected by one exact model route for one attachment. */
719
+ interface ImageRequestTarget {
720
+ /** Target width in pixels; a target above the source keeps the source width. */
721
+ width: number;
722
+ /** Target height in pixels; a target above the source keeps the source height. */
723
+ height: number;
724
+ /** Encoded-byte target before base64 expansion or Files API upload; the smallest quality-ladder output is kept when no quality fits. */
725
+ maxBytes: number;
726
+ }
727
+ /** Cached request version derived from one provider-independent normalized attachment. */
728
+ interface RequestImageAttachment {
729
+ /** Cache and upload-index key over the attachment id, policy, and fixed encoder parameters. */
730
+ variantId: ImageVariantId;
731
+ /** Durable normalized attachment from which this request version was derived. */
732
+ attachment: ImageAttachmentRef;
733
+ /** Encoded request bytes. */
734
+ data: Uint8Array;
735
+ mediaType: ImageMediaType;
736
+ bytes: number;
737
+ width: number;
738
+ height: number;
739
+ /** Provider-compatible sample depth proven after request encoding. */
740
+ depth: 'uchar';
741
+ /** Provider-compatible color space proven after request encoding. */
742
+ space: 'srgb';
743
+ /** Whether the encoded request version retains an alpha channel. */
744
+ hasAlpha: boolean;
745
+ }
746
+ //#endregion
747
+ //#region ../../node_modules/@deepseek-ai/dsh-attachment/lib/types/index.d.ts
748
+ declare module '@deepseek-ai/cordis' {
749
+ interface Context {
750
+ attachments: AttachmentStore;
751
+ }
752
+ }
753
+ /** Immutable binary attachment service. Implementations validate bytes before publishing a reference. */
754
+ declare abstract class AttachmentStore extends Service {
755
+ constructor(ctx: Context);
756
+ /** Deployment-resolved image policy used by authoritative and fast-path validation. */
757
+ abstract readonly imageLimits: ImageAttachmentLimits;
758
+ /**
759
+ * Validate one image without persisting it.
760
+ * Batch callers validate every member before saving any member.
761
+ * @param input - encoded bytes, declared media type, and optional display name.
762
+ * @returns completion after the encoded raster has been fully decoded.
763
+ */
764
+ abstract validateImage(input: SaveImageAttachment): Promise<void>;
765
+ /**
766
+ * Validate one ordered image batch before committing any member.
767
+ * Validation failures start no writes; storage failures return no partial
768
+ * references, although already published content-addressed objects may stay
769
+ * unreachable until a future retention policy collects them.
770
+ * @param inputs - encoded images in their owning message order.
771
+ * @returns durable references in the exact input order.
772
+ */
773
+ protected validateImageBatch(inputs: readonly SaveImageAttachment[]): void;
774
+ /**
775
+ * Validate and durably commit one ordered image batch.
776
+ * @param inputs - encoded images in owning-message order.
777
+ * @returns durable normalized attachment references in the same order after every member succeeds.
778
+ */
779
+ saveImages(inputs: readonly SaveImageAttachment[]): Promise<readonly ImageAttachmentRef[]>;
780
+ /**
781
+ * Admit one Host prompt and replace each uploaded image with its durable reference.
782
+ * Text and durable file references pass through unchanged. A prompt without image parts performs no storage operation.
783
+ * @param content - prompt parts in message order after file receipt resolution.
784
+ * @returns admitted prompt parts in the same order as `content`.
785
+ * @throws AttachmentError when the image batch is refused.
786
+ */
787
+ admitPromptContent(content: readonly AttachmentAdmissionPart[]): Promise<AdmittedPromptContentPart[]>;
788
+ /**
789
+ * Decode and durably commit one canonical base64 file upload.
790
+ * @param input - canonical base64 bytes and optional display name.
791
+ * @returns the durable content-addressed file reference.
792
+ * @throws AttachmentError when the encoding or storage operation is refused.
793
+ */
794
+ admitEncodedFile(input: EncodedFileAttachment): Promise<FileAttachmentRef>;
795
+ /**
796
+ * Identify a failure emitted by this attachment capability by its stable code.
797
+ * @param error - value caught from an attachment operation.
798
+ * @returns whether the value is an attachment failure.
799
+ */
800
+ isAttachmentError(error: unknown): error is AttachmentError;
801
+ /**
802
+ * Validate and durably commit one image before its owning session event is appended.
803
+ * The returned reference describes the persisted normalized image. When
804
+ * normalization reduces the raster, its `originalDimensions` records the
805
+ * orientation-applied input dimensions.
806
+ * @param input - encoded bytes, declared media type, and optional display name.
807
+ * @returns the durable content-addressed normalized image reference.
808
+ */
809
+ abstract saveImage(input: SaveImageAttachment): Promise<ImageAttachmentRef>;
810
+ /**
811
+ * Read one image and verify that bytes still match the recorded reference.
812
+ * @param ref - durable reference from the session log.
813
+ * @param signal - optional cancellation for backend read and verification work.
814
+ * @returns the verified bytes and normalized attachment reference.
815
+ * @throws the signal reason when aborted, or a storage error when verification fails.
816
+ */
817
+ abstract readImage(ref: ImageAttachmentRef, signal?: AbortSignal): Promise<StoredImageAttachment>;
818
+ /**
819
+ * Locate the provider-owned normalized object in the harness host filesystem.
820
+ * @param ref - durable normalized attachment reference.
821
+ * @returns an absolute host path, or undefined when this backend is not host-file-backed.
822
+ * @throws an AttachmentError when the durable reference is invalid.
823
+ */
824
+ imageHostPath(ref: ImageAttachmentRef): string | undefined;
825
+ /**
826
+ * Durably commit one file byte-for-byte before its owning session event is
827
+ * appended. Files carry no admission limits: any byte content and length is
828
+ * accepted, and the stored object is the exact submitted bytes. Backends
829
+ * without verbatim file storage keep this default rejection.
830
+ * @param input - exact bytes and optional display name.
831
+ * @returns the durable content-addressed file reference.
832
+ */
833
+ saveFile(input: SaveFileAttachment): Promise<FileAttachmentRef>;
834
+ /**
835
+ * Durably commit one file byte-for-byte from bounded chunks. Providers must
836
+ * apply backpressure and must not collect the complete file in memory.
837
+ * Backends without streamed verbatim storage keep this default rejection.
838
+ * @param input - ordered exact bytes, optional cancellation, and display name.
839
+ * @returns the durable content-addressed file reference.
840
+ */
841
+ saveFileStream(input: SaveFileStreamAttachment): Promise<FileAttachmentRef>;
842
+ /**
843
+ * Read and verify one verbatim stored file as bounded chunks. Providers must
844
+ * not collect the complete file in memory. Backends without verbatim file
845
+ * reads keep this default rejection.
846
+ * @param ref - durable reference from the session log.
847
+ * @param signal - optional cancellation for backend reads and verification work.
848
+ * @returns exact file bytes in order; integrity failures reject the iteration.
849
+ */
850
+ readFileStream(ref: FileAttachmentRef, signal?: AbortSignal): AsyncIterable<Uint8Array>;
851
+ /**
852
+ * Locate the verbatim stored file object in the harness host filesystem.
853
+ * @param ref - durable file reference.
854
+ * @returns an absolute host path, or undefined when this backend is not host-file-backed.
855
+ * @throws an AttachmentError when the durable reference is invalid.
856
+ */
857
+ fileHostPath(ref: FileAttachmentRef): string | undefined;
858
+ /**
859
+ * Generate or read one deterministic model-request version from the stored normalized image.
860
+ * @param ref - durable provider-independent normalized attachment reference.
861
+ * @param target - route-chosen dimensions and byte target; an unmet byte target yields the smallest ladder output.
862
+ * @param signal - optional cancellation.
863
+ * @returns request bytes and the cache/upload identity covering every transform input.
864
+ */
865
+ readImageRequest(ref: ImageAttachmentRef, target: ImageRequestTarget, signal?: AbortSignal): Promise<RequestImageAttachment>;
866
+ }
867
+ //#endregion
461
868
  //#region ../../node_modules/@deepseek-ai/dsh-llm/lib/types/brand.d.ts
462
869
  /** Stable identity carried by one message across inbox, log, and model-request boundaries. */
463
870
  type MessageId = Branded<'MessageId'>;
@@ -703,9 +1110,8 @@ interface ToolRemovalBlock {
703
1110
  }
704
1111
  /**
705
1112
  * Merge-extensible content blocks keyed by `type`. New core blocks must land
706
- * with adapter, UI, and compaction support. Developer tool-change blocks are
707
- * reserved for Session V4 persistence; providers and UI reject them until
708
- * their producers and consumers are implemented together.
1113
+ * with adapter, UI, and compaction support. Tool-change blocks belong to
1114
+ * developer messages; `projectToolUpdates` selects what each route receives.
709
1115
  */
710
1116
  interface ContentBlockMap {
711
1117
  'text': TextBlock;
@@ -838,9 +1244,26 @@ interface LlmConfigurableProvider {
838
1244
  * from outside.
839
1245
  */
840
1246
  declared?: boolean;
1247
+ /**
1248
+ * Route endpoint the adapter uses when the profile sets no `baseURL`; the
1249
+ * adapter may still send an individual model to that model's own endpoint.
1250
+ * Absent when the route has no fixed endpoint.
1251
+ */
1252
+ defaultBaseURL?: string;
1253
+ /** Environment variables used to construct a provider endpoint; absent when none are reported. */
1254
+ baseURLEnv?: readonly string[];
1255
+ /** Authentication the adapter performs when the profile names no credential reference; absent when it reports none. */
1256
+ nativeAuth?: LlmNativeAuth;
841
1257
  /** Configuration diagnostic for repair; unaffected models may remain serviceable. */
842
1258
  error?: string;
843
1259
  }
1260
+ /** Authentication a provider route performs without a credential reference in its profile. */
1261
+ interface LlmNativeAuth {
1262
+ /** Environment variables the route's authentication reads, in lookup order; empty when it reads none. */
1263
+ env: readonly string[];
1264
+ /** Whether a stored OAuth sign-in can authenticate the route. */
1265
+ oauth: boolean;
1266
+ }
844
1267
  /**
845
1268
  * One interrogation of a provider endpoint that configuration has not stored
846
1269
  * yet. Configuration surfaces send the draft a user is still editing, so the
@@ -920,7 +1343,7 @@ interface LlmReasoningEffortInfo {
920
1343
  }
921
1344
  /** Selectable reasoning efforts for one exact provider/model route. */
922
1345
  interface LlmModelReasoningInfo {
923
- /** Supported efforts in adapter-preferred display order. */
1346
+ /** Supported efforts from least to greatest selectable reasoning effort, not predicted token use or latency. */
924
1347
  efforts: readonly LlmReasoningEffortInfo[];
925
1348
  /**
926
1349
  * Adapter-configured default materialized into requests when callers omit
@@ -935,6 +1358,16 @@ interface LlmModelReasoningInfo {
935
1358
  * can follow the cached history instead of rewriting message 0.
936
1359
  */
937
1360
  type SystemPromptUpdate = 'in-history';
1361
+ /**
1362
+ * How a model accepts native tool declarations that change mid-conversation.
1363
+ * `'addition-only'`: the model reads a `tool-addition` block in a later
1364
+ * developer message as activating a tool declared with `deferLoading`, so an
1365
+ * added tool follows the cached history instead of rewriting the declaration
1366
+ * list. `'in-history'`: the model additionally reads `tool-removal` blocks,
1367
+ * so a removed tool keeps its declaration and the removal follows the history.
1368
+ * Absent means every request declares the complete current tool list.
1369
+ */
1370
+ type ToolUpdate = 'in-history' | 'addition-only';
938
1371
  /** Exact-route model metadata resolved by its owning adapter. */
939
1372
  interface LlmResolvedModelInfo extends LlmModelInfo {
940
1373
  /** Provider-owned context capacity when known. */
@@ -945,6 +1378,8 @@ interface LlmResolvedModelInfo extends LlmModelInfo {
945
1378
  reasoning?: LlmModelReasoningInfo;
946
1379
  /** Declared mid-conversation system prompt handling; absent means only a leading system message is read. */
947
1380
  systemPromptUpdate?: SystemPromptUpdate;
1381
+ /** Declared mid-conversation tool declaration handling; absent means every request declares the complete tool list. */
1382
+ toolUpdate?: ToolUpdate;
948
1383
  }
949
1384
  /**
950
1385
  * Adapter-private lossless-JSON state for replaying a successful response,
@@ -1033,6 +1468,18 @@ interface RequestUserInput {
1033
1468
  }
1034
1469
  /** A durable conversation message or a user input used only for one request. */
1035
1470
  type RequestMessage = Message | RequestUserInput;
1471
+ /** Logged tool declarations and update identities since the last declaration reset. */
1472
+ interface ToolHistory {
1473
+ /** Complete active declarations at the start of this history. */
1474
+ readonly tools: readonly ToolSchema[];
1475
+ /** Ordered developer messages, with additions resolved from their historical headers. */
1476
+ readonly updates: readonly {
1477
+ /** Identity used to locate this update in the derived request history. */
1478
+ readonly messageId: MessageId;
1479
+ /** Added definitions resolved from the event's referenced request header. */
1480
+ readonly additions: readonly ToolSchema[];
1481
+ }[];
1482
+ }
1036
1483
  /** A single model request, fully assembled. */
1037
1484
  interface GenerateOptions {
1038
1485
  /** Registered provider route selecting the adapter instance. */
@@ -1054,6 +1501,8 @@ interface GenerateOptions {
1054
1501
  system?: string;
1055
1502
  /** Tool schemas (adapters map to the provider's `tools` field). */
1056
1503
  tools?: ToolSchema[];
1504
+ /** Session-folded tool history used for route projection; omission sends complete declarations without tool updates. */
1505
+ toolHistory?: ToolHistory;
1057
1506
  temperature?: number;
1058
1507
  maxTokens?: number;
1059
1508
  /**
@@ -1070,8 +1519,8 @@ interface GenerateOptions {
1070
1519
  sessionId?: Branded<'SessionId'>;
1071
1520
  /**
1072
1521
  * Provider-neutral classification for an auxiliary model call. Adapters may
1073
- * map the purpose to model-hidden transport metadata or purpose-specific
1074
- * generation policy. Ordinary conversation requests leave it unset.
1522
+ * map the purpose to model-hidden transport metadata. Ordinary conversation
1523
+ * requests leave it unset.
1075
1524
  */
1076
1525
  purpose?: 'compaction' | 'session-title';
1077
1526
  }
@@ -1407,20 +1856,33 @@ interface ResolvedAlwaysRetryPolicy extends ResolvedRetryBackoff {
1407
1856
  type ResolvedRetryPolicy = ResolvedNormalRetryPolicy | ResolvedAlwaysRetryPolicy;
1408
1857
  //#endregion
1409
1858
  //#region ../../node_modules/@deepseek-ai/dsh-llm/lib/types/call-config.d.ts
1859
+ /** Concrete generation settings; omitted controls use the selected route's defaults. */
1860
+ interface LlmCallControls {
1861
+ reasoningEffort?: ReasoningEffortId;
1862
+ temperature?: number;
1863
+ maxTokens?: number;
1864
+ stop?: string[];
1865
+ }
1410
1866
  /**
1411
1867
  * Provider, model, reasoning effort, and sampling scalars of one conversation's
1412
1868
  * requests. Every field maps 1:1 onto the same-named `GenerateOptions` field;
1413
1869
  * the loop builds requests from the logged header rather than accepting these
1414
1870
  * per call.
1415
1871
  */
1416
- interface LlmCallConfig {
1872
+ interface LlmCallConfig extends LlmCallControls {
1417
1873
  provider: string;
1418
1874
  model: string;
1419
- reasoningEffort?: ReasoningEffortId;
1420
- temperature?: number;
1421
- maxTokens?: number;
1422
- stop?: string[];
1423
1875
  }
1876
+ /**
1877
+ * Synchronous, pure configuration of one call before defaults and validation.
1878
+ * Compose functions in the desired order; later writes replace earlier ones.
1879
+ * The returned controls cannot change the captured route. Errors reject
1880
+ * preparation before dispatch; only the resolved configuration is recordable.
1881
+ * @param controls - detached, deeply frozen proposed controls, without defaults.
1882
+ * @param model - detached, deeply frozen metadata from the captured adapter generation.
1883
+ * @returns concrete controls; omitted fields receive the route's defaults.
1884
+ */
1885
+ type ConfigureCall = (controls: Readonly<LlmCallControls>, model: Readonly<LlmResolvedModelInfo>) => LlmCallControls;
1424
1886
  /**
1425
1887
  * Effective config fields supplied by exact-model adapter resolution rather
1426
1888
  * than by the caller's request proposal.
@@ -1463,6 +1925,8 @@ interface PreparedLlmCall {
1463
1925
  readonly inputModalities?: readonly ModelModality[];
1464
1926
  /** Exact model system prompt update mode captured with the adapter dispatch generation. */
1465
1927
  readonly systemPromptUpdate?: SystemPromptUpdate;
1928
+ /** Exact model tool update mode captured with the adapter dispatch generation. */
1929
+ readonly toolUpdate?: ToolUpdate;
1466
1930
  /** Config fields materialized by the captured adapter rather than proposed by the caller. */
1467
1931
  readonly adapterDefaults: LlmCallConfigAdapterDefaults;
1468
1932
  /**
@@ -1510,10 +1974,20 @@ declare abstract class LlmAdapter {
1510
1974
  * @returns route-owned image pricing, or `undefined` when the route declares none.
1511
1975
  */
1512
1976
  imageRequestPricing(_provider: string, _model: string): LlmImageRequestPricing | undefined;
1977
+ /**
1978
+ * Resolve the image dimensions and byte target this adapter sends to the model.
1979
+ * The default preserves normalized images; adapters that resize must override it.
1980
+ * @param _provider - registered provider route.
1981
+ * @param _model - exact model id.
1982
+ * @param image - normalized image whose request projection is being resolved.
1983
+ * @returns the same target used by request serialization, before provider-internal processing.
1984
+ */
1985
+ imageRequestTarget(_provider: string, _model: string, image: ImageAttachmentRef): ImageRequestTarget;
1513
1986
  /**
1514
1987
  * List models this adapter can currently advertise for one owned provider.
1515
- * The result is advisory: an adapter may accept unlisted model ids, and
1516
- * consumers must not turn absence into request rejection.
1988
+ * Core routing accepts unlisted model ids; catalog-driven entry points such
1989
+ * as the GUI may require membership. Adapters used there must advertise
1990
+ * their available models; the base empty catalog offers no GUI selection.
1517
1991
  * @param _provider - one provider route owned by this adapter.
1518
1992
  * @returns discoverable models in adapter-preferred order.
1519
1993
  */
@@ -1690,6 +2164,14 @@ declare class LlmRuntime extends TypertRemoteService {
1690
2164
  * @returns the owning adapter's image pricing for the route, when declared.
1691
2165
  */
1692
2166
  imageRequestPricing(provider: string, model: string): LlmImageRequestPricing | undefined;
2167
+ /**
2168
+ * Resolve the image projection for an exact registered model route.
2169
+ * @param provider - registered provider route.
2170
+ * @param model - exact model id.
2171
+ * @param image - normalized image reference.
2172
+ * @returns dimensions and byte target used by the adapter's request serializer.
2173
+ */
2174
+ imageRequestTarget(provider: string, model: string, image: ImageAttachmentRef): ImageRequestTarget;
1693
2175
  /**
1694
2176
  * Resolve the exact text one durable file occurrence contributes to every
1695
2177
  * provider request in the current execution environment.
@@ -1701,7 +2183,8 @@ declare class LlmRuntime extends TypertRemoteService {
1701
2183
  private detachedModalities;
1702
2184
  /**
1703
2185
  * Discover models advertised by one registered provider. Catalog membership
1704
- * is advisory and never changes routing or request validation.
2186
+ * does not constrain core routing. Catalog-driven entry points may restrict
2187
+ * selection and submission to the advertised models.
1705
2188
  * @param provider - registered provider route to inspect.
1706
2189
  * @returns detached model metadata in adapter-preferred order.
1707
2190
  */
@@ -1737,11 +2220,15 @@ declare class LlmRuntime extends TypertRemoteService {
1737
2220
  * Resolve one call under its current adapter registration. The returned
1738
2221
  * one-shot handle keeps that registration across header logging and dispatch,
1739
2222
  * so HMR cannot combine one adapter's capability result with another adapter.
1740
- * @param config - provider/model route and optional request controls.
2223
+ * An optional synchronous callback selects concrete controls using captured
2224
+ * model metadata. Defaults and validation apply to its result. Callback
2225
+ * failures and cancellation reject preparation before dispatch.
2226
+ * @param config - provider/model route and optional concrete request controls.
1741
2227
  * @param signal - optional cancellation for adapter-owned capability lookup.
2228
+ * @param configure - pure control selection, called once before defaults and validation.
1742
2229
  * @returns a prepared config and its registration-bound stream entry point.
1743
2230
  */
1744
- prepareCall(config: LlmCallConfig, signal?: AbortSignal): Promise<PreparedLlmCall>;
2231
+ prepareCall(config: LlmCallConfig, signal?: AbortSignal, configure?: ConfigureCall): Promise<PreparedLlmCall>;
1745
2232
  private registration;
1746
2233
  /** Remove replay state whose historical route is owned by another adapter. */
1747
2234
  private forAdapter;