@cosmicdrift/kumiko-types 0.235.2 → 0.235.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cosmicdrift/kumiko-types",
3
- "version": "0.235.2",
3
+ "version": "0.235.4",
4
4
  "description": "Framework-Type-Definitions für Kumiko — FeatureDefinition, BootCheck-Types und die reinen Engine-Types. Erlaubt Downstream-Konsumenten, gegen die Type-Contracts zu bauen, ohne das ganze Framework-Package zu importieren. Enthaelt keine identitaets-sensitiven Runtime-Werte mehr (Error-Klassen leben seit #1629 in kumiko-framework, Brand-Symbole nutzen Symbol.for) und ist deshalb eine plain dependency, keine peerDependency.",
5
5
  "license": "BUSL-1.1",
6
6
  "author": "Marc Frost <marc@cosmicdriftgamestudio.com>",
@@ -233,6 +233,10 @@
233
233
  "./snapshot-types": {
234
234
  "types": "./src/snapshot-types.ts",
235
235
  "default": "./src/snapshot-types.ts"
236
+ },
237
+ "./agent-exposure": {
238
+ "types": "./src/agent-exposure.ts",
239
+ "default": "./src/agent-exposure.ts"
236
240
  }
237
241
  },
238
242
  "devDependencies": {
@@ -0,0 +1,14 @@
1
+ import type { AgentExposure, AgentHandlerHints } from "./handlers";
2
+
3
+ /** Fail-closed: a handler without a `description` stays invisible to the agent
4
+ * unless it opts in explicitly. `kind` is a parameter because write and query
5
+ * handler definitions are structurally indistinguishable at runtime. */
6
+ export function resolveAgentExposure(
7
+ def: { readonly description?: string; readonly agent?: AgentHandlerHints },
8
+ kind: "query" | "write",
9
+ ): AgentExposure {
10
+ return {
11
+ expose: def.agent?.expose ?? def.description !== undefined,
12
+ risk: def.agent?.risk ?? (kind === "query" ? "low" : "mid"),
13
+ };
14
+ }
@@ -2,6 +2,7 @@ import type { ZodType, z } from "zod";
2
2
  import type { KumikoEventTypeMap } from "./event-type-map";
3
3
  import type {
4
4
  AccessRule,
5
+ AgentHandlerHints,
5
6
  HandlerContext,
6
7
  QueryEvent,
7
8
  RateLimitOption,
@@ -34,6 +35,8 @@ export type WriteHandlerDefinition<
34
35
  readonly name: TName;
35
36
  readonly schema: TSchema;
36
37
  readonly access?: AccessRule;
38
+ readonly description?: string;
39
+ readonly agent?: AgentHandlerHints;
37
40
  readonly unsafeSkipTransitionGuard?: boolean;
38
41
  readonly rateLimit?: RateLimitOption;
39
42
  readonly handler: (
@@ -59,6 +62,8 @@ export type WriteHandlerInput<
59
62
  readonly name: TName;
60
63
  readonly schema: TSchema;
61
64
  readonly access?: AccessRule;
65
+ readonly description?: string;
66
+ readonly agent?: AgentHandlerHints;
62
67
  readonly unsafeSkipTransitionGuard?: boolean;
63
68
  readonly rateLimit?: RateLimitOption;
64
69
  } & (
@@ -86,6 +91,8 @@ export type QueryHandlerDefinition<
86
91
  readonly name: TName;
87
92
  readonly schema: TSchema;
88
93
  readonly access?: AccessRule;
94
+ readonly description?: string;
95
+ readonly agent?: AgentHandlerHints;
89
96
  readonly rateLimit?: RateLimitOption;
90
97
  readonly handler: (
91
98
  query: QueryEvent<z.infer<TSchema>>,
package/src/feature.ts CHANGED
@@ -27,6 +27,7 @@ import type { EntityTableMeta } from "./entity-table-meta-types";
27
27
  import type { EntityDefinition } from "./fields";
28
28
  import type {
29
29
  AccessRule,
30
+ AgentHandlerHints,
30
31
  AuthClaimsFn,
31
32
  AuthClaimsHookDef,
32
33
  ClaimKeyDefinition,
@@ -453,7 +454,12 @@ export type FeatureRegistrar<TFeature extends string = string> = {
453
454
  name: string,
454
455
  schema: TSchema,
455
456
  handler: WriteHandlerFn<z.infer<TSchema>>,
456
- options?: { access?: AccessRule; rateLimit?: RateLimitOption },
457
+ options?: {
458
+ access?: AccessRule;
459
+ rateLimit?: RateLimitOption;
460
+ description?: string;
461
+ agent?: AgentHandlerHints;
462
+ },
457
463
  ): HandlerRef;
458
464
 
459
465
  queryHandler<TName extends string, TSchema extends ZodType>(
@@ -463,7 +469,13 @@ export type FeatureRegistrar<TFeature extends string = string> = {
463
469
  name: string,
464
470
  schema: TSchema,
465
471
  handler: QueryHandlerFn<z.infer<TSchema>>,
466
- options?: { access?: AccessRule; rateLimit?: RateLimitOption; outputSchema?: ZodType },
472
+ options?: {
473
+ access?: AccessRule;
474
+ rateLimit?: RateLimitOption;
475
+ outputSchema?: ZodType;
476
+ description?: string;
477
+ agent?: AgentHandlerHints;
478
+ },
467
479
  ): HandlerRef;
468
480
 
469
481
  streamHandler<TName extends string, TSchema extends ZodType>(
@@ -865,6 +877,7 @@ export type Registry = {
865
877
  getWriteHandler(name: string): WriteHandlerDef | undefined;
866
878
  getQueryHandler(name: string): QueryHandlerDef | undefined;
867
879
  getAllQueryHandlers(): ReadonlyMap<string, QueryHandlerDef>;
880
+ getAllWriteHandlers(): ReadonlyMap<string, WriteHandlerDef>;
868
881
  getStreamHandler(name: string): StreamHandlerDef | undefined;
869
882
  getAllStreamHandlers(): ReadonlyMap<string, StreamHandlerDef>;
870
883
  getSearchableFields(entityName: string): readonly string[];
package/src/fields.ts CHANGED
@@ -237,6 +237,9 @@ export type RetentionDef = {
237
237
 
238
238
  export type TextFieldDef = {
239
239
  readonly type: "text";
240
+ /** Optional free-text semantics for the AI agent manifest — never rendered;
241
+ * the i18n label is what users see. */
242
+ readonly description?: string;
240
243
  readonly maxLength?: number;
241
244
  readonly required?: boolean;
242
245
  readonly searchable?: boolean;
@@ -279,6 +282,7 @@ export type TextFieldDef = {
279
282
  */
280
283
  export type LongTextFieldDef = {
281
284
  readonly type: "longText";
285
+ readonly description?: string;
282
286
  /** Optionale soft-Cap. Default unbounded (= Postgres-text-limit, 1 GB).
283
287
  * Nützlich für defensive Caps wie 1 MB damit ein verirrter Browser-
284
288
  * Paste nicht die DB sprengt. */
@@ -293,6 +297,7 @@ export type LongTextFieldDef = {
293
297
 
294
298
  export type BooleanFieldDef = {
295
299
  readonly type: "boolean";
300
+ readonly description?: string;
296
301
  readonly required?: boolean;
297
302
  readonly sortable?: boolean;
298
303
  readonly filterable?: boolean;
@@ -303,6 +308,7 @@ export type BooleanFieldDef = {
303
308
 
304
309
  export type SelectFieldDef<TOptions extends readonly string[] = readonly string[]> = {
305
310
  readonly type: "select";
311
+ readonly description?: string;
306
312
  readonly options: TOptions;
307
313
  readonly required?: boolean;
308
314
  readonly sortable?: boolean;
@@ -327,6 +333,7 @@ export type SelectFieldDef<TOptions extends readonly string[] = readonly string[
327
333
  // rejected Duplikate erst wenn Bedarf da ist.
328
334
  export type MultiSelectFieldDef<TOptions extends readonly string[] = readonly string[]> = {
329
335
  readonly type: "multiSelect";
336
+ readonly description?: string;
330
337
  readonly options: TOptions;
331
338
  readonly required?: boolean;
332
339
  readonly filterable?: boolean;
@@ -359,6 +366,7 @@ export type MultiSelectFieldDef<TOptions extends readonly string[] = readonly st
359
366
  */
360
367
  export type NumberFieldDef = {
361
368
  readonly type: "number";
369
+ readonly description?: string;
362
370
  readonly required?: boolean;
363
371
  readonly sortable?: boolean;
364
372
  readonly filterable?: boolean;
@@ -390,6 +398,7 @@ export type NumberFieldDef = {
390
398
  */
391
399
  export type BigIntFieldDef = {
392
400
  readonly type: "bigInt";
401
+ readonly description?: string;
393
402
  readonly required?: boolean;
394
403
  readonly sortable?: boolean;
395
404
  readonly filterable?: boolean;
@@ -412,6 +421,7 @@ export type BigIntFieldDef = {
412
421
  */
413
422
  export type DecimalFieldDef = {
414
423
  readonly type: "decimal";
424
+ readonly description?: string;
415
425
  readonly precision: number;
416
426
  readonly scale: number;
417
427
  readonly required?: boolean;
@@ -424,6 +434,7 @@ export type DecimalFieldDef = {
424
434
 
425
435
  export type MoneyFieldDef = {
426
436
  readonly type: "money";
437
+ readonly description?: string;
427
438
  readonly required?: boolean;
428
439
  readonly sortable?: boolean;
429
440
  readonly filterable?: boolean;
@@ -446,6 +457,7 @@ export type MoneyFieldDef = {
446
457
  // ist ein menschlich-lesbares Feld wie "name", "title", "email".
447
458
  export type ReferenceFieldDef = {
448
459
  readonly type: "reference";
460
+ readonly description?: string;
449
461
  readonly entity: string;
450
462
  readonly required?: boolean;
451
463
  readonly filterable?: boolean;
@@ -528,6 +540,7 @@ export type EmbeddedDerivedCellDef = {
528
540
 
529
541
  export type EmbeddedFieldDef = {
530
542
  readonly type: "embedded";
543
+ readonly description?: string;
531
544
  readonly required?: boolean;
532
545
  readonly sensitive?: boolean;
533
546
  readonly schema: Readonly<Record<string, EmbeddedSubFieldDef>>;
@@ -574,6 +587,7 @@ export type EmbeddedFieldDef = {
574
587
  // + NOT NULL, identisch zu embedded.
575
588
  export type JsonbFieldDef = {
576
589
  readonly type: "jsonb";
590
+ readonly description?: string;
577
591
  readonly sensitive?: boolean;
578
592
  readonly access?: FieldAccess;
579
593
  } & ResolvedPiiFlags;
@@ -587,6 +601,7 @@ export type JsonbFieldDef = {
587
601
  // Siehe docs/plans/architecture/timezones.md
588
602
  export type DateFieldDef = {
589
603
  readonly type: "date";
604
+ readonly description?: string;
590
605
  readonly required?: boolean;
591
606
  readonly sortable?: boolean;
592
607
  readonly filterable?: boolean;
@@ -615,6 +630,7 @@ export type DateFieldDef = {
615
630
  // Feld statt eines lose verdrahteten Pairs (siehe LocatedTimestampFieldDef).
616
631
  export type TimestampFieldDef = {
617
632
  readonly type: "timestamp";
633
+ readonly description?: string;
618
634
  readonly required?: boolean;
619
635
  readonly sortable?: boolean;
620
636
  readonly filterable?: boolean;
@@ -645,6 +661,7 @@ export type TimestampFieldDef = {
645
661
  // (TEXT-Spalte) korrekt sind und der `locatedBy`-Marker eindeutig auflöst.
646
662
  export type TzFieldDef = {
647
663
  readonly type: "tz";
664
+ readonly description?: string;
648
665
  readonly required?: boolean;
649
666
  readonly sensitive?: boolean;
650
667
  readonly access?: FieldAccess;
@@ -670,6 +687,7 @@ export type TzFieldDef = {
670
687
  // Siehe docs/plans/architecture/timezones.md.
671
688
  export type LocatedTimestampFieldDef = {
672
689
  readonly type: "locatedTimestamp";
690
+ readonly description?: string;
673
691
  readonly required?: boolean;
674
692
  readonly sortable?: boolean;
675
693
  readonly filterable?: boolean;
@@ -687,6 +705,7 @@ export type LocatedTimestampFieldDef = {
687
705
 
688
706
  export type FileFieldDef = {
689
707
  readonly type: "file";
708
+ readonly description?: string;
690
709
  readonly required?: boolean;
691
710
  readonly maxSize?: string;
692
711
  readonly accept?: readonly string[];
@@ -695,6 +714,7 @@ export type FileFieldDef = {
695
714
 
696
715
  export type ImageFieldDef = {
697
716
  readonly type: "image";
717
+ readonly description?: string;
698
718
  readonly required?: boolean;
699
719
  readonly maxSize?: string;
700
720
  readonly accept?: readonly string[];
@@ -710,6 +730,7 @@ export type ImageFieldDef = {
710
730
 
711
731
  export type FilesFieldDef = {
712
732
  readonly type: "files";
733
+ readonly description?: string;
713
734
  readonly maxSize?: string;
714
735
  readonly accept?: readonly string[];
715
736
  readonly maxCount?: number;
@@ -718,6 +739,7 @@ export type FilesFieldDef = {
718
739
 
719
740
  export type ImagesFieldDef = {
720
741
  readonly type: "images";
742
+ readonly description?: string;
721
743
  readonly maxSize?: string;
722
744
  readonly accept?: readonly string[];
723
745
  readonly maxCount?: number;
@@ -921,4 +943,6 @@ export type EntityDefinition<F extends FieldsMap = FieldsMap> = {
921
943
  * nameable as a column in a declarative `entityList`. See DerivedFieldDef.
922
944
  */
923
945
  readonly derivedFields?: DerivedFieldsMap;
946
+ /** Optional free-text semantics for the AI agent manifest — see TextFieldDef.description. */
947
+ readonly description?: string;
924
948
  };
package/src/handlers.ts CHANGED
@@ -929,11 +929,27 @@ export type RateLimitOption = {
929
929
  readonly cost?: number;
930
930
  };
931
931
 
932
+ export type AgentRisk = "low" | "mid" | "high";
933
+
934
+ /** Per-handler hints for the AI-agent manifest. `expose` overrides the
935
+ * default derived from `description`; `risk` overrides the per-kind default. */
936
+ export type AgentHandlerHints = {
937
+ readonly expose?: boolean;
938
+ readonly risk?: AgentRisk;
939
+ };
940
+
941
+ export type AgentExposure = {
942
+ readonly expose: boolean;
943
+ readonly risk: AgentRisk;
944
+ };
945
+
932
946
  export type WriteHandlerDef = {
933
947
  readonly name: string;
934
948
  readonly schema: ZodType;
935
949
  readonly handler: WriteHandlerFn;
936
950
  readonly access?: AccessRule;
951
+ readonly description?: string;
952
+ readonly agent?: AgentHandlerHints;
937
953
  readonly unsafeSkipTransitionGuard?: boolean;
938
954
  readonly rateLimit?: RateLimitOption;
939
955
  // Set when the author wrote a `perform: stepsPipeline(...)` block. Boot-
@@ -951,6 +967,8 @@ export type QueryHandlerDef = {
951
967
  readonly schema: ZodType;
952
968
  readonly handler: QueryHandlerFn;
953
969
  readonly access?: AccessRule;
970
+ readonly description?: string;
971
+ readonly agent?: AgentHandlerHints;
954
972
  readonly rateLimit?: RateLimitOption;
955
973
  /** Zod schema of the handler's actual return value — the paged envelope
956
974
  * `{ rows, nextCursor, total? }` for a `definePagedQueryHandler`, or the
package/src/screen.ts CHANGED
@@ -326,6 +326,7 @@ export type EntityListScreenDefinition = {
326
326
  readonly type: "entityList";
327
327
  readonly nav?: ScreenNavSugar;
328
328
  readonly detailFor?: string;
329
+ readonly description?: string;
329
330
  readonly entity: string;
330
331
  readonly columns: readonly ListColumnSpec[];
331
332
  // Row renderer (Desktop) — when omitted, renderer draws the default table
@@ -404,6 +405,7 @@ export type ProjectionListScreenDefinition = {
404
405
  readonly type: "projectionList";
405
406
  readonly nav?: ScreenNavSugar;
406
407
  readonly detailFor?: string;
408
+ readonly description?: string;
407
409
  readonly query: string;
408
410
  readonly columns: readonly ListColumnSpec[];
409
411
  readonly rowRenderer?: PlatformComponent;
@@ -464,6 +466,7 @@ export type ProjectionDetailScreenDefinition = {
464
466
  readonly type: "projectionDetail";
465
467
  readonly nav?: ScreenNavSugar;
466
468
  readonly detailFor?: string;
469
+ readonly description?: string;
467
470
  readonly query: string;
468
471
  /** Query-payload key for the row-id. Default "id". */
469
472
  readonly idParam?: string;
@@ -632,6 +635,7 @@ export type DashboardScreenDefinition = {
632
635
  readonly type: "dashboard";
633
636
  readonly nav?: ScreenNavSugar;
634
637
  readonly detailFor?: string;
638
+ readonly description?: string;
635
639
  readonly panels: readonly DashboardPanelDefinition[];
636
640
  readonly filter?: DashboardFilterDefinition;
637
641
  readonly slots?: ScreenSlots;
@@ -767,6 +771,7 @@ export type EntityEditScreenDefinition = {
767
771
  readonly type: "entityEdit";
768
772
  readonly nav?: ScreenNavSugar;
769
773
  readonly detailFor?: string;
774
+ readonly description?: string;
770
775
  readonly entity: string;
771
776
  readonly layout: EditLayout;
772
777
  /** Optionaler i18n-Key (oder Roh-String) für den Submit-Button. Default
@@ -846,6 +851,7 @@ export type ActionFormScreenDefinition = {
846
851
  readonly type: "actionForm";
847
852
  readonly nav?: ScreenNavSugar;
848
853
  readonly detailFor?: string;
854
+ readonly description?: string;
849
855
  /** Write-Handler-QN der bei Submit gerufen wird. Form-Object landet
850
856
  * 1:1 als payload — Handler-Schema (Zod) validiert weiter. */
851
857
  readonly handler: string;
@@ -901,6 +907,7 @@ export type CustomScreenDefinition = {
901
907
  readonly type: "custom";
902
908
  readonly nav?: ScreenNavSugar;
903
909
  readonly detailFor?: string;
910
+ readonly description?: string;
904
911
  readonly renderer: PlatformComponent;
905
912
  readonly routes?: readonly CustomScreenRoute[];
906
913
  /** Parent list screen for breadcrumb when this detail is not in nav. */
@@ -956,6 +963,7 @@ export type ConfigEditScreenDefinition = {
956
963
  readonly type: "configEdit";
957
964
  readonly nav?: ScreenNavSugar;
958
965
  readonly detailFor?: string;
966
+ readonly description?: string;
959
967
  /** scope für config:write:set Calls. Muss zur Scope-Deklaration der
960
968
  * in `configKeys` referenzierten Keys passen — Boot-Validator
961
969
  * prüft das gegen die Registry. */
@@ -998,6 +1006,7 @@ export type SecretsEditScreenDefinition = {
998
1006
  readonly type: "secretsEdit";
999
1007
  readonly nav?: ScreenNavSugar;
1000
1008
  readonly detailFor?: string;
1009
+ readonly description?: string;
1001
1010
  /** field id -> qualified secret name (`<feature>:secret:<kebab>`). */
1002
1011
  readonly secretKeys: Readonly<Record<string, string>>;
1003
1012
  /** field id -> i18n key for the label. */
@@ -1035,10 +1044,10 @@ export type ScreenNavSugar = {
1035
1044
  readonly order?: number;
1036
1045
  };
1037
1046
 
1038
- // `nav`/`detailFor` live directly on every variant (not only via this
1047
+ // `nav`/`detailFor`/`description` live directly on every variant (not only via this
1039
1048
  // union) so a screen typed as its own concrete kind — e.g. `const screen:
1040
1049
  // CustomScreenDefinition = {...}` in a module split out of `feature.ts` —
1041
- // still accepts both fields; a union-only intersection drops them the
1050
+ // still accepts all three; a union-only intersection drops them the
1042
1051
  // moment a caller narrows to one member.
1043
1052
  //
1044
1053
  // `detailFor` applies to any screen kind because any kind can be the