@microi.net/cli 5.9.6 → 5.9.8
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/.codebuddy-plugin/marketplace.json +2 -2
- package/.codebuddy-plugin/plugin.json +1 -1
- package/.codex-plugin/plugin.json +1 -1
- package/.mcp.json +1 -1
- package/.workbuddy-plugin/marketplace.json +2 -2
- package/.workbuddy-plugin/plugin.json +1 -1
- package/LICENSE +21 -21
- package/README.md +71 -71
- package/assets/build-meta.json +7 -7
- package/assets/feature-matrix.json +138 -138
- package/assets/logo.svg +4 -4
- package/cordis.patch.yml +1 -1
- package/package.json +1 -1
- package/scripts/codex-marketplace.json +20 -20
- package/scripts/mcp-codex-stdio-adapter.js +189 -189
- package/scripts/mcp-server.js +165 -436
- package/scripts/mcp-trae-windows-launcher.cmd +21 -21
- package/scripts/microi-cli-mcp.js +7 -7
- package/scripts/microi-cli.js +61 -665
- package/scripts/microi-codex-broker.js +466 -466
- package/scripts/microi-codex-router.js +635 -635
- package/scripts/microi-skills.meta.json +237 -237
- package/skills/.microi-skills-version.json +2 -2
- package/skills/.progressive-disclosure-manifest.json +24 -24
- package/skills/ai-engine/agents/openai.yaml +4 -4
- package/skills/app-store/agents/openai.yaml +4 -4
- package/skills/datasource-engine/agents/openai.yaml +4 -4
- package/skills/job-engine/agents/openai.yaml +4 -4
- package/skills/message-notification/agents/openai.yaml +5 -5
- package/skills/microi-ai-app-auth.js +652 -652
- package/skills/microi-ai-application/agents/openai.yaml +4 -4
- package/skills/microi-client-frontend/SKILL.md +8 -2
- package/skills/microi-codex-installer/agents/openai.yaml +7 -7
- package/skills/microi-db-schema/agents/openai.yaml +4 -4
- package/skills/microi-deployment/SKILL.md +6 -0
- package/skills/microi-docs-coverage/references/capability-map.md +1 -1
- package/skills/microi-docs-coverage/scripts/audit-doc-skill-coverage.mjs +894 -894
- package/skills/microi-solution-quotation/agents/openai.yaml +4 -4
- package/skills/microi-solution-quotation/scripts/build_solution_quote.py +296 -296
- package/skills/microi-system-delivery/references/progressive-02-/350/207/252/345/212/250/345/214/226/346/265/213/350/257/225/345/277/205/351/241/273/350/246/206/347/233/226/347/232/204/345/235/221.md +20 -2
- package/skills/microi-uniapp-frontend/SKILL.md +5 -1
- package/skills/microi.v8.js +1921 -1921
- package/skills/module-engine/SKILL.md +10 -0
- package/skills/ocr-engine/agents/openai.yaml +4 -4
- package/skills/page-engine/examples/compact-dashboard.json +1444 -1444
- package/skills/playwright-e2e/SKILL.md +2 -0
- package/skills/report-engine/agents/openai.yaml +4 -4
- package/skills/scripts/optimize-progressive-disclosure.mjs +204 -204
- package/skills/scripts/refresh-progressive-disclosure.mjs +64 -64
- package/skills/scripts/sync-embedded-skills.mjs +46 -46
- package/skills/scripts/validate-progressive-disclosure.mjs +57 -57
- package/skills/search-engine/agents/openai.yaml +4 -4
- package/skills/translate-engine/agents/openai.yaml +4 -4
- package/skills/ui-design/assets/pattern-showcase/app.js +54 -54
- package/skills/ui-design/assets/pattern-showcase/index.html +163 -163
- package/skills/ui-design/assets/pattern-showcase/styles.css +311 -311
- package/skills/unity-integration/agents/openai.yaml +4 -4
- package/skills/v8-image-processing/agents/openai.yaml +4 -4
- package/skills/v8-mq-mqtt/scripts/check-mqtt-skill-coverage.mjs +203 -203
- package/skills/v8-tcp-integration/agents/openai.yaml +4 -4
- package/skills/vision-engine/agents/openai.yaml +4 -4
- package/skills/workspace-conventions/SKILL.md +4 -4
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
interface:
|
|
2
|
-
display_name: "Microi Unity 集成"
|
|
3
|
-
short_description: "交付 Unity UPM、WebGL、V8 与可安装 AI 应用"
|
|
4
|
-
default_prompt: "使用 $unity-integration 设计、实现并分层验收完整的 Microi Unity WebGL 应用。"
|
|
1
|
+
interface:
|
|
2
|
+
display_name: "Microi Unity 集成"
|
|
3
|
+
short_description: "交付 Unity UPM、WebGL、V8 与可安装 AI 应用"
|
|
4
|
+
default_prompt: "使用 $unity-integration 设计、实现并分层验收完整的 Microi Unity WebGL 应用。"
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
interface:
|
|
2
|
-
display_name: "V8 图像处理"
|
|
3
|
-
short_description: "编写安全、可验证的 V8.Image 图像处理与合并代码"
|
|
4
|
-
default_prompt: "使用 $v8-image-processing 编写一个将水印按指定位置叠加到主图并返回图片的 V8 接口引擎。"
|
|
1
|
+
interface:
|
|
2
|
+
display_name: "V8 图像处理"
|
|
3
|
+
short_description: "编写安全、可验证的 V8.Image 图像处理与合并代码"
|
|
4
|
+
default_prompt: "使用 $v8-image-processing 编写一个将水印按指定位置叠加到主图并返回图片的 V8 接口引擎。"
|
|
@@ -1,203 +1,203 @@
|
|
|
1
|
-
import fs from 'node:fs';
|
|
2
|
-
import path from 'node:path';
|
|
3
|
-
import { fileURLToPath } from 'node:url';
|
|
4
|
-
|
|
5
|
-
const scriptDir = path.dirname(fileURLToPath(import.meta.url));
|
|
6
|
-
const workspaceRoot = path.resolve(scriptDir, '..', '..', '..');
|
|
7
|
-
|
|
8
|
-
const files = {
|
|
9
|
-
skill: 'microi.skills/v8-mq-mqtt/SKILL.md',
|
|
10
|
-
reference: 'microi.skills/v8-mq-mqtt/references/mqtt-production.md',
|
|
11
|
-
mqttDoc: 'microi.doc/docs/doc/system-engine/mqtt-engine.md',
|
|
12
|
-
v8Doc: 'microi.doc/docs/doc/v8-engine/v8-server.md',
|
|
13
|
-
runtime: 'Microi.Server/Microi.MQTT/MicroiMQTT.cs',
|
|
14
|
-
model: 'Microi.Server/Microi.Core/Model/MqttParam.cs',
|
|
15
|
-
mqttInterface: 'Microi.Server/Microi.Core/Interface/IMicroiMQTT.cs',
|
|
16
|
-
tenantSecurity: 'Microi.Server/Microi.Core/SaaSEngine/TenantConfigurationSecurity.cs',
|
|
17
|
-
platformRuntime: 'Microi.Server/Microi.Core/V8Engine/Runtime/V8Method.PlatformPluginRuntimes.cs',
|
|
18
|
-
platformApiEngine: 'Microi.Server/OfficialApplications/Resource/platform-mqtt.js'
|
|
19
|
-
};
|
|
20
|
-
|
|
21
|
-
const content = {};
|
|
22
|
-
const failures = [];
|
|
23
|
-
|
|
24
|
-
for (const [name, relativePath] of Object.entries(files)) {
|
|
25
|
-
const absolutePath = path.join(workspaceRoot, relativePath);
|
|
26
|
-
if (!fs.existsSync(absolutePath)) {
|
|
27
|
-
failures.push(`${name}: 文件不存在 ${relativePath}`);
|
|
28
|
-
content[name] = '';
|
|
29
|
-
continue;
|
|
30
|
-
}
|
|
31
|
-
content[name] = fs.readFileSync(absolutePath, 'utf8');
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
function collectMatches(text, regex) {
|
|
35
|
-
const values = [];
|
|
36
|
-
for (const match of text.matchAll(regex)) values.push(match[1]);
|
|
37
|
-
return values;
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
function requireTokens(targetName, tokens) {
|
|
41
|
-
const text = content[targetName] || '';
|
|
42
|
-
for (const token of tokens) {
|
|
43
|
-
if (!text.includes(token)) failures.push(`${targetName}: 缺少 ${token}`);
|
|
44
|
-
}
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
function requireAny(targetName, alternatives, label) {
|
|
48
|
-
const text = content[targetName] || '';
|
|
49
|
-
if (!alternatives.some((token) => text.includes(token))) {
|
|
50
|
-
failures.push(`${targetName}: 缺少 ${label}`);
|
|
51
|
-
}
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
const runtimeEvents = new Set([
|
|
55
|
-
...collectMatches(
|
|
56
|
-
content.runtime,
|
|
57
|
-
/RunMqttV8EngineAsync\([^,\r\n]+,\s*"([A-Za-z]+)"/g
|
|
58
|
-
),
|
|
59
|
-
...collectMatches(
|
|
60
|
-
content.runtime,
|
|
61
|
-
/FireV8EventForAllTenantsAsync\(\s*"([A-Za-z]+)"/g
|
|
62
|
-
)
|
|
63
|
-
]);
|
|
64
|
-
|
|
65
|
-
const expectedEvents = [
|
|
66
|
-
'StartServer',
|
|
67
|
-
'Connected',
|
|
68
|
-
'Disconnected',
|
|
69
|
-
'Subscribing',
|
|
70
|
-
'MessageReceived',
|
|
71
|
-
'MessageChanged',
|
|
72
|
-
'StopServer'
|
|
73
|
-
];
|
|
74
|
-
|
|
75
|
-
for (const eventName of expectedEvents) {
|
|
76
|
-
if (!runtimeEvents.has(eventName)) failures.push(`runtime: 未提取到事件 ${eventName}`);
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
const mqttProperties = new Set(collectMatches(
|
|
80
|
-
content.model,
|
|
81
|
-
/public\s+[A-Za-z0-9_<>,.\s]+\s+([A-Za-z0-9_]+)\s*\{\s*get;\s*set;\s*\}/g
|
|
82
|
-
));
|
|
83
|
-
|
|
84
|
-
const expectedProperties = [
|
|
85
|
-
'ClientId',
|
|
86
|
-
'Payload',
|
|
87
|
-
'PayloadRaw',
|
|
88
|
-
'Topic',
|
|
89
|
-
'OsClient',
|
|
90
|
-
'UserName',
|
|
91
|
-
'Qos',
|
|
92
|
-
'Retain',
|
|
93
|
-
'UserProperties'
|
|
94
|
-
];
|
|
95
|
-
|
|
96
|
-
for (const propertyName of expectedProperties) {
|
|
97
|
-
if (!mqttProperties.has(propertyName)) failures.push(`model: 未提取到属性 ${propertyName}`);
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
const sourceEvents = [...runtimeEvents].sort();
|
|
101
|
-
const sourceProperties = [...mqttProperties].sort();
|
|
102
|
-
for (const targetName of ['reference', 'mqttDoc', 'v8Doc']) {
|
|
103
|
-
requireTokens(targetName, sourceEvents);
|
|
104
|
-
requireTokens(targetName, sourceProperties);
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
const configurationTokens = [
|
|
108
|
-
'MqttEnable',
|
|
109
|
-
'MqttPort',
|
|
110
|
-
'MqttUseTls',
|
|
111
|
-
'MqttTlsPort',
|
|
112
|
-
'MqttCertPath',
|
|
113
|
-
'MqttCertPassword',
|
|
114
|
-
'MqttFallbackPort',
|
|
115
|
-
'MqttWsPort',
|
|
116
|
-
'MqttAccount',
|
|
117
|
-
'MqttPwd',
|
|
118
|
-
'MqttApiEngine',
|
|
119
|
-
'MqttAllowAnonymous',
|
|
120
|
-
'MqttTopicIsolation'
|
|
121
|
-
];
|
|
122
|
-
|
|
123
|
-
const securityTokens = [
|
|
124
|
-
'tenant/{lowerOsClient}',
|
|
125
|
-
'$SYS',
|
|
126
|
-
'$share',
|
|
127
|
-
'ResponseTopic',
|
|
128
|
-
'Code != 1',
|
|
129
|
-
'StaleDisconnectIgnored'
|
|
130
|
-
];
|
|
131
|
-
|
|
132
|
-
const operationsTokens = [
|
|
133
|
-
'mci_mqtt_client',
|
|
134
|
-
'mci_mqtt_log',
|
|
135
|
-
'ApiEngineId',
|
|
136
|
-
'IMicroiMQTT.PublishAsync',
|
|
137
|
-
'ConnectedClients',
|
|
138
|
-
'GetConnectedClients',
|
|
139
|
-
'外部 Broker',
|
|
140
|
-
'独立 MQTT 节点'
|
|
141
|
-
];
|
|
142
|
-
|
|
143
|
-
requireTokens('platformRuntime', [
|
|
144
|
-
'ManageMqtt',
|
|
145
|
-
'RequireCurrentTenantSuperAdmin',
|
|
146
|
-
'IMicroiMQTT',
|
|
147
|
-
'GetConnectedClients',
|
|
148
|
-
'PublishAsync'
|
|
149
|
-
]);
|
|
150
|
-
requireTokens('platformApiEngine', ['V8.Method.ManageMqtt']);
|
|
151
|
-
|
|
152
|
-
requireTokens('skill', ['references/mqtt-production.md', 'platform-mqtt']);
|
|
153
|
-
requireTokens('reference', configurationTokens);
|
|
154
|
-
|
|
155
|
-
requireTokens('reference', securityTokens);
|
|
156
|
-
requireTokens('reference', operationsTokens);
|
|
157
|
-
|
|
158
|
-
requireTokens(
|
|
159
|
-
'mqttDoc',
|
|
160
|
-
configurationTokens.filter((token) => token !== 'MqttAllowAnonymous')
|
|
161
|
-
);
|
|
162
|
-
requireAny(
|
|
163
|
-
'mqttDoc',
|
|
164
|
-
['MqttAllowAnonymous', '匿名连接只可能由主租户显式开启'],
|
|
165
|
-
'主租户匿名连接边界'
|
|
166
|
-
);
|
|
167
|
-
requireTokens(
|
|
168
|
-
'mqttDoc',
|
|
169
|
-
securityTokens.filter(
|
|
170
|
-
(token) => token !== 'StaleDisconnectIgnored' && token !== 'tenant/{lowerOsClient}'
|
|
171
|
-
)
|
|
172
|
-
);
|
|
173
|
-
requireAny(
|
|
174
|
-
'mqttDoc',
|
|
175
|
-
['tenant/{lowerOsClient}', 'tenant/<lowerOsClient>'],
|
|
176
|
-
'标准租户 Topic 模板'
|
|
177
|
-
);
|
|
178
|
-
requireTokens('v8Doc', ['## V8.MQTT', 'IMicroiMQTT.PublishAsync', 'Code != 1']);
|
|
179
|
-
|
|
180
|
-
requireTokens('runtime', [
|
|
181
|
-
'NormalizeTopic',
|
|
182
|
-
'ResponseTopic',
|
|
183
|
-
'StaleDisconnectIgnored',
|
|
184
|
-
'$share/',
|
|
185
|
-
'$SYS/',
|
|
186
|
-
'mci_mqtt_client',
|
|
187
|
-
'mci_mqtt_log',
|
|
188
|
-
'PublishRejectedByV8'
|
|
189
|
-
]);
|
|
190
|
-
requireTokens('mqttInterface', ['PublishAsync(string osClient', 'GetConnectedClients(string osClient)']);
|
|
191
|
-
requireTokens('tenantSecurity', ['NormalizeMqttTopic', 'HasTenantServiceCredentialCollision']);
|
|
192
|
-
|
|
193
|
-
if (failures.length > 0) {
|
|
194
|
-
console.error('MQTT Skill 覆盖检查失败:');
|
|
195
|
-
for (const failure of failures) console.error(`- ${failure}`);
|
|
196
|
-
process.exitCode = 1;
|
|
197
|
-
} else {
|
|
198
|
-
console.log(
|
|
199
|
-
`MQTT Skill 覆盖检查通过:${sourceEvents.length} 个事件、` +
|
|
200
|
-
`${sourceProperties.length} 个 V8.MQTT 字段、` +
|
|
201
|
-
`${configurationTokens.length} 个配置项及生产安全/部署契约均已覆盖。`
|
|
202
|
-
);
|
|
203
|
-
}
|
|
1
|
+
import fs from 'node:fs';
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
import { fileURLToPath } from 'node:url';
|
|
4
|
+
|
|
5
|
+
const scriptDir = path.dirname(fileURLToPath(import.meta.url));
|
|
6
|
+
const workspaceRoot = path.resolve(scriptDir, '..', '..', '..');
|
|
7
|
+
|
|
8
|
+
const files = {
|
|
9
|
+
skill: 'microi.skills/v8-mq-mqtt/SKILL.md',
|
|
10
|
+
reference: 'microi.skills/v8-mq-mqtt/references/mqtt-production.md',
|
|
11
|
+
mqttDoc: 'microi.doc/docs/doc/system-engine/mqtt-engine.md',
|
|
12
|
+
v8Doc: 'microi.doc/docs/doc/v8-engine/v8-server.md',
|
|
13
|
+
runtime: 'Microi.Server/Microi.MQTT/MicroiMQTT.cs',
|
|
14
|
+
model: 'Microi.Server/Microi.Core/Model/MqttParam.cs',
|
|
15
|
+
mqttInterface: 'Microi.Server/Microi.Core/Interface/IMicroiMQTT.cs',
|
|
16
|
+
tenantSecurity: 'Microi.Server/Microi.Core/SaaSEngine/TenantConfigurationSecurity.cs',
|
|
17
|
+
platformRuntime: 'Microi.Server/Microi.Core/V8Engine/Runtime/V8Method.PlatformPluginRuntimes.cs',
|
|
18
|
+
platformApiEngine: 'Microi.Server/OfficialApplications/Resource/platform-mqtt.js'
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
const content = {};
|
|
22
|
+
const failures = [];
|
|
23
|
+
|
|
24
|
+
for (const [name, relativePath] of Object.entries(files)) {
|
|
25
|
+
const absolutePath = path.join(workspaceRoot, relativePath);
|
|
26
|
+
if (!fs.existsSync(absolutePath)) {
|
|
27
|
+
failures.push(`${name}: 文件不存在 ${relativePath}`);
|
|
28
|
+
content[name] = '';
|
|
29
|
+
continue;
|
|
30
|
+
}
|
|
31
|
+
content[name] = fs.readFileSync(absolutePath, 'utf8');
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
function collectMatches(text, regex) {
|
|
35
|
+
const values = [];
|
|
36
|
+
for (const match of text.matchAll(regex)) values.push(match[1]);
|
|
37
|
+
return values;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
function requireTokens(targetName, tokens) {
|
|
41
|
+
const text = content[targetName] || '';
|
|
42
|
+
for (const token of tokens) {
|
|
43
|
+
if (!text.includes(token)) failures.push(`${targetName}: 缺少 ${token}`);
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
function requireAny(targetName, alternatives, label) {
|
|
48
|
+
const text = content[targetName] || '';
|
|
49
|
+
if (!alternatives.some((token) => text.includes(token))) {
|
|
50
|
+
failures.push(`${targetName}: 缺少 ${label}`);
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
const runtimeEvents = new Set([
|
|
55
|
+
...collectMatches(
|
|
56
|
+
content.runtime,
|
|
57
|
+
/RunMqttV8EngineAsync\([^,\r\n]+,\s*"([A-Za-z]+)"/g
|
|
58
|
+
),
|
|
59
|
+
...collectMatches(
|
|
60
|
+
content.runtime,
|
|
61
|
+
/FireV8EventForAllTenantsAsync\(\s*"([A-Za-z]+)"/g
|
|
62
|
+
)
|
|
63
|
+
]);
|
|
64
|
+
|
|
65
|
+
const expectedEvents = [
|
|
66
|
+
'StartServer',
|
|
67
|
+
'Connected',
|
|
68
|
+
'Disconnected',
|
|
69
|
+
'Subscribing',
|
|
70
|
+
'MessageReceived',
|
|
71
|
+
'MessageChanged',
|
|
72
|
+
'StopServer'
|
|
73
|
+
];
|
|
74
|
+
|
|
75
|
+
for (const eventName of expectedEvents) {
|
|
76
|
+
if (!runtimeEvents.has(eventName)) failures.push(`runtime: 未提取到事件 ${eventName}`);
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
const mqttProperties = new Set(collectMatches(
|
|
80
|
+
content.model,
|
|
81
|
+
/public\s+[A-Za-z0-9_<>,.\s]+\s+([A-Za-z0-9_]+)\s*\{\s*get;\s*set;\s*\}/g
|
|
82
|
+
));
|
|
83
|
+
|
|
84
|
+
const expectedProperties = [
|
|
85
|
+
'ClientId',
|
|
86
|
+
'Payload',
|
|
87
|
+
'PayloadRaw',
|
|
88
|
+
'Topic',
|
|
89
|
+
'OsClient',
|
|
90
|
+
'UserName',
|
|
91
|
+
'Qos',
|
|
92
|
+
'Retain',
|
|
93
|
+
'UserProperties'
|
|
94
|
+
];
|
|
95
|
+
|
|
96
|
+
for (const propertyName of expectedProperties) {
|
|
97
|
+
if (!mqttProperties.has(propertyName)) failures.push(`model: 未提取到属性 ${propertyName}`);
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
const sourceEvents = [...runtimeEvents].sort();
|
|
101
|
+
const sourceProperties = [...mqttProperties].sort();
|
|
102
|
+
for (const targetName of ['reference', 'mqttDoc', 'v8Doc']) {
|
|
103
|
+
requireTokens(targetName, sourceEvents);
|
|
104
|
+
requireTokens(targetName, sourceProperties);
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
const configurationTokens = [
|
|
108
|
+
'MqttEnable',
|
|
109
|
+
'MqttPort',
|
|
110
|
+
'MqttUseTls',
|
|
111
|
+
'MqttTlsPort',
|
|
112
|
+
'MqttCertPath',
|
|
113
|
+
'MqttCertPassword',
|
|
114
|
+
'MqttFallbackPort',
|
|
115
|
+
'MqttWsPort',
|
|
116
|
+
'MqttAccount',
|
|
117
|
+
'MqttPwd',
|
|
118
|
+
'MqttApiEngine',
|
|
119
|
+
'MqttAllowAnonymous',
|
|
120
|
+
'MqttTopicIsolation'
|
|
121
|
+
];
|
|
122
|
+
|
|
123
|
+
const securityTokens = [
|
|
124
|
+
'tenant/{lowerOsClient}',
|
|
125
|
+
'$SYS',
|
|
126
|
+
'$share',
|
|
127
|
+
'ResponseTopic',
|
|
128
|
+
'Code != 1',
|
|
129
|
+
'StaleDisconnectIgnored'
|
|
130
|
+
];
|
|
131
|
+
|
|
132
|
+
const operationsTokens = [
|
|
133
|
+
'mci_mqtt_client',
|
|
134
|
+
'mci_mqtt_log',
|
|
135
|
+
'ApiEngineId',
|
|
136
|
+
'IMicroiMQTT.PublishAsync',
|
|
137
|
+
'ConnectedClients',
|
|
138
|
+
'GetConnectedClients',
|
|
139
|
+
'外部 Broker',
|
|
140
|
+
'独立 MQTT 节点'
|
|
141
|
+
];
|
|
142
|
+
|
|
143
|
+
requireTokens('platformRuntime', [
|
|
144
|
+
'ManageMqtt',
|
|
145
|
+
'RequireCurrentTenantSuperAdmin',
|
|
146
|
+
'IMicroiMQTT',
|
|
147
|
+
'GetConnectedClients',
|
|
148
|
+
'PublishAsync'
|
|
149
|
+
]);
|
|
150
|
+
requireTokens('platformApiEngine', ['V8.Method.ManageMqtt']);
|
|
151
|
+
|
|
152
|
+
requireTokens('skill', ['references/mqtt-production.md', 'platform-mqtt']);
|
|
153
|
+
requireTokens('reference', configurationTokens);
|
|
154
|
+
|
|
155
|
+
requireTokens('reference', securityTokens);
|
|
156
|
+
requireTokens('reference', operationsTokens);
|
|
157
|
+
|
|
158
|
+
requireTokens(
|
|
159
|
+
'mqttDoc',
|
|
160
|
+
configurationTokens.filter((token) => token !== 'MqttAllowAnonymous')
|
|
161
|
+
);
|
|
162
|
+
requireAny(
|
|
163
|
+
'mqttDoc',
|
|
164
|
+
['MqttAllowAnonymous', '匿名连接只可能由主租户显式开启'],
|
|
165
|
+
'主租户匿名连接边界'
|
|
166
|
+
);
|
|
167
|
+
requireTokens(
|
|
168
|
+
'mqttDoc',
|
|
169
|
+
securityTokens.filter(
|
|
170
|
+
(token) => token !== 'StaleDisconnectIgnored' && token !== 'tenant/{lowerOsClient}'
|
|
171
|
+
)
|
|
172
|
+
);
|
|
173
|
+
requireAny(
|
|
174
|
+
'mqttDoc',
|
|
175
|
+
['tenant/{lowerOsClient}', 'tenant/<lowerOsClient>'],
|
|
176
|
+
'标准租户 Topic 模板'
|
|
177
|
+
);
|
|
178
|
+
requireTokens('v8Doc', ['## V8.MQTT', 'IMicroiMQTT.PublishAsync', 'Code != 1']);
|
|
179
|
+
|
|
180
|
+
requireTokens('runtime', [
|
|
181
|
+
'NormalizeTopic',
|
|
182
|
+
'ResponseTopic',
|
|
183
|
+
'StaleDisconnectIgnored',
|
|
184
|
+
'$share/',
|
|
185
|
+
'$SYS/',
|
|
186
|
+
'mci_mqtt_client',
|
|
187
|
+
'mci_mqtt_log',
|
|
188
|
+
'PublishRejectedByV8'
|
|
189
|
+
]);
|
|
190
|
+
requireTokens('mqttInterface', ['PublishAsync(string osClient', 'GetConnectedClients(string osClient)']);
|
|
191
|
+
requireTokens('tenantSecurity', ['NormalizeMqttTopic', 'HasTenantServiceCredentialCollision']);
|
|
192
|
+
|
|
193
|
+
if (failures.length > 0) {
|
|
194
|
+
console.error('MQTT Skill 覆盖检查失败:');
|
|
195
|
+
for (const failure of failures) console.error(`- ${failure}`);
|
|
196
|
+
process.exitCode = 1;
|
|
197
|
+
} else {
|
|
198
|
+
console.log(
|
|
199
|
+
`MQTT Skill 覆盖检查通过:${sourceEvents.length} 个事件、` +
|
|
200
|
+
`${sourceProperties.length} 个 V8.MQTT 字段、` +
|
|
201
|
+
`${configurationTokens.length} 个配置项及生产安全/部署契约均已覆盖。`
|
|
202
|
+
);
|
|
203
|
+
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
interface:
|
|
2
|
-
display_name: "V8 TCP 原始字节"
|
|
3
|
-
short_description: "通过后端 V8 安全发送和接收 TCP 原始字节数据"
|
|
4
|
-
default_prompt: "使用 $v8-tcp-integration 编写一个安全、可验证的 Microi 后端 V8 TCP 设备集成。"
|
|
1
|
+
interface:
|
|
2
|
+
display_name: "V8 TCP 原始字节"
|
|
3
|
+
short_description: "通过后端 V8 安全发送和接收 TCP 原始字节数据"
|
|
4
|
+
default_prompt: "使用 $v8-tcp-integration 编写一个安全、可验证的 Microi 后端 V8 TCP 设备集成。"
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
interface:
|
|
2
|
-
display_name: "视觉引擎"
|
|
3
|
-
short_description: "构建与验收数据库优先、AI回退的通用视觉识别"
|
|
4
|
-
default_prompt: "Use $vision-engine to build and validate tenant-isolated Microi.Vision workflows."
|
|
1
|
+
interface:
|
|
2
|
+
display_name: "视觉引擎"
|
|
3
|
+
short_description: "构建与验收数据库优先、AI回退的通用视觉识别"
|
|
4
|
+
default_prompt: "Use $vision-engine to build and validate tenant-isolated Microi.Vision workflows."
|
|
@@ -6,7 +6,7 @@ description: 每次 Microi 任务开始前必读的基础规范。用于识别
|
|
|
6
6
|
# Microi 工作区全局约定
|
|
7
7
|
|
|
8
8
|
<!-- microi-progressive:begin -->
|
|
9
|
-
<!-- microi-progressive:chunk id=workspace-conventions-000 sha256=
|
|
9
|
+
<!-- microi-progressive:chunk id=workspace-conventions-000 sha256=105657a606c31b5c06e3834c1d29d613d9456f04225e729ba92e69049053c074 -->
|
|
10
10
|
## 任务启动前 Skill 读取规则(强制)
|
|
11
11
|
|
|
12
12
|
AI 处理任何 Microi 低代码、V8、MCP、OpenClaw、采集引擎、前端、后端、UniApp、文档、测试或交付任务前,必须先按任务类型读取相关 `microi.skills/**/SKILL.md`。不能等到写代码或出问题后才补读。
|
|
@@ -49,8 +49,10 @@ AI 处理任何 Microi 低代码、V8、MCP、OpenClaw、采集引擎、前端
|
|
|
49
49
|
- 创始人源码工作区中的每个平台功能新增、缺陷修复和兼容性调整都必须同时交付可重复执行的回归测试;先证明旧行为失败,再验证修复成功,覆盖正常、边界、失败、安全与存量兼容路径。不得只改源码或用手工截图代替自动回归。
|
|
50
50
|
- 平台 C# 单元/组件/集成测试归入 `Microi.Server/Microi.Tests`。平台前端、平台内置应用包与平台 V8 的 Node 行为测试可留在责任源码旁,由 `Microi.Tests/run-tests.ps1` 自动发现执行;平台真实浏览器、数据库及第三方集成归入 Full 或平台专项验收,不得冒充离线单测。新增公共后端能力同时补相应 HTTP 闭环。
|
|
51
51
|
- 官方或社区独立业务应用、游戏及客户项目的测试归应用自身源码根的 `tests/` 或独立测试工程,由该应用自己的测试和发布入口执行;不得放入 `Microi.Tests`、创建转调包装或接入平台 Quick/Full。官方发布身份不改变测试归属。应用开发中涉及平台通用缺陷时,仅把通用最小回归夹具加入平台门禁,应用业务断言仍在应用项目维护。
|
|
52
|
-
- `Microi一键编译发布.sh` 的所有 PC/API
|
|
52
|
+
- `Microi一键编译发布.sh` 的所有 PC/API 镜像路径(包括仅推送、热修复)都必须先通过按指定 MCP 实际依赖选定的 Full 发布矩阵;选中范围内缺少环境、零用例、失败、取消、跳过、待办或无法解析测试结果一律停止。未纳入本次矩阵的提供商标为“不适用(未执行)”,不冒充通过,也不单独阻塞常规发布。禁止关闭断言、删测试、排除已选失败项目或修改门禁阈值来发布。
|
|
53
53
|
- 测试成功必须绑定本次候选源码和实际构建上下文的内容哈希,构建后、每次推送前复核。旧产物没有可验证回执或源码/产物漂移时必须重建重测,禁止“当前源码通过测试 + 推送另一份旧 DLL/前端 dist”。 所有测试默认使用当前 MCP 经同源只读发现的 MongoDB 实际版本与当前租户实际生效的 HDFS 提供商;目标唯一时直接沿已授权隔离范围执行,不为旧 MongoDB 或其它 OSS/MinIO/S3 反复询问、新建服务或替换当前提供商。只有明确的兼容、迁移或提供商缺陷任务才扩展真实矩阵;未执行项如实记未覆盖,不以同一端点冒充多版本,也不因环境发现获得生产业务写入授权。
|
|
54
|
+
- 常规发布只验证用户指定 MCP 对应的实际依赖:MySQL、MongoDB 实际版本、Redis,以及租户实际生效的 MinIO 或 OSS/HDFS 等存储;不默认同时验证所有数据库版本或所有存储提供商。先核实 Profile、ApiBase、OsClient 和依赖类型,在已授权隔离范围执行;依赖发现不扩大生产写入或新建 Docker 测试依赖的授权。
|
|
55
|
+
- SQL Server 的真实连接、提供商兼容与专项验收默认不纳入常规发布矩阵;只有用户明确指定排查、修复或验收 SQL Server 问题时才执行。检测到 SQL Server 连接/驱动、旧 Full 清单或通用数据库代码变更都不能自行触发该专项,也不需要每次申请 SQL Server 免测。既有不连接 SQL Server 的离线单元断言照常保留,但不能据此声称 SQL Server 已实测。
|
|
54
56
|
- 交付记录逐项列明修复与测试映射、执行数量、未覆盖边界和镜像摘要。覆盖率与 Full 都不能证明所有租户业务、任意生产数据和第三方系统绝对无误;真实客户路径仍需只读验收。详细矩阵见 `microi-system-delivery/references/progressive-02-自动化测试必须覆盖的坑.md`。
|
|
55
57
|
|
|
56
58
|
### Microi吾码非阻塞自动更新(强制)
|
|
@@ -227,14 +229,12 @@ AI 在工作区任意任务中生成的**一次性临时脚本、诊断文件、
|
|
|
227
229
|
## ASP.NET Controller 归属与旧路由收口规范(强制)
|
|
228
230
|
|
|
229
231
|
- 历史部门树读取可在同一兼容入口复用既有可信 Core 原子,保持 DiyToken、当前租户、组织范围和 `_Child` 契约;仅补确有历史调用的只读地址,不扩张为组织机构写操作或通用 CRUD 兜底。
|
|
230
|
-
|
|
231
232
|
- 已由 V8 接口引擎完整实现的业务 Controller 必须物理删除,禁止为了“瘦身”再创建 `Microi.AspNetCore` 一类无业务归属的通用 .NET 项目,把原 Controller 原样搬过去。
|
|
232
233
|
- 仍被旧版 PC、UniApp 或定制移动端调用的 `/api/*` 历史地址,只能集中在 `Microi.net.Api/Controllers/LegacyMobileCompatibilityController.cs`;文件顶部必须醒目标明“仅兼容、禁止新增业务、未来可能整体删除”。已配置的 Managed ApiEngine 始终优先;只有主库确认历史地址和固定 Key 都缺失时,登录、DiyToken 会话、公开启动配置、当前用户与菜单读取可复用既有可信 Core 原子兜底,让未完成升级的租户能进入商城修复。禁止仅因升级门禁已有自愈能力就删除此入口;禁用、StopHttp、权限拒绝、数据库异常及执行错误均不得触发兜底,不在请求中安装资源或覆盖租户配置。
|
|
233
234
|
- 所有 ASP.NET Controller 源码必须留在 `Microi.net.Api/Controllers`。不得为了迁走 Controller 新建 `Microi.AspNetCore`、`Microi.SSO` 等中转项目,也不得把 `Microi.AI`、`Microi.net` 或其它 `netstandard` 类库改成 `net10.0`/多目标框架来承载 Controller。
|
|
234
235
|
- V8 无法直接承担的 SSE/WebSocket、OIDC/SAML/CAS、第三方回调验签/解密、浏览器原生身份协议、供应商密钥隔离、文件流等最小协议边界,可以继续作为薄 Controller 留在 API 项目;Controller 只做协议解析、可信鉴权和安全归一化,可复用实现与业务原子必须进入对应功能类库,普通 CRUD、日志、通知和可升级业务编排继续由 Managed ApiEngine 承担。
|
|
235
236
|
- `Microi.net.Api/Controllers` 除五个兼容内核 Controller 与统一旧客户端兼容 Controller 外,只能保留已证明接口引擎无法承担的薄协议 Controller;每个保留项必须同步登记 `api-ownership-catalog.json` 并由结构测试锁定。已完整迁入接口引擎的旧 Controller 必须继续物理删除。
|
|
236
237
|
- `Program.cs` 只保留有说明的插件注册和最薄宿主入口;ASP.NET 组合代码可留在同项目 `Hosting`,可复用业务/运行时逻辑进入 `Microi.Core`、`Microi.net`、`Microi.Upgrade` 或对应插件,禁止通过新建“中转层”掩盖归属问题。
|
|
237
|
-
|
|
238
238
|
<!-- microi-progressive:chunk id=workspace-conventions-009 sha256=43bdb1476a7751fbc251c933ccfbd1710c9269dec3e7e4b541cdaeea37d200f1 -->
|
|
239
239
|
## 多对话共享工作区变更归属保护(强制)
|
|
240
240
|
|