agentikit 0.0.12 → 0.0.13
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 +17 -1
- package/package.json +1 -1
- package/dist/src/similarity.js +0 -211
package/README.md
CHANGED
|
@@ -35,11 +35,24 @@ When you search or open an asset, the working stash takes priority. This
|
|
|
35
35
|
means you can install a kit and override individual assets by cloning them
|
|
36
36
|
into your working stash.
|
|
37
37
|
|
|
38
|
+
## Prerequisites
|
|
39
|
+
|
|
40
|
+
Agent-i-Kit requires [Bun](https://bun.sh) (v1.0+) as its runtime. It uses
|
|
41
|
+
Bun-specific APIs (`bun:sqlite`) that are not available in Node.js.
|
|
42
|
+
|
|
43
|
+
```sh
|
|
44
|
+
# Install Bun if you don't have it
|
|
45
|
+
curl -fsSL https://bun.sh/install | bash
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
> **Don't want to install Bun?** Use the [standalone binary](#standalone-binary)
|
|
49
|
+
> instead -- it has no runtime dependencies.
|
|
50
|
+
|
|
38
51
|
## Quick Start
|
|
39
52
|
|
|
40
53
|
```sh
|
|
41
54
|
# Install
|
|
42
|
-
|
|
55
|
+
bun install -g agentikit
|
|
43
56
|
|
|
44
57
|
# Initialize your stash
|
|
45
58
|
akm init
|
|
@@ -59,6 +72,9 @@ akm search "lint" --source both
|
|
|
59
72
|
|
|
60
73
|
### Standalone Binary
|
|
61
74
|
|
|
75
|
+
The standalone binary bundles everything it needs and does **not** require Bun
|
|
76
|
+
or Node.js.
|
|
77
|
+
|
|
62
78
|
```sh
|
|
63
79
|
# macOS / Linux
|
|
64
80
|
curl -fsSL https://raw.githubusercontent.com/itlackey/agentikit/main/install.sh | bash
|
package/package.json
CHANGED
package/dist/src/similarity.js
DELETED
|
@@ -1,211 +0,0 @@
|
|
|
1
|
-
export class TfIdfAdapter {
|
|
2
|
-
documents = [];
|
|
3
|
-
idf = new Map();
|
|
4
|
-
entries = [];
|
|
5
|
-
buildIndex(entries) {
|
|
6
|
-
this.entries = entries;
|
|
7
|
-
const docCount = entries.length;
|
|
8
|
-
if (docCount === 0)
|
|
9
|
-
return;
|
|
10
|
-
// Compute term frequencies per document
|
|
11
|
-
const docFreqs = new Map();
|
|
12
|
-
this.documents = entries.map((entry) => {
|
|
13
|
-
const tokens = tokenize(entry.text);
|
|
14
|
-
const termFreqs = new Map();
|
|
15
|
-
for (const token of tokens) {
|
|
16
|
-
termFreqs.set(token, (termFreqs.get(token) || 0) + 1);
|
|
17
|
-
}
|
|
18
|
-
// Track document frequency for IDF
|
|
19
|
-
for (const term of termFreqs.keys()) {
|
|
20
|
-
docFreqs.set(term, (docFreqs.get(term) || 0) + 1);
|
|
21
|
-
}
|
|
22
|
-
return { entry, termFreqs, magnitude: 0 };
|
|
23
|
-
});
|
|
24
|
-
// Compute IDF: log(N / df)
|
|
25
|
-
this.idf = new Map();
|
|
26
|
-
for (const [term, df] of docFreqs) {
|
|
27
|
-
this.idf.set(term, Math.log(docCount / df));
|
|
28
|
-
}
|
|
29
|
-
// Compute document magnitudes for cosine similarity
|
|
30
|
-
for (const doc of this.documents) {
|
|
31
|
-
let sumSq = 0;
|
|
32
|
-
for (const [term, tf] of doc.termFreqs) {
|
|
33
|
-
const idf = this.idf.get(term) || 0;
|
|
34
|
-
const tfidf = tf * idf;
|
|
35
|
-
sumSq += tfidf * tfidf;
|
|
36
|
-
}
|
|
37
|
-
doc.magnitude = Math.sqrt(sumSq);
|
|
38
|
-
}
|
|
39
|
-
}
|
|
40
|
-
search(query, limit, typeFilter) {
|
|
41
|
-
if (this.documents.length === 0)
|
|
42
|
-
return [];
|
|
43
|
-
const queryTokens = tokenize(query.toLowerCase());
|
|
44
|
-
if (queryTokens.length === 0) {
|
|
45
|
-
// Empty query: return all, sorted by type
|
|
46
|
-
return this.documents
|
|
47
|
-
.filter((d) => !typeFilter || typeFilter === "any" || d.entry.entry.type === typeFilter)
|
|
48
|
-
.slice(0, limit)
|
|
49
|
-
.map((d) => ({
|
|
50
|
-
entry: d.entry.entry,
|
|
51
|
-
path: d.entry.path,
|
|
52
|
-
score: 1,
|
|
53
|
-
}));
|
|
54
|
-
}
|
|
55
|
-
// Build query TF-IDF vector
|
|
56
|
-
const queryTermFreqs = new Map();
|
|
57
|
-
for (const token of queryTokens) {
|
|
58
|
-
queryTermFreqs.set(token, (queryTermFreqs.get(token) || 0) + 1);
|
|
59
|
-
}
|
|
60
|
-
let queryMagnitude = 0;
|
|
61
|
-
const queryVector = new Map();
|
|
62
|
-
for (const [term, tf] of queryTermFreqs) {
|
|
63
|
-
const idf = this.idf.get(term) || 0;
|
|
64
|
-
const tfidf = tf * idf;
|
|
65
|
-
queryVector.set(term, tfidf);
|
|
66
|
-
queryMagnitude += tfidf * tfidf;
|
|
67
|
-
}
|
|
68
|
-
queryMagnitude = Math.sqrt(queryMagnitude);
|
|
69
|
-
if (queryMagnitude === 0) {
|
|
70
|
-
// All query terms are unknown — fallback to substring match
|
|
71
|
-
return this.substringFallback(query, limit, typeFilter);
|
|
72
|
-
}
|
|
73
|
-
const results = [];
|
|
74
|
-
const querySet = new Set(queryTokens);
|
|
75
|
-
for (const doc of this.documents) {
|
|
76
|
-
if (typeFilter && typeFilter !== "any" && doc.entry.entry.type !== typeFilter)
|
|
77
|
-
continue;
|
|
78
|
-
// Cosine similarity
|
|
79
|
-
let dotProduct = 0;
|
|
80
|
-
for (const [term, queryTfidf] of queryVector) {
|
|
81
|
-
const docTf = doc.termFreqs.get(term) || 0;
|
|
82
|
-
if (docTf === 0)
|
|
83
|
-
continue;
|
|
84
|
-
const docIdf = this.idf.get(term) || 0;
|
|
85
|
-
dotProduct += queryTfidf * (docTf * docIdf);
|
|
86
|
-
}
|
|
87
|
-
let score = doc.magnitude > 0 && queryMagnitude > 0
|
|
88
|
-
? dotProduct / (doc.magnitude * queryMagnitude)
|
|
89
|
-
: 0;
|
|
90
|
-
// Boost: tag exact match
|
|
91
|
-
const tags = doc.entry.entry.tags || [];
|
|
92
|
-
for (const tag of tags) {
|
|
93
|
-
if (querySet.has(tag.toLowerCase())) {
|
|
94
|
-
score += 0.15;
|
|
95
|
-
}
|
|
96
|
-
}
|
|
97
|
-
// Boost: intent phrase contains query token
|
|
98
|
-
const intents = doc.entry.entry.intents || [];
|
|
99
|
-
for (const intent of intents) {
|
|
100
|
-
const intentLower = intent.toLowerCase();
|
|
101
|
-
for (const token of queryTokens) {
|
|
102
|
-
if (intentLower.includes(token)) {
|
|
103
|
-
score += 0.12;
|
|
104
|
-
break; // one boost per intent phrase
|
|
105
|
-
}
|
|
106
|
-
}
|
|
107
|
-
}
|
|
108
|
-
// Boost: name contains query token
|
|
109
|
-
const nameLower = doc.entry.entry.name.toLowerCase().replace(/[-_]/g, " ");
|
|
110
|
-
for (const token of queryTokens) {
|
|
111
|
-
if (nameLower.includes(token)) {
|
|
112
|
-
score += 0.1;
|
|
113
|
-
break;
|
|
114
|
-
}
|
|
115
|
-
}
|
|
116
|
-
if (score > 0) {
|
|
117
|
-
results.push({
|
|
118
|
-
entry: doc.entry.entry,
|
|
119
|
-
path: doc.entry.path,
|
|
120
|
-
score: Math.round(score * 1000) / 1000,
|
|
121
|
-
});
|
|
122
|
-
}
|
|
123
|
-
}
|
|
124
|
-
results.sort((a, b) => b.score - a.score);
|
|
125
|
-
return results.slice(0, limit);
|
|
126
|
-
}
|
|
127
|
-
serialize() {
|
|
128
|
-
const idf = {};
|
|
129
|
-
for (const [term, val] of this.idf) {
|
|
130
|
-
idf[term] = val;
|
|
131
|
-
}
|
|
132
|
-
const docs = this.documents.map((d) => {
|
|
133
|
-
const termFreqs = {};
|
|
134
|
-
for (const [term, tf] of d.termFreqs) {
|
|
135
|
-
termFreqs[term] = tf;
|
|
136
|
-
}
|
|
137
|
-
return { id: d.entry.id, termFreqs, magnitude: d.magnitude };
|
|
138
|
-
});
|
|
139
|
-
return { idf, docs };
|
|
140
|
-
}
|
|
141
|
-
static deserialize(data, entries) {
|
|
142
|
-
const adapter = new TfIdfAdapter();
|
|
143
|
-
adapter.entries = entries;
|
|
144
|
-
adapter.idf = new Map(Object.entries(data.idf));
|
|
145
|
-
const entryMap = new Map(entries.map((e) => [e.id, e]));
|
|
146
|
-
adapter.documents = data.docs
|
|
147
|
-
.map((d) => {
|
|
148
|
-
const entry = entryMap.get(d.id);
|
|
149
|
-
if (!entry)
|
|
150
|
-
return null;
|
|
151
|
-
return {
|
|
152
|
-
entry,
|
|
153
|
-
termFreqs: new Map(Object.entries(d.termFreqs)),
|
|
154
|
-
magnitude: d.magnitude,
|
|
155
|
-
};
|
|
156
|
-
})
|
|
157
|
-
.filter((d) => d !== null);
|
|
158
|
-
return adapter;
|
|
159
|
-
}
|
|
160
|
-
substringFallback(query, limit, typeFilter) {
|
|
161
|
-
const q = query.toLowerCase();
|
|
162
|
-
const tokens = tokenize(q);
|
|
163
|
-
return this.documents
|
|
164
|
-
.map((d) => {
|
|
165
|
-
if (typeFilter && typeFilter !== "any" && d.entry.entry.type !== typeFilter)
|
|
166
|
-
return null;
|
|
167
|
-
// Check if any query token matches the document text or name
|
|
168
|
-
const text = d.entry.text;
|
|
169
|
-
const name = d.entry.entry.name.toLowerCase();
|
|
170
|
-
let matchCount = 0;
|
|
171
|
-
for (const token of tokens) {
|
|
172
|
-
if (text.includes(token) || name.includes(token))
|
|
173
|
-
matchCount++;
|
|
174
|
-
}
|
|
175
|
-
// Also check full substring match
|
|
176
|
-
if (text.includes(q) || name.includes(q))
|
|
177
|
-
matchCount = Math.max(matchCount, tokens.length);
|
|
178
|
-
if (matchCount === 0)
|
|
179
|
-
return null;
|
|
180
|
-
return {
|
|
181
|
-
entry: d.entry.entry,
|
|
182
|
-
path: d.entry.path,
|
|
183
|
-
score: Math.round((matchCount / Math.max(tokens.length, 1)) * 500) / 1000,
|
|
184
|
-
};
|
|
185
|
-
})
|
|
186
|
-
.filter((d) => d !== null)
|
|
187
|
-
.sort((a, b) => b.score - a.score)
|
|
188
|
-
.slice(0, limit);
|
|
189
|
-
}
|
|
190
|
-
}
|
|
191
|
-
// ── Tokenization ────────────────────────────────────────────────────────────
|
|
192
|
-
const STOP_WORDS = new Set([
|
|
193
|
-
"a", "an", "the", "is", "are", "was", "were", "be", "been", "being",
|
|
194
|
-
"have", "has", "had", "do", "does", "did", "will", "would", "could",
|
|
195
|
-
"should", "may", "might", "shall", "can", "need", "dare", "ought",
|
|
196
|
-
"to", "of", "in", "for", "on", "with", "at", "by", "from", "as",
|
|
197
|
-
"into", "through", "during", "before", "after", "above", "below",
|
|
198
|
-
"and", "but", "or", "nor", "not", "so", "yet", "both", "either",
|
|
199
|
-
"neither", "each", "every", "all", "any", "few", "more", "most",
|
|
200
|
-
"other", "some", "such", "no", "only", "own", "same", "than",
|
|
201
|
-
"too", "very", "just", "because", "if", "when", "where", "how",
|
|
202
|
-
"what", "which", "who", "whom", "this", "that", "these", "those",
|
|
203
|
-
"it", "its",
|
|
204
|
-
]);
|
|
205
|
-
function tokenize(text) {
|
|
206
|
-
return text
|
|
207
|
-
.toLowerCase()
|
|
208
|
-
.replace(/[^a-z0-9]+/g, " ")
|
|
209
|
-
.split(/\s+/)
|
|
210
|
-
.filter((t) => t.length > 1 && !STOP_WORDS.has(t));
|
|
211
|
-
}
|