@tai42/studio-sdk 30.0.0 → 31.0.0

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.
Files changed (252) hide show
  1. package/README.md +98 -10
  2. package/dist/components/agent-picker.d.ts +1 -1
  3. package/dist/components/agent-picker.d.ts.map +1 -1
  4. package/dist/components/agent-picker.js +1 -0
  5. package/dist/components/agent-picker.js.map +1 -1
  6. package/dist/components/channel-picker.d.ts +1 -1
  7. package/dist/components/channel-picker.d.ts.map +1 -1
  8. package/dist/components/channel-picker.js +1 -0
  9. package/dist/components/channel-picker.js.map +1 -1
  10. package/dist/components/combo-draft-editor.d.ts +31 -0
  11. package/dist/components/combo-draft-editor.d.ts.map +1 -0
  12. package/dist/components/combo-draft-editor.js +16 -0
  13. package/dist/components/combo-draft-editor.js.map +1 -0
  14. package/dist/components/committed-combo-list.d.ts +17 -0
  15. package/dist/components/committed-combo-list.d.ts.map +1 -0
  16. package/dist/components/{extension-combo-parts.js → committed-combo-list.js} +2 -22
  17. package/dist/components/committed-combo-list.js.map +1 -0
  18. package/dist/components/components.css +53 -0
  19. package/dist/components/explorer-body.d.ts +1 -0
  20. package/dist/components/explorer-body.d.ts.map +1 -1
  21. package/dist/components/explorer-body.js +6 -4
  22. package/dist/components/explorer-body.js.map +1 -1
  23. package/dist/components/explorer-view.d.ts +16 -7
  24. package/dist/components/explorer-view.d.ts.map +1 -1
  25. package/dist/components/explorer-view.js +27 -13
  26. package/dist/components/explorer-view.js.map +1 -1
  27. package/dist/components/extension-combo-builder.d.ts +4 -4
  28. package/dist/components/extension-combo-builder.js +3 -2
  29. package/dist/components/extension-combo-builder.js.map +1 -1
  30. package/dist/components/extension-config-editor.js.map +1 -1
  31. package/dist/components/field.d.ts +6 -0
  32. package/dist/components/field.d.ts.map +1 -1
  33. package/dist/components/field.js +15 -2
  34. package/dist/components/field.js.map +1 -1
  35. package/dist/components/folder-actions.d.ts +51 -0
  36. package/dist/components/folder-actions.d.ts.map +1 -0
  37. package/dist/components/folder-actions.js +173 -0
  38. package/dist/components/folder-actions.js.map +1 -0
  39. package/dist/components/folder-filing.d.ts +32 -0
  40. package/dist/components/folder-filing.d.ts.map +1 -0
  41. package/dist/components/folder-filing.js +51 -0
  42. package/dist/components/folder-filing.js.map +1 -0
  43. package/dist/components/folder-nav.d.ts +9 -4
  44. package/dist/components/folder-nav.d.ts.map +1 -1
  45. package/dist/components/folder-nav.js +18 -22
  46. package/dist/components/folder-nav.js.map +1 -1
  47. package/dist/components/folder-occupancy.d.ts +27 -0
  48. package/dist/components/folder-occupancy.d.ts.map +1 -0
  49. package/dist/components/folder-occupancy.js +54 -0
  50. package/dist/components/folder-occupancy.js.map +1 -0
  51. package/dist/components/named-list-picker.d.ts +5 -3
  52. package/dist/components/named-list-picker.d.ts.map +1 -1
  53. package/dist/components/named-list-picker.js +7 -7
  54. package/dist/components/named-list-picker.js.map +1 -1
  55. package/dist/components/primitives.d.ts +2 -1
  56. package/dist/components/primitives.d.ts.map +1 -1
  57. package/dist/components/primitives.js +2 -1
  58. package/dist/components/primitives.js.map +1 -1
  59. package/dist/components/searchable-select-model.d.ts +40 -0
  60. package/dist/components/searchable-select-model.d.ts.map +1 -0
  61. package/dist/components/searchable-select-model.js +69 -0
  62. package/dist/components/searchable-select-model.js.map +1 -0
  63. package/dist/components/searchable-select.d.ts +38 -0
  64. package/dist/components/searchable-select.d.ts.map +1 -0
  65. package/dist/components/searchable-select.js +200 -0
  66. package/dist/components/searchable-select.js.map +1 -0
  67. package/dist/components/selected-tool-badges.d.ts +13 -0
  68. package/dist/components/selected-tool-badges.d.ts.map +1 -0
  69. package/dist/components/selected-tool-badges.js +14 -0
  70. package/dist/components/selected-tool-badges.js.map +1 -0
  71. package/dist/components/subject-section.d.ts.map +1 -1
  72. package/dist/components/subject-section.js +2 -2
  73. package/dist/components/subject-section.js.map +1 -1
  74. package/dist/components/table.d.ts +7 -1
  75. package/dist/components/table.d.ts.map +1 -1
  76. package/dist/components/table.js +2 -2
  77. package/dist/components/table.js.map +1 -1
  78. package/dist/components/tag-filter-field.d.ts +11 -0
  79. package/dist/components/tag-filter-field.d.ts.map +1 -0
  80. package/dist/components/tag-filter-field.js +15 -0
  81. package/dist/components/tag-filter-field.js.map +1 -0
  82. package/dist/components/tool-meta-access.d.ts +28 -0
  83. package/dist/components/tool-meta-access.d.ts.map +1 -0
  84. package/dist/components/tool-meta-access.js +65 -0
  85. package/dist/components/tool-meta-access.js.map +1 -0
  86. package/dist/components/tool-name-entry.d.ts +26 -0
  87. package/dist/components/tool-name-entry.d.ts.map +1 -0
  88. package/dist/components/tool-name-entry.js +43 -0
  89. package/dist/components/tool-name-entry.js.map +1 -0
  90. package/dist/components/tool-picker.d.ts +24 -19
  91. package/dist/components/tool-picker.d.ts.map +1 -1
  92. package/dist/components/tool-picker.js +55 -35
  93. package/dist/components/tool-picker.js.map +1 -1
  94. package/dist/components/tool-select.d.ts +26 -0
  95. package/dist/components/tool-select.d.ts.map +1 -0
  96. package/dist/components/tool-select.js +82 -0
  97. package/dist/components/tool-select.js.map +1 -0
  98. package/dist/extension-combos.d.ts +6 -1
  99. package/dist/extension-combos.d.ts.map +1 -1
  100. package/dist/extension-combos.js +8 -0
  101. package/dist/extension-combos.js.map +1 -1
  102. package/dist/hooks/useApi.d.ts +1 -0
  103. package/dist/hooks/useApi.d.ts.map +1 -1
  104. package/dist/hooks/useSystemKinds.d.ts +27 -12
  105. package/dist/hooks/useSystemKinds.d.ts.map +1 -1
  106. package/dist/hooks/useSystemKinds.js +56 -16
  107. package/dist/hooks/useSystemKinds.js.map +1 -1
  108. package/dist/index.d.ts +51 -49
  109. package/dist/index.d.ts.map +1 -1
  110. package/dist/index.js +34 -26
  111. package/dist/index.js.map +1 -1
  112. package/dist/marketplace-install/use-mount-install.d.ts +6 -6
  113. package/dist/plugin/version.d.ts +1 -1
  114. package/dist/plugin/version.js +1 -1
  115. package/dist/schema-editor/SchemaEditor.d.ts +7 -2
  116. package/dist/schema-editor/SchemaEditor.d.ts.map +1 -1
  117. package/dist/schema-editor/SchemaEditor.js +1 -1
  118. package/dist/schema-editor/SchemaEditor.js.map +1 -1
  119. package/dist/schema-editor/index.d.ts +2 -2
  120. package/dist/schema-editor/index.d.ts.map +1 -1
  121. package/dist/schema-form/array-field.d.ts.map +1 -1
  122. package/dist/schema-form/array-field.js +6 -2
  123. package/dist/schema-form/array-field.js.map +1 -1
  124. package/dist/schema-form/classify.d.ts +4 -1
  125. package/dist/schema-form/classify.d.ts.map +1 -1
  126. package/dist/schema-form/classify.js +36 -15
  127. package/dist/schema-form/classify.js.map +1 -1
  128. package/dist/schema-form/collapsed-object-field.d.ts +20 -0
  129. package/dist/schema-form/collapsed-object-field.d.ts.map +1 -0
  130. package/dist/schema-form/collapsed-object-field.js +14 -0
  131. package/dist/schema-form/collapsed-object-field.js.map +1 -0
  132. package/dist/schema-form/context.d.ts +27 -1
  133. package/dist/schema-form/context.d.ts.map +1 -1
  134. package/dist/schema-form/context.js +14 -0
  135. package/dist/schema-form/context.js.map +1 -1
  136. package/dist/schema-form/default-value.d.ts +21 -6
  137. package/dist/schema-form/default-value.d.ts.map +1 -1
  138. package/dist/schema-form/default-value.js +74 -15
  139. package/dist/schema-form/default-value.js.map +1 -1
  140. package/dist/schema-form/expression-field.d.ts +48 -0
  141. package/dist/schema-form/expression-field.d.ts.map +1 -0
  142. package/dist/schema-form/expression-field.js +88 -0
  143. package/dist/schema-form/expression-field.js.map +1 -0
  144. package/dist/schema-form/field-model.d.ts +23 -4
  145. package/dist/schema-form/field-model.d.ts.map +1 -1
  146. package/dist/schema-form/field-node.d.ts.map +1 -1
  147. package/dist/schema-form/field-node.js +16 -3
  148. package/dist/schema-form/field-node.js.map +1 -1
  149. package/dist/schema-form/index.d.ts +3 -3
  150. package/dist/schema-form/index.d.ts.map +1 -1
  151. package/dist/schema-form/index.js +2 -2
  152. package/dist/schema-form/index.js.map +1 -1
  153. package/dist/schema-form/object-fields.d.ts +6 -3
  154. package/dist/schema-form/object-fields.d.ts.map +1 -1
  155. package/dist/schema-form/object-fields.js +14 -3
  156. package/dist/schema-form/object-fields.js.map +1 -1
  157. package/dist/schema-form/record-field.d.ts.map +1 -1
  158. package/dist/schema-form/record-field.js +6 -2
  159. package/dist/schema-form/record-field.js.map +1 -1
  160. package/dist/schema-form/seeding-action.d.ts +15 -0
  161. package/dist/schema-form/seeding-action.d.ts.map +1 -0
  162. package/dist/schema-form/seeding-action.js +35 -0
  163. package/dist/schema-form/seeding-action.js.map +1 -0
  164. package/dist/schema-form/string-annotations.d.ts +22 -8
  165. package/dist/schema-form/string-annotations.d.ts.map +1 -1
  166. package/dist/schema-form/string-annotations.js +39 -14
  167. package/dist/schema-form/string-annotations.js.map +1 -1
  168. package/dist/schema-form/string-field.js +2 -84
  169. package/dist/schema-form/string-field.js.map +1 -1
  170. package/dist/schema-form/templated-field.d.ts +13 -0
  171. package/dist/schema-form/templated-field.d.ts.map +1 -0
  172. package/dist/schema-form/templated-field.js +43 -0
  173. package/dist/schema-form/templated-field.js.map +1 -0
  174. package/dist/schema-form/union-field.d.ts.map +1 -1
  175. package/dist/schema-form/union-field.js +6 -2
  176. package/dist/schema-form/union-field.js.map +1 -1
  177. package/dist/schema-form/union.d.ts +4 -4
  178. package/dist/schema-form/union.d.ts.map +1 -1
  179. package/dist/schema-form/union.js +8 -1
  180. package/dist/schema-form/union.js.map +1 -1
  181. package/dist/schema-form/validate.d.ts.map +1 -1
  182. package/dist/schema-form/validate.js +28 -0
  183. package/dist/schema-form/validate.js.map +1 -1
  184. package/dist/search-match.d.ts +29 -0
  185. package/dist/search-match.d.ts.map +1 -0
  186. package/dist/search-match.js +38 -0
  187. package/dist/search-match.js.map +1 -0
  188. package/dist/tool-organization.d.ts +15 -0
  189. package/dist/tool-organization.d.ts.map +1 -0
  190. package/dist/tool-organization.js +6 -0
  191. package/dist/tool-organization.js.map +1 -0
  192. package/package.json +3 -2
  193. package/src/components/agent-picker.tsx +2 -1
  194. package/src/components/channel-picker.tsx +2 -1
  195. package/src/components/combo-draft-editor.tsx +96 -0
  196. package/src/components/{extension-combo-parts.tsx → committed-combo-list.tsx} +4 -105
  197. package/src/components/components.css +53 -0
  198. package/src/components/explorer-body.tsx +29 -5
  199. package/src/components/explorer-view.tsx +48 -17
  200. package/src/components/extension-combo-builder.tsx +10 -10
  201. package/src/components/extension-config-editor.tsx +3 -3
  202. package/src/components/field.tsx +18 -2
  203. package/src/components/folder-actions.tsx +341 -0
  204. package/src/components/folder-filing.tsx +109 -0
  205. package/src/components/folder-nav.tsx +26 -10
  206. package/src/components/folder-occupancy.ts +83 -0
  207. package/src/components/named-list-picker.tsx +11 -7
  208. package/src/components/primitives.tsx +2 -1
  209. package/src/components/searchable-select-model.ts +105 -0
  210. package/src/components/searchable-select.tsx +432 -0
  211. package/src/components/selected-tool-badges.tsx +41 -0
  212. package/src/components/subject-section.tsx +3 -2
  213. package/src/components/table.tsx +12 -2
  214. package/src/components/tag-filter-field.tsx +37 -0
  215. package/src/components/tool-meta-access.tsx +101 -0
  216. package/src/components/tool-name-entry.tsx +77 -0
  217. package/src/components/tool-picker.tsx +87 -52
  218. package/src/components/tool-select.tsx +136 -0
  219. package/src/extension-combos.ts +15 -1
  220. package/src/hooks/useSystemKinds.tsx +77 -17
  221. package/src/index.ts +98 -94
  222. package/src/plugin/version.ts +1 -1
  223. package/src/schema-editor/SchemaEditor.tsx +9 -3
  224. package/src/schema-editor/index.ts +2 -2
  225. package/src/schema-form/array-field.tsx +10 -2
  226. package/src/schema-form/classify.ts +41 -15
  227. package/src/schema-form/collapsed-object-field.tsx +56 -0
  228. package/src/schema-form/context.ts +33 -1
  229. package/src/schema-form/default-value.ts +89 -15
  230. package/src/schema-form/expression-field.tsx +162 -0
  231. package/src/schema-form/field-model.ts +27 -4
  232. package/src/schema-form/field-node.tsx +41 -2
  233. package/src/schema-form/index.ts +3 -2
  234. package/src/schema-form/object-fields.tsx +11 -4
  235. package/src/schema-form/record-field.tsx +10 -2
  236. package/src/schema-form/seeding-action.ts +44 -0
  237. package/src/schema-form/string-annotations.ts +40 -14
  238. package/src/schema-form/string-field.tsx +2 -147
  239. package/src/schema-form/templated-field.tsx +124 -0
  240. package/src/schema-form/union-field.tsx +11 -2
  241. package/src/schema-form/union.ts +12 -5
  242. package/src/schema-form/validate.ts +28 -0
  243. package/src/search-match.ts +41 -0
  244. package/src/tool-organization.ts +34 -0
  245. package/dist/components/extension-combo-parts.d.ts +0 -46
  246. package/dist/components/extension-combo-parts.d.ts.map +0 -1
  247. package/dist/components/extension-combo-parts.js.map +0 -1
  248. package/dist/components/tool-picker-parts.d.ts +0 -43
  249. package/dist/components/tool-picker-parts.d.ts.map +0 -1
  250. package/dist/components/tool-picker-parts.js +0 -89
  251. package/dist/components/tool-picker-parts.js.map +0 -1
  252. package/src/components/tool-picker-parts.tsx +0 -195
