@ouro.bot/cli 0.1.0-alpha.887 → 0.1.0-alpha.888
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/changelog.json
CHANGED
|
@@ -1,6 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"_note": "This changelog is maintained as part of the PR/version-bump workflow. Agent-curated, not auto-generated. Agents read this file directly via read_file to understand what changed between versions.",
|
|
3
3
|
"versions": [
|
|
4
|
+
{
|
|
5
|
+
"version": "0.1.0-alpha.888",
|
|
6
|
+
"changes": [
|
|
7
|
+
"Answer gates (source grounding and brevity) now hold a plain-text reply as well as a settle answer, so a reply with no settle call can no longer name an unsourced cast or ignore a brevity request."
|
|
8
|
+
]
|
|
9
|
+
},
|
|
4
10
|
{
|
|
5
11
|
"version": "0.1.0-alpha.887",
|
|
6
12
|
"changes": [
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
<?xml version="1.0"?>
|
|
2
2
|
<Container version="2">
|
|
3
3
|
<Name>ouro-butler</Name>
|
|
4
|
-
<Repository>ghcr.io/ourostack/ouroboros-butler:0.1.0-alpha.
|
|
4
|
+
<Repository>ghcr.io/ourostack/ouroboros-butler:0.1.0-alpha.888</Repository>
|
|
5
5
|
<Registry>https://github.com/ourostack/ouroboros/pkgs/container/ouroboros-butler</Registry>
|
|
6
6
|
<Network>host</Network>
|
|
7
7
|
<Shell>sh</Shell>
|
package/dist/heart/core.js
CHANGED
|
@@ -1208,6 +1208,38 @@ async function runAgent(messages, callbacks, channel, signal, options) {
|
|
|
1208
1208
|
rejectedAttempt = [structuredClone(assistant)];
|
|
1209
1209
|
nextAttemptControls = controls;
|
|
1210
1210
|
};
|
|
1211
|
+
// Answer gates run only for agents that opt in (ToolContext.answerGates), on every reply the person would receive: a settle answer
|
|
1212
|
+
// and a plain-text reply with no tool call alike (alpha.886 replay: a plain-text reply skipped them and an invented cast went out).
|
|
1213
|
+
// A request-specific contract (options.requiredToolCalls) already validates its own terminal answer. Each gate has its own bounded
|
|
1214
|
+
// retry, and none spends the last provider iteration.
|
|
1215
|
+
const answerGateVerdict = (answer, intent) => {
|
|
1216
|
+
const gates = options?.requiredToolCalls ? undefined : options?.toolContext?.answerGates;
|
|
1217
|
+
const retriesLeft = providerIterations < stepBudget - 1;
|
|
1218
|
+
let groundingError = null;
|
|
1219
|
+
let unverifiedNames = null;
|
|
1220
|
+
const grounding = gates?.sourceGrounding ? (0, source_grounding_1.sourceGroundingFinding)({ answer, userText: userTexts(messages).join("\n"), latestUserText: latestUserMessageText(messages.slice(0, turnStartLength)), knownText: priorTurnsText(messages.slice(0, turnStartLength)), tools: turnToolRecords }) : null;
|
|
1221
|
+
if (grounding) {
|
|
1222
|
+
if (groundingRejections < ANSWER_GATE_MAX_REJECTIONS && retriesLeft) {
|
|
1223
|
+
groundingRejections += 1;
|
|
1224
|
+
groundingError = grounding.message;
|
|
1225
|
+
(0, runtime_1.emitNervesEvent)({ level: "warn", component: "engine", event: "engine.answer_gate_rejected", message: "answer named things from a work that the turn did not look up; sending the model back", meta: { gate: "source_grounding", rejection: groundingRejections, cap: ANSWER_GATE_MAX_REJECTIONS, lookupsRun: grounding.lookups } });
|
|
1226
|
+
}
|
|
1227
|
+
else {
|
|
1228
|
+
unverifiedNames = grounding.names;
|
|
1229
|
+
(0, runtime_1.emitNervesEvent)({ level: "warn", component: "engine", event: "engine.answer_gate_disclosed", message: "unsourced names survived the retries; delivering with a disclosure", meta: { gate: "source_grounding", names: grounding.names.length } });
|
|
1230
|
+
}
|
|
1231
|
+
}
|
|
1232
|
+
let brevityError = null;
|
|
1233
|
+
if (!groundingError && gates?.brevity && !options?.toolContext?.context?.isGroupChat && brevityRejections < ANSWER_GATE_MAX_REJECTIONS && retriesLeft
|
|
1234
|
+
&& (0, reply_style_1.briefStyleRequested)(userTexts(messages), (0, reply_style_1.savedCommunicationPreference)(options?.toolContext?.context?.friend))) {
|
|
1235
|
+
brevityError = (0, reply_style_1.briefStyleViolation)(answer, intent);
|
|
1236
|
+
if (brevityError) {
|
|
1237
|
+
brevityRejections += 1;
|
|
1238
|
+
(0, runtime_1.emitNervesEvent)({ level: "warn", component: "engine", event: "engine.answer_gate_rejected", message: "answer broke the person's brevity request; sending the model back", meta: { gate: "brevity", rejection: brevityRejections, cap: ANSWER_GATE_MAX_REJECTIONS } });
|
|
1239
|
+
}
|
|
1240
|
+
}
|
|
1241
|
+
return { error: groundingError ?? brevityError, unverifiedNames };
|
|
1242
|
+
};
|
|
1211
1243
|
const rejectToolBatch = (assistant, reasons) => {
|
|
1212
1244
|
rejectAttempt(assistant, assistant.tool_calls.map((call, index) => ({
|
|
1213
1245
|
role: "tool", tool_call_id: call.id, content: reasons[index],
|
|
@@ -1774,6 +1806,24 @@ async function runAgent(messages, callbacks, channel, signal, options) {
|
|
|
1774
1806
|
}]);
|
|
1775
1807
|
continue;
|
|
1776
1808
|
}
|
|
1809
|
+
// A plain-text reply reaches the person just as a settle answer does, so the answer gates hold it too.
|
|
1810
|
+
const textAnswer = isPrivateRuntimeChannel ? "" : stripThinkBlocksForViolationCheck(result.content).trim();
|
|
1811
|
+
const textVerdict = textAnswer ? answerGateVerdict(textAnswer) : null;
|
|
1812
|
+
if (textVerdict?.error) {
|
|
1813
|
+
streamCallbackBuffer?.discard();
|
|
1814
|
+
callbacks.onClearText?.();
|
|
1815
|
+
rejectAttempt(msg, [{ role: "user", content: textVerdict.error }]);
|
|
1816
|
+
continue;
|
|
1817
|
+
}
|
|
1818
|
+
if (textVerdict?.unverifiedNames) {
|
|
1819
|
+
const disclosed = (0, source_grounding_1.withUnverifiedDisclosure)(textAnswer, textVerdict.unverifiedNames);
|
|
1820
|
+
streamCallbackBuffer?.discard();
|
|
1821
|
+
callbacks.onClearText?.();
|
|
1822
|
+
callbacks.onTextChunk(disclosed);
|
|
1823
|
+
pushGenerated({ ...msg, content: disclosed });
|
|
1824
|
+
done = true;
|
|
1825
|
+
continue;
|
|
1826
|
+
}
|
|
1777
1827
|
// Legitimate text-only response, or cap reached — accept as-is.
|
|
1778
1828
|
await streamCallbackBuffer?.flush();
|
|
1779
1829
|
pushGenerated(msg);
|
|
@@ -1976,34 +2026,7 @@ async function runAgent(messages, callbacks, channel, signal, options) {
|
|
|
1976
2026
|
sawSettleContentMismatch = true;
|
|
1977
2027
|
(0, runtime_1.emitNervesEvent)({ level: "warn", component: "engine", event: "engine.settle_content_mismatch", message: "settle answer differs from the reply text written beside it; asking once for the reply as the answer", meta: { answerLength: deliveredAnswer.length, contentLength: msg.content.length } });
|
|
1978
2028
|
}
|
|
1979
|
-
|
|
1980
|
-
// already validates its own terminal answer. Each gate has its own bounded retry, and none spends the last provider iteration.
|
|
1981
|
-
const gates = options?.requiredToolCalls ? undefined : options?.toolContext?.answerGates;
|
|
1982
|
-
const retriesLeft = providerIterations < stepBudget - 1;
|
|
1983
|
-
let groundingError = null;
|
|
1984
|
-
let unverifiedNames = null;
|
|
1985
|
-
const grounding = gates?.sourceGrounding ? (0, source_grounding_1.sourceGroundingFinding)({ answer: deliveredAnswer, userText: userTexts(messages).join("\n"), latestUserText: latestUserMessageText(messages.slice(0, turnStartLength)), knownText: priorTurnsText(messages.slice(0, turnStartLength)), tools: turnToolRecords }) : null;
|
|
1986
|
-
if (grounding) {
|
|
1987
|
-
if (groundingRejections < ANSWER_GATE_MAX_REJECTIONS && retriesLeft) {
|
|
1988
|
-
groundingRejections += 1;
|
|
1989
|
-
groundingError = grounding.message;
|
|
1990
|
-
(0, runtime_1.emitNervesEvent)({ level: "warn", component: "engine", event: "engine.answer_gate_rejected", message: "settle answer named things from a work that the turn did not look up; sending the model back", meta: { gate: "source_grounding", rejection: groundingRejections, cap: ANSWER_GATE_MAX_REJECTIONS, lookupsRun: grounding.lookups } });
|
|
1991
|
-
}
|
|
1992
|
-
else {
|
|
1993
|
-
unverifiedNames = grounding.names;
|
|
1994
|
-
(0, runtime_1.emitNervesEvent)({ level: "warn", component: "engine", event: "engine.answer_gate_disclosed", message: "unsourced names survived the retries; delivering with a disclosure", meta: { gate: "source_grounding", names: grounding.names.length } });
|
|
1995
|
-
}
|
|
1996
|
-
}
|
|
1997
|
-
let brevityError = null;
|
|
1998
|
-
if (!groundingError && gates?.brevity && !options?.toolContext?.context?.isGroupChat && brevityRejections < ANSWER_GATE_MAX_REJECTIONS && retriesLeft
|
|
1999
|
-
&& (0, reply_style_1.briefStyleRequested)(userTexts(messages), (0, reply_style_1.savedCommunicationPreference)(options?.toolContext?.context?.friend))) {
|
|
2000
|
-
brevityError = (0, reply_style_1.briefStyleViolation)(deliveredAnswer, intent);
|
|
2001
|
-
if (brevityError) {
|
|
2002
|
-
brevityRejections += 1;
|
|
2003
|
-
(0, runtime_1.emitNervesEvent)({ level: "warn", component: "engine", event: "engine.answer_gate_rejected", message: "settle answer broke the person's brevity request; sending the model back", meta: { gate: "brevity", rejection: brevityRejections, cap: ANSWER_GATE_MAX_REJECTIONS } });
|
|
2004
|
-
}
|
|
2005
|
-
}
|
|
2006
|
-
const answerGateError = groundingError ?? brevityError;
|
|
2029
|
+
const { error: answerGateError, unverifiedNames } = answerGateVerdict(deliveredAnswer, intent);
|
|
2007
2030
|
const retryError = contentMismatch
|
|
2008
2031
|
?? answerGateError
|
|
2009
2032
|
?? privateReturnAckLeakError(deliveredAnswer, privateReturnHeldTokens)
|
package/npm-shrinkwrap.json
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ouro.bot/cli",
|
|
3
|
-
"version": "0.1.0-alpha.
|
|
3
|
+
"version": "0.1.0-alpha.888",
|
|
4
4
|
"lockfileVersion": 3,
|
|
5
5
|
"requires": true,
|
|
6
6
|
"packages": {
|
|
7
7
|
"": {
|
|
8
8
|
"name": "@ouro.bot/cli",
|
|
9
|
-
"version": "0.1.0-alpha.
|
|
9
|
+
"version": "0.1.0-alpha.888",
|
|
10
10
|
"dependencies": {
|
|
11
11
|
"@anthropic-ai/sdk": "^0.78.0",
|
|
12
12
|
"@azure/identity": "^4.13.0",
|