@tai42/api-client 14.0.0 → 15.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.
package/src/schemas.ts CHANGED
@@ -12,6 +12,35 @@ export const jsonValue: z.ZodType = z.unknown();
12
12
  /** A JSON Schema object (Pydantic-emitted). Permissive; parsed by the auto-form. */
13
13
  export const jsonSchema = z.record(z.string(), z.unknown());
14
14
 
15
+ /**
16
+ * One authored-text value: either inline `content` (text written in place) or a
17
+ * stored template `id` (a template resource fetched and rendered), never both and
18
+ * never neither. `kwargs` are the render parameters and apply in BOTH cases — a
19
+ * prompt with placeholders needs its values whether it was typed inline or fetched.
20
+ * `.strict()` refuses any other key so a drifting field fails the parse loudly.
21
+ */
22
+ export const templatedText = z
23
+ .object({
24
+ content: z.string().optional(),
25
+ id: z.string().optional(),
26
+ kwargs: z.record(z.string(), z.unknown()).optional(),
27
+ })
28
+ .strict()
29
+ .refine((value) => (value.content === undefined) !== (value.id === undefined), {
30
+ message: 'A templated-text value sets exactly one of `content` or `id`.',
31
+ });
32
+ export type TemplatedText = z.infer<typeof templatedText>;
33
+
34
+ /**
35
+ * A templated-text value that must carry a source: inline `content` is non-empty, or
36
+ * a stored template `id` is chosen. Used where the platform contract requires a
37
+ * value (e.g. a state binding's subject, an update's adapter when present).
38
+ */
39
+ export const requiredTemplatedText = templatedText.refine(
40
+ (value) => (value.id !== undefined ? value.id.length > 0 : (value.content ?? '').length > 0),
41
+ { message: 'Provide inline text or choose a stored template.' },
42
+ );
43
+
15
44
  // -- tools -------------------------------------------------------------------
16
45
 
17
46
  export const toolNames = z.array(z.string());
@@ -158,8 +187,10 @@ export type PresetDetail = z.infer<typeof presetDetail>;
158
187
  * carries the program; the other is `null`.
159
188
  */
160
189
  export const stateInjection = z.object({
190
+ // `template_jq` names a program the attached state template ships; it is resolved
191
+ // through compiled programs, never rendered as text, so it stays a plain string.
161
192
  template_jq: z.string().nullable().default(null),
162
- jq: z.string().nullable().default(null),
193
+ jq: templatedText.nullable().default(null),
163
194
  into: z.string(),
164
195
  });
165
196
  export type StateInjection = z.infer<typeof stateInjection>;
@@ -174,13 +205,15 @@ export type StateInjection = z.infer<typeof stateInjection>;
174
205
  * `template_jq`/`jq` carries the program.
175
206
  */
176
207
  export const stateUpdate = z.object({
208
+ // `template_jq` names a program the attached state template ships; resolved through
209
+ // compiled programs, never rendered as text, so it stays a plain string.
177
210
  template_jq: z.string().nullable().default(null),
178
- jq: z.string().nullable().default(null),
179
- // A named update's adapter is either a non-empty jq or `null` (no adapter — the
180
- // run input passes through). `min(1)` makes the empty string impossible to
181
- // round-trip: the platform compile-checks any non-null adapter and refuses `''`.
182
- adapter: z.string().min(1).nullable().default(null),
183
- op_id: z.string().nullable().default(null),
211
+ jq: templatedText.nullable().default(null),
212
+ // A named update's adapter is either an authored value or `null` (no adapter — the
213
+ // run input passes through). When present it must carry a source (the platform
214
+ // compile-checks a non-null adapter and refuses an empty one).
215
+ adapter: requiredTemplatedText.nullable().default(null),
216
+ op_id: templatedText.nullable().default(null),
184
217
  });
185
218
  export type StateUpdate = z.infer<typeof stateUpdate>;
186
219
 
@@ -195,10 +228,10 @@ export type StateUpdate = z.infer<typeof stateUpdate>;
195
228
  export const stateAttach = z.object({
196
229
  state: z.string(),
197
230
  templates: z.array(z.string()).default([]),
198
- // The platform contract enforces a non-empty subject (min_length=1); an empty
199
- // expression is rejected here, never sent for the server to refuse.
200
- subject_expr: z.string().min(1),
201
- scope_expr: z.string().nullable().default(null),
231
+ // The platform contract enforces a subject that carries a source; an empty one is
232
+ // rejected here, never sent for the server to refuse.
233
+ subject_expr: requiredTemplatedText,
234
+ scope_expr: templatedText.nullable().default(null),
202
235
  input_injections: z.array(stateInjection).default([]),
203
236
  updates: z.array(stateUpdate).default([]),
204
237
  });