@@ -1,9 +1,12 @@
1
1
  /**
2
- * Detect the annotations that opt a (ref-resolved) string schema out of the plain
3
- * text box: the media-upload annotations (`contentEncoding`/`contentMediaType`/
4
- * `format: "data-url"`) and the `x-tai42-expression` expression-editor annotation.
5
- * Both degrade to `undefined` on anything malformed, so an annotated field never
6
- * renders differently from the plain string it falls back to.
2
+ * Detect the vendor and media annotations that opt a property out of its plain
3
+ * editor: the media-upload annotations (`contentEncoding`/`contentMediaType`/
4
+ * `format: "data-url"`) on a string, the `x-tai42-expression` expression-editor
5
+ * annotation on a string or templated-text property (or on a union of them, where
6
+ * it governs every member), and the `x-tai42-templated-text` mark the platform's
7
+ * templated-text type carries. The first two degrade to
8
+ * `undefined` on anything malformed, so an annotated field never renders differently
9
+ * from the plain field it falls back to.
7
10
  */
8
11
  import { isRecord } from '../guards';
9
12
  import type {
@@ -15,6 +18,29 @@ import type {
15
18
  import type { JsonSchema } from './types';
16
19
 
17
20
  const EXPRESSION_KEYWORD = 'x-tai42-expression';
21
+ const TEMPLATED_TEXT_KEYWORD = 'x-tai42-templated-text';
22
+
23
+ /**
24
+ * Is this (ref-resolved) schema the platform's templated-text type? The type stamps
25
+ * `x-tai42-templated-text` on its own schema, so every property of the type is
26
+ * recognised by the mark, never by a field name or a property layout.
27
+ */
28
+ export function isTemplatedText(schema: JsonSchema): boolean {
29
+ return isRecord(schema[TEMPLATED_TEXT_KEYWORD]);
30
+ }
31
+
32
+ /**
33
+ * A schema node as its property site declares it: the `x-tai42-expression`
34
+ * annotation sits on the property site (a union wrapper, or the node holding a
35
+ * `$ref`), and it governs the node the value is checked against (the union member
36
+ * the value takes, or the referenced definition), so a node that carries none of its
37
+ * own gets the site's. The node is returned unchanged when there is nothing to carry.
38
+ */
39
+ export function withSiteExpression(member: JsonSchema, site: JsonSchema): JsonSchema {
40
+ const annotation: unknown = site[EXPRESSION_KEYWORD];
41
+ if (annotation === undefined || member[EXPRESSION_KEYWORD] !== undefined) return member;
42
+ return { ...member, [EXPRESSION_KEYWORD]: annotation };
43
+ }
18
44
 
19
45
  /**
20
46
  * Detect the media-upload annotations on a (ref-resolved) string schema. A field
@@ -99,20 +125,20 @@ function parseCaveatList(value: unknown): readonly string[] | undefined | null {
99
125
  }
100
126
 
101
127
  /**
102
- * Detect the `x-tai42-expression` annotation on a (ref-resolved) string schema,
103
- * mirroring {@link mediaUpload}: a well-formed annotation opts the field into the
104
- * jq expression editor; anything else — absent, non-object, unknown language, or
105
- * any wrongly-typed member — yields `undefined`, so the field renders EXACTLY as
106
- * the plain string input it is today. Malformed payloads NEVER throw: a bad
107
- * annotation is a server-side authoring bug, and degrading to the ordinary text
108
- * box keeps the form usable while staying byte-identical to the unannotated
109
- * rendering.
128
+ * Detect the `x-tai42-expression` annotation on a property schema (a string, or the
129
+ * property site of a templated-text field), mirroring {@link mediaUpload}: a
130
+ * well-formed annotation opts the field into the jq expression editor; anything
131
+ * else — absent, non-object, unknown language, or any wrongly-typed member — yields
132
+ * `undefined`, so the field renders EXACTLY as its unannotated editor. Malformed
133
+ * payloads NEVER throw: a bad annotation is a server-side authoring bug, and
134
+ * degrading to the ordinary editor keeps the form usable while staying
135
+ * byte-identical to the unannotated rendering.
110
136
  */
111
137
  export function expressionAnnotation(schema: JsonSchema): ExpressionAnnotation | undefined {
112
138
  const raw: unknown = schema[EXPRESSION_KEYWORD];
113
139
  if (!isRecord(raw)) return undefined;
114
140
  // The language gate doubles as the forward-compatibility valve: a future
115
- // language this client does not understand degrades to a plain string field.
141
+ // language this client does not understand degrades to the unannotated field.
116
142
  if (raw.language !== 'jq') return undefined;
117
143
 
118
144
  const label = optionalString(raw.label);
@@ -19,15 +19,15 @@
19
19
  * annotated field with no injected door falls back to the plain string input.
20
20
  */
21
21
  import type { ReactNode } from 'react';
22
- import { Suspense, useCallback, useContext, useMemo, useState } from 'react';
22
+ import { useCallback, useContext, useState } from 'react';
23
23
 
24
24
  import { CompletionInput } from '../components/completion-input';
25
25
  import { Field } from '../components/field';
26
26
  import { AlertTriangleIcon } from '../components/icons';
27
27
  import { Textarea, TextInput } from '../components/inputs';
28
28
  import { errorMessage } from '../errors';
29
- import type { ExpressionFieldComponent, ExpressionInputShape } from './context';
30
29
  import { CompletionProviderContext, ExpressionFieldContext } from './context';
30
+ import { ExpressionField } from './expression-field';
31
31
  import type { DateConstraints, ExpressionAnnotation, MediaUpload } from './field-model';
32
32
  import { MediaField } from './media-field';
33
33
  import type { CompletionProvider } from './SchemaForm';
@@ -240,151 +240,6 @@ function CompletionField({
240
240
  );
241
241
  }
242
242
 
243
- /**
244
- * An expression-annotated string field, rendered through the injected door: a
245
- * multiline resting control with the door's own visual-editor button. The door
246
- * brings its own label/description/error chrome (a11y-linked slots), so it is NOT
247
- * wrapped in the form's `Field` component — the annotation's descriptor fields map
248
- * onto the input-shape descriptor, and the form's per-field error feeds `error`.
249
- *
250
- * The door is rendered as an ELEMENT, never called as a function, so its hooks and
251
- * state (editor open, worker handle) belong to it and survive re-renders of this
252
- * field.
253
- *
254
- * It mounts inside a `Suspense` boundary because a host is free to inject a `lazy`
255
- * door to keep the jq subgraph in a split chunk of ITS OWN bundle. The fallback
256
- * paints the resting shell — label/description/error chrome around the current
257
- * value in a read-only multiline control — so the field holds its layout and keeps
258
- * the value visible while that chunk resolves, and the swap does not flash. A door
259
- * injected eagerly never suspends and renders straight through.
260
- *
261
- * The form passes only the props the field owns; a jq door's `serverValidate`,
262
- * `onEditorOpenChange`, and `compact` stay unwired, because no author-time
263
- * validation endpoint applies to a schema-declared field, the hosts that render
264
- * `SchemaForm` register no global shortcuts to mute, and every sibling field shows
265
- * a visible label (the compact variant is for dense host rows).
266
- */
267
- function ExpressionField({
268
- component: Door,
269
- heading,
270
- description,
271
- error,
272
- expression,
273
- argName,
274
- value,
275
- onChange,
276
- }: {
277
- component: ExpressionFieldComponent;
278
- heading: string;
279
- description: string | undefined;
280
- error: string | undefined;
281
- expression: ExpressionAnnotation;
282
- argName: string;
283
- value: string;
284
- onChange: (value: string) => void;
285
- }): ReactNode {
286
- // Memoised: the descriptor's identity feeds the door's own memoisation, so a
287
- // fresh object each keystroke would defeat it.
288
- const shape = useMemo(() => expressionShape(expression, argName), [expression, argName]);
289
- return (
290
- <Suspense
291
- fallback={
292
- <ExpressionFieldSkeleton
293
- heading={heading}
294
- description={description}
295
- error={error}
296
- value={value}
297
- />
298
- }
299
- >
300
- <Door
301
- label={heading}
302
- description={description}
303
- error={error}
304
- shape={shape}
305
- multiline
306
- value={value}
307
- onChange={onChange}
308
- />
309
- </Suspense>
310
- );
311
- }
312
-
313
- /**
314
- * The resting shell shown while a lazily-injected door resolves. It mirrors the
315
- * live door's footprint — the same label/description/error chrome wrapping a
316
- * multiline control seeded with the current value — but the control is
317
- * non-interactive (read-only, `aria-busy`) because there is nothing to edit yet. Matching the
318
- * footprint is what keeps the Suspense swap from shifting layout or flashing.
319
- */
320
- function ExpressionFieldSkeleton({
321
- heading,
322
- description,
323
- error,
324
- value,
325
- }: {
326
- heading: string;
327
- description: string | undefined;
328
- error: string | undefined;
329
- value: string;
330
- }): ReactNode {
331
- return (
332
- <Field label={heading} description={description} error={error}>
333
- <Textarea value={value} readOnly aria-busy="true" />
334
- </Field>
335
- );
336
- }
337
-
338
- /**
339
- * Map a classified expression annotation onto the door's input-shape descriptor.
340
- * A bare annotation (`language` only) maps to NO descriptor — an undeclared shape
341
- * is the honest rendering when the server said nothing about `.`. When any
342
- * descriptor field is present, the required descriptor members the annotation
343
- * omits fall back to neutral values rather than invented copy.
344
- */
345
- function expressionShape(
346
- expression: ExpressionAnnotation,
347
- argName: string,
348
- ): ExpressionInputShape | undefined {
349
- const declared =
350
- [
351
- expression.label,
352
- expression.blurb,
353
- expression.keys,
354
- expression.variables,
355
- expression.returns,
356
- expression.caveats,
357
- ].some((field) => field !== undefined) || expression.hasSample;
358
- if (!declared) return undefined;
359
- return {
360
- // Opaque, host-namespaced, stable per field (memoisation/telemetry only).
361
- id: argName === '' ? 'tai42.schema-form' : `tai42.schema-form.${argName}`,
362
- label: expression.label ?? 'input',
363
- blurb: expression.blurb ?? '',
364
- keys: expression.keys ?? [],
365
- returns: expression.returns ?? '',
366
- ...(expression.caveats === undefined ? {} : { caveats: expression.caveats }),
367
- ...(expression.hasSample ? { sample: expression.sample } : {}),
368
- ...(expression.variables === undefined
369
- ? {}
370
- : { variables: expression.variables.map(expressionVariable) }),
371
- };
372
- }
373
-
374
- /** Map one classified annotation variable onto the door's variable descriptor. */
375
- function expressionVariable(
376
- variable: NonNullable<ExpressionAnnotation['variables']>[number],
377
- ): NonNullable<ExpressionInputShape['variables']>[number] {
378
- return {
379
- name: variable.name,
380
- blurb: variable.blurb,
381
- // The annotation glosses no sub-keys of a variable's value, so the door gets
382
- // the variable's shape as untyped (empty keys).
383
- keys: [],
384
- ...(variable.hasSample ? { sample: variable.sample } : {}),
385
- };
386
- }
387
-
388
243
  // The native control per JSON-Schema `format`. `date` and `time` post the exact
389
244
  // wire shapes their formats expect (`YYYY-MM-DD`; `HH:mm` or `HH:mm:ss`), so they
390
245
  // render natively. `date-time` is deliberately absent: the browser's
@@ -0,0 +1,124 @@
1
+ /**
2
+ * The templated-text field renderer: a property typed as the platform's templated
3
+ * text is authored through the shared {@link TemplatedTextField} — inline content or
4
+ * a stored template id, plus the render kwargs — exactly as a hand-built templated
5
+ * field is. When the property carries an `x-tai42-expression` annotation and the host
6
+ * injected an expression door, the inline editor IS that door (the resting control
7
+ * plus its visual-editor button); otherwise it is the field's plain textarea.
8
+ *
9
+ * The stored-template catalog comes from the host's {@link TemplatedTextCatalogContext}
10
+ * hook, called only here, so only a form that draws a templated-text field reads it.
11
+ */
12
+ import type { TemplatedText } from '@tai42/api-client';
13
+ import { type ReactNode, useContext, useState } from 'react';
14
+
15
+ import {
16
+ TemplatedTextField,
17
+ type TemplatedTextInlineProps,
18
+ } from '../components/templated-text-field';
19
+ import { isRecord } from '../guards';
20
+ import { ExpressionFieldContext, TemplatedTextCatalogContext } from './context';
21
+ import { ExpressionField } from './expression-field';
22
+ import type { ExpressionAnnotation } from './field-model';
23
+
24
+ /** The form value read as a templated text: its string source(s) and its kwargs. */
25
+ function templatedTextOf(value: unknown): TemplatedText | null {
26
+ if (!isRecord(value)) return null;
27
+ const { content, id, kwargs } = value;
28
+ return {
29
+ ...(typeof content === 'string' ? { content } : {}),
30
+ ...(typeof id === 'string' ? { id } : {}),
31
+ ...(isRecord(kwargs) ? { kwargs } : {}),
32
+ };
33
+ }
34
+
35
+ /**
36
+ * Which mount of the field is current. The field seeds its editing state from the
37
+ * value once, so a value the caller REPLACES (not one this field emitted) mounts a
38
+ * fresh field seeded from it.
39
+ */
40
+ interface Mount {
41
+ readonly value: unknown;
42
+ readonly emitted: unknown;
43
+ readonly generation: number;
44
+ }
45
+
46
+ export function TemplatedField({
47
+ heading,
48
+ description,
49
+ error,
50
+ expression,
51
+ argName,
52
+ required,
53
+ value,
54
+ onChange,
55
+ }: {
56
+ heading: string;
57
+ description: string | undefined;
58
+ error: string | undefined;
59
+ expression: ExpressionAnnotation | undefined;
60
+ argName: string;
61
+ required: boolean;
62
+ value: unknown;
63
+ onChange: (value: unknown) => void;
64
+ }): ReactNode {
65
+ const useCatalog = useContext(TemplatedTextCatalogContext);
66
+ const catalog = useCatalog();
67
+ const door = useContext(ExpressionFieldContext);
68
+ const [mount, setMount] = useState<Mount>({ value, emitted: value, generation: 0 });
69
+ if (mount.value !== value) {
70
+ setMount({
71
+ value,
72
+ emitted: mount.emitted,
73
+ generation: value === mount.emitted ? mount.generation : mount.generation + 1,
74
+ });
75
+ }
76
+
77
+ // An emptied optional field drops its key; a required one keeps its empty source
78
+ // (the shared field emits it), so validation names the missing source and a union
79
+ // member stays the chosen one.
80
+ const emit = (next: TemplatedText | null): void => {
81
+ const formValue = next ?? undefined;
82
+ setMount((current) => ({ ...current, emitted: formValue }));
83
+ onChange(formValue);
84
+ };
85
+
86
+ const renderInline =
87
+ expression !== undefined && door !== undefined
88
+ ? (inline: TemplatedTextInlineProps): ReactNode => (
89
+ // The field's group header is the single visible label; the door keeps
90
+ // its own label element as the control's accessible name.
91
+ <div className={inline.hideLabel ? 'tai-templated-inline--grouped' : undefined}>
92
+ <ExpressionField
93
+ component={door}
94
+ heading={inline.label}
95
+ description={undefined}
96
+ error={inline.error}
97
+ expression={expression}
98
+ argName={argName}
99
+ value={inline.value}
100
+ onChange={inline.onChange}
101
+ />
102
+ </div>
103
+ )
104
+ : undefined;
105
+
106
+ return (
107
+ <TemplatedTextField
108
+ key={mount.generation}
109
+ label={heading}
110
+ description={description}
111
+ error={error}
112
+ value={templatedTextOf(value)}
113
+ onChange={emit}
114
+ required={required}
115
+ templates={catalog?.templates}
116
+ templatesLoading={catalog?.loading}
117
+ templatesError={catalog?.error}
118
+ onTemplatesRetry={catalog?.onRetry}
119
+ storageAbsent={catalog?.storageAbsent}
120
+ storagePresenceLoading={catalog?.storagePresenceLoading}
121
+ renderInline={renderInline}
122
+ />
123
+ );
124
+ }
@@ -18,6 +18,7 @@ import type { FieldModel, UnionVariant } from './field-model';
18
18
  import { FieldNode } from './field-node';
19
19
  import { ObjectFields } from './object-fields';
20
20
  import { resolveRef } from './resolve';
21
+ import { useSeedingAction } from './seeding-action';
21
22
  import { groupClass } from './styles';
22
23
  import type { JsonSchema, SchemaFormErrors } from './types';
23
24
  import { activeVariantIndex } from './union';
@@ -132,11 +133,15 @@ export function UnionField({
132
133
  value: String(position),
133
134
  label: variant.label,
134
135
  }));
136
+ const switching = useSeedingAction(model.members);
135
137
  const selectVariant = (key: string): void => {
136
138
  const position = Number(key);
137
139
  const variant = model.variants[position];
138
140
  if (variant === undefined) return;
139
- onChange(switchVariantValue(value, variant, model.discriminator, root));
141
+ const switched = switching.seed(() =>
142
+ switchVariantValue(value, variant, model.discriminator, root),
143
+ );
144
+ if (switched.ok) onChange(switched.value);
140
145
  };
141
146
 
142
147
  const active = index === -1 ? undefined : model.variants[index];
@@ -147,7 +152,10 @@ export function UnionField({
147
152
  // and describes — a synthetic heading there is noise, so it is suppressed
148
153
  // exactly as a root object's is; nested unions keep theirs.
149
154
  <FieldGroup heading={heading} description={description} error={error} atRoot={path === ''}>
150
- <Field label={pickerLabel(model.discriminator, model.variants, root)}>
155
+ <Field
156
+ label={pickerLabel(model.discriminator, model.variants, root)}
157
+ error={switching.failure}
158
+ >
151
159
  <Select
152
160
  options={options}
153
161
  value={index === -1 ? '' : String(index)}
@@ -159,6 +167,7 @@ export function UnionField({
159
167
  <div className={groupClass}>
160
168
  <ObjectFields
161
169
  properties={activeClassified.model.properties}
170
+ shape={activeClassified.model.shape}
162
171
  requiredKeys={activeClassified.model.required}
163
172
  root={root}
164
173
  value={value}
@@ -1,18 +1,24 @@
1
1
  /**
2
2
  * Which variant of a union a given value currently inhabits. Discriminated
3
- * unions read the tag property directly; plain unions score each object variant
4
- * by how many of its required properties the value carries (a best-effort match
5
- * when Pydantic emitted no discriminator). Returns `-1` when no variant is
6
- * active (an unset/`null` value, or nothing matches).
3
+ * unions read the tag property directly; plain unions score each variant that can
4
+ * hold an object by how many of its required properties the value carries (a
5
+ * best-effort match when Pydantic emitted no discriminator). Returns `-1` when no
6
+ * variant is active (an unset/`null` value, or nothing matches).
7
7
  */
8
8
  import type { UnionVariant } from './field-model';
9
- import { resolveRef } from './resolve';
9
+ import { resolveRef, typeList } from './resolve';
10
10
  import type { JsonSchema } from './types';
11
11
 
12
12
  function isPlainObject(value: unknown): value is Record<string, unknown> {
13
13
  return typeof value === 'object' && value !== null && !Array.isArray(value);
14
14
  }
15
15
 
16
+ /** Whether a resolved schema can hold an object: it is typed `object`, or untyped. */
17
+ function holdsObject(schema: JsonSchema): boolean {
18
+ const types = typeList(schema);
19
+ return types.length === 0 || types.includes('object');
20
+ }
21
+
16
22
  /** Whether a resolved scalar schema accepts the runtime type of `value`. */
17
23
  function scalarSchemaAccepts(schema: JsonSchema, value: unknown): boolean {
18
24
  if (schema.const !== undefined) return schema.const === value;
@@ -64,6 +70,7 @@ export function activeVariantIndex(
64
70
  let bestScore = -1;
65
71
  variants.forEach((variant, index) => {
66
72
  const resolved = resolveRef(variant.schema, root);
73
+ if (!holdsObject(resolved)) return;
67
74
  const required = resolved.required ?? [];
68
75
  let score = 0;
69
76
  for (const key of required) {
@@ -508,6 +508,31 @@ function validateRecord(
508
508
  }
509
509
  }
510
510
 
511
+ /**
512
+ * A templated-text value: an object carrying exactly one non-empty source — inline
513
+ * `content` or a stored template `id` — and, when present, a `kwargs` object.
514
+ */
515
+ function validateTemplatedText(value: unknown, path: string, ctx: ValidateCtx): void {
516
+ if (!isRecord(value)) {
517
+ shapeError(ctx, path, 'must be an object');
518
+ return;
519
+ }
520
+ const content = ownValue(value, 'content');
521
+ const id = ownValue(value, 'id');
522
+ const hasContent = typeof content === 'string';
523
+ const hasId = typeof id === 'string';
524
+ if (hasContent === hasId) {
525
+ shapeError(ctx, path, 'must set exactly one of inline content or a stored template id');
526
+ return;
527
+ }
528
+ if ((hasContent ? content : id) === '') {
529
+ shapeError(ctx, path, 'needs inline content or a stored template');
530
+ return;
531
+ }
532
+ const kwargs = ownValue(value, 'kwargs');
533
+ if (kwargs !== undefined && !isRecord(kwargs)) shapeError(ctx, path, 'kwargs must be an object');
534
+ }
535
+
511
536
  function validateUnion(
512
537
  model: ModelOf<'union'>,
513
538
  value: unknown,
@@ -569,6 +594,9 @@ function dispatchKind(model: FieldModel, value: unknown, path: string, ctx: Vali
569
594
  case 'record':
570
595
  validateRecord(model, value, path, ctx);
571
596
  return;
597
+ case 'templated-text':
598
+ validateTemplatedText(value, path, ctx);
599
+ return;
572
600
  case 'union':
573
601
  validateUnion(model, value, path, ctx);
574
602
  return;
@@ -0,0 +1,41 @@
1
+ /**
2
+ * The one text-search rule every Studio list applies: a case-insensitive substring
3
+ * match of the trimmed query against the texts the reader sees. A blank query matches
4
+ * everything.
5
+ */
6
+
7
+ /**
8
+ * The query in the form a match compares: trimmed and lower-cased. A list that tests
9
+ * many texts against one query computes this once and hands it to {@link textHasNeedle}.
10
+ */
11
+ export function searchNeedle(query: string): string {
12
+ return query.trim().toLowerCase();
13
+ }
14
+
15
+ /** True when `needle` (from {@link searchNeedle}) is blank or `loweredText` contains it. */
16
+ export function textHasNeedle(loweredText: string, needle: string): boolean {
17
+ return needle === '' || loweredText.includes(needle);
18
+ }
19
+
20
+ /**
21
+ * True when `query` holds nothing but blanks, so it matches every text: a list that
22
+ * draws itself differently while no search is active asks this.
23
+ */
24
+ export function isBlankSearch(query: string): boolean {
25
+ return searchNeedle(query) === '';
26
+ }
27
+
28
+ /**
29
+ * True when any one of `texts` contains `query`, ignoring case and the query's
30
+ * surrounding blanks; a blank query matches every row. Each text is tested on its own,
31
+ * so a row searched by several fields (a name and a display name) never matches across
32
+ * the seam between two of them.
33
+ *
34
+ * @param query - what the reader typed.
35
+ * @param texts - the texts the row is searched by (for a row of the connector's tool
36
+ * list, its `toolDisplayLabel`, which carries both the display name and the raw name).
37
+ */
38
+ export function matchesSearch(query: string, ...texts: readonly string[]): boolean {
39
+ const needle = searchNeedle(query);
40
+ return needle === '' || texts.some((text) => textHasNeedle(text.toLowerCase(), needle));
41
+ }
@@ -0,0 +1,34 @@
1
+ /**
2
+ * The tool-organization folder tree the package publishes: the folder model and its
3
+ * navigation, which folders a screen draws, the folder writes, filing one tool, and
4
+ * who may make each overlay write. Every screen that shows the tree composes these.
5
+ */
6
+ export type {
7
+ CreateFolder,
8
+ FolderActionsMenuProps,
9
+ FoldersChanged,
10
+ } from './components/folder-actions';
11
+ export { FolderActionsMenu, useCreateFolder } from './components/folder-actions';
12
+ export type { MoveToFolderDialogProps } from './components/folder-filing';
13
+ export { MoveToFolderDialog } from './components/folder-filing';
14
+ export type {
15
+ Folder,
16
+ FolderBreadcrumbProps,
17
+ FolderPickerProps,
18
+ FolderRowProps,
19
+ } from './components/folder-nav';
20
+ export {
21
+ childFolders,
22
+ FolderBreadcrumb,
23
+ folderPathTo,
24
+ FolderPicker,
25
+ FolderRow,
26
+ toFolders,
27
+ } from './components/folder-nav';
28
+ export { foldersForView } from './components/folder-occupancy';
29
+ export type { ToolMetaWriteAccess } from './components/tool-meta-access';
30
+ export {
31
+ ToolMetaWriteError,
32
+ useReportToolMetaRefusal,
33
+ useToolMetaWriteAccess,
34
+ } from './components/tool-meta-access';
@@ -1,46 +0,0 @@
1
- /**
2
- * The pieces of `ExtensionComboBuilder`: the committed-combo list
3
- * (`CommittedComboList`), the under-construction combo editor (`ComboDraftEditor`),
4
- * and the shared combo helpers. The builder owns the state and composes these.
5
- */
6
- import type { Extension, PresetExtensionElement } from '@tai42/api-client';
7
- import { type ReactNode } from 'react';
8
- import type { JsonSchema } from '../schema-form/types';
9
- import { type ExtensionConfigChange } from './extension-config-editor';
10
- /** Two combos are equal when their NAME sequences match (config is not part of identity). */
11
- export declare function sameNames(a: readonly string[], b: readonly string[]): boolean;
12
- /** The element names in a combo that are absent from the known catalog. */
13
- export declare function unknownNames(combo: readonly PresetExtensionElement[], availableNames: ReadonlySet<string>): string[];
14
- /** The current combos, each a row of name badges with per-combo Edit and Remove. */
15
- export declare function CommittedComboList({ value, availableReady, availableNames, editing, disabled, onEdit, onRemove, }: {
16
- readonly value: readonly PresetExtensionElement[][];
17
- readonly availableReady: boolean;
18
- readonly availableNames: ReadonlySet<string>;
19
- readonly editing: number | null;
20
- readonly disabled: boolean | undefined;
21
- readonly onEdit: (index: number) => void;
22
- readonly onRemove: (index: number) => void;
23
- }): ReactNode;
24
- /** A drafted extension whose catalog entry declares a settings schema. */
25
- export interface ConfigurableExtension {
26
- readonly name: string;
27
- readonly schema: JsonSchema;
28
- }
29
- /** The combo under construction: the extension picker, one settings form per drafted
30
- * configurable extension, the duplicate note, and the Add/Update + Cancel actions. */
31
- export declare function ComboDraftEditor({ available, draft, onDraftChange, configurable, draftConfigs, onDraftConfigChange, isDuplicate, canAdd, editing, disabled, idPrefix, onCommit, onReset, }: {
32
- readonly available: readonly Extension[];
33
- readonly draft: string[];
34
- readonly onDraftChange: (draft: string[]) => void;
35
- readonly configurable: readonly ConfigurableExtension[];
36
- readonly draftConfigs: Readonly<Record<string, Record<string, unknown> | undefined>>;
37
- readonly onDraftConfigChange: (name: string, change: ExtensionConfigChange) => void;
38
- readonly isDuplicate: boolean;
39
- readonly canAdd: boolean;
40
- readonly editing: number | null;
41
- readonly disabled: boolean | undefined;
42
- readonly idPrefix: string;
43
- readonly onCommit: () => void;
44
- readonly onReset: () => void;
45
- }): ReactNode;
46
- //# sourceMappingURL=extension-combo-parts.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"extension-combo-parts.d.ts","sourceRoot":"","sources":["../../src/components/extension-combo-parts.tsx"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,OAAO,KAAK,EAAE,SAAS,EAAE,sBAAsB,EAAE,MAAM,mBAAmB,CAAC;AAC3E,OAAO,EAAY,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AAGjD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAC;AAEvD,OAAO,EAAE,KAAK,qBAAqB,EAAyB,MAAM,2BAA2B,CAAC;AAK9F,6FAA6F;AAC7F,wBAAgB,SAAS,CAAC,CAAC,EAAE,SAAS,MAAM,EAAE,EAAE,CAAC,EAAE,SAAS,MAAM,EAAE,GAAG,OAAO,CAE7E;AAED,2EAA2E;AAC3E,wBAAgB,YAAY,CAC1B,KAAK,EAAE,SAAS,sBAAsB,EAAE,EACxC,cAAc,EAAE,WAAW,CAAC,MAAM,CAAC,GAClC,MAAM,EAAE,CAEV;AA4ED,oFAAoF;AACpF,wBAAgB,kBAAkB,CAAC,EACjC,KAAK,EACL,cAAc,EACd,cAAc,EACd,OAAO,EACP,QAAQ,EACR,MAAM,EACN,QAAQ,GACT,EAAE;IACD,QAAQ,CAAC,KAAK,EAAE,SAAS,sBAAsB,EAAE,EAAE,CAAC;IACpD,QAAQ,CAAC,cAAc,EAAE,OAAO,CAAC;IACjC,QAAQ,CAAC,cAAc,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC;IAC7C,QAAQ,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IAChC,QAAQ,CAAC,QAAQ,EAAE,OAAO,GAAG,SAAS,CAAC;IACvC,QAAQ,CAAC,MAAM,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IACzC,QAAQ,CAAC,QAAQ,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;CAC5C,GAAG,SAAS,CAqBZ;AAED,0EAA0E;AAC1E,MAAM,WAAW,qBAAqB;IACpC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,MAAM,EAAE,UAAU,CAAC;CAC7B;AAED;uFACuF;AACvF,wBAAgB,gBAAgB,CAAC,EAC/B,SAAS,EACT,KAAK,EACL,aAAa,EACb,YAAY,EACZ,YAAY,EACZ,mBAAmB,EACnB,WAAW,EACX,MAAM,EACN,OAAO,EACP,QAAQ,EACR,QAAQ,EACR,QAAQ,EACR,OAAO,GACR,EAAE;IACD,QAAQ,CAAC,SAAS,EAAE,SAAS,SAAS,EAAE,CAAC;IACzC,QAAQ,CAAC,KAAK,EAAE,MAAM,EAAE,CAAC;IACzB,QAAQ,CAAC,aAAa,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,IAAI,CAAC;IAClD,QAAQ,CAAC,YAAY,EAAE,SAAS,qBAAqB,EAAE,CAAC;IACxD,QAAQ,CAAC,YAAY,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,SAAS,CAAC,CAAC,CAAC;IACrF,QAAQ,CAAC,mBAAmB,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,qBAAqB,KAAK,IAAI,CAAC;IACpF,QAAQ,CAAC,WAAW,EAAE,OAAO,CAAC;IAC9B,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAC;IACzB,QAAQ,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IAChC,QAAQ,CAAC,QAAQ,EAAE,OAAO,GAAG,SAAS,CAAC;IACvC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,QAAQ,EAAE,MAAM,IAAI,CAAC;IAC9B,QAAQ,CAAC,OAAO,EAAE,MAAM,IAAI,CAAC;CAC9B,GAAG,SAAS,CA8CZ"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"extension-combo-parts.js","sourceRoot":"","sources":["../../src/components/extension-combo-parts.tsx"],"names":[],"mappings":"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"}