@tanstack/ai-devtools-core 0.5.9 → 0.5.10

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.
@@ -2,4 +2,5 @@ export { HookDashboard } from './HookDashboard'
2
2
  export { HookDetails } from './HookDetails'
3
3
  export { GenerationPanel, GenerationPreview } from './GenerationPanel'
4
4
  export { MemoryPanel } from './MemoryPanel'
5
+ export { SkillsPanel } from './SkillsPanel'
5
6
  export { ToolFixtureForm } from './ToolFixtureForm'
@@ -20,6 +20,11 @@ import {
20
20
  clearMemoryRegistry,
21
21
  createMemoryRegistryState,
22
22
  } from './memory-registry'
23
+ import {
24
+ applySkillsSnapshot,
25
+ clearSkillsRegistry,
26
+ createSkillsRegistryState,
27
+ } from './skills-registry'
23
28
  import type { ContentPartSource, TokenUsage } from '@tanstack/ai'
24
29
  import type {
25
30
  ContentPart,
@@ -28,6 +33,7 @@ import type {
28
33
  } from '@tanstack/ai-event-client'
29
34
  import type { HookRegistryState, ToolFixtureRecord } from './hook-registry'
30
35
  import type { MemoryRegistryState } from './memory-registry'
36
+ import type { SkillsRegistryState } from './skills-registry'
31
37
  import type { ParentComponent } from 'solid-js'
32
38
 
33
39
  interface MessagePart {
@@ -236,6 +242,7 @@ interface AIStoreState {
236
242
  activeConversationId: string | null
237
243
  hooks: HookRegistryState
238
244
  memory: MemoryRegistryState
245
+ skills: SkillsRegistryState
239
246
  }
240
247
 
241
248
  interface AIContextValue {
@@ -244,6 +251,7 @@ interface AIContextValue {
244
251
  selectConversation: (id: string) => void
245
252
  clearHooks: () => void
246
253
  clearMemory: () => void
254
+ clearSkills: () => void
247
255
  selectHook: (id: string | null) => void
248
256
  saveToolFixture: (fixture: ToolFixtureRecord) => void
249
257
  deleteToolFixture: (fixtureId: string) => void
@@ -266,6 +274,7 @@ export const AIProvider: ParentComponent = (props) => {
266
274
  activeConversationId: null,
267
275
  hooks: createHookRegistryState(),
268
276
  memory: createMemoryRegistryState(),
277
+ skills: createSkillsRegistryState(),
269
278
  })
270
279
 
271
280
  const streamToConversation = new Map<string, string>()
@@ -661,6 +670,15 @@ export const AIProvider: ParentComponent = (props) => {
661
670
  )
662
671
  }
663
672
 
673
+ function clearSkills() {
674
+ setState(
675
+ 'skills',
676
+ produce((skills: SkillsRegistryState) => {
677
+ clearSkillsRegistry(skills)
678
+ }),
679
+ )
680
+ }
681
+
664
682
  function selectHook(id: string | null) {
665
683
  setState(
666
684
  'hooks',
@@ -1248,6 +1266,14 @@ export const AIProvider: ParentComponent = (props) => {
1248
1266
  }),
1249
1267
  )
1250
1268
  }),
1269
+ aiEventClient.on('skills:snapshot', (e) => {
1270
+ setState(
1271
+ 'skills',
1272
+ produce((skills: SkillsRegistryState) => {
1273
+ applySkillsSnapshot(skills, e.payload)
1274
+ }),
1275
+ )
1276
+ }),
1251
1277
  )
1252
1278
 
1253
1279
  const recordRunEvent = (
@@ -3465,6 +3491,7 @@ export const AIProvider: ParentComponent = (props) => {
3465
3491
  selectConversation,
3466
3492
  clearHooks,
3467
3493
  clearMemory,
3494
+ clearSkills,
3468
3495
  selectHook,
3469
3496
  saveToolFixture,
3470
3497
  deleteToolFixture,
@@ -0,0 +1,50 @@
1
+ /**
2
+ * DevTools accumulator for the `skills:snapshot` event. Pure reducers so the
3
+ * mapping is unit-testable without a Solid store.
4
+ *
5
+ * Keyed by hookId (the chat client that received the CUSTOM chunk). The Skills
6
+ * tab resolves the active hook and reads that snapshot.
7
+ */
8
+
9
+ export interface SkillCatalogEntry {
10
+ name: string
11
+ description: string
12
+ }
13
+
14
+ export interface SkillsSnapshot {
15
+ catalog: Array<SkillCatalogEntry>
16
+ activated: Array<string>
17
+ updatedAt: number
18
+ }
19
+
20
+ export interface SkillsRegistryState {
21
+ snapshots: Record<string, SkillsSnapshot>
22
+ }
23
+
24
+ export function createSkillsRegistryState(): SkillsRegistryState {
25
+ return { snapshots: {} }
26
+ }
27
+
28
+ export function clearSkillsRegistry(state: SkillsRegistryState): void {
29
+ state.snapshots = {}
30
+ }
31
+
32
+ export function applySkillsSnapshot(
33
+ state: SkillsRegistryState,
34
+ payload: {
35
+ hookId?: string
36
+ catalog?: Array<SkillCatalogEntry>
37
+ activated?: Array<string>
38
+ timestamp?: number
39
+ },
40
+ ): void {
41
+ const key =
42
+ payload.hookId && payload.hookId.length > 0 ? payload.hookId : '_default'
43
+ const catalog = Array.isArray(payload.catalog) ? payload.catalog : []
44
+ const activated = Array.isArray(payload.activated) ? payload.activated : []
45
+ state.snapshots[key] = {
46
+ catalog,
47
+ activated,
48
+ updatedAt: payload.timestamp ?? Date.now(),
49
+ }
50
+ }
@@ -1695,7 +1695,6 @@ const stylesFactory = (theme: 'light' | 'dark') => {
1695
1695
  border: 1px solid ${t(colors.gray[200], colors.darkGray[600])};
1696
1696
  border-radius: ${border.radius.sm};
1697
1697
  background: ${t(colors.white, colors.darkGray[900])};
1698
- min-height: 260px;
1699
1698
  max-height: 420px;
1700
1699
  overflow: auto;
1701
1700
  padding: ${size[2]} ${size[2]} ${size[2]} ${size[5]};
@@ -2570,7 +2569,7 @@ const stylesFactory = (theme: 'light' | 'dark') => {
2570
2569
  gap: ${size[3]};
2571
2570
  align-items: start;
2572
2571
  & > * {
2573
- min-height: 280px;
2572
+ max-height: 420px;
2574
2573
  border: 1px solid oklch(0.28 0.03 260);
2575
2574
  border-radius: 6px;
2576
2575
  background: oklch(0.18 0.02 260);
@@ -3634,7 +3633,6 @@ const stylesFactory = (theme: 'light' | 'dark') => {
3634
3633
  `,
3635
3634
  stepJsonPanel: css`
3636
3635
  margin: ${size[1.5]} ${size[3]};
3637
- min-height: 280px;
3638
3636
  max-height: 520px;
3639
3637
  overflow: auto;
3640
3638
  padding: ${size[2]} ${size[2]} ${size[2]} ${size[5]};