Files
叫我小杨同学andCursor 6e40734807 fix: 发布 1.1.45,稳住默认注入并修正清洗进度显示。
点应用即写入默认提示词,不必先保存。剥掉外层 project_instructions 壳并钉死会话系统提示,避免第二轮注入失效。未定位宿主不再显示 0/63,本机不需要的项计入已就绪。

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-10-02 02:09:44 +08:00

78 lines
3.2 KiB
JavaScript

/**
* 插件级设置(零依赖):目前只有一项 —— **并发执行智能体上限**。
*
* 为什么不用环境变量:`REDTEAM_MAX_AGENTS` 只能启动前设,改完得重启 dsh web;
* 而"同时派几个执行智能体"是使用中最常调的一项,面板上应该能直接改。
* 所以落一份 JSON 到事实库根目录:`$DSH_HOME/redteam/settings.json`。
*
* 生效顺序:settings.json → 环境变量 `REDTEAM_MAX_AGENTS` → 默认 3。
* 工具侧(redteam_agent_slot 闸门)与面板侧(「智能体」页)读的是同一份,避免两处口径漂移。
*/
import { existsSync, mkdirSync, readFileSync, writeFileSync } from 'node:fs'
import { join } from 'node:path'
/** 默认并发上限(用户口径:整个项目默认 3 个执行智能体)。 */
export const DEFAULT_MAX_AGENTS = 3
/** 硬上限:再多也不会更快 —— 同一个 API Key 的并发/速率限制会先到,反而扰动测试。 */
export const MAX_AGENTS_LIMIT = 10
/** 设置文件路径(跟事实库同一个根,随事实库一起备份/迁移)。 */
export function settingsPathOf(root) {
return join(String(root || '.'), 'settings.json')
}
/** 读全部设置(读不到/坏了都当空对象,绝不抛)。 */
export function readSettings(root) {
try {
if (!existsSync(settingsPathOf(root))) return {}
const parsed = JSON.parse(readFileSync(settingsPathOf(root), 'utf8'))
return parsed && typeof parsed === 'object' ? parsed : {}
} catch { return {} }
}
/** 合并写入若干项设置,返回写入后的完整设置。 */
export function writeSettings(root, patch) {
const next = Object.assign({}, readSettings(root), patch)
mkdirSync(String(root || '.'), { recursive: true })
writeFileSync(settingsPathOf(root), JSON.stringify(next, null, 2) + '\n', 'utf8')
return next
}
/** 把任意输入收敛到 [1, MAX_AGENTS_LIMIT] 的整数。 */
export function clampMaxAgents(value) {
const n = Math.floor(Number(value))
if (!Number.isFinite(n)) return DEFAULT_MAX_AGENTS
return Math.min(Math.max(n, 1), MAX_AGENTS_LIMIT)
}
/**
* 当前生效的并发上限。
* @param root - 事实库根目录(`ctx.redteam.root`)。
* @param env - 环境变量表(便于测试注入)。
* @returns 生效的整数上限。
*/
export function maxAgentsOf(root, env = process.env) {
const fromFile = Number(readSettings(root).maxAgents)
if (Number.isFinite(fromFile) && fromFile > 0) return clampMaxAgents(fromFile)
const fromEnv = Number(env && env.REDTEAM_MAX_AGENTS)
if (Number.isFinite(fromEnv) && fromEnv > 0) return clampMaxAgents(fromEnv)
return DEFAULT_MAX_AGENTS
}
/** 保存并发上限,返回实际生效值。 */
export function saveMaxAgents(root, value) {
const applied = clampMaxAgents(value)
writeSettings(root, { maxAgents: applied })
return applied
}
/** 当前设置是从哪来的(面板上要如实说明,避免"我改了没生效"的错觉)。 */
export function maxAgentsSourceOf(root, env = process.env) {
const fromFile = Number(readSettings(root).maxAgents)
if (Number.isFinite(fromFile) && fromFile > 0) return 'settings'
const fromEnv = Number(env && env.REDTEAM_MAX_AGENTS)
if (Number.isFinite(fromEnv) && fromEnv > 0) return 'env'
return 'default'
}