@tanstack/ai-devtools-core 0.5.8 → 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,13 +20,20 @@ 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 {
30
+ ContentPart,
25
31
  DevtoolsToolFixtureApplyEvent,
26
32
  RunLifecycleEvent,
27
33
  } from '@tanstack/ai-event-client'
28
34
  import type { HookRegistryState, ToolFixtureRecord } from './hook-registry'
29
35
  import type { MemoryRegistryState } from './memory-registry'
36
+ import type { SkillsRegistryState } from './skills-registry'
30
37
  import type { ParentComponent } from 'solid-js'
31
38
 
32
39
  interface MessagePart {
@@ -40,7 +47,7 @@ interface MessagePart {
40
47
  | 'video'
41
48
  | 'document'
42
49
  | 'structured-output'
43
- content?: string
50
+ content?: string | Array<ContentPart>
44
51
  status?: 'streaming' | 'complete' | 'error'
45
52
  raw?: string
46
53
  partial?: unknown
@@ -235,6 +242,7 @@ interface AIStoreState {
235
242
  activeConversationId: string | null
236
243
  hooks: HookRegistryState
237
244
  memory: MemoryRegistryState
245
+ skills: SkillsRegistryState
238
246
  }
239
247
 
240
248
  interface AIContextValue {
@@ -243,6 +251,7 @@ interface AIContextValue {
243
251
  selectConversation: (id: string) => void
244
252
  clearHooks: () => void
245
253
  clearMemory: () => void
254
+ clearSkills: () => void
246
255
  selectHook: (id: string | null) => void
247
256
  saveToolFixture: (fixture: ToolFixtureRecord) => void
248
257
  deleteToolFixture: (fixtureId: string) => void
@@ -265,6 +274,7 @@ export const AIProvider: ParentComponent = (props) => {
265
274
  activeConversationId: null,
266
275
  hooks: createHookRegistryState(),
267
276
  memory: createMemoryRegistryState(),
277
+ skills: createSkillsRegistryState(),
268
278
  })
269
279
 
270
280
  const streamToConversation = new Map<string, string>()
@@ -660,6 +670,15 @@ export const AIProvider: ParentComponent = (props) => {
660
670
  )
661
671
  }
662
672
 
673
+ function clearSkills() {
674
+ setState(
675
+ 'skills',
676
+ produce((skills: SkillsRegistryState) => {
677
+ clearSkillsRegistry(skills)
678
+ }),
679
+ )
680
+ }
681
+
663
682
  function selectHook(id: string | null) {
664
683
  setState(
665
684
  'hooks',
@@ -1247,6 +1266,14 @@ export const AIProvider: ParentComponent = (props) => {
1247
1266
  }),
1248
1267
  )
1249
1268
  }),
1269
+ aiEventClient.on('skills:snapshot', (e) => {
1270
+ setState(
1271
+ 'skills',
1272
+ produce((skills: SkillsRegistryState) => {
1273
+ applySkillsSnapshot(skills, e.payload)
1274
+ }),
1275
+ )
1276
+ }),
1250
1277
  )
1251
1278
 
1252
1279
  const recordRunEvent = (
@@ -3464,6 +3491,7 @@ export const AIProvider: ParentComponent = (props) => {
3464
3491
  selectConversation,
3465
3492
  clearHooks,
3466
3493
  clearMemory,
3494
+ clearSkills,
3467
3495
  selectHook,
3468
3496
  saveToolFixture,
3469
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]};