@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.
- package/dist/components/components.css +1 -1
- package/dist/components/entity-card-grid.d.ts +15 -0
- package/dist/components/entity-card-grid.d.ts.map +1 -0
- package/dist/components/entity-card-grid.js +5 -0
- package/dist/components/entity-card-grid.js.map +1 -0
- package/dist/components/extension-combo-builder.d.ts.map +1 -1
- package/dist/components/extension-combo-builder.js +1 -1
- package/dist/components/extension-combo-builder.js.map +1 -1
- package/dist/components/folder-nav.d.ts +63 -0
- package/dist/components/folder-nav.d.ts.map +1 -0
- package/dist/components/folder-nav.js +123 -0
- package/dist/components/folder-nav.js.map +1 -0
- package/dist/components/icons.d.ts +4 -0
- package/dist/components/icons.d.ts.map +1 -1
- package/dist/components/icons.js +4 -0
- package/dist/components/icons.js.map +1 -1
- package/dist/components/overlay-details-fields.d.ts +50 -0
- package/dist/components/overlay-details-fields.d.ts.map +1 -0
- package/dist/components/overlay-details-fields.js +17 -0
- package/dist/components/overlay-details-fields.js.map +1 -0
- package/dist/components/view-toggle.d.ts +31 -0
- package/dist/components/view-toggle.d.ts.map +1 -0
- package/dist/components/view-toggle.js +59 -0
- package/dist/components/view-toggle.js.map +1 -0
- package/dist/hooks/useApi.d.ts +72 -15
- package/dist/hooks/useApi.d.ts.map +1 -1
- package/dist/index.d.ts +13 -4
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +8 -2
- package/dist/index.js.map +1 -1
- package/dist/navigation/context.d.ts +8 -0
- package/dist/navigation/context.d.ts.map +1 -1
- package/dist/navigation/context.js +11 -0
- package/dist/navigation/context.js.map +1 -1
- package/dist/navigation/index.d.ts +2 -2
- package/dist/navigation/index.d.ts.map +1 -1
- package/dist/navigation/index.js +1 -1
- package/dist/navigation/index.js.map +1 -1
- package/dist/navigation/types.d.ts +14 -0
- package/dist/navigation/types.d.ts.map +1 -1
- package/dist/plugin/types.d.ts +51 -1
- package/dist/plugin/types.d.ts.map +1 -1
- package/dist/tool-visibility.d.ts +32 -0
- package/dist/tool-visibility.d.ts.map +1 -0
- package/dist/tool-visibility.js +33 -0
- package/dist/tool-visibility.js.map +1 -0
- package/package.json +2 -2
- package/src/components/components.css +1 -1
- package/src/components/entity-card-grid.tsx +25 -0
- package/src/components/extension-combo-builder.tsx +3 -1
- package/src/components/folder-nav.tsx +255 -0
- package/src/components/icons.tsx +17 -0
- package/src/components/overlay-details-fields.tsx +102 -0
- package/src/components/view-toggle.tsx +92 -0
- package/src/index.ts +37 -1
- package/src/navigation/context.tsx +15 -0
- package/src/navigation/index.ts +8 -1
- package/src/navigation/types.ts +25 -0
- package/src/plugin/types.ts +54 -1
- package/src/tool-visibility.ts +53 -0
package/src/navigation/types.ts
CHANGED
|
@@ -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
|
}
|
package/src/plugin/types.ts
CHANGED
|
@@ -45,9 +45,39 @@ export interface ToolPanelProps {
|
|
|
45
45
|
readonly run: (args: Record<string, unknown>) => Promise<unknown>;
|
|
46
46
|
}
|
|
47
47
|
|
|
48
|
-
/**
|
|
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
|
+
}
|