@takoviz/ai-sdk 1.0.1 → 2.0.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/README.md +78 -72
- package/dist/index.d.ts +140 -4
- package/dist/index.js +132 -55
- package/package.json +24 -21
- package/PUBLISH.md +0 -45
- package/VERCEL_REGISTRY.md +0 -104
- package/dist/types.d.ts +0 -36
- package/dist/types.js +0 -1
- package/test.ts +0 -22
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
#
|
|
1
|
+
# @takoviz/ai-sdk
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Tako tools for the [Vercel AI SDK](https://sdk.vercel.ai/) — give your agents access to Tako's knowledge base: charts and well-sourced data (`takoSearch`), synthesized answers (`takoAnswer`), and the underlying data behind any result (`takoContents`).
|
|
4
4
|
|
|
5
5
|
## Installation
|
|
6
6
|
|
|
@@ -10,108 +10,114 @@ npm install @takoviz/ai-sdk ai
|
|
|
10
10
|
|
|
11
11
|
## Setup
|
|
12
12
|
|
|
13
|
-
Get
|
|
13
|
+
Get an API key from the [Tako dashboard](https://trytako.com) and set it as an environment variable:
|
|
14
14
|
|
|
15
15
|
```bash
|
|
16
16
|
export TAKO_API_KEY=your_api_key_here
|
|
17
17
|
```
|
|
18
18
|
|
|
19
|
-
##
|
|
19
|
+
## Tools
|
|
20
|
+
|
|
21
|
+
| Tool | Endpoint | What it does |
|
|
22
|
+
| --- | --- | --- |
|
|
23
|
+
| `takoSearch()` | `POST /api/v3/search` | Fast retrieval: Tako cards + web results, no synthesis |
|
|
24
|
+
| `takoAnswer()` | `POST /api/v1/answer` | Retrieval **plus** an LLM-synthesized, sourced answer |
|
|
25
|
+
| `takoContents()` | `POST /api/v1/contents` | Download a result's data (card CSV or web page text) |
|
|
26
|
+
|
|
27
|
+
## Quick start
|
|
20
28
|
|
|
21
29
|
```typescript
|
|
22
|
-
import {
|
|
23
|
-
import {
|
|
30
|
+
import { takoAnswer } from '@takoviz/ai-sdk';
|
|
31
|
+
import { openai } from '@ai-sdk/openai';
|
|
32
|
+
import { generateText, isStepCount } from 'ai';
|
|
24
33
|
|
|
25
34
|
const { text } = await generateText({
|
|
26
|
-
model: '
|
|
27
|
-
prompt: '
|
|
28
|
-
tools: {
|
|
29
|
-
|
|
30
|
-
},
|
|
31
|
-
maxSteps: 5,
|
|
35
|
+
model: openai('gpt-4o-mini'),
|
|
36
|
+
prompt: 'Did AMD or Nvidia grow headcount faster over the last decade?',
|
|
37
|
+
tools: { tako_answer: takoAnswer() },
|
|
38
|
+
stopWhen: isStepCount(5),
|
|
32
39
|
});
|
|
33
40
|
|
|
34
41
|
console.log(text);
|
|
35
42
|
```
|
|
36
43
|
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
You can customize the search behavior by passing a configuration object:
|
|
44
|
+
Give the agent the full toolset so it can search, answer, and drill into data:
|
|
40
45
|
|
|
41
46
|
```typescript
|
|
42
|
-
|
|
43
|
-
model: 'openai/gpt-4o-mini',
|
|
44
|
-
prompt: 'What is the GDP of major economies?',
|
|
45
|
-
tools: {
|
|
46
|
-
takoSearch: takoSearch({
|
|
47
|
-
apiKey: 'your_api_key', // Optional: override environment variable
|
|
48
|
-
sourceIndexes: ['tako', 'web'], // Default: ['tako', 'web']
|
|
49
|
-
searchEffort: 'deep', // Options: 'fast', 'deep', 'auto'. Default: 'fast'
|
|
50
|
-
countryCode: 'US', // Default: 'US'
|
|
51
|
-
locale: 'en-US', // Default: 'en-US'
|
|
52
|
-
outputSettings: {
|
|
53
|
-
knowledgeCardSettings: {
|
|
54
|
-
imageDarkMode: true, // Default: false
|
|
55
|
-
},
|
|
56
|
-
},
|
|
57
|
-
}),
|
|
58
|
-
},
|
|
59
|
-
maxSteps: 5,
|
|
60
|
-
});
|
|
61
|
-
```
|
|
47
|
+
import { takoSearch, takoAnswer, takoContents } from '@takoviz/ai-sdk';
|
|
62
48
|
|
|
63
|
-
|
|
49
|
+
const tools = {
|
|
50
|
+
tako_search: takoSearch(),
|
|
51
|
+
tako_answer: takoAnswer(),
|
|
52
|
+
tako_contents: takoContents(),
|
|
53
|
+
};
|
|
54
|
+
```
|
|
64
55
|
|
|
65
|
-
|
|
56
|
+
## Configuration
|
|
66
57
|
|
|
67
|
-
|
|
58
|
+
`takoSearch` and `takoAnswer` take the same config:
|
|
68
59
|
|
|
69
|
-
|
|
60
|
+
```typescript
|
|
61
|
+
takoSearch({
|
|
62
|
+
apiKey: 'your_api_key', // optional; defaults to TAKO_API_KEY
|
|
63
|
+
baseUrl: 'https://trytako.com', // optional; override for staging
|
|
64
|
+
effort: 'fast', // 'fast' (default) | 'instant' | 'deep'
|
|
65
|
+
sources: { // a source is searched iff its key is present; omit to search both
|
|
66
|
+
tako: { count: 5, includeContents: false, deferDataRetrieval: false },
|
|
67
|
+
web: { count: 5, includeContents: false },
|
|
68
|
+
},
|
|
69
|
+
countryCode: 'US', // default 'US'
|
|
70
|
+
locale: 'en-US', // default 'en-US'
|
|
71
|
+
timezone: 'America/New_York',// optional IANA timezone
|
|
72
|
+
outputSettings: {
|
|
73
|
+
imageDarkMode: false,
|
|
74
|
+
forceRefresh: false, // instant mode only
|
|
75
|
+
},
|
|
76
|
+
});
|
|
77
|
+
```
|
|
70
78
|
|
|
71
|
-
|
|
72
|
-
- `config.sourceIndexes` (optional): Array of index sources to search. Options: `'tako'`, `'web'`, `'connected_data'`. Default: `['tako', 'web']`.
|
|
73
|
-
- `config.searchEffort` (optional): Search depth. Options: `'fast'`, `'deep'`, `'auto'`. Default: `'fast'`.
|
|
74
|
-
- `config.countryCode` (optional): ISO3166-1 alpha-2 country code. Default: `'US'`.
|
|
75
|
-
- `config.locale` (optional): Language/region identifier. Default: `'en-US'`.
|
|
76
|
-
- `config.outputSettings` (optional): Output customization options.
|
|
79
|
+
`takoContents` takes:
|
|
77
80
|
|
|
78
|
-
|
|
81
|
+
```typescript
|
|
82
|
+
takoContents({
|
|
83
|
+
apiKey: 'your_api_key',
|
|
84
|
+
baseUrl: 'https://trytako.com',
|
|
85
|
+
mode: 'url', // 'url' (default) → presigned link; 'inline' → content in the response
|
|
86
|
+
});
|
|
87
|
+
```
|
|
79
88
|
|
|
80
|
-
|
|
89
|
+
The LLM supplies only the dynamic input: `{ query }` for `takoSearch`/`takoAnswer`, and `{ url }` (a card's `webpage_url` or a web result's `url`) for `takoContents`.
|
|
81
90
|
|
|
82
|
-
##
|
|
91
|
+
## Responses
|
|
83
92
|
|
|
84
|
-
|
|
93
|
+
`takoSearch` resolves to:
|
|
85
94
|
|
|
86
95
|
```typescript
|
|
87
96
|
{
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
card_id: string;
|
|
92
|
-
title: string;
|
|
93
|
-
description: string;
|
|
94
|
-
webpage_url: string;
|
|
95
|
-
image_url: string;
|
|
96
|
-
sources: Array<{ source_name: string; url: string }>;
|
|
97
|
-
visualization_data: {
|
|
98
|
-
data: any[];
|
|
99
|
-
viz_config: Record<string, any>;
|
|
100
|
-
};
|
|
101
|
-
}
|
|
102
|
-
];
|
|
103
|
-
answer: string;
|
|
104
|
-
};
|
|
97
|
+
cards: TakoCard[]; // Tako knowledge cards (title, description, image_url, webpage_url, sources, ...)
|
|
98
|
+
web_results: TakoWebResult[];
|
|
99
|
+
contents_total_cost: number;
|
|
105
100
|
request_id: string;
|
|
106
101
|
}
|
|
107
102
|
```
|
|
108
103
|
|
|
109
|
-
|
|
104
|
+
`takoAnswer` additionally includes `answer: string` (with `cards[0]` as the lead card). `takoContents` resolves to `{ contents: TakoContentItem[]; request_id: string }`, where each item has a `format` (`'csv'` | `'text'`), a `cost`, and either a presigned `url`/`expires_at` (url mode) or inline `data`/`total_rows`/`truncated` (inline mode).
|
|
110
105
|
|
|
111
|
-
|
|
106
|
+
Full type definitions ship with the package.
|
|
107
|
+
|
|
108
|
+
## TypeScript
|
|
112
109
|
|
|
113
110
|
```typescript
|
|
114
|
-
import type {
|
|
111
|
+
import type {
|
|
112
|
+
TakoRetrievalConfig,
|
|
113
|
+
TakoContentsConfig,
|
|
114
|
+
TakoSearchResult,
|
|
115
|
+
TakoAnswerResult,
|
|
116
|
+
TakoContentsResult,
|
|
117
|
+
TakoCard,
|
|
118
|
+
TakoWebResult,
|
|
119
|
+
TakoContentItem,
|
|
120
|
+
} from '@takoviz/ai-sdk';
|
|
115
121
|
```
|
|
116
122
|
|
|
117
123
|
## License
|
|
@@ -120,6 +126,6 @@ MIT
|
|
|
120
126
|
|
|
121
127
|
## Links
|
|
122
128
|
|
|
123
|
-
- [Tako
|
|
124
|
-
- [Vercel AI SDK
|
|
125
|
-
- [GitHub
|
|
129
|
+
- [Tako documentation](https://docs.trytako.com)
|
|
130
|
+
- [Vercel AI SDK](https://sdk.vercel.ai/docs)
|
|
131
|
+
- [GitHub repository](https://github.com/TakoData/ai-sdk)
|
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,141 @@
|
|
|
1
|
-
import
|
|
2
|
-
|
|
1
|
+
import { Tool } from 'ai';
|
|
2
|
+
|
|
3
|
+
type TakoSearchEffort = "fast" | "instant" | "deep";
|
|
4
|
+
type TakoContentsMode = "url" | "inline";
|
|
5
|
+
type TakoContentFormat = "csv" | "text";
|
|
6
|
+
/** CardSourceIndex on the response surface. */
|
|
7
|
+
type TakoCardSourceIndex = "tako" | "web" | "connected_data" | "tako_deep_v2";
|
|
8
|
+
type TakoKnowledgeCardRelevance = "High" | "Medium" | "Low";
|
|
9
|
+
interface TakoBaseConfig {
|
|
10
|
+
/** Tako API key. Falls back to TAKO_API_KEY / TAKO_API_TOKEN env vars. */
|
|
11
|
+
apiKey?: string;
|
|
12
|
+
/** API base URL. Default "https://trytako.com". */
|
|
13
|
+
baseUrl?: string;
|
|
14
|
+
}
|
|
15
|
+
interface TakoSourceOptions {
|
|
16
|
+
/** Max results for this source, 1–20 (server default 5). */
|
|
17
|
+
count?: number;
|
|
18
|
+
/** Inline this source's underlying data in the response. */
|
|
19
|
+
includeContents?: boolean;
|
|
20
|
+
}
|
|
21
|
+
interface TakoCardSourceOptions extends TakoSourceOptions {
|
|
22
|
+
/** Defer data retrieval (faster, less detail). Mutually exclusive with includeContents. */
|
|
23
|
+
deferDataRetrieval?: boolean;
|
|
24
|
+
}
|
|
25
|
+
interface TakoRetrievalConfig extends TakoBaseConfig {
|
|
26
|
+
/** "fast" (default) | "instant" | "deep". */
|
|
27
|
+
effort?: TakoSearchEffort;
|
|
28
|
+
/** Per-source settings. A source is searched iff its key is present. Omit to search tako + web. */
|
|
29
|
+
sources?: {
|
|
30
|
+
tako?: TakoCardSourceOptions;
|
|
31
|
+
web?: TakoSourceOptions;
|
|
32
|
+
};
|
|
33
|
+
/** ISO 3166-1 alpha-2 country code. Default "US". */
|
|
34
|
+
countryCode?: string;
|
|
35
|
+
/** BCP-47 locale tag. Default "en-US". */
|
|
36
|
+
locale?: string;
|
|
37
|
+
/** IANA timezone, e.g. "America/New_York". */
|
|
38
|
+
timezone?: string;
|
|
39
|
+
outputSettings?: {
|
|
40
|
+
imageDarkMode?: boolean;
|
|
41
|
+
/** Instant mode only. */
|
|
42
|
+
forceRefresh?: boolean;
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
interface TakoContentsConfig extends TakoBaseConfig {
|
|
46
|
+
/** "url" (default) returns a presigned link; "inline" returns content in the body. */
|
|
47
|
+
mode?: TakoContentsMode;
|
|
48
|
+
}
|
|
49
|
+
interface TakoResultContent {
|
|
50
|
+
format: TakoContentFormat;
|
|
51
|
+
cost: number;
|
|
52
|
+
data?: string | null;
|
|
53
|
+
total_rows?: number | null;
|
|
54
|
+
truncated?: boolean;
|
|
55
|
+
}
|
|
56
|
+
interface TakoCardSourceIndexSegment {
|
|
57
|
+
index_type: TakoCardSourceIndex;
|
|
58
|
+
segment_id: string;
|
|
59
|
+
}
|
|
60
|
+
interface TakoCardSourcePrivateIndex {
|
|
61
|
+
index_type: TakoCardSourceIndex;
|
|
62
|
+
private_index_id: string;
|
|
63
|
+
/** Optional for private indexes. */
|
|
64
|
+
segment_id?: string | null;
|
|
65
|
+
}
|
|
66
|
+
interface TakoKnowledgeCardSource {
|
|
67
|
+
source_name: string | null;
|
|
68
|
+
source_description: string | null;
|
|
69
|
+
source_index: TakoCardSourceIndex | TakoCardSourceIndexSegment | TakoCardSourcePrivateIndex;
|
|
70
|
+
url: string | null;
|
|
71
|
+
source_text?: string | null;
|
|
72
|
+
}
|
|
73
|
+
interface TakoKnowledgeCardMethodology {
|
|
74
|
+
methodology_name: string | null;
|
|
75
|
+
methodology_description: string | null;
|
|
76
|
+
}
|
|
77
|
+
interface TakoCard {
|
|
78
|
+
card_id?: string | null;
|
|
79
|
+
title?: string | null;
|
|
80
|
+
description?: string | null;
|
|
81
|
+
semantic_description?: string | null;
|
|
82
|
+
webpage_url?: string | null;
|
|
83
|
+
image_url?: string | null;
|
|
84
|
+
embed_url?: string | null;
|
|
85
|
+
sources?: TakoKnowledgeCardSource[] | null;
|
|
86
|
+
methodologies?: TakoKnowledgeCardMethodology[] | null;
|
|
87
|
+
source_indexes?: (TakoCardSourceIndex | TakoCardSourceIndexSegment)[] | null;
|
|
88
|
+
card_type?: string | null;
|
|
89
|
+
relevance?: TakoKnowledgeCardRelevance | null;
|
|
90
|
+
content?: TakoResultContent | null;
|
|
91
|
+
}
|
|
92
|
+
interface TakoWebResult {
|
|
93
|
+
title: string;
|
|
94
|
+
url: string;
|
|
95
|
+
snippet?: string | null;
|
|
96
|
+
source_name?: string | null;
|
|
97
|
+
publish_date?: string | null;
|
|
98
|
+
content?: TakoResultContent | null;
|
|
99
|
+
citation_number?: number | null;
|
|
100
|
+
}
|
|
101
|
+
interface TakoContentItem extends TakoResultContent {
|
|
102
|
+
source_url: string;
|
|
103
|
+
url?: string | null;
|
|
104
|
+
expires_at?: string | null;
|
|
105
|
+
}
|
|
106
|
+
interface TakoSearchResult {
|
|
107
|
+
cards: TakoCard[];
|
|
108
|
+
web_results: TakoWebResult[];
|
|
109
|
+
contents_total_cost: number;
|
|
110
|
+
request_id: string;
|
|
111
|
+
}
|
|
112
|
+
interface TakoAnswerResult {
|
|
113
|
+
/** Synthesized text answer. */
|
|
114
|
+
answer: string;
|
|
115
|
+
/** Backing cards; cards[0] is the lead card. */
|
|
116
|
+
cards: TakoCard[];
|
|
117
|
+
web_results: TakoWebResult[];
|
|
118
|
+
contents_total_cost: number;
|
|
119
|
+
request_id: string;
|
|
120
|
+
}
|
|
121
|
+
interface TakoContentsResult {
|
|
122
|
+
contents: TakoContentItem[];
|
|
123
|
+
request_id: string;
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
/** Tako fast-pipeline search: returns Tako cards + web results, no LLM synthesis. */
|
|
127
|
+
declare function takoSearch(config?: TakoRetrievalConfig): Tool<{
|
|
3
128
|
query: string;
|
|
4
|
-
},
|
|
5
|
-
|
|
129
|
+
}, TakoSearchResult>;
|
|
130
|
+
|
|
131
|
+
/** Tako answer: fast-pipeline retrieval plus an LLM-synthesized answer grounded in the results. */
|
|
132
|
+
declare function takoAnswer(config?: TakoRetrievalConfig): Tool<{
|
|
133
|
+
query: string;
|
|
134
|
+
}, TakoAnswerResult>;
|
|
135
|
+
|
|
136
|
+
/** Download the data behind a result URL: a Tako card's CSV or a web page's text. */
|
|
137
|
+
declare function takoContents(config?: TakoContentsConfig): Tool<{
|
|
138
|
+
url: string;
|
|
139
|
+
}, TakoContentsResult>;
|
|
140
|
+
|
|
141
|
+
export { type TakoAnswerResult, type TakoBaseConfig, type TakoCard, type TakoCardSourceIndex, type TakoCardSourceIndexSegment, type TakoCardSourceOptions, type TakoCardSourcePrivateIndex, type TakoContentFormat, type TakoContentItem, type TakoContentsConfig, type TakoContentsMode, type TakoContentsResult, type TakoKnowledgeCardMethodology, type TakoKnowledgeCardRelevance, type TakoKnowledgeCardSource, type TakoResultContent, type TakoRetrievalConfig, type TakoSearchEffort, type TakoSearchResult, type TakoSourceOptions, type TakoWebResult, takoAnswer, takoContents, takoSearch };
|
package/dist/index.js
CHANGED
|
@@ -1,58 +1,135 @@
|
|
|
1
|
-
|
|
1
|
+
// src/tools/search.ts
|
|
2
|
+
import { tool } from "ai";
|
|
2
3
|
import { z } from "zod";
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
text: query,
|
|
21
|
-
},
|
|
22
|
-
source_indexes: sourceIndexes,
|
|
23
|
-
search_effort: searchEffort,
|
|
24
|
-
country_code: countryCode,
|
|
25
|
-
locale: locale,
|
|
26
|
-
};
|
|
27
|
-
if (outputSettings) {
|
|
28
|
-
requestBody.output_settings = {
|
|
29
|
-
knowledge_card_settings: {
|
|
30
|
-
image_dark_mode: outputSettings.knowledgeCardSettings?.imageDarkMode,
|
|
31
|
-
},
|
|
32
|
-
};
|
|
33
|
-
}
|
|
34
|
-
try {
|
|
35
|
-
const response = await fetch("https://trytako.com/api/v1/knowledge_search", {
|
|
36
|
-
method: "POST",
|
|
37
|
-
headers: {
|
|
38
|
-
"Content-Type": "application/json",
|
|
39
|
-
"X-API-Key": apiKey,
|
|
40
|
-
},
|
|
41
|
-
body: JSON.stringify(requestBody),
|
|
42
|
-
});
|
|
43
|
-
if (!response.ok) {
|
|
44
|
-
const errorText = await response.text();
|
|
45
|
-
throw new Error(`Tako API error: ${response.status} - ${errorText}`);
|
|
46
|
-
}
|
|
47
|
-
const data = await response.json();
|
|
48
|
-
return data;
|
|
49
|
-
}
|
|
50
|
-
catch (error) {
|
|
51
|
-
if (error instanceof Error) {
|
|
52
|
-
throw new Error(`Failed to search with Tako: ${error.message}`);
|
|
53
|
-
}
|
|
54
|
-
throw error;
|
|
55
|
-
}
|
|
56
|
-
},
|
|
4
|
+
|
|
5
|
+
// src/client.ts
|
|
6
|
+
async function callTako(opts) {
|
|
7
|
+
const { baseUrl, path, apiKey, body, operation } = opts;
|
|
8
|
+
if (!apiKey) {
|
|
9
|
+
throw new Error(
|
|
10
|
+
"TAKO_API_KEY is required. Set it in environment variables or pass it in config."
|
|
11
|
+
);
|
|
12
|
+
}
|
|
13
|
+
try {
|
|
14
|
+
const response = await fetch(`${baseUrl}${path}`, {
|
|
15
|
+
method: "POST",
|
|
16
|
+
headers: {
|
|
17
|
+
"Content-Type": "application/json",
|
|
18
|
+
"X-API-Key": apiKey
|
|
19
|
+
},
|
|
20
|
+
body: JSON.stringify(body)
|
|
57
21
|
});
|
|
22
|
+
if (!response.ok) {
|
|
23
|
+
const errorText = await response.text();
|
|
24
|
+
throw new Error(`Tako API error: ${response.status} - ${errorText}`);
|
|
25
|
+
}
|
|
26
|
+
return await response.json();
|
|
27
|
+
} catch (error) {
|
|
28
|
+
if (error instanceof Error) {
|
|
29
|
+
throw new Error(`Failed to ${operation} with Tako: ${error.message}`);
|
|
30
|
+
}
|
|
31
|
+
throw error;
|
|
32
|
+
}
|
|
58
33
|
}
|
|
34
|
+
|
|
35
|
+
// src/request.ts
|
|
36
|
+
var DEFAULT_BASE_URL = "https://trytako.com";
|
|
37
|
+
function resolveApiKey(config) {
|
|
38
|
+
return config.apiKey ?? process.env.TAKO_API_KEY ?? process.env.TAKO_API_TOKEN;
|
|
39
|
+
}
|
|
40
|
+
function resolveBaseUrl(config) {
|
|
41
|
+
return (config.baseUrl ?? DEFAULT_BASE_URL).replace(/\/+$/, "");
|
|
42
|
+
}
|
|
43
|
+
function buildSearchRequestBody(config, query) {
|
|
44
|
+
const body = {
|
|
45
|
+
query,
|
|
46
|
+
effort: config.effort ?? "fast",
|
|
47
|
+
country_code: config.countryCode ?? "US",
|
|
48
|
+
locale: config.locale ?? "en-US"
|
|
49
|
+
};
|
|
50
|
+
if (config.sources) {
|
|
51
|
+
const sources = {};
|
|
52
|
+
if (config.sources.tako) {
|
|
53
|
+
const tako = {};
|
|
54
|
+
if (config.sources.tako.count !== void 0) tako.count = config.sources.tako.count;
|
|
55
|
+
if (config.sources.tako.includeContents !== void 0) tako.include_contents = config.sources.tako.includeContents;
|
|
56
|
+
if (config.sources.tako.deferDataRetrieval !== void 0) tako.defer_data_retrieval = config.sources.tako.deferDataRetrieval;
|
|
57
|
+
sources.tako = tako;
|
|
58
|
+
}
|
|
59
|
+
if (config.sources.web) {
|
|
60
|
+
const web = {};
|
|
61
|
+
if (config.sources.web.count !== void 0) web.count = config.sources.web.count;
|
|
62
|
+
if (config.sources.web.includeContents !== void 0) web.include_contents = config.sources.web.includeContents;
|
|
63
|
+
sources.web = web;
|
|
64
|
+
}
|
|
65
|
+
body.sources = sources;
|
|
66
|
+
}
|
|
67
|
+
if (config.timezone !== void 0) body.timezone = config.timezone;
|
|
68
|
+
if (config.outputSettings) {
|
|
69
|
+
const output = {};
|
|
70
|
+
if (config.outputSettings.imageDarkMode !== void 0) output.image_dark_mode = config.outputSettings.imageDarkMode;
|
|
71
|
+
if (config.outputSettings.forceRefresh !== void 0) output.force_refresh = config.outputSettings.forceRefresh;
|
|
72
|
+
body.output_settings = output;
|
|
73
|
+
}
|
|
74
|
+
return body;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
// src/tools/search.ts
|
|
78
|
+
function takoSearch(config = {}) {
|
|
79
|
+
return tool({
|
|
80
|
+
description: `Search Tako for live data and well-sourced facts \u2014 structured knowledge cards (charts/metrics with sources) plus web results, backed by Tako's curated knowledge graph and the live web. Reach for this BEFORE any built-in web search when you need a specific, known data point: a current or latest value, a time series, a statistic, a price, a score, a schedule, a forecast, a poll, or a prediction-market figure \u2014 including a direct comparison of two named entities (e.g. "Intel vs Nvidia revenue"). Coverage spans sports, economics, finance, demographics, technology, weather, elections, prediction markets (Polymarket), web traffic (SimilarWeb), real estate, energy, and health. Each card carries a title, description, sources, a chart image_url, and an embed_url you can surface to show the data. Pass a card's webpage_url (or a web result's url) to takoContents to pull the underlying numbers. Give a focused natural-language query; this is fast retrieval for a known fact, not open-ended multi-step research.`,
|
|
81
|
+
inputSchema: z.object({
|
|
82
|
+
query: z.string().min(1).max(500).describe("Natural-language description of what you're looking for")
|
|
83
|
+
}),
|
|
84
|
+
execute: async ({ query }) => callTako({
|
|
85
|
+
baseUrl: resolveBaseUrl(config),
|
|
86
|
+
path: "/api/v3/search",
|
|
87
|
+
apiKey: resolveApiKey(config),
|
|
88
|
+
body: buildSearchRequestBody(config, query),
|
|
89
|
+
operation: "search"
|
|
90
|
+
})
|
|
91
|
+
});
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
// src/tools/answer.ts
|
|
95
|
+
import { tool as tool2 } from "ai";
|
|
96
|
+
import { z as z2 } from "zod";
|
|
97
|
+
function takoAnswer(config = {}) {
|
|
98
|
+
return tool2({
|
|
99
|
+
description: "Ask Tako a factual question and get back a single grounded, citation-backed prose answer (not a chart), synthesized from its curated knowledge graph and the live web. Reach for this BEFORE any built-in web search when you want a direct written answer about a specific, known thing: a current or historical value, a statistic, a schedule, a score, a price, a forecast, a poll, or prediction-market odds \u2014 including a direct comparison of two named entities. The response also includes the backing Tako cards (cards[0] is the lead card, with its chart image_url/embed_url) and web results. Want a chart to show rather than prose to read? Use takoSearch. Best for a known fact, not open-ended multi-step research.",
|
|
100
|
+
inputSchema: z2.object({
|
|
101
|
+
query: z2.string().min(1).max(500).describe("The question to answer")
|
|
102
|
+
}),
|
|
103
|
+
execute: async ({ query }) => callTako({
|
|
104
|
+
baseUrl: resolveBaseUrl(config),
|
|
105
|
+
path: "/api/v1/answer",
|
|
106
|
+
apiKey: resolveApiKey(config),
|
|
107
|
+
body: buildSearchRequestBody(config, query),
|
|
108
|
+
operation: "answer"
|
|
109
|
+
})
|
|
110
|
+
});
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
// src/tools/contents.ts
|
|
114
|
+
import { tool as tool3 } from "ai";
|
|
115
|
+
import { z as z3 } from "zod";
|
|
116
|
+
function takoContents(config = {}) {
|
|
117
|
+
return tool3({
|
|
118
|
+
description: `Fetch the underlying data behind a result URL \u2014 a Tako card's webpage_url yields a CSV of the card's data; any other URL (a web result's url) yields the page's extracted full text. Pass a single url taken from a prior takoSearch/takoAnswer result. Delivery is set at construction via \`mode\`: the default "url" returns a short-lived presigned download_url (no row cap) for handing over a download/embed link or for large data you won't read yourself; "inline" instead returns the content in the response (CSV capped at 1000 rows, with total_rows/truncated, or web text) so you can read and reason over the numbers directly.`,
|
|
119
|
+
inputSchema: z3.object({
|
|
120
|
+
url: z3.string().min(1).describe("A TakoCard.webpage_url or WebResult.url to download contents for")
|
|
121
|
+
}),
|
|
122
|
+
execute: async ({ url }) => callTako({
|
|
123
|
+
baseUrl: resolveBaseUrl(config),
|
|
124
|
+
path: "/api/v1/contents",
|
|
125
|
+
apiKey: resolveApiKey(config),
|
|
126
|
+
body: { url, mode: config.mode ?? "url" },
|
|
127
|
+
operation: "fetch contents"
|
|
128
|
+
})
|
|
129
|
+
});
|
|
130
|
+
}
|
|
131
|
+
export {
|
|
132
|
+
takoAnswer,
|
|
133
|
+
takoContents,
|
|
134
|
+
takoSearch
|
|
135
|
+
};
|
package/package.json
CHANGED
|
@@ -1,21 +1,20 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@takoviz/ai-sdk",
|
|
3
|
-
"version": "
|
|
4
|
-
"description": "Tako knowledge search
|
|
3
|
+
"version": "2.0.0",
|
|
4
|
+
"description": "Tako knowledge search, answer, and contents tools for the Vercel AI SDK",
|
|
5
|
+
"type": "module",
|
|
5
6
|
"main": "./dist/index.js",
|
|
7
|
+
"module": "./dist/index.js",
|
|
6
8
|
"types": "./dist/index.d.ts",
|
|
7
9
|
"exports": {
|
|
8
10
|
".": {
|
|
9
11
|
"import": "./dist/index.js",
|
|
10
|
-
"require": "./dist/index.js",
|
|
11
12
|
"types": "./dist/index.d.ts"
|
|
12
13
|
}
|
|
13
14
|
},
|
|
14
|
-
"
|
|
15
|
-
"
|
|
16
|
-
|
|
17
|
-
"prepublishOnly": "npm run build"
|
|
18
|
-
},
|
|
15
|
+
"files": [
|
|
16
|
+
"dist"
|
|
17
|
+
],
|
|
19
18
|
"keywords": [
|
|
20
19
|
"tako",
|
|
21
20
|
"knowledge-search",
|
|
@@ -27,7 +26,7 @@
|
|
|
27
26
|
],
|
|
28
27
|
"author": "Tako",
|
|
29
28
|
"license": "MIT",
|
|
30
|
-
"homepage": "https://
|
|
29
|
+
"homepage": "https://trytako.com",
|
|
31
30
|
"repository": {
|
|
32
31
|
"type": "git",
|
|
33
32
|
"url": "git+https://github.com/TakoData/ai-sdk.git"
|
|
@@ -36,18 +35,22 @@
|
|
|
36
35
|
"url": "https://github.com/TakoData/ai-sdk/issues"
|
|
37
36
|
},
|
|
38
37
|
"peerDependencies": {
|
|
39
|
-
"ai": "^6.0.18"
|
|
40
|
-
|
|
41
|
-
"dependencies": {
|
|
42
|
-
"@ai-sdk/anthropic": "^3.0.8",
|
|
43
|
-
"@ai-sdk/gateway": "^3.0.9",
|
|
44
|
-
"@ai-sdk/openai": "^3.0.7",
|
|
45
|
-
"@ai-sdk/provider-utils": "^4.0.4",
|
|
46
|
-
"zod": "^3.22.0"
|
|
38
|
+
"ai": "^6.0.18 || ^7.0.0",
|
|
39
|
+
"zod": "^4.0.0"
|
|
47
40
|
},
|
|
48
41
|
"devDependencies": {
|
|
49
|
-
"@
|
|
50
|
-
"
|
|
51
|
-
"
|
|
42
|
+
"@ai-sdk/openai": "^4.0.0",
|
|
43
|
+
"@types/node": "^24.10.1",
|
|
44
|
+
"ai": "^7.0.0",
|
|
45
|
+
"tsup": "^8.5.0",
|
|
46
|
+
"tsx": "^4.20.6",
|
|
47
|
+
"typescript": "^5.9.3",
|
|
48
|
+
"vitest": "^3.0.0"
|
|
49
|
+
},
|
|
50
|
+
"scripts": {
|
|
51
|
+
"build": "tsup src/index.ts --format esm --dts",
|
|
52
|
+
"typecheck": "tsc --noEmit -p tsconfig.check.json",
|
|
53
|
+
"test": "vitest run",
|
|
54
|
+
"test:watch": "vitest"
|
|
52
55
|
}
|
|
53
|
-
}
|
|
56
|
+
}
|
package/PUBLISH.md
DELETED
|
@@ -1,45 +0,0 @@
|
|
|
1
|
-
# Publishing to npm
|
|
2
|
-
|
|
3
|
-
## Steps to Publish
|
|
4
|
-
|
|
5
|
-
1. **Login to npm** (if not already logged in):
|
|
6
|
-
```bash
|
|
7
|
-
npm login
|
|
8
|
-
```
|
|
9
|
-
|
|
10
|
-
2. **Build the package**:
|
|
11
|
-
```bash
|
|
12
|
-
npm run build
|
|
13
|
-
```
|
|
14
|
-
This compiles TypeScript to JavaScript in the `dist/` folder.
|
|
15
|
-
|
|
16
|
-
3. **Publish to npm**:
|
|
17
|
-
```bash
|
|
18
|
-
npm publish --access public
|
|
19
|
-
```
|
|
20
|
-
|
|
21
|
-
The package will be published as `@takoviz/ai-sdk` version `1.0.0`.
|
|
22
|
-
|
|
23
|
-
4. **Verify publication**:
|
|
24
|
-
- Check at: https://www.npmjs.com/package/@takoviz/ai-sdk
|
|
25
|
-
- Test installation: `npm install @takoviz/ai-sdk`
|
|
26
|
-
|
|
27
|
-
---
|
|
28
|
-
|
|
29
|
-
## Updating Version
|
|
30
|
-
|
|
31
|
-
To publish a new version:
|
|
32
|
-
|
|
33
|
-
1. Update version in `package.json`:
|
|
34
|
-
```bash
|
|
35
|
-
npm version patch # For bug fixes (1.0.0 -> 1.0.1)
|
|
36
|
-
npm version minor # For new features (1.0.0 -> 1.1.0)
|
|
37
|
-
npm version major # For breaking changes (1.0.0 -> 2.0.0)
|
|
38
|
-
```
|
|
39
|
-
|
|
40
|
-
2. Build and publish:
|
|
41
|
-
```bash
|
|
42
|
-
npm run build
|
|
43
|
-
npm publish --access public
|
|
44
|
-
git push && git push --tags
|
|
45
|
-
```
|
package/VERCEL_REGISTRY.md
DELETED
|
@@ -1,104 +0,0 @@
|
|
|
1
|
-
# Adding Tako to Vercel AI Registry
|
|
2
|
-
|
|
3
|
-
After publishing to npm, follow these steps to add Tako to the official Vercel AI tools registry.
|
|
4
|
-
|
|
5
|
-
## Prerequisites
|
|
6
|
-
|
|
7
|
-
- ✅ Package published to npm at `@takoviz/ai-sdk`
|
|
8
|
-
- ✅ README with clear documentation
|
|
9
|
-
- ✅ Working code example tested
|
|
10
|
-
- ✅ API key instructions in README
|
|
11
|
-
|
|
12
|
-
## Steps
|
|
13
|
-
|
|
14
|
-
### 1. Fork and Clone Vercel AI Repository
|
|
15
|
-
|
|
16
|
-
```bash
|
|
17
|
-
git clone https://github.com/vercel/ai.git
|
|
18
|
-
cd ai
|
|
19
|
-
pnpm install
|
|
20
|
-
```
|
|
21
|
-
|
|
22
|
-
### 2. Create Feature Branch
|
|
23
|
-
|
|
24
|
-
```bash
|
|
25
|
-
git checkout -b feat/add-tool-tako-search
|
|
26
|
-
```
|
|
27
|
-
|
|
28
|
-
### 3. Add Tool Entry
|
|
29
|
-
|
|
30
|
-
Edit `content/tools-registry/registry.ts` and add this entry to the tools array:
|
|
31
|
-
|
|
32
|
-
```typescript
|
|
33
|
-
{
|
|
34
|
-
slug: 'tako-search',
|
|
35
|
-
name: 'Tako Search',
|
|
36
|
-
description: 'Search Tako\'s knowledge base for data visualizations, insights, and well-sourced information with charts and analytics.',
|
|
37
|
-
packageName: '@takoviz/ai-sdk',
|
|
38
|
-
installCommand: {
|
|
39
|
-
pnpm: 'pnpm add @takoviz/ai-sdk',
|
|
40
|
-
npm: 'npm install @takoviz/ai-sdk',
|
|
41
|
-
yarn: 'yarn add @takoviz/ai-sdk',
|
|
42
|
-
bun: 'bun add @takoviz/ai-sdk',
|
|
43
|
-
},
|
|
44
|
-
codeExample: `import { takoSearch } from '@takoviz/ai-sdk';
|
|
45
|
-
import { generateText } from 'ai';
|
|
46
|
-
|
|
47
|
-
const { text } = await generateText({
|
|
48
|
-
model: 'openai/gpt-4o-mini',
|
|
49
|
-
prompt: 'What is the stock price of Nvidia?',
|
|
50
|
-
tools: {
|
|
51
|
-
takoSearch: takoSearch(),
|
|
52
|
-
},
|
|
53
|
-
maxSteps: 5,
|
|
54
|
-
});
|
|
55
|
-
|
|
56
|
-
console.log(text);`,
|
|
57
|
-
docsUrl: 'https://github.com/TakoData/ai-sdk#readme',
|
|
58
|
-
npmUrl: 'https://www.npmjs.com/package/@takoviz/ai-sdk',
|
|
59
|
-
websiteUrl: 'https://tako.com',
|
|
60
|
-
apiKeyEnvName: 'TAKO_API_KEY',
|
|
61
|
-
apiKeyUrl: 'https://trytako.com',
|
|
62
|
-
tags: ['search', 'data', 'visualization', 'analytics'],
|
|
63
|
-
},
|
|
64
|
-
```
|
|
65
|
-
|
|
66
|
-
### 4. Test Locally
|
|
67
|
-
|
|
68
|
-
```bash
|
|
69
|
-
pnpm dev
|
|
70
|
-
```
|
|
71
|
-
|
|
72
|
-
Navigate to the tools registry page and verify your tool appears correctly.
|
|
73
|
-
|
|
74
|
-
### 5. Create Pull Request
|
|
75
|
-
|
|
76
|
-
```bash
|
|
77
|
-
git add content/tools-registry/registry.ts
|
|
78
|
-
git commit -m "feat(tools-registry): add tako-search"
|
|
79
|
-
git push origin feat/add-tool-tako-search
|
|
80
|
-
```
|
|
81
|
-
|
|
82
|
-
Then:
|
|
83
|
-
1. Go to https://github.com/vercel/ai
|
|
84
|
-
2. Click "New Pull Request"
|
|
85
|
-
3. Use title: `feat(tools-registry): add tako-search`
|
|
86
|
-
4. Description:
|
|
87
|
-
```
|
|
88
|
-
Adds Tako Search tool to the registry.
|
|
89
|
-
|
|
90
|
-
Tako Search provides access to Tako's knowledge base with data visualizations,
|
|
91
|
-
charts, and well-sourced analytics for AI applications.
|
|
92
|
-
|
|
93
|
-
- Package: @takoviz/ai-sdk
|
|
94
|
-
- Docs: https://github.com/TakoData/ai-sdk
|
|
95
|
-
- Website: https://tako.com
|
|
96
|
-
```
|
|
97
|
-
|
|
98
|
-
### 6. Wait for Review
|
|
99
|
-
|
|
100
|
-
The Vercel team will review and merge your PR. Once merged, Tako will appear in the official AI SDK tools registry at https://sdk.vercel.ai/docs/ai-sdk-ui/tools-registry!
|
|
101
|
-
|
|
102
|
-
## Reference
|
|
103
|
-
|
|
104
|
-
Official guide: https://github.com/vercel/ai/blob/main/contributing/add-new-tool-to-registry.md
|
package/dist/types.d.ts
DELETED
|
@@ -1,36 +0,0 @@
|
|
|
1
|
-
export interface TakoSearchConfig {
|
|
2
|
-
apiKey?: string;
|
|
3
|
-
sourceIndexes?: ("tako" | "web" | "connected_data")[];
|
|
4
|
-
searchEffort?: "fast" | "deep" | "auto";
|
|
5
|
-
outputSettings?: {
|
|
6
|
-
knowledgeCardSettings?: {
|
|
7
|
-
imageDarkMode?: boolean;
|
|
8
|
-
};
|
|
9
|
-
};
|
|
10
|
-
countryCode?: string;
|
|
11
|
-
locale?: string;
|
|
12
|
-
}
|
|
13
|
-
export interface TakoSource {
|
|
14
|
-
source_name: string;
|
|
15
|
-
url: string;
|
|
16
|
-
}
|
|
17
|
-
export interface TakoVisualizationData {
|
|
18
|
-
data: any[];
|
|
19
|
-
viz_config: Record<string, any>;
|
|
20
|
-
}
|
|
21
|
-
export interface TakoKnowledgeCard {
|
|
22
|
-
card_id: string;
|
|
23
|
-
title: string;
|
|
24
|
-
description: string;
|
|
25
|
-
webpage_url: string;
|
|
26
|
-
image_url: string;
|
|
27
|
-
sources: TakoSource[];
|
|
28
|
-
visualization_data: TakoVisualizationData;
|
|
29
|
-
}
|
|
30
|
-
export interface TakoSearchResponse {
|
|
31
|
-
outputs: {
|
|
32
|
-
knowledge_cards: TakoKnowledgeCard[];
|
|
33
|
-
answer: string;
|
|
34
|
-
};
|
|
35
|
-
request_id: string;
|
|
36
|
-
}
|
package/dist/types.js
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export {};
|
package/test.ts
DELETED
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
import { takoSearch } from './src/index.js';
|
|
2
|
-
import { generateText } from 'ai';
|
|
3
|
-
import { openai } from '@ai-sdk/openai';
|
|
4
|
-
|
|
5
|
-
async function test() {
|
|
6
|
-
const result = await generateText({
|
|
7
|
-
model: openai('gpt-4o-mini'),
|
|
8
|
-
prompt: 'What is the stock price of Nvidia?',
|
|
9
|
-
tools: {
|
|
10
|
-
takoSearch: takoSearch(),
|
|
11
|
-
},
|
|
12
|
-
maxSteps: 5,
|
|
13
|
-
});
|
|
14
|
-
|
|
15
|
-
console.log('Result text:', result.text);
|
|
16
|
-
console.log('\nTool calls:', JSON.stringify(result.toolCalls, null, 2));
|
|
17
|
-
console.log('\nTool results:', JSON.stringify(result.toolResults, null, 2));
|
|
18
|
-
console.log('\nSteps:', result.steps.length);
|
|
19
|
-
console.log('\nWarnings:', result.warnings);
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
test().catch(console.error);
|