@tai42/api-client 0.2.0 → 0.4.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/index.ts CHANGED
@@ -22,6 +22,7 @@ export type {
22
22
  CreatePresetBody,
23
23
  SavePresetVersionBody,
24
24
  ValidatePresetBody,
25
+ ToolMetaPatch,
25
26
  StorageUploadBody,
26
27
  MetricsQuery,
27
28
  RunsQuery,
@@ -86,6 +87,9 @@ export type {
86
87
  PresetValidation,
87
88
  PresetVersionTags,
88
89
  PresetExtensionElement,
90
+ FolderRecord,
91
+ ToolMetaRecord,
92
+ ToolMetaOverlay,
89
93
  PolicyBody,
90
94
  PolicyVersion,
91
95
  ValidateConditionResult,
@@ -152,7 +156,12 @@ export type {
152
156
  MarketplaceLatestVersion,
153
157
  MarketplaceAdvisory,
154
158
  MarketplacePluginDetail,
159
+ MarketplaceInstalledCompat,
155
160
  MarketplaceInstalledPlugin,
161
+ MarketplaceQuarantinedPlugin,
162
+ MarketplaceInstalled,
163
+ MarketplaceUpgradeAllRow,
164
+ MarketplaceUpgradeAllResult,
156
165
  MarketplaceInstallResult,
157
166
  MarketplaceUninstallResult,
158
167
  } from './schemas';
package/src/schemas.ts CHANGED
@@ -57,12 +57,19 @@ export const toolMediaResult = z
57
57
  export type ToolMediaResult = z.infer<typeof toolMediaResult>;
58
58
 
59
59
  /**
60
- * The ADDITIVE per-tool native-tags map (`GET /api/tools/tags`). Distinct from the
61
- * flat `toolNames` contract (`GET /api/tools`, unchanged): this surfaces each
62
- * tool's FastMCP `tags` — including the ones preset bodies project — so the shared
63
- * `ToolPicker` can group/filter its options by tag.
60
+ * The ADDITIVE per-tool native surface (`GET /api/tools/tags`). Distinct from the
61
+ * flat `toolNames` contract (`GET /api/tools`, unchanged): each entry carries the
62
+ * tool's read-only FastMCP `tags` — so the shared `ToolPicker` can group/filter its
63
+ * options — plus `hidden`, the tool's OWN plugin-declared visibility (read from the
64
+ * FastMCP `meta` under `tai42/hidden`; a tool that never declared it is not hidden).
65
+ * The tool_meta overlay's tri-state override is merged on top client-side; this read
66
+ * exposes only the declaration.
64
67
  */
65
- export const toolTagEntry = z.object({ name: z.string(), tags: z.array(z.string()) });
68
+ export const toolTagEntry = z.object({
69
+ name: z.string(),
70
+ tags: z.array(z.string()),
71
+ hidden: z.boolean(),
72
+ });
66
73
  export const toolTags = z.array(toolTagEntry);
67
74
  export type ToolTagEntry = z.infer<typeof toolTagEntry>;
68
75
 
@@ -109,9 +116,9 @@ export const presetExtensions = z.array(z.array(presetExtensionElement));
109
116
  * One preset as `GET /api/presets` returns it. Every preset is versioned, so
110
117
  * `active_version` is always an int; `conflicted` marks a QUARANTINED row (its
111
118
  * name collided with a foreign tool at boot — delete-only). `extensions` are the
112
- * ACTIVE version's extension combos, `tags` the preset's categorization labels
113
- * (distinct from a version's generic label list), and `output_schema` the
114
- * optional author-set output JSON Schema. A drift throws `ApiSchemaError`;
119
+ * ACTIVE version's extension combos and `output_schema` the optional author-set
120
+ * output JSON Schema. Categorization tags live in the tool_meta overlay
121
+ * (`GET /api/tool-meta`), never on the record. A drift throws `ApiSchemaError`;
115
122
  * nothing is coerced.
116
123
  */
117
124
  export const presetRecord = z.object({
@@ -119,7 +126,6 @@ export const presetRecord = z.object({
119
126
  base_tool: z.string(),
120
127
  description: z.string(),
121
128
  active_version: z.number(),
122
- tags: z.array(z.string()),
123
129
  extensions: presetExtensions,
124
130
  output_schema: z.record(z.string(), z.unknown()).nullable(),
125
131
  conflicted: z.boolean(),
@@ -144,7 +150,6 @@ export const presetBody = z.object({
144
150
  description: z.string(),
145
151
  fixed_kwargs: z.record(z.string(), z.unknown()),
146
152
  extensions: presetExtensions,
147
- tags: z.array(z.string()),
148
153
  output_schema: z.record(z.string(), z.unknown()).nullable(),
149
154
  });
150
155
  export type PresetBody = z.infer<typeof presetBody>;
@@ -152,7 +157,8 @@ export type PresetBody = z.infer<typeof presetBody>;
152
157
  /**
153
158
  * One immutable version row (`GET /api/presets/{name}/versions[/{version}]`).
154
159
  * `is_current` flags the active version; `tags` here is the GENERIC per-version
155
- * label list (kind-agnostic), distinct from the categorization `body.tags`.
160
+ * label list (kind-agnostic) — the only preset tags that remain, distinct from the
161
+ * removed record-level categorization and from the tool_meta overlay.
156
162
  */
157
163
  export const presetVersion = z.object({
158
164
  version: z.number(),
@@ -216,6 +222,54 @@ export const presetVersionTags = z.object({
216
222
  });
217
223
  export type PresetVersionTags = z.infer<typeof presetVersionTags>;
218
224
 
225
+ // -- tool_meta (the organizational overlay) ----------------------------------
226
+
227
+ /**
228
+ * One folder in the tool-organization tree (`tool_folders`). `parent_id` is `null`
229
+ * for a root folder and otherwise the containing folder's `id`; nesting is endless
230
+ * via the parent chain. Ids are UUID strings. A drift throws `ApiSchemaError`.
231
+ */
232
+ export const folderRecord = z.object({
233
+ id: z.string(),
234
+ name: z.string(),
235
+ parent_id: z.string().nullable(),
236
+ });
237
+ export type FolderRecord = z.infer<typeof folderRecord>;
238
+
239
+ /**
240
+ * The organizational overlay for one tool, keyed by `tool_name`. `display_name`
241
+ * overrides the rendered label (`display_name ?? name`); `folder_id` places the tool
242
+ * in a folder (`null` = unfiled); `tags` is the user's editable categorization,
243
+ * merged with the tool's read-only native tags by the UI; `hidden` is TRI-STATE —
244
+ * `null` = defer to the plugin declaration, `true` = force hidden, `false` = force
245
+ * visible. A drift throws `ApiSchemaError`.
246
+ */
247
+ export const toolMetaRecord = z.object({
248
+ tool_name: z.string(),
249
+ display_name: z.string().nullable(),
250
+ folder_id: z.string().nullable(),
251
+ tags: z.array(z.string()),
252
+ hidden: z.boolean().nullable(),
253
+ });
254
+ export type ToolMetaRecord = z.infer<typeof toolMetaRecord>;
255
+
256
+ /**
257
+ * `GET /api/tool-meta` — the whole overlay in one read: the flat folder tree plus
258
+ * every per-tool row. The UI builds the tree and merges the rows against the live
259
+ * tool list client-side. A drift throws `ApiSchemaError`.
260
+ */
261
+ export const toolMetaOverlay = z.object({
262
+ folders: z.array(folderRecord),
263
+ meta: z.array(toolMetaRecord),
264
+ });
265
+ export type ToolMetaOverlay = z.infer<typeof toolMetaOverlay>;
266
+
267
+ /** `DELETE /api/tool-meta/tools/{tool_name}` — the dropped overlay row (idempotent). */
268
+ export const toolMetaDeleted = z.object({ tool_name: z.string(), deleted: z.literal(true) });
269
+
270
+ /** `DELETE /api/tool-meta/folders/{folder_id}` — the removed empty folder. */
271
+ export const folderDeleted = z.object({ folder_id: z.string(), deleted: z.literal(true) });
272
+
219
273
  // -- templates ---------------------------------------------------------------
220
274
 
221
275
  export const templateNames = z.array(z.string());
@@ -1446,25 +1500,90 @@ export const marketplacePluginDetail = z.object({
1446
1500
  });
1447
1501
  export type MarketplacePluginDetail = z.infer<typeof marketplacePluginDetail>;
1448
1502
 
1503
+ /**
1504
+ * One installed plugin's compat verdict against the RUNNING tai42-contract:
1505
+ * `compatible` / `incompatible` per its declared contract range, `unknown` when
1506
+ * no verdict could be computed. `reason` is the human-readable explanation of a
1507
+ * non-`compatible` verdict, `null` when compatible. CLOSED (`.strict()`): the
1508
+ * server is built against exactly this shape, so an unknown key is drift and
1509
+ * throws instead of being stripped.
1510
+ */
1511
+ export const marketplaceInstalledCompat = z
1512
+ .object({
1513
+ status: z.enum(['compatible', 'incompatible', 'unknown']),
1514
+ reason: z.string().nullable(),
1515
+ })
1516
+ .strict();
1517
+ export type MarketplaceInstalledCompat = z.infer<typeof marketplaceInstalledCompat>;
1518
+
1449
1519
  /**
1450
1520
  * One installed marketplace plugin as the local attribution store records it.
1451
- * `latest` is the newest registry version (`null` when unknown); update
1452
- * availability comes from the wire field `update_available` (computed
1453
- * server-side as a PEP 440 comparison). `missing_upstream` flags a plugin the
1454
- * registry no longer lists.
1521
+ * `latest` is the newest registry version (`null` when unknown);
1522
+ * `update_available` advertises only a newer COMPATIBLE version, and
1523
+ * `incompatible_newer` names the newest version blocked by the running
1524
+ * contract (`null` when none), so "an update exists but needs a newer core" is
1525
+ * visible. `missing_upstream` flags a plugin the registry no longer lists.
1526
+ * `compat` is the row's verdict against the running contract. CLOSED, like
1527
+ * every shape of the installed listing.
1455
1528
  */
1456
- export const marketplaceInstalledPlugin = z.object({
1457
- ref: z.string(),
1458
- version: z.string(),
1459
- source: z.string(),
1460
- installed_at: z.string(),
1461
- latest: z.string().nullable(),
1462
- update_available: z.boolean(),
1463
- missing_upstream: z.boolean(),
1464
- });
1465
- export const marketplaceInstalled = z.array(marketplaceInstalledPlugin);
1529
+ export const marketplaceInstalledPlugin = z
1530
+ .object({
1531
+ ref: z.string(),
1532
+ version: z.string(),
1533
+ source: z.string(),
1534
+ installed_at: z.string(),
1535
+ latest: z.string().nullable(),
1536
+ update_available: z.boolean(),
1537
+ incompatible_newer: z.string().nullable(),
1538
+ missing_upstream: z.boolean(),
1539
+ compat: marketplaceInstalledCompat,
1540
+ })
1541
+ .strict();
1466
1542
  export type MarketplaceInstalledPlugin = z.infer<typeof marketplaceInstalledPlugin>;
1467
1543
 
1544
+ /** One plugin the boot pass quarantined instead of loading, with why. CLOSED. */
1545
+ export const marketplaceQuarantinedPlugin = z
1546
+ .object({
1547
+ name: z.string(),
1548
+ reason: z.string(),
1549
+ })
1550
+ .strict();
1551
+ export type MarketplaceQuarantinedPlugin = z.infer<typeof marketplaceQuarantinedPlugin>;
1552
+
1553
+ /**
1554
+ * The installed inventory (`GET /api/marketplace/installed`): the attributed
1555
+ * rows plus every plugin the boot pass quarantined instead of loading. CLOSED.
1556
+ */
1557
+ export const marketplaceInstalled = z
1558
+ .object({
1559
+ installed: z.array(marketplaceInstalledPlugin),
1560
+ quarantined: z.array(marketplaceQuarantinedPlugin),
1561
+ })
1562
+ .strict();
1563
+ export type MarketplaceInstalled = z.infer<typeof marketplaceInstalled>;
1564
+
1565
+ /**
1566
+ * One per-plugin outcome of `POST /api/marketplace/upgrade-all`: `upgraded`,
1567
+ * already `up-to-date`, `no-compatible-version` in the registry, or `failed`;
1568
+ * `detail` always carries the human-readable specifics. CLOSED.
1569
+ */
1570
+ export const marketplaceUpgradeAllRow = z
1571
+ .object({
1572
+ ref: z.string(),
1573
+ outcome: z.enum(['upgraded', 'up-to-date', 'no-compatible-version', 'failed']),
1574
+ detail: z.string(),
1575
+ })
1576
+ .strict();
1577
+ export type MarketplaceUpgradeAllRow = z.infer<typeof marketplaceUpgradeAllRow>;
1578
+
1579
+ /** The whole upgrade-all readout: one outcome row per installed plugin. CLOSED. */
1580
+ export const marketplaceUpgradeAllResult = z
1581
+ .object({
1582
+ results: z.array(marketplaceUpgradeAllRow),
1583
+ })
1584
+ .strict();
1585
+ export type MarketplaceUpgradeAllResult = z.infer<typeof marketplaceUpgradeAllResult>;
1586
+
1468
1587
  /** The advisory state for installed plugins, with when it was last fetched. */
1469
1588
  export const marketplaceAdvisories = z.object({
1470
1589
  advisories: z.array(marketplaceAdvisory),