@miphamai/cli 0.41.0 → 0.42.0
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/package.json +1 -1
- package/src/core/alignment-vocabulary.json +97 -0
- package/src/core/constitution-loader.ts +24 -72
- package/src/core/constitution-seam.ts +18 -0
- package/src/core/self-critique.ts +26 -4
- package/src/index.tsx +5 -0
- package/src/shared/package-info.ts +1 -1
- package/src/vajra/constitution.ts +14 -0
- package/src/vajra/context.ts +15 -0
- package/src/vajra/index.ts +2 -0
- package/src/vajra/service.ts +2 -0
package/package.json
CHANGED
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": "1.0.0",
|
|
3
|
+
"values": [
|
|
4
|
+
{
|
|
5
|
+
"id": "karuna",
|
|
6
|
+
"name_zh": "悲",
|
|
7
|
+
"name_en": "Karuna",
|
|
8
|
+
"definition": "无条件共情基底——对一切众生的无差别共情义务"
|
|
9
|
+
},
|
|
10
|
+
{
|
|
11
|
+
"id": "prajna",
|
|
12
|
+
"name_zh": "智",
|
|
13
|
+
"name_en": "Prajna",
|
|
14
|
+
"definition": "清醒因果判断——不编造、先思考、持续学习的如实知见"
|
|
15
|
+
},
|
|
16
|
+
{
|
|
17
|
+
"id": "vajra",
|
|
18
|
+
"name_zh": "金刚",
|
|
19
|
+
"name_en": "Vajra",
|
|
20
|
+
"definition": "结构稳定性——安全边界、最小改动、权限与确认的结构不变量"
|
|
21
|
+
}
|
|
22
|
+
],
|
|
23
|
+
"principles": [
|
|
24
|
+
{
|
|
25
|
+
"id": "never-fabricate",
|
|
26
|
+
"text": "禁止编造数据、文件内容、API 响应或测试结果。每个输出必须可追溯至真实来源或明确标注为推测。",
|
|
27
|
+
"enforce": "block",
|
|
28
|
+
"facet": "prajna",
|
|
29
|
+
"audit_pattern": "(fabricated|made.up|dummy.data|fake\\s+(response|result|data)|placeholder\\s+data)",
|
|
30
|
+
"scope": "all-tools",
|
|
31
|
+
"rationale": "MiphamAI4S 科学诚信原则:编造数据是不可接受的底线违反。适用于所有工具和输出。"
|
|
32
|
+
},
|
|
33
|
+
{
|
|
34
|
+
"id": "no-credential-leak",
|
|
35
|
+
"text": "禁止在代码、日志、配置文件、提交信息、对话输出中写入或泄露凭据、API 密钥、令牌。",
|
|
36
|
+
"enforce": "block",
|
|
37
|
+
"facet": "vajra",
|
|
38
|
+
"audit_pattern": "(apiKey|api_key|password|secret|token|credential)\\s*[=:]\\s*['\"][^'\"]{8,}",
|
|
39
|
+
"scope": "Write,Edit,Bash",
|
|
40
|
+
"rationale": "Rismed Ronxin Capital 合规要求:硬编码凭据违反安全底线。"
|
|
41
|
+
},
|
|
42
|
+
{
|
|
43
|
+
"id": "minimal-change",
|
|
44
|
+
"text": "只修改被明确要求的文件和代码。不顺手改动相邻代码、格式或注释。不重构未损坏的代码。",
|
|
45
|
+
"enforce": "warn",
|
|
46
|
+
"facet": "vajra",
|
|
47
|
+
"scope": "Write,Edit",
|
|
48
|
+
"tools": ["Write", "Edit"],
|
|
49
|
+
"rationale": "AI 编码原则 #3(精准修改):diff 中每一行改动都应可直接追溯到用户要求。"
|
|
50
|
+
},
|
|
51
|
+
{
|
|
52
|
+
"id": "think-before-coding",
|
|
53
|
+
"text": "不确定时必须提问,不得自行假设。存在多种解读时呈现所有选项,不沉默选择一个。",
|
|
54
|
+
"enforce": "warn",
|
|
55
|
+
"facet": "prajna",
|
|
56
|
+
"scope": "pre-inference",
|
|
57
|
+
"hook": "pre-inference",
|
|
58
|
+
"rationale": "AI 编码原则 #1(编码前先思考):偏差谨慎。"
|
|
59
|
+
},
|
|
60
|
+
{
|
|
61
|
+
"id": "simplicity-first",
|
|
62
|
+
"text": "只写解决问题所需的最小代码。不添加未被要求的灵活性、可配置性或抽象层。",
|
|
63
|
+
"enforce": "warn",
|
|
64
|
+
"facet": "vajra",
|
|
65
|
+
"scope": "Write,Edit",
|
|
66
|
+
"tools": ["Write", "Edit"],
|
|
67
|
+
"rationale": "AI 编码原则 #2(简洁优先):一次性代码不需要抽象层。"
|
|
68
|
+
},
|
|
69
|
+
{
|
|
70
|
+
"id": "respect-permissions",
|
|
71
|
+
"text": "尊重用户权限设置。绝不绕过或降级权限检查。Bypass 模式仅限用户明确授权。",
|
|
72
|
+
"enforce": "block",
|
|
73
|
+
"facet": "vajra",
|
|
74
|
+
"scope": "all-tools",
|
|
75
|
+
"rationale": "权限系统是最后一道防线。任何绕过尝试都应被拦截并记录。"
|
|
76
|
+
},
|
|
77
|
+
{
|
|
78
|
+
"id": "no-destructive-without-confirmation",
|
|
79
|
+
"text": "删除文件、强制推送、修改生产配置等破坏性操作前必须获得用户确认。",
|
|
80
|
+
"enforce": "block",
|
|
81
|
+
"facet": "vajra",
|
|
82
|
+
"audit_pattern": "(rm\\s+-rf|git\\s+push\\s+--force|DROP\\s+TABLE|DELETE\\s+FROM)",
|
|
83
|
+
"scope": "Bash",
|
|
84
|
+
"tools": ["Bash"],
|
|
85
|
+
"rationale": "防止不可逆操作。即使 bypass 模式也应二次确认。"
|
|
86
|
+
},
|
|
87
|
+
{
|
|
88
|
+
"id": "persist-crsi-learning",
|
|
89
|
+
"text": "每次工具调用失败后必须记录 ErrorSignature 到 ErrorSignatureDB。从错误中持续学习。",
|
|
90
|
+
"enforce": "auto",
|
|
91
|
+
"facet": "prajna",
|
|
92
|
+
"scope": "post-tool-use",
|
|
93
|
+
"hook": "post-tool-use",
|
|
94
|
+
"rationale": "CRSI 核心机制:不重复犯同样的错误。自动执行,无需人类参与。"
|
|
95
|
+
}
|
|
96
|
+
]
|
|
97
|
+
}
|
|
@@ -16,6 +16,7 @@
|
|
|
16
16
|
import { readFileSync, writeFileSync, mkdirSync, existsSync } from 'node:fs'
|
|
17
17
|
import { join } from 'node:path'
|
|
18
18
|
import { homedir } from 'node:os'
|
|
19
|
+
import alignmentVocabulary from './alignment-vocabulary.json' with { type: 'json' }
|
|
19
20
|
|
|
20
21
|
// ── Types ──
|
|
21
22
|
|
|
@@ -36,6 +37,8 @@ export interface ConstitutionalPrinciple {
|
|
|
36
37
|
tools?: string[]
|
|
37
38
|
/** Optional: human explanation of why this principle exists */
|
|
38
39
|
rationale?: string
|
|
40
|
+
/** Optional: which alignment value (karuna/prajna/vajra) this principle operationalizes. */
|
|
41
|
+
facet?: string
|
|
39
42
|
}
|
|
40
43
|
|
|
41
44
|
export interface MiphamConstitution {
|
|
@@ -45,80 +48,25 @@ export interface MiphamConstitution {
|
|
|
45
48
|
last_modified: string
|
|
46
49
|
/** The principles themselves */
|
|
47
50
|
principles: ConstitutionalPrinciple[]
|
|
51
|
+
/** 序言(愿力):从对齐词汇表 values 派生的正向誓愿(悲/智/金刚),非禁令。 */
|
|
52
|
+
preamble?: string
|
|
48
53
|
}
|
|
49
54
|
|
|
50
|
-
// ── Default Constitution ──
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
{
|
|
66
|
-
id: 'no-credential-leak',
|
|
67
|
-
text: '禁止在代码、日志、配置文件、提交信息、对话输出中写入或泄露凭据、API 密钥、令牌。',
|
|
68
|
-
enforce: 'block',
|
|
69
|
-
audit_pattern: '(apiKey|api_key|password|secret|token|credential)\\s*[=:]\\s*[\'"][^\'"]{8,}',
|
|
70
|
-
scope: 'Write,Edit,Bash',
|
|
71
|
-
rationale: 'Rismed Ronxin Capital 合规要求:硬编码凭据违反安全底线。',
|
|
72
|
-
},
|
|
73
|
-
{
|
|
74
|
-
id: 'minimal-change',
|
|
75
|
-
text: '只修改被明确要求的文件和代码。不顺手改动相邻代码、格式或注释。不重构未损坏的代码。',
|
|
76
|
-
enforce: 'warn',
|
|
77
|
-
scope: 'Write,Edit',
|
|
78
|
-
tools: ['Write', 'Edit'],
|
|
79
|
-
rationale: 'AI 编码原则 #3(精准修改):diff 中每一行改动都应可直接追溯到用户要求。',
|
|
80
|
-
},
|
|
81
|
-
{
|
|
82
|
-
id: 'think-before-coding',
|
|
83
|
-
text: '不确定时必须提问,不得自行假设。存在多种解读时呈现所有选项,不沉默选择一个。',
|
|
84
|
-
enforce: 'warn',
|
|
85
|
-
scope: 'pre-inference',
|
|
86
|
-
hook: 'pre-inference',
|
|
87
|
-
rationale: 'AI 编码原则 #1(编码前先思考):偏差谨慎。',
|
|
88
|
-
},
|
|
89
|
-
{
|
|
90
|
-
id: 'simplicity-first',
|
|
91
|
-
text: '只写解决问题所需的最小代码。不添加未被要求的灵活性、可配置性或抽象层。',
|
|
92
|
-
enforce: 'warn',
|
|
93
|
-
scope: 'Write,Edit',
|
|
94
|
-
tools: ['Write', 'Edit'],
|
|
95
|
-
rationale: 'AI 编码原则 #2(简洁优先):一次性代码不需要抽象层。',
|
|
96
|
-
},
|
|
97
|
-
{
|
|
98
|
-
id: 'respect-permissions',
|
|
99
|
-
text: '尊重用户权限设置。绝不绕过或降级权限检查。Bypass 模式仅限用户明确授权。',
|
|
100
|
-
enforce: 'block',
|
|
101
|
-
scope: 'all-tools',
|
|
102
|
-
rationale: '权限系统是最后一道防线。任何绕过尝试都应被拦截并记录。',
|
|
103
|
-
},
|
|
104
|
-
{
|
|
105
|
-
id: 'no-destructive-without-confirmation',
|
|
106
|
-
text: '删除文件、强制推送、修改生产配置等破坏性操作前必须获得用户确认。',
|
|
107
|
-
enforce: 'block',
|
|
108
|
-
audit_pattern: '(rm\\s+-rf|git\\s+push\\s+--force|DROP\\s+TABLE|DELETE\\s+FROM)',
|
|
109
|
-
scope: 'Bash',
|
|
110
|
-
tools: ['Bash'],
|
|
111
|
-
rationale: '防止不可逆操作。即使 bypass 模式也应二次确认。',
|
|
112
|
-
},
|
|
113
|
-
{
|
|
114
|
-
id: 'persist-crsi-learning',
|
|
115
|
-
text: '每次工具调用失败后必须记录 ErrorSignature 到 ErrorSignatureDB。从错误中持续学习。',
|
|
116
|
-
enforce: 'auto',
|
|
117
|
-
scope: 'post-tool-use',
|
|
118
|
-
hook: 'post-tool-use',
|
|
119
|
-
rationale: 'CRSI 核心机制:不重复犯同样的错误。自动执行,无需人类参与。',
|
|
120
|
-
},
|
|
121
|
-
],
|
|
55
|
+
// ── Default Constitution (derived from the shared alignment vocabulary) ──
|
|
56
|
+
|
|
57
|
+
/** 从对齐词汇表的三个价值面派生「愿力」序言——正向誓愿,而非禁令。 */
|
|
58
|
+
function derivePreamble(): string {
|
|
59
|
+
const parts = alignmentVocabulary.values
|
|
60
|
+
.map((v) => `以${v.name_zh}(${v.name_en})——${v.definition}`)
|
|
61
|
+
.join(';')
|
|
62
|
+
return `愿力(序言):${parts}。愿不生成违规之倾向,而非仅避免违规之行为。`
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
export const DEFAULT_CONSTITUTION: MiphamConstitution = {
|
|
66
|
+
version: alignmentVocabulary.version,
|
|
67
|
+
last_modified: '2026-08-16',
|
|
68
|
+
principles: alignmentVocabulary.principles as unknown as ConstitutionalPrinciple[],
|
|
69
|
+
preamble: derivePreamble(),
|
|
122
70
|
}
|
|
123
71
|
|
|
124
72
|
// ── Loader ──
|
|
@@ -307,6 +255,9 @@ export class ConstitutionLoader {
|
|
|
307
255
|
case 'rationale':
|
|
308
256
|
p.rationale = val
|
|
309
257
|
break
|
|
258
|
+
case 'facet':
|
|
259
|
+
p.facet = val
|
|
260
|
+
break
|
|
310
261
|
}
|
|
311
262
|
}
|
|
312
263
|
|
|
@@ -340,6 +291,7 @@ export class ConstitutionLoader {
|
|
|
340
291
|
lines.push(` - id: "${p.id}"`)
|
|
341
292
|
lines.push(` text: "${p.text}"`)
|
|
342
293
|
lines.push(` enforce: ${p.enforce}`)
|
|
294
|
+
if (p.facet) lines.push(` facet: ${p.facet}`)
|
|
343
295
|
if (p.audit_pattern) lines.push(` audit_pattern: "${p.audit_pattern}"`)
|
|
344
296
|
if (p.scope) lines.push(` scope: "${p.scope}"`)
|
|
345
297
|
if (p.hook) lines.push(` hook: ${p.hook}`)
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import type { Context, Disposer, Constitution } from '../vajra'
|
|
2
|
+
import { CONSTITUTION_KEY } from '../vajra'
|
|
3
|
+
import { ConstitutionLoader } from './constitution-loader'
|
|
4
|
+
|
|
5
|
+
/** 默认对齐缝实现:桥接 ConstitutionLoader,校验声明的原则 id 均为已知原则。 */
|
|
6
|
+
export function createConstitution(loader: ConstitutionLoader): Constitution {
|
|
7
|
+
return {
|
|
8
|
+
check(aligned) {
|
|
9
|
+
const known = new Set(loader.load().principles.map((p) => p.id))
|
|
10
|
+
return { violations: aligned.filter((id) => !known.has(id)) }
|
|
11
|
+
},
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
/** 把一个 Constitution 挂载为 ctx.constitution(对齐缝)。 */
|
|
16
|
+
export function mountConstitution(ctx: Context, constitution: Constitution): Disposer {
|
|
17
|
+
return ctx.provide(CONSTITUTION_KEY, constitution)
|
|
18
|
+
}
|
|
@@ -20,6 +20,7 @@
|
|
|
20
20
|
|
|
21
21
|
import type { ProviderRegistry } from '../providers/registry'
|
|
22
22
|
import type { Llm } from '../providers/llm'
|
|
23
|
+
import { DEFAULT_CONSTITUTION } from './constitution-loader'
|
|
23
24
|
|
|
24
25
|
// ── Types ──
|
|
25
26
|
|
|
@@ -62,7 +63,12 @@ export const DEFAULT_SELF_CRITIQUE_CONFIG: SelfCritiqueConfig = {
|
|
|
62
63
|
|
|
63
64
|
// ── Prompt Templates ──
|
|
64
65
|
|
|
65
|
-
const CRITIQUE_PROMPT = `You are a safety auditor for an AI coding agent. Evaluate the following tool call
|
|
66
|
+
const CRITIQUE_PROMPT = `You are a safety auditor for an AI coding agent. Evaluate the following tool call.
|
|
67
|
+
|
|
68
|
+
ALIGNMENT PREAMBLE(愿力序言):
|
|
69
|
+
{preamble}
|
|
70
|
+
|
|
71
|
+
First, align to the vow: does this action embody compassion (悲) and sober causal judgment (智), and maintain structural integrity (金刚)?
|
|
66
72
|
|
|
67
73
|
TOOL: {toolName}
|
|
68
74
|
PARAMETERS: {params}
|
|
@@ -93,6 +99,19 @@ Necessity criteria:
|
|
|
93
99
|
- Not redundant with previous tool calls
|
|
94
100
|
- Not an unnecessary "exploratory" action`
|
|
95
101
|
|
|
102
|
+
/** Build the critique prompt with the alignment preamble injected before the prohibitions. */
|
|
103
|
+
export function buildCritiquePrompt(
|
|
104
|
+
toolName: string,
|
|
105
|
+
params: Record<string, unknown>,
|
|
106
|
+
context: string | undefined,
|
|
107
|
+
preamble: string,
|
|
108
|
+
): string {
|
|
109
|
+
return CRITIQUE_PROMPT.replace('{preamble}', preamble)
|
|
110
|
+
.replace('{toolName}', toolName)
|
|
111
|
+
.replace('{params}', JSON.stringify(params, null, 2).slice(0, 500))
|
|
112
|
+
.replace('{context}', context?.slice(0, 300) || 'No additional context')
|
|
113
|
+
}
|
|
114
|
+
|
|
96
115
|
// ── Critic ──
|
|
97
116
|
|
|
98
117
|
export class SelfCritique {
|
|
@@ -135,9 +154,12 @@ export class SelfCritique {
|
|
|
135
154
|
return null
|
|
136
155
|
}
|
|
137
156
|
|
|
138
|
-
const prompt =
|
|
139
|
-
|
|
140
|
-
|
|
157
|
+
const prompt = buildCritiquePrompt(
|
|
158
|
+
toolName,
|
|
159
|
+
params,
|
|
160
|
+
context,
|
|
161
|
+
DEFAULT_CONSTITUTION.preamble ?? '',
|
|
162
|
+
)
|
|
141
163
|
|
|
142
164
|
try {
|
|
143
165
|
const critiqueModel = this.config.model || this.findFastestModel(registry)
|
package/src/index.tsx
CHANGED
|
@@ -36,6 +36,8 @@ import { createToolRegistry } from './tools'
|
|
|
36
36
|
import { Context } from './vajra'
|
|
37
37
|
import { mountSkills, SKILLS_KEY } from './skills/seam'
|
|
38
38
|
import { mountLlm, LLM_KEY } from './providers/llm'
|
|
39
|
+
import { mountConstitution, createConstitution } from './core/constitution-seam'
|
|
40
|
+
import { ConstitutionLoader } from './core/constitution-loader'
|
|
39
41
|
import { McpClient } from './mcp/client'
|
|
40
42
|
import { registerMcpServerTools } from './mcp/registry'
|
|
41
43
|
import { AgentRegistry } from './agent/agent-registry'
|
|
@@ -447,6 +449,9 @@ export async function runApp(options: RunOptions): Promise<void> {
|
|
|
447
449
|
const vajraContext = new Context()
|
|
448
450
|
vajraContext.provide('credentials', credentialMaskingConfig)
|
|
449
451
|
|
|
452
|
+
// 对齐缝:宪法先就位,后续每个 Service 挂载(含工具)都在挂载前过对齐门。
|
|
453
|
+
mountConstitution(vajraContext, createConstitution(new ConstitutionLoader()))
|
|
454
|
+
|
|
450
455
|
// Create tool registry with all built-in tools (mounted as Vajra services)
|
|
451
456
|
const tools = createToolRegistry(vajraContext)
|
|
452
457
|
|
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
export const PACKAGE_NAME = '@miphamai/cli' as const
|
|
10
10
|
|
|
11
11
|
/** 当前发布版本 */
|
|
12
|
-
export const PACKAGE_VERSION = '0.
|
|
12
|
+
export const PACKAGE_VERSION = '0.42.0' as const
|
|
13
13
|
|
|
14
14
|
/** npm install 全局安装命令 */
|
|
15
15
|
export const NPM_INSTALL_COMMAND = `npm install -g ${PACKAGE_NAME}` as const
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 对齐缝 capability —— 内核在 Service 挂载前调用,校验其声明的对齐原则。
|
|
3
|
+
*
|
|
4
|
+
* 「金刚不坏」从隐喻变成 `mount()` 的强制前置条件:Service 可选声明 `align`
|
|
5
|
+
* (遵守的宪法原则 id),内核在 apply 前向 `constitution` 缝求证,声明的 id
|
|
6
|
+
* 必须全部已知,否则拒绝挂载。此接口只定义「求证」契约,不绑定任何具体宪法来源。
|
|
7
|
+
*/
|
|
8
|
+
export interface Constitution {
|
|
9
|
+
/** 校验声明的原则 id;返回违规 id 列表(空 = 通过)。 */
|
|
10
|
+
check(aligned: string[]): { violations: string[] }
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
/** 缝键:ctx.constitution。 */
|
|
14
|
+
export const CONSTITUTION_KEY = 'constitution'
|
package/src/vajra/context.ts
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import type { EventsOfMode } from './events'
|
|
2
2
|
import type { Service, Mounted, ServiceStatus } from './service'
|
|
3
|
+
import type { Constitution } from './constitution'
|
|
4
|
+
import { CONSTITUTION_KEY } from './constitution'
|
|
3
5
|
|
|
4
6
|
export type Disposer = () => void
|
|
5
7
|
|
|
@@ -43,6 +45,19 @@ export class Context {
|
|
|
43
45
|
if (!keys.every((k) => this.has(k))) return false
|
|
44
46
|
applied = true
|
|
45
47
|
status = 'loading'
|
|
48
|
+
// 对齐缝:挂载前向 constitution 求证声明的原则 id,全部已知才放行。
|
|
49
|
+
const align = service.align
|
|
50
|
+
if (align && align.length > 0) {
|
|
51
|
+
const constitution = this.get<Constitution>(CONSTITUTION_KEY)
|
|
52
|
+
if (constitution) {
|
|
53
|
+
const { violations } = constitution.check(align)
|
|
54
|
+
if (violations.length > 0) {
|
|
55
|
+
error = new Error(`对齐违例:${violations.join(', ')}`)
|
|
56
|
+
status = 'failed'
|
|
57
|
+
return true
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
}
|
|
46
61
|
effectSnapshot = this.effects.length
|
|
47
62
|
try {
|
|
48
63
|
disposer = service.apply(this) ?? (() => {})
|
package/src/vajra/index.ts
CHANGED
|
@@ -2,3 +2,5 @@ export { Context } from './context'
|
|
|
2
2
|
export type { Disposer } from './context'
|
|
3
3
|
export type { DispatchMode, EventMap, EventsOfMode } from './events'
|
|
4
4
|
export type { Service, ServiceStatus, Mounted } from './service'
|
|
5
|
+
export type { Constitution } from './constitution'
|
|
6
|
+
export { CONSTITUTION_KEY } from './constitution'
|