@octocodeai/freellama-mcp-server 0.9.0 → 0.10.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/README.md +42 -0
- package/dist/index.js +558 -314
- package/dist/research/bash-agent.js +21 -12
- package/dist/research/coder-agent.js +21 -12
- package/dist/research/github-agent.js +22 -13
- package/dist/research/octocode-agent.js +21 -12
- package/docs/MODEL_SELECTION.md +1 -1
- package/package.json +6 -6
|
@@ -1690,12 +1690,18 @@ function evidencePaths(observations, workspace, limit = 10) {
|
|
|
1690
1690
|
}
|
|
1691
1691
|
return found;
|
|
1692
1692
|
}
|
|
1693
|
-
function
|
|
1694
|
-
return
|
|
1693
|
+
function unseenPaths(answer, observations) {
|
|
1694
|
+
return pathsIn(answer).filter((candidate) => !observations.some((text) => text.includes(candidate)));
|
|
1695
1695
|
}
|
|
1696
|
-
function
|
|
1696
|
+
function observedPaths(observations, limit = 10) {
|
|
1697
|
+
return [...new Set(observations.flatMap((text) => pathsIn(text)))].slice(0, limit);
|
|
1698
|
+
}
|
|
1699
|
+
function groundingRepairNotice(missing, evidence, observed = false) {
|
|
1700
|
+
return `These paths in your answer ${observed ? "did not appear in any tool result" : "do not exist in the workspace"}: ${missing.join(", ")}. ` + (evidence.length > 0 ? `Paths your own commands returned: ${evidence.join(", ")}. ` : "") + `Return a finish action again that cites only paths ${observed ? "your tool results showed" : "that exist"}; if the evidence does not establish the answer, say so.`;
|
|
1701
|
+
}
|
|
1702
|
+
function groundingNote(missing, observed = false) {
|
|
1697
1703
|
return `
|
|
1698
|
-
[freellama: cited path(s) not found in the workspace: ${missing.join(", ")}; treat this answer as unverified]`;
|
|
1704
|
+
[freellama: cited path(s) ${observed ? "not seen in any tool result" : "not found in the workspace"}: ${missing.join(", ")}; treat this answer as unverified]`;
|
|
1699
1705
|
}
|
|
1700
1706
|
function toolErrorHint(message) {
|
|
1701
1707
|
if (/rg: unrecognized flag --(?:exclude-dir|include)/.test(message)) {
|
|
@@ -1886,6 +1892,9 @@ async function runLoop(spec, hooks, env, inputs) {
|
|
|
1886
1892
|
let groundingRepaired = false;
|
|
1887
1893
|
let sourceRepaired = false;
|
|
1888
1894
|
const seenOutputs = [];
|
|
1895
|
+
const observed = spec.grounding === "observed";
|
|
1896
|
+
const ungrounded = (text) => observed ? unseenPaths(text, seenOutputs) : missingPaths(text, root);
|
|
1897
|
+
const evidenceFor = () => observed ? observedPaths(seenOutputs) : evidencePaths(seenOutputs, root);
|
|
1889
1898
|
for (let turn = 0; turn < runtime.max_turns; turn += 1) {
|
|
1890
1899
|
const at = { turn: turn + 1, maxTurns: runtime.max_turns };
|
|
1891
1900
|
phaseAt = at;
|
|
@@ -1937,20 +1946,20 @@ async function runLoop(spec, hooks, env, inputs) {
|
|
|
1937
1946
|
}
|
|
1938
1947
|
if (action.action === "finish") {
|
|
1939
1948
|
const proposed = trimSpace(String(action.answer ?? ""));
|
|
1940
|
-
const missing =
|
|
1949
|
+
const missing = ungrounded(proposed);
|
|
1941
1950
|
if (missing.length > 0 && !groundingRepaired) {
|
|
1942
1951
|
groundingRepaired = true;
|
|
1943
1952
|
progress?.({ event: "repair", ...at });
|
|
1944
1953
|
messages.push({ role: "assistant", content: echo(action) });
|
|
1945
|
-
messages.push({ role: "user", content: groundingRepairNotice(missing,
|
|
1954
|
+
messages.push({ role: "user", content: groundingRepairNotice(missing, evidenceFor(), observed) });
|
|
1946
1955
|
if (!refit()) {
|
|
1947
|
-
answer = proposed + groundingNote(missing);
|
|
1956
|
+
answer = proposed + groundingNote(missing, observed);
|
|
1948
1957
|
exhausted = false;
|
|
1949
1958
|
break;
|
|
1950
1959
|
}
|
|
1951
1960
|
continue;
|
|
1952
1961
|
}
|
|
1953
|
-
const evidence = spec.requireSource !== false && missing.length === 0 && !sourceRepaired && pathsIn(proposed).length === 0 ?
|
|
1962
|
+
const evidence = spec.requireSource !== false && missing.length === 0 && !sourceRepaired && pathsIn(proposed).length === 0 ? evidenceFor() : [];
|
|
1954
1963
|
if (evidence.length > 0) {
|
|
1955
1964
|
sourceRepaired = true;
|
|
1956
1965
|
progress?.({ event: "repair", ...at });
|
|
@@ -1964,7 +1973,7 @@ async function runLoop(spec, hooks, env, inputs) {
|
|
|
1964
1973
|
continue;
|
|
1965
1974
|
}
|
|
1966
1975
|
progress?.({ event: "finish", ...at });
|
|
1967
|
-
answer = missing.length > 0 ? proposed + groundingNote(missing) : proposed;
|
|
1976
|
+
answer = missing.length > 0 ? proposed + groundingNote(missing, observed) : proposed;
|
|
1968
1977
|
exhausted = false;
|
|
1969
1978
|
break;
|
|
1970
1979
|
}
|
|
@@ -2020,8 +2029,8 @@ async function runLoop(spec, hooks, env, inputs) {
|
|
|
2020
2029
|
const finalAction = spec.parseAction(content(response));
|
|
2021
2030
|
if (finalAction.action !== "finish") throw new ValidationError("forced final response was not finish");
|
|
2022
2031
|
answer = trimSpace(String(finalAction.answer ?? ""));
|
|
2023
|
-
const missing =
|
|
2024
|
-
if (missing.length > 0) answer += groundingNote(missing);
|
|
2032
|
+
const missing = ungrounded(answer);
|
|
2033
|
+
if (missing.length > 0) answer += groundingNote(missing, observed);
|
|
2025
2034
|
} catch (error) {
|
|
2026
2035
|
if (!isTransportError(error) && !isValidationError(error)) throw error;
|
|
2027
2036
|
let diagnostic;
|
|
@@ -2595,7 +2604,7 @@ Verify: local answers are candidates. Each run_task result ends with check: line
|
|
|
2595
2604
|
|
|
2596
2605
|
Coding: the answer is SEARCH/REPLACE blocks. ${APPLY_EDITS}
|
|
2597
2606
|
|
|
2598
|
-
Hand a result on: saveAs:"<name>" writes the answer to handoffs/<name>.md and returns handoff_file; a later run_task reads it with files:[handoff_file].
|
|
2607
|
+
Hand a result on: saveAs:"<name>" writes the answer to handoffs/<name>.md and returns handoff_file; a later run_task reads it with files:[handoff_file]. Answers over 8,000 characters come back as a summary with check: lines and an output_file holding the whole answer; output:"inline" returns the whole text, outputPath:"<path>" writes (or replaces) that file inside your project.
|
|
2599
2608
|
|
|
2600
2609
|
Approval: pull a model only after the user approves one exact tag and its size (ollama_pull approvedSizeBytes). Unload only a model you warmed or the user named; delete only a tag the user names. A memory refusal names what holds memory: tell the user and never stop their processes.`;
|
|
2601
2610
|
|
|
@@ -1695,12 +1695,18 @@ function evidencePaths(observations, workspace, limit = 10) {
|
|
|
1695
1695
|
}
|
|
1696
1696
|
return found;
|
|
1697
1697
|
}
|
|
1698
|
-
function
|
|
1699
|
-
return
|
|
1698
|
+
function unseenPaths(answer, observations) {
|
|
1699
|
+
return pathsIn(answer).filter((candidate) => !observations.some((text) => text.includes(candidate)));
|
|
1700
1700
|
}
|
|
1701
|
-
function
|
|
1701
|
+
function observedPaths(observations, limit = 10) {
|
|
1702
|
+
return [...new Set(observations.flatMap((text) => pathsIn(text)))].slice(0, limit);
|
|
1703
|
+
}
|
|
1704
|
+
function groundingRepairNotice(missing, evidence, observed = false) {
|
|
1705
|
+
return `These paths in your answer ${observed ? "did not appear in any tool result" : "do not exist in the workspace"}: ${missing.join(", ")}. ` + (evidence.length > 0 ? `Paths your own commands returned: ${evidence.join(", ")}. ` : "") + `Return a finish action again that cites only paths ${observed ? "your tool results showed" : "that exist"}; if the evidence does not establish the answer, say so.`;
|
|
1706
|
+
}
|
|
1707
|
+
function groundingNote(missing, observed = false) {
|
|
1702
1708
|
return `
|
|
1703
|
-
[freellama: cited path(s) not found in the workspace: ${missing.join(", ")}; treat this answer as unverified]`;
|
|
1709
|
+
[freellama: cited path(s) ${observed ? "not seen in any tool result" : "not found in the workspace"}: ${missing.join(", ")}; treat this answer as unverified]`;
|
|
1704
1710
|
}
|
|
1705
1711
|
function toolErrorHint(message) {
|
|
1706
1712
|
if (/rg: unrecognized flag --(?:exclude-dir|include)/.test(message)) {
|
|
@@ -1891,6 +1897,9 @@ async function runLoop(spec, hooks, env, inputs) {
|
|
|
1891
1897
|
let groundingRepaired = false;
|
|
1892
1898
|
let sourceRepaired = false;
|
|
1893
1899
|
const seenOutputs = [];
|
|
1900
|
+
const observed = spec.grounding === "observed";
|
|
1901
|
+
const ungrounded = (text) => observed ? unseenPaths(text, seenOutputs) : missingPaths(text, root);
|
|
1902
|
+
const evidenceFor = () => observed ? observedPaths(seenOutputs) : evidencePaths(seenOutputs, root);
|
|
1894
1903
|
for (let turn = 0; turn < runtime.max_turns; turn += 1) {
|
|
1895
1904
|
const at = { turn: turn + 1, maxTurns: runtime.max_turns };
|
|
1896
1905
|
phaseAt = at;
|
|
@@ -1942,20 +1951,20 @@ async function runLoop(spec, hooks, env, inputs) {
|
|
|
1942
1951
|
}
|
|
1943
1952
|
if (action.action === "finish") {
|
|
1944
1953
|
const proposed = trimSpace(String(action.answer ?? ""));
|
|
1945
|
-
const missing =
|
|
1954
|
+
const missing = ungrounded(proposed);
|
|
1946
1955
|
if (missing.length > 0 && !groundingRepaired) {
|
|
1947
1956
|
groundingRepaired = true;
|
|
1948
1957
|
progress?.({ event: "repair", ...at });
|
|
1949
1958
|
messages.push({ role: "assistant", content: echo(action) });
|
|
1950
|
-
messages.push({ role: "user", content: groundingRepairNotice(missing,
|
|
1959
|
+
messages.push({ role: "user", content: groundingRepairNotice(missing, evidenceFor(), observed) });
|
|
1951
1960
|
if (!refit()) {
|
|
1952
|
-
answer = proposed + groundingNote(missing);
|
|
1961
|
+
answer = proposed + groundingNote(missing, observed);
|
|
1953
1962
|
exhausted = false;
|
|
1954
1963
|
break;
|
|
1955
1964
|
}
|
|
1956
1965
|
continue;
|
|
1957
1966
|
}
|
|
1958
|
-
const evidence = spec.requireSource !== false && missing.length === 0 && !sourceRepaired && pathsIn(proposed).length === 0 ?
|
|
1967
|
+
const evidence = spec.requireSource !== false && missing.length === 0 && !sourceRepaired && pathsIn(proposed).length === 0 ? evidenceFor() : [];
|
|
1959
1968
|
if (evidence.length > 0) {
|
|
1960
1969
|
sourceRepaired = true;
|
|
1961
1970
|
progress?.({ event: "repair", ...at });
|
|
@@ -1969,7 +1978,7 @@ async function runLoop(spec, hooks, env, inputs) {
|
|
|
1969
1978
|
continue;
|
|
1970
1979
|
}
|
|
1971
1980
|
progress?.({ event: "finish", ...at });
|
|
1972
|
-
answer = missing.length > 0 ? proposed + groundingNote(missing) : proposed;
|
|
1981
|
+
answer = missing.length > 0 ? proposed + groundingNote(missing, observed) : proposed;
|
|
1973
1982
|
exhausted = false;
|
|
1974
1983
|
break;
|
|
1975
1984
|
}
|
|
@@ -2025,8 +2034,8 @@ async function runLoop(spec, hooks, env, inputs) {
|
|
|
2025
2034
|
const finalAction = spec.parseAction(content(response));
|
|
2026
2035
|
if (finalAction.action !== "finish") throw new ValidationError("forced final response was not finish");
|
|
2027
2036
|
answer = trimSpace(String(finalAction.answer ?? ""));
|
|
2028
|
-
const missing =
|
|
2029
|
-
if (missing.length > 0) answer += groundingNote(missing);
|
|
2037
|
+
const missing = ungrounded(answer);
|
|
2038
|
+
if (missing.length > 0) answer += groundingNote(missing, observed);
|
|
2030
2039
|
} catch (error) {
|
|
2031
2040
|
if (!isTransportError(error) && !isValidationError(error)) throw error;
|
|
2032
2041
|
let diagnostic;
|
|
@@ -4281,7 +4290,7 @@ Verify: local answers are candidates. Each run_task result ends with check: line
|
|
|
4281
4290
|
|
|
4282
4291
|
Coding: the answer is SEARCH/REPLACE blocks. ${APPLY_EDITS}
|
|
4283
4292
|
|
|
4284
|
-
Hand a result on: saveAs:"<name>" writes the answer to handoffs/<name>.md and returns handoff_file; a later run_task reads it with files:[handoff_file].
|
|
4293
|
+
Hand a result on: saveAs:"<name>" writes the answer to handoffs/<name>.md and returns handoff_file; a later run_task reads it with files:[handoff_file]. Answers over 8,000 characters come back as a summary with check: lines and an output_file holding the whole answer; output:"inline" returns the whole text, outputPath:"<path>" writes (or replaces) that file inside your project.
|
|
4285
4294
|
|
|
4286
4295
|
Approval: pull a model only after the user approves one exact tag and its size (ollama_pull approvedSizeBytes). Unload only a model you warmed or the user named; delete only a tag the user names. A memory refusal names what holds memory: tell the user and never stop their processes.`;
|
|
4287
4296
|
|
|
@@ -1653,12 +1653,18 @@ function evidencePaths(observations, workspace, limit = 10) {
|
|
|
1653
1653
|
}
|
|
1654
1654
|
return found;
|
|
1655
1655
|
}
|
|
1656
|
-
function
|
|
1657
|
-
return
|
|
1656
|
+
function unseenPaths(answer, observations) {
|
|
1657
|
+
return pathsIn(answer).filter((candidate) => !observations.some((text) => text.includes(candidate)));
|
|
1658
1658
|
}
|
|
1659
|
-
function
|
|
1659
|
+
function observedPaths(observations, limit = 10) {
|
|
1660
|
+
return [...new Set(observations.flatMap((text) => pathsIn(text)))].slice(0, limit);
|
|
1661
|
+
}
|
|
1662
|
+
function groundingRepairNotice(missing, evidence, observed = false) {
|
|
1663
|
+
return `These paths in your answer ${observed ? "did not appear in any tool result" : "do not exist in the workspace"}: ${missing.join(", ")}. ` + (evidence.length > 0 ? `Paths your own commands returned: ${evidence.join(", ")}. ` : "") + `Return a finish action again that cites only paths ${observed ? "your tool results showed" : "that exist"}; if the evidence does not establish the answer, say so.`;
|
|
1664
|
+
}
|
|
1665
|
+
function groundingNote(missing, observed = false) {
|
|
1660
1666
|
return `
|
|
1661
|
-
[freellama: cited path(s) not found in the workspace: ${missing.join(", ")}; treat this answer as unverified]`;
|
|
1667
|
+
[freellama: cited path(s) ${observed ? "not seen in any tool result" : "not found in the workspace"}: ${missing.join(", ")}; treat this answer as unverified]`;
|
|
1662
1668
|
}
|
|
1663
1669
|
function toolErrorHint(message) {
|
|
1664
1670
|
if (/rg: unrecognized flag --(?:exclude-dir|include)/.test(message)) {
|
|
@@ -1849,6 +1855,9 @@ async function runLoop(spec, hooks, env, inputs) {
|
|
|
1849
1855
|
let groundingRepaired = false;
|
|
1850
1856
|
let sourceRepaired = false;
|
|
1851
1857
|
const seenOutputs = [];
|
|
1858
|
+
const observed = spec.grounding === "observed";
|
|
1859
|
+
const ungrounded = (text) => observed ? unseenPaths(text, seenOutputs) : missingPaths(text, root);
|
|
1860
|
+
const evidenceFor = () => observed ? observedPaths(seenOutputs) : evidencePaths(seenOutputs, root);
|
|
1852
1861
|
for (let turn = 0; turn < runtime.max_turns; turn += 1) {
|
|
1853
1862
|
const at = { turn: turn + 1, maxTurns: runtime.max_turns };
|
|
1854
1863
|
phaseAt = at;
|
|
@@ -1900,20 +1909,20 @@ async function runLoop(spec, hooks, env, inputs) {
|
|
|
1900
1909
|
}
|
|
1901
1910
|
if (action.action === "finish") {
|
|
1902
1911
|
const proposed = trimSpace(String(action.answer ?? ""));
|
|
1903
|
-
const missing =
|
|
1912
|
+
const missing = ungrounded(proposed);
|
|
1904
1913
|
if (missing.length > 0 && !groundingRepaired) {
|
|
1905
1914
|
groundingRepaired = true;
|
|
1906
1915
|
progress?.({ event: "repair", ...at });
|
|
1907
1916
|
messages.push({ role: "assistant", content: echo(action) });
|
|
1908
|
-
messages.push({ role: "user", content: groundingRepairNotice(missing,
|
|
1917
|
+
messages.push({ role: "user", content: groundingRepairNotice(missing, evidenceFor(), observed) });
|
|
1909
1918
|
if (!refit()) {
|
|
1910
|
-
answer = proposed + groundingNote(missing);
|
|
1919
|
+
answer = proposed + groundingNote(missing, observed);
|
|
1911
1920
|
exhausted = false;
|
|
1912
1921
|
break;
|
|
1913
1922
|
}
|
|
1914
1923
|
continue;
|
|
1915
1924
|
}
|
|
1916
|
-
const evidence = spec.requireSource !== false && missing.length === 0 && !sourceRepaired && pathsIn(proposed).length === 0 ?
|
|
1925
|
+
const evidence = spec.requireSource !== false && missing.length === 0 && !sourceRepaired && pathsIn(proposed).length === 0 ? evidenceFor() : [];
|
|
1917
1926
|
if (evidence.length > 0) {
|
|
1918
1927
|
sourceRepaired = true;
|
|
1919
1928
|
progress?.({ event: "repair", ...at });
|
|
@@ -1927,7 +1936,7 @@ async function runLoop(spec, hooks, env, inputs) {
|
|
|
1927
1936
|
continue;
|
|
1928
1937
|
}
|
|
1929
1938
|
progress?.({ event: "finish", ...at });
|
|
1930
|
-
answer = missing.length > 0 ? proposed + groundingNote(missing) : proposed;
|
|
1939
|
+
answer = missing.length > 0 ? proposed + groundingNote(missing, observed) : proposed;
|
|
1931
1940
|
exhausted = false;
|
|
1932
1941
|
break;
|
|
1933
1942
|
}
|
|
@@ -1983,8 +1992,8 @@ async function runLoop(spec, hooks, env, inputs) {
|
|
|
1983
1992
|
const finalAction = spec.parseAction(content(response));
|
|
1984
1993
|
if (finalAction.action !== "finish") throw new ValidationError("forced final response was not finish");
|
|
1985
1994
|
answer = trimSpace(String(finalAction.answer ?? ""));
|
|
1986
|
-
const missing =
|
|
1987
|
-
if (missing.length > 0) answer += groundingNote(missing);
|
|
1995
|
+
const missing = ungrounded(answer);
|
|
1996
|
+
if (missing.length > 0) answer += groundingNote(missing, observed);
|
|
1988
1997
|
} catch (error) {
|
|
1989
1998
|
if (!isTransportError(error) && !isValidationError(error)) throw error;
|
|
1990
1999
|
let diagnostic;
|
|
@@ -2681,7 +2690,7 @@ Verify: local answers are candidates. Each run_task result ends with check: line
|
|
|
2681
2690
|
|
|
2682
2691
|
Coding: the answer is SEARCH/REPLACE blocks. ${APPLY_EDITS}
|
|
2683
2692
|
|
|
2684
|
-
Hand a result on: saveAs:"<name>" writes the answer to handoffs/<name>.md and returns handoff_file; a later run_task reads it with files:[handoff_file].
|
|
2693
|
+
Hand a result on: saveAs:"<name>" writes the answer to handoffs/<name>.md and returns handoff_file; a later run_task reads it with files:[handoff_file]. Answers over 8,000 characters come back as a summary with check: lines and an output_file holding the whole answer; output:"inline" returns the whole text, outputPath:"<path>" writes (or replaces) that file inside your project.
|
|
2685
2694
|
|
|
2686
2695
|
Approval: pull a model only after the user approves one exact tag and its size (ollama_pull approvedSizeBytes). Unload only a model you warmed or the user named; delete only a tag the user names. A memory refusal names what holds memory: tell the user and never stop their processes.`;
|
|
2687
2696
|
|
|
@@ -2919,5 +2928,5 @@ if (isEntry(import.meta.url, "octocode-agent")) {
|
|
|
2919
2928
|
|
|
2920
2929
|
// src/research/github-agent.ts
|
|
2921
2930
|
if (isEntry(import.meta.url, "github-agent")) {
|
|
2922
|
-
process.exitCode = await runAdapter(GITHUB_ADAPTER);
|
|
2931
|
+
process.exitCode = await runAdapter({ ...GITHUB_ADAPTER, grounding: "observed" });
|
|
2923
2932
|
}
|
|
@@ -1658,12 +1658,18 @@ function evidencePaths(observations, workspace, limit = 10) {
|
|
|
1658
1658
|
}
|
|
1659
1659
|
return found;
|
|
1660
1660
|
}
|
|
1661
|
-
function
|
|
1662
|
-
return
|
|
1661
|
+
function unseenPaths(answer, observations) {
|
|
1662
|
+
return pathsIn(answer).filter((candidate) => !observations.some((text) => text.includes(candidate)));
|
|
1663
1663
|
}
|
|
1664
|
-
function
|
|
1664
|
+
function observedPaths(observations, limit = 10) {
|
|
1665
|
+
return [...new Set(observations.flatMap((text) => pathsIn(text)))].slice(0, limit);
|
|
1666
|
+
}
|
|
1667
|
+
function groundingRepairNotice(missing, evidence, observed = false) {
|
|
1668
|
+
return `These paths in your answer ${observed ? "did not appear in any tool result" : "do not exist in the workspace"}: ${missing.join(", ")}. ` + (evidence.length > 0 ? `Paths your own commands returned: ${evidence.join(", ")}. ` : "") + `Return a finish action again that cites only paths ${observed ? "your tool results showed" : "that exist"}; if the evidence does not establish the answer, say so.`;
|
|
1669
|
+
}
|
|
1670
|
+
function groundingNote(missing, observed = false) {
|
|
1665
1671
|
return `
|
|
1666
|
-
[freellama: cited path(s) not found in the workspace: ${missing.join(", ")}; treat this answer as unverified]`;
|
|
1672
|
+
[freellama: cited path(s) ${observed ? "not seen in any tool result" : "not found in the workspace"}: ${missing.join(", ")}; treat this answer as unverified]`;
|
|
1667
1673
|
}
|
|
1668
1674
|
function toolErrorHint(message) {
|
|
1669
1675
|
if (/rg: unrecognized flag --(?:exclude-dir|include)/.test(message)) {
|
|
@@ -1854,6 +1860,9 @@ async function runLoop(spec, hooks, env, inputs) {
|
|
|
1854
1860
|
let groundingRepaired = false;
|
|
1855
1861
|
let sourceRepaired = false;
|
|
1856
1862
|
const seenOutputs = [];
|
|
1863
|
+
const observed = spec.grounding === "observed";
|
|
1864
|
+
const ungrounded = (text) => observed ? unseenPaths(text, seenOutputs) : missingPaths(text, root);
|
|
1865
|
+
const evidenceFor = () => observed ? observedPaths(seenOutputs) : evidencePaths(seenOutputs, root);
|
|
1857
1866
|
for (let turn = 0; turn < runtime.max_turns; turn += 1) {
|
|
1858
1867
|
const at = { turn: turn + 1, maxTurns: runtime.max_turns };
|
|
1859
1868
|
phaseAt = at;
|
|
@@ -1905,20 +1914,20 @@ async function runLoop(spec, hooks, env, inputs) {
|
|
|
1905
1914
|
}
|
|
1906
1915
|
if (action.action === "finish") {
|
|
1907
1916
|
const proposed = trimSpace(String(action.answer ?? ""));
|
|
1908
|
-
const missing =
|
|
1917
|
+
const missing = ungrounded(proposed);
|
|
1909
1918
|
if (missing.length > 0 && !groundingRepaired) {
|
|
1910
1919
|
groundingRepaired = true;
|
|
1911
1920
|
progress?.({ event: "repair", ...at });
|
|
1912
1921
|
messages.push({ role: "assistant", content: echo(action) });
|
|
1913
|
-
messages.push({ role: "user", content: groundingRepairNotice(missing,
|
|
1922
|
+
messages.push({ role: "user", content: groundingRepairNotice(missing, evidenceFor(), observed) });
|
|
1914
1923
|
if (!refit()) {
|
|
1915
|
-
answer = proposed + groundingNote(missing);
|
|
1924
|
+
answer = proposed + groundingNote(missing, observed);
|
|
1916
1925
|
exhausted = false;
|
|
1917
1926
|
break;
|
|
1918
1927
|
}
|
|
1919
1928
|
continue;
|
|
1920
1929
|
}
|
|
1921
|
-
const evidence = spec.requireSource !== false && missing.length === 0 && !sourceRepaired && pathsIn(proposed).length === 0 ?
|
|
1930
|
+
const evidence = spec.requireSource !== false && missing.length === 0 && !sourceRepaired && pathsIn(proposed).length === 0 ? evidenceFor() : [];
|
|
1922
1931
|
if (evidence.length > 0) {
|
|
1923
1932
|
sourceRepaired = true;
|
|
1924
1933
|
progress?.({ event: "repair", ...at });
|
|
@@ -1932,7 +1941,7 @@ async function runLoop(spec, hooks, env, inputs) {
|
|
|
1932
1941
|
continue;
|
|
1933
1942
|
}
|
|
1934
1943
|
progress?.({ event: "finish", ...at });
|
|
1935
|
-
answer = missing.length > 0 ? proposed + groundingNote(missing) : proposed;
|
|
1944
|
+
answer = missing.length > 0 ? proposed + groundingNote(missing, observed) : proposed;
|
|
1936
1945
|
exhausted = false;
|
|
1937
1946
|
break;
|
|
1938
1947
|
}
|
|
@@ -1988,8 +1997,8 @@ async function runLoop(spec, hooks, env, inputs) {
|
|
|
1988
1997
|
const finalAction = spec.parseAction(content(response));
|
|
1989
1998
|
if (finalAction.action !== "finish") throw new ValidationError("forced final response was not finish");
|
|
1990
1999
|
answer = trimSpace(String(finalAction.answer ?? ""));
|
|
1991
|
-
const missing =
|
|
1992
|
-
if (missing.length > 0) answer += groundingNote(missing);
|
|
2000
|
+
const missing = ungrounded(answer);
|
|
2001
|
+
if (missing.length > 0) answer += groundingNote(missing, observed);
|
|
1993
2002
|
} catch (error) {
|
|
1994
2003
|
if (!isTransportError(error) && !isValidationError(error)) throw error;
|
|
1995
2004
|
let diagnostic;
|
|
@@ -2681,7 +2690,7 @@ Verify: local answers are candidates. Each run_task result ends with check: line
|
|
|
2681
2690
|
|
|
2682
2691
|
Coding: the answer is SEARCH/REPLACE blocks. ${APPLY_EDITS}
|
|
2683
2692
|
|
|
2684
|
-
Hand a result on: saveAs:"<name>" writes the answer to handoffs/<name>.md and returns handoff_file; a later run_task reads it with files:[handoff_file].
|
|
2693
|
+
Hand a result on: saveAs:"<name>" writes the answer to handoffs/<name>.md and returns handoff_file; a later run_task reads it with files:[handoff_file]. Answers over 8,000 characters come back as a summary with check: lines and an output_file holding the whole answer; output:"inline" returns the whole text, outputPath:"<path>" writes (or replaces) that file inside your project.
|
|
2685
2694
|
|
|
2686
2695
|
Approval: pull a model only after the user approves one exact tag and its size (ollama_pull approvedSizeBytes). Unload only a model you warmed or the user named; delete only a tag the user names. A memory refusal names what holds memory: tell the user and never stop their processes.`;
|
|
2687
2696
|
|
package/docs/MODEL_SELECTION.md
CHANGED
|
@@ -192,7 +192,7 @@ command reports the core catalog and does not expose these enrichment flags.
|
|
|
192
192
|
|---|---|---|---|
|
|
193
193
|
| `includeLibrary` | `installed`, `detail` | `false` | Requests public metadata; the default makes no website calls |
|
|
194
194
|
| `includeReadme` | Library step 2, or `detail` with `includeLibrary:true` | `false` | Returns the README text with its format |
|
|
195
|
-
| `includeVerbose` | `detail` | `false` |
|
|
195
|
+
| `includeVerbose` | `installed`, `resident`, `detail` | `false` | `installed`/`resident`: full per-model records (benchmark, policy rank, execution observation, thinking, context defaults) instead of the slim set; `detail`: Ollama's license and Modelfile fields, independently of README enrichment |
|
|
196
196
|
| `limit`, `cursor` | `raw`, library tag listings; `limit` also applies to library search | Tag/raw page size 20; search limit 10; maximum 50 | Pages large lists; the tag cursor rejects a changed tag list |
|
|
197
197
|
| `query`, `capabilities`, `order`, `source` | Library search | Popular order, both sources | Filter by capability word (such as `decision`), order by `popular` or `newest`, or limit to `ollama` or `huggingface` |
|
|
198
198
|
| `ollamaEndpoint` | Direct Ollama views and library inventory reads | Configured Ollama endpoint | Chooses the Ollama instance; enriched managed inventory uses each model's assigned backend |
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@octocodeai/freellama-mcp-server",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.10.0",
|
|
4
4
|
"description": "MCP server exposing FreeLlama core as tools, via native NAPI bindings into packages/rust-core.",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -50,11 +50,11 @@
|
|
|
50
50
|
"zod": "^4.6.7"
|
|
51
51
|
},
|
|
52
52
|
"optionalDependencies": {
|
|
53
|
-
"@octocodeai/freellama-native-darwin-arm64": "0.
|
|
54
|
-
"@octocodeai/freellama-native-linux-arm64-gnu": "0.
|
|
55
|
-
"@octocodeai/freellama-native-linux-x64-gnu": "0.
|
|
56
|
-
"@octocodeai/freellama-native-win32-arm64-msvc": "0.
|
|
57
|
-
"@octocodeai/freellama-native-win32-x64-msvc": "0.
|
|
53
|
+
"@octocodeai/freellama-native-darwin-arm64": "0.10.0",
|
|
54
|
+
"@octocodeai/freellama-native-linux-arm64-gnu": "0.10.0",
|
|
55
|
+
"@octocodeai/freellama-native-linux-x64-gnu": "0.10.0",
|
|
56
|
+
"@octocodeai/freellama-native-win32-arm64-msvc": "0.10.0",
|
|
57
|
+
"@octocodeai/freellama-native-win32-x64-msvc": "0.10.0"
|
|
58
58
|
},
|
|
59
59
|
"author": "Guy Bary",
|
|
60
60
|
"license": "Apache-2.0 OR MIT",
|