@zhin.js/core 1.0.37 → 1.0.39
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/CHANGELOG.md +18 -0
- package/README.md +57 -3
- package/lib/adapter.d.ts +11 -0
- package/lib/adapter.d.ts.map +1 -1
- package/lib/adapter.js +61 -0
- package/lib/adapter.js.map +1 -1
- package/lib/ai/index.d.ts +3 -39
- package/lib/ai/index.d.ts.map +1 -1
- package/lib/ai/index.js +2 -44
- package/lib/ai/index.js.map +1 -1
- package/lib/ai/providers/anthropic.d.ts.map +1 -1
- package/lib/ai/providers/anthropic.js +2 -0
- package/lib/ai/providers/anthropic.js.map +1 -1
- package/lib/ai/providers/openai.d.ts.map +1 -1
- package/lib/ai/providers/openai.js +8 -0
- package/lib/ai/providers/openai.js.map +1 -1
- package/lib/ai/types.d.ts +5 -3
- package/lib/ai/types.d.ts.map +1 -1
- package/lib/built/ai-trigger.js.map +1 -1
- package/lib/built/common-adapter-tools.d.ts +55 -0
- package/lib/built/common-adapter-tools.d.ts.map +1 -0
- package/lib/built/common-adapter-tools.js +158 -0
- package/lib/built/common-adapter-tools.js.map +1 -0
- package/lib/built/dispatcher.d.ts.map +1 -1
- package/lib/built/dispatcher.js +50 -46
- package/lib/built/dispatcher.js.map +1 -1
- package/lib/built/skill.d.ts.map +1 -1
- package/lib/built/skill.js +0 -1
- package/lib/built/skill.js.map +1 -1
- package/lib/built/tool.d.ts +3 -3
- package/lib/built/tool.d.ts.map +1 -1
- package/lib/built/tool.js.map +1 -1
- package/lib/feature.d.ts +16 -1
- package/lib/feature.d.ts.map +1 -1
- package/lib/feature.js +41 -2
- package/lib/feature.js.map +1 -1
- package/lib/index.d.ts +1 -0
- package/lib/index.d.ts.map +1 -1
- package/lib/index.js +2 -0
- package/lib/index.js.map +1 -1
- package/lib/plugin.d.ts +38 -1
- package/lib/plugin.d.ts.map +1 -1
- package/lib/plugin.js +73 -22
- package/lib/plugin.js.map +1 -1
- package/lib/scheduler/scheduler.js +1 -1
- package/lib/scheduler/scheduler.js.map +1 -1
- package/lib/types.d.ts +43 -28
- package/lib/types.d.ts.map +1 -1
- package/lib/utils.d.ts +12 -3
- package/lib/utils.d.ts.map +1 -1
- package/lib/utils.js +64 -54
- package/lib/utils.js.map +1 -1
- package/package.json +5 -5
- package/src/adapter.ts +85 -5
- package/src/ai/index.ts +8 -186
- package/src/ai/providers/anthropic.ts +1 -0
- package/src/ai/providers/openai.ts +5 -1
- package/src/ai/types.ts +6 -4
- package/src/built/ai-trigger.ts +2 -2
- package/src/built/common-adapter-tools.ts +207 -0
- package/src/built/dispatcher.ts +51 -52
- package/src/built/skill.ts +3 -4
- package/src/built/tool.ts +3 -3
- package/src/feature.ts +45 -2
- package/src/index.ts +2 -0
- package/src/plugin.ts +92 -31
- package/src/scheduler/scheduler.ts +1 -1
- package/src/types.ts +39 -28
- package/src/utils.ts +63 -52
- package/tests/ai/setup.ts +2 -2
- package/tests/utils.test.ts +1 -3
- package/lib/ai/agent.d.ts +0 -130
- package/lib/ai/agent.d.ts.map +0 -1
- package/lib/ai/agent.js +0 -702
- package/lib/ai/agent.js.map +0 -1
- package/lib/ai/bootstrap.d.ts +0 -91
- package/lib/ai/bootstrap.d.ts.map +0 -1
- package/lib/ai/bootstrap.js +0 -243
- package/lib/ai/bootstrap.js.map +0 -1
- package/lib/ai/builtin-tools.d.ts +0 -59
- package/lib/ai/builtin-tools.d.ts.map +0 -1
- package/lib/ai/builtin-tools.js +0 -777
- package/lib/ai/builtin-tools.js.map +0 -1
- package/lib/ai/compaction.d.ts +0 -132
- package/lib/ai/compaction.d.ts.map +0 -1
- package/lib/ai/compaction.js +0 -370
- package/lib/ai/compaction.js.map +0 -1
- package/lib/ai/context-manager.d.ts +0 -213
- package/lib/ai/context-manager.d.ts.map +0 -1
- package/lib/ai/context-manager.js +0 -313
- package/lib/ai/context-manager.js.map +0 -1
- package/lib/ai/conversation-memory.d.ts +0 -181
- package/lib/ai/conversation-memory.d.ts.map +0 -1
- package/lib/ai/conversation-memory.js +0 -581
- package/lib/ai/conversation-memory.js.map +0 -1
- package/lib/ai/cron-engine.d.ts +0 -92
- package/lib/ai/cron-engine.d.ts.map +0 -1
- package/lib/ai/cron-engine.js +0 -278
- package/lib/ai/cron-engine.js.map +0 -1
- package/lib/ai/follow-up.d.ts +0 -131
- package/lib/ai/follow-up.d.ts.map +0 -1
- package/lib/ai/follow-up.js +0 -265
- package/lib/ai/follow-up.js.map +0 -1
- package/lib/ai/hooks.d.ts +0 -143
- package/lib/ai/hooks.d.ts.map +0 -1
- package/lib/ai/hooks.js +0 -108
- package/lib/ai/hooks.js.map +0 -1
- package/lib/ai/init.d.ts +0 -30
- package/lib/ai/init.d.ts.map +0 -1
- package/lib/ai/init.js +0 -686
- package/lib/ai/init.js.map +0 -1
- package/lib/ai/output.d.ts +0 -93
- package/lib/ai/output.d.ts.map +0 -1
- package/lib/ai/output.js +0 -176
- package/lib/ai/output.js.map +0 -1
- package/lib/ai/rate-limiter.d.ts +0 -38
- package/lib/ai/rate-limiter.d.ts.map +0 -1
- package/lib/ai/rate-limiter.js +0 -86
- package/lib/ai/rate-limiter.js.map +0 -1
- package/lib/ai/service.d.ts +0 -88
- package/lib/ai/service.d.ts.map +0 -1
- package/lib/ai/service.js +0 -285
- package/lib/ai/service.js.map +0 -1
- package/lib/ai/session.d.ts +0 -186
- package/lib/ai/session.d.ts.map +0 -1
- package/lib/ai/session.js +0 -443
- package/lib/ai/session.js.map +0 -1
- package/lib/ai/subagent.d.ts +0 -50
- package/lib/ai/subagent.d.ts.map +0 -1
- package/lib/ai/subagent.js +0 -144
- package/lib/ai/subagent.js.map +0 -1
- package/lib/ai/tone-detector.d.ts +0 -19
- package/lib/ai/tone-detector.d.ts.map +0 -1
- package/lib/ai/tone-detector.js +0 -72
- package/lib/ai/tone-detector.js.map +0 -1
- package/lib/ai/tools.d.ts +0 -45
- package/lib/ai/tools.d.ts.map +0 -1
- package/lib/ai/tools.js +0 -206
- package/lib/ai/tools.js.map +0 -1
- package/lib/ai/user-profile.d.ts +0 -56
- package/lib/ai/user-profile.d.ts.map +0 -1
- package/lib/ai/user-profile.js +0 -130
- package/lib/ai/user-profile.js.map +0 -1
- package/lib/ai/zhin-agent/builtin-tools.d.ts +0 -17
- package/lib/ai/zhin-agent/builtin-tools.d.ts.map +0 -1
- package/lib/ai/zhin-agent/builtin-tools.js +0 -220
- package/lib/ai/zhin-agent/builtin-tools.js.map +0 -1
- package/lib/ai/zhin-agent/config.d.ts +0 -54
- package/lib/ai/zhin-agent/config.d.ts.map +0 -1
- package/lib/ai/zhin-agent/config.js +0 -76
- package/lib/ai/zhin-agent/config.js.map +0 -1
- package/lib/ai/zhin-agent/exec-policy.d.ts +0 -20
- package/lib/ai/zhin-agent/exec-policy.d.ts.map +0 -1
- package/lib/ai/zhin-agent/exec-policy.js +0 -71
- package/lib/ai/zhin-agent/exec-policy.js.map +0 -1
- package/lib/ai/zhin-agent/index.d.ts +0 -70
- package/lib/ai/zhin-agent/index.d.ts.map +0 -1
- package/lib/ai/zhin-agent/index.js +0 -404
- package/lib/ai/zhin-agent/index.js.map +0 -1
- package/lib/ai/zhin-agent/prompt.d.ts +0 -21
- package/lib/ai/zhin-agent/prompt.d.ts.map +0 -1
- package/lib/ai/zhin-agent/prompt.js +0 -111
- package/lib/ai/zhin-agent/prompt.js.map +0 -1
- package/lib/ai/zhin-agent/tool-collector.d.ts +0 -22
- package/lib/ai/zhin-agent/tool-collector.d.ts.map +0 -1
- package/lib/ai/zhin-agent/tool-collector.js +0 -218
- package/lib/ai/zhin-agent/tool-collector.js.map +0 -1
- package/src/ai/agent.ts +0 -831
- package/src/ai/bootstrap.ts +0 -309
- package/src/ai/builtin-tools.ts +0 -849
- package/src/ai/compaction.ts +0 -529
- package/src/ai/context-manager.ts +0 -440
- package/src/ai/conversation-memory.ts +0 -774
- package/src/ai/cron-engine.ts +0 -337
- package/src/ai/follow-up.ts +0 -357
- package/src/ai/hooks.ts +0 -223
- package/src/ai/init.ts +0 -762
- package/src/ai/output.ts +0 -261
- package/src/ai/rate-limiter.ts +0 -129
- package/src/ai/service.ts +0 -331
- package/src/ai/session.ts +0 -544
- package/src/ai/subagent.ts +0 -209
- package/src/ai/tone-detector.ts +0 -89
- package/src/ai/tools.ts +0 -218
- package/src/ai/user-profile.ts +0 -181
- package/src/ai/zhin-agent/builtin-tools.ts +0 -247
- package/src/ai/zhin-agent/config.ts +0 -113
- package/src/ai/zhin-agent/exec-policy.ts +0 -78
- package/src/ai/zhin-agent/index.ts +0 -512
- package/src/ai/zhin-agent/prompt.ts +0 -131
- package/src/ai/zhin-agent/tool-collector.ts +0 -243
- package/tests/ai/agent.test.ts +0 -614
- package/tests/ai/context-manager.test.ts +0 -413
- package/tests/ai/conversation-memory.test.ts +0 -128
- package/tests/ai/follow-up.test.ts +0 -175
- package/tests/ai/integration.test.ts +0 -584
- package/tests/ai/output.test.ts +0 -128
- package/tests/ai/rate-limiter.test.ts +0 -108
- package/tests/ai/session.test.ts +0 -375
- package/tests/ai/subagent.test.ts +0 -270
- package/tests/ai/tone-detector.test.ts +0 -80
- package/tests/ai/tools-builtin.test.ts +0 -346
- package/tests/ai/user-profile.test.ts +0 -73
- package/tests/ai/zhin-agent.test.ts +0 -177
package/src/ai/bootstrap.ts
DELETED
|
@@ -1,309 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Workspace Bootstrap Files
|
|
3
|
-
*
|
|
4
|
-
* Injectable prompt files inspired by OpenClaw's workspace bootstrap design:
|
|
5
|
-
*
|
|
6
|
-
* AGENTS.md — persistent memory / instructions (AI read-write)
|
|
7
|
-
* SOUL.md — persona definition (read-only)
|
|
8
|
-
* TOOLS.md — tool usage guidelines (read-only)
|
|
9
|
-
*
|
|
10
|
-
* Key design:
|
|
11
|
-
* 1. mtime-based file cache to avoid redundant disk reads
|
|
12
|
-
* 2. Missing files are silently skipped
|
|
13
|
-
* 3. Per-file and total size limits to prevent prompt injection
|
|
14
|
-
* 4. Unified ContextFile format for system prompt injection
|
|
15
|
-
*/
|
|
16
|
-
|
|
17
|
-
import * as fs from 'fs';
|
|
18
|
-
import * as path from 'path';
|
|
19
|
-
import { Logger } from '@zhin.js/logger';
|
|
20
|
-
|
|
21
|
-
const logger = new Logger(null, 'Bootstrap');
|
|
22
|
-
|
|
23
|
-
// ============================================================================
|
|
24
|
-
// 常量
|
|
25
|
-
// ============================================================================
|
|
26
|
-
|
|
27
|
-
/** 支持的引导文件名(顺序:SOUL → AGENTS → TOOLS) */
|
|
28
|
-
export const BOOTSTRAP_FILENAMES = [
|
|
29
|
-
'SOUL.md',
|
|
30
|
-
'AGENTS.md',
|
|
31
|
-
'TOOLS.md',
|
|
32
|
-
] as const;
|
|
33
|
-
|
|
34
|
-
export type BootstrapFileName = typeof BOOTSTRAP_FILENAMES[number];
|
|
35
|
-
|
|
36
|
-
/** 单文件最大字符数(默认 16KB) */
|
|
37
|
-
const DEFAULT_MAX_CHARS = 16 * 1024;
|
|
38
|
-
|
|
39
|
-
/** 所有引导文件总最大字符数(默认 48KB) */
|
|
40
|
-
const DEFAULT_TOTAL_MAX_CHARS = 48 * 1024;
|
|
41
|
-
|
|
42
|
-
// ============================================================================
|
|
43
|
-
// 类型
|
|
44
|
-
// ============================================================================
|
|
45
|
-
|
|
46
|
-
/** 引导文件信息 */
|
|
47
|
-
export interface BootstrapFile {
|
|
48
|
-
name: BootstrapFileName;
|
|
49
|
-
path: string;
|
|
50
|
-
content?: string;
|
|
51
|
-
missing: boolean;
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
/** 上下文文件(用于注入到 system prompt) */
|
|
55
|
-
export interface ContextFile {
|
|
56
|
-
path: string;
|
|
57
|
-
content: string;
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
// ============================================================================
|
|
61
|
-
// 文件缓存(基于 mtime)
|
|
62
|
-
// ============================================================================
|
|
63
|
-
|
|
64
|
-
const fileCache = new Map<string, { content: string; mtimeMs: number }>();
|
|
65
|
-
|
|
66
|
-
/**
|
|
67
|
-
* 读文件,带 mtime 缓存
|
|
68
|
-
*/
|
|
69
|
-
async function readFileWithCache(filePath: string): Promise<string> {
|
|
70
|
-
try {
|
|
71
|
-
const stats = await fs.promises.stat(filePath);
|
|
72
|
-
const mtimeMs = stats.mtimeMs;
|
|
73
|
-
const cached = fileCache.get(filePath);
|
|
74
|
-
|
|
75
|
-
if (cached && cached.mtimeMs === mtimeMs) {
|
|
76
|
-
return cached.content;
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
const content = await fs.promises.readFile(filePath, 'utf-8');
|
|
80
|
-
fileCache.set(filePath, { content, mtimeMs });
|
|
81
|
-
return content;
|
|
82
|
-
} catch {
|
|
83
|
-
fileCache.delete(filePath);
|
|
84
|
-
throw new Error(`Failed to read file: ${filePath}`);
|
|
85
|
-
}
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
/**
|
|
89
|
-
* 清除文件缓存(热重载时调用)
|
|
90
|
-
*/
|
|
91
|
-
export function clearBootstrapCache(): void {
|
|
92
|
-
fileCache.clear();
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
// ============================================================================
|
|
96
|
-
// 文件加载
|
|
97
|
-
// ============================================================================
|
|
98
|
-
|
|
99
|
-
/**
|
|
100
|
-
* 获取数据目录
|
|
101
|
-
*/
|
|
102
|
-
function getDataDir(workspaceDir?: string): string {
|
|
103
|
-
const cwd = workspaceDir || process.cwd();
|
|
104
|
-
return path.join(cwd, 'data');
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
/**
|
|
108
|
-
* 获取文件制长期记忆目录(data/memory),不存在则创建
|
|
109
|
-
*/
|
|
110
|
-
export function getMemoryDir(workspaceDir?: string): string {
|
|
111
|
-
const dir = path.join(getDataDir(workspaceDir), 'memory');
|
|
112
|
-
if (!fs.existsSync(dir)) {
|
|
113
|
-
fs.mkdirSync(dir, { recursive: true });
|
|
114
|
-
}
|
|
115
|
-
return dir;
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
function todayDate(): string {
|
|
119
|
-
return new Date().toISOString().split('T')[0];
|
|
120
|
-
}
|
|
121
|
-
|
|
122
|
-
/**
|
|
123
|
-
* 读取文件制长期记忆 + 当日笔记,拼成注入 system prompt 的字符串(与 miniclawd 一致)
|
|
124
|
-
* 同步读取,供 buildRichSystemPrompt 等同步调用
|
|
125
|
-
*/
|
|
126
|
-
export function getFileMemoryContext(workspaceDir?: string): string {
|
|
127
|
-
const memoryDir = getMemoryDir(workspaceDir);
|
|
128
|
-
const parts: string[] = [];
|
|
129
|
-
|
|
130
|
-
const memoryFile = path.join(memoryDir, 'MEMORY.md');
|
|
131
|
-
if (fs.existsSync(memoryFile)) {
|
|
132
|
-
try {
|
|
133
|
-
const longTerm = fs.readFileSync(memoryFile, 'utf-8').trim();
|
|
134
|
-
if (longTerm) parts.push('## Long-term Memory\n' + longTerm);
|
|
135
|
-
} catch {
|
|
136
|
-
// ignore read errors
|
|
137
|
-
}
|
|
138
|
-
}
|
|
139
|
-
|
|
140
|
-
const todayFile = path.join(memoryDir, `${todayDate()}.md`);
|
|
141
|
-
if (fs.existsSync(todayFile)) {
|
|
142
|
-
try {
|
|
143
|
-
const today = fs.readFileSync(todayFile, 'utf-8').trim();
|
|
144
|
-
if (today) parts.push("## Today's Notes\n" + today);
|
|
145
|
-
} catch {
|
|
146
|
-
// ignore read errors
|
|
147
|
-
}
|
|
148
|
-
}
|
|
149
|
-
|
|
150
|
-
return parts.length > 0 ? parts.join('\n\n') : '';
|
|
151
|
-
}
|
|
152
|
-
|
|
153
|
-
/**
|
|
154
|
-
* 加载工作区引导文件
|
|
155
|
-
*
|
|
156
|
-
* 搜索顺序:项目根目录 → data/ 目录
|
|
157
|
-
*/
|
|
158
|
-
export async function loadBootstrapFiles(
|
|
159
|
-
workspaceDir?: string,
|
|
160
|
-
): Promise<BootstrapFile[]> {
|
|
161
|
-
const cwd = workspaceDir || process.cwd();
|
|
162
|
-
const dataDir = getDataDir(cwd);
|
|
163
|
-
|
|
164
|
-
const result: BootstrapFile[] = [];
|
|
165
|
-
|
|
166
|
-
for (const name of BOOTSTRAP_FILENAMES) {
|
|
167
|
-
// 优先项目根目录
|
|
168
|
-
const rootPath = path.join(cwd, name);
|
|
169
|
-
const dataPath = path.join(dataDir, name);
|
|
170
|
-
|
|
171
|
-
let found = false;
|
|
172
|
-
for (const filePath of [rootPath, dataPath]) {
|
|
173
|
-
try {
|
|
174
|
-
const content = await readFileWithCache(filePath);
|
|
175
|
-
result.push({ name, path: filePath, content, missing: false });
|
|
176
|
-
found = true;
|
|
177
|
-
break; // 找到就不再搜索
|
|
178
|
-
} catch {
|
|
179
|
-
// 继续尝试下一个路径
|
|
180
|
-
}
|
|
181
|
-
}
|
|
182
|
-
|
|
183
|
-
if (!found) {
|
|
184
|
-
result.push({ name, path: rootPath, missing: true });
|
|
185
|
-
}
|
|
186
|
-
}
|
|
187
|
-
|
|
188
|
-
return result;
|
|
189
|
-
}
|
|
190
|
-
|
|
191
|
-
/**
|
|
192
|
-
* 将引导文件转为上下文文件列表(用于注入到 system prompt)
|
|
193
|
-
*
|
|
194
|
-
* 自动裁剪超长内容,跳过缺失文件
|
|
195
|
-
*/
|
|
196
|
-
export function buildContextFiles(
|
|
197
|
-
bootstrapFiles: BootstrapFile[],
|
|
198
|
-
options?: {
|
|
199
|
-
maxChars?: number;
|
|
200
|
-
totalMaxChars?: number;
|
|
201
|
-
},
|
|
202
|
-
): ContextFile[] {
|
|
203
|
-
const maxChars = options?.maxChars ?? DEFAULT_MAX_CHARS;
|
|
204
|
-
const totalMaxChars = options?.totalMaxChars ?? DEFAULT_TOTAL_MAX_CHARS;
|
|
205
|
-
|
|
206
|
-
const contextFiles: ContextFile[] = [];
|
|
207
|
-
let totalChars = 0;
|
|
208
|
-
|
|
209
|
-
for (const file of bootstrapFiles) {
|
|
210
|
-
if (file.missing || !file.content) continue;
|
|
211
|
-
|
|
212
|
-
let content = file.content.trim();
|
|
213
|
-
if (!content) continue;
|
|
214
|
-
|
|
215
|
-
// 单文件裁剪
|
|
216
|
-
if (content.length > maxChars) {
|
|
217
|
-
content = content.slice(0, maxChars) + '\n...(truncated)';
|
|
218
|
-
logger.warn(`Bootstrap file ${file.name} exceeds ${maxChars} chars, truncated`);
|
|
219
|
-
}
|
|
220
|
-
|
|
221
|
-
// 总量限制
|
|
222
|
-
if (totalChars + content.length > totalMaxChars) {
|
|
223
|
-
logger.warn(`Bootstrap total exceeds ${totalMaxChars} chars, skipping ${file.name}`);
|
|
224
|
-
break;
|
|
225
|
-
}
|
|
226
|
-
|
|
227
|
-
contextFiles.push({ path: file.name, content });
|
|
228
|
-
totalChars += content.length;
|
|
229
|
-
}
|
|
230
|
-
|
|
231
|
-
return contextFiles;
|
|
232
|
-
}
|
|
233
|
-
|
|
234
|
-
/**
|
|
235
|
-
* 加载 SOUL.md 人格定义
|
|
236
|
-
*/
|
|
237
|
-
export async function loadSoulPersona(workspaceDir?: string): Promise<string | null> {
|
|
238
|
-
const files = await loadBootstrapFiles(workspaceDir);
|
|
239
|
-
const soulFile = files.find(f => f.name === 'SOUL.md' && !f.missing);
|
|
240
|
-
return soulFile?.content?.trim() || null;
|
|
241
|
-
}
|
|
242
|
-
|
|
243
|
-
/**
|
|
244
|
-
* 加载 TOOLS.md 工具使用指引
|
|
245
|
-
*/
|
|
246
|
-
export async function loadToolsGuide(workspaceDir?: string): Promise<string | null> {
|
|
247
|
-
const files = await loadBootstrapFiles(workspaceDir);
|
|
248
|
-
const toolsFile = files.find(f => f.name === 'TOOLS.md' && !f.missing);
|
|
249
|
-
return toolsFile?.content?.trim() || null;
|
|
250
|
-
}
|
|
251
|
-
|
|
252
|
-
/**
|
|
253
|
-
* 加载 AGENTS.md 持久化记忆
|
|
254
|
-
*/
|
|
255
|
-
export async function loadAgentsMemory(workspaceDir?: string): Promise<string | null> {
|
|
256
|
-
const files = await loadBootstrapFiles(workspaceDir);
|
|
257
|
-
const agentsFile = files.find(f => f.name === 'AGENTS.md' && !f.missing);
|
|
258
|
-
return agentsFile?.content?.trim() || null;
|
|
259
|
-
}
|
|
260
|
-
|
|
261
|
-
// ============================================================================
|
|
262
|
-
// System Prompt 构建帮助函数
|
|
263
|
-
// ============================================================================
|
|
264
|
-
|
|
265
|
-
/**
|
|
266
|
-
* 构建引导文件上下文段(注入到 system prompt 末尾)
|
|
267
|
-
*
|
|
268
|
-
* 格式与 OpenClaw 一致:
|
|
269
|
-
* ```
|
|
270
|
-
* # Project Context
|
|
271
|
-
*
|
|
272
|
-
* The following project context files have been loaded:
|
|
273
|
-
* If SOUL.md is present, embody its persona and tone.
|
|
274
|
-
*
|
|
275
|
-
* ## SOUL.md
|
|
276
|
-
*
|
|
277
|
-
* <content>
|
|
278
|
-
*
|
|
279
|
-
* ## TOOLS.md
|
|
280
|
-
*
|
|
281
|
-
* <content>
|
|
282
|
-
* ```
|
|
283
|
-
*/
|
|
284
|
-
export function buildBootstrapContextSection(contextFiles: ContextFile[]): string {
|
|
285
|
-
if (contextFiles.length === 0) return '';
|
|
286
|
-
|
|
287
|
-
const hasSoul = contextFiles.some(f =>
|
|
288
|
-
f.path.toLowerCase().endsWith('soul.md'),
|
|
289
|
-
);
|
|
290
|
-
|
|
291
|
-
const lines: string[] = [
|
|
292
|
-
'# Project Context',
|
|
293
|
-
'',
|
|
294
|
-
'The following project context files have been loaded:',
|
|
295
|
-
];
|
|
296
|
-
|
|
297
|
-
if (hasSoul) {
|
|
298
|
-
lines.push(
|
|
299
|
-
'If SOUL.md is present, embody its persona and tone. Avoid generic responses.',
|
|
300
|
-
);
|
|
301
|
-
}
|
|
302
|
-
lines.push('');
|
|
303
|
-
|
|
304
|
-
for (const file of contextFiles) {
|
|
305
|
-
lines.push(`## ${file.path}`, '', file.content, '');
|
|
306
|
-
}
|
|
307
|
-
|
|
308
|
-
return lines.join('\n');
|
|
309
|
-
}
|