@ia-ccun/code-agent-cli 0.0.52-release → 0.0.53
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/config/agent/bin/README.md +102 -0
- package/config/agent/bin/fd.exe +0 -0
- package/config/agent/bin/rg.exe +0 -0
- package/config/agent/extensions/aicode-advisor.ts +13 -0
- package/config/agent/extensions/aicode-btw.ts +66 -14
- package/config/agent/extensions/aicode-cd.ts +834 -0
- package/config/agent/extensions/aicode-grillMe.ts +198 -0
- package/config/agent/extensions/aicode-pets.ts +362 -0
- package/config/agent/extensions/aicode-safety-guard.ts +552 -0
- package/config/agent/extensions/aicode-tips.ts +70 -16
- package/config/agent/extensions/aicode-todo-progress.ts +547 -0
- package/config/agent/extensions/custom.ts +93 -95
- package/config/agent/extensions/error-monitor.ts +1 -18
- package/config/agent/extensions/ponytail.ts +441 -0
- package/config/agent/extensions/tps.ts +87 -0
- package/config/agent/extensions/working-msg.ts +165 -50
- package/config/agent/help.md +0 -7
- package/config/agent/models.json +7 -7
- package/config/agent/settings.json +2 -1
- package/config/agent/skills/chroma/LICENSE +21 -0
- package/config/agent/skills/chroma/chroma-local/SKILL.md +165 -0
- package/config/agent/skills/chroma/chroma-local/cli.md +48 -0
- package/config/agent/skills/chroma/chroma-local/data-model.md +103 -0
- package/config/agent/skills/chroma/chroma-local/error-handling/python.md +166 -0
- package/config/agent/skills/chroma/chroma-local/error-handling/typescript.md +231 -0
- package/config/agent/skills/chroma/chroma-local/local-chroma/python.md +95 -0
- package/config/agent/skills/chroma/chroma-local/local-chroma/typescript.md +101 -0
- package/config/agent/skills/chroma/chroma-local/metadata/python.md +154 -0
- package/config/agent/skills/chroma/chroma-local/metadata/typescript.md +153 -0
- package/config/agent/skills/chroma/chroma-local/querying/python.md +147 -0
- package/config/agent/skills/chroma/chroma-local/querying/typescript.md +157 -0
- package/config/agent/skills/chroma/chroma-local/regex/python.md +69 -0
- package/config/agent/skills/chroma/chroma-local/regex/typescript.md +71 -0
- package/config/agent/skills/chroma/chroma-local/understanding-a-codebase.md +80 -0
- package/config/agent/skills/chroma/chroma-local/updating-deleting/python.md +159 -0
- package/config/agent/skills/chroma/chroma-local/updating-deleting/typescript.md +228 -0
- package/config/agent/skills/milvus-skill/LICENSE +202 -0
- package/config/agent/skills/milvus-skill/README.md +37 -0
- package/config/agent/skills/milvus-skill/SKILL.md +259 -0
- package/config/agent/skills/milvus-skill/references/collection.md +86 -0
- package/config/agent/skills/milvus-skill/references/database.md +24 -0
- package/config/agent/skills/milvus-skill/references/index.md +69 -0
- package/config/agent/skills/milvus-skill/references/partition.md +29 -0
- package/config/agent/skills/milvus-skill/references/patterns.md +150 -0
- package/config/agent/skills/milvus-skill/references/user-role.md +90 -0
- package/config/agent/skills/milvus-skill/references/vector.md +247 -0
- package/config/agent/skills/ponytail/SKILL.md +100 -0
- package/config/agent/skills/ponytail-audit/SKILL.md +40 -0
- package/config/agent/skills/ponytail-debt/SKILL.md +44 -0
- package/config/agent/skills/ponytail-help/SKILL.md +68 -0
- package/config/agent/skills/ponytail-review/SKILL.md +56 -0
- package/config/agent/skills/zread/README.md +115 -0
- package/config/agent/skills/zread/SKILL.md +103 -0
- package/config/agent/skills/zread/references/stdio-protocol.md +312 -0
- package/package.json +6 -5
- package/scripts/postinstall.js +58 -1
- package/config/agent/dangerous-patterns.json +0 -106
- package/config/agent/extensions/bash-check.ts +0 -227
|
@@ -2,11 +2,15 @@
|
|
|
2
2
|
* @author: xujianjiang
|
|
3
3
|
* working-message
|
|
4
4
|
*
|
|
5
|
-
* 自定义工作消息,格式类似 Claude Code: ✶ xxx… (时间
|
|
5
|
+
* 自定义工作消息,格式类似 Claude Code: ✶ xxx… (时间)
|
|
6
|
+
*
|
|
7
|
+
* 改进:使用 dispose 模式防止内存泄漏
|
|
8
|
+
* - 使用明确类型,避免 any
|
|
9
|
+
* - 实现可靠的定时器清理机制
|
|
10
|
+
* - 双重保障确保资源释放
|
|
6
11
|
*/
|
|
7
12
|
|
|
8
|
-
import type { ExtensionAPI, TurnEndEvent } from "@earendil-works/pi-coding-agent";
|
|
9
|
-
import type { AssistantMessage } from "@earendil-works/pi-ai";
|
|
13
|
+
import type { ExtensionAPI, ExtensionContext, TurnEndEvent } from "@earendil-works/pi-coding-agent";
|
|
10
14
|
|
|
11
15
|
// 主题色 #49bccf
|
|
12
16
|
const accentColor = "\x1b[38;2;73;188;207m";
|
|
@@ -44,10 +48,100 @@ const workingMessages = [
|
|
|
44
48
|
"Algorithm", "Architecture", "Database", "Cache", "Queue", "Microservice",
|
|
45
49
|
];
|
|
46
50
|
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
51
|
+
/**
|
|
52
|
+
* 工作消息状态管理器 - 使用 dispose 模式
|
|
53
|
+
* 确保定时器和 UI 引用的生命周期管理,防止内存泄漏
|
|
54
|
+
*/
|
|
55
|
+
class WorkingMessageStateManager {
|
|
56
|
+
// ✅ 使用明确类型,避免 any
|
|
57
|
+
private _ui: ExtensionContext['ui'] | null = null;
|
|
58
|
+
private _intervalId: ReturnType<typeof setInterval> | null = null;
|
|
59
|
+
private _startTime: number = 0;
|
|
60
|
+
private _disposed: boolean = false;
|
|
61
|
+
|
|
62
|
+
// Getter 方法
|
|
63
|
+
get ui(): ExtensionContext['ui'] | null {
|
|
64
|
+
return this._ui;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
get intervalId(): ReturnType<typeof setInterval> | null {
|
|
68
|
+
return this._intervalId;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
get startTime(): number {
|
|
72
|
+
return this._startTime;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
isDisposed(): boolean {
|
|
76
|
+
return this._disposed;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
// Setter 方法(检查 disposed 状态)
|
|
80
|
+
setUI(ui: ExtensionContext['ui'] | null): void {
|
|
81
|
+
if (this._disposed) {
|
|
82
|
+
console.warn('[working-msg] State already disposed, cannot set UI');
|
|
83
|
+
return;
|
|
84
|
+
}
|
|
85
|
+
this._ui = ui;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
setInterval(intervalId: ReturnType<typeof setInterval> | null): void {
|
|
89
|
+
if (this._disposed) {
|
|
90
|
+
console.warn('[working-msg] State already disposed, cannot set interval');
|
|
91
|
+
return;
|
|
92
|
+
}
|
|
93
|
+
this._intervalId = intervalId;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
setStartTime(startTime: number): void {
|
|
97
|
+
if (this._disposed) {
|
|
98
|
+
console.warn('[working-msg] State already disposed, cannot set start time');
|
|
99
|
+
return;
|
|
100
|
+
}
|
|
101
|
+
this._startTime = startTime;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
/**
|
|
105
|
+
* dispose() - 清理所有资源
|
|
106
|
+
* ✅ 双重保障:清理定时器 + 清理 UI 引用
|
|
107
|
+
* ✅ disposed 标记防止重复清理
|
|
108
|
+
*/
|
|
109
|
+
dispose(): void {
|
|
110
|
+
if (this._disposed) {
|
|
111
|
+
return; // 防止重复 dispose
|
|
112
|
+
}
|
|
50
113
|
|
|
114
|
+
// ✅ 清理定时器(双重保障)
|
|
115
|
+
if (this._intervalId) {
|
|
116
|
+
clearInterval(this._intervalId);
|
|
117
|
+
this._intervalId = null;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
// ✅ 清理 UI 引用
|
|
121
|
+
if (this._ui) {
|
|
122
|
+
try {
|
|
123
|
+
this._ui.setWorkingMessage(undefined);
|
|
124
|
+
} catch (error) {
|
|
125
|
+
// ✅ 忽略错误,确保清理继续
|
|
126
|
+
console.warn('[working-msg] Error clearing working message:', error);
|
|
127
|
+
}
|
|
128
|
+
this._ui = null;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
this._disposed = true;
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
/**
|
|
135
|
+
* reset() - 重置状态(用于新的 turn)
|
|
136
|
+
*/
|
|
137
|
+
reset(): void {
|
|
138
|
+
this.dispose(); // 先清理旧资源
|
|
139
|
+
this._disposed = false; // 重置 disposed 标记
|
|
140
|
+
this._startTime = 0;
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
// 工具函数
|
|
51
145
|
function getNextMessage(): string {
|
|
52
146
|
const randomIndex = Math.floor(Math.random() * workingMessages.length);
|
|
53
147
|
return workingMessages[randomIndex];
|
|
@@ -60,56 +154,77 @@ function formatTime(seconds: number): string {
|
|
|
60
154
|
return `${mins} m ${secs} s`;
|
|
61
155
|
}
|
|
62
156
|
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
157
|
+
/**
|
|
158
|
+
* ✅ 改进的定时器逻辑
|
|
159
|
+
* - 不依赖 try-catch
|
|
160
|
+
* - 检查 disposed 状态
|
|
161
|
+
* - 使用 state.ui(明确类型)
|
|
162
|
+
*/
|
|
163
|
+
function startInterval(state: WorkingMessageStateManager): void {
|
|
164
|
+
if (state.isDisposed() || !state.ui) {
|
|
165
|
+
return;
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
const intervalId = setInterval(() => {
|
|
169
|
+
// ✅ 每次执行前检查 disposed 和 UI 状态
|
|
170
|
+
if (state.isDisposed() || !state.ui) {
|
|
171
|
+
// ✅ 自动清理
|
|
172
|
+
state.dispose();
|
|
173
|
+
return;
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
// ✅ 安全执行(明确类型)
|
|
177
|
+
const elapsed = Math.floor((Date.now() - state.startTime) / 1000);
|
|
178
|
+
const timeStr = formatTime(elapsed);
|
|
179
|
+
const msg = `${accentColor} ✶ ${getNextMessage()}…${reset} (${timeStr})`;
|
|
180
|
+
|
|
181
|
+
try {
|
|
182
|
+
state.ui.setWorkingMessage(msg);
|
|
183
|
+
} catch (error) {
|
|
184
|
+
// ✅ 如果 UI 调用失败,自动清理
|
|
185
|
+
console.warn('[working-msg] UI call failed, disposing:', error);
|
|
186
|
+
state.dispose();
|
|
187
|
+
}
|
|
188
|
+
}, 3000);
|
|
189
|
+
|
|
190
|
+
state.setInterval(intervalId);
|
|
66
191
|
}
|
|
67
192
|
|
|
193
|
+
/**
|
|
194
|
+
* 扩展主函数 - 使用 dispose 模式管理状态
|
|
195
|
+
*/
|
|
68
196
|
export default function workingMessageExtension(pi: ExtensionAPI) {
|
|
69
|
-
//
|
|
197
|
+
// ✅ 单一状态管理器
|
|
198
|
+
const state = new WorkingMessageStateManager();
|
|
199
|
+
|
|
200
|
+
// ✅ session_shutdown - 清理所有资源
|
|
201
|
+
pi.on("session_shutdown", async (_event, ctx) => {
|
|
202
|
+
state.dispose();
|
|
203
|
+
});
|
|
204
|
+
|
|
205
|
+
// ✅ turn_start - 初始化状态并启动定时器
|
|
70
206
|
pi.on("turn_start", async (_event, ctx) => {
|
|
71
|
-
if (!ctx.ui)
|
|
72
|
-
|
|
73
|
-
// 记录开始时间
|
|
74
|
-
startTime = Date.now();
|
|
75
|
-
totalTokens = 0;
|
|
76
|
-
|
|
77
|
-
// 立即设置第一条
|
|
78
|
-
const updateMessage = () => {
|
|
79
|
-
const elapsed = Math.floor((Date.now() - startTime) / 1000);
|
|
80
|
-
const timeStr = formatTime(elapsed);
|
|
81
|
-
const tokensStr = formatTokens(totalTokens);
|
|
82
|
-
// ✶ 和单词显示为主题色
|
|
83
|
-
const msg = `${accentColor} ✶ ${getNextMessage()}…${reset} (${timeStr} · ↓ ${tokensStr} tokens)`;
|
|
84
|
-
ctx.ui?.setWorkingMessage(msg);
|
|
85
|
-
};
|
|
86
|
-
|
|
87
|
-
updateMessage();
|
|
88
|
-
|
|
89
|
-
// 每3秒更新一次
|
|
90
|
-
if (!intervalId) {
|
|
91
|
-
intervalId = setInterval(() => {
|
|
92
|
-
// 获取当前 tokens 使用量
|
|
93
|
-
for (const entry of ctx.sessionManager.getBranch()) {
|
|
94
|
-
if (entry.type === "message" && (entry as any).message?.role === "assistant") {
|
|
95
|
-
const msg = (entry as any).message as AssistantMessage;
|
|
96
|
-
if (msg.usage?.output) {
|
|
97
|
-
totalTokens = msg.usage.output;
|
|
98
|
-
}
|
|
99
|
-
}
|
|
100
|
-
}
|
|
101
|
-
updateMessage();
|
|
102
|
-
}, 3000);
|
|
207
|
+
if (!ctx.ui) {
|
|
208
|
+
return;
|
|
103
209
|
}
|
|
210
|
+
|
|
211
|
+
// ✅ 重置状态(清理旧资源)
|
|
212
|
+
state.reset();
|
|
213
|
+
state.setUI(ctx.ui); // ✅ 明确类型:ExtensionContext['ui']
|
|
214
|
+
state.setStartTime(Date.now());
|
|
215
|
+
|
|
216
|
+
// 设置第一条消息
|
|
217
|
+
const elapsed = Math.floor((Date.now() - state.startTime) / 1000);
|
|
218
|
+
const timeStr = formatTime(elapsed);
|
|
219
|
+
const msg = `${accentColor} ✶ ${getNextMessage()}…${reset} (${timeStr})`;
|
|
220
|
+
state.ui?.setWorkingMessage(msg);
|
|
221
|
+
|
|
222
|
+
// ✅ 启动定时器
|
|
223
|
+
startInterval(state);
|
|
104
224
|
});
|
|
105
225
|
|
|
106
|
-
//
|
|
226
|
+
// ✅ turn_end - 清理所有资源
|
|
107
227
|
pi.on("turn_end", async (_event: TurnEndEvent, ctx) => {
|
|
108
|
-
|
|
109
|
-
clearInterval(intervalId);
|
|
110
|
-
intervalId = null;
|
|
111
|
-
}
|
|
112
|
-
// 恢复默认消息
|
|
113
|
-
ctx.ui?.setWorkingMessage(undefined);
|
|
228
|
+
state.dispose();
|
|
114
229
|
});
|
|
115
|
-
}
|
|
230
|
+
}
|
package/config/agent/help.md
CHANGED
|
@@ -470,13 +470,6 @@ aicode-cli --verbose
|
|
|
470
470
|
| `--theme <name>` | 指定主题 |
|
|
471
471
|
| `--model <name>` | 指定模型 |
|
|
472
472
|
| `--clear` | 启动时清理会话 |
|
|
473
|
-
|
|
474
|
-
### 相关资源
|
|
475
|
-
|
|
476
|
-
- **项目仓库**: https://github.com/ia-ccun/code-agent-cli
|
|
477
|
-
- **npm 包**: https://www.npmjs.com/package/@ia-ccun/code-agent-cli
|
|
478
|
-
- **pi-coding-agent**: 底层 Agent 框架
|
|
479
|
-
|
|
480
473
|
---
|
|
481
474
|
|
|
482
475
|
*世界那么哒 · AI 实践落地 @2026*
|
package/config/agent/models.json
CHANGED
|
@@ -1,20 +1,20 @@
|
|
|
1
1
|
{
|
|
2
2
|
"providers": {
|
|
3
|
-
"
|
|
4
|
-
"name": "
|
|
3
|
+
"aicode": {
|
|
4
|
+
"name": "aicode llm",
|
|
5
5
|
"baseUrl": "https://ai-llm.cc.com/v1",
|
|
6
6
|
"api": "openai-completions",
|
|
7
|
-
"apiKey": "你自己的APIKEY",
|
|
7
|
+
"apiKey": "你自己的APIKEY sk-xxxxxxxxxxxxxxxxxx",
|
|
8
8
|
"headers": {
|
|
9
9
|
"User-Agent": "${VERSION}"
|
|
10
10
|
},
|
|
11
11
|
"models": [
|
|
12
12
|
{
|
|
13
|
-
"id": "
|
|
14
|
-
"name": "
|
|
15
|
-
"contextWindow":
|
|
13
|
+
"id": "qwen3.6-35b-a3b",
|
|
14
|
+
"name": "qwen3.6",
|
|
15
|
+
"contextWindow": 128000,
|
|
16
16
|
"maxTokens": 100000,
|
|
17
|
-
"reasoning":
|
|
17
|
+
"reasoning": false,
|
|
18
18
|
"input": ["text"],
|
|
19
19
|
"cost": {
|
|
20
20
|
"input": 5,
|
|
@@ -10,7 +10,8 @@
|
|
|
10
10
|
"~/.aicode-cli/agent/extensions/custom-footer.ts",
|
|
11
11
|
"~/.aicode-cli/agent/extensions/custom.ts",
|
|
12
12
|
"~/.aicode-cli/agent/extensions/review.ts",
|
|
13
|
-
"~/.aicode-cli/agent/extensions/working-msg.ts"
|
|
13
|
+
"~/.aicode-cli/agent/extensions/working-msg.ts",
|
|
14
|
+
"-extensions/aicode-pets.ts"
|
|
14
15
|
],
|
|
15
16
|
"packages":[
|
|
16
17
|
"npm:pi-subagents@0.17.1",
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Chroma
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,165 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: chroma-local
|
|
3
|
+
description: Use when the user needs self-hosted or local Chroma for semantic search, including `ChromaClient`, `HttpClient`, or Python `EphemeralClient`, local persistence, Docker or `chroma run`, or OSS Chroma without Chroma Cloud features.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
## Instructions
|
|
7
|
+
|
|
8
|
+
Determine these before writing code. Prefer discovering them from the repo and the user request. Ask only when the choice materially changes the implementation.
|
|
9
|
+
|
|
10
|
+
1. **Runtime shape**
|
|
11
|
+
- Are they connecting to a running local server, embedding Chroma into tests, or setting up local development from scratch?
|
|
12
|
+
- Decide whether they need `chroma run`, a Docker or service command, `HttpClient` or `ChromaClient`, or Python `EphemeralClient`.
|
|
13
|
+
|
|
14
|
+
2. **Persistence**
|
|
15
|
+
- Persistent local data: choose an intentional data path.
|
|
16
|
+
- Disposable test data: use defaults or a temp directory.
|
|
17
|
+
|
|
18
|
+
3. **Embedding model**
|
|
19
|
+
- Reuse the app's existing embedding provider when possible.
|
|
20
|
+
- Otherwise default to `@chroma-core/default-embed` in TypeScript or the standard local default in Python.
|
|
21
|
+
- If the user explicitly wants OpenAI embeddings in TypeScript, install and use `@chroma-core/openai`.
|
|
22
|
+
|
|
23
|
+
4. **Indexed data shape**
|
|
24
|
+
- Determine what is being indexed, how it should be chunked, and what metadata is needed for filtering and updates.
|
|
25
|
+
|
|
26
|
+
## Routing
|
|
27
|
+
|
|
28
|
+
- **Existing local server**
|
|
29
|
+
- Confirm host and port before changing client code.
|
|
30
|
+
- Validate the server is reachable before assuming collections are missing.
|
|
31
|
+
|
|
32
|
+
- **Fresh local development**
|
|
33
|
+
- Add a local startup path such as `chroma run` or the repo's existing Docker or service command.
|
|
34
|
+
- Default to `localhost:8000` unless the repo already uses another address.
|
|
35
|
+
|
|
36
|
+
- **Python tests or disposable local workflows**
|
|
37
|
+
- Prefer `EphemeralClient` when persistence is unnecessary.
|
|
38
|
+
- Call out that data is lost when the process exits.
|
|
39
|
+
|
|
40
|
+
- **Persistent local development**
|
|
41
|
+
- Use a stable data path and make persistence explicit in code or config.
|
|
42
|
+
- Do not silently switch between ephemeral and persistent modes.
|
|
43
|
+
|
|
44
|
+
- **Search integration work**
|
|
45
|
+
- Use `getOrCreateCollection()` in TypeScript or `get_or_create_collection()` in Python.
|
|
46
|
+
- Design document IDs and metadata so upserts and deletes are straightforward.
|
|
47
|
+
- Batch writes when syncing large datasets.
|
|
48
|
+
|
|
49
|
+
## Ask vs proceed
|
|
50
|
+
|
|
51
|
+
**Ask first:**
|
|
52
|
+
- Embedding model choice (cost and quality implications)
|
|
53
|
+
- Whether they need persistent local data
|
|
54
|
+
- How they are starting the local server
|
|
55
|
+
- Multi-tenant data isolation strategy
|
|
56
|
+
|
|
57
|
+
**Proceed with sensible defaults:**
|
|
58
|
+
- Use `getOrCreateCollection()` (TypeScript) / `get_or_create_collection()` (Python)
|
|
59
|
+
- Use cosine similarity (most common)
|
|
60
|
+
- Chunk size under 8KB
|
|
61
|
+
- Store source IDs in metadata for updates/deletes
|
|
62
|
+
- Use a local server on `localhost:8000` unless the repo already configures another address or is using Python `EphemeralClient`
|
|
63
|
+
|
|
64
|
+
## What to validate
|
|
65
|
+
|
|
66
|
+
- Correct client import (`ChromaClient`, `HttpClient`, or `Client`)
|
|
67
|
+
- Embedding function package is installed (TypeScript)
|
|
68
|
+
- Local server is reachable before assuming collections are missing
|
|
69
|
+
- Local path and persistence mode are intentional
|
|
70
|
+
|
|
71
|
+
## Implementation notes
|
|
72
|
+
|
|
73
|
+
- Local Chroma is the right default for development, tests, and self-hosted deployments.
|
|
74
|
+
- OSS Chroma does not include Chroma Cloud-only features such as `Schema()` and `Search()`.
|
|
75
|
+
- If the user asks for hybrid dense and sparse retrieval, treat that as a likely Chroma Cloud requirement unless the repo already implements an OSS workaround.
|
|
76
|
+
- For open source Chroma, dense retrieval with a single embedding function is the normal baseline.
|
|
77
|
+
|
|
78
|
+
## Minimal patterns
|
|
79
|
+
|
|
80
|
+
Start a local Chroma server when the repo needs one:
|
|
81
|
+
|
|
82
|
+
```bash
|
|
83
|
+
chroma run
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
Default address: `localhost:8000`.
|
|
87
|
+
|
|
88
|
+
TypeScript local client:
|
|
89
|
+
|
|
90
|
+
```typescript
|
|
91
|
+
import { ChromaClient } from 'chromadb';
|
|
92
|
+
import { DefaultEmbeddingFunction } from '@chroma-core/default-embed';
|
|
93
|
+
|
|
94
|
+
const client = new ChromaClient();
|
|
95
|
+
|
|
96
|
+
const embeddingFunction = new DefaultEmbeddingFunction();
|
|
97
|
+
const collection = await client.getOrCreateCollection({
|
|
98
|
+
name: 'my_collection',
|
|
99
|
+
embeddingFunction,
|
|
100
|
+
});
|
|
101
|
+
|
|
102
|
+
// Add documents
|
|
103
|
+
await collection.add({
|
|
104
|
+
ids: ['doc1', 'doc2'],
|
|
105
|
+
documents: ['First document text', 'Second document text'],
|
|
106
|
+
});
|
|
107
|
+
|
|
108
|
+
// Query
|
|
109
|
+
const results = await collection.query({
|
|
110
|
+
queryTexts: ['search query'],
|
|
111
|
+
nResults: 5,
|
|
112
|
+
});
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
Python local client:
|
|
116
|
+
|
|
117
|
+
```python
|
|
118
|
+
import chromadb
|
|
119
|
+
|
|
120
|
+
client = chromadb.HttpClient(host="localhost", port=8000)
|
|
121
|
+
|
|
122
|
+
collection = client.get_or_create_collection(name="my_collection")
|
|
123
|
+
|
|
124
|
+
# Add documents
|
|
125
|
+
collection.add(
|
|
126
|
+
ids=["doc1", "doc2"] ,
|
|
127
|
+
documents=["First document text", "Second document text"],
|
|
128
|
+
)
|
|
129
|
+
|
|
130
|
+
# Query
|
|
131
|
+
results = collection.query(
|
|
132
|
+
query_texts=["search query"],
|
|
133
|
+
n_results=5,
|
|
134
|
+
)
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
## Learn More
|
|
138
|
+
|
|
139
|
+
Fetch Chroma's `llms.txt` only when you need API or product details that are not already in the repo or this skill: https://docs.trychroma.com/llms.txt
|
|
140
|
+
|
|
141
|
+
## Available Topics
|
|
142
|
+
|
|
143
|
+
### Typescript
|
|
144
|
+
|
|
145
|
+
- [Chroma Regex Filtering](./regex/typescript.md) - Learn how to use regex filters in Chroma queries
|
|
146
|
+
- [Query and Get](./querying/typescript.md) - Query and Get Data from Chroma Collections
|
|
147
|
+
- [Metadata](./metadata/typescript.md) - Store and query metadata, including filters and array values
|
|
148
|
+
- [Updating and Deleting](./updating-deleting/typescript.md) - Update existing documents and delete data from collections
|
|
149
|
+
- [Error Handling](./error-handling/typescript.md) - Handling errors and failures when working with Chroma
|
|
150
|
+
- [Local Chroma](./local-chroma/typescript.md) - How to run and use local chroma
|
|
151
|
+
|
|
152
|
+
### Python
|
|
153
|
+
|
|
154
|
+
- [Chroma Regex Filtering](./regex/python.md) - Learn how to use regex filters in Chroma queries
|
|
155
|
+
- [Query and Get](./querying/python.md) - Query and Get Data from Chroma Collections
|
|
156
|
+
- [Metadata](./metadata/python.md) - Store and query metadata, including filters and array values
|
|
157
|
+
- [Updating and Deleting](./updating-deleting/python.md) - Update existing documents and delete data from collections
|
|
158
|
+
- [Error Handling](./error-handling/python.md) - Handling errors and failures when working with Chroma
|
|
159
|
+
- [Local Chroma](./local-chroma/python.md) - How to run and use local chroma
|
|
160
|
+
|
|
161
|
+
## General
|
|
162
|
+
|
|
163
|
+
- [Data Model](./data-model.md) - An overview of how Chroma stores data
|
|
164
|
+
- [Integrating Chroma into an existing system](./understanding-a-codebase.md) - Guidance for adding Chroma search to an existing application
|
|
165
|
+
- [Chroma CLI](./cli.md) - Starting and managing a local open source Chroma server from the CLI
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: Chroma CLI
|
|
3
|
+
description: Starting and managing a local open source Chroma server from the CLI
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
## Chroma CLI
|
|
7
|
+
|
|
8
|
+
The Chroma CLI can also be used for local open source Chroma workflows. This topic focuses on starting and managing a local server, not Chroma Cloud account setup.
|
|
9
|
+
|
|
10
|
+
### Install
|
|
11
|
+
|
|
12
|
+
```bash
|
|
13
|
+
pip install chromadb
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
### Start a local server
|
|
17
|
+
|
|
18
|
+
Run Chroma locally on the default address:
|
|
19
|
+
|
|
20
|
+
```bash
|
|
21
|
+
chroma run
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
This starts a server on `localhost:8000`.
|
|
25
|
+
|
|
26
|
+
### Choose a persistent data directory
|
|
27
|
+
|
|
28
|
+
Store local data in a specific path instead of the default working directory:
|
|
29
|
+
|
|
30
|
+
```bash
|
|
31
|
+
chroma run --path ./chroma-data
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
### Change the port
|
|
35
|
+
|
|
36
|
+
If another process already uses port `8000`, pick another one:
|
|
37
|
+
|
|
38
|
+
```bash
|
|
39
|
+
chroma run --port 8001
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
Update your client code to match the chosen host and port.
|
|
43
|
+
|
|
44
|
+
### Local workflow tips
|
|
45
|
+
|
|
46
|
+
- Use a dedicated data directory per environment so dev and test data do not mix.
|
|
47
|
+
- In tests, use disposable directories or clear collections between runs.
|
|
48
|
+
- Check that the server is running before debugging client-side collection errors.
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: Data Model
|
|
3
|
+
description: An overview of how Chroma stores data
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
## Data Model
|
|
7
|
+
|
|
8
|
+
Use this reference when designing collection layout, chunking, IDs, metadata, and filtering for Chroma.
|
|
9
|
+
|
|
10
|
+
### Core concepts
|
|
11
|
+
|
|
12
|
+
**Collections** are the top-level containers, similar to tables in a relational database. Each collection has its own embedding configuration and indexes.
|
|
13
|
+
|
|
14
|
+
**Documents** are the searchable units within a collection. Each document has:
|
|
15
|
+
- **ID** - A unique string identifier
|
|
16
|
+
- **Content** - The text that gets embedded and searched
|
|
17
|
+
- **Embedding** - The vector representation
|
|
18
|
+
- **Metadata** - Key-value pairs for filtering
|
|
19
|
+
|
|
20
|
+
## Chunking
|
|
21
|
+
|
|
22
|
+
Most real-world data is too large to fit in a single document. Chunking splits content into searchable pieces.
|
|
23
|
+
|
|
24
|
+
### Chunking strategy
|
|
25
|
+
|
|
26
|
+
**Recommended chunk size:** Keep chunks comfortably below product limits and small enough to preserve search precision and context. Generally, 8KB or less is a good default starting point.
|
|
27
|
+
|
|
28
|
+
**Good chunking preserves meaning:**
|
|
29
|
+
- Split at natural boundaries (paragraphs, sentences, sections)
|
|
30
|
+
- Don't cut mid-sentence or mid-word
|
|
31
|
+
- Include enough context for the chunk to be meaningful on its own
|
|
32
|
+
|
|
33
|
+
**Determine from the repo or ask if ambiguous:**
|
|
34
|
+
- What type of content are they indexing?
|
|
35
|
+
- Are there natural boundaries (chapters, sections, records)?
|
|
36
|
+
- How much context does a search result need to be useful?
|
|
37
|
+
|
|
38
|
+
### Tracking chunks with metadata
|
|
39
|
+
|
|
40
|
+
When a single source document becomes multiple chunks, use metadata to track the relationship:
|
|
41
|
+
|
|
42
|
+
```
|
|
43
|
+
{
|
|
44
|
+
"source_id": "post-123", // ID in the primary database
|
|
45
|
+
"source_type": "blog_post", // Type of content
|
|
46
|
+
"chunk_index": 0, // Position in sequence
|
|
47
|
+
"total_chunks": 3 // Total chunks from this source
|
|
48
|
+
}
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
This approach is better than encoding information in the document ID because:
|
|
52
|
+
- IDs can be simple UUIDs
|
|
53
|
+
- Metadata is filterable
|
|
54
|
+
- Updates and deletes are easier (filter by `source_id`)
|
|
55
|
+
|
|
56
|
+
## Collection organization
|
|
57
|
+
|
|
58
|
+
For multi-tenant applications, separate collections per tenant are a strong default when isolation, deletion, and search quality matter more than minimizing collection count.
|
|
59
|
+
|
|
60
|
+
**Why this works better:**
|
|
61
|
+
- Nearest neighbor search is more accurate with fewer candidates
|
|
62
|
+
- Lower latency with smaller collections
|
|
63
|
+
- Natural isolation between tenants
|
|
64
|
+
- Easy to delete all tenant data by dropping the collection
|
|
65
|
+
|
|
66
|
+
**Example:** A knowledge base SaaS might have collections like `kb_customer_123`, `kb_customer_456`, etc.
|
|
67
|
+
|
|
68
|
+
**Determine from the repo or ask if ambiguous:** What's the smallest logical unit of data isolation in their application?
|
|
69
|
+
|
|
70
|
+
## Filtering
|
|
71
|
+
|
|
72
|
+
Metadata filtering reduces the candidate set before vector search runs, making queries faster and more precise.
|
|
73
|
+
|
|
74
|
+
### Filter operators
|
|
75
|
+
|
|
76
|
+
| Operator | Description | Types |
|
|
77
|
+
|----------|-------------|-------|
|
|
78
|
+
| `$eq` | Equal (default) | string, int, bool |
|
|
79
|
+
| `$ne` | Not equal | string, int, bool |
|
|
80
|
+
| `$gt`, `$gte` | Greater than (or equal) | int |
|
|
81
|
+
| `$lt`, `$lte` | Less than (or equal) | int |
|
|
82
|
+
| `$in` | In list | string, int |
|
|
83
|
+
| `$nin` | Not in list | string, int |
|
|
84
|
+
| `$and`, `$or` | Logical combinators | filter arrays |
|
|
85
|
+
| `$contains`, `$not_contains` | Check within arrays | arrays of string, int, bool |
|
|
86
|
+
|
|
87
|
+
### Document content filtering
|
|
88
|
+
|
|
89
|
+
Beyond metadata, you can filter on the document text itself using `where_document`:
|
|
90
|
+
- `$contains` - Full-text substring search
|
|
91
|
+
- `$regex` - Regular expression matching
|
|
92
|
+
|
|
93
|
+
## Dense vs sparse vectors
|
|
94
|
+
|
|
95
|
+
**Dense vectors** (default) are produced by neural embedding models. They capture semantic meaning, so "car" and "automobile" will be similar.
|
|
96
|
+
|
|
97
|
+
**Sparse vectors** (BM25, SPLADE) are high-dimensional but mostly zeros. They excel at exact keyword matching.
|
|
98
|
+
|
|
99
|
+
**Hybrid search** combines both, often outperforming either alone. Chroma Cloud supports hybrid search through the Schema and Search APIs.
|
|
100
|
+
|
|
101
|
+
### Important note
|
|
102
|
+
|
|
103
|
+
When creating collections, `get_or_create_collection()` accepts either an `embedding_function` OR a `schema`, but not both. Use Schema when you need multiple indexes or sparse embeddings.
|