metheus-governance-mcp-cli 0.2.203 → 0.2.205
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/cli.mjs +66 -22
- package/lib/local-ai-adapters.mjs +5 -4
- package/lib/runner-orchestration.mjs +70 -12
- package/lib/selftest-runner-scenarios.mjs +239 -0
- package/package.json +1 -1
package/cli.mjs
CHANGED
|
@@ -184,6 +184,7 @@ import {
|
|
|
184
184
|
} from "./lib/runner-execution.mjs";
|
|
185
185
|
import {
|
|
186
186
|
processRunnerSelectedRecord,
|
|
187
|
+
resolveHumanIntentContext,
|
|
187
188
|
resolveRunnerResponderAdjudication,
|
|
188
189
|
resolveRunnerStartupLoopAdjudication,
|
|
189
190
|
selectRunnerPendingWork,
|
|
@@ -2986,6 +2987,7 @@ async function claimRunnerRequestForHumanComment({
|
|
|
2986
2987
|
selectedRecord,
|
|
2987
2988
|
selectedBotUsernames = [],
|
|
2988
2989
|
normalizedIntent = "",
|
|
2990
|
+
sharedHumanIntent = null,
|
|
2989
2991
|
runtime = null,
|
|
2990
2992
|
archiveThreadID = "",
|
|
2991
2993
|
}) {
|
|
@@ -3039,6 +3041,7 @@ async function claimRunnerRequestForHumanComment({
|
|
|
3039
3041
|
}
|
|
3040
3042
|
const requests = normalizeBotRunnerRequests(stateForClaim.requests);
|
|
3041
3043
|
const existing = safeObject(requests[requestKey]);
|
|
3044
|
+
const normalizedSharedHumanIntent = safeObject(sharedHumanIntent);
|
|
3042
3045
|
const currentMessageID = intFromRawAllowZero(parsed.messageID, 0);
|
|
3043
3046
|
let sharedConversationSource = currentMessageID > 0
|
|
3044
3047
|
? pickRunnerSharedConversationSourceRequest(
|
|
@@ -3097,20 +3100,22 @@ async function claimRunnerRequestForHumanComment({
|
|
|
3097
3100
|
conversation_id: resolvedConversationID,
|
|
3098
3101
|
selected_bot_usernames: uniqueOrderedStrings(selectedBotUsernames, normalizeTelegramMentionUsername),
|
|
3099
3102
|
conversation_intent_mode: String(
|
|
3100
|
-
existing.conversation_intent_mode || sharedConversationSource.conversation_intent_mode || referencedRequest.conversation_intent_mode || "",
|
|
3103
|
+
existing.conversation_intent_mode || sharedConversationSource.conversation_intent_mode || referencedRequest.conversation_intent_mode || normalizedSharedHumanIntent.intentMode || "",
|
|
3101
3104
|
).trim().toLowerCase(),
|
|
3102
3105
|
conversation_lead_bot: normalizeTelegramMentionUsername(
|
|
3103
|
-
existing.conversation_lead_bot || sharedConversationSource.conversation_lead_bot || referencedRequest.conversation_lead_bot,
|
|
3106
|
+
existing.conversation_lead_bot || sharedConversationSource.conversation_lead_bot || referencedRequest.conversation_lead_bot || normalizedSharedHumanIntent.leadBotSelector,
|
|
3104
3107
|
),
|
|
3105
3108
|
conversation_summary_bot: normalizeTelegramMentionUsername(
|
|
3106
|
-
existing.conversation_summary_bot || sharedConversationSource.conversation_summary_bot || referencedRequest.conversation_summary_bot,
|
|
3109
|
+
existing.conversation_summary_bot || sharedConversationSource.conversation_summary_bot || referencedRequest.conversation_summary_bot || normalizedSharedHumanIntent.summaryBotSelector,
|
|
3107
3110
|
),
|
|
3108
3111
|
conversation_participants: uniqueOrderedStrings(
|
|
3109
3112
|
ensureArray(existing.conversation_participants).length
|
|
3110
3113
|
? existing.conversation_participants
|
|
3111
3114
|
: ensureArray(sharedConversationSource.conversation_participants).length
|
|
3112
3115
|
? sharedConversationSource.conversation_participants
|
|
3113
|
-
: referencedRequest.conversation_participants
|
|
3116
|
+
: ensureArray(referencedRequest.conversation_participants).length
|
|
3117
|
+
? referencedRequest.conversation_participants
|
|
3118
|
+
: normalizedSharedHumanIntent.participantSelectors,
|
|
3114
3119
|
normalizeTelegramMentionUsername,
|
|
3115
3120
|
),
|
|
3116
3121
|
conversation_initial_responders: uniqueOrderedStrings(
|
|
@@ -3118,7 +3123,9 @@ async function claimRunnerRequestForHumanComment({
|
|
|
3118
3123
|
? existing.conversation_initial_responders
|
|
3119
3124
|
: ensureArray(sharedConversationSource.conversation_initial_responders).length
|
|
3120
3125
|
? sharedConversationSource.conversation_initial_responders
|
|
3121
|
-
: referencedRequest.conversation_initial_responders
|
|
3126
|
+
: ensureArray(referencedRequest.conversation_initial_responders).length
|
|
3127
|
+
? referencedRequest.conversation_initial_responders
|
|
3128
|
+
: normalizedSharedHumanIntent.initialResponderSelectors,
|
|
3122
3129
|
normalizeTelegramMentionUsername,
|
|
3123
3130
|
),
|
|
3124
3131
|
conversation_allowed_responders: uniqueOrderedStrings(
|
|
@@ -3126,14 +3133,17 @@ async function claimRunnerRequestForHumanComment({
|
|
|
3126
3133
|
? existing.conversation_allowed_responders
|
|
3127
3134
|
: ensureArray(sharedConversationSource.conversation_allowed_responders).length
|
|
3128
3135
|
? sharedConversationSource.conversation_allowed_responders
|
|
3129
|
-
: referencedRequest.conversation_allowed_responders
|
|
3136
|
+
: ensureArray(referencedRequest.conversation_allowed_responders).length
|
|
3137
|
+
? referencedRequest.conversation_allowed_responders
|
|
3138
|
+
: normalizedSharedHumanIntent.allowedResponderSelectors,
|
|
3130
3139
|
normalizeTelegramMentionUsername,
|
|
3131
3140
|
),
|
|
3132
3141
|
conversation_allow_bot_to_bot: existing.conversation_allow_bot_to_bot === true
|
|
3133
3142
|
|| sharedConversationSource.conversation_allow_bot_to_bot === true
|
|
3134
|
-
|| referencedRequest.conversation_allow_bot_to_bot === true
|
|
3143
|
+
|| referencedRequest.conversation_allow_bot_to_bot === true
|
|
3144
|
+
|| normalizedSharedHumanIntent.allowBotToBot === true,
|
|
3135
3145
|
conversation_reply_expectation: String(
|
|
3136
|
-
existing.conversation_reply_expectation || sharedConversationSource.conversation_reply_expectation || referencedRequest.conversation_reply_expectation || "",
|
|
3146
|
+
existing.conversation_reply_expectation || sharedConversationSource.conversation_reply_expectation || referencedRequest.conversation_reply_expectation || normalizedSharedHumanIntent.replyExpectation || "",
|
|
3137
3147
|
).trim().toLowerCase(),
|
|
3138
3148
|
execution_contract_type: String(
|
|
3139
3149
|
existing.execution_contract_type || sharedConversationSource.execution_contract_type || referencedRequest.execution_contract_type || "",
|
|
@@ -3154,7 +3164,9 @@ async function claimRunnerRequestForHumanComment({
|
|
|
3154
3164
|
? existing.next_expected_responders
|
|
3155
3165
|
: ensureArray(sharedConversationSource.next_expected_responders).length
|
|
3156
3166
|
? sharedConversationSource.next_expected_responders
|
|
3157
|
-
: referencedRequest.next_expected_responders
|
|
3167
|
+
: ensureArray(referencedRequest.next_expected_responders).length
|
|
3168
|
+
? referencedRequest.next_expected_responders
|
|
3169
|
+
: normalizedSharedHumanIntent.initialResponderSelectors,
|
|
3158
3170
|
normalizeTelegramMentionUsername,
|
|
3159
3171
|
),
|
|
3160
3172
|
normalized_intent: resolvedNormalizedIntent,
|
|
@@ -7592,7 +7604,7 @@ async function processRunnerRouteOnce(route, runtime, mode, options = {}) {
|
|
|
7592
7604
|
}
|
|
7593
7605
|
return null;
|
|
7594
7606
|
};
|
|
7595
|
-
const prepareRunnerRequestClaim = async (selectedRecord, selectedResponderSelectors = []) => {
|
|
7607
|
+
const prepareRunnerRequestClaim = async (selectedRecord, selectedResponderSelectors = [], sharedHumanIntent = null) => {
|
|
7596
7608
|
const parsed = safeObject(selectedRecord?.parsedArchive);
|
|
7597
7609
|
const kind = String(parsed.kind || "").trim().toLowerCase();
|
|
7598
7610
|
if (kind === "bot_reply") {
|
|
@@ -7622,6 +7634,8 @@ async function processRunnerRouteOnce(route, runtime, mode, options = {}) {
|
|
|
7622
7634
|
routeKey,
|
|
7623
7635
|
selectedRecord,
|
|
7624
7636
|
selectedBotUsernames: selectedResponderSelectors,
|
|
7637
|
+
normalizedIntent: String(safeObject(sharedHumanIntent).intentType || "").trim().toLowerCase(),
|
|
7638
|
+
sharedHumanIntent,
|
|
7625
7639
|
runtime,
|
|
7626
7640
|
archiveThreadID: archiveThread.threadID,
|
|
7627
7641
|
});
|
|
@@ -7679,17 +7693,26 @@ async function processRunnerRouteOnce(route, runtime, mode, options = {}) {
|
|
|
7679
7693
|
skippedRecords.push(startupLoopSkipped.skippedRecord);
|
|
7680
7694
|
continue;
|
|
7681
7695
|
}
|
|
7696
|
+
const routingExecutionDeps = {
|
|
7697
|
+
...buildRunnerExecutionDeps(),
|
|
7698
|
+
managedConversationBots,
|
|
7699
|
+
resolveConversationPeerBots: resolveRunnerConversationPeers,
|
|
7700
|
+
};
|
|
7701
|
+
const sharedHumanIntentContext = await resolveHumanIntentContext({
|
|
7702
|
+
selectedRecord,
|
|
7703
|
+
normalizedRoute,
|
|
7704
|
+
bot,
|
|
7705
|
+
executionPlan,
|
|
7706
|
+
deps: routingExecutionDeps,
|
|
7707
|
+
});
|
|
7682
7708
|
const adjudication = await resolveRunnerResponderAdjudication({
|
|
7683
7709
|
selectedRecord,
|
|
7684
7710
|
pendingOrdered: pending.ordered,
|
|
7685
7711
|
normalizedRoute,
|
|
7686
7712
|
bot,
|
|
7687
7713
|
executionPlan,
|
|
7688
|
-
deps:
|
|
7689
|
-
|
|
7690
|
-
managedConversationBots,
|
|
7691
|
-
resolveConversationPeerBots: resolveRunnerConversationPeers,
|
|
7692
|
-
},
|
|
7714
|
+
deps: routingExecutionDeps,
|
|
7715
|
+
precomputedHumanIntent: safeObject(sharedHumanIntentContext).humanIntent || null,
|
|
7693
7716
|
});
|
|
7694
7717
|
const currentBotSelected = ensureArray(adjudication.selected_bot_usernames)
|
|
7695
7718
|
.map((value) => String(value || "").trim().replace(/^@+/, "").toLowerCase())
|
|
@@ -7710,7 +7733,11 @@ async function processRunnerRouteOnce(route, runtime, mode, options = {}) {
|
|
|
7710
7733
|
});
|
|
7711
7734
|
continue;
|
|
7712
7735
|
}
|
|
7713
|
-
const requestClaim = await prepareRunnerRequestClaim(
|
|
7736
|
+
const requestClaim = await prepareRunnerRequestClaim(
|
|
7737
|
+
selectedRecord,
|
|
7738
|
+
adjudication.selected_bot_usernames,
|
|
7739
|
+
safeObject(sharedHumanIntentContext).humanIntent || null,
|
|
7740
|
+
);
|
|
7714
7741
|
if (!requestClaim.ok) {
|
|
7715
7742
|
await syncRunnerRequestLedgerForProjectToServer({
|
|
7716
7743
|
normalizedRoute,
|
|
@@ -7836,6 +7863,7 @@ async function processRunnerRouteOnce(route, runtime, mode, options = {}) {
|
|
|
7836
7863
|
requestKey: String(requestClaim.requestKey || "").trim(),
|
|
7837
7864
|
triggerDecision,
|
|
7838
7865
|
responderAdjudication: adjudication,
|
|
7866
|
+
humanIntentContext: sharedHumanIntentContext,
|
|
7839
7867
|
},
|
|
7840
7868
|
};
|
|
7841
7869
|
}
|
|
@@ -7918,17 +7946,26 @@ async function processRunnerRouteOnce(route, runtime, mode, options = {}) {
|
|
|
7918
7946
|
skippedRecords.push(startupLoopSkipped.skippedRecord);
|
|
7919
7947
|
continue;
|
|
7920
7948
|
}
|
|
7949
|
+
const routingExecutionDeps = {
|
|
7950
|
+
...buildRunnerExecutionDeps(),
|
|
7951
|
+
managedConversationBots,
|
|
7952
|
+
resolveConversationPeerBots: resolveRunnerConversationPeers,
|
|
7953
|
+
};
|
|
7954
|
+
const sharedHumanIntentContext = await resolveHumanIntentContext({
|
|
7955
|
+
selectedRecord,
|
|
7956
|
+
normalizedRoute,
|
|
7957
|
+
bot,
|
|
7958
|
+
executionPlan,
|
|
7959
|
+
deps: routingExecutionDeps,
|
|
7960
|
+
});
|
|
7921
7961
|
const inlineAdjudication = await resolveRunnerResponderAdjudication({
|
|
7922
7962
|
selectedRecord,
|
|
7923
7963
|
pendingOrdered: pending.ordered,
|
|
7924
7964
|
normalizedRoute,
|
|
7925
7965
|
bot,
|
|
7926
7966
|
executionPlan,
|
|
7927
|
-
deps:
|
|
7928
|
-
|
|
7929
|
-
managedConversationBots,
|
|
7930
|
-
resolveConversationPeerBots: resolveRunnerConversationPeers,
|
|
7931
|
-
},
|
|
7967
|
+
deps: routingExecutionDeps,
|
|
7968
|
+
precomputedHumanIntent: safeObject(sharedHumanIntentContext).humanIntent || null,
|
|
7932
7969
|
});
|
|
7933
7970
|
const inlineCurrentBotSelected = ensureArray(inlineAdjudication.selected_bot_usernames)
|
|
7934
7971
|
.map((value) => String(value || "").trim().replace(/^@+/, "").toLowerCase())
|
|
@@ -7950,7 +7987,11 @@ async function processRunnerRouteOnce(route, runtime, mode, options = {}) {
|
|
|
7950
7987
|
continue;
|
|
7951
7988
|
}
|
|
7952
7989
|
const currentRouteState = safeObject(loadBotRunnerState().routes[routeKey]);
|
|
7953
|
-
const requestClaim = await prepareRunnerRequestClaim(
|
|
7990
|
+
const requestClaim = await prepareRunnerRequestClaim(
|
|
7991
|
+
selectedRecord,
|
|
7992
|
+
inlineAdjudication.selected_bot_usernames,
|
|
7993
|
+
safeObject(sharedHumanIntentContext).humanIntent || null,
|
|
7994
|
+
);
|
|
7954
7995
|
if (!requestClaim.ok) {
|
|
7955
7996
|
await syncRunnerRequestLedgerForProjectToServer({
|
|
7956
7997
|
normalizedRoute,
|
|
@@ -8096,6 +8137,7 @@ async function processRunnerRouteOnce(route, runtime, mode, options = {}) {
|
|
|
8096
8137
|
triggerDecision,
|
|
8097
8138
|
responderAdjudication: inlineAdjudication,
|
|
8098
8139
|
persistedHumanIntentRequest: claimedRequest,
|
|
8140
|
+
precomputedHumanIntentContext: sharedHumanIntentContext,
|
|
8099
8141
|
deps: {
|
|
8100
8142
|
saveRunnerRouteState,
|
|
8101
8143
|
startRunnerTypingHeartbeat,
|
|
@@ -10465,6 +10507,7 @@ async function runRunnerStartResolvedRoutes(routes, flags, options = {}) {
|
|
|
10465
10507
|
triggerDecision: deferredExecution.triggerDecision,
|
|
10466
10508
|
responderAdjudication: deferredExecution.responderAdjudication,
|
|
10467
10509
|
persistedHumanIntentRequest: loadRunnerRequestByKey(deferredExecution.requestKey),
|
|
10510
|
+
precomputedHumanIntentContext: safeObject(deferredExecution.humanIntentContext),
|
|
10468
10511
|
deps: {
|
|
10469
10512
|
saveRunnerRouteState,
|
|
10470
10513
|
startRunnerTypingHeartbeat,
|
|
@@ -14951,6 +14994,7 @@ TELEGRAM_BOT_REVIEW_TOKEN=review-token
|
|
|
14951
14994
|
safeObject,
|
|
14952
14995
|
normalizeRunnerTriggerPolicy,
|
|
14953
14996
|
evaluateTelegramRunnerTrigger,
|
|
14997
|
+
resolveRunnerResponderAdjudication,
|
|
14954
14998
|
selectPendingArchiveComments,
|
|
14955
14999
|
selectRunnerPendingWork,
|
|
14956
15000
|
processRunnerSelectedRecord,
|
|
@@ -2067,7 +2067,7 @@ function buildConversationIntentAnalysisPrompt({
|
|
|
2067
2067
|
"You are a conversation intent contract parser for a public Telegram room with managed bots.",
|
|
2068
2068
|
"Infer the human's intended bot participation contract from the human message only.",
|
|
2069
2069
|
"Do not infer from prior bot replies. Do not invent bots outside managed_bots.",
|
|
2070
|
-
"Be conservative. If the
|
|
2070
|
+
"Be conservative only when the human truly does not indicate collaboration. If the message clearly asks multiple managed bots to discuss, review, brainstorm, compare perspectives, or talk together, do not collapse it to single_bot.",
|
|
2071
2071
|
"Also decide whether the human is asking for immediate execution/work now or only asking for information/explanation.",
|
|
2072
2072
|
"Also classify the current message intent type.",
|
|
2073
2073
|
"",
|
|
@@ -2092,12 +2092,13 @@ function buildConversationIntentAnalysisPrompt({
|
|
|
2092
2092
|
"- intent_type=bot_role_query for asking about bot roles, bot ownership, or how managed bots are meant to collaborate.",
|
|
2093
2093
|
"- intent_type=workspace_query for asking about the current workspace, project folder, or working directory.",
|
|
2094
2094
|
"- intent_type=artifact_location_query for asking where a file, document, pdf, guide, or artifact is located.",
|
|
2095
|
-
"- intent_type=explanation_query for explanation, clarification,
|
|
2095
|
+
"- intent_type=explanation_query for explanation, clarification, informational questions, discussion requests, review requests, brainstorming requests, or requests for bots to talk together about a topic when no concrete work execution is explicitly requested.",
|
|
2096
2096
|
"- intent_type=ctxpack_mutation for requests to create/update project guidance, instructions, rules, policies, or other ctxpack-backed source documents now.",
|
|
2097
2097
|
"- intent_type=workitem_mutation for requests to create/update actionable work items, backlog tasks, or task breakdowns now.",
|
|
2098
|
-
"- intent_type=general_execution for
|
|
2098
|
+
"- intent_type=general_execution only for concrete work requests that should execute now, such as creating/updating files, running tools/commands, modifying project artifacts, or producing validated deliverables.",
|
|
2099
|
+
"- If the human asks bots to discuss, debate, review, brainstorm, compare opinions, or hold a conversation about a topic, default to reply_expectation=informational unless they explicitly ask for concrete execution/output now.",
|
|
2099
2100
|
"- reply_expectation=actionable when the human is asking the bot(s) to actually do work now, produce concrete results, create/update files, delegate concrete tasks, or otherwise execute immediately.",
|
|
2100
|
-
"- reply_expectation=informational when the human is only asking for explanation, status, location, clarification, or other non-execution information.",
|
|
2101
|
+
"- reply_expectation=informational when the human is only asking for explanation, status, location, clarification, discussion, review, brainstorming, or other non-execution information.",
|
|
2101
2102
|
"",
|
|
2102
2103
|
`managed_bots=${JSON.stringify(bots)}`,
|
|
2103
2104
|
`human_message=${JSON.stringify(String(messageText || "").trim())}`,
|
|
@@ -973,9 +973,8 @@ function buildHumanIntentFromPersistedRunnerRequest({
|
|
|
973
973
|
const allowedResponderSelectors = normalizeManagedSelectors(persistedRequest.conversation_allowed_responders);
|
|
974
974
|
const leadBotSelector = normalizeMentionSelector(persistedRequest.conversation_lead_bot);
|
|
975
975
|
const summaryBotSelector = normalizeMentionSelector(persistedRequest.conversation_summary_bot);
|
|
976
|
-
const
|
|
976
|
+
const hasConversationContract = Boolean(
|
|
977
977
|
intentMode
|
|
978
|
-
|| intentType
|
|
979
978
|
|| replyExpectation
|
|
980
979
|
|| participantSelectors.length
|
|
981
980
|
|| initialResponderSelectors.length
|
|
@@ -983,7 +982,13 @@ function buildHumanIntentFromPersistedRunnerRequest({
|
|
|
983
982
|
|| leadBotSelector
|
|
984
983
|
|| summaryBotSelector,
|
|
985
984
|
);
|
|
986
|
-
|
|
985
|
+
const hasExecutionContract = Boolean(
|
|
986
|
+
String(persistedRequest.execution_contract_type || "").trim()
|
|
987
|
+
|| persistedRequest.execution_contract_actionable === true
|
|
988
|
+
|| ensureArray(persistedRequest.execution_contract_targets).length
|
|
989
|
+
|| ensureArray(persistedRequest.next_expected_responders).length,
|
|
990
|
+
);
|
|
991
|
+
if (!hasConversationContract && !hasExecutionContract) {
|
|
987
992
|
return null;
|
|
988
993
|
}
|
|
989
994
|
return {
|
|
@@ -999,7 +1004,7 @@ function buildHumanIntentFromPersistedRunnerRequest({
|
|
|
999
1004
|
};
|
|
1000
1005
|
}
|
|
1001
1006
|
|
|
1002
|
-
async function resolveHumanIntentContext({
|
|
1007
|
+
export async function resolveHumanIntentContext({
|
|
1003
1008
|
selectedRecord,
|
|
1004
1009
|
normalizedRoute,
|
|
1005
1010
|
bot,
|
|
@@ -3952,6 +3957,7 @@ export async function resolveRunnerResponderAdjudication({
|
|
|
3952
3957
|
bot,
|
|
3953
3958
|
executionPlan,
|
|
3954
3959
|
deps,
|
|
3960
|
+
precomputedHumanIntent = null,
|
|
3955
3961
|
}) {
|
|
3956
3962
|
const cacheKey = buildRunnerResponderAdjudicationCacheKey({ normalizedRoute, selectedRecord });
|
|
3957
3963
|
if (runnerResponderAdjudicationPromises.has(cacheKey)) {
|
|
@@ -3967,6 +3973,11 @@ export async function resolveRunnerResponderAdjudication({
|
|
|
3967
3973
|
bot,
|
|
3968
3974
|
deps,
|
|
3969
3975
|
});
|
|
3976
|
+
const managedBotSelectors = new Set(
|
|
3977
|
+
managedBots
|
|
3978
|
+
.map((entry) => normalizeMentionSelector(entry.username))
|
|
3979
|
+
.filter(Boolean),
|
|
3980
|
+
);
|
|
3970
3981
|
const triggerFacts = {
|
|
3971
3982
|
message_kind: String(safeObject(selectedRecord?.parsedArchive).kind || "").trim(),
|
|
3972
3983
|
chat_type: String(safeObject(selectedRecord?.parsedArchive).chatType || "").trim(),
|
|
@@ -3982,6 +3993,47 @@ export async function resolveRunnerResponderAdjudication({
|
|
|
3982
3993
|
trigger_reason: String(entry.trigger_reason || "").trim(),
|
|
3983
3994
|
})),
|
|
3984
3995
|
};
|
|
3996
|
+
const humanIntent = safeObject(precomputedHumanIntent);
|
|
3997
|
+
const contractInitialResponders = uniqueOrdered(
|
|
3998
|
+
ensureArray(humanIntent.initialResponderSelectors)
|
|
3999
|
+
.map((value) => normalizeMentionSelector(value))
|
|
4000
|
+
.filter((value) => value && managedBotSelectors.has(value)),
|
|
4001
|
+
);
|
|
4002
|
+
const contractAllowedResponders = uniqueOrdered(
|
|
4003
|
+
ensureArray(humanIntent.allowedResponderSelectors)
|
|
4004
|
+
.map((value) => normalizeMentionSelector(value))
|
|
4005
|
+
.filter((value) => value && managedBotSelectors.has(value)),
|
|
4006
|
+
);
|
|
4007
|
+
const contractParticipants = uniqueOrdered(
|
|
4008
|
+
ensureArray(humanIntent.participantSelectors)
|
|
4009
|
+
.map((value) => normalizeMentionSelector(value))
|
|
4010
|
+
.filter((value) => value && managedBotSelectors.has(value)),
|
|
4011
|
+
);
|
|
4012
|
+
const contractLeadBot = normalizeMentionSelector(humanIntent.leadBotSelector);
|
|
4013
|
+
const selectedFromContract = uniqueOrdered(
|
|
4014
|
+
(
|
|
4015
|
+
contractInitialResponders.length
|
|
4016
|
+
? contractInitialResponders
|
|
4017
|
+
: contractAllowedResponders.length
|
|
4018
|
+
? contractAllowedResponders
|
|
4019
|
+
: contractParticipants.length
|
|
4020
|
+
? contractParticipants
|
|
4021
|
+
: contractLeadBot && managedBotSelectors.has(contractLeadBot)
|
|
4022
|
+
? [contractLeadBot]
|
|
4023
|
+
: []
|
|
4024
|
+
).filter(Boolean),
|
|
4025
|
+
);
|
|
4026
|
+
if (selectedFromContract.length > 0) {
|
|
4027
|
+
return {
|
|
4028
|
+
decision: selectedFromContract.length > 1 ? "multiple_responders" : "single_responder",
|
|
4029
|
+
selected_bot_usernames: selectedFromContract,
|
|
4030
|
+
referenced_bot_usernames: triggerFacts.mentioned_bot_usernames,
|
|
4031
|
+
confidence: "high",
|
|
4032
|
+
reason_code: "precomputed_human_intent_contract",
|
|
4033
|
+
clarification: "",
|
|
4034
|
+
managed_bots: managedBots,
|
|
4035
|
+
};
|
|
4036
|
+
}
|
|
3985
4037
|
if (!adjudicator) {
|
|
3986
4038
|
const fallbackSelected = managedBots
|
|
3987
4039
|
.filter((entry) => entry.trigger_eligible === true)
|
|
@@ -4104,6 +4156,7 @@ export async function processRunnerSelectedRecord({
|
|
|
4104
4156
|
triggerDecision: precomputedTriggerDecision = null,
|
|
4105
4157
|
responderAdjudication: precomputedResponderAdjudication = null,
|
|
4106
4158
|
persistedHumanIntentRequest = null,
|
|
4159
|
+
precomputedHumanIntentContext = null,
|
|
4107
4160
|
deps,
|
|
4108
4161
|
}) {
|
|
4109
4162
|
const saveRunnerRouteState = requireDependency(deps, "saveRunnerRouteState");
|
|
@@ -4123,6 +4176,8 @@ export async function processRunnerSelectedRecord({
|
|
|
4123
4176
|
...safeObject(buildRunnerExecutionDeps()),
|
|
4124
4177
|
...safeObject(deps),
|
|
4125
4178
|
};
|
|
4179
|
+
const normalizedPrecomputedHumanIntentContext = safeObject(precomputedHumanIntentContext);
|
|
4180
|
+
const normalizedPrecomputedHumanIntent = safeObject(normalizedPrecomputedHumanIntentContext.humanIntent);
|
|
4126
4181
|
const validateWorkspaceArtifacts = typeof executionDeps.validateWorkspaceArtifacts === "function"
|
|
4127
4182
|
? executionDeps.validateWorkspaceArtifacts
|
|
4128
4183
|
: null;
|
|
@@ -4167,6 +4222,7 @@ export async function processRunnerSelectedRecord({
|
|
|
4167
4222
|
bot,
|
|
4168
4223
|
executionPlan,
|
|
4169
4224
|
deps: executionDeps,
|
|
4225
|
+
precomputedHumanIntent: normalizedPrecomputedHumanIntent,
|
|
4170
4226
|
});
|
|
4171
4227
|
const selectedResponderSelectors = ensureArray(responderAdjudication.selected_bot_usernames)
|
|
4172
4228
|
.map((value) => normalizeMentionSelector(value))
|
|
@@ -4196,14 +4252,16 @@ export async function processRunnerSelectedRecord({
|
|
|
4196
4252
|
};
|
|
4197
4253
|
}
|
|
4198
4254
|
|
|
4199
|
-
const humanIntentContext =
|
|
4200
|
-
|
|
4201
|
-
|
|
4202
|
-
|
|
4203
|
-
|
|
4204
|
-
|
|
4205
|
-
|
|
4206
|
-
|
|
4255
|
+
const humanIntentContext = Object.keys(normalizedPrecomputedHumanIntentContext).length > 0
|
|
4256
|
+
? normalizedPrecomputedHumanIntentContext
|
|
4257
|
+
: await resolveHumanIntentContext({
|
|
4258
|
+
selectedRecord,
|
|
4259
|
+
normalizedRoute,
|
|
4260
|
+
bot,
|
|
4261
|
+
executionPlan,
|
|
4262
|
+
deps: executionDeps,
|
|
4263
|
+
persistedRequest: persistedHumanIntentRequest,
|
|
4264
|
+
});
|
|
4207
4265
|
const precomputedIntentType = normalizeHumanIntentType(
|
|
4208
4266
|
safeObject(safeObject(humanIntentContext).humanIntent).intentType,
|
|
4209
4267
|
);
|
|
@@ -118,6 +118,7 @@ export async function runSelftestRunnerScenarios(push, deps) {
|
|
|
118
118
|
const safeObject = requireDependency(deps, "safeObject");
|
|
119
119
|
const normalizeRunnerTriggerPolicy = requireDependency(deps, "normalizeRunnerTriggerPolicy");
|
|
120
120
|
const evaluateTelegramRunnerTrigger = requireDependency(deps, "evaluateTelegramRunnerTrigger");
|
|
121
|
+
const resolveRunnerResponderAdjudication = requireDependency(deps, "resolveRunnerResponderAdjudication");
|
|
121
122
|
const selectPendingArchiveComments = requireDependency(deps, "selectPendingArchiveComments");
|
|
122
123
|
const selectRunnerPendingWork = requireDependency(deps, "selectRunnerPendingWork");
|
|
123
124
|
const processRunnerSelectedRecord = requireDependency(deps, "processRunnerSelectedRecord");
|
|
@@ -2935,6 +2936,108 @@ export async function runSelftestRunnerScenarios(push, deps) {
|
|
|
2935
2936
|
push("public_multi_bot_human_intent_is_computed_once_per_message", false, String(err?.message || err));
|
|
2936
2937
|
}
|
|
2937
2938
|
|
|
2939
|
+
try {
|
|
2940
|
+
let adjudicatorCalls = 0;
|
|
2941
|
+
const adjudication = await resolveRunnerResponderAdjudication({
|
|
2942
|
+
selectedRecord: {
|
|
2943
|
+
id: "comment-precomputed-human-intent-adjudication",
|
|
2944
|
+
parsedArchive: {
|
|
2945
|
+
kind: "telegram_message",
|
|
2946
|
+
chatID: "-100123",
|
|
2947
|
+
chatType: "supergroup",
|
|
2948
|
+
senderIsBot: false,
|
|
2949
|
+
body: "@RyoAI_bot @RyoAI2_bot @RyoAI3_bot discuss this project together.",
|
|
2950
|
+
mentionUsernames: ["RyoAI_bot", "RyoAI2_bot", "RyoAI3_bot"],
|
|
2951
|
+
messageID: 1193,
|
|
2952
|
+
},
|
|
2953
|
+
},
|
|
2954
|
+
pendingOrdered: [],
|
|
2955
|
+
normalizedRoute: normalizeRunnerRoute({
|
|
2956
|
+
name: "telegram-monitor-precomputed-human-intent-adjudication",
|
|
2957
|
+
project_id: selftestProjectID,
|
|
2958
|
+
provider: "telegram",
|
|
2959
|
+
role: "monitor",
|
|
2960
|
+
role_profile: "monitor",
|
|
2961
|
+
destination_id: "dest-1",
|
|
2962
|
+
destination_label: "Main Room",
|
|
2963
|
+
server_bot_name: "RyoAI_bot",
|
|
2964
|
+
server_bot_id: "bot-lead-1",
|
|
2965
|
+
trigger_policy: {
|
|
2966
|
+
mentions_only: true,
|
|
2967
|
+
direct_messages: true,
|
|
2968
|
+
reply_to_bot_messages: true,
|
|
2969
|
+
},
|
|
2970
|
+
archive_policy: {
|
|
2971
|
+
mirror_replies: true,
|
|
2972
|
+
dedupe_inbound: true,
|
|
2973
|
+
dedupe_outbound: true,
|
|
2974
|
+
skip_bot_messages: true,
|
|
2975
|
+
},
|
|
2976
|
+
dry_run_delivery: true,
|
|
2977
|
+
}),
|
|
2978
|
+
bot: {
|
|
2979
|
+
id: "bot-lead-1",
|
|
2980
|
+
name: "RyoAI_bot",
|
|
2981
|
+
username: "RyoAI_bot",
|
|
2982
|
+
role: "monitor",
|
|
2983
|
+
provider: "telegram",
|
|
2984
|
+
},
|
|
2985
|
+
executionPlan: {
|
|
2986
|
+
mode: "role_profile",
|
|
2987
|
+
roleProfileName: "monitor",
|
|
2988
|
+
roleProfile: {
|
|
2989
|
+
client: "sample",
|
|
2990
|
+
model: "",
|
|
2991
|
+
permissionMode: "read_only",
|
|
2992
|
+
reasoningEffort: "low",
|
|
2993
|
+
},
|
|
2994
|
+
workspaceDir: path.join(os.tmpdir(), "metheus-runner-selftest-precomputed-human-intent-adjudication"),
|
|
2995
|
+
workspaceSource: "selftest",
|
|
2996
|
+
usedCommandFallback: false,
|
|
2997
|
+
},
|
|
2998
|
+
precomputedHumanIntent: {
|
|
2999
|
+
intentMode: "delegated_single_lead",
|
|
3000
|
+
intentType: "explanation_query",
|
|
3001
|
+
participantSelectors: ["ryoai_bot", "ryoai2_bot", "ryoai3_bot"],
|
|
3002
|
+
initialResponderSelectors: ["ryoai_bot"],
|
|
3003
|
+
allowedResponderSelectors: ["ryoai_bot", "ryoai2_bot", "ryoai3_bot"],
|
|
3004
|
+
leadBotSelector: "ryoai_bot",
|
|
3005
|
+
summaryBotSelector: "ryoai_bot",
|
|
3006
|
+
allowBotToBot: true,
|
|
3007
|
+
replyExpectation: "informational",
|
|
3008
|
+
},
|
|
3009
|
+
deps: {
|
|
3010
|
+
adjudicateRunnerRespondersWithAI: async () => {
|
|
3011
|
+
adjudicatorCalls += 1;
|
|
3012
|
+
return {
|
|
3013
|
+
decision: "multiple_responders",
|
|
3014
|
+
selected_bot_usernames: ["ryoai2_bot", "ryoai3_bot"],
|
|
3015
|
+
};
|
|
3016
|
+
},
|
|
3017
|
+
managedConversationBots: [
|
|
3018
|
+
{ route: { serverBotName: "RyoAI_bot" }, bot: { username: "RyoAI_bot", name: "RyoAI_bot" } },
|
|
3019
|
+
{ route: { serverBotName: "RyoAI2_bot" }, bot: { username: "RyoAI2_bot", name: "RyoAI2_bot" } },
|
|
3020
|
+
{ route: { serverBotName: "RyoAI3_bot" }, bot: { username: "RyoAI3_bot", name: "RyoAI3_bot" } },
|
|
3021
|
+
],
|
|
3022
|
+
resolveConversationPeerBots: () => [
|
|
3023
|
+
{ id: "bot-lead-1", name: "RyoAI_bot" },
|
|
3024
|
+
{ id: "bot-peer-1", name: "RyoAI2_bot" },
|
|
3025
|
+
{ id: "bot-peer-2", name: "RyoAI3_bot" },
|
|
3026
|
+
],
|
|
3027
|
+
},
|
|
3028
|
+
});
|
|
3029
|
+
push(
|
|
3030
|
+
"precomputed_human_intent_contract_drives_responder_selection",
|
|
3031
|
+
adjudicatorCalls === 0
|
|
3032
|
+
&& ensureArray(adjudication.selected_bot_usernames).length === 1
|
|
3033
|
+
&& String(ensureArray(adjudication.selected_bot_usernames)[0] || "") === "ryoai_bot"
|
|
3034
|
+
&& String(adjudication.reason_code || "") === "precomputed_human_intent_contract",
|
|
3035
|
+
`adjudicator_calls=${adjudicatorCalls} selected=${JSON.stringify(ensureArray(adjudication.selected_bot_usernames))} reason=${String(adjudication.reason_code || "(none)")}`,
|
|
3036
|
+
);
|
|
3037
|
+
} catch (err) {
|
|
3038
|
+
push("precomputed_human_intent_contract_drives_responder_selection", false, String(err?.message || err));
|
|
3039
|
+
}
|
|
3040
|
+
|
|
2938
3041
|
try {
|
|
2939
3042
|
let humanIntentCalls = 0;
|
|
2940
3043
|
const processed = await processRunnerSelectedRecord({
|
|
@@ -3074,6 +3177,142 @@ export async function runSelftestRunnerScenarios(push, deps) {
|
|
|
3074
3177
|
push("public_multi_bot_persisted_human_intent_skips_reanalysis", false, String(err?.message || err));
|
|
3075
3178
|
}
|
|
3076
3179
|
|
|
3180
|
+
try {
|
|
3181
|
+
let humanIntentCalls = 0;
|
|
3182
|
+
const processed = await processRunnerSelectedRecord({
|
|
3183
|
+
routeKey: "public-persisted-intent-only-key",
|
|
3184
|
+
normalizedRoute: normalizeRunnerRoute({
|
|
3185
|
+
name: "telegram-monitor-public-persisted-intent-only",
|
|
3186
|
+
project_id: selftestProjectID,
|
|
3187
|
+
provider: "telegram",
|
|
3188
|
+
role: "monitor",
|
|
3189
|
+
role_profile: "monitor",
|
|
3190
|
+
destination_id: "dest-1",
|
|
3191
|
+
destination_label: "Main Room",
|
|
3192
|
+
server_bot_name: "RyoAI_bot",
|
|
3193
|
+
server_bot_id: "bot-lead-1",
|
|
3194
|
+
trigger_policy: {
|
|
3195
|
+
mentions_only: true,
|
|
3196
|
+
direct_messages: true,
|
|
3197
|
+
reply_to_bot_messages: true,
|
|
3198
|
+
},
|
|
3199
|
+
archive_policy: {
|
|
3200
|
+
mirror_replies: true,
|
|
3201
|
+
dedupe_inbound: true,
|
|
3202
|
+
dedupe_outbound: true,
|
|
3203
|
+
skip_bot_messages: true,
|
|
3204
|
+
},
|
|
3205
|
+
dry_run_delivery: true,
|
|
3206
|
+
}),
|
|
3207
|
+
selectedRecord: {
|
|
3208
|
+
id: "comment-public-persisted-intent-only",
|
|
3209
|
+
createdAt: "2026-03-16T00:07:00.000Z",
|
|
3210
|
+
parsedArchive: {
|
|
3211
|
+
kind: "telegram_message",
|
|
3212
|
+
chatID: "-100123",
|
|
3213
|
+
chatType: "supergroup",
|
|
3214
|
+
senderIsBot: false,
|
|
3215
|
+
body: "@RyoAI_bot @RyoAI2_bot @RyoAI3_bot continue the discussion.",
|
|
3216
|
+
mentionUsernames: ["RyoAI_bot", "RyoAI2_bot", "RyoAI3_bot"],
|
|
3217
|
+
messageID: 1192,
|
|
3218
|
+
},
|
|
3219
|
+
},
|
|
3220
|
+
pendingOrdered: [],
|
|
3221
|
+
bot: {
|
|
3222
|
+
id: "bot-lead-1",
|
|
3223
|
+
name: "RyoAI_bot",
|
|
3224
|
+
username: "RyoAI_bot",
|
|
3225
|
+
role: "monitor",
|
|
3226
|
+
provider: "telegram",
|
|
3227
|
+
},
|
|
3228
|
+
destination: {
|
|
3229
|
+
id: "dest-1",
|
|
3230
|
+
label: "Main Room",
|
|
3231
|
+
provider: "telegram",
|
|
3232
|
+
chatID: "-100123",
|
|
3233
|
+
},
|
|
3234
|
+
archiveThread: {
|
|
3235
|
+
threadID: "thread-1",
|
|
3236
|
+
workItemID: "work-item-1",
|
|
3237
|
+
},
|
|
3238
|
+
executionPlan: {
|
|
3239
|
+
mode: "role_profile",
|
|
3240
|
+
roleProfileName: "monitor",
|
|
3241
|
+
roleProfile: {
|
|
3242
|
+
client: "sample",
|
|
3243
|
+
model: "",
|
|
3244
|
+
permissionMode: "read_only",
|
|
3245
|
+
reasoningEffort: "low",
|
|
3246
|
+
},
|
|
3247
|
+
workspaceDir: path.join(os.tmpdir(), "metheus-runner-selftest-persisted-human-intent-only"),
|
|
3248
|
+
workspaceSource: "selftest",
|
|
3249
|
+
usedCommandFallback: false,
|
|
3250
|
+
},
|
|
3251
|
+
runtime: {
|
|
3252
|
+
baseURL: "https://example.test",
|
|
3253
|
+
token: "selftest-token",
|
|
3254
|
+
timeoutSeconds: 30,
|
|
3255
|
+
actor: { user_id: "user-1" },
|
|
3256
|
+
},
|
|
3257
|
+
responderAdjudication: {
|
|
3258
|
+
selected_bot_usernames: ["ryoai_bot"],
|
|
3259
|
+
},
|
|
3260
|
+
persistedHumanIntentRequest: {
|
|
3261
|
+
request_key: "persisted-request-1192",
|
|
3262
|
+
normalized_intent: "general_execution",
|
|
3263
|
+
},
|
|
3264
|
+
deps: {
|
|
3265
|
+
saveRunnerRouteState: () => {},
|
|
3266
|
+
startRunnerTypingHeartbeat: () => ({ async stop() {} }),
|
|
3267
|
+
runRunnerAIExecution: async () => ({
|
|
3268
|
+
skip: false,
|
|
3269
|
+
reply: "bot replied",
|
|
3270
|
+
replyToMessageID: 0,
|
|
3271
|
+
contract: {
|
|
3272
|
+
type: "direct_result",
|
|
3273
|
+
actionable: false,
|
|
3274
|
+
},
|
|
3275
|
+
}),
|
|
3276
|
+
performLocalBotDelivery: async () => ({
|
|
3277
|
+
delivery: { dryRun: true, body: {} },
|
|
3278
|
+
archive: {},
|
|
3279
|
+
}),
|
|
3280
|
+
serializeRunnerTriggerPolicy: (value) => value,
|
|
3281
|
+
serializeRunnerArchivePolicy: (value) => value,
|
|
3282
|
+
buildRunnerExecutionDeps: () => ({
|
|
3283
|
+
analyzeHumanConversationIntentWithAI: async () => {
|
|
3284
|
+
humanIntentCalls += 1;
|
|
3285
|
+
return {
|
|
3286
|
+
mode: "multi_bot_collab",
|
|
3287
|
+
lead_bot: "ryoai_bot",
|
|
3288
|
+
summary_bot: "ryoai_bot",
|
|
3289
|
+
participants: ["ryoai_bot", "ryoai2_bot", "ryoai3_bot"],
|
|
3290
|
+
initial_responders: ["ryoai_bot", "ryoai2_bot", "ryoai3_bot"],
|
|
3291
|
+
allowed_responders: ["ryoai_bot", "ryoai2_bot", "ryoai3_bot"],
|
|
3292
|
+
allow_bot_to_bot: true,
|
|
3293
|
+
reply_expectation: "informational",
|
|
3294
|
+
intent_type: "explanation_query",
|
|
3295
|
+
};
|
|
3296
|
+
},
|
|
3297
|
+
}),
|
|
3298
|
+
buildRunnerDeliveryDeps: () => ({}),
|
|
3299
|
+
buildRunnerRuntimeDeps: () => ({}),
|
|
3300
|
+
resolveConversationPeerBots: () => [
|
|
3301
|
+
{ id: "bot-lead-1", name: "RyoAI_bot" },
|
|
3302
|
+
{ id: "bot-peer-1", name: "RyoAI2_bot" },
|
|
3303
|
+
{ id: "bot-peer-2", name: "RyoAI3_bot" },
|
|
3304
|
+
],
|
|
3305
|
+
},
|
|
3306
|
+
});
|
|
3307
|
+
push(
|
|
3308
|
+
"public_multi_bot_persisted_intent_only_reanalyzes_human_message",
|
|
3309
|
+
processed.kind === "replied" && humanIntentCalls === 1,
|
|
3310
|
+
`kind=${String(processed.kind || "(none)")} human_intent_calls=${humanIntentCalls}`,
|
|
3311
|
+
);
|
|
3312
|
+
} catch (err) {
|
|
3313
|
+
push("public_multi_bot_persisted_intent_only_reanalyzes_human_message", false, String(err?.message || err));
|
|
3314
|
+
}
|
|
3315
|
+
|
|
3077
3316
|
try {
|
|
3078
3317
|
const deliveredTexts = [];
|
|
3079
3318
|
const deliveredConversation = [];
|