metheus-governance-mcp-cli 0.2.207 → 0.2.209
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 +204 -55
- package/lib/local-ai-adapters.mjs +21 -1
- package/lib/runner-delivery.mjs +8 -1
- package/lib/runner-orchestration.mjs +380 -159
- package/lib/runner-trigger.mjs +8 -2
- package/lib/selftest-runner-scenarios.mjs +12320 -12209
- package/package.json +1 -1
package/cli.mjs
CHANGED
|
@@ -2623,7 +2623,7 @@ function inferRunnerRequestClaimIntent(selectedRecord) {
|
|
|
2623
2623
|
if (looksLikeRunnerClaimQuestion(rawText) && normalizedText.split(/\s+/).filter(Boolean).length <= 8) {
|
|
2624
2624
|
return "status_query";
|
|
2625
2625
|
}
|
|
2626
|
-
return "
|
|
2626
|
+
return "";
|
|
2627
2627
|
}
|
|
2628
2628
|
|
|
2629
2629
|
function resolveRunnerRequestClaimIntent({
|
|
@@ -2634,7 +2634,8 @@ function resolveRunnerRequestClaimIntent({
|
|
|
2634
2634
|
if (explicitIntent) {
|
|
2635
2635
|
return explicitIntent;
|
|
2636
2636
|
}
|
|
2637
|
-
|
|
2637
|
+
const inferredIntent = inferRunnerRequestClaimIntent(selectedRecord);
|
|
2638
|
+
return inferredIntent === "status_query" ? inferredIntent : "";
|
|
2638
2639
|
}
|
|
2639
2640
|
|
|
2640
2641
|
function buildSyntheticReplyChainConversationID(normalizedRoute, chatID, anchorMessageID) {
|
|
@@ -2647,6 +2648,16 @@ function buildSyntheticReplyChainConversationID(normalizedRoute, chatID, anchorM
|
|
|
2647
2648
|
return `reply_chain:${provider}:${normalizedChatID}:${normalizedAnchorMessageID}`;
|
|
2648
2649
|
}
|
|
2649
2650
|
|
|
2651
|
+
function buildSyntheticHumanOpeningConversationID(normalizedRoute, chatID, messageID) {
|
|
2652
|
+
const provider = String(normalizedRoute?.provider || "").trim() || "unknown";
|
|
2653
|
+
const normalizedChatID = String(chatID || "").trim() || "-";
|
|
2654
|
+
const normalizedMessageID = intFromRawAllowZero(messageID, 0);
|
|
2655
|
+
if (normalizedMessageID <= 0) {
|
|
2656
|
+
return "";
|
|
2657
|
+
}
|
|
2658
|
+
return `human_opening:${provider}:${normalizedChatID}:${normalizedMessageID}`;
|
|
2659
|
+
}
|
|
2660
|
+
|
|
2650
2661
|
function findRunnerRequestsForScope(state, normalizedRoute, selectors = {}) {
|
|
2651
2662
|
const requests = normalizeBotRunnerRequests(state?.requests);
|
|
2652
2663
|
const projectID = String(normalizedRoute?.projectID || "").trim();
|
|
@@ -3259,13 +3270,17 @@ async function claimRunnerRequestForHumanComment({
|
|
|
3259
3270
|
normalizedIntent,
|
|
3260
3271
|
selectedRecord,
|
|
3261
3272
|
});
|
|
3262
|
-
|
|
3273
|
+
let stateForClaim = safeObject(replyChainResolution.state);
|
|
3274
|
+
const normalizedSharedHumanIntent = safeObject(sharedHumanIntent);
|
|
3275
|
+
const provisionalNormalizedIntent = String(
|
|
3276
|
+
normalizedSharedHumanIntent.intentType || resolvedNormalizedIntent || "",
|
|
3277
|
+
).trim().toLowerCase();
|
|
3278
|
+
const provisionalRequestKey = buildRunnerRequestKey({
|
|
3263
3279
|
normalizedRoute,
|
|
3264
3280
|
selectedRecord,
|
|
3265
3281
|
selectedBotUsernames,
|
|
3266
|
-
normalizedIntent:
|
|
3282
|
+
normalizedIntent: provisionalNormalizedIntent,
|
|
3267
3283
|
});
|
|
3268
|
-
let stateForClaim = safeObject(replyChainResolution.state);
|
|
3269
3284
|
const baseConversationID = String(
|
|
3270
3285
|
parsed.conversationID
|
|
3271
3286
|
|| replyChainContext.conversationID
|
|
@@ -3285,9 +3300,6 @@ async function claimRunnerRequestForHumanComment({
|
|
|
3285
3300
|
requests: backfilled.requests,
|
|
3286
3301
|
};
|
|
3287
3302
|
}
|
|
3288
|
-
const requests = normalizeBotRunnerRequests(stateForClaim.requests);
|
|
3289
|
-
const existing = safeObject(requests[requestKey]);
|
|
3290
|
-
const normalizedSharedHumanIntent = safeObject(sharedHumanIntent);
|
|
3291
3303
|
const currentMessageID = intFromRawAllowZero(parsed.messageID, 0);
|
|
3292
3304
|
let sharedConversationSource = currentMessageID > 0
|
|
3293
3305
|
? pickRunnerSharedConversationSourceRequest(
|
|
@@ -3295,7 +3307,7 @@ async function claimRunnerRequestForHumanComment({
|
|
|
3295
3307
|
chatID: String(parsed.chatID || parsed.chatId || "").trim(),
|
|
3296
3308
|
messageID: currentMessageID,
|
|
3297
3309
|
}),
|
|
3298
|
-
|
|
3310
|
+
provisionalRequestKey,
|
|
3299
3311
|
)
|
|
3300
3312
|
: {};
|
|
3301
3313
|
if (
|
|
@@ -3309,14 +3321,36 @@ async function claimRunnerRequestForHumanComment({
|
|
|
3309
3321
|
runtime,
|
|
3310
3322
|
chatID: String(parsed.chatID || parsed.chatId || "").trim(),
|
|
3311
3323
|
messageID: currentMessageID,
|
|
3312
|
-
excludeRequestKey:
|
|
3324
|
+
excludeRequestKey: provisionalRequestKey,
|
|
3313
3325
|
}));
|
|
3314
3326
|
}
|
|
3315
3327
|
const resolvedConversationID = String(
|
|
3316
3328
|
baseConversationID
|
|
3317
3329
|
|| sharedConversationSource.conversation_id
|
|
3330
|
+
|| (
|
|
3331
|
+
Object.keys(normalizedSharedHumanIntent).length > 0
|
|
3332
|
+
? buildSyntheticHumanOpeningConversationID(
|
|
3333
|
+
normalizedRoute,
|
|
3334
|
+
String(parsed.chatID || parsed.chatId || "").trim(),
|
|
3335
|
+
currentMessageID,
|
|
3336
|
+
)
|
|
3337
|
+
: ""
|
|
3338
|
+
)
|
|
3318
3339
|
|| "",
|
|
3319
3340
|
).trim();
|
|
3341
|
+
const preferredNormalizedIntent = String(
|
|
3342
|
+
normalizedSharedHumanIntent.intentType
|
|
3343
|
+
|| resolvedNormalizedIntent
|
|
3344
|
+
|| "",
|
|
3345
|
+
).trim().toLowerCase();
|
|
3346
|
+
const requestKey = buildRunnerRequestKey({
|
|
3347
|
+
normalizedRoute,
|
|
3348
|
+
selectedRecord,
|
|
3349
|
+
selectedBotUsernames,
|
|
3350
|
+
normalizedIntent: preferredNormalizedIntent,
|
|
3351
|
+
});
|
|
3352
|
+
const requests = normalizeBotRunnerRequests(stateForClaim.requests);
|
|
3353
|
+
const existing = safeObject(requests[requestKey]);
|
|
3320
3354
|
if (isFinalRunnerRequestStatus(existing.status)) {
|
|
3321
3355
|
return {
|
|
3322
3356
|
ok: false,
|
|
@@ -3346,50 +3380,70 @@ async function claimRunnerRequestForHumanComment({
|
|
|
3346
3380
|
conversation_id: resolvedConversationID,
|
|
3347
3381
|
selected_bot_usernames: uniqueOrderedStrings(selectedBotUsernames, normalizeTelegramMentionUsername),
|
|
3348
3382
|
conversation_intent_mode: String(
|
|
3349
|
-
|
|
3383
|
+
normalizedSharedHumanIntent.intentMode
|
|
3384
|
+
|| existing.conversation_intent_mode
|
|
3385
|
+
|| sharedConversationSource.conversation_intent_mode
|
|
3386
|
+
|| referencedRequest.conversation_intent_mode
|
|
3387
|
+
|| "",
|
|
3350
3388
|
).trim().toLowerCase(),
|
|
3351
3389
|
conversation_lead_bot: normalizeTelegramMentionUsername(
|
|
3352
|
-
|
|
3390
|
+
normalizedSharedHumanIntent.leadBotSelector
|
|
3391
|
+
|| existing.conversation_lead_bot
|
|
3392
|
+
|| sharedConversationSource.conversation_lead_bot
|
|
3393
|
+
|| referencedRequest.conversation_lead_bot,
|
|
3353
3394
|
),
|
|
3354
3395
|
conversation_summary_bot: normalizeTelegramMentionUsername(
|
|
3355
|
-
|
|
3396
|
+
normalizedSharedHumanIntent.summaryBotSelector
|
|
3397
|
+
|| existing.conversation_summary_bot
|
|
3398
|
+
|| sharedConversationSource.conversation_summary_bot
|
|
3399
|
+
|| referencedRequest.conversation_summary_bot,
|
|
3356
3400
|
),
|
|
3357
3401
|
conversation_participants: uniqueOrderedStrings(
|
|
3358
|
-
ensureArray(
|
|
3359
|
-
?
|
|
3360
|
-
: ensureArray(
|
|
3361
|
-
?
|
|
3362
|
-
: ensureArray(
|
|
3363
|
-
?
|
|
3364
|
-
:
|
|
3402
|
+
ensureArray(normalizedSharedHumanIntent.participantSelectors).length
|
|
3403
|
+
? normalizedSharedHumanIntent.participantSelectors
|
|
3404
|
+
: ensureArray(existing.conversation_participants).length
|
|
3405
|
+
? existing.conversation_participants
|
|
3406
|
+
: ensureArray(sharedConversationSource.conversation_participants).length
|
|
3407
|
+
? sharedConversationSource.conversation_participants
|
|
3408
|
+
: ensureArray(referencedRequest.conversation_participants).length
|
|
3409
|
+
? referencedRequest.conversation_participants
|
|
3410
|
+
: [],
|
|
3365
3411
|
normalizeTelegramMentionUsername,
|
|
3366
3412
|
),
|
|
3367
3413
|
conversation_initial_responders: uniqueOrderedStrings(
|
|
3368
|
-
ensureArray(
|
|
3369
|
-
?
|
|
3370
|
-
: ensureArray(
|
|
3371
|
-
?
|
|
3372
|
-
: ensureArray(
|
|
3373
|
-
?
|
|
3374
|
-
:
|
|
3414
|
+
ensureArray(normalizedSharedHumanIntent.initialResponderSelectors).length
|
|
3415
|
+
? normalizedSharedHumanIntent.initialResponderSelectors
|
|
3416
|
+
: ensureArray(existing.conversation_initial_responders).length
|
|
3417
|
+
? existing.conversation_initial_responders
|
|
3418
|
+
: ensureArray(sharedConversationSource.conversation_initial_responders).length
|
|
3419
|
+
? sharedConversationSource.conversation_initial_responders
|
|
3420
|
+
: ensureArray(referencedRequest.conversation_initial_responders).length
|
|
3421
|
+
? referencedRequest.conversation_initial_responders
|
|
3422
|
+
: [],
|
|
3375
3423
|
normalizeTelegramMentionUsername,
|
|
3376
3424
|
),
|
|
3377
3425
|
conversation_allowed_responders: uniqueOrderedStrings(
|
|
3378
|
-
ensureArray(
|
|
3379
|
-
?
|
|
3380
|
-
: ensureArray(
|
|
3381
|
-
?
|
|
3382
|
-
: ensureArray(
|
|
3383
|
-
?
|
|
3384
|
-
:
|
|
3426
|
+
ensureArray(normalizedSharedHumanIntent.allowedResponderSelectors).length
|
|
3427
|
+
? normalizedSharedHumanIntent.allowedResponderSelectors
|
|
3428
|
+
: ensureArray(existing.conversation_allowed_responders).length
|
|
3429
|
+
? existing.conversation_allowed_responders
|
|
3430
|
+
: ensureArray(sharedConversationSource.conversation_allowed_responders).length
|
|
3431
|
+
? sharedConversationSource.conversation_allowed_responders
|
|
3432
|
+
: ensureArray(referencedRequest.conversation_allowed_responders).length
|
|
3433
|
+
? referencedRequest.conversation_allowed_responders
|
|
3434
|
+
: [],
|
|
3385
3435
|
normalizeTelegramMentionUsername,
|
|
3386
3436
|
),
|
|
3387
|
-
conversation_allow_bot_to_bot:
|
|
3437
|
+
conversation_allow_bot_to_bot: normalizedSharedHumanIntent.allowBotToBot === true
|
|
3438
|
+
|| existing.conversation_allow_bot_to_bot === true
|
|
3388
3439
|
|| sharedConversationSource.conversation_allow_bot_to_bot === true
|
|
3389
|
-
|| referencedRequest.conversation_allow_bot_to_bot === true
|
|
3390
|
-
|| normalizedSharedHumanIntent.allowBotToBot === true,
|
|
3440
|
+
|| referencedRequest.conversation_allow_bot_to_bot === true,
|
|
3391
3441
|
conversation_reply_expectation: String(
|
|
3392
|
-
|
|
3442
|
+
normalizedSharedHumanIntent.replyExpectation
|
|
3443
|
+
|| existing.conversation_reply_expectation
|
|
3444
|
+
|| sharedConversationSource.conversation_reply_expectation
|
|
3445
|
+
|| referencedRequest.conversation_reply_expectation
|
|
3446
|
+
|| "",
|
|
3393
3447
|
).trim().toLowerCase(),
|
|
3394
3448
|
execution_contract_type: String(
|
|
3395
3449
|
existing.execution_contract_type || sharedConversationSource.execution_contract_type || referencedRequest.execution_contract_type || "",
|
|
@@ -3412,10 +3466,10 @@ async function claimRunnerRequestForHumanComment({
|
|
|
3412
3466
|
? sharedConversationSource.next_expected_responders
|
|
3413
3467
|
: ensureArray(referencedRequest.next_expected_responders).length
|
|
3414
3468
|
? referencedRequest.next_expected_responders
|
|
3415
|
-
:
|
|
3469
|
+
: [],
|
|
3416
3470
|
normalizeTelegramMentionUsername,
|
|
3417
3471
|
),
|
|
3418
|
-
normalized_intent:
|
|
3472
|
+
normalized_intent: String(preferredNormalizedIntent || existing.normalized_intent || "").trim().toLowerCase(),
|
|
3419
3473
|
status: "claimed",
|
|
3420
3474
|
claimed_by_route: String(routeKey || "").trim(),
|
|
3421
3475
|
claimed_at: firstNonEmptyString([existing.claimed_at, nowISO]) || nowISO,
|
|
@@ -3466,6 +3520,89 @@ function isActionableRunnerRequestIntent(rawIntent) {
|
|
|
3466
3520
|
return Boolean(normalizedIntent) && !isInformationalRunnerRequestIntent(normalizedIntent);
|
|
3467
3521
|
}
|
|
3468
3522
|
|
|
3523
|
+
function runnerRequestHasConversationContract(requestRaw) {
|
|
3524
|
+
const request = safeObject(requestRaw);
|
|
3525
|
+
return Boolean(
|
|
3526
|
+
String(request.conversation_id || "").trim()
|
|
3527
|
+
|| String(request.conversation_intent_mode || "").trim()
|
|
3528
|
+
|| String(request.conversation_reply_expectation || "").trim()
|
|
3529
|
+
|| ensureArray(request.conversation_participants).length
|
|
3530
|
+
|| ensureArray(request.conversation_initial_responders).length
|
|
3531
|
+
|| ensureArray(request.conversation_allowed_responders).length
|
|
3532
|
+
);
|
|
3533
|
+
}
|
|
3534
|
+
|
|
3535
|
+
function runnerRequestHasCompleteConversationContract(requestRaw) {
|
|
3536
|
+
const request = safeObject(requestRaw);
|
|
3537
|
+
const intentMode = String(request.conversation_intent_mode || "").trim().toLowerCase();
|
|
3538
|
+
const conversationID = String(request.conversation_id || "").trim();
|
|
3539
|
+
const replyExpectation = String(request.conversation_reply_expectation || "").trim().toLowerCase();
|
|
3540
|
+
const participants = ensureArray(request.conversation_participants);
|
|
3541
|
+
const initialResponders = ensureArray(request.conversation_initial_responders);
|
|
3542
|
+
const allowedResponders = ensureArray(request.conversation_allowed_responders);
|
|
3543
|
+
if (!runnerRequestHasConversationContract(request)) {
|
|
3544
|
+
return false;
|
|
3545
|
+
}
|
|
3546
|
+
if (!conversationID || !intentMode || !replyExpectation) {
|
|
3547
|
+
return false;
|
|
3548
|
+
}
|
|
3549
|
+
if (intentMode === "single_bot") {
|
|
3550
|
+
return allowedResponders.length > 0 || participants.length > 0;
|
|
3551
|
+
}
|
|
3552
|
+
return participants.length > 0 && initialResponders.length > 0 && allowedResponders.length > 0;
|
|
3553
|
+
}
|
|
3554
|
+
|
|
3555
|
+
function runnerRequestHasExecutionContract(requestRaw) {
|
|
3556
|
+
const request = safeObject(requestRaw);
|
|
3557
|
+
return Boolean(
|
|
3558
|
+
String(request.execution_contract_type || "").trim()
|
|
3559
|
+
|| request.execution_contract_actionable === true
|
|
3560
|
+
|| ensureArray(request.execution_contract_targets).length
|
|
3561
|
+
|| ensureArray(request.next_expected_responders).length
|
|
3562
|
+
);
|
|
3563
|
+
}
|
|
3564
|
+
|
|
3565
|
+
function runnerRequestHasCompleteExecutionContract(requestRaw) {
|
|
3566
|
+
const request = safeObject(requestRaw);
|
|
3567
|
+
const executionContractType = String(request.execution_contract_type || "").trim().toLowerCase();
|
|
3568
|
+
const executionTargets = ensureArray(request.execution_contract_targets);
|
|
3569
|
+
const nextExpectedResponders = ensureArray(request.next_expected_responders);
|
|
3570
|
+
if (!runnerRequestHasExecutionContract(request)) {
|
|
3571
|
+
return false;
|
|
3572
|
+
}
|
|
3573
|
+
if (!executionContractType) {
|
|
3574
|
+
return false;
|
|
3575
|
+
}
|
|
3576
|
+
if (executionContractType === "delegation") {
|
|
3577
|
+
return executionTargets.length > 0 || nextExpectedResponders.length > 0;
|
|
3578
|
+
}
|
|
3579
|
+
if (executionContractType === "summary_request") {
|
|
3580
|
+
return nextExpectedResponders.length > 0 || executionTargets.length > 0;
|
|
3581
|
+
}
|
|
3582
|
+
return true;
|
|
3583
|
+
}
|
|
3584
|
+
|
|
3585
|
+
function runnerRequestHasContractSignals(requestRaw) {
|
|
3586
|
+
const request = safeObject(requestRaw);
|
|
3587
|
+
return runnerRequestHasConversationContract(request) || runnerRequestHasExecutionContract(request);
|
|
3588
|
+
}
|
|
3589
|
+
|
|
3590
|
+
function runnerRequestRequiresActionableContract(requestRaw) {
|
|
3591
|
+
const request = safeObject(requestRaw);
|
|
3592
|
+
const replyExpectation = String(request.conversation_reply_expectation || "").trim().toLowerCase();
|
|
3593
|
+
const executionContractType = String(request.execution_contract_type || "").trim().toLowerCase();
|
|
3594
|
+
if (request.execution_contract_actionable === true) {
|
|
3595
|
+
return true;
|
|
3596
|
+
}
|
|
3597
|
+
if (replyExpectation === "actionable") {
|
|
3598
|
+
return true;
|
|
3599
|
+
}
|
|
3600
|
+
if (["delegation", "direct_result"].includes(executionContractType)) {
|
|
3601
|
+
return true;
|
|
3602
|
+
}
|
|
3603
|
+
return false;
|
|
3604
|
+
}
|
|
3605
|
+
|
|
3469
3606
|
function loadRunnerRequestByKey(requestKey) {
|
|
3470
3607
|
const key = String(requestKey || "").trim();
|
|
3471
3608
|
if (!key) {
|
|
@@ -3477,7 +3614,7 @@ function loadRunnerRequestByKey(requestKey) {
|
|
|
3477
3614
|
function actionableRunnerRequestMissingRootWorkItem(requestRaw) {
|
|
3478
3615
|
const request = safeObject(requestRaw);
|
|
3479
3616
|
return (
|
|
3480
|
-
|
|
3617
|
+
runnerRequestRequiresActionableContract(request)
|
|
3481
3618
|
&& !String(request.root_work_item_id || "").trim()
|
|
3482
3619
|
);
|
|
3483
3620
|
}
|
|
@@ -3789,7 +3926,7 @@ async function ensureRunnerRootWorkItemForRequest({
|
|
|
3789
3926
|
requestKey: key,
|
|
3790
3927
|
};
|
|
3791
3928
|
}
|
|
3792
|
-
if (!
|
|
3929
|
+
if (!runnerRequestRequiresActionableContract(existing)) {
|
|
3793
3930
|
return {
|
|
3794
3931
|
ok: true,
|
|
3795
3932
|
requestKey: key,
|
|
@@ -4181,7 +4318,7 @@ function resolveRunnerContinuationRequestForBotReply({
|
|
|
4181
4318
|
execution_contract_actionable: session.last_execution_contract_actionable === true,
|
|
4182
4319
|
execution_contract_targets: ensureArray(session.last_execution_contract_targets),
|
|
4183
4320
|
next_expected_responders: ensureArray(session.next_expected_responders),
|
|
4184
|
-
normalized_intent: String(
|
|
4321
|
+
normalized_intent: String(fallbackRequest.normalized_intent || "").trim().toLowerCase(),
|
|
4185
4322
|
status: "running",
|
|
4186
4323
|
claimed_by_route: String(sessionMatch.routeKey || "").trim(),
|
|
4187
4324
|
claimed_at: firstNonEmptyString([session.started_at, nowISO]),
|
|
@@ -4298,6 +4435,26 @@ function markRunnerRequestLifecycle({
|
|
|
4298
4435
|
normalizeTelegramMentionUsername,
|
|
4299
4436
|
).filter((selector) => selector && selector !== normalizedCurrentBotSelector);
|
|
4300
4437
|
const shouldRemainRunningAfterReply = continuationSelectors.length > 0;
|
|
4438
|
+
const nextConversationIntentMode = String(
|
|
4439
|
+
conversationIntentMode
|
|
4440
|
+
|| existing.conversation_intent_mode
|
|
4441
|
+
|| "",
|
|
4442
|
+
).trim().toLowerCase();
|
|
4443
|
+
const nextExecutionContractType = String(
|
|
4444
|
+
executionContractType
|
|
4445
|
+
|| existing.execution_contract_type
|
|
4446
|
+
|| "",
|
|
4447
|
+
).trim().toLowerCase();
|
|
4448
|
+
const nextNormalizedIntent = (() => {
|
|
4449
|
+
const explicitIntent = String(normalizedIntent || "").trim().toLowerCase();
|
|
4450
|
+
if (explicitIntent) {
|
|
4451
|
+
return explicitIntent;
|
|
4452
|
+
}
|
|
4453
|
+
if (nextConversationIntentMode && !nextExecutionContractType) {
|
|
4454
|
+
return "";
|
|
4455
|
+
}
|
|
4456
|
+
return String(existing.normalized_intent || "").trim().toLowerCase();
|
|
4457
|
+
})();
|
|
4301
4458
|
const normalizedOutcome = String(outcome || "").trim().toLowerCase();
|
|
4302
4459
|
const nextStatus = (() => {
|
|
4303
4460
|
if (normalizedOutcome === "claimed") return "claimed";
|
|
@@ -4329,11 +4486,7 @@ function markRunnerRequestLifecycle({
|
|
|
4329
4486
|
ensureArray(allowedResponders).length ? allowedResponders : existing.conversation_allowed_responders,
|
|
4330
4487
|
normalizeTelegramMentionUsername,
|
|
4331
4488
|
),
|
|
4332
|
-
conversation_intent_mode:
|
|
4333
|
-
conversationIntentMode
|
|
4334
|
-
|| existing.conversation_intent_mode
|
|
4335
|
-
|| "",
|
|
4336
|
-
).trim().toLowerCase(),
|
|
4489
|
+
conversation_intent_mode: nextConversationIntentMode,
|
|
4337
4490
|
conversation_lead_bot: normalizeTelegramMentionUsername(
|
|
4338
4491
|
conversationLeadBot
|
|
4339
4492
|
|| existing.conversation_lead_bot
|
|
@@ -4351,11 +4504,7 @@ function markRunnerRequestLifecycle({
|
|
|
4351
4504
|
|| existing.conversation_reply_expectation
|
|
4352
4505
|
|| "",
|
|
4353
4506
|
).trim().toLowerCase(),
|
|
4354
|
-
execution_contract_type:
|
|
4355
|
-
executionContractType
|
|
4356
|
-
|| existing.execution_contract_type
|
|
4357
|
-
|| "",
|
|
4358
|
-
).trim().toLowerCase(),
|
|
4507
|
+
execution_contract_type: nextExecutionContractType,
|
|
4359
4508
|
execution_contract_actionable: executionContractActionable === true
|
|
4360
4509
|
|| existing.execution_contract_actionable === true,
|
|
4361
4510
|
execution_contract_targets: uniqueOrderedStrings(
|
|
@@ -4366,7 +4515,7 @@ function markRunnerRequestLifecycle({
|
|
|
4366
4515
|
ensureArray(nextExpectedResponders).length ? nextExpectedResponders : existing.next_expected_responders,
|
|
4367
4516
|
normalizeTelegramMentionUsername,
|
|
4368
4517
|
),
|
|
4369
|
-
normalized_intent:
|
|
4518
|
+
normalized_intent: nextNormalizedIntent,
|
|
4370
4519
|
status: nextStatus,
|
|
4371
4520
|
started_at: firstNonEmptyString([existing.started_at, nowISO]),
|
|
4372
4521
|
completed_at: nextStatus === "completed" ? nowISO : String(existing.completed_at || "").trim(),
|
|
@@ -4807,7 +4956,7 @@ async function syncRunnerRequestLedgerForProjectToServer({ normalizedRoute, runt
|
|
|
4807
4956
|
})[String(request.request_key || "").trim()]
|
|
4808
4957
|
: request;
|
|
4809
4958
|
if (
|
|
4810
|
-
|
|
4959
|
+
runnerRequestRequiresActionableContract(recoveredRequest)
|
|
4811
4960
|
&& !String(recoveredRequest.root_work_item_id || "").trim()
|
|
4812
4961
|
) {
|
|
4813
4962
|
continue;
|
|
@@ -949,7 +949,7 @@ function normalizeExecutionContract(rawContract) {
|
|
|
949
949
|
|| contract.target_summary_bot
|
|
950
950
|
|| "",
|
|
951
951
|
).trim().replace(/^@+/, "").toLowerCase();
|
|
952
|
-
const
|
|
952
|
+
const explicitNextResponders = uniqueOrdered(
|
|
953
953
|
ensureArray(contract.next_responders || contract.nextResponders || contract.responders)
|
|
954
954
|
.map((item) => String(item || "").trim().replace(/^@+/, "").toLowerCase())
|
|
955
955
|
.filter(Boolean),
|
|
@@ -962,6 +962,13 @@ function normalizeExecutionContract(rawContract) {
|
|
|
962
962
|
].includes(type)
|
|
963
963
|
? type
|
|
964
964
|
: "";
|
|
965
|
+
const nextResponders = explicitNextResponders.length > 0
|
|
966
|
+
? explicitNextResponders
|
|
967
|
+
: normalizedType === "delegation"
|
|
968
|
+
? uniqueOrdered(assignments.map((item) => String(item.target_bot || item.targetBot || "").trim().replace(/^@+/, "").toLowerCase()).filter(Boolean))
|
|
969
|
+
: normalizedType === "summary_request" && summaryBot
|
|
970
|
+
? [summaryBot]
|
|
971
|
+
: [];
|
|
965
972
|
const actionable = contract.actionable === true
|
|
966
973
|
|| (normalizedType === "delegation" && assignments.length > 0)
|
|
967
974
|
|| (normalizedType === "summary_request" && Boolean(summaryBot))
|
|
@@ -2078,7 +2085,9 @@ export function serializeLocalAIResult(result) {
|
|
|
2078
2085
|
function buildConversationIntentAnalysisPrompt({
|
|
2079
2086
|
messageText,
|
|
2080
2087
|
managedBots,
|
|
2088
|
+
contractGuardrail = null,
|
|
2081
2089
|
}) {
|
|
2090
|
+
const guardrail = safeObject(contractGuardrail);
|
|
2082
2091
|
const bots = ensureArray(managedBots).map((item) => {
|
|
2083
2092
|
const bot = safeObject(item);
|
|
2084
2093
|
return {
|
|
@@ -2122,6 +2131,15 @@ function buildConversationIntentAnalysisPrompt({
|
|
|
2122
2131
|
"- 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.",
|
|
2123
2132
|
"- 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.",
|
|
2124
2133
|
"- reply_expectation=informational when the human is only asking for explanation, status, location, clarification, discussion, review, brainstorming, or other non-execution information.",
|
|
2134
|
+
guardrail.require_complete_contract === true
|
|
2135
|
+
? "- Contract guardrail: do not leave intent_type, reply_expectation, participants, initial_responders, or allowed_responders empty when the message clearly addresses managed bots."
|
|
2136
|
+
: "",
|
|
2137
|
+
guardrail.require_explicit_actionable_intent === true
|
|
2138
|
+
? "- Contract guardrail: if reply_expectation=actionable, intent_type must be exactly one of ctxpack_mutation, workitem_mutation, or general_execution."
|
|
2139
|
+
: "",
|
|
2140
|
+
String(guardrail.reason || "").trim()
|
|
2141
|
+
? `- Contract guardrail reason: ${String(guardrail.reason || "").trim()}`
|
|
2142
|
+
: "",
|
|
2125
2143
|
"",
|
|
2126
2144
|
`managed_bots=${JSON.stringify(bots)}`,
|
|
2127
2145
|
`human_message=${JSON.stringify(String(messageText || "").trim())}`,
|
|
@@ -2464,6 +2482,7 @@ export function analyzeHumanConversationIntentWithAI({
|
|
|
2464
2482
|
messageText,
|
|
2465
2483
|
managedBots,
|
|
2466
2484
|
workspaceDir,
|
|
2485
|
+
contractGuardrail = null,
|
|
2467
2486
|
client = "",
|
|
2468
2487
|
model = "",
|
|
2469
2488
|
env = process.env,
|
|
@@ -2491,6 +2510,7 @@ export function analyzeHumanConversationIntentWithAI({
|
|
|
2491
2510
|
promptText: buildConversationIntentAnalysisPrompt({
|
|
2492
2511
|
messageText,
|
|
2493
2512
|
managedBots: bots,
|
|
2513
|
+
contractGuardrail,
|
|
2494
2514
|
}),
|
|
2495
2515
|
workspaceDir,
|
|
2496
2516
|
model: parserModel,
|
package/lib/runner-delivery.mjs
CHANGED
|
@@ -101,11 +101,18 @@ function normalizeExecutionContractForArchive(rawContract) {
|
|
|
101
101
|
})
|
|
102
102
|
.filter(Boolean);
|
|
103
103
|
const summaryBot = normalizeMentionUsername(contract.summary_bot || contract.summaryBot || "");
|
|
104
|
-
const
|
|
104
|
+
const explicitNextResponders = Array.from(new Set(
|
|
105
105
|
ensureArray(contract.next_responders || contract.nextResponders || contract.responders)
|
|
106
106
|
.map((item) => normalizeMentionUsername(item))
|
|
107
107
|
.filter(Boolean),
|
|
108
108
|
));
|
|
109
|
+
const nextResponders = explicitNextResponders.length > 0
|
|
110
|
+
? explicitNextResponders
|
|
111
|
+
: type === "delegation"
|
|
112
|
+
? Array.from(new Set(assignments.map((item) => normalizeMentionUsername(item.target_bot)).filter(Boolean)))
|
|
113
|
+
: type === "summary_request" && summaryBot
|
|
114
|
+
? [summaryBot]
|
|
115
|
+
: [];
|
|
109
116
|
const actionable = contract.actionable === true;
|
|
110
117
|
if (!type && !assignments.length && !summaryBot && !nextResponders.length && !actionable) {
|
|
111
118
|
return null;
|