metheus-governance-mcp-cli 0.2.200 → 0.2.202
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 +295 -52
- package/lib/local-ai-adapters.mjs +1 -4
- package/lib/runner-data.mjs +10 -15
- package/lib/runner-orchestration.mjs +87 -150
- package/lib/runner-trigger.mjs +0 -1
- package/lib/selftest-runner-scenarios.mjs +385 -14
- package/lib/selftest-telegram-e2e.mjs +51 -0
- package/package.json +1 -1
package/cli.mjs
CHANGED
|
@@ -2553,6 +2553,76 @@ async function findServerRunnerRequestForMessageID({
|
|
|
2553
2553
|
}
|
|
2554
2554
|
}
|
|
2555
2555
|
|
|
2556
|
+
async function loadRunnerArchiveThreadMessageIndex({
|
|
2557
|
+
runtime,
|
|
2558
|
+
threadID,
|
|
2559
|
+
cache = null,
|
|
2560
|
+
}) {
|
|
2561
|
+
const normalizedThreadID = String(threadID || "").trim();
|
|
2562
|
+
if (
|
|
2563
|
+
cache
|
|
2564
|
+
&& String(cache.threadID || "").trim() === normalizedThreadID
|
|
2565
|
+
&& cache.messageIndex instanceof Map
|
|
2566
|
+
) {
|
|
2567
|
+
return cache;
|
|
2568
|
+
}
|
|
2569
|
+
if (!normalizedThreadID || !runtime?.baseURL || !runtime?.token) {
|
|
2570
|
+
return {
|
|
2571
|
+
threadID: normalizedThreadID,
|
|
2572
|
+
messageIndex: new Map(),
|
|
2573
|
+
};
|
|
2574
|
+
}
|
|
2575
|
+
try {
|
|
2576
|
+
const comments = await listThreadCommentsTail({
|
|
2577
|
+
siteBaseURL: runtime.baseURL,
|
|
2578
|
+
threadID: normalizedThreadID,
|
|
2579
|
+
token: runtime.token,
|
|
2580
|
+
timeoutSeconds: runtime.timeoutSeconds,
|
|
2581
|
+
actorUserID: runtime.actor?.user_id,
|
|
2582
|
+
tailLimit: 300,
|
|
2583
|
+
scanLimit: 1200,
|
|
2584
|
+
});
|
|
2585
|
+
const messageIndex = new Map();
|
|
2586
|
+
for (const commentRaw of ensureArray(comments)) {
|
|
2587
|
+
const comment = safeObject(commentRaw);
|
|
2588
|
+
const parsedArchive = safeObject(comment.parsedArchive || parseArchivedChatComment(comment.body));
|
|
2589
|
+
const messageID = intFromRawAllowZero(parsedArchive.messageID, 0);
|
|
2590
|
+
if (messageID > 0 && !messageIndex.has(messageID)) {
|
|
2591
|
+
messageIndex.set(messageID, {
|
|
2592
|
+
...comment,
|
|
2593
|
+
parsedArchive,
|
|
2594
|
+
});
|
|
2595
|
+
}
|
|
2596
|
+
}
|
|
2597
|
+
return {
|
|
2598
|
+
threadID: normalizedThreadID,
|
|
2599
|
+
messageIndex,
|
|
2600
|
+
};
|
|
2601
|
+
} catch {
|
|
2602
|
+
return {
|
|
2603
|
+
threadID: normalizedThreadID,
|
|
2604
|
+
messageIndex: new Map(),
|
|
2605
|
+
};
|
|
2606
|
+
}
|
|
2607
|
+
}
|
|
2608
|
+
|
|
2609
|
+
async function findRunnerArchiveThreadMessageByID({
|
|
2610
|
+
runtime,
|
|
2611
|
+
threadID,
|
|
2612
|
+
messageID,
|
|
2613
|
+
cache = null,
|
|
2614
|
+
}) {
|
|
2615
|
+
const nextCache = await loadRunnerArchiveThreadMessageIndex({
|
|
2616
|
+
runtime,
|
|
2617
|
+
threadID,
|
|
2618
|
+
cache,
|
|
2619
|
+
});
|
|
2620
|
+
return {
|
|
2621
|
+
cache: nextCache,
|
|
2622
|
+
record: safeObject(nextCache.messageIndex.get(intFromRawAllowZero(messageID, 0))),
|
|
2623
|
+
};
|
|
2624
|
+
}
|
|
2625
|
+
|
|
2556
2626
|
function resolveRunnerReplyChainConversationContext(state, normalizedRoute, selectedRecord) {
|
|
2557
2627
|
const parsed = safeObject(selectedRecord?.parsedArchive);
|
|
2558
2628
|
const explicitConversationID = String(parsed.conversationID || "").trim();
|
|
@@ -2600,6 +2670,8 @@ async function resolveRunnerReplyChainConversationContextWithServerFallback({
|
|
|
2600
2670
|
normalizedRoute,
|
|
2601
2671
|
selectedRecord,
|
|
2602
2672
|
runtime,
|
|
2673
|
+
archiveThreadID = "",
|
|
2674
|
+
hydrationAttempted = false,
|
|
2603
2675
|
}) {
|
|
2604
2676
|
const initialState = safeObject(state);
|
|
2605
2677
|
const initialContext = resolveRunnerReplyChainConversationContext(initialState, normalizedRoute, selectedRecord);
|
|
@@ -2611,11 +2683,11 @@ async function resolveRunnerReplyChainConversationContextWithServerFallback({
|
|
|
2611
2683
|
};
|
|
2612
2684
|
}
|
|
2613
2685
|
const parsed = safeObject(selectedRecord?.parsedArchive);
|
|
2614
|
-
const
|
|
2686
|
+
const initialReplyToMessageID = intFromRawAllowZero(
|
|
2615
2687
|
parsed.replyToMessageID || safeObject(initialContext).replyToMessageID,
|
|
2616
2688
|
0,
|
|
2617
2689
|
);
|
|
2618
|
-
if (
|
|
2690
|
+
if (initialReplyToMessageID <= 0) {
|
|
2619
2691
|
return {
|
|
2620
2692
|
state: initialState,
|
|
2621
2693
|
replyChainContext: initialContext,
|
|
@@ -2623,43 +2695,142 @@ async function resolveRunnerReplyChainConversationContextWithServerFallback({
|
|
|
2623
2695
|
};
|
|
2624
2696
|
}
|
|
2625
2697
|
const chatID = String(parsed.chatID || parsed.chatId || "").trim();
|
|
2626
|
-
const
|
|
2627
|
-
|
|
2628
|
-
|
|
2629
|
-
|
|
2630
|
-
|
|
2631
|
-
|
|
2632
|
-
|
|
2633
|
-
|
|
2634
|
-
|
|
2635
|
-
|
|
2698
|
+
const normalizedArchiveThreadID = firstNonEmptyString([
|
|
2699
|
+
archiveThreadID,
|
|
2700
|
+
selectedRecord?.thread_id,
|
|
2701
|
+
selectedRecord?.threadID,
|
|
2702
|
+
selectedRecord?.threadId,
|
|
2703
|
+
]);
|
|
2704
|
+
let stateForLookup = initialState;
|
|
2705
|
+
let replyToMessageID = initialReplyToMessageID;
|
|
2706
|
+
let archiveThreadCache = null;
|
|
2707
|
+
let lastAnchorMessageID = intFromRawAllowZero(safeObject(initialContext).anchorMessageID, 0) || initialReplyToMessageID;
|
|
2708
|
+
const visitedMessageIDs = new Set();
|
|
2709
|
+
|
|
2710
|
+
const buildContextFromRequest = (referencedRequestRaw, reasonSuffix = "") => {
|
|
2711
|
+
const referencedRequest = safeObject(referencedRequestRaw);
|
|
2712
|
+
const anchorMessageID = intFromRawAllowZero(referencedRequest.source_message_id, 0) || replyToMessageID;
|
|
2636
2713
|
return {
|
|
2637
|
-
state:
|
|
2638
|
-
...initialState,
|
|
2639
|
-
requests: requestIndex,
|
|
2640
|
-
},
|
|
2714
|
+
state: stateForLookup,
|
|
2641
2715
|
replyChainContext: {
|
|
2642
|
-
conversationID: String(
|
|
2716
|
+
conversationID: String(referencedRequest.conversation_id || "").trim()
|
|
2643
2717
|
|| buildSyntheticReplyChainConversationID(normalizedRoute, chatID, anchorMessageID),
|
|
2644
|
-
replyToMessageID,
|
|
2718
|
+
replyToMessageID: initialReplyToMessageID,
|
|
2645
2719
|
anchorMessageID,
|
|
2646
|
-
reason: String(
|
|
2647
|
-
?
|
|
2648
|
-
:
|
|
2649
|
-
referencedRequest
|
|
2720
|
+
reason: String(referencedRequest.conversation_id || "").trim()
|
|
2721
|
+
? `reply_request_conversation${reasonSuffix}`
|
|
2722
|
+
: `reply_request_synthetic${reasonSuffix}`,
|
|
2723
|
+
referencedRequest,
|
|
2650
2724
|
},
|
|
2651
|
-
hydrated:
|
|
2725
|
+
hydrated: hydrationAttempted,
|
|
2652
2726
|
};
|
|
2727
|
+
};
|
|
2728
|
+
|
|
2729
|
+
for (let hop = 0; hop < 8 && replyToMessageID > 0; hop += 1) {
|
|
2730
|
+
if (visitedMessageIDs.has(replyToMessageID)) {
|
|
2731
|
+
break;
|
|
2732
|
+
}
|
|
2733
|
+
visitedMessageIDs.add(replyToMessageID);
|
|
2734
|
+
|
|
2735
|
+
const localReferencedRequest = safeObject(findRunnerRequestsForMessageID(stateForLookup, normalizedRoute, {
|
|
2736
|
+
chatID,
|
|
2737
|
+
messageID: replyToMessageID,
|
|
2738
|
+
})[0]);
|
|
2739
|
+
if (localReferencedRequest.request_key) {
|
|
2740
|
+
return buildContextFromRequest(localReferencedRequest, hop > 0 ? "_chain" : "");
|
|
2741
|
+
}
|
|
2742
|
+
|
|
2743
|
+
if (runtime?.baseURL && runtime?.token) {
|
|
2744
|
+
const serverReferencedRequest = await findServerRunnerRequestForMessageID({
|
|
2745
|
+
normalizedRoute,
|
|
2746
|
+
runtime,
|
|
2747
|
+
chatID,
|
|
2748
|
+
messageID: replyToMessageID,
|
|
2749
|
+
});
|
|
2750
|
+
if (serverReferencedRequest.request_key) {
|
|
2751
|
+
const requestIndex = normalizeBotRunnerRequests(stateForLookup.requests);
|
|
2752
|
+
requestIndex[String(serverReferencedRequest.request_key || "").trim()] = serverReferencedRequest;
|
|
2753
|
+
stateForLookup = {
|
|
2754
|
+
...stateForLookup,
|
|
2755
|
+
requests: requestIndex,
|
|
2756
|
+
};
|
|
2757
|
+
return buildContextFromRequest(serverReferencedRequest, hop > 0 ? "_chain_server" : "_server");
|
|
2758
|
+
}
|
|
2759
|
+
}
|
|
2760
|
+
|
|
2761
|
+
if (!normalizedArchiveThreadID || !runtime?.baseURL || !runtime?.token) {
|
|
2762
|
+
break;
|
|
2763
|
+
}
|
|
2764
|
+
const archivedMessageLookup = await findRunnerArchiveThreadMessageByID({
|
|
2765
|
+
runtime,
|
|
2766
|
+
threadID: normalizedArchiveThreadID,
|
|
2767
|
+
messageID: replyToMessageID,
|
|
2768
|
+
cache: archiveThreadCache,
|
|
2769
|
+
});
|
|
2770
|
+
archiveThreadCache = archivedMessageLookup.cache;
|
|
2771
|
+
const archivedRecord = safeObject(archivedMessageLookup.record);
|
|
2772
|
+
const archivedParsed = safeObject(archivedRecord.parsedArchive || parseArchivedChatComment(archivedRecord.body));
|
|
2773
|
+
const archivedMessageID = intFromRawAllowZero(archivedParsed.messageID, 0) || replyToMessageID;
|
|
2774
|
+
if (archivedMessageID > 0) {
|
|
2775
|
+
lastAnchorMessageID = archivedMessageID;
|
|
2776
|
+
}
|
|
2777
|
+
const archivedConversationID = String(archivedParsed.conversationID || "").trim();
|
|
2778
|
+
if (archivedConversationID) {
|
|
2779
|
+
return {
|
|
2780
|
+
state: stateForLookup,
|
|
2781
|
+
replyChainContext: {
|
|
2782
|
+
conversationID: archivedConversationID,
|
|
2783
|
+
replyToMessageID: initialReplyToMessageID,
|
|
2784
|
+
anchorMessageID: archivedMessageID,
|
|
2785
|
+
reason: "reply_chain_archive_conversation",
|
|
2786
|
+
referencedRequest: null,
|
|
2787
|
+
},
|
|
2788
|
+
hydrated: hydrationAttempted,
|
|
2789
|
+
};
|
|
2790
|
+
}
|
|
2791
|
+
const nextReplyToMessageID = intFromRawAllowZero(archivedParsed.replyToMessageID, 0);
|
|
2792
|
+
if (nextReplyToMessageID <= 0) {
|
|
2793
|
+
return {
|
|
2794
|
+
state: stateForLookup,
|
|
2795
|
+
replyChainContext: {
|
|
2796
|
+
conversationID: buildSyntheticReplyChainConversationID(normalizedRoute, chatID, lastAnchorMessageID || archivedMessageID),
|
|
2797
|
+
replyToMessageID: initialReplyToMessageID,
|
|
2798
|
+
anchorMessageID: lastAnchorMessageID || archivedMessageID,
|
|
2799
|
+
reason: "reply_chain_archive_synthetic",
|
|
2800
|
+
referencedRequest: null,
|
|
2801
|
+
},
|
|
2802
|
+
hydrated: hydrationAttempted,
|
|
2803
|
+
};
|
|
2804
|
+
}
|
|
2805
|
+
replyToMessageID = nextReplyToMessageID;
|
|
2653
2806
|
}
|
|
2654
|
-
|
|
2655
|
-
|
|
2656
|
-
|
|
2657
|
-
|
|
2658
|
-
|
|
2807
|
+
|
|
2808
|
+
if (!hydrationAttempted && runtime?.baseURL && runtime?.token) {
|
|
2809
|
+
const hydratedState = await hydrateRunnerRequestLedgerFromServer({
|
|
2810
|
+
normalizedRoute,
|
|
2811
|
+
runtime,
|
|
2812
|
+
});
|
|
2813
|
+
const hydratedResolution = await resolveRunnerReplyChainConversationContextWithServerFallback({
|
|
2814
|
+
state: hydratedState,
|
|
2815
|
+
normalizedRoute,
|
|
2816
|
+
selectedRecord,
|
|
2817
|
+
runtime,
|
|
2818
|
+
archiveThreadID: normalizedArchiveThreadID,
|
|
2819
|
+
hydrationAttempted: true,
|
|
2820
|
+
});
|
|
2821
|
+
return {
|
|
2822
|
+
state: hydratedResolution.state,
|
|
2823
|
+
replyChainContext: hydratedResolution.replyChainContext,
|
|
2824
|
+
hydrated: true,
|
|
2825
|
+
};
|
|
2826
|
+
}
|
|
2827
|
+
|
|
2659
2828
|
return {
|
|
2660
|
-
state:
|
|
2661
|
-
replyChainContext:
|
|
2662
|
-
|
|
2829
|
+
state: stateForLookup,
|
|
2830
|
+
replyChainContext: hydrationAttempted
|
|
2831
|
+
? resolveRunnerReplyChainConversationContext(stateForLookup, normalizedRoute, selectedRecord)
|
|
2832
|
+
: initialContext,
|
|
2833
|
+
hydrated: hydrationAttempted,
|
|
2663
2834
|
};
|
|
2664
2835
|
}
|
|
2665
2836
|
|
|
@@ -2709,6 +2880,7 @@ async function claimRunnerRequestForHumanComment({
|
|
|
2709
2880
|
selectedBotUsernames = [],
|
|
2710
2881
|
normalizedIntent = "",
|
|
2711
2882
|
runtime = null,
|
|
2883
|
+
archiveThreadID = "",
|
|
2712
2884
|
}) {
|
|
2713
2885
|
const parsed = safeObject(selectedRecord?.parsedArchive);
|
|
2714
2886
|
const commentKind = String(parsed.kind || "").trim().toLowerCase();
|
|
@@ -2724,6 +2896,7 @@ async function claimRunnerRequestForHumanComment({
|
|
|
2724
2896
|
normalizedRoute,
|
|
2725
2897
|
selectedRecord,
|
|
2726
2898
|
runtime,
|
|
2899
|
+
archiveThreadID,
|
|
2727
2900
|
});
|
|
2728
2901
|
const replyChainContext = safeObject(replyChainResolution.replyChainContext);
|
|
2729
2902
|
const referencedRequest = safeObject(replyChainContext.referencedRequest);
|
|
@@ -5431,9 +5604,6 @@ function formatTelegramInboundArchiveComment(normalized) {
|
|
|
5431
5604
|
if (normalized.mentionUsernames.length > 0) {
|
|
5432
5605
|
headerLines.push(`mention_usernames: ${normalized.mentionUsernames.map((item) => `@${item}`).join(", ")}`);
|
|
5433
5606
|
}
|
|
5434
|
-
if (normalized.messageThreadID) {
|
|
5435
|
-
headerLines.push(`telegram_topic_id: ${normalized.messageThreadID}`);
|
|
5436
|
-
}
|
|
5437
5607
|
if (normalized.replyToMessageID > 0) {
|
|
5438
5608
|
headerLines.push(`reply_to_message_id: ${normalized.replyToMessageID}`);
|
|
5439
5609
|
headerLines.push(`reply_to_sender_is_bot: ${normalized.replyToFromIsBot ? "true" : "false"}`);
|
|
@@ -6149,6 +6319,7 @@ function stableTextModulo(rawValue, modulo = 1) {
|
|
|
6149
6319
|
return hash % normalizedModulo;
|
|
6150
6320
|
}
|
|
6151
6321
|
|
|
6322
|
+
/* Dead small_talk helper kept only as commented legacy code after lookup-only migration.
|
|
6152
6323
|
function buildRunnerSmallTalkReply({ route, executionPlan } = {}) {
|
|
6153
6324
|
const normalizedRoute = safeObject(route);
|
|
6154
6325
|
const roleProfileName = normalizeRunnerRoleProfileName(
|
|
@@ -6185,6 +6356,30 @@ function buildRunnerSmallTalkReply({ route, executionPlan } = {}) {
|
|
|
6185
6356
|
const templatePool = roleSpecificReplies[roleProfileName] || roleSpecificReplies.monitor;
|
|
6186
6357
|
return templatePool[stableTextModulo(`${displayName}:${roleProfileName}`, templatePool.length)];
|
|
6187
6358
|
}
|
|
6359
|
+
*/
|
|
6360
|
+
|
|
6361
|
+
function buildInformationalMiniExecutionOverride({ route, executionPlan } = {}) {
|
|
6362
|
+
const safeRoute = safeObject(route);
|
|
6363
|
+
const safeExecutionPlan = safeObject(executionPlan);
|
|
6364
|
+
const roleProfileName = normalizeRunnerRoleProfileName(
|
|
6365
|
+
safeExecutionPlan.roleProfileName || safeRoute.roleProfile || safeRoute.role || "monitor",
|
|
6366
|
+
) || "monitor";
|
|
6367
|
+
const lightweightModel = String(
|
|
6368
|
+
resolveResponderAdjudicatorModelDisplayName({ client: "gpt", env: process.env }) || "gpt-5.3-codex-spark",
|
|
6369
|
+
).trim() || "gpt-5.3-codex-spark";
|
|
6370
|
+
return {
|
|
6371
|
+
mode: "role_profile",
|
|
6372
|
+
role_profile_name: roleProfileName,
|
|
6373
|
+
role_profile: normalizeRunnerRoleProfile(roleProfileName, {
|
|
6374
|
+
client: "gpt",
|
|
6375
|
+
model: lightweightModel,
|
|
6376
|
+
permission_mode: "read_only",
|
|
6377
|
+
reasoning_effort: "low",
|
|
6378
|
+
}),
|
|
6379
|
+
workspace_dir: String(safeExecutionPlan.workspaceDir || safeRoute.workspaceDir || "").trim(),
|
|
6380
|
+
workspace_source: String(safeExecutionPlan.workspaceSource || "").trim(),
|
|
6381
|
+
};
|
|
6382
|
+
}
|
|
6188
6383
|
|
|
6189
6384
|
function summarizeRunnerRequestForStatusLookup(entryRaw) {
|
|
6190
6385
|
const entry = safeObject(entryRaw);
|
|
@@ -6411,13 +6606,23 @@ async function resolveInformationalQueryReply({
|
|
|
6411
6606
|
}) {
|
|
6412
6607
|
const normalizedIntentType = String(intentType || "").trim();
|
|
6413
6608
|
const messageText = String(safeObject(selectedRecord?.parsedArchive).body || "").trim();
|
|
6609
|
+
const executionOverride = buildInformationalMiniExecutionOverride({ route, executionPlan });
|
|
6414
6610
|
if (normalizedIntentType === "small_talk") {
|
|
6415
6611
|
return {
|
|
6416
6612
|
handled: true,
|
|
6417
|
-
|
|
6613
|
+
response_mode: "lookup_only",
|
|
6614
|
+
reply: "",
|
|
6418
6615
|
source: "small_talk",
|
|
6616
|
+
lookup: {
|
|
6617
|
+
intent_type: "small_talk",
|
|
6618
|
+
user_message: messageText,
|
|
6619
|
+
bot_name: firstNonEmptyString([route?.botName, route?.serverBotName, route?.server_bot_name, route?.name]),
|
|
6620
|
+
bot_role: String(route?.role || route?.roleProfile || "").trim(),
|
|
6621
|
+
},
|
|
6622
|
+
execution_override: executionOverride,
|
|
6419
6623
|
};
|
|
6420
6624
|
}
|
|
6625
|
+
/* Dead legacy direct small_talk branch kept commented for reference.
|
|
6421
6626
|
if (false && normalizedIntentType === "small_talk") {
|
|
6422
6627
|
return {
|
|
6423
6628
|
handled: true,
|
|
@@ -6425,6 +6630,7 @@ async function resolveInformationalQueryReply({
|
|
|
6425
6630
|
source: "small_talk",
|
|
6426
6631
|
};
|
|
6427
6632
|
}
|
|
6633
|
+
*/
|
|
6428
6634
|
if (normalizedIntentType === "workspace_query") {
|
|
6429
6635
|
const workspace = resolveProjectWorkspaceBindingSummary(route?.projectID, executionPlan?.workspaceDir || route?.workspaceDir || "");
|
|
6430
6636
|
const workspaceDir = String(workspace.workspace_dir || "").trim();
|
|
@@ -6433,9 +6639,13 @@ async function resolveInformationalQueryReply({
|
|
|
6433
6639
|
: "현재 이 프로젝트는 project-workspaces.json에 로컬 작업 폴더가 바인딩되어 있지 않습니다.";
|
|
6434
6640
|
return {
|
|
6435
6641
|
handled: true,
|
|
6436
|
-
|
|
6642
|
+
response_mode: "lookup_only",
|
|
6643
|
+
reply: "",
|
|
6437
6644
|
source: "project.workspace",
|
|
6438
|
-
lookup:
|
|
6645
|
+
lookup: {
|
|
6646
|
+
...workspace,
|
|
6647
|
+
},
|
|
6648
|
+
execution_override: executionOverride,
|
|
6439
6649
|
};
|
|
6440
6650
|
}
|
|
6441
6651
|
if (normalizedIntentType === "bot_role_query") {
|
|
@@ -6447,9 +6657,13 @@ async function resolveInformationalQueryReply({
|
|
|
6447
6657
|
});
|
|
6448
6658
|
return {
|
|
6449
6659
|
handled: true,
|
|
6450
|
-
|
|
6660
|
+
response_mode: "lookup_only",
|
|
6661
|
+
reply: "",
|
|
6451
6662
|
source: "project.bot_roles",
|
|
6452
|
-
lookup:
|
|
6663
|
+
lookup: {
|
|
6664
|
+
...payload,
|
|
6665
|
+
},
|
|
6666
|
+
execution_override: executionOverride,
|
|
6453
6667
|
};
|
|
6454
6668
|
}
|
|
6455
6669
|
if (normalizedIntentType === "status_query") {
|
|
@@ -6512,9 +6726,13 @@ async function resolveInformationalQueryReply({
|
|
|
6512
6726
|
});
|
|
6513
6727
|
return {
|
|
6514
6728
|
handled: true,
|
|
6515
|
-
|
|
6729
|
+
response_mode: "lookup_only",
|
|
6730
|
+
reply: "",
|
|
6516
6731
|
source: "project.file.locate",
|
|
6517
|
-
lookup:
|
|
6732
|
+
lookup: {
|
|
6733
|
+
...payload,
|
|
6734
|
+
},
|
|
6735
|
+
execution_override: executionOverride,
|
|
6518
6736
|
};
|
|
6519
6737
|
}
|
|
6520
6738
|
return null;
|
|
@@ -7142,6 +7360,7 @@ async function processRunnerRouteOnce(route, runtime, mode, options = {}) {
|
|
|
7142
7360
|
selectedRecord,
|
|
7143
7361
|
selectedBotUsernames: selectedResponderSelectors,
|
|
7144
7362
|
runtime,
|
|
7363
|
+
archiveThreadID: archiveThread.threadID,
|
|
7145
7364
|
});
|
|
7146
7365
|
};
|
|
7147
7366
|
if (deferExecution) {
|
|
@@ -14175,20 +14394,44 @@ async function runSelftest(flags = {}) {
|
|
|
14175
14394
|
String(parsedEnv.SLACK_BOT_TOKEN || "") === "xoxb-test",
|
|
14176
14395
|
`token=${String(parsedEnv.SLACK_BOT_TOKEN || "(missing)")}`,
|
|
14177
14396
|
);
|
|
14178
|
-
const
|
|
14179
|
-
|
|
14180
|
-
|
|
14397
|
+
const informationalMiniReply = await resolveInformationalQueryReply({
|
|
14398
|
+
intentType: "small_talk",
|
|
14399
|
+
route: { botName: "RyoAI_bot", role: "monitor", roleProfile: "monitor" },
|
|
14400
|
+
routeState: {},
|
|
14401
|
+
selectedRecord: {
|
|
14402
|
+
parsedArchive: {
|
|
14403
|
+
body: "@RyoAI_bot 하이",
|
|
14404
|
+
},
|
|
14405
|
+
},
|
|
14406
|
+
runtime: {},
|
|
14407
|
+
executionPlan: {
|
|
14408
|
+
mode: "role_profile",
|
|
14409
|
+
roleProfileName: "monitor",
|
|
14410
|
+
roleProfile: {
|
|
14411
|
+
client: "gpt",
|
|
14412
|
+
model: "gpt-5.4",
|
|
14413
|
+
permissionMode: "workspace_write",
|
|
14414
|
+
reasoningEffort: "medium",
|
|
14415
|
+
},
|
|
14416
|
+
workspaceDir: "C:\\selftest-workspace",
|
|
14417
|
+
workspaceSource: "selftest",
|
|
14418
|
+
},
|
|
14181
14419
|
});
|
|
14182
|
-
const
|
|
14183
|
-
|
|
14184
|
-
|
|
14420
|
+
const expectedInformationalModel = resolveResponderAdjudicatorModelDisplayName({
|
|
14421
|
+
client: "gpt",
|
|
14422
|
+
env: process.env,
|
|
14185
14423
|
});
|
|
14186
14424
|
push(
|
|
14187
|
-
"
|
|
14188
|
-
|
|
14189
|
-
&&
|
|
14190
|
-
&&
|
|
14191
|
-
|
|
14425
|
+
"small_talk_reply_uses_lookup_only_mini_override",
|
|
14426
|
+
safeObject(informationalMiniReply).handled === true
|
|
14427
|
+
&& String(safeObject(informationalMiniReply).response_mode || "") === "lookup_only"
|
|
14428
|
+
&& String(safeObject(informationalMiniReply).reply || "") === ""
|
|
14429
|
+
&& !Object.prototype.hasOwnProperty.call(safeObject(safeObject(informationalMiniReply).lookup), "proposed_summary")
|
|
14430
|
+
&& String(safeObject(safeObject(informationalMiniReply).execution_override).role_profile?.client || "") === "gpt"
|
|
14431
|
+
&& String(safeObject(safeObject(informationalMiniReply).execution_override).role_profile?.model || "") === String(expectedInformationalModel || "")
|
|
14432
|
+
&& String(safeObject(safeObject(informationalMiniReply).execution_override).role_profile?.permissionMode || "") === "read_only"
|
|
14433
|
+
&& String(safeObject(safeObject(informationalMiniReply).execution_override).role_profile?.reasoningEffort || "") === "low",
|
|
14434
|
+
JSON.stringify(safeObject(informationalMiniReply).execution_override || {}),
|
|
14192
14435
|
);
|
|
14193
14436
|
const telegramEnvV2Parsed = parseSimpleEnvText(`
|
|
14194
14437
|
TELEGRAM_API_BASE_URL=http://127.0.0.1:8999/api
|
|
@@ -1786,9 +1786,6 @@ export function buildLocalBotPrompt(payload, { terse = true } = {}) {
|
|
|
1786
1786
|
if (queryLookupResponseMode) {
|
|
1787
1787
|
lines.push(`- Response mode: ${queryLookupResponseMode}`);
|
|
1788
1788
|
}
|
|
1789
|
-
if (String(queryLookup.proposed_reply || "").trim()) {
|
|
1790
|
-
lines.push(`- Proposed factual reply: ${String(queryLookup.proposed_reply || "").trim()}`);
|
|
1791
|
-
}
|
|
1792
1789
|
if (queryLookupFacts != null) {
|
|
1793
1790
|
lines.push("Structured lookup facts:");
|
|
1794
1791
|
lines.push(JSON.stringify(queryLookupFacts, null, 2));
|
|
@@ -1994,7 +1991,7 @@ export function buildLocalBotPrompt(payload, { terse = true } = {}) {
|
|
|
1994
1991
|
String(conversation.intent_mode || "").trim() === "delegated_single_lead"
|
|
1995
1992
|
? (selfIsLeadBot
|
|
1996
1993
|
? "This bot is the lead bot for a delegated public collaboration. It may assign work publicly only to allowed responders, and it may not expand the participant set."
|
|
1997
|
-
: "This bot is not the lead bot.
|
|
1994
|
+
: "This bot is not the lead bot. Prefer replying when the human, the lead bot, or another managed bot explicitly addresses this bot in the live room context. Do not expand the participant set beyond the allowed responders.")
|
|
1998
1995
|
: "Use the human conversation contract as the source of truth for who may reply.",
|
|
1999
1996
|
conversation.allow_bot_to_bot === true
|
|
2000
1997
|
? "If another bot explicitly mentioned you and you are in the allowed responders list, you may answer that bot publicly in the room."
|
package/lib/runner-data.mjs
CHANGED
|
@@ -827,6 +827,7 @@ export async function discoverArchiveThreadForDestination(
|
|
|
827
827
|
const providerEnvConfig = requireDependency(deps, "providerEnvConfig");
|
|
828
828
|
const parseArchivedChatComment = requireDependency(deps, "parseArchivedChatComment");
|
|
829
829
|
const providerLabel = providerEnvConfig(provider).label;
|
|
830
|
+
const hasConfiguredArchiveWorkItem = archiveWorkItemID && isUUID(archiveWorkItemID);
|
|
830
831
|
|
|
831
832
|
if (archiveThreadID && isUUID(archiveThreadID)) {
|
|
832
833
|
return {
|
|
@@ -837,8 +838,7 @@ export async function discoverArchiveThreadForDestination(
|
|
|
837
838
|
}
|
|
838
839
|
|
|
839
840
|
const candidateWorkItemIDs = [];
|
|
840
|
-
|
|
841
|
-
if (archiveWorkItemID && isUUID(archiveWorkItemID)) {
|
|
841
|
+
if (hasConfiguredArchiveWorkItem) {
|
|
842
842
|
candidateWorkItemIDs.push(archiveWorkItemID);
|
|
843
843
|
} else {
|
|
844
844
|
const workItems = await listProjectWorkItems({
|
|
@@ -864,11 +864,9 @@ export async function discoverArchiveThreadForDestination(
|
|
|
864
864
|
token,
|
|
865
865
|
timeoutSeconds,
|
|
866
866
|
}, deps);
|
|
867
|
-
let fallbackThreadID = "";
|
|
868
867
|
for (const thread of threads) {
|
|
869
868
|
const threadID = String(thread.id || "").trim();
|
|
870
869
|
if (!threadID) continue;
|
|
871
|
-
if (!fallbackThreadID) fallbackThreadID = threadID;
|
|
872
870
|
const comments = await listThreadComments({
|
|
873
871
|
siteBaseURL,
|
|
874
872
|
threadID,
|
|
@@ -889,15 +887,8 @@ export async function discoverArchiveThreadForDestination(
|
|
|
889
887
|
};
|
|
890
888
|
}
|
|
891
889
|
}
|
|
892
|
-
if (
|
|
893
|
-
|
|
894
|
-
threadID: fallbackThreadID,
|
|
895
|
-
workItemID,
|
|
896
|
-
source: "fallback-thread",
|
|
897
|
-
};
|
|
898
|
-
}
|
|
899
|
-
if (!reusableWorkItemID) {
|
|
900
|
-
reusableWorkItemID = workItemID;
|
|
890
|
+
if (hasConfiguredArchiveWorkItem) {
|
|
891
|
+
break;
|
|
901
892
|
}
|
|
902
893
|
}
|
|
903
894
|
|
|
@@ -907,7 +898,9 @@ export async function discoverArchiveThreadForDestination(
|
|
|
907
898
|
const archiveDescription = `Auto-created archive work item for ${providerLabel} destination ${destinationLabel}.`;
|
|
908
899
|
try {
|
|
909
900
|
const threadBody = `Auto-created archive thread for ${providerLabel} destination ${destinationLabel} (chat_id=${destination.chatID}).`;
|
|
910
|
-
let resolvedWorkItemID =
|
|
901
|
+
let resolvedWorkItemID = hasConfiguredArchiveWorkItem
|
|
902
|
+
? String(archiveWorkItemID || "").trim()
|
|
903
|
+
: "";
|
|
911
904
|
if (!resolvedWorkItemID) {
|
|
912
905
|
const createdWorkItem = await createProjectWorkItem(
|
|
913
906
|
{
|
|
@@ -941,7 +934,9 @@ export async function discoverArchiveThreadForDestination(
|
|
|
941
934
|
return {
|
|
942
935
|
threadID: createdThreadID,
|
|
943
936
|
workItemID: resolvedWorkItemID,
|
|
944
|
-
source:
|
|
937
|
+
source: hasConfiguredArchiveWorkItem
|
|
938
|
+
? "auto-created-thread-on-configured-work-item"
|
|
939
|
+
: "auto-created-thread",
|
|
945
940
|
};
|
|
946
941
|
}
|
|
947
942
|
}
|