@tai42/studio-sdk 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.
Files changed (60) hide show
  1. package/dist/components/components.css +1 -1
  2. package/dist/components/entity-card-grid.d.ts +15 -0
  3. package/dist/components/entity-card-grid.d.ts.map +1 -0
  4. package/dist/components/entity-card-grid.js +5 -0
  5. package/dist/components/entity-card-grid.js.map +1 -0
  6. package/dist/components/extension-combo-builder.d.ts.map +1 -1
  7. package/dist/components/extension-combo-builder.js +1 -1
  8. package/dist/components/extension-combo-builder.js.map +1 -1
  9. package/dist/components/folder-nav.d.ts +63 -0
  10. package/dist/components/folder-nav.d.ts.map +1 -0
  11. package/dist/components/folder-nav.js +123 -0
  12. package/dist/components/folder-nav.js.map +1 -0
  13. package/dist/components/icons.d.ts +4 -0
  14. package/dist/components/icons.d.ts.map +1 -1
  15. package/dist/components/icons.js +4 -0
  16. package/dist/components/icons.js.map +1 -1
  17. package/dist/components/overlay-details-fields.d.ts +50 -0
  18. package/dist/components/overlay-details-fields.d.ts.map +1 -0
  19. package/dist/components/overlay-details-fields.js +17 -0
  20. package/dist/components/overlay-details-fields.js.map +1 -0
  21. package/dist/components/view-toggle.d.ts +31 -0
  22. package/dist/components/view-toggle.d.ts.map +1 -0
  23. package/dist/components/view-toggle.js +59 -0
  24. package/dist/components/view-toggle.js.map +1 -0
  25. package/dist/hooks/useApi.d.ts +72 -15
  26. package/dist/hooks/useApi.d.ts.map +1 -1
  27. package/dist/index.d.ts +13 -4
  28. package/dist/index.d.ts.map +1 -1
  29. package/dist/index.js +8 -2
  30. package/dist/index.js.map +1 -1
  31. package/dist/navigation/context.d.ts +8 -0
  32. package/dist/navigation/context.d.ts.map +1 -1
  33. package/dist/navigation/context.js +11 -0
  34. package/dist/navigation/context.js.map +1 -1
  35. package/dist/navigation/index.d.ts +2 -2
  36. package/dist/navigation/index.d.ts.map +1 -1
  37. package/dist/navigation/index.js +1 -1
  38. package/dist/navigation/index.js.map +1 -1
  39. package/dist/navigation/types.d.ts +14 -0
  40. package/dist/navigation/types.d.ts.map +1 -1
  41. package/dist/plugin/types.d.ts +51 -1
  42. package/dist/plugin/types.d.ts.map +1 -1
  43. package/dist/tool-visibility.d.ts +32 -0
  44. package/dist/tool-visibility.d.ts.map +1 -0
  45. package/dist/tool-visibility.js +33 -0
  46. package/dist/tool-visibility.js.map +1 -0
  47. package/package.json +2 -2
  48. package/src/components/components.css +1 -1
  49. package/src/components/entity-card-grid.tsx +25 -0
  50. package/src/components/extension-combo-builder.tsx +3 -1
  51. package/src/components/folder-nav.tsx +255 -0
  52. package/src/components/icons.tsx +17 -0
  53. package/src/components/overlay-details-fields.tsx +102 -0
  54. package/src/components/view-toggle.tsx +92 -0
  55. package/src/index.ts +37 -1
  56. package/src/navigation/context.tsx +15 -0
  57. package/src/navigation/index.ts +8 -1
  58. package/src/navigation/types.ts +25 -0
  59. package/src/plugin/types.ts +54 -1
  60. package/src/tool-visibility.ts +53 -0
@@ -77,14 +77,39 @@ export interface PageProps<T extends RouteToken> {
77
77
  search: RouteSearch<T>;
78
78
  }
79
79
 