@@ -1576,8 +1609,8 @@ export type Notifications = z.infer<typeof notifications>;
1576
1609
 
1577
1610
  // -- hooks -------------------------------------------------------------------
1578
1611
  // Shapes match tai42_contract.hooks.HookParams: a hook fires a `tool` on a `topic`,
1579
- // optionally gated by a `condition` and shaped by an `expr` (each either an inline
1580
- // spec or a registered id, with its own kwargs).
1612
+ // optionally gated by a `condition` and shaped by an `expr` (each an authored
1613
+ // templated-text value: inline content or a stored template id, with render kwargs).
1581
1614
 
1582
1615
  /** A fire door — who may trigger a path, not what the fire may do. A string enum. */
1583
1616
  export const triggerAuth = z.enum([
@@ -1613,14 +1646,8 @@ export const hookParams = z.object({
1613
1646
  // The optional state subject the fire targets; `null` leaves it with no ambient
1614
1647
  // state context (a state tool it calls must then carry an explicit subject).
1615
1648
  subject: hookSubject.nullable().default(null),
1616
- condition: z.string().nullable().default(null),
1617
- condition_id: z.string().nullable().default(null),
1618
- // The `*_kwargs` pair is non-optional in the contract (defaults to {}, never
1619
- // null) — unlike the sibling condition/expr string fields, which are nullable.
1620
- condition_kwargs: z.record(z.string(), z.unknown()).default({}),
1621
- expr: z.string().nullable().default(null),
1622
- expr_id: z.string().nullable().default(null),
1623
- expr_kwargs: z.record(z.string(), z.unknown()).default({}),
1649
+ condition: templatedText.nullable().default(null),
1650
+ expr: templatedText.nullable().default(null),
1624
1651
  // The optional door-layer state binding this hook applies around its fire's tool
1625
1652
  // run (`null` when the hook touches no state).
1626
1653
  state_binding: stateBinding.nullable().default(null),
@@ -1802,16 +1829,14 @@ export type RoleGrants = z.infer<typeof roleGrants>;
1802
1829
  * read-only base-tier ceiling — the seeded jq `condition` plus `base_tier`
1803
1830
  * (`editor`/`viewer`, or `null` for the reserved `allow_all` admin). Layer 2 is the
1804
1831
  * editable per-tag `grants` map. `allow_all` (admin) carries an empty `grants` map
1805
- * and reaches everything, un-lockable. `condition`/`condition_id`/`condition_kwargs`
1806
- * are the base-tier jq — READ-ONLY here (no raw-jq authoring surface).
1832
+ * and reaches everything, un-lockable. `condition` is the base-tier jq (an authored
1833
+ * templated-text value) — READ-ONLY here (no raw-jq authoring surface).
1807
1834
  */
1808
1835
  export const roleBody = z.object({
1809
1836
  name: z.string(),
1810
1837
  description: z.string(),
1811
1838
  scopes: z.array(z.string()),
1812
- condition: z.string().nullable(),
1813
- condition_id: z.string().nullable(),
1814
- condition_kwargs: jsonValue.nullable(),
1839
+ condition: templatedText.nullable(),
1815
1840
  base_tier: z.string().nullable(),
1816
1841
  allow_all: z.boolean(),
1817
1842
  grants: roleGrants,
@@ -1879,9 +1904,7 @@ export const tokensPayload = z.array(
1879
1904
  description: z.string(),
1880
1905
  scopes: z.array(z.string()),
1881
1906
  policy_data: jsonValue,
1882
- condition: z.string().nullable().optional(),
1883
- condition_id: z.string().nullable().optional(),
1884
- condition_kwargs: jsonValue.nullable().optional(),
1907
+ condition: templatedText.nullable().optional(),
1885
1908
  }),
1886
1909
  );
1887
1910
  export type TokensPayload = z.infer<typeof tokensPayload>;
@@ -2061,15 +2084,13 @@ export type ValidateConditionResult = z.infer<typeof validateConditionResult>;
2061
2084
  /**
2062
2085
  * The enforced policy shape a version body carries. SECRET-ADJACENT — `condition`
2063
2086
  * can reveal auth logic, so its fixtures are hand-authored, never captured.
2064
- * `condition`/`condition_id` are mutually exclusive at author time; both are
2065
- * nullable here because whichever mode is unused is stored as `null`.
2087
+ * `condition` is an authored templated-text value (inline content or a stored
2088
+ * template id); `null` when the policy carries no condition.
2066
2089
  */
2067
2090
  export const policyBody = z.object({
2068
2091
  scopes: z.array(z.string()),
2069
2092
  policy_data: jsonValue,
2070
- condition: z.string().nullable(),
2071
- condition_id: z.string().nullable(),
2072
- condition_kwargs: jsonValue.nullable(),
2093
+ condition: templatedText.nullable(),
2073
2094
  });
2074
2095
  export type PolicyBody = z.infer<typeof policyBody>;
2075
2096
 
@@ -2777,11 +2798,12 @@ export const stateStats = z.object({
2777
2798
  export type StateStats = z.infer<typeof stateStats>;
2778
2799
 
2779
2800
  /**
2780
- * One template jq: `jq` is a program over the subject's attached subtree, its `purpose`
2781
- * either `input` (a read-only program feeding a tool argument) or `update` (a program
2782
- * returning an op batch that mutates the record). `params` are its declared argument
2783
- * names; `reads`/`writes` are the template-relative record paths an `update` declares,
2784
- * each a list of key segments; `description` is the human label.
2801
+ * One template jq: `jq` is a program over the subject's attached subtree, authored as a
2802
+ * templated text (inline `content` or a stored template `id`); its `purpose` is either
2803
+ * `input` (a read-only program feeding a tool argument) or `update` (a program returning
2804
+ * an op batch that mutates the record). `params` are its declared argument names;
2805
+ * `reads`/`writes` are the template-relative record paths an `update` declares, each a
2806
+ * list of key segments; `description` is the human label.
2785
2807
  */
2786
2808
  export const templateJq = z.object({
2787
2809
  description: z.string().default(''),
@@ -2789,27 +2811,40 @@ export const templateJq = z.object({
2789
2811
  params: z.array(z.string()).default([]),
2790
2812
  reads: z.array(z.array(z.string())).default([]),
2791
2813
  writes: z.array(z.array(z.string())).default([]),
2792
- jq: z.string(),
2814
+ jq: templatedText,
2793
2815
  });
2794
2816
  export type TemplateJq = z.infer<typeof templateJq>;
2795
2817
 
2796
2818
  /**
2797
- * How a declarations edit settles open records: `view` reads the record, `close`
2798
- * builds the op batch that settles it, `resolutions` names the resolutions a close
2799
- * may name — each a jq program.
2819
+ * How a declarations edit settles open records: `orphans` returns the items a record
2820
+ * orphans against the new declarations, `close` builds the op batch that closes one
2821
+ * orphan, `resolutions` names the resolutions a close may name — each a templated-text
2822
+ * jq program (inline `content` or a stored template `id`).
2800
2823
  */
2801
2824
  export const templateReconcile = z.object({
2802
- view: z.string(),
2803
- close: z.string(),
2804
- resolutions: z.string(),
2825
+ orphans: templatedText,
2826
+ close: templatedText,
2827
+ resolutions: templatedText,
2805
2828
  });
2806
2829
  export type TemplateReconcile = z.infer<typeof templateReconcile>;
2807
2830
 
2831
+ /**
2832
+ * A template's declarations section: `schema` is the JSON schema of the static values an
2833
+ * attachment stores, and `check` is an optional attach-time predicate authored as a
2834
+ * templated text (inline `content` or a stored template `id`), `null` when the template
2835
+ * declares none.
2836
+ */
2837
+ export const templateDeclarations = z.object({
2838
+ schema: jsonSchema,
2839
+ check: templatedText.nullable().default(null),
2840
+ });
2841
+ export type TemplateDeclarations = z.infer<typeof templateDeclarations>;
2842
+
2808
2843
  /**
2809
2844
  * The platform half of a state-template document (mirrors StateTemplateDocument).
2810
2845
  * `template_jq` maps a name to its definition (each carrying its `purpose`);
2811
- * `reconcile` is the settle policy — both optional (`null` when the template declares
2812
- * none).
2846
+ * `reconcile` is the settle policy; `declarations` is the static-values section — all
2847
+ * optional (`null` when the template declares none).
2813
2848
  */
2814
2849
  export const stateTemplateDocument = z.object({
2815
2850
  kind: z.literal('state-template').default('state-template'),
@@ -2818,7 +2853,7 @@ export const stateTemplateDocument = z.object({
2818
2853
  parameters: z.record(z.string(), z.unknown()).default({}),
2819
2854
  schema: jsonSchema,
2820
2855
  regimes: z.array(stateRegime).default([]),
2821
- declarations: z.record(z.string(), z.unknown()).nullable().default(null),
2856
+ declarations: templateDeclarations.nullable().default(null),
2822
2857
  trace: z.record(z.string(), z.unknown()).default({}),
2823
2858
  template_jq: z.record(z.string(), templateJq).nullable().default(null),
2824
2859
  reconcile: templateReconcile.nullable().default(null),