@tanstack/ai-devtools-core 0.0.3 → 0.1.1
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/README.md +26 -0
- package/dist/esm/components/ConversationDetails.js +0 -15
- package/dist/esm/components/ConversationDetails.js.map +1 -1
- package/dist/esm/components/conversation/ChunksCollapsible.js.map +1 -1
- package/dist/esm/components/conversation/ConversationTabs.d.ts +1 -1
- package/dist/esm/components/conversation/ConversationTabs.js +6 -22
- package/dist/esm/components/conversation/ConversationTabs.js.map +1 -1
- package/dist/esm/components/conversation/index.d.ts +0 -1
- package/dist/esm/store/ai-context.d.ts +0 -11
- package/dist/esm/store/ai-context.js +3 -57
- package/dist/esm/store/ai-context.js.map +1 -1
- package/package.json +3 -3
- package/src/components/ConversationDetails.tsx +0 -9
- package/src/components/conversation/ChunksCollapsible.tsx +1 -3
- package/src/components/conversation/ConversationTabs.tsx +1 -17
- package/src/components/conversation/index.ts +0 -1
- package/src/store/ai-context.tsx +3 -94
- package/dist/esm/components/conversation/EmbeddingsTab.d.ts +0 -7
- package/dist/esm/components/conversation/EmbeddingsTab.js +0 -90
- package/dist/esm/components/conversation/EmbeddingsTab.js.map +0 -1
- package/src/components/conversation/EmbeddingsTab.tsx +0 -80
package/README.md
CHANGED
|
@@ -38,7 +38,9 @@
|
|
|
38
38
|
A powerful, type-safe AI SDK for building AI-powered applications.
|
|
39
39
|
|
|
40
40
|
- Provider-agnostic adapters (OpenAI, Anthropic, Gemini, Ollama, etc.)
|
|
41
|
+
- **Tree-shakeable adapters** - Import only what you need for smaller bundles
|
|
41
42
|
- **Multimodal content support** - Send images, audio, video, and documents
|
|
43
|
+
- **Image generation** - Generate images with OpenAI DALL-E/GPT-Image and Gemini Imagen
|
|
42
44
|
- Chat completion, streaming, and agent loop strategies
|
|
43
45
|
- Headless chat state management with adapters (SSE, HTTP stream, custom)
|
|
44
46
|
- Isomorphic type-safe tools with server/client execution
|
|
@@ -46,6 +48,30 @@ A powerful, type-safe AI SDK for building AI-powered applications.
|
|
|
46
48
|
|
|
47
49
|
### <a href="https://tanstack.com/ai">Read the docs →</b></a>
|
|
48
50
|
|
|
51
|
+
## Tree-Shakeable Adapters
|
|
52
|
+
|
|
53
|
+
Import only the functionality you need for smaller bundle sizes:
|
|
54
|
+
|
|
55
|
+
```typescript
|
|
56
|
+
// Only chat functionality - no summarization code bundled
|
|
57
|
+
import { openaiText } from '@tanstack/ai-openai/adapters'
|
|
58
|
+
import { generate } from '@tanstack/ai'
|
|
59
|
+
|
|
60
|
+
const textAdapter = openaiText()
|
|
61
|
+
|
|
62
|
+
const result = generate({
|
|
63
|
+
adapter: textAdapter,
|
|
64
|
+
model: 'gpt-4o',
|
|
65
|
+
messages: [{ role: 'user', content: [{ type: 'text', content: 'Hello!' }] }],
|
|
66
|
+
})
|
|
67
|
+
|
|
68
|
+
for await (const chunk of result) {
|
|
69
|
+
console.log(chunk)
|
|
70
|
+
}
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
Available adapters: `openaiText`, `openaiEmbed`, `openaiSummarize`, `anthropicText`, `geminiText`, `ollamaText`, and more.
|
|
74
|
+
|
|
49
75
|
## Bonus: TanStack Start Integration
|
|
50
76
|
|
|
51
77
|
TanStack AI works with **any** framework (Next.js, Express, Remix, etc.).
|
|
@@ -6,7 +6,6 @@ import { ConversationHeader } from "./conversation/ConversationHeader.js";
|
|
|
6
6
|
import { ConversationTabs } from "./conversation/ConversationTabs.js";
|
|
7
7
|
import { MessagesTab } from "./conversation/MessagesTab.js";
|
|
8
8
|
import { ChunksTab } from "./conversation/ChunksTab.js";
|
|
9
|
-
import { EmbeddingsTab } from "./conversation/EmbeddingsTab.js";
|
|
10
9
|
import { SummariesTab } from "./conversation/SummariesTab.js";
|
|
11
10
|
var _tmpl$ = /* @__PURE__ */ template(`<div>Select a conversation to view details`), _tmpl$2 = /* @__PURE__ */ template(`<div><div>`);
|
|
12
11
|
const ConversationDetails = () => {
|
|
@@ -25,8 +24,6 @@ const ConversationDetails = () => {
|
|
|
25
24
|
if (conv.type === "server") {
|
|
26
25
|
if (conv.chunks.length > 0) {
|
|
27
26
|
setActiveTab("chunks");
|
|
28
|
-
} else if (conv.hasEmbedding || conv.embeddings && conv.embeddings.length > 0) {
|
|
29
|
-
setActiveTab("embeddings");
|
|
30
27
|
} else if (conv.hasSummarize || conv.summaries && conv.summaries.length > 0) {
|
|
31
28
|
setActiveTab("summaries");
|
|
32
29
|
} else {
|
|
@@ -91,18 +88,6 @@ const ConversationDetails = () => {
|
|
|
91
88
|
});
|
|
92
89
|
}
|
|
93
90
|
}), null);
|
|
94
|
-
insert(_el$3, createComponent(Show, {
|
|
95
|
-
get when() {
|
|
96
|
-
return activeTab() === "embeddings";
|
|
97
|
-
},
|
|
98
|
-
get children() {
|
|
99
|
-
return createComponent(EmbeddingsTab, {
|
|
100
|
-
get embeddings() {
|
|
101
|
-
return conv().embeddings ?? [];
|
|
102
|
-
}
|
|
103
|
-
});
|
|
104
|
-
}
|
|
105
|
-
}), null);
|
|
106
91
|
insert(_el$3, createComponent(Show, {
|
|
107
92
|
get when() {
|
|
108
93
|
return activeTab() === "summaries";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ConversationDetails.js","sources":["../../../src/components/ConversationDetails.tsx"],"sourcesContent":["import { Show, createEffect, createSignal } from 'solid-js'\nimport { useStyles } from '../styles/use-styles'\nimport { useAIStore } from '../store/ai-context'\nimport {\n ChunksTab,\n ConversationHeader,\n ConversationTabs,\n
|
|
1
|
+
{"version":3,"file":"ConversationDetails.js","sources":["../../../src/components/ConversationDetails.tsx"],"sourcesContent":["import { Show, createEffect, createSignal } from 'solid-js'\nimport { useStyles } from '../styles/use-styles'\nimport { useAIStore } from '../store/ai-context'\nimport {\n ChunksTab,\n ConversationHeader,\n ConversationTabs,\n MessagesTab,\n SummariesTab,\n} from './conversation'\nimport type { TabType } from './conversation'\nimport type { Conversation } from '../store/ai-context'\nimport type { Component } from 'solid-js'\n\nexport const ConversationDetails: Component = () => {\n const { state } = useAIStore()\n const styles = useStyles()\n const [activeTab, setActiveTab] = createSignal<TabType>('messages')\n\n const activeConversation = (): Conversation | undefined => {\n if (!state.activeConversationId) return undefined\n return state.conversations[state.activeConversationId]\n }\n\n // Update active tab when conversation changes\n createEffect(() => {\n const conv = activeConversation()\n if (conv) {\n // For server conversations, always use chunks (messages tab is hidden)\n if (conv.type === 'server') {\n if (conv.chunks.length > 0) {\n setActiveTab('chunks')\n } else if (\n conv.hasSummarize ||\n (conv.summaries && conv.summaries.length > 0)\n ) {\n setActiveTab('summaries')\n } else {\n setActiveTab('chunks')\n }\n } else {\n // For client conversations, default to messages tab\n setActiveTab('messages')\n }\n }\n })\n\n return (\n <Show\n when={activeConversation()}\n fallback={\n <div class={styles().conversationDetails.emptyState}>\n Select a conversation to view details\n </div>\n }\n >\n {(conv) => (\n <div class={styles().conversationDetails.container}>\n <ConversationHeader conversation={conv()} />\n <ConversationTabs\n conversation={conv()}\n activeTab={activeTab()}\n onTabChange={setActiveTab}\n />\n <div class={styles().conversationDetails.contentArea}>\n <Show when={activeTab() === 'messages'}>\n <MessagesTab messages={conv().messages} />\n </Show>\n <Show when={activeTab() === 'chunks'}>\n <ChunksTab chunks={conv().chunks} messages={conv().messages} />\n </Show>\n <Show when={activeTab() === 'summaries'}>\n <SummariesTab summaries={conv().summaries ?? []} />\n </Show>\n </div>\n </div>\n )}\n </Show>\n )\n}\n"],"names":["ConversationDetails","state","useAIStore","styles","useStyles","activeTab","setActiveTab","createSignal","activeConversation","activeConversationId","undefined","conversations","createEffect","conv","type","chunks","length","hasSummarize","summaries","_$createComponent","Show","when","fallback","_el$","_tmpl$","_$effect","_$className","conversationDetails","emptyState","children","_el$2","_tmpl$2","_el$3","firstChild","_$insert","ConversationHeader","conversation","ConversationTabs","onTabChange","MessagesTab","messages","ChunksTab","SummariesTab","_p$","_v$","container","_v$2","contentArea","e","t"],"mappings":";;;;;;;;;;AAcO,MAAMA,sBAAiCA,MAAM;AAClD,QAAM;AAAA,IAAEC;AAAAA,EAAAA,IAAUC,WAAAA;AAClB,QAAMC,SAASC,UAAAA;AACf,QAAM,CAACC,WAAWC,YAAY,IAAIC,aAAsB,UAAU;AAElE,QAAMC,qBAAqBA,MAAgC;AACzD,QAAI,CAACP,MAAMQ,qBAAsB,QAAOC;AACxC,WAAOT,MAAMU,cAAcV,MAAMQ,oBAAoB;AAAA,EACvD;AAGAG,eAAa,MAAM;AACjB,UAAMC,OAAOL,mBAAAA;AACb,QAAIK,MAAM;AAER,UAAIA,KAAKC,SAAS,UAAU;AAC1B,YAAID,KAAKE,OAAOC,SAAS,GAAG;AAC1BV,uBAAa,QAAQ;AAAA,QACvB,WACEO,KAAKI,gBACJJ,KAAKK,aAAaL,KAAKK,UAAUF,SAAS,GAC3C;AACAV,uBAAa,WAAW;AAAA,QAC1B,OAAO;AACLA,uBAAa,QAAQ;AAAA,QACvB;AAAA,MACF,OAAO;AAELA,qBAAa,UAAU;AAAA,MACzB;AAAA,IACF;AAAA,EACF,CAAC;AAED,SAAAa,gBACGC,MAAI;AAAA,IAAA,IACHC,OAAI;AAAA,aAAEb,mBAAAA;AAAAA,IAAoB;AAAA,IAAA,IAC1Bc,WAAQ;AAAA,cAAA,MAAA;AAAA,YAAAC,OAAAC,OAAAA;AAAAC,eAAA,MAAAC,UAAAH,MACMpB,SAASwB,oBAAoBC,UAAU,CAAA;AAAA,eAAAL;AAAAA,MAAA,GAAA;AAAA,IAAA;AAAA,IAAAM,UAKnDhB,WAAI,MAAA;AAAA,UAAAiB,QAAAC,QAAAA,GAAAC,QAAAF,MAAAG;AAAAC,aAAAJ,OAAAX,gBAEDgB,oBAAkB;AAAA,QAAA,IAACC,eAAY;AAAA,iBAAEvB,KAAAA;AAAAA,QAAM;AAAA,MAAA,CAAA,GAAAmB,KAAA;AAAAE,aAAAJ,OAAAX,gBACvCkB,kBAAgB;AAAA,QAAA,IACfD,eAAY;AAAA,iBAAEvB,KAAAA;AAAAA,QAAM;AAAA,QAAA,IACpBR,YAAS;AAAA,iBAAEA,UAAAA;AAAAA,QAAW;AAAA,QACtBiC,aAAahC;AAAAA,MAAAA,CAAY,GAAA0B,KAAA;AAAAE,aAAAF,OAAAb,gBAGxBC,MAAI;AAAA,QAAA,IAACC,OAAI;AAAA,iBAAEhB,gBAAgB;AAAA,QAAU;AAAA,QAAA,IAAAwB,WAAA;AAAA,iBAAAV,gBACnCoB,aAAW;AAAA,YAAA,IAACC,WAAQ;AAAA,qBAAE3B,OAAO2B;AAAAA,YAAQ;AAAA,UAAA,CAAA;AAAA,QAAA;AAAA,MAAA,CAAA,GAAA,IAAA;AAAAN,aAAAF,OAAAb,gBAEvCC,MAAI;AAAA,QAAA,IAACC,OAAI;AAAA,iBAAEhB,gBAAgB;AAAA,QAAQ;AAAA,QAAA,IAAAwB,WAAA;AAAA,iBAAAV,gBACjCsB,WAAS;AAAA,YAAA,IAAC1B,SAAM;AAAA,qBAAEF,OAAOE;AAAAA,YAAM;AAAA,YAAA,IAAEyB,WAAQ;AAAA,qBAAE3B,OAAO2B;AAAAA,YAAQ;AAAA,UAAA,CAAA;AAAA,QAAA;AAAA,MAAA,CAAA,GAAA,IAAA;AAAAN,aAAAF,OAAAb,gBAE5DC,MAAI;AAAA,QAAA,IAACC,OAAI;AAAA,iBAAEhB,gBAAgB;AAAA,QAAW;AAAA,QAAA,IAAAwB,WAAA;AAAA,iBAAAV,gBACpCuB,cAAY;AAAA,YAAA,IAACxB,YAAS;AAAA,qBAAEL,KAAAA,EAAOK,aAAa,CAAA;AAAA,YAAE;AAAA,UAAA,CAAA;AAAA,QAAA;AAAA,MAAA,CAAA,GAAA,IAAA;AAAAO,aAAAkB,CAAAA,QAAA;AAAA,YAAAC,MAfzCzC,SAASwB,oBAAoBkB,WAASC,OAOpC3C,SAASwB,oBAAoBoB;AAAWH,gBAAAD,IAAAK,KAAAtB,UAAAI,OAAAa,IAAAK,IAAAJ,GAAA;AAAAE,iBAAAH,IAAAM,KAAAvB,UAAAM,OAAAW,IAAAM,IAAAH,IAAA;AAAA,eAAAH;AAAAA,MAAA,GAAA;AAAA,QAAAK,GAAAtC;AAAAA,QAAAuC,GAAAvC;AAAAA,MAAAA,CAAA;AAAA,aAAAoB;AAAAA,IAAA,GAAA;AAAA,EAAA,CAYvD;AAGP;"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ChunksCollapsible.js","sources":["../../../../src/components/conversation/ChunksCollapsible.tsx"],"sourcesContent":["import { For, Show } from 'solid-js'\nimport { useStyles } from '../../styles/use-styles'\nimport { ChunkItem } from './ChunkItem'\nimport { ChunkBadges } from './ChunkBadges'\nimport type { Component } from 'solid-js'\nimport type { Chunk } from '../../store/ai-store'\n\ninterface ChunksCollapsibleProps {\n chunks: Array<Chunk>\n}\n\nexport const ChunksCollapsible: Component<ChunksCollapsibleProps> = (props) => {\n const styles = useStyles()\n\n const accumulatedContent = () =>\n props.chunks\n .filter((c) => c.type === 'content' && (c.content || c.delta))\n .map((c) => c.delta || c.content)\n .join('')\n\n // Total raw chunks = sum of all chunkCounts\n const totalRawChunks = () =>\n props.chunks.reduce((sum, c) => sum + (c.chunkCount || 1), 0)\n\n return (\n <details class={styles().conversationDetails.chunksDetails}>\n <summary class={styles().conversationDetails.chunksSummary}>\n <div class={styles().conversationDetails.chunksSummaryRow}>\n <span class={styles().conversationDetails.chunksSummaryArrow}
|
|
1
|
+
{"version":3,"file":"ChunksCollapsible.js","sources":["../../../../src/components/conversation/ChunksCollapsible.tsx"],"sourcesContent":["import { For, Show } from 'solid-js'\nimport { useStyles } from '../../styles/use-styles'\nimport { ChunkItem } from './ChunkItem'\nimport { ChunkBadges } from './ChunkBadges'\nimport type { Component } from 'solid-js'\nimport type { Chunk } from '../../store/ai-store'\n\ninterface ChunksCollapsibleProps {\n chunks: Array<Chunk>\n}\n\nexport const ChunksCollapsible: Component<ChunksCollapsibleProps> = (props) => {\n const styles = useStyles()\n\n const accumulatedContent = () =>\n props.chunks\n .filter((c) => c.type === 'content' && (c.content || c.delta))\n .map((c) => c.delta || c.content)\n .join('')\n\n // Total raw chunks = sum of all chunkCounts\n const totalRawChunks = () =>\n props.chunks.reduce((sum, c) => sum + (c.chunkCount || 1), 0)\n\n return (\n <details class={styles().conversationDetails.chunksDetails}>\n <summary class={styles().conversationDetails.chunksSummary}>\n <div class={styles().conversationDetails.chunksSummaryRow}>\n <span class={styles().conversationDetails.chunksSummaryArrow}>▶</span>\n <span class={styles().conversationDetails.chunksSummaryTitle}>\n 📦 {totalRawChunks()} chunks\n </span>\n <ChunkBadges chunks={props.chunks} />\n </div>\n {/* Accumulated Content Preview */}\n <Show when={accumulatedContent()}>\n <div\n class={styles().conversationDetails.contentPreview}\n title={accumulatedContent()}\n >\n {accumulatedContent()}\n </div>\n </Show>\n </summary>\n <div class={styles().conversationDetails.chunksContainer}>\n <div class={styles().conversationDetails.chunksList}>\n <For each={props.chunks}>\n {(chunk, index) => (\n <ChunkItem chunk={chunk} index={index()} variant=\"small\" />\n )}\n </For>\n </div>\n </div>\n </details>\n )\n}\n"],"names":["ChunksCollapsible","props","styles","useStyles","accumulatedContent","chunks","filter","c","type","content","delta","map","join","totalRawChunks","reduce","sum","chunkCount","_el$","_tmpl$2","_el$2","firstChild","_el$3","_el$4","_el$5","nextSibling","_el$6","_el$8","_el$0","_el$1","_$insert","_$createComponent","ChunkBadges","Show","when","children","_el$9","_tmpl$","_$effect","_p$","_v$","conversationDetails","contentPreview","_v$2","e","_$className","t","_$setAttribute","undefined","For","each","chunk","index","ChunkItem","variant","_v$3","chunksDetails","_v$4","chunksSummary","_v$5","chunksSummaryRow","_v$6","chunksSummaryArrow","_v$7","chunksSummaryTitle","_v$8","chunksContainer","_v$9","chunksList","a","o","i","n","s"],"mappings":"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"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { Component } from 'solid-js';
|
|
2
2
|
import { Conversation } from '../../store/ai-context.js';
|
|
3
|
-
export type TabType = 'messages' | 'chunks' | '
|
|
3
|
+
export type TabType = 'messages' | 'chunks' | 'summaries';
|
|
4
4
|
interface ConversationTabsProps {
|
|
5
5
|
conversation: Conversation;
|
|
6
6
|
activeTab: TabType;
|
|
@@ -1,22 +1,19 @@
|
|
|
1
1
|
import { template, insert, createComponent, effect, className, memo, delegateEvents } from "solid-js/web";
|
|
2
2
|
import { Show } from "solid-js";
|
|
3
3
|
import { useStyles } from "../../styles/use-styles.js";
|
|
4
|
-
var _tmpl$ = /* @__PURE__ */ template(`<button>💬 Messages (<!>)`), _tmpl$2 = /* @__PURE__ */ template(`<button>📦 Chunks (<!>)`), _tmpl$3 = /* @__PURE__ */ template(`<button
|
|
4
|
+
var _tmpl$ = /* @__PURE__ */ template(`<button>💬 Messages (<!>)`), _tmpl$2 = /* @__PURE__ */ template(`<button>📦 Chunks (<!>)`), _tmpl$3 = /* @__PURE__ */ template(`<button>📝 Summaries (<!>)`), _tmpl$4 = /* @__PURE__ */ template(`<div>`);
|
|
5
5
|
const ConversationTabs = (props) => {
|
|
6
6
|
const styles = useStyles();
|
|
7
7
|
const conv = () => props.conversation;
|
|
8
8
|
const totalRawChunks = () => conv().chunks.reduce((sum, c) => sum + (c.chunkCount || 1), 0);
|
|
9
|
-
const embeddingsCount = () => conv().embeddings?.length ?? 0;
|
|
10
9
|
const summariesCount = () => conv().summaries?.length ?? 0;
|
|
11
10
|
const hasMessages = () => conv().type === "client" && conv().messages.length > 0;
|
|
12
11
|
const hasChunks = () => conv().chunks.length > 0 || conv().type === "server";
|
|
13
|
-
const hasEmbeddings = () => conv().hasEmbedding || embeddingsCount() > 0;
|
|
14
12
|
const hasSummaries = () => conv().hasSummarize || summariesCount() > 0;
|
|
15
13
|
const visibleTabCount = () => {
|
|
16
14
|
let count = 0;
|
|
17
15
|
if (hasMessages()) count++;
|
|
18
16
|
if (hasChunks() && conv().type === "server") count++;
|
|
19
|
-
if (hasEmbeddings()) count++;
|
|
20
17
|
if (hasSummaries()) count++;
|
|
21
18
|
return count;
|
|
22
19
|
};
|
|
@@ -24,7 +21,7 @@ const ConversationTabs = (props) => {
|
|
|
24
21
|
return null;
|
|
25
22
|
}
|
|
26
23
|
return (() => {
|
|
27
|
-
var _el$ = _tmpl$
|
|
24
|
+
var _el$ = _tmpl$4();
|
|
28
25
|
insert(_el$, createComponent(Show, {
|
|
29
26
|
get when() {
|
|
30
27
|
return hasMessages();
|
|
@@ -53,30 +50,17 @@ const ConversationTabs = (props) => {
|
|
|
53
50
|
}), null);
|
|
54
51
|
insert(_el$, createComponent(Show, {
|
|
55
52
|
get when() {
|
|
56
|
-
return
|
|
53
|
+
return hasSummaries();
|
|
57
54
|
},
|
|
58
55
|
get children() {
|
|
59
56
|
var _el$0 = _tmpl$3(), _el$1 = _el$0.firstChild, _el$11 = _el$1.nextSibling;
|
|
60
57
|
_el$11.nextSibling;
|
|
61
|
-
_el$0.$$click = () => props.onTabChange("
|
|
62
|
-
insert(_el$0,
|
|
63
|
-
effect(() => className(_el$0, `${styles().actionButton} ${props.activeTab === "
|
|
58
|
+
_el$0.$$click = () => props.onTabChange("summaries");
|
|
59
|
+
insert(_el$0, summariesCount, _el$11);
|
|
60
|
+
effect(() => className(_el$0, `${styles().actionButton} ${props.activeTab === "summaries" ? styles().conversationDetails.tabButtonActive : ""}`));
|
|
64
61
|
return _el$0;
|
|
65
62
|
}
|
|
66
63
|
}), null);
|
|
67
|
-
insert(_el$, createComponent(Show, {
|
|
68
|
-
get when() {
|
|
69
|
-
return hasSummaries();
|
|
70
|
-
},
|
|
71
|
-
get children() {
|
|
72
|
-
var _el$12 = _tmpl$4(), _el$13 = _el$12.firstChild, _el$15 = _el$13.nextSibling;
|
|
73
|
-
_el$15.nextSibling;
|
|
74
|
-
_el$12.$$click = () => props.onTabChange("summaries");
|
|
75
|
-
insert(_el$12, summariesCount, _el$15);
|
|
76
|
-
effect(() => className(_el$12, `${styles().actionButton} ${props.activeTab === "summaries" ? styles().conversationDetails.tabButtonActive : ""}`));
|
|
77
|
-
return _el$12;
|
|
78
|
-
}
|
|
79
|
-
}), null);
|
|
80
64
|
effect(() => className(_el$, styles().conversationDetails.tabsContainer));
|
|
81
65
|
return _el$;
|
|
82
66
|
})();
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ConversationTabs.js","sources":["../../../../src/components/conversation/ConversationTabs.tsx"],"sourcesContent":["import { Show } from 'solid-js'\nimport { useStyles } from '../../styles/use-styles'\nimport type { Component } from 'solid-js'\nimport type { Conversation } from '../../store/ai-context'\n\nexport type TabType = 'messages' | 'chunks' | '
|
|
1
|
+
{"version":3,"file":"ConversationTabs.js","sources":["../../../../src/components/conversation/ConversationTabs.tsx"],"sourcesContent":["import { Show } from 'solid-js'\nimport { useStyles } from '../../styles/use-styles'\nimport type { Component } from 'solid-js'\nimport type { Conversation } from '../../store/ai-context'\n\nexport type TabType = 'messages' | 'chunks' | 'summaries'\n\ninterface ConversationTabsProps {\n conversation: Conversation\n activeTab: TabType\n onTabChange: (tab: TabType) => void\n}\n\nexport const ConversationTabs: Component<ConversationTabsProps> = (props) => {\n const styles = useStyles()\n const conv = () => props.conversation\n\n // Total raw chunks = sum of all chunkCounts\n const totalRawChunks = () =>\n conv().chunks.reduce((sum, c) => sum + (c.chunkCount || 1), 0)\n\n const summariesCount = () => conv().summaries?.length ?? 0\n\n // Determine if we should show any chat-related tabs\n // For server conversations, don't show messages tab - only chunks\n const hasMessages = () =>\n conv().type === 'client' && conv().messages.length > 0\n const hasChunks = () => conv().chunks.length > 0 || conv().type === 'server'\n const hasSummaries = () => conv().hasSummarize || summariesCount() > 0\n\n // Count how many tabs would be visible\n const visibleTabCount = () => {\n let count = 0\n if (hasMessages()) count++\n if (hasChunks() && conv().type === 'server') count++\n if (hasSummaries()) count++\n return count\n }\n\n // Don't render tabs if only one tab would be visible\n if (visibleTabCount() <= 1) {\n return null\n }\n\n return (\n <div class={styles().conversationDetails.tabsContainer}>\n {/* Show messages tab for client conversations or when there are messages */}\n <Show when={hasMessages()}>\n <button\n class={`${styles().actionButton} ${\n props.activeTab === 'messages'\n ? styles().conversationDetails.tabButtonActive\n : ''\n }`}\n onClick={() => props.onTabChange('messages')}\n >\n 💬 Messages ({conv().messages.length})\n </button>\n </Show>\n {/* Show chunks tab for server conversations or when there are chunks */}\n <Show when={hasChunks() && conv().type === 'server'}>\n <button\n class={`${styles().actionButton} ${\n props.activeTab === 'chunks'\n ? styles().conversationDetails.tabButtonActive\n : ''\n }`}\n onClick={() => props.onTabChange('chunks')}\n >\n 📦 Chunks ({totalRawChunks()})\n </button>\n </Show>\n {/* Show summaries tab if there are summarize operations */}\n <Show when={hasSummaries()}>\n <button\n class={`${styles().actionButton} ${\n props.activeTab === 'summaries'\n ? styles().conversationDetails.tabButtonActive\n : ''\n }`}\n onClick={() => props.onTabChange('summaries')}\n >\n 📝 Summaries ({summariesCount()})\n </button>\n </Show>\n </div>\n )\n}\n"],"names":["ConversationTabs","props","styles","useStyles","conv","conversation","totalRawChunks","chunks","reduce","sum","c","chunkCount","summariesCount","summaries","length","hasMessages","type","messages","hasChunks","hasSummaries","hasSummarize","visibleTabCount","count","_el$","_tmpl$4","_$insert","_$createComponent","Show","when","children","_el$2","_tmpl$","_el$3","firstChild","_el$5","nextSibling","$$click","onTabChange","_$effect","_$className","actionButton","activeTab","conversationDetails","tabButtonActive","_$memo","_el$6","_tmpl$2","_el$7","_el$9","_el$0","_tmpl$3","_el$1","_el$11","tabsContainer","_$delegateEvents"],"mappings":";;;;AAaO,MAAMA,mBAAsDC,CAAAA,UAAU;AAC3E,QAAMC,SAASC,UAAAA;AACf,QAAMC,OAAOA,MAAMH,MAAMI;AAGzB,QAAMC,iBAAiBA,MACrBF,KAAAA,EAAOG,OAAOC,OAAO,CAACC,KAAKC,MAAMD,OAAOC,EAAEC,cAAc,IAAI,CAAC;AAE/D,QAAMC,iBAAiBA,MAAMR,KAAAA,EAAOS,WAAWC,UAAU;AAIzD,QAAMC,cAAcA,MAClBX,KAAAA,EAAOY,SAAS,YAAYZ,KAAAA,EAAOa,SAASH,SAAS;AACvD,QAAMI,YAAYA,MAAMd,KAAAA,EAAOG,OAAOO,SAAS,KAAKV,OAAOY,SAAS;AACpE,QAAMG,eAAeA,MAAMf,KAAAA,EAAOgB,gBAAgBR,mBAAmB;AAGrE,QAAMS,kBAAkBA,MAAM;AAC5B,QAAIC,QAAQ;AACZ,QAAIP,cAAeO;AACnB,QAAIJ,UAAAA,KAAed,KAAAA,EAAOY,SAAS,SAAUM;AAC7C,QAAIH,eAAgBG;AACpB,WAAOA;AAAAA,EACT;AAGA,MAAID,gBAAAA,KAAqB,GAAG;AAC1B,WAAO;AAAA,EACT;AAEA,UAAA,MAAA;AAAA,QAAAE,OAAAC,QAAAA;AAAAC,WAAAF,MAAAG,gBAGKC,MAAI;AAAA,MAAA,IAACC,OAAI;AAAA,eAAEb,YAAAA;AAAAA,MAAa;AAAA,MAAA,IAAAc,WAAA;AAAA,YAAAC,QAAAC,UAAAC,QAAAF,MAAAG,YAAAC,QAAAF,MAAAG;AAAAD,cAAAC;AAAAL,cAAAM,UAOZ,MAAMnC,MAAMoC,YAAY,UAAU;AAACZ,eAAAK,OAAA,MAE9B1B,KAAAA,EAAOa,SAASH,QAAMoB,KAAA;AAAAI,eAAA,MAAAC,UAAAT,OAP7B,GAAG5B,OAAAA,EAASsC,YAAY,IAC7BvC,MAAMwC,cAAc,aAChBvC,OAAAA,EAASwC,oBAAoBC,kBAC7B,EAAE,EACN,CAAA;AAAA,eAAAb;AAAAA,MAAA;AAAA,IAAA,CAAA,GAAA,IAAA;AAAAL,WAAAF,MAAAG,gBAOLC,MAAI;AAAA,MAAA,IAACC,OAAI;AAAA,eAAEgB,KAAA,MAAA,CAAA,CAAA1B,UAAAA,CAAW,EAAA,KAAId,KAAAA,EAAOY,SAAS;AAAA,MAAQ;AAAA,MAAA,IAAAa,WAAA;AAAA,YAAAgB,QAAAC,WAAAC,QAAAF,MAAAZ,YAAAe,QAAAD,MAAAZ;AAAAa,cAAAb;AAAAU,cAAAT,UAOtC,MAAMnC,MAAMoC,YAAY,QAAQ;AAACZ,eAAAoB,OAE9BvC,gBAAc0C,KAAA;AAAAV,eAAA,MAAAC,UAAAM,OAPnB,GAAG3C,OAAAA,EAASsC,YAAY,IAC7BvC,MAAMwC,cAAc,WAChBvC,OAAAA,EAASwC,oBAAoBC,kBAC7B,EAAE,EACN,CAAA;AAAA,eAAAE;AAAAA,MAAA;AAAA,IAAA,CAAA,GAAA,IAAA;AAAApB,WAAAF,MAAAG,gBAOLC,MAAI;AAAA,MAAA,IAACC,OAAI;AAAA,eAAET,aAAAA;AAAAA,MAAc;AAAA,MAAA,IAAAU,WAAA;AAAA,YAAAoB,QAAAC,WAAAC,QAAAF,MAAAhB,YAAAmB,SAAAD,MAAAhB;AAAAiB,eAAAjB;AAAAc,cAAAb,UAOb,MAAMnC,MAAMoC,YAAY,WAAW;AAACZ,eAAAwB,OAE9BrC,gBAAcwC,MAAA;AAAAd,eAAA,MAAAC,UAAAU,OAPtB,GAAG/C,OAAAA,EAASsC,YAAY,IAC7BvC,MAAMwC,cAAc,cAChBvC,OAAAA,EAASwC,oBAAoBC,kBAC7B,EAAE,EACN,CAAA;AAAA,eAAAM;AAAAA,MAAA;AAAA,IAAA,CAAA,GAAA,IAAA;AAAAX,WAAA,MAAAC,UAAAhB,MAlCIrB,SAASwC,oBAAoBW,aAAa,CAAA;AAAA,WAAA9B;AAAAA,EAAA,GAAA;AA0C1D;AAAC+B,eAAA,CAAA,OAAA,CAAA;"}
|
|
@@ -3,5 +3,4 @@ export { ConversationTabs } from './ConversationTabs.js';
|
|
|
3
3
|
export type { TabType } from './ConversationTabs.js';
|
|
4
4
|
export { MessagesTab } from './MessagesTab.js';
|
|
5
5
|
export { ChunksTab } from './ChunksTab.js';
|
|
6
|
-
export { EmbeddingsTab } from './EmbeddingsTab.js';
|
|
7
6
|
export { SummariesTab } from './SummariesTab.js';
|
|
@@ -70,14 +70,6 @@ export interface Chunk {
|
|
|
70
70
|
/** Number of raw chunks that were merged into this consolidated chunk */
|
|
71
71
|
chunkCount: number;
|
|
72
72
|
}
|
|
73
|
-
export interface EmbeddingOperation {
|
|
74
|
-
id: string;
|
|
75
|
-
model: string;
|
|
76
|
-
inputCount: number;
|
|
77
|
-
duration: number;
|
|
78
|
-
timestamp: number;
|
|
79
|
-
status: 'started' | 'completed';
|
|
80
|
-
}
|
|
81
73
|
export interface SummarizeOperation {
|
|
82
74
|
id: string;
|
|
83
75
|
model: string;
|
|
@@ -105,10 +97,7 @@ export interface Conversation {
|
|
|
105
97
|
providerOptions?: Record<string, unknown>;
|
|
106
98
|
/** Flags for which operation types this conversation has */
|
|
107
99
|
hasChat?: boolean;
|
|
108
|
-
hasEmbedding?: boolean;
|
|
109
100
|
hasSummarize?: boolean;
|
|
110
|
-
/** Embedding operations in this conversation */
|
|
111
|
-
embeddings?: Array<EmbeddingOperation>;
|
|
112
101
|
/** Summarize operations in this conversation */
|
|
113
102
|
summaries?: Array<SummarizeOperation>;
|
|
114
103
|
}
|
|
@@ -744,7 +744,7 @@ const AIProvider = (props) => {
|
|
|
744
744
|
}
|
|
745
745
|
}
|
|
746
746
|
}));
|
|
747
|
-
cleanupFns.push(aiEventClient.on("
|
|
747
|
+
cleanupFns.push(aiEventClient.on("text:started", (e) => {
|
|
748
748
|
const streamId = e.payload.streamId;
|
|
749
749
|
const model = e.payload.model;
|
|
750
750
|
e.payload.provider;
|
|
@@ -781,7 +781,7 @@ const AIProvider = (props) => {
|
|
|
781
781
|
}
|
|
782
782
|
}
|
|
783
783
|
}));
|
|
784
|
-
cleanupFns.push(aiEventClient.on("
|
|
784
|
+
cleanupFns.push(aiEventClient.on("text:completed", (e) => {
|
|
785
785
|
const {
|
|
786
786
|
requestId,
|
|
787
787
|
usage
|
|
@@ -801,7 +801,7 @@ const AIProvider = (props) => {
|
|
|
801
801
|
}
|
|
802
802
|
}
|
|
803
803
|
}));
|
|
804
|
-
cleanupFns.push(aiEventClient.on("
|
|
804
|
+
cleanupFns.push(aiEventClient.on("text:iteration", (e) => {
|
|
805
805
|
const {
|
|
806
806
|
requestId,
|
|
807
807
|
iterationNumber
|
|
@@ -879,60 +879,6 @@ const AIProvider = (props) => {
|
|
|
879
879
|
}
|
|
880
880
|
}
|
|
881
881
|
}));
|
|
882
|
-
cleanupFns.push(aiEventClient.on("embedding:started", (e) => {
|
|
883
|
-
const {
|
|
884
|
-
requestId,
|
|
885
|
-
model,
|
|
886
|
-
inputCount,
|
|
887
|
-
timestamp,
|
|
888
|
-
clientId
|
|
889
|
-
} = e.payload;
|
|
890
|
-
let conversationId = clientId;
|
|
891
|
-
if (!conversationId || !state.conversations[conversationId]) {
|
|
892
|
-
const activeClients = Object.values(state.conversations).filter((c) => c.type === "client" && c.status === "active").sort((a, b) => b.startedAt - a.startedAt);
|
|
893
|
-
if (activeClients.length > 0 && activeClients[0]) {
|
|
894
|
-
conversationId = activeClients[0].id;
|
|
895
|
-
} else {
|
|
896
|
-
conversationId = `embedding-${requestId}`;
|
|
897
|
-
getOrCreateConversation(conversationId, "server", `Embedding (${model})`);
|
|
898
|
-
updateConversation(conversationId, {
|
|
899
|
-
model
|
|
900
|
-
});
|
|
901
|
-
}
|
|
902
|
-
}
|
|
903
|
-
requestToConversation.set(requestId, conversationId);
|
|
904
|
-
const embeddingOp = {
|
|
905
|
-
id: requestId,
|
|
906
|
-
model,
|
|
907
|
-
inputCount,
|
|
908
|
-
duration: 0,
|
|
909
|
-
timestamp,
|
|
910
|
-
status: "started"
|
|
911
|
-
};
|
|
912
|
-
const conv = state.conversations[conversationId];
|
|
913
|
-
if (conv) {
|
|
914
|
-
const embeddings = conv.embeddings || [];
|
|
915
|
-
setState("conversations", conversationId, "embeddings", [...embeddings, embeddingOp]);
|
|
916
|
-
setState("conversations", conversationId, "hasEmbedding", true);
|
|
917
|
-
}
|
|
918
|
-
}));
|
|
919
|
-
cleanupFns.push(aiEventClient.on("embedding:completed", (e) => {
|
|
920
|
-
const {
|
|
921
|
-
requestId,
|
|
922
|
-
duration
|
|
923
|
-
} = e.payload;
|
|
924
|
-
const conversationId = requestToConversation.get(requestId);
|
|
925
|
-
if (!conversationId || !state.conversations[conversationId]) return;
|
|
926
|
-
const conv = state.conversations[conversationId];
|
|
927
|
-
if (!conv.embeddings) return;
|
|
928
|
-
const embeddingIndex = conv.embeddings.findIndex((op) => op.id === requestId);
|
|
929
|
-
if (embeddingIndex >= 0) {
|
|
930
|
-
setState("conversations", conversationId, "embeddings", embeddingIndex, produce((op) => {
|
|
931
|
-
op.duration = duration;
|
|
932
|
-
op.status = "completed";
|
|
933
|
-
}));
|
|
934
|
-
}
|
|
935
|
-
}));
|
|
936
882
|
cleanupFns.push(aiEventClient.on("summarize:started", (e) => {
|
|
937
883
|
const {
|
|
938
884
|
requestId,
|