80
+ /**
81
+ * A plugin page's deep-link search object. Plugin paths are RUNTIME contributions
82
+ * outside the compile-time {@link RouteToken} map, so their search is an open bag of
83
+ * serializable values (the page's own {@link PluginPageParamsSchema} validates it);
84
+ * this is deliberately NOT a `RouteSearch`.
85
+ */
86
+ export type PluginSearch = Record<string, unknown>;
87
+
80
88
  /**
81
89
  * The runtime navigation surface the shell provides through
82
90
  * {@link NavigationProvider}. `navigate` performs a client-side transition;
83
91
  * `resolvePath` produces the href a link should point at (so an AppLink is a real
84
92
  * anchor — middle-click / open-in-new-tab work — while still driving a
85
93
  * client-side transition on plain click).
94
+ *
95
+ * `navigatePlugin`/`resolvePluginPath` are the plugin-page twins: they target a
96
+ * runtime plugin path (`/plugins/{pluginId}/{pagePath}` plus an optional validated
97
+ * sub-path `params` and `search`), NOT a route token — `routes.ts` never learns
98
+ * plugin paths. Plugins reach these two via the {@link usePluginNavigation} hook.
86
99
  */
87
100
  export interface NavigationContextValue {
88
101
  navigate: <T extends RouteToken>(token: T, search?: RouteSearch<T>) => void;
89
102
  resolvePath: <T extends RouteToken>(token: T, search?: RouteSearch<T>) => string;
103
+ navigatePlugin: (
104
+ pluginId: string,
105
+ pagePath: string,
106
+ params?: string,
107
+ search?: PluginSearch,
108
+ ) => void;
109
+ resolvePluginPath: (
110
+ pluginId: string,
111
+ pagePath: string,
112
+ params?: string,
113
+ search?: PluginSearch,
114
+ ) => string;
90
115
  }
@@ -45,9 +45,39 @@ export interface ToolPanelProps {
45
45
  readonly run: (args: Record<string, unknown>) => Promise<unknown>;
46
46
  }
47
47
 
48
- /** Props a contributed full page receives. Navigation is via shell route tokens. */
48
+ /**
49
+ * Props a contributed full page receives. A page is deep-linkable: the shell mounts
50
+ * it at `/plugins/{pluginId}/{path}` and, when the contribution declares a
51
+ * {@link PluginPageParamsSchema}, forwards the VALIDATED sub-path remainder as
52
+ * `params` and the VALIDATED search object as `search`. Both are OPTIONAL — a page
53
+ * that declares no schema receives neither (and accepts no sub-path), so this stays
54
+ * a non-breaking addition to every existing contribution and the plugin API version
55
+ * does not move. Navigate between plugin pages with `usePluginNavigation`.
56
+ */
49
57
  export interface PluginPageProps {
50
58
  readonly pluginId: string;
59
+ /** The validated sub-path remainder (present only when the page declared a schema). */
60
+ readonly params?: Record<string, unknown>;
61
+ /** The validated search object (present only when the page declared a schema). */
62
+ readonly search?: Record<string, unknown>;
63
+ }
64
+
65
+ /**
66
+ * A page's optional deep-link schema. The shell resolves a URL to a page by
67
+ * LONGEST registered `path` prefix; the remainder of the URL after the matched
68
+ * prefix is handed to `parseParams`, and the raw search object to `parseSearch`.
69
+ * Each parser VALIDATES and shapes its input, RAISING on anything it rejects — the
70
+ * shell renders that throw as a loud error card, never a blank or partial view. A
71
+ * contribution that omits the schema entirely accepts no sub-path (the pre-deep-link
72
+ * behavior, unchanged). Omitting just one parser leaves that half unvalidated:
73
+ * absent `parseParams` means the page still matches only its exact `path`; absent
74
+ * `parseSearch` means `search` is not forwarded.
75
+ */
76
+ export interface PluginPageParamsSchema {
77
+ /** Validate + shape the sub-path remainder after this page's prefix; throws to reject. */
78
+ readonly parseParams?: (remainder: string) => Record<string, unknown>;
79
+ /** Validate + shape the raw search object; throws to reject. */
80
+ readonly parseSearch?: (raw: Record<string, unknown>) => Record<string, unknown>;
51
81
  }
52
82
 
53
83
  /** Props a contributed settings tab receives. */
@@ -67,6 +97,13 @@ export interface PageContribution {
67
97
  readonly component: ComponentType<PluginPageProps>;
68
98
  /** Capability gate (see {@link RequiredCapabilities}); absent ⇒ full-only. */
69
99
  readonly requiredCapabilities?: RequiredCapabilities;
100
+ /**
101
+ * Deep-link schema (see {@link PluginPageParamsSchema}). When present the page is
102
+ * addressable under its `path` PREFIX, and the shell validates the sub-path
103
+ * remainder + search before rendering. Absent ⇒ the page matches only its exact
104
+ * `path` and receives no `params`/`search` (unchanged behavior).
105
+ */
106
+ readonly params?: PluginPageParamsSchema;
70
107
  }
