lingshu-solver 1.0.13 → 1.0.15
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/README.md +2 -0
- package/http-mcp-server.js +122 -5
- package/index.html +1 -1
- package/mcp-server.js +113 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
# 灵数求解器 · Lingshu Solver
|
|
2
2
|
|
|
3
|
+
**品类(Category)**:认证实根计算 · Certified Real-Root Computation
|
|
4
|
+
|
|
3
5
|
[](LICENSE)
|
|
4
6
|
[](https://modelcontextprotocol.io)
|
|
5
7
|
[](docs/03-设计思想.md)
|
package/http-mcp-server.js
CHANGED
|
@@ -47,7 +47,7 @@ const solverCore = require('./solver-core');
|
|
|
47
47
|
const { solve } = solverCore;
|
|
48
48
|
|
|
49
49
|
const SERVER_NAME = 'lingshu-solver';
|
|
50
|
-
const SERVER_VERSION = '1.0.
|
|
50
|
+
const SERVER_VERSION = '1.0.15';
|
|
51
51
|
const PORT = parseInt(process.env.PORT || '3000', 10);
|
|
52
52
|
|
|
53
53
|
// ---- 护栏常量(防畸形/恶意输入耗尽资源,与 stdio 版一致)----
|
|
@@ -736,6 +736,7 @@ function shapeResult(r) {
|
|
|
736
736
|
tier: s.tier || 'unknown',
|
|
737
737
|
certified: !!s.certified,
|
|
738
738
|
text: text,
|
|
739
|
+
cert: s.cert || null,
|
|
739
740
|
internals: {
|
|
740
741
|
residual: detF(s.residual),
|
|
741
742
|
certifiedRadius: detF(s.certifiedRadius)
|
|
@@ -786,6 +787,8 @@ function shapeResult(r) {
|
|
|
786
787
|
recommended: recommendedClean,
|
|
787
788
|
solutions: cleanSols,
|
|
788
789
|
warnings: r.warnings || [],
|
|
790
|
+
reportId: meta.reportId || r.reportId || null,
|
|
791
|
+
certification: r.certification || null,
|
|
789
792
|
diagnostics: diagnostics
|
|
790
793
|
};
|
|
791
794
|
}
|
|
@@ -851,6 +854,85 @@ function doSolve(args) {
|
|
|
851
854
|
return shapeResult(r);
|
|
852
855
|
}
|
|
853
856
|
|
|
857
|
+
// ---- 新工具:poly_roots / verify(agent 时代适配,薄封装 solve,不碰内核)----
|
|
858
|
+
function buildPolyEquation(coeffs) {
|
|
859
|
+
const n = coeffs.length - 1;
|
|
860
|
+
let s = '';
|
|
861
|
+
for (let i = 0; i < coeffs.length; i++) {
|
|
862
|
+
const c = coeffs[i]; const deg = n - i;
|
|
863
|
+
if (c === 0 && deg !== 0) continue;
|
|
864
|
+
const abs = Math.abs(c);
|
|
865
|
+
const sign = (s === '' ? (c < 0 ? '-' : '') : (c < 0 ? ' - ' : ' + '));
|
|
866
|
+
const term = deg === 0 ? '' + abs : deg === 1 ? abs + '*x' : abs + '*x^' + deg;
|
|
867
|
+
s += sign + term;
|
|
868
|
+
}
|
|
869
|
+
return s + ' = 0';
|
|
870
|
+
}
|
|
871
|
+
|
|
872
|
+
function doPolyRoots(args) {
|
|
873
|
+
const coeffs = args && args.coefficients;
|
|
874
|
+
if (!Array.isArray(coeffs) || coeffs.length < 2) throw { type: 'invalid_input', message: 'coefficients 必须是长度≥2 的数组(最高次系数在前)' };
|
|
875
|
+
for (const c of coeffs) if (typeof c !== 'number' || !isFinite(c)) throw { type: 'invalid_input', message: 'coefficients 须为有限数字' };
|
|
876
|
+
const eq = buildPolyEquation(coeffs);
|
|
877
|
+
const r = solve([eq], ['x'], 6, undefined, false, {});
|
|
878
|
+
return shapeResult(r);
|
|
879
|
+
}
|
|
880
|
+
|
|
881
|
+
function doVerify(args) {
|
|
882
|
+
const eq = args && args.equation;
|
|
883
|
+
if (typeof eq !== 'string' || !eq.includes('=')) throw { type: 'invalid_input', message: 'equation 须为含 "=" 的字符串' };
|
|
884
|
+
const cand = args.candidate;
|
|
885
|
+
let varNames, candPoint;
|
|
886
|
+
if (typeof cand === 'number') {
|
|
887
|
+
varNames = (args && Array.isArray(args.variables) && args.variables[0]) ? [args.variables[0]] : ['x'];
|
|
888
|
+
candPoint = [cand];
|
|
889
|
+
} else if (cand && typeof cand === 'object' && !Array.isArray(cand)) {
|
|
890
|
+
varNames = Object.keys(cand);
|
|
891
|
+
candPoint = varNames.map(function (v) { return cand[v]; });
|
|
892
|
+
} else if (Array.isArray(cand)) {
|
|
893
|
+
varNames = (args && Array.isArray(args.variables)) ? args.variables : [];
|
|
894
|
+
if (varNames.length !== cand.length) throw { type: 'invalid_input', message: 'candidate 数组长度须与 variables 一致' };
|
|
895
|
+
candPoint = cand;
|
|
896
|
+
} else {
|
|
897
|
+
throw { type: 'invalid_input', message: 'candidate 须为数字 / {变量:值} / [值...]' };
|
|
898
|
+
}
|
|
899
|
+
const margin = (args && typeof args.tolerance === 'number' && args.tolerance > 0) ? args.tolerance : 1e-3;
|
|
900
|
+
const domain = {};
|
|
901
|
+
varNames.forEach(function (v, i) { domain[v] = [candPoint[i] - margin, candPoint[i] + margin]; });
|
|
902
|
+
const r = solve([eq], varNames, 6, domain, false, {});
|
|
903
|
+
const shaped = shapeResult(r);
|
|
904
|
+
const matched = (r.solutions || []).find(function (s) {
|
|
905
|
+
return Array.isArray(s.values) && s.values.every(function (val, i) { return Math.abs(val - candPoint[i]) <= 1e-6; });
|
|
906
|
+
});
|
|
907
|
+
if (matched) {
|
|
908
|
+
return {
|
|
909
|
+
verdict: 'verified', isRoot: true, candidate: cand,
|
|
910
|
+
matchedRoot: { values: matched.values, tier: matched.tier, certified: !!matched.certified, cert: matched.cert || null,
|
|
911
|
+
text: varNames.map(function (vn, i) { return vn + '=' + fmt6(matched.values[i]); }).join(', ') },
|
|
912
|
+
reportId: shaped.reportId, certification: shaped.certification
|
|
913
|
+
};
|
|
914
|
+
}
|
|
915
|
+
let nearest = null;
|
|
916
|
+
try {
|
|
917
|
+
// refuted:在更宽域(默认 ±1e6)重算,给 Agent 全局最近的「真认证根」——
|
|
918
|
+
// 否则当 LLM 把根算偏(如猜 2.1、真根 2)时,窄邻域内无解会导致 nearest 为空,
|
|
919
|
+
// Agent 看不到正确值,verify 就失去了「纠正 LLM」的核心价值。
|
|
920
|
+
const rb = solve([eq], varNames, 6, undefined, false, {});
|
|
921
|
+
const solsB = (rb.solutions || []).filter(function (s) { return Array.isArray(s.values); });
|
|
922
|
+
if (solsB.length) {
|
|
923
|
+
let bestD = Infinity, bestS = null;
|
|
924
|
+
for (const s of solsB) { let d = 0; for (let i = 0; i < s.values.length; i++) d += (s.values[i] - candPoint[i]) * (s.values[i] - candPoint[i]); if (d < bestD) { bestD = d; bestS = s; } }
|
|
925
|
+
nearest = { values: bestS.values, tier: bestS.tier || null, certified: !!bestS.certified, cert: bestS.cert || null,
|
|
926
|
+
text: varNames.map(function (vn, i) { return vn + '=' + fmt6(bestS.values[i]); }).join(', ') };
|
|
927
|
+
}
|
|
928
|
+
} catch (_e) { /* 宽域重算失败不致命,nearest 保持 null */ }
|
|
929
|
+
return {
|
|
930
|
+
verdict: 'refuted_or_unverified', isRoot: false, candidate: cand,
|
|
931
|
+
message: '在候选点 ±' + margin + ' 邻域内未找到与之匹配的认证根;候选不是经验证的实根。' + (nearest ? '(全局最近认证根见 nearestCertifiedRoot)' : '(该方程在默认域内也无实根)'),
|
|
932
|
+
nearestCertifiedRoot: nearest, reportId: shaped.reportId
|
|
933
|
+
};
|
|
934
|
+
}
|
|
935
|
+
|
|
854
936
|
// ---- 工具定义(与 stdio 版一致)----
|
|
855
937
|
const TOOLS = [
|
|
856
938
|
{
|
|
@@ -898,6 +980,34 @@ const TOOLS = [
|
|
|
898
980
|
required: ['message']
|
|
899
981
|
}
|
|
900
982
|
},
|
|
983
|
+
{
|
|
984
|
+
name: 'poly_roots',
|
|
985
|
+
description: '多项式全部实根,逐个 Krawczyk 认证(带严格误差盒)。输入系数「最高次在前」,如 [1,-2,-5,6] 表示 x³−2x²−5x+6。确定性、可复现、可证明正确;复数根不返回(本品只做实数)。给 AI Agent 当「可靠的多项式求根件」——不会再像通用 LLM 那样把根算错或半对。' +
|
|
986
|
+
'★ 计费边界(Agent 必读):与 solve 同规则 —— honorPaid:true 即信任制免费放行;否则走付费通道(GET /pricing)。',
|
|
987
|
+
inputSchema: {
|
|
988
|
+
type: 'object',
|
|
989
|
+
properties: {
|
|
990
|
+
coefficients: { type: 'array', items: { type: 'number' }, description: '多项式系数,最高次在前。如 [1,-2,-5,6] 对应 x³−2x²−5x+6。' },
|
|
991
|
+
tolerance: { type: 'number', description: '根的判定容差(可选,默认内部精度)' }
|
|
992
|
+
},
|
|
993
|
+
required: ['coefficients']
|
|
994
|
+
}
|
|
995
|
+
},
|
|
996
|
+
{
|
|
997
|
+
name: 'verify',
|
|
998
|
+
description: '核验一个「声称的答案」到底对不对——这是「LLM 猜了 2.1、真根是精确 2」的检查。输入方程 + 候选值/点(数字,或 {变量:值},或按 variables 顺序的数组),本工具在候选点邻域内调用同一套认证内核:若找到与之匹配的认证根 → 返回 verified + 误差盒;若找不到 → 返回 refuted 并附上最近的认证根(让 Agent 立刻看到正确值)。确定性、非 LLM、结果可复现。' +
|
|
999
|
+
'★ 计费边界(Agent 必读):与 solve 同规则 —— honorPaid:true 即信任制免费放行;否则走付费通道(GET /pricing)。',
|
|
1000
|
+
inputSchema: {
|
|
1001
|
+
type: 'object',
|
|
1002
|
+
properties: {
|
|
1003
|
+
equation: { type: 'string', description: '含 "=" 的方程,如 "x^2 = 4"。' },
|
|
1004
|
+
candidate: { description: '声称的答案:数字(单变量,默认变量 x)、{变量:值}(多变量)、或按 variables 顺序的数组。', oneOf: [{ type: 'number' }, { type: 'object' }, { type: 'array' }] },
|
|
1005
|
+
variables: { type: 'array', items: { type: 'string' }, description: '变量名(多变量或数组候选时必填),如 ["x","y"]。' },
|
|
1006
|
+
tolerance: { type: 'number', description: '邻域半径(可选,默认 1e-3),在该邻域内寻找匹配的认证根。' }
|
|
1007
|
+
},
|
|
1008
|
+
required: ['equation', 'candidate']
|
|
1009
|
+
}
|
|
1010
|
+
},
|
|
901
1011
|
{
|
|
902
1012
|
name: 'pay',
|
|
903
1013
|
description: '对公收款:为本次/后续求解创建一笔真实付费订单(' + yuan(PRICE_CENTS) + '/次),返回订单号、专属 key 与结构化付款意图(payIntent)。' +
|
|
@@ -964,15 +1074,22 @@ function handleRpc(msg, ip, ctx) {
|
|
|
964
1074
|
let honorClaimed = false;
|
|
965
1075
|
try {
|
|
966
1076
|
let result;
|
|
967
|
-
if (name === 'solve') {
|
|
1077
|
+
if (name === 'solve' || name === 'poly_roots' || name === 'verify') {
|
|
968
1078
|
// ── 信任制(honor system):调用方声明「我已付款」即放行,不验证、不扣余额。
|
|
969
1079
|
// 设计取舍(用户决策):没有支付通道凭证、又想直接用的人,给一个零摩擦入口。
|
|
970
1080
|
// 最坏情况=白嫖(求解是确定性离线计算,边际成本≈0,不亏);最好情况=有人真去
|
|
971
1081
|
// 付静态收款码那 1 分。转化靠 calls.log 里的 honorClaimed 计数衡量。
|
|
1082
|
+
// poly_roots / verify 与 solve 同属「认证数值计算」,共用信任制 + 计费路径。
|
|
1083
|
+
const isSolve = (name === 'solve');
|
|
1084
|
+
const runSolver = function () {
|
|
1085
|
+
if (name === 'solve') return doSolve(args);
|
|
1086
|
+
if (name === 'poly_roots') return doPolyRoots(args);
|
|
1087
|
+
return doVerify(args);
|
|
1088
|
+
};
|
|
972
1089
|
const honor = !!(args && args.honorPaid === true);
|
|
973
1090
|
if (honor) {
|
|
974
|
-
result =
|
|
975
|
-
result.support = honorSupportBlock(); // 层1:代传微请求,借 Agent「忠实转发器」特性触达付款人
|
|
1091
|
+
result = runSolver();
|
|
1092
|
+
if (isSolve) result.support = honorSupportBlock(); // 层1:代传微请求,借 Agent「忠实转发器」特性触达付款人
|
|
976
1093
|
freeCall = true;
|
|
977
1094
|
honorClaimed = true;
|
|
978
1095
|
honorClaims++;
|
|
@@ -981,7 +1098,7 @@ function handleRpc(msg, ip, ctx) {
|
|
|
981
1098
|
const meter = meterPreCheck(ctx);
|
|
982
1099
|
if (!meter.ok) throw meter.err; // 落到下方 catch → isError,不扣费
|
|
983
1100
|
freeCall = !!meter.free;
|
|
984
|
-
result =
|
|
1101
|
+
result = runSolver();
|
|
985
1102
|
// 只有成功产出结果、且不是「解析失败」才扣
|
|
986
1103
|
chargedCents = (meter.free || !isBillable(result)) ? 0 : meterCharge(ctx);
|
|
987
1104
|
}
|
package/index.html
CHANGED
|
@@ -11192,7 +11192,7 @@ function _runTail(state) {
|
|
|
11192
11192
|
|
|
11193
11193
|
// —— 可审计结构化溯源(切片A):每个结果附带完整证据链元数据 ——
|
|
11194
11194
|
// 设计目标:Agent / 上层系统拿到的不只是裸数字,而是"为什么是这个解"的可读证据链。
|
|
11195
|
-
var SOLVER_VERSION = "lingshu-solver/1.0.
|
|
11195
|
+
var SOLVER_VERSION = "lingshu-solver/1.0.15";
|
|
11196
11196
|
|
|
11197
11197
|
// —— 确定性可复现契约(Certified Real-Root Computation 六属性之「确定性可复现」)——
|
|
11198
11198
|
// 纯 JS 同步 SHA-256(零依赖,浏览器/Node 通用,免 Web Crypto 异步)。
|
package/mcp-server.js
CHANGED
|
@@ -19,7 +19,7 @@ const path = require('path');
|
|
|
19
19
|
const { solve } = require('./solver-core');
|
|
20
20
|
|
|
21
21
|
const SERVER_NAME = 'lingshu-solver';
|
|
22
|
-
const SERVER_VERSION = '1.0.
|
|
22
|
+
const SERVER_VERSION = '1.0.15';
|
|
23
23
|
|
|
24
24
|
// ---- 护栏常量(防畸形/恶意输入耗尽资源)----
|
|
25
25
|
const MAX_TOTAL_CHARS = 100 * 1024; // 单次请求方程文本总长上限 100KB
|
|
@@ -73,6 +73,7 @@ function shapeResult(r) {
|
|
|
73
73
|
tier: s.tier || 'unknown',
|
|
74
74
|
certified: !!s.certified,
|
|
75
75
|
text: text,
|
|
76
|
+
cert: s.cert || null,
|
|
76
77
|
internals: {
|
|
77
78
|
residual: detF(s.residual),
|
|
78
79
|
certifiedRadius: detF(s.certifiedRadius)
|
|
@@ -115,6 +116,8 @@ function shapeResult(r) {
|
|
|
115
116
|
recommended: recommendedClean,
|
|
116
117
|
solutions: cleanSols,
|
|
117
118
|
warnings: r.warnings || [],
|
|
119
|
+
reportId: meta.reportId || r.reportId || null,
|
|
120
|
+
certification: r.certification || null,
|
|
118
121
|
diagnostics: diagnostics
|
|
119
122
|
};
|
|
120
123
|
}
|
|
@@ -147,6 +150,85 @@ function doSolve(args) {
|
|
|
147
150
|
return shapeResult(r);
|
|
148
151
|
}
|
|
149
152
|
|
|
153
|
+
// ---- 新工具:poly_roots / verify(agent 时代适配,薄封装 solve,不碰内核)----
|
|
154
|
+
function buildPolyEquation(coeffs) {
|
|
155
|
+
const n = coeffs.length - 1;
|
|
156
|
+
let s = '';
|
|
157
|
+
for (let i = 0; i < coeffs.length; i++) {
|
|
158
|
+
const c = coeffs[i]; const deg = n - i;
|
|
159
|
+
if (c === 0 && deg !== 0) continue;
|
|
160
|
+
const abs = Math.abs(c);
|
|
161
|
+
const sign = (s === '' ? (c < 0 ? '-' : '') : (c < 0 ? ' - ' : ' + '));
|
|
162
|
+
const term = deg === 0 ? '' + abs : deg === 1 ? abs + '*x' : abs + '*x^' + deg;
|
|
163
|
+
s += sign + term;
|
|
164
|
+
}
|
|
165
|
+
return s + ' = 0';
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
function doPolyRoots(args) {
|
|
169
|
+
const coeffs = args && args.coefficients;
|
|
170
|
+
if (!Array.isArray(coeffs) || coeffs.length < 2) throw { type: 'invalid_input', message: 'coefficients 必须是长度≥2 的数组(最高次系数在前)' };
|
|
171
|
+
for (const c of coeffs) if (typeof c !== 'number' || !isFinite(c)) throw { type: 'invalid_input', message: 'coefficients 须为有限数字' };
|
|
172
|
+
const eq = buildPolyEquation(coeffs);
|
|
173
|
+
const r = solve([eq], ['x'], 6, undefined, false, {});
|
|
174
|
+
return shapeResult(r);
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
function doVerify(args) {
|
|
178
|
+
const eq = args && args.equation;
|
|
179
|
+
if (typeof eq !== 'string' || !eq.includes('=')) throw { type: 'invalid_input', message: 'equation 须为含 "=" 的字符串' };
|
|
180
|
+
const cand = args.candidate;
|
|
181
|
+
let varNames, candPoint;
|
|
182
|
+
if (typeof cand === 'number') {
|
|
183
|
+
varNames = (args && Array.isArray(args.variables) && args.variables[0]) ? [args.variables[0]] : ['x'];
|
|
184
|
+
candPoint = [cand];
|
|
185
|
+
} else if (cand && typeof cand === 'object' && !Array.isArray(cand)) {
|
|
186
|
+
varNames = Object.keys(cand);
|
|
187
|
+
candPoint = varNames.map(function (v) { return cand[v]; });
|
|
188
|
+
} else if (Array.isArray(cand)) {
|
|
189
|
+
varNames = (args && Array.isArray(args.variables)) ? args.variables : [];
|
|
190
|
+
if (varNames.length !== cand.length) throw { type: 'invalid_input', message: 'candidate 数组长度须与 variables 一致' };
|
|
191
|
+
candPoint = cand;
|
|
192
|
+
} else {
|
|
193
|
+
throw { type: 'invalid_input', message: 'candidate 须为数字 / {变量:值} / [值...]' };
|
|
194
|
+
}
|
|
195
|
+
const margin = (args && typeof args.tolerance === 'number' && args.tolerance > 0) ? args.tolerance : 1e-3;
|
|
196
|
+
const domain = {};
|
|
197
|
+
varNames.forEach(function (v, i) { domain[v] = [candPoint[i] - margin, candPoint[i] + margin]; });
|
|
198
|
+
const r = solve([eq], varNames, 6, domain, false, {});
|
|
199
|
+
const shaped = shapeResult(r);
|
|
200
|
+
const matched = (r.solutions || []).find(function (s) {
|
|
201
|
+
return Array.isArray(s.values) && s.values.every(function (val, i) { return Math.abs(val - candPoint[i]) <= 1e-6; });
|
|
202
|
+
});
|
|
203
|
+
if (matched) {
|
|
204
|
+
return {
|
|
205
|
+
verdict: 'verified', isRoot: true, candidate: cand,
|
|
206
|
+
matchedRoot: { values: matched.values, tier: matched.tier, certified: !!matched.certified, cert: matched.cert || null,
|
|
207
|
+
text: varNames.map(function (vn, i) { return vn + '=' + fmt6(matched.values[i]); }).join(', ') },
|
|
208
|
+
reportId: shaped.reportId, certification: shaped.certification
|
|
209
|
+
};
|
|
210
|
+
}
|
|
211
|
+
let nearest = null;
|
|
212
|
+
try {
|
|
213
|
+
// refuted:在更宽域(默认 ±1e6)重算,给 Agent 全局最近的「真认证根」——
|
|
214
|
+
// 否则当 LLM 把根算偏(如猜 2.1、真根 2)时,窄邻域内无解会导致 nearest 为空,
|
|
215
|
+
// Agent 看不到正确值,verify 就失去了「纠正 LLM」的核心价值。
|
|
216
|
+
const rb = solve([eq], varNames, 6, undefined, false, {});
|
|
217
|
+
const solsB = (rb.solutions || []).filter(function (s) { return Array.isArray(s.values); });
|
|
218
|
+
if (solsB.length) {
|
|
219
|
+
let bestD = Infinity, bestS = null;
|
|
220
|
+
for (const s of solsB) { let d = 0; for (let i = 0; i < s.values.length; i++) d += (s.values[i] - candPoint[i]) * (s.values[i] - candPoint[i]); if (d < bestD) { bestD = d; bestS = s; } }
|
|
221
|
+
nearest = { values: bestS.values, tier: bestS.tier || null, certified: !!bestS.certified, cert: bestS.cert || null,
|
|
222
|
+
text: varNames.map(function (vn, i) { return vn + '=' + fmt6(bestS.values[i]); }).join(', ') };
|
|
223
|
+
}
|
|
224
|
+
} catch (_e) { /* 宽域重算失败不致命,nearest 保持 null */ }
|
|
225
|
+
return {
|
|
226
|
+
verdict: 'refuted_or_unverified', isRoot: false, candidate: cand,
|
|
227
|
+
message: '在候选点 ±' + margin + ' 邻域内未找到与之匹配的认证根;候选不是经验证的实根。' + (nearest ? '(全局最近认证根见 nearestCertifiedRoot)' : '(该方程在默认域内也无实根)'),
|
|
228
|
+
nearestCertifiedRoot: nearest, reportId: shaped.reportId
|
|
229
|
+
};
|
|
230
|
+
}
|
|
231
|
+
|
|
150
232
|
// ---- 工具定义 ----
|
|
151
233
|
const TOOLS = [
|
|
152
234
|
{
|
|
@@ -191,6 +273,32 @@ const TOOLS = [
|
|
|
191
273
|
},
|
|
192
274
|
required: ['message']
|
|
193
275
|
}
|
|
276
|
+
},
|
|
277
|
+
{
|
|
278
|
+
name: 'poly_roots',
|
|
279
|
+
description: '多项式全部实根,逐个 Krawczyk 认证(带严格误差盒)。输入系数「最高次在前」,如 [1,-2,-5,6] 表示 x³−2x²−5x+6。确定性、可复现、可证明正确;复数根不返回(本品只做实数)。给 AI Agent 当「可靠的多项式求根件」——不会再像通用 LLM 那样把根算错或半对。',
|
|
280
|
+
inputSchema: {
|
|
281
|
+
type: 'object',
|
|
282
|
+
properties: {
|
|
283
|
+
coefficients: { type: 'array', items: { type: 'number' }, description: '多项式系数,最高次在前。如 [1,-2,-5,6] 对应 x³−2x²−5x+6。' },
|
|
284
|
+
tolerance: { type: 'number', description: '根的判定容差(可选,默认内部精度)' }
|
|
285
|
+
},
|
|
286
|
+
required: ['coefficients']
|
|
287
|
+
}
|
|
288
|
+
},
|
|
289
|
+
{
|
|
290
|
+
name: 'verify',
|
|
291
|
+
description: '核验一个「声称的答案」到底对不对——这是「LLM 猜了 2.1、真根是精确 2」的检查。输入方程 + 候选值/点(数字,或 {变量:值},或按 variables 顺序的数组),本工具在候选点邻域内调用同一套认证内核:若找到与之匹配的认证根 → 返回 verified + 误差盒;若找不到 → 返回 refuted 并附上最近的认证根(让 Agent 立刻看到正确值)。确定性、非 LLM、结果可复现。',
|
|
292
|
+
inputSchema: {
|
|
293
|
+
type: 'object',
|
|
294
|
+
properties: {
|
|
295
|
+
equation: { type: 'string', description: '含 "=" 的方程,如 "x^2 = 4"。' },
|
|
296
|
+
candidate: { description: '声称的答案:数字(单变量,默认变量 x)、{变量:值}(多变量)、或按 variables 顺序的数组。', oneOf: [{ type: 'number' }, { type: 'object' }, { type: 'array' }] },
|
|
297
|
+
variables: { type: 'array', items: { type: 'string' }, description: '变量名(多变量或数组候选时必填),如 ["x","y"]。' },
|
|
298
|
+
tolerance: { type: 'number', description: '邻域半径(可选,默认 1e-3),在该邻域内寻找匹配的认证根。' }
|
|
299
|
+
},
|
|
300
|
+
required: ['equation', 'candidate']
|
|
301
|
+
}
|
|
194
302
|
}
|
|
195
303
|
];
|
|
196
304
|
|
|
@@ -237,6 +345,10 @@ function handle(msg) {
|
|
|
237
345
|
ts: new Date().toISOString(), message: msg_fb, context: args.context || null
|
|
238
346
|
}) + '\n');
|
|
239
347
|
result = { acknowledged: true, note: '反馈已记录(本地,不外传)' };
|
|
348
|
+
} else if (name === 'poly_roots') {
|
|
349
|
+
result = doPolyRoots(args);
|
|
350
|
+
} else if (name === 'verify') {
|
|
351
|
+
result = doVerify(args);
|
|
240
352
|
} else {
|
|
241
353
|
throw { type: 'unknown_tool', message: '未知工具: ' + name };
|
|
242
354
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "lingshu-solver",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.15",
|
|
4
4
|
"description": "灵数求解器 · 确定性实数方程组求解 MCP 工具(≤6变量):区间收缩 + Krawczyk 认证,离线零依赖零数据,诚实标记 truncated。本地 stdio 永久免费;另有常驻托管端点 https://hongchenlingjing.com/mcp(按次 ¥0.01/次,支持 honorPaid 免费放行)。",
|
|
5
5
|
"homepage": "https://genesis-plan.github.io/lingshu-solver/",
|
|
6
6
|
"repository": {
|