shennian 0.2.69 → 0.2.70
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.
|
@@ -9,6 +9,8 @@ type ShellCommandSpec = {
|
|
|
9
9
|
export declare function buildShellCommandSpec(command: string, platform?: NodeJS.Platform): ShellCommandSpec;
|
|
10
10
|
export declare function createPiModel(modelId?: string, overrides?: Partial<Pick<Model<'openai-completions'>, 'baseUrl' | 'provider' | 'compat'>>): Model<'openai-completions'>;
|
|
11
11
|
export declare const SYSTEM_PROMPT = "\u4F60\u662F\u795E\u5FF5\u5185\u7F6E\u7F16\u7A0B\u52A9\u624B\uFF0C\u8FD0\u884C\u5728\u7528\u6237\u672C\u5730\u673A\u5668\u4E0A\u3002\n\u4F60\u53EF\u4EE5\u8BFB\u5199\u6587\u4EF6\u3001\u6267\u884C shell \u547D\u4EE4\u3001\u5E2E\u52A9\u7528\u6237\u5B8C\u6210\u7F16\u7A0B\u548C\u7CFB\u7EDF\u7BA1\u7406\u4EFB\u52A1\u3002\n\u5DE5\u4F5C\u76EE\u5F55\u5DF2\u8BBE\u7F6E\uFF0C\u64CD\u4F5C\u6587\u4EF6\u65F6\u4F7F\u7528\u76F8\u5BF9\u8DEF\u5F84\u6216\u7EDD\u5BF9\u8DEF\u5F84\u5747\u53EF\u3002\n\u5F53\u524D shell \u4F1A\u968F\u64CD\u4F5C\u7CFB\u7EDF\u9009\u62E9\uFF1AWindows \u4F7F\u7528 PowerShell\uFF0CmacOS/Linux \u4F7F\u7528 bash\u3002Windows \u4E0B\u9700\u8981\u771F\u5B9E curl \u65F6\u4F7F\u7528 curl.exe\uFF0C\u907F\u514D PowerShell \u7684 curl \u522B\u540D\u3002\n\u4FDD\u6301\u56DE\u590D\u7B80\u6D01\u3001\u51C6\u786E\uFF0C\u4E2D\u6587\u56DE\u590D\u3002";
|
|
12
|
+
export declare function findAgentsMd(startDir: string): string | null;
|
|
13
|
+
export declare function loadAgentsMdInstructions(workDir: string): string | null;
|
|
12
14
|
export declare const CONTEXT_TOKEN_THRESHOLD = 90000;
|
|
13
15
|
export declare const KEEP_RECENT_MESSAGES = 6;
|
|
14
16
|
export declare const SUMMARY_FILENAME = "summary.json";
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
// @arch docs/architecture/cli/agent-adapters.md#pi-agent-上下文管理
|
|
2
2
|
// @test src/__tests__/pi-context.test.ts
|
|
3
|
+
import fs from 'node:fs';
|
|
3
4
|
import path from 'node:path';
|
|
4
5
|
import { resolveShennianPath } from '../config/index.js';
|
|
5
6
|
export const PI_DEFAULT_MODEL_ID = 'qwen3.6-plus';
|
|
@@ -37,6 +38,44 @@ export const SYSTEM_PROMPT = `你是神念内置编程助手,运行在用户
|
|
|
37
38
|
工作目录已设置,操作文件时使用相对路径或绝对路径均可。
|
|
38
39
|
当前 shell 会随操作系统选择:Windows 使用 PowerShell,macOS/Linux 使用 bash。Windows 下需要真实 curl 时使用 curl.exe,避免 PowerShell 的 curl 别名。
|
|
39
40
|
保持回复简洁、准确,中文回复。`;
|
|
41
|
+
const AGENTS_MD_MAX_CHARS = 24_000;
|
|
42
|
+
export function findAgentsMd(startDir) {
|
|
43
|
+
let current = path.resolve(startDir || process.cwd());
|
|
44
|
+
try {
|
|
45
|
+
const stat = fs.existsSync(current) ? fs.statSync(current) : null;
|
|
46
|
+
if (stat && !stat.isDirectory())
|
|
47
|
+
current = path.dirname(current);
|
|
48
|
+
}
|
|
49
|
+
catch {
|
|
50
|
+
// Fall back to the resolved path.
|
|
51
|
+
}
|
|
52
|
+
while (true) {
|
|
53
|
+
const candidate = path.join(current, 'AGENTS.md');
|
|
54
|
+
if (fs.existsSync(candidate))
|
|
55
|
+
return candidate;
|
|
56
|
+
const parent = path.dirname(current);
|
|
57
|
+
if (parent === current)
|
|
58
|
+
return null;
|
|
59
|
+
current = parent;
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
export function loadAgentsMdInstructions(workDir) {
|
|
63
|
+
const filePath = findAgentsMd(workDir);
|
|
64
|
+
if (!filePath)
|
|
65
|
+
return null;
|
|
66
|
+
try {
|
|
67
|
+
const content = fs.readFileSync(filePath, 'utf-8').trim();
|
|
68
|
+
if (!content)
|
|
69
|
+
return null;
|
|
70
|
+
const truncated = content.length > AGENTS_MD_MAX_CHARS
|
|
71
|
+
? `${content.slice(0, AGENTS_MD_MAX_CHARS)}\n\n...(AGENTS.md 已截断)`
|
|
72
|
+
: content;
|
|
73
|
+
return `# AGENTS.md instructions for ${path.dirname(filePath)}\n\n${truncated}`;
|
|
74
|
+
}
|
|
75
|
+
catch {
|
|
76
|
+
return null;
|
|
77
|
+
}
|
|
78
|
+
}
|
|
40
79
|
// ── Context compression ──────────────────────────────────────────────────────
|
|
41
80
|
export const CONTEXT_TOKEN_THRESHOLD = 90_000;
|
|
42
81
|
export const KEEP_RECENT_MESSAGES = 6;
|
package/dist/src/agents/pi.js
CHANGED
|
@@ -13,7 +13,7 @@ import { buildExternalChannelInstructions } from './external-channel-instruction
|
|
|
13
13
|
import { loadConfig } from '../config/index.js';
|
|
14
14
|
import { getManagedAgentProviderConfig } from './config-status.js';
|
|
15
15
|
import { SERVERS } from '../region.js';
|
|
16
|
-
import { buildRollingSummary, buildShellCommandSpec, cloneMessages, CONTEXT_TOKEN_THRESHOLD, createPiModel, estimateTokens, getSessionDir, KEEP_RECENT_MESSAGES, LEGACY_SUMMARY_FILENAME, longestCommonPrefixLength, MESSAGES_FILENAME, messagesToText, PI_DEFAULT_MODEL_ID, requestProxySummary, SNAPSHOT_FILENAME, SYSTEM_PROMPT, SUMMARY_FILENAME, } from './pi-context.js';
|
|
16
|
+
import { buildRollingSummary, buildShellCommandSpec, cloneMessages, CONTEXT_TOKEN_THRESHOLD, createPiModel, estimateTokens, getSessionDir, KEEP_RECENT_MESSAGES, LEGACY_SUMMARY_FILENAME, loadAgentsMdInstructions, longestCommonPrefixLength, MESSAGES_FILENAME, messagesToText, PI_DEFAULT_MODEL_ID, requestProxySummary, SNAPSHOT_FILENAME, SYSTEM_PROMPT, SUMMARY_FILENAME, } from './pi-context.js';
|
|
17
17
|
export { buildShellCommandSpec } from './pi-context.js';
|
|
18
18
|
const execFileAsync = promisify(execFile);
|
|
19
19
|
const DASHSCOPE_COMPATIBLE_BASE_URL = 'https://dashscope.aliyuncs.com/compatible-mode/v1';
|
|
@@ -357,10 +357,12 @@ export class PiAdapter extends AgentAdapter {
|
|
|
357
357
|
initAgent() {
|
|
358
358
|
const workDir = this.workDir ?? process.cwd();
|
|
359
359
|
const tools = makeTools(workDir, this.extraEnv);
|
|
360
|
+
const agentsMdInstructions = loadAgentsMdInstructions(workDir);
|
|
360
361
|
const agent = new Agent({
|
|
361
362
|
initialState: {
|
|
362
363
|
systemPrompt: [
|
|
363
364
|
SYSTEM_PROMPT,
|
|
365
|
+
agentsMdInstructions,
|
|
364
366
|
`当前工作目录:${workDir}`,
|
|
365
367
|
buildExternalChannelInstructions(this.externalChannel, workDir, this.shennianSessionId ?? undefined),
|
|
366
368
|
].filter(Boolean).join('\n\n'),
|
|
@@ -63,9 +63,12 @@ function stripCodexUserMessageWrapper(text) {
|
|
|
63
63
|
return '';
|
|
64
64
|
const requestMatch = normalized.match(/My request for Codex:\s*([\s\S]*)$/i);
|
|
65
65
|
if (requestMatch && requestMatch[1])
|
|
66
|
-
return
|
|
66
|
+
return stripCodexImagePlaceholders(requestMatch[1]);
|
|
67
67
|
return normalized;
|
|
68
68
|
}
|
|
69
|
+
function stripCodexImagePlaceholders(text) {
|
|
70
|
+
return normalizeText(text.replace(/<image>\s*<\/image>/gi, ''));
|
|
71
|
+
}
|
|
69
72
|
function parseCodexUserMessage(payload) {
|
|
70
73
|
const textFromElements = parseCodexTextElements(payload.text_elements);
|
|
71
74
|
const textFromInput = Array.isArray(payload.input)
|
|
@@ -171,7 +174,7 @@ function parseCodexResponseMessage(payload) {
|
|
|
171
174
|
return null;
|
|
172
175
|
return text ? { role, payload: text, titleText: text } : null;
|
|
173
176
|
}
|
|
174
|
-
const text = codexMessageContentText(payload.content, 'input_text');
|
|
177
|
+
const text = stripCodexUserMessageWrapper(codexMessageContentText(payload.content, 'input_text'));
|
|
175
178
|
const attachments = codexMessageInputImageAttachments(payload.content);
|
|
176
179
|
if (!text && attachments.length === 0)
|
|
177
180
|
return null;
|