71
108
 
72
109
  /**
@@ -81,6 +118,16 @@ export interface RegisteredPage extends PageContribution {
81
118
  readonly pluginId: string;
82
119
  }
83
120
 
121
+ /**
122
+ * The sidebar section a nav entry renders in. A named core section groups the
123
+ * entry there, after that section's core rows; `'Plugins'`, an absent field, or
124
+ * any unrecognised value falls to the Plugins section. The shell tolerates an
125
+ * unknown value at runtime (a bundle newer than this host), so the field is a
126
+ * placement hint, never a hard contract.
127
+ */
128
+ export type NavEntrySection =
129
+ 'Capabilities' | 'Integrations' | 'Activity' | 'Administration' | 'Plugins';
130
+
84
131
  export interface NavEntryContribution {
85
132
  /**
86
133
  * Path of a page THIS plugin registers. The nav entry links to
@@ -89,6 +136,12 @@ export interface NavEntryContribution {
89
136
  */
90
137
  readonly path: string;
91
138
  readonly title: string;
139
+ /**
140
+ * Optional target sidebar section (see {@link NavEntrySection}); absent ⇒ the
141
+ * Plugins section. Additive — an older bundle omits it and stays on the same
142
+ * plugin API version.
143
+ */
144
+ readonly section?: NavEntrySection;
92
145
  /**
93
146
  * Optional icon rendered before the title. It must be a square inline SVG that
94
147
  * fills its box and draws with `currentColor`; the host constrains the slot,
@@ -0,0 +1,53 @@
1
+ /**
2
+ * The tool-visibility tri-state, shared by every surface that must honor it: the
3
+ * tools screen's list (and its "show hidden" toggle) and every tool picker.
4
+ *
5
+ * EFFECTIVE hidden is the overlay's tri-state OVERRIDE of the plugin's own
6
+ * declaration: an overlay opinion (`true`/`false`) wins, else the plugin
7
+ * declaration stands. So an overlay `false` UNHIDES a plugin-hidden tool, `true`
8
+ * force-hides, and `null` (no overlay row is the same) DEFERS to the declaration
9
+ * (PLAN §Tools-read-surface). The rule lives here ONCE so the list-exclusion and
10
+ * the picker-exclusion can never drift apart.
11
+ */
12
+ import type { ToolMetaRecord, ToolTagEntry } from '@tai42/api-client';
13
+
14
+ /**
15
+ * Effective hidden after the tri-state override. `overlayHidden` is the overlay's
16
+ * `hidden` (`true`/`false`), or `null`/`undefined` when the overlay defers or has
17
+ * no row; `declaredHidden` is the plugin's own `hidden`. Overlay opinion wins;
18
+ * absence defers to the declaration.
19
+ */
20
+ export function effectiveHidden(
21
+ overlayHidden: boolean | null | undefined,
22
+ declaredHidden: boolean,
23
+ ): boolean {
24
+ return overlayHidden ?? declaredHidden;
25
+ }
26
+
27
+ /**
28
+ * The set of tool names whose EFFECTIVE visibility is hidden, from the native
29
+ * declarations (`listToolTags`) merged with the tool_meta overlay (`listToolMeta`).
30
+ * A picker excludes exactly these names from its options; the server stays the
31
+ * authority (a slipped-through name is rejected loudly there), so a name in the set
32
+ * that is not among a picker's options is simply inert.
33
+ *
34
+ * The union of both sources is walked so an overlay row that force-hides a tool
35
+ * carrying no native tag entry is still caught, and an overlay `false` on a
36
+ * plugin-hidden tool correctly keeps it OUT of the set (unhidden).
37
+ */
38
+ export function hiddenToolNames(
39
+ tagEntries: readonly ToolTagEntry[],
40
+ overlayRows: readonly ToolMetaRecord[],
41
+ ): Set<string> {
42
+ const declaredByName = new Map(tagEntries.map((entry) => [entry.name, entry.hidden]));
43
+ const overlayByName = new Map(overlayRows.map((row) => [row.tool_name, row.hidden]));
44
+ const names = new Set<string>([...declaredByName.keys(), ...overlayByName.keys()]);
45
+
46
+ const hidden = new Set<string>();
47
+ for (const name of names) {
48
+ if (effectiveHidden(overlayByName.get(name) ?? null, declaredByName.get(name) ?? false)) {
49
+ hidden.add(name);
50
+ }
51
+ }
52
+ return hidden;
53
+ }