nexus-agents 2.72.1 → 2.74.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{adaptive-memory-UPE76IP6.js → adaptive-memory-OJY3IVNM.js} +3 -3
- package/dist/{child-mcp-config-5HRJGLCR.js → child-mcp-config-KMCKKPNY.js} +2 -2
- package/dist/{chunk-TF3GROMO.js → chunk-2SVS5WRV.js} +2 -2
- package/dist/{chunk-QECRZ3YA.js → chunk-3ESCBV47.js} +2 -2
- package/dist/{chunk-QL4HCYRD.js → chunk-3SZBDLFX.js} +3 -3
- package/dist/{chunk-VTVKC4FS.js → chunk-44MVIL3F.js} +4 -4
- package/dist/{chunk-BVETPIOQ.js → chunk-4K6L7RKC.js} +3 -3
- package/dist/chunk-4K6L7RKC.js.map +1 -0
- package/dist/{chunk-C3JGKBL2.js → chunk-65R32U3M.js} +4 -4
- package/dist/{chunk-3FIDMWFC.js → chunk-BK54O5J5.js} +2 -2
- package/dist/chunk-BK54O5J5.js.map +1 -0
- package/dist/{chunk-J4VR2WNI.js → chunk-BYKS53GW.js} +1086 -1709
- package/dist/chunk-BYKS53GW.js.map +1 -0
- package/dist/{chunk-L6N2S3UB.js → chunk-CCODJRS6.js} +2 -2
- package/dist/{chunk-DA5UDQYW.js → chunk-DGELGUZF.js} +2 -2
- package/dist/{chunk-2KB63QGE.js → chunk-EQHYXT56.js} +2 -2
- package/dist/{chunk-VPC3YNFR.js → chunk-G5VE2DZS.js} +2 -2
- package/dist/{chunk-2MD5MWCK.js → chunk-GS3GW7C7.js} +2 -2
- package/dist/{chunk-ES6GFP35.js → chunk-NC2LECY6.js} +26 -9
- package/dist/chunk-NC2LECY6.js.map +1 -0
- package/dist/{chunk-5MHIWRKB.js → chunk-NQR7QAZX.js} +21 -2
- package/dist/chunk-NQR7QAZX.js.map +1 -0
- package/dist/{chunk-5WQ3SRSE.js → chunk-PAFH336F.js} +2 -2
- package/dist/{chunk-O4KUCF5S.js → chunk-Q3RFPJYK.js} +1325 -441
- package/dist/chunk-Q3RFPJYK.js.map +1 -0
- package/dist/{chunk-P5OFZWDW.js → chunk-Q6JDV36D.js} +13 -6
- package/dist/chunk-Q6JDV36D.js.map +1 -0
- package/dist/{chunk-A35XORXU.js → chunk-Q7FTNKPO.js} +2 -2
- package/dist/chunk-QON7LR7J.js +153 -0
- package/dist/chunk-QON7LR7J.js.map +1 -0
- package/dist/{chunk-53K3KEKT.js → chunk-T5VPZZYX.js} +1564 -848
- package/dist/chunk-T5VPZZYX.js.map +1 -0
- package/dist/{chunk-TQFRPFMG.js → chunk-TBRNRW2Q.js} +2 -2
- package/dist/{chunk-345KMHWH.js → chunk-UWJKMBPL.js} +6 -6
- package/dist/{chunk-V7ATY4BG.js → chunk-VJD5LANR.js} +14 -16
- package/dist/chunk-VJD5LANR.js.map +1 -0
- package/dist/{chunk-YOREAPF6.js → chunk-WCCTIRSB.js} +11 -10
- package/dist/chunk-WCCTIRSB.js.map +1 -0
- package/dist/{cli-circuit-breaker-GFF2RLBZ.js → cli-circuit-breaker-STXIH563.js} +4 -4
- package/dist/cli.d.ts +5 -2
- package/dist/cli.js +138 -106
- package/dist/cli.js.map +1 -1
- package/dist/{composite-router-33F3F74I.js → composite-router-7AHZN3VI.js} +2 -2
- package/dist/{consensus-vote-5V4KVHBE.js → consensus-vote-XY55C7WQ.js} +11 -10
- package/dist/consensus-vote-types-CoGbAEjf.d.ts +195 -0
- package/dist/{doctor-deep-AHDTNURD.js → doctor-deep-ONHJTGR4.js} +3 -3
- package/dist/{expert-bridge-DMDHHDEU.js → expert-bridge-3AWQHR65.js} +3 -3
- package/dist/{factory-FVD7PZ6S.js → factory-E5NMAMZC.js} +5 -5
- package/dist/{factory-VQS3HJ7V.js → factory-HWHQ44BB.js} +4 -4
- package/dist/index.d.ts +4089 -3693
- package/dist/index.js +85 -73
- package/dist/index.js.map +1 -1
- package/dist/{init-opencode-EIOIPVWL.js → init-opencode-Z7OQ5RCB.js} +5 -5
- package/dist/{issue-triage-HJUJWGAD.js → issue-triage-UWBHMQHC.js} +4 -4
- package/dist/{mobimem-BOJFXQ7B.js → mobimem-G4UXJTCV.js} +2 -2
- package/dist/{registry-command-NCWUJKAF.js → registry-command-HYWVRAHE.js} +5 -6
- package/dist/registry-command-HYWVRAHE.js.map +1 -0
- package/dist/{repo-security-plan-3J45VAD6.js → repo-security-plan-W35CXK3T.js} +3 -3
- package/dist/{research-helpers-synthesize-UGQHZZJN.js → research-helpers-synthesize-GUQORWL4.js} +3 -3
- package/dist/{routing-memory-NO7QEH7T.js → routing-memory-VOJBOX3X.js} +2 -2
- package/dist/{session-memory-DOXLEWEU.js → session-memory-B6LQMF4N.js} +3 -3
- package/dist/{setup-command-BWUFMZ7U.js → setup-command-CTC5YNA4.js} +9 -8
- package/dist/{setup-config-E3JZYSLR.js → setup-config-53MHJA7S.js} +3 -3
- package/dist/{setup-custom-api-DHJ5DRH2.js → setup-custom-api-VD5W754A.js} +4 -4
- package/dist/{weather-report-FNN4OX3N.js → weather-report-APASTJDQ.js} +2 -2
- package/package.json +1 -1
- package/dist/chunk-3FIDMWFC.js.map +0 -1
- package/dist/chunk-53K3KEKT.js.map +0 -1
- package/dist/chunk-5MHIWRKB.js.map +0 -1
- package/dist/chunk-BVETPIOQ.js.map +0 -1
- package/dist/chunk-ES6GFP35.js.map +0 -1
- package/dist/chunk-J4VR2WNI.js.map +0 -1
- package/dist/chunk-O4KUCF5S.js.map +0 -1
- package/dist/chunk-P5OFZWDW.js.map +0 -1
- package/dist/chunk-V7ATY4BG.js.map +0 -1
- package/dist/chunk-YOREAPF6.js.map +0 -1
- package/dist/model-capabilities-types-B57GZryc.d.ts +0 -18
- package/dist/registry-command-NCWUJKAF.js.map +0 -1
- /package/dist/{adaptive-memory-UPE76IP6.js.map → adaptive-memory-OJY3IVNM.js.map} +0 -0
- /package/dist/{child-mcp-config-5HRJGLCR.js.map → child-mcp-config-KMCKKPNY.js.map} +0 -0
- /package/dist/{chunk-TF3GROMO.js.map → chunk-2SVS5WRV.js.map} +0 -0
- /package/dist/{chunk-QECRZ3YA.js.map → chunk-3ESCBV47.js.map} +0 -0
- /package/dist/{chunk-QL4HCYRD.js.map → chunk-3SZBDLFX.js.map} +0 -0
- /package/dist/{chunk-VTVKC4FS.js.map → chunk-44MVIL3F.js.map} +0 -0
- /package/dist/{chunk-C3JGKBL2.js.map → chunk-65R32U3M.js.map} +0 -0
- /package/dist/{chunk-L6N2S3UB.js.map → chunk-CCODJRS6.js.map} +0 -0
- /package/dist/{chunk-DA5UDQYW.js.map → chunk-DGELGUZF.js.map} +0 -0
- /package/dist/{chunk-2KB63QGE.js.map → chunk-EQHYXT56.js.map} +0 -0
- /package/dist/{chunk-VPC3YNFR.js.map → chunk-G5VE2DZS.js.map} +0 -0
- /package/dist/{chunk-2MD5MWCK.js.map → chunk-GS3GW7C7.js.map} +0 -0
- /package/dist/{chunk-5WQ3SRSE.js.map → chunk-PAFH336F.js.map} +0 -0
- /package/dist/{chunk-A35XORXU.js.map → chunk-Q7FTNKPO.js.map} +0 -0
- /package/dist/{chunk-TQFRPFMG.js.map → chunk-TBRNRW2Q.js.map} +0 -0
- /package/dist/{chunk-345KMHWH.js.map → chunk-UWJKMBPL.js.map} +0 -0
- /package/dist/{cli-circuit-breaker-GFF2RLBZ.js.map → cli-circuit-breaker-STXIH563.js.map} +0 -0
- /package/dist/{composite-router-33F3F74I.js.map → composite-router-7AHZN3VI.js.map} +0 -0
- /package/dist/{consensus-vote-5V4KVHBE.js.map → consensus-vote-XY55C7WQ.js.map} +0 -0
- /package/dist/{doctor-deep-AHDTNURD.js.map → doctor-deep-ONHJTGR4.js.map} +0 -0
- /package/dist/{expert-bridge-DMDHHDEU.js.map → expert-bridge-3AWQHR65.js.map} +0 -0
- /package/dist/{factory-FVD7PZ6S.js.map → factory-E5NMAMZC.js.map} +0 -0
- /package/dist/{factory-VQS3HJ7V.js.map → factory-HWHQ44BB.js.map} +0 -0
- /package/dist/{init-opencode-EIOIPVWL.js.map → init-opencode-Z7OQ5RCB.js.map} +0 -0
- /package/dist/{issue-triage-HJUJWGAD.js.map → issue-triage-UWBHMQHC.js.map} +0 -0
- /package/dist/{mobimem-BOJFXQ7B.js.map → mobimem-G4UXJTCV.js.map} +0 -0
- /package/dist/{repo-security-plan-3J45VAD6.js.map → repo-security-plan-W35CXK3T.js.map} +0 -0
- /package/dist/{research-helpers-synthesize-UGQHZZJN.js.map → research-helpers-synthesize-GUQORWL4.js.map} +0 -0
- /package/dist/{routing-memory-NO7QEH7T.js.map → routing-memory-VOJBOX3X.js.map} +0 -0
- /package/dist/{session-memory-DOXLEWEU.js.map → session-memory-B6LQMF4N.js.map} +0 -0
- /package/dist/{setup-command-BWUFMZ7U.js.map → setup-command-CTC5YNA4.js.map} +0 -0
- /package/dist/{setup-config-E3JZYSLR.js.map → setup-config-53MHJA7S.js.map} +0 -0
- /package/dist/{setup-custom-api-DHJ5DRH2.js.map → setup-custom-api-VD5W754A.js.map} +0 -0
- /package/dist/{weather-report-FNN4OX3N.js.map → weather-report-APASTJDQ.js.map} +0 -0
|
@@ -4,15 +4,18 @@ import {
|
|
|
4
4
|
createStream,
|
|
5
5
|
requireApiKey,
|
|
6
6
|
validateApiKeyPresence
|
|
7
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-NQR7QAZX.js";
|
|
8
8
|
import {
|
|
9
9
|
CUSTOM_API_BASE_URL_ENV,
|
|
10
10
|
PROVIDER_ENV_KEYS,
|
|
11
11
|
validateCustomApiBaseUrl
|
|
12
|
-
} from "./chunk-
|
|
12
|
+
} from "./chunk-PAFH336F.js";
|
|
13
|
+
import {
|
|
14
|
+
getDefaultAvailableModelsCache
|
|
15
|
+
} from "./chunk-QON7LR7J.js";
|
|
13
16
|
import {
|
|
14
17
|
CUSTOM_API_DEFAULT_MODEL
|
|
15
|
-
} from "./chunk-
|
|
18
|
+
} from "./chunk-GS3GW7C7.js";
|
|
16
19
|
import {
|
|
17
20
|
createCliAdapter,
|
|
18
21
|
createCliDetectionCache,
|
|
@@ -20,10 +23,10 @@ import {
|
|
|
20
23
|
getAvailableClis,
|
|
21
24
|
isCliAvailable,
|
|
22
25
|
withTimeout
|
|
23
|
-
} from "./chunk-
|
|
26
|
+
} from "./chunk-NC2LECY6.js";
|
|
24
27
|
import {
|
|
25
28
|
SessionMemory
|
|
26
|
-
} from "./chunk-
|
|
29
|
+
} from "./chunk-EQHYXT56.js";
|
|
27
30
|
import {
|
|
28
31
|
AdaptiveMemoryBackend,
|
|
29
32
|
HybridMemoryBackend,
|
|
@@ -32,7 +35,7 @@ import {
|
|
|
32
35
|
getMemoryEntry,
|
|
33
36
|
memoryExists,
|
|
34
37
|
memoryRowToEntry
|
|
35
|
-
} from "./chunk-
|
|
38
|
+
} from "./chunk-3ESCBV47.js";
|
|
36
39
|
import {
|
|
37
40
|
stringifyValue,
|
|
38
41
|
tokenizeFiltered
|
|
@@ -42,8 +45,6 @@ import {
|
|
|
42
45
|
CACHE_TIMEOUTS,
|
|
43
46
|
CLI_NAMES,
|
|
44
47
|
DEFAULT_CLI,
|
|
45
|
-
DEFAULT_MODEL_CAPABILITIES,
|
|
46
|
-
DEFAULT_MODEL_PER_CLI,
|
|
47
48
|
ErrorCode,
|
|
48
49
|
MCP_TIMEOUTS,
|
|
49
50
|
MobiMem,
|
|
@@ -66,7 +67,10 @@ import {
|
|
|
66
67
|
formatPercentage,
|
|
67
68
|
formatZodError,
|
|
68
69
|
getCliModelName,
|
|
70
|
+
getDefaultModelForCli,
|
|
71
|
+
getDefaultRegistry,
|
|
69
72
|
getErrorMessage,
|
|
73
|
+
getInTreeCapabilitiesMatrix,
|
|
70
74
|
getMcpSafeDeadlineMs,
|
|
71
75
|
getOutcomeStore,
|
|
72
76
|
getRandomProvider,
|
|
@@ -78,9 +82,8 @@ import {
|
|
|
78
82
|
registerPersistentOutcomeStoreFactory,
|
|
79
83
|
resolveCliAlias,
|
|
80
84
|
resolveVoteTimeout,
|
|
81
|
-
toRateLimitError
|
|
82
|
-
|
|
83
|
-
} from "./chunk-O4KUCF5S.js";
|
|
85
|
+
toRateLimitError
|
|
86
|
+
} from "./chunk-Q3RFPJYK.js";
|
|
84
87
|
import {
|
|
85
88
|
ensureLearningDir,
|
|
86
89
|
getOutcomesFile
|
|
@@ -90,38 +93,38 @@ import {
|
|
|
90
93
|
} from "./chunk-GOT7OAL5.js";
|
|
91
94
|
|
|
92
95
|
// src/mcp/tools/consensus-vote.ts
|
|
93
|
-
import { z as
|
|
96
|
+
import { z as z20 } from "zod";
|
|
94
97
|
|
|
95
98
|
// src/mcp/mcp-notifier.ts
|
|
96
99
|
import { AsyncLocalStorage } from "async_hooks";
|
|
97
100
|
var internalLogger = createLogger({ component: "mcp-notifier" });
|
|
98
101
|
function createMcpNotifier(server) {
|
|
99
|
-
function send(level,
|
|
102
|
+
function send(level, logger12, data) {
|
|
100
103
|
try {
|
|
101
|
-
server.sendLoggingMessage({ level, logger:
|
|
104
|
+
server.sendLoggingMessage({ level, logger: logger12, data }).catch((error) => {
|
|
102
105
|
internalLogger.debug("Failed to send MCP notification", {
|
|
103
106
|
level,
|
|
104
|
-
logger:
|
|
107
|
+
logger: logger12,
|
|
105
108
|
error: getErrorMessage(error)
|
|
106
109
|
});
|
|
107
110
|
});
|
|
108
111
|
} catch (error) {
|
|
109
112
|
internalLogger.debug("Failed to send MCP notification", {
|
|
110
113
|
level,
|
|
111
|
-
logger:
|
|
114
|
+
logger: logger12,
|
|
112
115
|
error: getErrorMessage(error)
|
|
113
116
|
});
|
|
114
117
|
}
|
|
115
118
|
}
|
|
116
119
|
return {
|
|
117
|
-
info: (
|
|
118
|
-
send("info",
|
|
120
|
+
info: (logger12, data) => {
|
|
121
|
+
send("info", logger12, data);
|
|
119
122
|
},
|
|
120
|
-
debug: (
|
|
121
|
-
send("debug",
|
|
123
|
+
debug: (logger12, data) => {
|
|
124
|
+
send("debug", logger12, data);
|
|
122
125
|
},
|
|
123
|
-
warn: (
|
|
124
|
-
send("warning",
|
|
126
|
+
warn: (logger12, data) => {
|
|
127
|
+
send("warning", logger12, data);
|
|
125
128
|
}
|
|
126
129
|
};
|
|
127
130
|
}
|
|
@@ -246,7 +249,7 @@ var RateLimiter = class {
|
|
|
246
249
|
this.logger.debug("Rate limiter reset", { tokens: this.tokens });
|
|
247
250
|
}
|
|
248
251
|
};
|
|
249
|
-
function createDefaultRateLimiter(name,
|
|
252
|
+
function createDefaultRateLimiter(name, logger12) {
|
|
250
253
|
const config = {
|
|
251
254
|
capacity: 100,
|
|
252
255
|
refillRate: 10,
|
|
@@ -255,8 +258,8 @@ function createDefaultRateLimiter(name, logger11) {
|
|
|
255
258
|
if (name !== void 0) {
|
|
256
259
|
config.name = name;
|
|
257
260
|
}
|
|
258
|
-
if (
|
|
259
|
-
config.logger =
|
|
261
|
+
if (logger12 !== void 0) {
|
|
262
|
+
config.logger = logger12;
|
|
260
263
|
}
|
|
261
264
|
return new RateLimiter(config);
|
|
262
265
|
}
|
|
@@ -1014,13 +1017,69 @@ function createAccessPolicyChainMiddleware(toolName) {
|
|
|
1014
1017
|
};
|
|
1015
1018
|
}
|
|
1016
1019
|
|
|
1017
|
-
// src/mcp/
|
|
1018
|
-
|
|
1020
|
+
// src/mcp/error-envelope.ts
|
|
1021
|
+
import { z as z2 } from "zod";
|
|
1022
|
+
var ErrorCategorySchema = z2.enum([
|
|
1023
|
+
"transient",
|
|
1024
|
+
"validation",
|
|
1025
|
+
"permission",
|
|
1026
|
+
"business",
|
|
1027
|
+
"internal"
|
|
1028
|
+
]);
|
|
1029
|
+
var ToolErrorEnvelopeSchema = z2.object({
|
|
1030
|
+
errorCategory: ErrorCategorySchema,
|
|
1031
|
+
/** Whether retrying the same call could succeed without caller changes. */
|
|
1032
|
+
isRetryable: z2.boolean(),
|
|
1033
|
+
/** Human-readable summary. Bounded to keep stack traces out of results. */
|
|
1034
|
+
message: z2.string().min(1).max(2e3),
|
|
1035
|
+
/**
|
|
1036
|
+
* Optional structured context. MUST NOT carry secrets, credentials,
|
|
1037
|
+
* absolute filesystem paths, or raw Error/response objects — those are
|
|
1038
|
+
* an information-disclosure risk (this field is not output-sanitized).
|
|
1039
|
+
*/
|
|
1040
|
+
detail: z2.record(z2.string(), z2.unknown()).optional()
|
|
1041
|
+
});
|
|
1042
|
+
var ERROR_ENVELOPE_META_KEY = "nexus-agents/error";
|
|
1043
|
+
function defaultRetryable(category) {
|
|
1044
|
+
return category === "transient";
|
|
1045
|
+
}
|
|
1046
|
+
|
|
1047
|
+
// src/mcp/tools/tool-result.ts
|
|
1048
|
+
function toolSuccess(text) {
|
|
1049
|
+
return {
|
|
1050
|
+
content: [{ type: "text", text }]
|
|
1051
|
+
};
|
|
1052
|
+
}
|
|
1053
|
+
function toolSuccessStructured(data) {
|
|
1054
|
+
return {
|
|
1055
|
+
content: [{ type: "text", text: JSON.stringify(data, null, 2) }],
|
|
1056
|
+
structuredContent: data
|
|
1057
|
+
};
|
|
1058
|
+
}
|
|
1059
|
+
function toolStructuredError(input) {
|
|
1060
|
+
const envelope = {
|
|
1061
|
+
errorCategory: input.errorCategory,
|
|
1062
|
+
isRetryable: input.isRetryable ?? defaultRetryable(input.errorCategory),
|
|
1063
|
+
message: input.message,
|
|
1064
|
+
...input.detail !== void 0 ? { detail: input.detail } : {}
|
|
1065
|
+
};
|
|
1019
1066
|
return {
|
|
1020
1067
|
isError: true,
|
|
1021
|
-
content: [{ type: "text", text:
|
|
1068
|
+
content: [{ type: "text", text: envelope.message }],
|
|
1069
|
+
_meta: { [ERROR_ENVELOPE_META_KEY]: envelope }
|
|
1022
1070
|
};
|
|
1023
1071
|
}
|
|
1072
|
+
function toolError(message) {
|
|
1073
|
+
return toolStructuredError({ errorCategory: "internal", message });
|
|
1074
|
+
}
|
|
1075
|
+
|
|
1076
|
+
// src/mcp/middleware/middleware-chain.ts
|
|
1077
|
+
function errorResult(category, message, requestId) {
|
|
1078
|
+
return toolStructuredError({
|
|
1079
|
+
errorCategory: category,
|
|
1080
|
+
message: `${message} (request: ${requestId})`
|
|
1081
|
+
});
|
|
1082
|
+
}
|
|
1024
1083
|
function createValidationMiddleware(schema) {
|
|
1025
1084
|
return async (args, ctx, next) => {
|
|
1026
1085
|
const result = validateToolInput(schema, args);
|
|
@@ -1028,7 +1087,11 @@ function createValidationMiddleware(schema) {
|
|
|
1028
1087
|
ctx.logger.warn("Validation failed", {
|
|
1029
1088
|
error: result.error.message
|
|
1030
1089
|
});
|
|
1031
|
-
return errorResult(
|
|
1090
|
+
return errorResult(
|
|
1091
|
+
"validation",
|
|
1092
|
+
`Validation error: ${result.error.message}`,
|
|
1093
|
+
ctx.requestContext.requestId
|
|
1094
|
+
);
|
|
1032
1095
|
}
|
|
1033
1096
|
ctx.validatedArgs = result.value;
|
|
1034
1097
|
return next(result.value, ctx);
|
|
@@ -1046,7 +1109,11 @@ function createPolicyMiddleware(firewall, toolName, mode, allowedPaths) {
|
|
|
1046
1109
|
reason: decision.reason,
|
|
1047
1110
|
ruleName: decision.ruleName
|
|
1048
1111
|
});
|
|
1049
|
-
return errorResult(
|
|
1112
|
+
return errorResult(
|
|
1113
|
+
"permission",
|
|
1114
|
+
`Policy denied: ${decision.reason}`,
|
|
1115
|
+
ctx.requestContext.requestId
|
|
1116
|
+
);
|
|
1050
1117
|
}
|
|
1051
1118
|
ctx.logger.debug("Policy check passed", { reason: decision.reason });
|
|
1052
1119
|
return next(args, ctx);
|
|
@@ -1061,6 +1128,7 @@ function createRateLimitMiddleware(limiter) {
|
|
|
1061
1128
|
nextTokenMs: state.nextTokenMs
|
|
1062
1129
|
});
|
|
1063
1130
|
return errorResult(
|
|
1131
|
+
"transient",
|
|
1064
1132
|
`Rate limit exceeded. Try again in ${String(state.nextTokenMs)}ms`,
|
|
1065
1133
|
ctx.requestContext.requestId
|
|
1066
1134
|
);
|
|
@@ -1080,7 +1148,7 @@ function createTimeoutMiddleware(guard, toolName) {
|
|
|
1080
1148
|
code: result.error.code,
|
|
1081
1149
|
timeoutMs: result.error.timeoutMs
|
|
1082
1150
|
});
|
|
1083
|
-
return errorResult(result.error.message, ctx.requestContext.requestId);
|
|
1151
|
+
return errorResult("transient", result.error.message, ctx.requestContext.requestId);
|
|
1084
1152
|
}
|
|
1085
1153
|
if (result.value.nearTimeout) {
|
|
1086
1154
|
ctx.logger.warn("Operation completed near timeout threshold", {
|
|
@@ -1109,7 +1177,7 @@ function createAuditMiddleware() {
|
|
|
1109
1177
|
ctx.logger.error("Tool execution failed", error instanceof Error ? error : void 0, {
|
|
1110
1178
|
durationMs
|
|
1111
1179
|
});
|
|
1112
|
-
return errorResult(`Internal error: ${message}`, ctx.requestContext.requestId);
|
|
1180
|
+
return errorResult("internal", `Internal error: ${message}`, ctx.requestContext.requestId);
|
|
1113
1181
|
}
|
|
1114
1182
|
};
|
|
1115
1183
|
}
|
|
@@ -1176,13 +1244,13 @@ function buildMiddlewareStack(config) {
|
|
|
1176
1244
|
return middlewares;
|
|
1177
1245
|
}
|
|
1178
1246
|
function createMiddlewareChain(config) {
|
|
1179
|
-
const
|
|
1247
|
+
const logger12 = config.logger ?? createLogger({ tool: config.toolName });
|
|
1180
1248
|
const middlewares = buildMiddlewareStack(config);
|
|
1181
1249
|
const composed = composeMiddleware(middlewares);
|
|
1182
1250
|
return (handler) => {
|
|
1183
1251
|
return async (args) => {
|
|
1184
1252
|
const requestContext = createRequestContext({ toolName: config.toolName });
|
|
1185
|
-
const requestLogger =
|
|
1253
|
+
const requestLogger = logger12.child(contextForLogging(requestContext));
|
|
1186
1254
|
const ctx = { requestContext, logger: requestLogger };
|
|
1187
1255
|
return composed(args, ctx, (finalArgs, finalCtx) => handler(finalArgs, finalCtx));
|
|
1188
1256
|
};
|
|
@@ -1284,6 +1352,26 @@ function toSdkCallback(handler) {
|
|
|
1284
1352
|
return runWithContexts(handler, args, progressCtx, signal);
|
|
1285
1353
|
};
|
|
1286
1354
|
}
|
|
1355
|
+
var MCP_SDK_DEFAULT_REQUEST_TIMEOUT_MS = 6e4;
|
|
1356
|
+
function toSdkCallbackWithBudgetCheck(handler, toolName, configuredTimeoutMs, logger12) {
|
|
1357
|
+
const log = logger12 ?? wrapperLogger;
|
|
1358
|
+
return (args, extra) => {
|
|
1359
|
+
const progressCtx = extractProgressContext(extra);
|
|
1360
|
+
const signal = extra?.signal;
|
|
1361
|
+
if (configuredTimeoutMs > MCP_SDK_DEFAULT_REQUEST_TIMEOUT_MS && progressCtx === void 0) {
|
|
1362
|
+
log.warn(
|
|
1363
|
+
"MCP tool budget exceeds client default and no progressToken received \u2014 request likely to be killed by client before server-side deadline",
|
|
1364
|
+
{
|
|
1365
|
+
tool: toolName,
|
|
1366
|
+
configuredTimeoutMs,
|
|
1367
|
+
mcpSdkDefaultMs: MCP_SDK_DEFAULT_REQUEST_TIMEOUT_MS,
|
|
1368
|
+
remediation: "Client should pass `onprogress` and `resetTimeoutOnProgress: true` when calling, or extend `options.timeout`. See docs/architecture/MCP_PROTOCOL.md."
|
|
1369
|
+
}
|
|
1370
|
+
);
|
|
1371
|
+
}
|
|
1372
|
+
return runWithContexts(handler, args, progressCtx, signal);
|
|
1373
|
+
};
|
|
1374
|
+
}
|
|
1287
1375
|
|
|
1288
1376
|
// src/audit/secure-handler-audit.ts
|
|
1289
1377
|
function actorFromContext(ctx, fallback) {
|
|
@@ -1391,15 +1479,15 @@ function sanitizeToolInput(args) {
|
|
|
1391
1479
|
detectedPatterns: uniquePatterns
|
|
1392
1480
|
};
|
|
1393
1481
|
}
|
|
1394
|
-
function logSanitizationResult(result,
|
|
1482
|
+
function logSanitizationResult(result, logger12, toolName) {
|
|
1395
1483
|
if (result.wasModified) {
|
|
1396
|
-
|
|
1484
|
+
logger12.warn("Tool input sanitized \u2014 XML injection tags stripped", {
|
|
1397
1485
|
tool: toolName,
|
|
1398
1486
|
modifiedFields: result.modifiedCount
|
|
1399
1487
|
});
|
|
1400
1488
|
}
|
|
1401
1489
|
if (result.detectedPatterns.length > 0) {
|
|
1402
|
-
|
|
1490
|
+
logger12.warn("Injection patterns detected in tool input", {
|
|
1403
1491
|
tool: toolName,
|
|
1404
1492
|
patterns: result.detectedPatterns
|
|
1405
1493
|
});
|
|
@@ -1408,27 +1496,22 @@ function logSanitizationResult(result, logger11, toolName) {
|
|
|
1408
1496
|
|
|
1409
1497
|
// src/mcp/middleware/secure-handler.ts
|
|
1410
1498
|
function rateLimitError(nextTokenMs) {
|
|
1411
|
-
return {
|
|
1412
|
-
|
|
1413
|
-
|
|
1414
|
-
|
|
1415
|
-
type: "text",
|
|
1416
|
-
text: `Rate limit exceeded. Try again in ${String(nextTokenMs)}ms.`
|
|
1417
|
-
}
|
|
1418
|
-
]
|
|
1419
|
-
};
|
|
1499
|
+
return toolStructuredError({
|
|
1500
|
+
errorCategory: "transient",
|
|
1501
|
+
message: `Rate limit exceeded. Try again in ${String(nextTokenMs)}ms.`
|
|
1502
|
+
});
|
|
1420
1503
|
}
|
|
1421
1504
|
function policyDeniedError(reason, requestId) {
|
|
1422
|
-
return {
|
|
1423
|
-
|
|
1424
|
-
|
|
1425
|
-
};
|
|
1505
|
+
return toolStructuredError({
|
|
1506
|
+
errorCategory: "permission",
|
|
1507
|
+
message: `Policy denied: ${reason} (request: ${requestId})`
|
|
1508
|
+
});
|
|
1426
1509
|
}
|
|
1427
1510
|
function internalError(message, requestId) {
|
|
1428
|
-
return {
|
|
1429
|
-
|
|
1430
|
-
|
|
1431
|
-
};
|
|
1511
|
+
return toolStructuredError({
|
|
1512
|
+
errorCategory: "internal",
|
|
1513
|
+
message: `Internal error: ${message} (request: ${requestId})`
|
|
1514
|
+
});
|
|
1432
1515
|
}
|
|
1433
1516
|
var MAX_INPUT_SIZE_BYTES = 10 * 1024 * 1024;
|
|
1434
1517
|
var SECRET_PATTERNS = [
|
|
@@ -1444,11 +1527,11 @@ var SECRET_PATTERNS = [
|
|
|
1444
1527
|
// password= or token= in output
|
|
1445
1528
|
/(?:password|token|secret|apikey|api_key)\s*[=:]\s*\S{8,}/i
|
|
1446
1529
|
];
|
|
1447
|
-
function sanitizeOutput(text,
|
|
1530
|
+
function sanitizeOutput(text, logger12) {
|
|
1448
1531
|
let sanitized = text;
|
|
1449
1532
|
for (const pattern of SECRET_PATTERNS) {
|
|
1450
1533
|
if (pattern.test(sanitized)) {
|
|
1451
|
-
|
|
1534
|
+
logger12.warn("Potential secret detected in tool output, redacting", {
|
|
1452
1535
|
pattern: pattern.source.slice(0, 30)
|
|
1453
1536
|
});
|
|
1454
1537
|
sanitized = sanitized.replace(pattern, "[REDACTED]");
|
|
@@ -1456,25 +1539,25 @@ function sanitizeOutput(text, logger11) {
|
|
|
1456
1539
|
}
|
|
1457
1540
|
return sanitized;
|
|
1458
1541
|
}
|
|
1459
|
-
function sanitizeToolResult(result,
|
|
1542
|
+
function sanitizeToolResult(result, logger12) {
|
|
1460
1543
|
for (const item of result.content) {
|
|
1461
|
-
item.text = sanitizeOutput(item.text,
|
|
1544
|
+
item.text = sanitizeOutput(item.text, logger12);
|
|
1462
1545
|
}
|
|
1463
1546
|
}
|
|
1464
|
-
function checkInputSize(args,
|
|
1547
|
+
function checkInputSize(args, logger12, requestId) {
|
|
1465
1548
|
if (args === void 0) return null;
|
|
1466
1549
|
const inputSize = JSON.stringify(args).length;
|
|
1467
1550
|
if (inputSize > MAX_INPUT_SIZE_BYTES) {
|
|
1468
|
-
|
|
1551
|
+
logger12.warn("Input size exceeds limit", { inputSize, limit: MAX_INPUT_SIZE_BYTES });
|
|
1469
1552
|
return internalError("Input too large", requestId);
|
|
1470
1553
|
}
|
|
1471
1554
|
return null;
|
|
1472
1555
|
}
|
|
1473
|
-
function checkRateLimit(rateLimiter,
|
|
1556
|
+
function checkRateLimit(rateLimiter, logger12) {
|
|
1474
1557
|
const acquired = rateLimiter.tryAcquire();
|
|
1475
1558
|
if (!acquired) {
|
|
1476
1559
|
const state = rateLimiter.getState();
|
|
1477
|
-
|
|
1560
|
+
logger12.warn("Rate limit exceeded");
|
|
1478
1561
|
return rateLimitError(state.nextTokenMs);
|
|
1479
1562
|
}
|
|
1480
1563
|
return null;
|
|
@@ -1495,14 +1578,14 @@ function checkPolicy(opts) {
|
|
|
1495
1578
|
opts.logger.debug("Policy check passed", { reason: decision.reason });
|
|
1496
1579
|
return null;
|
|
1497
1580
|
}
|
|
1498
|
-
async function executeHandler(handler, args, ctx,
|
|
1581
|
+
async function executeHandler(handler, args, ctx, logger12) {
|
|
1499
1582
|
const startTime = getTimeProvider().now();
|
|
1500
1583
|
const result = handler.length >= 2 ? await handler(args, ctx) : await handler(args);
|
|
1501
1584
|
const durationMs = getTimeProvider().now() - startTime;
|
|
1502
1585
|
if (result.isError === true) {
|
|
1503
|
-
|
|
1586
|
+
logger12.warn("Tool execution completed with error", { durationMs });
|
|
1504
1587
|
} else {
|
|
1505
|
-
|
|
1588
|
+
logger12.info("Tool execution completed", { durationMs });
|
|
1506
1589
|
}
|
|
1507
1590
|
return result;
|
|
1508
1591
|
}
|
|
@@ -1548,35 +1631,30 @@ function emitRateLimitAudit(auditLogger, toolName, ctx) {
|
|
|
1548
1631
|
requestId: ctx.requestId
|
|
1549
1632
|
});
|
|
1550
1633
|
}
|
|
1551
|
-
function checkSecurityTier(config, sanitizeResult,
|
|
1634
|
+
function checkSecurityTier(config, sanitizeResult, logger12) {
|
|
1552
1635
|
const tier = config.securityTier ?? "standard";
|
|
1553
1636
|
if (tier === "standard" || sanitizeResult.detectedPatterns.length === 0) {
|
|
1554
1637
|
return null;
|
|
1555
1638
|
}
|
|
1556
|
-
|
|
1639
|
+
logger12.warn("Input rejected by security tier validation", {
|
|
1557
1640
|
tier,
|
|
1558
1641
|
patterns: sanitizeResult.detectedPatterns
|
|
1559
1642
|
});
|
|
1560
|
-
return {
|
|
1561
|
-
|
|
1562
|
-
|
|
1563
|
-
|
|
1564
|
-
type: "text",
|
|
1565
|
-
text: `Input validation failed: detected patterns [${sanitizeResult.detectedPatterns.join(", ")}]. Remove prompt injection patterns and retry.`
|
|
1566
|
-
}
|
|
1567
|
-
]
|
|
1568
|
-
};
|
|
1643
|
+
return toolStructuredError({
|
|
1644
|
+
errorCategory: "permission",
|
|
1645
|
+
message: `Input validation failed: detected patterns [${sanitizeResult.detectedPatterns.join(", ")}]. Remove prompt injection patterns and retry.`
|
|
1646
|
+
});
|
|
1569
1647
|
}
|
|
1570
|
-
function runPreChecks(config, args, mode, requestContext,
|
|
1571
|
-
const sizeResult = checkInputSize(args,
|
|
1648
|
+
function runPreChecks(config, args, mode, requestContext, logger12) {
|
|
1649
|
+
const sizeResult = checkInputSize(args, logger12, requestContext.requestId);
|
|
1572
1650
|
if (sizeResult) return { error: sizeResult, sanitizedArgs: args };
|
|
1573
1651
|
const sanitizeResult = sanitizeToolInput(args);
|
|
1574
|
-
logSanitizationResult(sanitizeResult,
|
|
1652
|
+
logSanitizationResult(sanitizeResult, logger12, config.toolName);
|
|
1575
1653
|
const sanitizedArgs = sanitizeResult.wasModified ? sanitizeResult.sanitized : args;
|
|
1576
|
-
const tierError = checkSecurityTier(config, sanitizeResult,
|
|
1654
|
+
const tierError = checkSecurityTier(config, sanitizeResult, logger12);
|
|
1577
1655
|
if (tierError !== null) return { error: tierError, sanitizedArgs };
|
|
1578
1656
|
if (config.rateLimiter) {
|
|
1579
|
-
const rlResult = checkRateLimit(config.rateLimiter,
|
|
1657
|
+
const rlResult = checkRateLimit(config.rateLimiter, logger12);
|
|
1580
1658
|
if (rlResult) {
|
|
1581
1659
|
if (config.auditLogger)
|
|
1582
1660
|
emitRateLimitAudit(config.auditLogger, config.toolName, requestContext);
|
|
@@ -1590,7 +1668,7 @@ function runPreChecks(config, args, mode, requestContext, logger11) {
|
|
|
1590
1668
|
args: sanitizedArgs,
|
|
1591
1669
|
mode,
|
|
1592
1670
|
allowedPaths: config.allowedPaths,
|
|
1593
|
-
logger:
|
|
1671
|
+
logger: logger12,
|
|
1594
1672
|
requestId: requestContext.requestId
|
|
1595
1673
|
});
|
|
1596
1674
|
if (pResult) {
|
|
@@ -1602,7 +1680,7 @@ function runPreChecks(config, args, mode, requestContext, logger11) {
|
|
|
1602
1680
|
return { error: null, sanitizedArgs };
|
|
1603
1681
|
}
|
|
1604
1682
|
function createSecureHandler(handler, config) {
|
|
1605
|
-
const
|
|
1683
|
+
const logger12 = config.logger ?? createLogger({ tool: config.toolName });
|
|
1606
1684
|
const mode = config.executionMode ?? "read-only";
|
|
1607
1685
|
return async (args) => {
|
|
1608
1686
|
const ctxOpts = {
|
|
@@ -1610,7 +1688,7 @@ function createSecureHandler(handler, config) {
|
|
|
1610
1688
|
...config.callerInfo && { caller: config.callerInfo }
|
|
1611
1689
|
};
|
|
1612
1690
|
const requestContext = createRequestContext(ctxOpts);
|
|
1613
|
-
const requestLogger =
|
|
1691
|
+
const requestLogger = logger12.child(contextForLogging(requestContext));
|
|
1614
1692
|
requestLogger.info("Tool invocation started");
|
|
1615
1693
|
const { error: preCheckError, sanitizedArgs } = runPreChecks(
|
|
1616
1694
|
config,
|
|
@@ -1658,31 +1736,7 @@ async function executeAndAudit(handler, sanitizedArgs, requestContext, requestLo
|
|
|
1658
1736
|
}
|
|
1659
1737
|
}
|
|
1660
1738
|
|
|
1661
|
-
// src/mcp/tools/tool-result.ts
|
|
1662
|
-
function toolSuccess(text) {
|
|
1663
|
-
return {
|
|
1664
|
-
content: [{ type: "text", text }]
|
|
1665
|
-
};
|
|
1666
|
-
}
|
|
1667
|
-
function toolSuccessStructured(data) {
|
|
1668
|
-
return {
|
|
1669
|
-
content: [{ type: "text", text: JSON.stringify(data, null, 2) }],
|
|
1670
|
-
structuredContent: data
|
|
1671
|
-
};
|
|
1672
|
-
}
|
|
1673
|
-
function toolError(message) {
|
|
1674
|
-
return {
|
|
1675
|
-
isError: true,
|
|
1676
|
-
content: [{ type: "text", text: message }]
|
|
1677
|
-
};
|
|
1678
|
-
}
|
|
1679
|
-
|
|
1680
1739
|
// src/cli/vote-types.ts
|
|
1681
|
-
var THRESHOLD_MAP = {
|
|
1682
|
-
majority: "simple_majority",
|
|
1683
|
-
supermajority: "supermajority",
|
|
1684
|
-
unanimous: "unanimous"
|
|
1685
|
-
};
|
|
1686
1740
|
var VOTER_ROLES = {
|
|
1687
1741
|
architect: "Software Architect - evaluates technical design, scalability, and maintainability",
|
|
1688
1742
|
security: "Security Engineer - evaluates security implications, vulnerabilities, and attack vectors",
|
|
@@ -2219,7 +2273,48 @@ var ClaudeAdapter = class extends BaseAdapter {
|
|
|
2219
2273
|
return null;
|
|
2220
2274
|
}
|
|
2221
2275
|
}
|
|
2276
|
+
/**
|
|
2277
|
+
* (#2540) List models the Anthropic API currently exposes.
|
|
2278
|
+
* Wraps `client.models.list()`. Cached for 5 min, in-flight promise
|
|
2279
|
+
* shared across concurrent callers, throws on non-2xx so the
|
|
2280
|
+
* harness-side identity resolver knows to fall back.
|
|
2281
|
+
*/
|
|
2282
|
+
async listModels() {
|
|
2283
|
+
const now = Date.now();
|
|
2284
|
+
if (this.modelsCache !== null && now - this.modelsCache.fetchedAt < CLAUDE_LIST_MODELS_TTL_MS) {
|
|
2285
|
+
return this.modelsCache.value;
|
|
2286
|
+
}
|
|
2287
|
+
if (this.modelsInFlight !== null) return this.modelsInFlight;
|
|
2288
|
+
const inFlight = this.fetchModels();
|
|
2289
|
+
this.modelsInFlight = inFlight;
|
|
2290
|
+
try {
|
|
2291
|
+
const value = await inFlight;
|
|
2292
|
+
this.modelsCache = { value, fetchedAt: Date.now() };
|
|
2293
|
+
return value;
|
|
2294
|
+
} finally {
|
|
2295
|
+
this.modelsInFlight = null;
|
|
2296
|
+
}
|
|
2297
|
+
}
|
|
2298
|
+
modelsCache = null;
|
|
2299
|
+
modelsInFlight = null;
|
|
2300
|
+
async fetchModels() {
|
|
2301
|
+
const list = await this.client.models.list();
|
|
2302
|
+
const out = [];
|
|
2303
|
+
for (const m of list.data) {
|
|
2304
|
+
const entry = { id: m.id };
|
|
2305
|
+
if (typeof m.created_at === "string") {
|
|
2306
|
+
const ts = Date.parse(m.created_at);
|
|
2307
|
+
if (!Number.isNaN(ts)) {
|
|
2308
|
+
out.push({ ...entry, ownedBy: "anthropic", createdAt: Math.floor(ts / 1e3) });
|
|
2309
|
+
continue;
|
|
2310
|
+
}
|
|
2311
|
+
}
|
|
2312
|
+
out.push({ ...entry, ownedBy: "anthropic" });
|
|
2313
|
+
}
|
|
2314
|
+
return out;
|
|
2315
|
+
}
|
|
2222
2316
|
};
|
|
2317
|
+
var CLAUDE_LIST_MODELS_TTL_MS = 5 * 60 * 1e3;
|
|
2223
2318
|
function createClaudeAdapter(config) {
|
|
2224
2319
|
return new ClaudeAdapter(config);
|
|
2225
2320
|
}
|
|
@@ -2293,13 +2388,13 @@ var SdkAdapter = class extends BaseAdapter {
|
|
|
2293
2388
|
customBaseUrl;
|
|
2294
2389
|
/** Inflight init promise for coalescing concurrent calls (Issue #1438). */
|
|
2295
2390
|
initPromise;
|
|
2296
|
-
constructor(config,
|
|
2391
|
+
constructor(config, logger12) {
|
|
2297
2392
|
const apiKey = resolveApiKey(config.providerId, config.apiKey);
|
|
2298
2393
|
super({
|
|
2299
2394
|
providerId: `sdk-${config.providerId}`,
|
|
2300
2395
|
modelId: config.modelId,
|
|
2301
2396
|
capabilities: [ModelCapability.COMPLETION, ModelCapability.STREAMING],
|
|
2302
|
-
logger:
|
|
2397
|
+
logger: logger12 ?? createLogger({ adapter: `sdk-${config.providerId}` }),
|
|
2303
2398
|
...apiKey !== void 0 ? { apiKey } : {},
|
|
2304
2399
|
...config.timeout !== void 0 ? { timeout: config.timeout } : {},
|
|
2305
2400
|
...config.maxRetries !== void 0 ? { maxRetries: config.maxRetries } : {}
|
|
@@ -2478,19 +2573,19 @@ var SdkAdapter = class extends BaseAdapter {
|
|
|
2478
2573
|
|
|
2479
2574
|
// src/adapters/auto-adapter.ts
|
|
2480
2575
|
var defaultLogger = createLogger({ component: "auto-adapter" });
|
|
2481
|
-
function resolveCache(config,
|
|
2576
|
+
function resolveCache(config, logger12) {
|
|
2482
2577
|
if (config.cache !== void 0) {
|
|
2483
2578
|
return config.cache;
|
|
2484
2579
|
}
|
|
2485
2580
|
const enableCache = config.enableCache ?? true;
|
|
2486
|
-
return enableCache ? createCliDetectionCache({ logger:
|
|
2581
|
+
return enableCache ? createCliDetectionCache({ logger: logger12 }) : void 0;
|
|
2487
2582
|
}
|
|
2488
|
-
async function tryCliAdapter(config,
|
|
2583
|
+
async function tryCliAdapter(config, logger12, cache) {
|
|
2489
2584
|
const preferredCli = config.preferredCli;
|
|
2490
2585
|
const bridgeConfig = config.defaultCliTimeoutMs !== void 0 ? { defaultTimeoutMs: config.defaultCliTimeoutMs } : void 0;
|
|
2491
2586
|
if (preferredCli !== void 0 && await isCliAvailable(preferredCli, cache)) {
|
|
2492
|
-
|
|
2493
|
-
const cliAdapter2 = createCliAdapter({ cli: preferredCli, logger:
|
|
2587
|
+
logger12.info("Using preferred CLI", { cli: preferredCli });
|
|
2588
|
+
const cliAdapter2 = createCliAdapter({ cli: preferredCli, logger: logger12 });
|
|
2494
2589
|
await cliAdapter2.initialize();
|
|
2495
2590
|
return {
|
|
2496
2591
|
adapter: createCliToModelAdapter(cliAdapter2, bridgeConfig),
|
|
@@ -2502,15 +2597,15 @@ async function tryCliAdapter(config, logger11, cache) {
|
|
|
2502
2597
|
}
|
|
2503
2598
|
const availableClis = await getAvailableClis(cache);
|
|
2504
2599
|
if (availableClis.length === 0) {
|
|
2505
|
-
|
|
2600
|
+
logger12.info("No CLI adapters available");
|
|
2506
2601
|
return null;
|
|
2507
2602
|
}
|
|
2508
2603
|
const selectedCli = availableClis[0];
|
|
2509
2604
|
if (selectedCli === void 0) {
|
|
2510
2605
|
return null;
|
|
2511
2606
|
}
|
|
2512
|
-
|
|
2513
|
-
const cliAdapter = createCliAdapter({ cli: selectedCli, logger:
|
|
2607
|
+
logger12.info("Auto-selected CLI", { cli: selectedCli, available: availableClis });
|
|
2608
|
+
const cliAdapter = createCliAdapter({ cli: selectedCli, logger: logger12 });
|
|
2514
2609
|
await cliAdapter.initialize();
|
|
2515
2610
|
return {
|
|
2516
2611
|
adapter: createCliToModelAdapter(cliAdapter, bridgeConfig),
|
|
@@ -2524,13 +2619,13 @@ function resolveApiKeyFromEnv(configKey, envVar) {
|
|
|
2524
2619
|
const key = configKey ?? process.env[envVar];
|
|
2525
2620
|
return key !== void 0 && key.length > 0 ? key : void 0;
|
|
2526
2621
|
}
|
|
2527
|
-
function tryApiAdapter(config,
|
|
2528
|
-
const claudeModelId = getCliModelName(
|
|
2529
|
-
const codexModelId = getCliModelName(
|
|
2530
|
-
const geminiModelId = getCliModelName(
|
|
2622
|
+
function tryApiAdapter(config, logger12) {
|
|
2623
|
+
const claudeModelId = getCliModelName(getDefaultModelForCli("claude"));
|
|
2624
|
+
const codexModelId = getCliModelName(getDefaultModelForCli("codex"));
|
|
2625
|
+
const geminiModelId = getCliModelName(getDefaultModelForCli("gemini"));
|
|
2531
2626
|
const anthropicKey = resolveApiKeyFromEnv(config.anthropicApiKey, "ANTHROPIC_API_KEY");
|
|
2532
2627
|
if (anthropicKey !== void 0) {
|
|
2533
|
-
|
|
2628
|
+
logger12.info("Using Anthropic API adapter", { model: claudeModelId });
|
|
2534
2629
|
return {
|
|
2535
2630
|
adapter: createClaudeAdapter({ modelId: claudeModelId, apiKey: anthropicKey }),
|
|
2536
2631
|
source: "api",
|
|
@@ -2540,7 +2635,7 @@ function tryApiAdapter(config, logger11) {
|
|
|
2540
2635
|
}
|
|
2541
2636
|
const openaiKey = resolveApiKeyFromEnv(config.openaiApiKey, "OPENAI_API_KEY");
|
|
2542
2637
|
if (openaiKey !== void 0) {
|
|
2543
|
-
|
|
2638
|
+
logger12.info("Using OpenAI API adapter (AI SDK)", { model: codexModelId });
|
|
2544
2639
|
return {
|
|
2545
2640
|
adapter: new SdkAdapter({ providerId: "openai", modelId: codexModelId, apiKey: openaiKey }),
|
|
2546
2641
|
source: "api",
|
|
@@ -2550,7 +2645,7 @@ function tryApiAdapter(config, logger11) {
|
|
|
2550
2645
|
}
|
|
2551
2646
|
const googleKey = resolveApiKeyFromEnv(config.googleApiKey, "GOOGLE_AI_API_KEY");
|
|
2552
2647
|
if (googleKey !== void 0) {
|
|
2553
|
-
|
|
2648
|
+
logger12.info("Using Google AI API adapter (AI SDK)", { model: geminiModelId });
|
|
2554
2649
|
return {
|
|
2555
2650
|
adapter: new SdkAdapter({
|
|
2556
2651
|
providerId: "google",
|
|
@@ -2562,19 +2657,19 @@ function tryApiAdapter(config, logger11) {
|
|
|
2562
2657
|
reason: `Using Google AI API via AI SDK (model: ${geminiModelId})`
|
|
2563
2658
|
};
|
|
2564
2659
|
}
|
|
2565
|
-
const custom = tryCustomOpenAiAdapter(
|
|
2660
|
+
const custom = tryCustomOpenAiAdapter(logger12);
|
|
2566
2661
|
if (custom !== null) return custom;
|
|
2567
|
-
|
|
2662
|
+
logger12.info("No API keys available for any provider");
|
|
2568
2663
|
return null;
|
|
2569
2664
|
}
|
|
2570
|
-
function tryCustomOpenAiAdapter(
|
|
2665
|
+
function tryCustomOpenAiAdapter(logger12) {
|
|
2571
2666
|
const customKey = resolveApiKeyFromEnv(void 0, "NEXUS_CUSTOM_API_KEY");
|
|
2572
2667
|
const customBaseUrl = process.env["NEXUS_CUSTOM_API_BASE_URL"];
|
|
2573
2668
|
if (customKey === void 0 || customBaseUrl === void 0 || customBaseUrl === "") {
|
|
2574
2669
|
return null;
|
|
2575
2670
|
}
|
|
2576
2671
|
const customModelId = process.env["NEXUS_CUSTOM_MODEL"] ?? CUSTOM_API_DEFAULT_MODEL;
|
|
2577
|
-
|
|
2672
|
+
logger12.info("Using custom-openai SDK adapter", {
|
|
2578
2673
|
model: customModelId,
|
|
2579
2674
|
baseUrl: customBaseUrl
|
|
2580
2675
|
});
|
|
@@ -2590,52 +2685,52 @@ function tryCustomOpenAiAdapter(logger11) {
|
|
|
2590
2685
|
reason: `Using custom OpenAI-compatible gateway at ${customBaseUrl} (model: ${customModelId})`
|
|
2591
2686
|
};
|
|
2592
2687
|
}
|
|
2593
|
-
async function selectCliFirst(config,
|
|
2594
|
-
const cliResult = await tryCliAdapter(config,
|
|
2688
|
+
async function selectCliFirst(config, logger12, cache) {
|
|
2689
|
+
const cliResult = await tryCliAdapter(config, logger12, cache);
|
|
2595
2690
|
if (cliResult !== null) return cliResult;
|
|
2596
|
-
const apiResult = tryApiAdapter(config,
|
|
2691
|
+
const apiResult = tryApiAdapter(config, logger12);
|
|
2597
2692
|
if (apiResult !== null) return apiResult;
|
|
2598
2693
|
throw new Error(
|
|
2599
2694
|
"No adapters available. Install a CLI (claude/gemini/codex) or set ANTHROPIC_API_KEY, OPENAI_API_KEY, or GOOGLE_AI_API_KEY."
|
|
2600
2695
|
);
|
|
2601
2696
|
}
|
|
2602
|
-
async function selectApiFirst(config,
|
|
2603
|
-
const apiResult = tryApiAdapter(config,
|
|
2697
|
+
async function selectApiFirst(config, logger12, cache) {
|
|
2698
|
+
const apiResult = tryApiAdapter(config, logger12);
|
|
2604
2699
|
if (apiResult !== null) return apiResult;
|
|
2605
|
-
const cliResult = await tryCliAdapter(config,
|
|
2700
|
+
const cliResult = await tryCliAdapter(config, logger12, cache);
|
|
2606
2701
|
if (cliResult !== null) return cliResult;
|
|
2607
2702
|
throw new Error(
|
|
2608
2703
|
"No adapters available. Set ANTHROPIC_API_KEY/OPENAI_API_KEY/GOOGLE_AI_API_KEY or install a CLI (claude/gemini/codex)."
|
|
2609
2704
|
);
|
|
2610
2705
|
}
|
|
2611
|
-
async function selectCliOnly(config,
|
|
2612
|
-
const cliResult = await tryCliAdapter(config,
|
|
2706
|
+
async function selectCliOnly(config, logger12, cache) {
|
|
2707
|
+
const cliResult = await tryCliAdapter(config, logger12, cache);
|
|
2613
2708
|
if (cliResult !== null) return cliResult;
|
|
2614
2709
|
throw new Error(
|
|
2615
2710
|
"No CLI adapters available. Install and authenticate claude, gemini, or codex CLI."
|
|
2616
2711
|
);
|
|
2617
2712
|
}
|
|
2618
|
-
function selectApiOnly(config,
|
|
2619
|
-
const apiResult = tryApiAdapter(config,
|
|
2713
|
+
function selectApiOnly(config, logger12) {
|
|
2714
|
+
const apiResult = tryApiAdapter(config, logger12);
|
|
2620
2715
|
if (apiResult !== null) return apiResult;
|
|
2621
2716
|
throw new Error(
|
|
2622
2717
|
"No API key available. Set ANTHROPIC_API_KEY, OPENAI_API_KEY, or GOOGLE_AI_API_KEY."
|
|
2623
2718
|
);
|
|
2624
2719
|
}
|
|
2625
2720
|
async function createAutoAdapter(config = {}) {
|
|
2626
|
-
const
|
|
2721
|
+
const logger12 = config.logger ?? defaultLogger;
|
|
2627
2722
|
const priority = config.priority ?? "cli-first";
|
|
2628
|
-
const cache = resolveCache(config,
|
|
2629
|
-
|
|
2723
|
+
const cache = resolveCache(config, logger12);
|
|
2724
|
+
logger12.info("Auto-selecting adapter", { priority, cacheEnabled: cache !== void 0 });
|
|
2630
2725
|
switch (priority) {
|
|
2631
2726
|
case "cli-first":
|
|
2632
|
-
return selectCliFirst(config,
|
|
2727
|
+
return selectCliFirst(config, logger12, cache);
|
|
2633
2728
|
case "api-first":
|
|
2634
|
-
return selectApiFirst(config,
|
|
2729
|
+
return selectApiFirst(config, logger12, cache);
|
|
2635
2730
|
case "cli-only":
|
|
2636
|
-
return selectCliOnly(config,
|
|
2731
|
+
return selectCliOnly(config, logger12, cache);
|
|
2637
2732
|
case "api-only":
|
|
2638
|
-
return selectApiOnly(config,
|
|
2733
|
+
return selectApiOnly(config, logger12);
|
|
2639
2734
|
default: {
|
|
2640
2735
|
const exhaustive = priority;
|
|
2641
2736
|
throw new Error(`Unknown priority: ${String(exhaustive)}`);
|
|
@@ -3317,10 +3412,172 @@ function mapSelectionSource(selection) {
|
|
|
3317
3412
|
return "api";
|
|
3318
3413
|
}
|
|
3319
3414
|
|
|
3415
|
+
// src/adapters/model-not-found-fallback.ts
|
|
3416
|
+
var logger = createLogger({ component: "model-not-found-fallback" });
|
|
3417
|
+
function withModelNotFoundFallback(inner, options = {}) {
|
|
3418
|
+
const registry = options.registry ?? getDefaultRegistry();
|
|
3419
|
+
const cache = options.cache ?? getDefaultAvailableModelsCache();
|
|
3420
|
+
const resolvedOptions = {
|
|
3421
|
+
cache,
|
|
3422
|
+
registry,
|
|
3423
|
+
adapterFactory: options.adapterFactory,
|
|
3424
|
+
onRetirement: options.onRetirement
|
|
3425
|
+
};
|
|
3426
|
+
const wrapped = {
|
|
3427
|
+
providerId: inner.providerId,
|
|
3428
|
+
modelId: inner.modelId,
|
|
3429
|
+
capabilities: inner.capabilities,
|
|
3430
|
+
countTokens: (text) => inner.countTokens(text),
|
|
3431
|
+
validateConfig: () => inner.validateConfig(),
|
|
3432
|
+
stream: (request) => streamWithFallback(inner, request, resolvedOptions),
|
|
3433
|
+
complete: (request) => completeWithFallback(inner, request, resolvedOptions)
|
|
3434
|
+
};
|
|
3435
|
+
if (typeof inner.listModels === "function") {
|
|
3436
|
+
const list = inner.listModels.bind(inner);
|
|
3437
|
+
wrapped.listModels = () => list();
|
|
3438
|
+
}
|
|
3439
|
+
return wrapped;
|
|
3440
|
+
}
|
|
3441
|
+
async function completeWithFallback(inner, request, options) {
|
|
3442
|
+
const first = await inner.complete(request);
|
|
3443
|
+
if (first.ok) return first;
|
|
3444
|
+
if (first.error.code !== ErrorCode.MODEL_NOT_FOUND) return first;
|
|
3445
|
+
const fallback = await pickFallback(inner.modelId, options.cache, options.registry);
|
|
3446
|
+
if (fallback === null) {
|
|
3447
|
+
logger.warn("Model not found and no fallback available", {
|
|
3448
|
+
modelId: inner.modelId,
|
|
3449
|
+
providerId: inner.providerId,
|
|
3450
|
+
errorMessage: first.error.message
|
|
3451
|
+
});
|
|
3452
|
+
return first;
|
|
3453
|
+
}
|
|
3454
|
+
logger.info("Model retirement detected; retrying with fallback", {
|
|
3455
|
+
retiredModelId: inner.modelId,
|
|
3456
|
+
fallbackModelId: fallback,
|
|
3457
|
+
providerId: inner.providerId
|
|
3458
|
+
});
|
|
3459
|
+
notifyRetirement(options.onRetirement, {
|
|
3460
|
+
retiredModelId: inner.modelId,
|
|
3461
|
+
fallbackModelId: fallback,
|
|
3462
|
+
providerId: inner.providerId,
|
|
3463
|
+
errorMessage: first.error.message
|
|
3464
|
+
});
|
|
3465
|
+
if (options.adapterFactory === void 0) {
|
|
3466
|
+
return err(
|
|
3467
|
+
new ModelError(`${first.error.message} \u2014 suggested fallback: ${fallback}`, {
|
|
3468
|
+
code: ErrorCode.MODEL_NOT_FOUND,
|
|
3469
|
+
cause: first.error
|
|
3470
|
+
})
|
|
3471
|
+
);
|
|
3472
|
+
}
|
|
3473
|
+
const fallbackAdapter = options.adapterFactory(fallback);
|
|
3474
|
+
const retried = await fallbackAdapter.complete(request);
|
|
3475
|
+
if (retried.ok) return retried;
|
|
3476
|
+
return err(
|
|
3477
|
+
new ModelError(`Fallback ${fallback} also failed: ${retried.error.message}`, {
|
|
3478
|
+
code: retried.error.code,
|
|
3479
|
+
cause: retried.error
|
|
3480
|
+
})
|
|
3481
|
+
);
|
|
3482
|
+
}
|
|
3483
|
+
async function* streamWithFallback(inner, request, options) {
|
|
3484
|
+
try {
|
|
3485
|
+
for await (const chunk of inner.stream(request)) {
|
|
3486
|
+
yield chunk;
|
|
3487
|
+
}
|
|
3488
|
+
return;
|
|
3489
|
+
} catch (e) {
|
|
3490
|
+
if (!isModelNotFoundError(e)) throw e;
|
|
3491
|
+
const fallbackAdapter = await resolveStreamFallback(inner, e, options);
|
|
3492
|
+
for await (const chunk of fallbackAdapter.stream(request)) {
|
|
3493
|
+
yield chunk;
|
|
3494
|
+
}
|
|
3495
|
+
}
|
|
3496
|
+
}
|
|
3497
|
+
async function resolveStreamFallback(inner, cause, options) {
|
|
3498
|
+
const fallback = await pickFallback(inner.modelId, options.cache, options.registry);
|
|
3499
|
+
if (fallback === null) {
|
|
3500
|
+
logger.warn("Stream model not found and no fallback available", {
|
|
3501
|
+
modelId: inner.modelId,
|
|
3502
|
+
providerId: inner.providerId,
|
|
3503
|
+
errorMessage: cause instanceof Error ? cause.message : String(cause)
|
|
3504
|
+
});
|
|
3505
|
+
throw cause;
|
|
3506
|
+
}
|
|
3507
|
+
logger.info("Stream retirement detected; restarting with fallback (restart-from-zero)", {
|
|
3508
|
+
retiredModelId: inner.modelId,
|
|
3509
|
+
fallbackModelId: fallback,
|
|
3510
|
+
providerId: inner.providerId
|
|
3511
|
+
});
|
|
3512
|
+
notifyRetirement(options.onRetirement, {
|
|
3513
|
+
retiredModelId: inner.modelId,
|
|
3514
|
+
fallbackModelId: fallback,
|
|
3515
|
+
providerId: inner.providerId,
|
|
3516
|
+
errorMessage: cause instanceof Error ? cause.message : String(cause)
|
|
3517
|
+
});
|
|
3518
|
+
if (options.adapterFactory === void 0) {
|
|
3519
|
+
const message = `${cause instanceof Error ? cause.message : String(cause)} \u2014 suggested fallback: ${fallback}`;
|
|
3520
|
+
const causeErr = cause instanceof Error ? cause : void 0;
|
|
3521
|
+
throw new ModelError(
|
|
3522
|
+
message,
|
|
3523
|
+
causeErr !== void 0 ? { code: ErrorCode.MODEL_NOT_FOUND, cause: causeErr } : { code: ErrorCode.MODEL_NOT_FOUND }
|
|
3524
|
+
);
|
|
3525
|
+
}
|
|
3526
|
+
return options.adapterFactory(fallback);
|
|
3527
|
+
}
|
|
3528
|
+
function isModelNotFoundError(e) {
|
|
3529
|
+
if (e instanceof ModelError) {
|
|
3530
|
+
return e.code === ErrorCode.MODEL_NOT_FOUND;
|
|
3531
|
+
}
|
|
3532
|
+
if (typeof e === "object" && e !== null && "code" in e) {
|
|
3533
|
+
return e.code === ErrorCode.MODEL_NOT_FOUND;
|
|
3534
|
+
}
|
|
3535
|
+
return false;
|
|
3536
|
+
}
|
|
3537
|
+
function notifyRetirement(cb, info) {
|
|
3538
|
+
if (cb === void 0) return;
|
|
3539
|
+
try {
|
|
3540
|
+
cb(info);
|
|
3541
|
+
} catch (e) {
|
|
3542
|
+
logger.debug("onRetirement callback threw", {
|
|
3543
|
+
error: e instanceof Error ? e.message : String(e)
|
|
3544
|
+
});
|
|
3545
|
+
}
|
|
3546
|
+
}
|
|
3547
|
+
async function pickFallback(retiredModelId, cache, registry) {
|
|
3548
|
+
const refreshed = await cache.refresh();
|
|
3549
|
+
if (refreshed.length === 0) return null;
|
|
3550
|
+
const target = registry.getEntry(retiredModelId);
|
|
3551
|
+
const sameFamily = refreshed.find((m) => {
|
|
3552
|
+
if (m.id === retiredModelId) return false;
|
|
3553
|
+
const candidate = registry.getEntry(m.id);
|
|
3554
|
+
return candidate.family === target.family && candidate.vendor === target.vendor;
|
|
3555
|
+
});
|
|
3556
|
+
if (sameFamily !== void 0) return sameFamily.id;
|
|
3557
|
+
const sameVendor = refreshed.find((m) => {
|
|
3558
|
+
if (m.id === retiredModelId) return false;
|
|
3559
|
+
const candidate = registry.getEntry(m.id);
|
|
3560
|
+
return candidate.vendor === target.vendor;
|
|
3561
|
+
});
|
|
3562
|
+
return sameVendor?.id ?? null;
|
|
3563
|
+
}
|
|
3564
|
+
function wrapResilientWithFallback(inner, options = {}) {
|
|
3565
|
+
const wrapped = withModelNotFoundFallback(inner, options);
|
|
3566
|
+
return Object.assign(wrapped, {
|
|
3567
|
+
getHealth: inner.getHealth.bind(inner),
|
|
3568
|
+
refresh: inner.refresh.bind(inner),
|
|
3569
|
+
setPreferredCli: inner.setPreferredCli.bind(inner),
|
|
3570
|
+
onFailover: inner.onFailover.bind(inner),
|
|
3571
|
+
dispose: inner.dispose.bind(inner)
|
|
3572
|
+
});
|
|
3573
|
+
}
|
|
3574
|
+
|
|
3320
3575
|
// src/adapters/unified-registry.ts
|
|
3321
3576
|
var UnifiedAdapterRegistry = class {
|
|
3322
3577
|
logger;
|
|
3323
3578
|
defaultCliTimeoutMs;
|
|
3579
|
+
enableMissingModelFallback;
|
|
3580
|
+
missingModelFallbackOptions;
|
|
3324
3581
|
/** Pre-computed task → CLI routing (immutable after construction). */
|
|
3325
3582
|
taskRouting;
|
|
3326
3583
|
/** Per-CLI adapter cache — max 3 entries (claude/gemini/codex). */
|
|
@@ -3330,12 +3587,26 @@ var UnifiedAdapterRegistry = class {
|
|
|
3330
3587
|
constructor(config) {
|
|
3331
3588
|
this.logger = config?.logger ?? createLogger({ component: "unified-registry" });
|
|
3332
3589
|
this.defaultCliTimeoutMs = config?.defaultCliTimeoutMs;
|
|
3590
|
+
this.enableMissingModelFallback = config?.enableMissingModelFallback ?? false;
|
|
3591
|
+
this.missingModelFallbackOptions = config?.missingModelFallbackOptions;
|
|
3333
3592
|
this.taskRouting = this.buildTaskRouting();
|
|
3334
3593
|
this.logger.info("UnifiedAdapterRegistry initialized", {
|
|
3335
3594
|
categories: this.taskRouting.size,
|
|
3336
|
-
models:
|
|
3595
|
+
models: getInTreeCapabilitiesMatrix().models.length,
|
|
3596
|
+
missingModelFallback: this.enableMissingModelFallback
|
|
3337
3597
|
});
|
|
3338
3598
|
}
|
|
3599
|
+
/**
|
|
3600
|
+
* Apply the MODEL_NOT_FOUND fallback decorator if enabled, otherwise
|
|
3601
|
+
* return the adapter unchanged. The recursion guard from the original
|
|
3602
|
+
* issue is unnecessary here: the decorator's retry path uses the
|
|
3603
|
+
* caller-supplied `adapterFactory`; without one, it surfaces an
|
|
3604
|
+
* enriched error and never re-enters the resilient layer.
|
|
3605
|
+
*/
|
|
3606
|
+
maybeWrap(adapter) {
|
|
3607
|
+
if (!this.enableMissingModelFallback) return adapter;
|
|
3608
|
+
return wrapResilientWithFallback(adapter, this.missingModelFallbackOptions);
|
|
3609
|
+
}
|
|
3339
3610
|
// --------------------------------------------------------------------------
|
|
3340
3611
|
// Public API
|
|
3341
3612
|
// --------------------------------------------------------------------------
|
|
@@ -3377,15 +3648,19 @@ var UnifiedAdapterRegistry = class {
|
|
|
3377
3648
|
getAdapterForCli(cli) {
|
|
3378
3649
|
const cached = this.cliAdapters.get(cli);
|
|
3379
3650
|
if (cached !== void 0) return cached;
|
|
3380
|
-
const
|
|
3651
|
+
const raw = createResilientAdapter({
|
|
3381
3652
|
logger: this.logger,
|
|
3382
3653
|
preferredCli: cli,
|
|
3383
3654
|
...this.defaultCliTimeoutMs !== void 0 && {
|
|
3384
3655
|
defaultCliTimeoutMs: this.defaultCliTimeoutMs
|
|
3385
3656
|
}
|
|
3386
3657
|
});
|
|
3658
|
+
const adapter = this.maybeWrap(raw);
|
|
3387
3659
|
this.cliAdapters.set(cli, adapter);
|
|
3388
|
-
this.logger.info("Created CLI-specific adapter", {
|
|
3660
|
+
this.logger.info("Created CLI-specific adapter", {
|
|
3661
|
+
cli,
|
|
3662
|
+
missingModelFallback: this.enableMissingModelFallback
|
|
3663
|
+
});
|
|
3389
3664
|
return adapter;
|
|
3390
3665
|
}
|
|
3391
3666
|
/**
|
|
@@ -3394,10 +3669,11 @@ var UnifiedAdapterRegistry = class {
|
|
|
3394
3669
|
* Falls back to default adapter if model not recognized.
|
|
3395
3670
|
*/
|
|
3396
3671
|
getAdapterForModel(modelPreference) {
|
|
3397
|
-
const
|
|
3672
|
+
const allModels = getInTreeCapabilitiesMatrix().models;
|
|
3673
|
+
const exact = allModels.find(
|
|
3398
3674
|
(m) => m.id === modelPreference || m.cliAlias === modelPreference || m.cliModelName === modelPreference
|
|
3399
3675
|
);
|
|
3400
|
-
const prefix = exact ?? [...
|
|
3676
|
+
const prefix = exact ?? [...allModels].filter((m) => modelPreference.startsWith(m.id)).sort((a, b) => b.id.length - a.id.length)[0];
|
|
3401
3677
|
const model = prefix;
|
|
3402
3678
|
if (model !== void 0) {
|
|
3403
3679
|
this.logger.debug("Model resolved to CLI", {
|
|
@@ -3425,12 +3701,13 @@ var UnifiedAdapterRegistry = class {
|
|
|
3425
3701
|
*/
|
|
3426
3702
|
getDefault() {
|
|
3427
3703
|
if (this.defaultAdapter !== void 0) return this.defaultAdapter;
|
|
3428
|
-
|
|
3704
|
+
const raw = createResilientAdapter({
|
|
3429
3705
|
logger: this.logger,
|
|
3430
3706
|
...this.defaultCliTimeoutMs !== void 0 && {
|
|
3431
3707
|
defaultCliTimeoutMs: this.defaultCliTimeoutMs
|
|
3432
3708
|
}
|
|
3433
3709
|
});
|
|
3710
|
+
this.defaultAdapter = this.maybeWrap(raw);
|
|
3434
3711
|
return this.defaultAdapter;
|
|
3435
3712
|
}
|
|
3436
3713
|
/**
|
|
@@ -3440,7 +3717,7 @@ var UnifiedAdapterRegistry = class {
|
|
|
3440
3717
|
return {
|
|
3441
3718
|
taskRouting: [...this.taskRouting.values()],
|
|
3442
3719
|
cachedAdapters: [...this.cliAdapters.keys()],
|
|
3443
|
-
availableModels:
|
|
3720
|
+
availableModels: getInTreeCapabilitiesMatrix().models.length
|
|
3444
3721
|
};
|
|
3445
3722
|
}
|
|
3446
3723
|
/**
|
|
@@ -3491,8 +3768,8 @@ var ROLE_TO_CATEGORY = {
|
|
|
3491
3768
|
infrastructure_expert: "devops"
|
|
3492
3769
|
};
|
|
3493
3770
|
function resolveDefaultModel(cli) {
|
|
3494
|
-
if (cli
|
|
3495
|
-
return
|
|
3771
|
+
if (CLI_NAMES.includes(cli)) {
|
|
3772
|
+
return getDefaultModelForCli(cli);
|
|
3496
3773
|
}
|
|
3497
3774
|
return cli;
|
|
3498
3775
|
}
|
|
@@ -3725,7 +4002,7 @@ var SIMULATED_VOTE_REASONING = {
|
|
|
3725
4002
|
};
|
|
3726
4003
|
|
|
3727
4004
|
// src/cli/voter-response.ts
|
|
3728
|
-
import { z as
|
|
4005
|
+
import { z as z3 } from "zod";
|
|
3729
4006
|
var SyntheticVoteError = class extends Error {
|
|
3730
4007
|
constructor(reason, rawOutput) {
|
|
3731
4008
|
super(
|
|
@@ -3735,26 +4012,26 @@ var SyntheticVoteError = class extends Error {
|
|
|
3735
4012
|
this.name = "SyntheticVoteError";
|
|
3736
4013
|
}
|
|
3737
4014
|
};
|
|
3738
|
-
var RawFindingSchema =
|
|
3739
|
-
summary:
|
|
3740
|
-
location:
|
|
3741
|
-
severity:
|
|
3742
|
-
gate:
|
|
3743
|
-
reread_cited_line:
|
|
3744
|
-
traced_call_path:
|
|
3745
|
-
named_assertion:
|
|
3746
|
-
ruled_out_language_non_issue:
|
|
4015
|
+
var RawFindingSchema = z3.object({
|
|
4016
|
+
summary: z3.string().min(1).max(500).describe("One-line summary of the issue"),
|
|
4017
|
+
location: z3.string().min(1).max(200).describe("path/file.ext:line"),
|
|
4018
|
+
severity: z3.enum(["critical", "high", "medium", "low"]).default("medium"),
|
|
4019
|
+
gate: z3.object({
|
|
4020
|
+
reread_cited_line: z3.enum(["passed", "failed", "skipped"]).default("skipped"),
|
|
4021
|
+
traced_call_path: z3.enum(["passed", "failed", "skipped"]).default("skipped"),
|
|
4022
|
+
named_assertion: z3.string().default("").describe("Concrete failing assertion \u2014 substantive, not a rubber-stamp word"),
|
|
4023
|
+
ruled_out_language_non_issue: z3.enum(["passed", "failed", "skipped"]).default("skipped")
|
|
3747
4024
|
}),
|
|
3748
|
-
claim:
|
|
4025
|
+
claim: z3.string().min(1).max(2e3).describe("What is wrong and why it justifies blocking")
|
|
3749
4026
|
});
|
|
3750
|
-
var VoteResponseSchema =
|
|
3751
|
-
decision:
|
|
3752
|
-
reasoning:
|
|
3753
|
-
confidence:
|
|
3754
|
-
conditions:
|
|
4027
|
+
var VoteResponseSchema = z3.object({
|
|
4028
|
+
decision: z3.enum(["approve", "reject", "abstain"]).describe("Your vote decision"),
|
|
4029
|
+
reasoning: z3.string().min(10).max(4e3).describe("Explanation for your vote (10-4000 chars)"),
|
|
4030
|
+
confidence: z3.number().min(0).max(1).describe("Confidence level 0-1"),
|
|
4031
|
+
conditions: z3.array(z3.string()).optional().describe("Optional conditions for approval"),
|
|
3755
4032
|
/** Structured rejection categories for reject→refine→re-vote loops (Issue #1213). */
|
|
3756
|
-
rejectionCategories:
|
|
3757
|
-
|
|
4033
|
+
rejectionCategories: z3.array(
|
|
4034
|
+
z3.enum([
|
|
3758
4035
|
"YAGNI",
|
|
3759
4036
|
"DRY_VIOLATION",
|
|
3760
4037
|
"OVER_ENGINEERING",
|
|
@@ -3766,7 +4043,7 @@ var VoteResponseSchema = z2.object({
|
|
|
3766
4043
|
).optional().describe("Rejection reason categories when decision is reject"),
|
|
3767
4044
|
/** Top-level structured findings for PR-review mode (#2245 v4 follow-up).
|
|
3768
4045
|
* Replaces the YAML-in-reasoning encoding that proved lossy. */
|
|
3769
|
-
findings:
|
|
4046
|
+
findings: z3.array(RawFindingSchema).optional().describe("Structured findings (PR review only)")
|
|
3770
4047
|
});
|
|
3771
4048
|
var VOTE_PROMPT_EXAMPLES = `Example approve response:
|
|
3772
4049
|
{
|
|
@@ -3904,7 +4181,6 @@ var RATE_LIMIT_RETRY_DELAY_MS = 5e3;
|
|
|
3904
4181
|
function isRateLimitError(message) {
|
|
3905
4182
|
return isRateLimitLikeError(new Error(message));
|
|
3906
4183
|
}
|
|
3907
|
-
var validateTimeout2 = validateTimeout;
|
|
3908
4184
|
function createErrorVoteResult(role, errorMsg, processingTimeMs) {
|
|
3909
4185
|
return {
|
|
3910
4186
|
role,
|
|
@@ -4031,21 +4307,21 @@ async function executeSingleVoteAttempt(role, proposal, adapter, timeoutMs) {
|
|
|
4031
4307
|
}
|
|
4032
4308
|
}
|
|
4033
4309
|
async function executeWithRetries(opts) {
|
|
4034
|
-
const { role, proposal, adapter, logger:
|
|
4310
|
+
const { role, proposal, adapter, logger: logger12, timeoutMs, maxRetries } = opts;
|
|
4035
4311
|
let lastError = "";
|
|
4036
4312
|
for (let attempt = 0; attempt <= maxRetries; attempt++) {
|
|
4037
4313
|
if (attempt > 0) {
|
|
4038
4314
|
const isRateLimit = isRateLimitError(lastError);
|
|
4039
4315
|
const baseDelay = isRateLimit ? RATE_LIMIT_RETRY_DELAY_MS : INITIAL_RETRY_DELAY_MS;
|
|
4040
4316
|
const delayMs = baseDelay * Math.pow(2, attempt - 1);
|
|
4041
|
-
|
|
4317
|
+
logger12.debug("Retrying vote execution", { role, attempt, delayMs, isRateLimit });
|
|
4042
4318
|
await delay(delayMs);
|
|
4043
4319
|
}
|
|
4044
4320
|
const attemptStart = Date.now();
|
|
4045
4321
|
const result = await executeSingleVoteAttempt(role, proposal, adapter, timeoutMs);
|
|
4046
4322
|
const attemptMs = Date.now() - attemptStart;
|
|
4047
4323
|
if (result.ok) {
|
|
4048
|
-
|
|
4324
|
+
logger12.info("Vote attempt timing", {
|
|
4049
4325
|
role,
|
|
4050
4326
|
attempt: attempt + 1,
|
|
4051
4327
|
attemptMs,
|
|
@@ -4055,14 +4331,14 @@ async function executeWithRetries(opts) {
|
|
|
4055
4331
|
}
|
|
4056
4332
|
lastError = result.error;
|
|
4057
4333
|
const rateLimited = isRateLimitError(lastError);
|
|
4058
|
-
|
|
4334
|
+
logger12.info("Vote attempt timing", {
|
|
4059
4335
|
role,
|
|
4060
4336
|
attempt: attempt + 1,
|
|
4061
4337
|
attemptMs,
|
|
4062
4338
|
succeeded: false,
|
|
4063
4339
|
rateLimited
|
|
4064
4340
|
});
|
|
4065
|
-
|
|
4341
|
+
logger12.warn("Vote attempt failed", {
|
|
4066
4342
|
role,
|
|
4067
4343
|
attempt: attempt + 1,
|
|
4068
4344
|
maxRetries: maxRetries + 1,
|
|
@@ -4092,7 +4368,7 @@ async function launchVotesWithOverallDeadline(input) {
|
|
|
4092
4368
|
proposal,
|
|
4093
4369
|
roleAdapters,
|
|
4094
4370
|
fallbackAdapter,
|
|
4095
|
-
logger:
|
|
4371
|
+
logger: logger12,
|
|
4096
4372
|
voteOptions,
|
|
4097
4373
|
interDelay,
|
|
4098
4374
|
overallDeadlineMs,
|
|
@@ -4104,12 +4380,12 @@ async function launchVotesWithOverallDeadline(input) {
|
|
|
4104
4380
|
const adapter = roleAdapters.get(role) ?? fallbackAdapter;
|
|
4105
4381
|
const elapsed = Date.now() - startedAt;
|
|
4106
4382
|
const remaining = Math.max(1, overallDeadlineMs - elapsed);
|
|
4107
|
-
return raceWithDeadline(voteFn(role, proposal, adapter,
|
|
4383
|
+
return raceWithDeadline(voteFn(role, proposal, adapter, logger12, voteOptions), role, remaining);
|
|
4108
4384
|
});
|
|
4109
4385
|
const results = await Promise.all(wrapped);
|
|
4110
4386
|
const expired = results.filter((r) => r.source === "error" && r.error === DEADLINE_MESSAGE);
|
|
4111
4387
|
if (expired.length > 0) {
|
|
4112
|
-
|
|
4388
|
+
logger12.warn("Consensus overall deadline reached; returning partial results", {
|
|
4113
4389
|
totalRoles: roles.length,
|
|
4114
4390
|
expiredRoles: expired.map((r) => r.role),
|
|
4115
4391
|
overallDeadlineMs
|
|
@@ -4122,36 +4398,36 @@ async function launchVotesWithOverallDeadline(input) {
|
|
|
4122
4398
|
function computeOverallConsensusDeadlineMs(timeoutMs, maxRetries, roleCount, interDelayMs) {
|
|
4123
4399
|
const perVoteBudget = timeoutMs * (maxRetries + 1);
|
|
4124
4400
|
const staggerBudget = Math.max(0, roleCount - 1) * interDelayMs;
|
|
4125
|
-
return perVoteBudget + staggerBudget +
|
|
4401
|
+
return perVoteBudget + staggerBudget + VOTE_TIMEOUTS.overallDeadlineBufferMs;
|
|
4126
4402
|
}
|
|
4127
4403
|
var DEFAULT_INTER_AGENT_DELAY_MS = 2e3;
|
|
4128
4404
|
var defaultLogger2 = createLogger({ component: "voter-agents" });
|
|
4129
|
-
async function executeAgentVote(role, proposal, adapter,
|
|
4405
|
+
async function executeAgentVote(role, proposal, adapter, logger12, options) {
|
|
4130
4406
|
const start = getTimeProvider().now();
|
|
4131
4407
|
const timeoutMs = options?.timeoutMs ?? resolveVoteTimeout();
|
|
4132
4408
|
const maxRetries = options?.maxRetries ?? VOTE_TIMEOUTS.maxRetries;
|
|
4133
4409
|
const allowSimulation = options?.allowSimulation ?? false;
|
|
4134
|
-
|
|
4410
|
+
logger12.info("Executing vote", { role, model: adapter.modelId, provider: adapter.providerId });
|
|
4135
4411
|
const result = await executeWithRetries({
|
|
4136
4412
|
role,
|
|
4137
4413
|
proposal,
|
|
4138
4414
|
adapter,
|
|
4139
|
-
logger:
|
|
4415
|
+
logger: logger12,
|
|
4140
4416
|
timeoutMs,
|
|
4141
4417
|
maxRetries
|
|
4142
4418
|
});
|
|
4143
4419
|
const processingTimeMs = getTimeProvider().now() - start;
|
|
4144
4420
|
if (result.ok) {
|
|
4145
|
-
|
|
4421
|
+
logger12.info("Vote completed", { role, model: adapter.modelId, decision: result.vote.decision });
|
|
4146
4422
|
return { role, vote: result.vote, processingTimeMs, source: "llm", cli: adapter.providerId };
|
|
4147
4423
|
}
|
|
4148
|
-
|
|
4424
|
+
logger12.error("Vote execution failed after all retries", void 0, {
|
|
4149
4425
|
role,
|
|
4150
4426
|
model: adapter.modelId,
|
|
4151
4427
|
errorMessage: result.error
|
|
4152
4428
|
});
|
|
4153
4429
|
if (allowSimulation) {
|
|
4154
|
-
|
|
4430
|
+
logger12.warn("Falling back to simulation (allowSimulation=true)", { role });
|
|
4155
4431
|
return createSimulationVoteResult(role, proposal, processingTimeMs, result.error);
|
|
4156
4432
|
}
|
|
4157
4433
|
return createErrorVoteResult(role, result.error, processingTimeMs);
|
|
@@ -4162,10 +4438,10 @@ var NoAdapterError = class extends Error {
|
|
|
4162
4438
|
this.name = "NoAdapterError";
|
|
4163
4439
|
}
|
|
4164
4440
|
};
|
|
4165
|
-
function resolveAdapter(options,
|
|
4441
|
+
function resolveAdapter(options, logger12) {
|
|
4166
4442
|
try {
|
|
4167
4443
|
if (options.adapter !== void 0) return { adapter: options.adapter };
|
|
4168
|
-
const registry = getGlobalRegistry({ logger:
|
|
4444
|
+
const registry = getGlobalRegistry({ logger: logger12 });
|
|
4169
4445
|
return { adapter: registry.getDefault() };
|
|
4170
4446
|
} catch (error) {
|
|
4171
4447
|
return { error: getErrorMessage(error) };
|
|
@@ -4176,29 +4452,29 @@ function assignUniformAdapter(roles, adapter) {
|
|
|
4176
4452
|
for (const role of roles) adapters.set(role, adapter);
|
|
4177
4453
|
return adapters;
|
|
4178
4454
|
}
|
|
4179
|
-
function createCliAdapterMap(clis,
|
|
4180
|
-
const registry = getGlobalRegistry({ logger:
|
|
4455
|
+
function createCliAdapterMap(clis, logger12) {
|
|
4456
|
+
const registry = getGlobalRegistry({ logger: logger12 });
|
|
4181
4457
|
const result = /* @__PURE__ */ new Map();
|
|
4182
4458
|
for (const cli of clis) {
|
|
4183
4459
|
result.set(cli, registry.getAdapterForCli(cli));
|
|
4184
4460
|
}
|
|
4185
4461
|
return result;
|
|
4186
4462
|
}
|
|
4187
|
-
async function resolveDiverseAdapters(roles,
|
|
4463
|
+
async function resolveDiverseAdapters(roles, logger12, fallbackAdapter) {
|
|
4188
4464
|
let availableClis;
|
|
4189
4465
|
try {
|
|
4190
4466
|
availableClis = await getAvailableClis();
|
|
4191
4467
|
} catch (e) {
|
|
4192
|
-
|
|
4468
|
+
logger12.warn("Failed to resolve available CLIs; falling back to single adapter", {
|
|
4193
4469
|
error: String(e)
|
|
4194
4470
|
});
|
|
4195
4471
|
availableClis = [];
|
|
4196
4472
|
}
|
|
4197
4473
|
if (availableClis.length <= 1) {
|
|
4198
|
-
|
|
4474
|
+
logger12.info("Using single adapter for all roles", { cliCount: availableClis.length });
|
|
4199
4475
|
return assignUniformAdapter(roles, fallbackAdapter);
|
|
4200
4476
|
}
|
|
4201
|
-
const cliAdapters = createCliAdapterMap(availableClis,
|
|
4477
|
+
const cliAdapters = createCliAdapterMap(availableClis, logger12);
|
|
4202
4478
|
if (cliAdapters.size <= 1) return assignUniformAdapter(roles, fallbackAdapter);
|
|
4203
4479
|
const cliList = [...cliAdapters.entries()];
|
|
4204
4480
|
const adapters = /* @__PURE__ */ new Map();
|
|
@@ -4210,7 +4486,7 @@ async function resolveDiverseAdapters(roles, logger11, fallbackAdapter) {
|
|
|
4210
4486
|
adapters.set(role, entry[1]);
|
|
4211
4487
|
assignments[role] = entry[0];
|
|
4212
4488
|
}
|
|
4213
|
-
|
|
4489
|
+
logger12.info("Diverse adapters assigned", {
|
|
4214
4490
|
cliCount: cliAdapters.size,
|
|
4215
4491
|
clis: [...cliAdapters.keys()],
|
|
4216
4492
|
roleAssignments: assignments
|
|
@@ -4218,7 +4494,7 @@ async function resolveDiverseAdapters(roles, logger11, fallbackAdapter) {
|
|
|
4218
4494
|
return adapters;
|
|
4219
4495
|
}
|
|
4220
4496
|
async function launchStaggeredVotes(input) {
|
|
4221
|
-
const { roles, proposal, roleAdapters, fallbackAdapter, logger:
|
|
4497
|
+
const { roles, proposal, roleAdapters, fallbackAdapter, logger: logger12, voteOptions, interDelay } = input;
|
|
4222
4498
|
const computedDeadlineMs = computeOverallConsensusDeadlineMs(
|
|
4223
4499
|
voteOptions.timeoutMs,
|
|
4224
4500
|
voteOptions.maxRetries,
|
|
@@ -4227,7 +4503,7 @@ async function launchStaggeredVotes(input) {
|
|
|
4227
4503
|
);
|
|
4228
4504
|
const overallDeadlineMs = getMcpSafeDeadlineMs(computedDeadlineMs, "consensus_vote");
|
|
4229
4505
|
if (overallDeadlineMs < computedDeadlineMs) {
|
|
4230
|
-
|
|
4506
|
+
logger12.debug("Consensus deadline clamped to MCP wrapper timeout", {
|
|
4231
4507
|
computedDeadlineMs,
|
|
4232
4508
|
overallDeadlineMs
|
|
4233
4509
|
});
|
|
@@ -4237,7 +4513,7 @@ async function launchStaggeredVotes(input) {
|
|
|
4237
4513
|
proposal,
|
|
4238
4514
|
roleAdapters,
|
|
4239
4515
|
fallbackAdapter,
|
|
4240
|
-
logger:
|
|
4516
|
+
logger: logger12,
|
|
4241
4517
|
voteOptions,
|
|
4242
4518
|
interDelay,
|
|
4243
4519
|
overallDeadlineMs,
|
|
@@ -4245,26 +4521,26 @@ async function launchStaggeredVotes(input) {
|
|
|
4245
4521
|
});
|
|
4246
4522
|
}
|
|
4247
4523
|
async function collectRealVotes(options) {
|
|
4248
|
-
const
|
|
4524
|
+
const logger12 = options.logger ?? defaultLogger2;
|
|
4249
4525
|
const { roles, proposal, simulate, allowSimulation } = options;
|
|
4250
4526
|
const timeoutMs = options.timeoutMs ?? resolveVoteTimeout();
|
|
4251
4527
|
const maxRetries = options.maxRetries ?? VOTE_TIMEOUTS.maxRetries;
|
|
4252
4528
|
if (simulate === true) {
|
|
4253
|
-
|
|
4529
|
+
logger12.info("Using simulation mode (explicitly requested)");
|
|
4254
4530
|
return createSimulatedVotes(roles, proposal);
|
|
4255
4531
|
}
|
|
4256
|
-
const adapterResult = resolveAdapter(options,
|
|
4532
|
+
const adapterResult = resolveAdapter(options, logger12);
|
|
4257
4533
|
if ("error" in adapterResult) {
|
|
4258
|
-
|
|
4534
|
+
logger12.error("No adapter available for voting", void 0, { error: adapterResult.error });
|
|
4259
4535
|
if (allowSimulation === true) {
|
|
4260
|
-
|
|
4536
|
+
logger12.warn("Falling back to simulation (allowSimulation=true)");
|
|
4261
4537
|
return createSimulatedVotes(roles, proposal, "No adapter available");
|
|
4262
4538
|
}
|
|
4263
4539
|
throw new NoAdapterError(
|
|
4264
4540
|
`No adapter available for voting: ${adapterResult.error}. Install a CLI (claude/gemini/codex) or set ANTHROPIC_API_KEY.`
|
|
4265
4541
|
);
|
|
4266
4542
|
}
|
|
4267
|
-
const roleAdapters = options.adapter !== void 0 ? assignUniformAdapter(roles, adapterResult.adapter) : await resolveDiverseAdapters(roles,
|
|
4543
|
+
const roleAdapters = options.adapter !== void 0 ? assignUniformAdapter(roles, adapterResult.adapter) : await resolveDiverseAdapters(roles, logger12, adapterResult.adapter);
|
|
4268
4544
|
const voteOptions = { timeoutMs, maxRetries, allowSimulation: allowSimulation ?? false };
|
|
4269
4545
|
const interDelay = options.interAgentDelayMs ?? DEFAULT_INTER_AGENT_DELAY_MS;
|
|
4270
4546
|
return launchStaggeredVotes({
|
|
@@ -4272,15 +4548,15 @@ async function collectRealVotes(options) {
|
|
|
4272
4548
|
proposal,
|
|
4273
4549
|
roleAdapters,
|
|
4274
4550
|
fallbackAdapter: adapterResult.adapter,
|
|
4275
|
-
logger:
|
|
4551
|
+
logger: logger12,
|
|
4276
4552
|
voteOptions,
|
|
4277
4553
|
interDelay
|
|
4278
4554
|
});
|
|
4279
4555
|
}
|
|
4280
4556
|
|
|
4281
4557
|
// src/consensus/types-core.ts
|
|
4282
|
-
import { z as
|
|
4283
|
-
var ConsensusAlgorithmSchema =
|
|
4558
|
+
import { z as z4 } from "zod";
|
|
4559
|
+
var ConsensusAlgorithmSchema = z4.enum([
|
|
4284
4560
|
"simple_majority",
|
|
4285
4561
|
"supermajority",
|
|
4286
4562
|
"unanimous",
|
|
@@ -4288,8 +4564,8 @@ var ConsensusAlgorithmSchema = z3.enum([
|
|
|
4288
4564
|
"opinion_wise",
|
|
4289
4565
|
"higher_order"
|
|
4290
4566
|
]);
|
|
4291
|
-
var VoteDecisionSchema =
|
|
4292
|
-
var ProposalStatusSchema =
|
|
4567
|
+
var VoteDecisionSchema = z4.enum(["approve", "reject", "abstain"]);
|
|
4568
|
+
var ProposalStatusSchema = z4.enum([
|
|
4293
4569
|
"pending",
|
|
4294
4570
|
"voting",
|
|
4295
4571
|
"approved",
|
|
@@ -4297,7 +4573,7 @@ var ProposalStatusSchema = z3.enum([
|
|
|
4297
4573
|
"timeout",
|
|
4298
4574
|
"closed"
|
|
4299
4575
|
]);
|
|
4300
|
-
var RejectionCategorySchema =
|
|
4576
|
+
var RejectionCategorySchema = z4.enum([
|
|
4301
4577
|
"YAGNI",
|
|
4302
4578
|
"DRY_VIOLATION",
|
|
4303
4579
|
"OVER_ENGINEERING",
|
|
@@ -4307,69 +4583,69 @@ var RejectionCategorySchema = z3.enum([
|
|
|
4307
4583
|
"INSUFFICIENT_EVIDENCE"
|
|
4308
4584
|
]);
|
|
4309
4585
|
var REJECTION_CATEGORIES = RejectionCategorySchema.options;
|
|
4310
|
-
var FindingShapeSchema =
|
|
4311
|
-
summary:
|
|
4312
|
-
location:
|
|
4313
|
-
severity:
|
|
4314
|
-
gate:
|
|
4315
|
-
reread_cited_line:
|
|
4316
|
-
traced_call_path:
|
|
4317
|
-
named_assertion:
|
|
4318
|
-
ruled_out_language_non_issue:
|
|
4586
|
+
var FindingShapeSchema = z4.object({
|
|
4587
|
+
summary: z4.string().min(1).max(500),
|
|
4588
|
+
location: z4.string().min(1).max(200),
|
|
4589
|
+
severity: z4.enum(["critical", "high", "medium", "low"]).default("medium"),
|
|
4590
|
+
gate: z4.object({
|
|
4591
|
+
reread_cited_line: z4.enum(["passed", "failed", "skipped"]).default("skipped"),
|
|
4592
|
+
traced_call_path: z4.enum(["passed", "failed", "skipped"]).default("skipped"),
|
|
4593
|
+
named_assertion: z4.string().default(""),
|
|
4594
|
+
ruled_out_language_non_issue: z4.enum(["passed", "failed", "skipped"]).default("skipped")
|
|
4319
4595
|
}),
|
|
4320
|
-
claim:
|
|
4596
|
+
claim: z4.string().min(1).max(2e3)
|
|
4321
4597
|
});
|
|
4322
|
-
var VoteSchema =
|
|
4598
|
+
var VoteSchema = z4.object({
|
|
4323
4599
|
decision: VoteDecisionSchema,
|
|
4324
|
-
reasoning:
|
|
4325
|
-
confidence:
|
|
4326
|
-
conditions:
|
|
4600
|
+
reasoning: z4.string().min(1).describe("Explanation for the vote"),
|
|
4601
|
+
confidence: z4.number().min(0).max(1).describe("Confidence level 0-1"),
|
|
4602
|
+
conditions: z4.array(z4.string()).optional().describe("Conditions for approval"),
|
|
4327
4603
|
/** Structured rejection categories for reject→refine→re-vote loops (Issue #1213). */
|
|
4328
|
-
rejectionCategories:
|
|
4604
|
+
rejectionCategories: z4.array(RejectionCategorySchema).optional().describe("Rejection reason categories when decision is reject"),
|
|
4329
4605
|
/** Pre-verified PR-review findings (#2245 v4 follow-up). Optional;
|
|
4330
4606
|
* populated only when the voter emits the structured top-level array. */
|
|
4331
|
-
findings:
|
|
4332
|
-
timestamp:
|
|
4607
|
+
findings: z4.array(FindingShapeSchema).optional().describe("PR-review findings (pre-verified)"),
|
|
4608
|
+
timestamp: z4.iso.datetime().optional()
|
|
4333
4609
|
});
|
|
4334
|
-
var ProposalSchema =
|
|
4335
|
-
id:
|
|
4336
|
-
title:
|
|
4337
|
-
description:
|
|
4610
|
+
var ProposalSchema = z4.object({
|
|
4611
|
+
id: z4.string().optional().describe("Auto-generated if not provided"),
|
|
4612
|
+
title: z4.string().min(1).max(200).describe("Short proposal title"),
|
|
4613
|
+
description: z4.string().min(1).describe("Detailed proposal description"),
|
|
4338
4614
|
algorithm: ConsensusAlgorithmSchema,
|
|
4339
|
-
timeout:
|
|
4340
|
-
requiredVoters:
|
|
4341
|
-
metadata:
|
|
4342
|
-
createdAt:
|
|
4615
|
+
timeout: z4.number().int().positive().optional().describe("Timeout in milliseconds"),
|
|
4616
|
+
requiredVoters: z4.array(z4.string()).optional().describe("Agent IDs that must vote"),
|
|
4617
|
+
metadata: z4.record(z4.string(), z4.unknown()).optional().describe("Additional context"),
|
|
4618
|
+
createdAt: z4.iso.datetime().optional()
|
|
4343
4619
|
});
|
|
4344
|
-
var ConsensusResultSchema =
|
|
4345
|
-
proposalId:
|
|
4620
|
+
var ConsensusResultSchema = z4.object({
|
|
4621
|
+
proposalId: z4.string(),
|
|
4346
4622
|
proposal: ProposalSchema,
|
|
4347
4623
|
outcome: ProposalStatusSchema,
|
|
4348
|
-
votes:
|
|
4349
|
-
voteCounts:
|
|
4350
|
-
approve:
|
|
4351
|
-
reject:
|
|
4352
|
-
abstain:
|
|
4353
|
-
total:
|
|
4624
|
+
votes: z4.map(z4.string(), VoteSchema),
|
|
4625
|
+
voteCounts: z4.object({
|
|
4626
|
+
approve: z4.number().int().nonnegative(),
|
|
4627
|
+
reject: z4.number().int().nonnegative(),
|
|
4628
|
+
abstain: z4.number().int().nonnegative(),
|
|
4629
|
+
total: z4.number().int().nonnegative()
|
|
4354
4630
|
}),
|
|
4355
|
-
weightedCounts:
|
|
4356
|
-
approve:
|
|
4357
|
-
reject:
|
|
4358
|
-
abstain:
|
|
4359
|
-
totalWeight:
|
|
4631
|
+
weightedCounts: z4.object({
|
|
4632
|
+
approve: z4.number().nonnegative(),
|
|
4633
|
+
reject: z4.number().nonnegative(),
|
|
4634
|
+
abstain: z4.number().nonnegative(),
|
|
4635
|
+
totalWeight: z4.number().nonnegative()
|
|
4360
4636
|
}).optional(),
|
|
4361
|
-
approvalPercentage:
|
|
4362
|
-
quorumReached:
|
|
4363
|
-
startedAt:
|
|
4364
|
-
closedAt:
|
|
4365
|
-
durationMs:
|
|
4637
|
+
approvalPercentage: z4.number().min(0).max(100),
|
|
4638
|
+
quorumReached: z4.boolean(),
|
|
4639
|
+
startedAt: z4.iso.datetime(),
|
|
4640
|
+
closedAt: z4.iso.datetime(),
|
|
4641
|
+
durationMs: z4.number().int().nonnegative()
|
|
4366
4642
|
});
|
|
4367
|
-
var AgentPerformanceSchema =
|
|
4368
|
-
agentId:
|
|
4369
|
-
totalVotes:
|
|
4370
|
-
correctVotes:
|
|
4371
|
-
successRate:
|
|
4372
|
-
lastUpdated:
|
|
4643
|
+
var AgentPerformanceSchema = z4.object({
|
|
4644
|
+
agentId: z4.string(),
|
|
4645
|
+
totalVotes: z4.number().int().nonnegative(),
|
|
4646
|
+
correctVotes: z4.number().int().nonnegative(),
|
|
4647
|
+
successRate: z4.number().min(0).max(1),
|
|
4648
|
+
lastUpdated: z4.iso.datetime()
|
|
4373
4649
|
});
|
|
4374
4650
|
var DEFAULT_INCREMENTAL_QUORUM_CONFIG = {
|
|
4375
4651
|
enabled: false,
|
|
@@ -4378,19 +4654,19 @@ var DEFAULT_INCREMENTAL_QUORUM_CONFIG = {
|
|
|
4378
4654
|
confidenceThreshold: 0.6,
|
|
4379
4655
|
ambiguityBand: 0.15
|
|
4380
4656
|
};
|
|
4381
|
-
var ProposalCacheConfigSchema =
|
|
4382
|
-
enabled:
|
|
4383
|
-
ttlMs:
|
|
4657
|
+
var ProposalCacheConfigSchema = z4.object({
|
|
4658
|
+
enabled: z4.boolean().default(false),
|
|
4659
|
+
ttlMs: z4.number().int().positive().default(36e5),
|
|
4384
4660
|
// 1 hour
|
|
4385
|
-
maxEntries:
|
|
4661
|
+
maxEntries: z4.number().int().positive().default(500)
|
|
4386
4662
|
});
|
|
4387
|
-
var ConsensusEngineConfigSchema =
|
|
4388
|
-
defaultTimeout:
|
|
4663
|
+
var ConsensusEngineConfigSchema = z4.object({
|
|
4664
|
+
defaultTimeout: z4.number().int().positive().default(3e5),
|
|
4389
4665
|
// 5 minutes
|
|
4390
|
-
minVotersForQuorum:
|
|
4391
|
-
maxActiveProposals:
|
|
4392
|
-
enablePerformanceTracking:
|
|
4393
|
-
maxClosedProposals:
|
|
4666
|
+
minVotersForQuorum: z4.number().int().positive().default(2),
|
|
4667
|
+
maxActiveProposals: z4.number().int().positive().default(100),
|
|
4668
|
+
enablePerformanceTracking: z4.boolean().default(true),
|
|
4669
|
+
maxClosedProposals: z4.number().int().positive().default(1e3),
|
|
4394
4670
|
// Issue #549
|
|
4395
4671
|
proposalCache: ProposalCacheConfigSchema.optional()
|
|
4396
4672
|
// Issue #589
|
|
@@ -4415,50 +4691,50 @@ var VOTING_THRESHOLDS = {
|
|
|
4415
4691
|
higher_order: 0.5
|
|
4416
4692
|
// Alias for opinion_wise (Issue #514)
|
|
4417
4693
|
};
|
|
4418
|
-
var ConsensusMetricsSchema =
|
|
4419
|
-
totalProposals:
|
|
4420
|
-
approvedProposals:
|
|
4421
|
-
rejectedProposals:
|
|
4422
|
-
timedOutProposals:
|
|
4423
|
-
averageDurationMs:
|
|
4424
|
-
averageVotesPerProposal:
|
|
4425
|
-
algorithmUsage:
|
|
4694
|
+
var ConsensusMetricsSchema = z4.object({
|
|
4695
|
+
totalProposals: z4.number().int().nonnegative(),
|
|
4696
|
+
approvedProposals: z4.number().int().nonnegative(),
|
|
4697
|
+
rejectedProposals: z4.number().int().nonnegative(),
|
|
4698
|
+
timedOutProposals: z4.number().int().nonnegative(),
|
|
4699
|
+
averageDurationMs: z4.number().nonnegative(),
|
|
4700
|
+
averageVotesPerProposal: z4.number().nonnegative(),
|
|
4701
|
+
algorithmUsage: z4.record(ConsensusAlgorithmSchema, z4.number().int().nonnegative())
|
|
4426
4702
|
});
|
|
4427
4703
|
|
|
4428
4704
|
// src/consensus/types-voting-protocol.ts
|
|
4429
|
-
import { z as
|
|
4430
|
-
var VotingRoundPhaseSchema =
|
|
4431
|
-
var VotingRoundStatusSchema =
|
|
4705
|
+
import { z as z5 } from "zod";
|
|
4706
|
+
var VotingRoundPhaseSchema = z5.enum(["analysis", "deliberation", "consensus"]);
|
|
4707
|
+
var VotingRoundStatusSchema = z5.enum([
|
|
4432
4708
|
"pending",
|
|
4433
4709
|
"in_progress",
|
|
4434
4710
|
"awaiting_votes",
|
|
4435
4711
|
"completed",
|
|
4436
4712
|
"aborted"
|
|
4437
4713
|
]);
|
|
4438
|
-
var AgentFindingSchema =
|
|
4439
|
-
agentId:
|
|
4440
|
-
category:
|
|
4441
|
-
severity:
|
|
4442
|
-
description:
|
|
4443
|
-
location:
|
|
4444
|
-
suggestion:
|
|
4445
|
-
confidence:
|
|
4446
|
-
timestamp:
|
|
4714
|
+
var AgentFindingSchema = z5.object({
|
|
4715
|
+
agentId: z5.string(),
|
|
4716
|
+
category: z5.enum(["bug", "security", "performance", "style", "design", "documentation", "other"]),
|
|
4717
|
+
severity: z5.enum(["critical", "major", "minor", "suggestion"]),
|
|
4718
|
+
description: z5.string().min(1),
|
|
4719
|
+
location: z5.string().optional().describe("File path and line range if applicable"),
|
|
4720
|
+
suggestion: z5.string().optional().describe("Recommended fix"),
|
|
4721
|
+
confidence: z5.number().min(0).max(1),
|
|
4722
|
+
timestamp: z5.iso.datetime().optional()
|
|
4447
4723
|
});
|
|
4448
|
-
var FindingVoteSchema =
|
|
4449
|
-
agentId:
|
|
4450
|
-
findingId:
|
|
4451
|
-
agree:
|
|
4452
|
-
reasoning:
|
|
4453
|
-
amendedSeverity:
|
|
4724
|
+
var FindingVoteSchema = z5.object({
|
|
4725
|
+
agentId: z5.string(),
|
|
4726
|
+
findingId: z5.string(),
|
|
4727
|
+
agree: z5.boolean(),
|
|
4728
|
+
reasoning: z5.string().optional(),
|
|
4729
|
+
amendedSeverity: z5.enum(["critical", "major", "minor", "suggestion"]).optional()
|
|
4454
4730
|
});
|
|
4455
|
-
var VotingProtocolConfigSchema =
|
|
4456
|
-
committeeSize:
|
|
4457
|
-
maxRounds:
|
|
4458
|
-
roundTimeoutMs:
|
|
4459
|
-
agreementThreshold:
|
|
4460
|
-
enableAntiSycophancy:
|
|
4461
|
-
sycophancyThreshold:
|
|
4731
|
+
var VotingProtocolConfigSchema = z5.object({
|
|
4732
|
+
committeeSize: z5.number().int().min(2).max(7).default(3),
|
|
4733
|
+
maxRounds: z5.number().int().min(1).max(5).default(3),
|
|
4734
|
+
roundTimeoutMs: z5.number().int().positive().default(6e4),
|
|
4735
|
+
agreementThreshold: z5.number().min(0.5).max(1).default(0.67),
|
|
4736
|
+
enableAntiSycophancy: z5.boolean().default(true),
|
|
4737
|
+
sycophancyThreshold: z5.number().min(0).max(1).default(0.8)
|
|
4462
4738
|
});
|
|
4463
4739
|
var DEFAULT_VOTING_PROTOCOL_CONFIG = {
|
|
4464
4740
|
committeeSize: 3,
|
|
@@ -4470,30 +4746,30 @@ var DEFAULT_VOTING_PROTOCOL_CONFIG = {
|
|
|
4470
4746
|
};
|
|
4471
4747
|
|
|
4472
4748
|
// src/consensus/types-weighted-voting.ts
|
|
4473
|
-
import { z as
|
|
4474
|
-
var TaskOutcomeSchema2 =
|
|
4475
|
-
var WeightedAgentRecordSchema =
|
|
4476
|
-
agentId:
|
|
4477
|
-
totalTasks:
|
|
4478
|
-
successfulTasks:
|
|
4479
|
-
failedTasks:
|
|
4480
|
-
partialTasks:
|
|
4481
|
-
successRate:
|
|
4482
|
-
weight:
|
|
4483
|
-
trustScore:
|
|
4484
|
-
byzantineFlags:
|
|
4485
|
-
lastActive:
|
|
4486
|
-
createdAt:
|
|
4749
|
+
import { z as z6 } from "zod";
|
|
4750
|
+
var TaskOutcomeSchema2 = z6.enum(["success", "failure", "partial", "unknown"]);
|
|
4751
|
+
var WeightedAgentRecordSchema = z6.object({
|
|
4752
|
+
agentId: z6.string().min(1),
|
|
4753
|
+
totalTasks: z6.number().int().nonnegative(),
|
|
4754
|
+
successfulTasks: z6.number().int().nonnegative(),
|
|
4755
|
+
failedTasks: z6.number().int().nonnegative(),
|
|
4756
|
+
partialTasks: z6.number().int().nonnegative(),
|
|
4757
|
+
successRate: z6.number().min(0).max(1),
|
|
4758
|
+
weight: z6.number().min(0).max(1),
|
|
4759
|
+
trustScore: z6.number().min(0).max(1),
|
|
4760
|
+
byzantineFlags: z6.number().int().nonnegative(),
|
|
4761
|
+
lastActive: z6.date(),
|
|
4762
|
+
createdAt: z6.date()
|
|
4487
4763
|
});
|
|
4488
|
-
var WeightedVotingConfigSchema =
|
|
4489
|
-
minWeight:
|
|
4490
|
-
maxByzantineFraction:
|
|
4491
|
-
weightDecayFactor:
|
|
4492
|
-
weightRecoveryFactor:
|
|
4493
|
-
minTrustScore:
|
|
4494
|
-
byzantineFlagThreshold:
|
|
4495
|
-
initialWeight:
|
|
4496
|
-
quorumThreshold:
|
|
4764
|
+
var WeightedVotingConfigSchema = z6.object({
|
|
4765
|
+
minWeight: z6.number().min(0).max(1).default(0.1),
|
|
4766
|
+
maxByzantineFraction: z6.number().min(0).max(0.5).default(0.33),
|
|
4767
|
+
weightDecayFactor: z6.number().min(0.5).max(1).default(0.9),
|
|
4768
|
+
weightRecoveryFactor: z6.number().min(1).max(2).default(1.05),
|
|
4769
|
+
minTrustScore: z6.number().min(0).max(1).default(0.3),
|
|
4770
|
+
byzantineFlagThreshold: z6.number().int().positive().default(3),
|
|
4771
|
+
initialWeight: z6.number().min(0).max(1).default(0.5),
|
|
4772
|
+
quorumThreshold: z6.number().min(0.5).max(1).default(0.67)
|
|
4497
4773
|
});
|
|
4498
4774
|
var DEFAULT_WEIGHTED_VOTING_CONFIG = {
|
|
4499
4775
|
minWeight: 0.1,
|
|
@@ -4507,7 +4783,7 @@ var DEFAULT_WEIGHTED_VOTING_CONFIG = {
|
|
|
4507
4783
|
};
|
|
4508
4784
|
|
|
4509
4785
|
// src/consensus/higher-order-types.ts
|
|
4510
|
-
import { z as
|
|
4786
|
+
import { z as z7 } from "zod";
|
|
4511
4787
|
function createAgentPairKey(agentA, agentB) {
|
|
4512
4788
|
return agentA < agentB ? `${agentA}:${agentB}` : `${agentB}:${agentA}`;
|
|
4513
4789
|
}
|
|
@@ -4518,40 +4794,40 @@ function parseAgentPairKey(key) {
|
|
|
4518
4794
|
}
|
|
4519
4795
|
return [parts[0], parts[1]];
|
|
4520
4796
|
}
|
|
4521
|
-
var CorrelationCoefficientSchema =
|
|
4522
|
-
var IndependentSubsetSchema =
|
|
4523
|
-
id:
|
|
4524
|
-
agentIds:
|
|
4525
|
-
independenceScore:
|
|
4526
|
-
observationCount:
|
|
4797
|
+
var CorrelationCoefficientSchema = z7.number().min(-1).max(1);
|
|
4798
|
+
var IndependentSubsetSchema = z7.object({
|
|
4799
|
+
id: z7.string(),
|
|
4800
|
+
agentIds: z7.array(z7.string()),
|
|
4801
|
+
independenceScore: z7.number().min(0).max(1),
|
|
4802
|
+
observationCount: z7.number().int().nonnegative()
|
|
4527
4803
|
});
|
|
4528
|
-
var VotingObservationSchema =
|
|
4529
|
-
proposalId:
|
|
4530
|
-
agentId:
|
|
4531
|
-
decision:
|
|
4532
|
-
confidence:
|
|
4533
|
-
alignedWithOutcome:
|
|
4534
|
-
timestamp:
|
|
4804
|
+
var VotingObservationSchema = z7.object({
|
|
4805
|
+
proposalId: z7.string(),
|
|
4806
|
+
agentId: z7.string(),
|
|
4807
|
+
decision: z7.enum(["approve", "reject", "abstain"]),
|
|
4808
|
+
confidence: z7.number().min(0).max(1),
|
|
4809
|
+
alignedWithOutcome: z7.boolean(),
|
|
4810
|
+
timestamp: z7.date()
|
|
4535
4811
|
});
|
|
4536
|
-
var PairwiseVotingHistorySchema =
|
|
4537
|
-
pairKey:
|
|
4538
|
-
jointObservations:
|
|
4539
|
-
agreements:
|
|
4540
|
-
disagreements:
|
|
4812
|
+
var PairwiseVotingHistorySchema = z7.object({
|
|
4813
|
+
pairKey: z7.string(),
|
|
4814
|
+
jointObservations: z7.number().int().nonnegative(),
|
|
4815
|
+
agreements: z7.number().int().nonnegative(),
|
|
4816
|
+
disagreements: z7.number().int().nonnegative(),
|
|
4541
4817
|
correlation: CorrelationCoefficientSchema,
|
|
4542
|
-
lastUpdated:
|
|
4818
|
+
lastUpdated: z7.date()
|
|
4543
4819
|
});
|
|
4544
|
-
var HigherOrderVotingConfigSchema =
|
|
4545
|
-
minObservationsForCorrelation:
|
|
4546
|
-
correlationThreshold:
|
|
4547
|
-
correlationMaxAgeMs:
|
|
4820
|
+
var HigherOrderVotingConfigSchema = z7.object({
|
|
4821
|
+
minObservationsForCorrelation: z7.number().int().positive().default(10),
|
|
4822
|
+
correlationThreshold: z7.number().min(0).max(1).default(0.3),
|
|
4823
|
+
correlationMaxAgeMs: z7.number().int().positive().default(864e5),
|
|
4548
4824
|
// 24 hours
|
|
4549
|
-
independenceThreshold:
|
|
4550
|
-
fallbackToSimpleVoting:
|
|
4551
|
-
observationDecayFactor:
|
|
4552
|
-
maxObservationsPerAgent:
|
|
4553
|
-
maxProposals:
|
|
4554
|
-
maxTrackedPairs:
|
|
4825
|
+
independenceThreshold: z7.number().min(0).max(1).default(0.2),
|
|
4826
|
+
fallbackToSimpleVoting: z7.boolean().default(true),
|
|
4827
|
+
observationDecayFactor: z7.number().min(0).max(1).default(0.95),
|
|
4828
|
+
maxObservationsPerAgent: z7.number().int().positive().default(1e3),
|
|
4829
|
+
maxProposals: z7.number().int().positive().default(5e3),
|
|
4830
|
+
maxTrackedPairs: z7.number().int().positive().default(100)
|
|
4555
4831
|
});
|
|
4556
4832
|
var DEFAULT_HIGHER_ORDER_CONFIG = {
|
|
4557
4833
|
minObservationsForCorrelation: 10,
|
|
@@ -4565,25 +4841,25 @@ var DEFAULT_HIGHER_ORDER_CONFIG = {
|
|
|
4565
4841
|
maxProposals: 5e3,
|
|
4566
4842
|
maxTrackedPairs: 100
|
|
4567
4843
|
};
|
|
4568
|
-
var HigherOrderVotingResultSchema =
|
|
4569
|
-
decision:
|
|
4570
|
-
posteriorApproval:
|
|
4571
|
-
posteriorRejection:
|
|
4572
|
-
effectiveVoteCount:
|
|
4573
|
-
usedCorrelationData:
|
|
4574
|
-
method:
|
|
4575
|
-
improvementOverBaseline:
|
|
4576
|
-
independentSubsets:
|
|
4577
|
-
downweightedAgents:
|
|
4578
|
-
reasoning:
|
|
4844
|
+
var HigherOrderVotingResultSchema = z7.object({
|
|
4845
|
+
decision: z7.enum(["approve", "reject", "no_consensus"]),
|
|
4846
|
+
posteriorApproval: z7.number().min(0).max(1),
|
|
4847
|
+
posteriorRejection: z7.number().min(0).max(1),
|
|
4848
|
+
effectiveVoteCount: z7.number().nonnegative(),
|
|
4849
|
+
usedCorrelationData: z7.boolean(),
|
|
4850
|
+
method: z7.enum(["ow", "isp", "simple"]),
|
|
4851
|
+
improvementOverBaseline: z7.number(),
|
|
4852
|
+
independentSubsets: z7.array(IndependentSubsetSchema).optional(),
|
|
4853
|
+
downweightedAgents: z7.array(z7.string()),
|
|
4854
|
+
reasoning: z7.string()
|
|
4579
4855
|
});
|
|
4580
|
-
var CorrelationTrackerStatsSchema =
|
|
4581
|
-
totalAgents:
|
|
4582
|
-
trackedPairs:
|
|
4583
|
-
totalObservations:
|
|
4584
|
-
averageCorrelation:
|
|
4585
|
-
independentSubsetCount:
|
|
4586
|
-
pairsWithSufficientData:
|
|
4856
|
+
var CorrelationTrackerStatsSchema = z7.object({
|
|
4857
|
+
totalAgents: z7.number().int().nonnegative(),
|
|
4858
|
+
trackedPairs: z7.number().int().nonnegative(),
|
|
4859
|
+
totalObservations: z7.number().int().nonnegative(),
|
|
4860
|
+
averageCorrelation: z7.number(),
|
|
4861
|
+
independentSubsetCount: z7.number().int().nonnegative(),
|
|
4862
|
+
pairsWithSufficientData: z7.number().int().nonnegative()
|
|
4587
4863
|
});
|
|
4588
4864
|
|
|
4589
4865
|
// src/consensus/higher-order-helpers.ts
|
|
@@ -4758,13 +5034,13 @@ function buildReasoning(decision, effectiveVotes, downweightedAgents, method) {
|
|
|
4758
5034
|
}
|
|
4759
5035
|
|
|
4760
5036
|
// src/consensus/higher-order-voting.ts
|
|
4761
|
-
var
|
|
5037
|
+
var logger2 = createLogger({ component: "higher-order-voting" });
|
|
4762
5038
|
var OWVoting = class {
|
|
4763
5039
|
algorithm = "simple_majority";
|
|
4764
5040
|
config;
|
|
4765
5041
|
constructor(options = {}) {
|
|
4766
5042
|
this.config = { ...DEFAULT_HIGHER_ORDER_CONFIG, ...options.config };
|
|
4767
|
-
|
|
5043
|
+
logger2.info("OWVoting initialized", { config: this.config });
|
|
4768
5044
|
}
|
|
4769
5045
|
/** IVotingStrategy implementation for integration with ConsensusEngine. */
|
|
4770
5046
|
calculateOutcome(votes, _weights) {
|
|
@@ -4775,7 +5051,7 @@ var OWVoting = class {
|
|
|
4775
5051
|
const agentIds = Array.from(votes.keys());
|
|
4776
5052
|
const hasSufficientData = hasSufficientCorrelationData(agentIds, correlationMatrix);
|
|
4777
5053
|
if (!hasSufficientData && this.config.fallbackToSimpleVoting) {
|
|
4778
|
-
|
|
5054
|
+
logger2.info("Insufficient correlation data, falling back to simple voting", {
|
|
4779
5055
|
agentCount: agentIds.length,
|
|
4780
5056
|
reason: "insufficient_correlation_data"
|
|
4781
5057
|
});
|
|
@@ -4806,7 +5082,7 @@ var OWVoting = class {
|
|
|
4806
5082
|
downweightedAgents,
|
|
4807
5083
|
reasoning: buildReasoning(decision, effectiveVoteCount, downweightedAgents, "ow")
|
|
4808
5084
|
};
|
|
4809
|
-
|
|
5085
|
+
logger2.info("OW aggregation complete", {
|
|
4810
5086
|
decision,
|
|
4811
5087
|
posteriorApproval: posteriorApproval.toFixed(3),
|
|
4812
5088
|
effectiveVotes: effectiveVoteCount.toFixed(2),
|
|
@@ -4819,7 +5095,7 @@ var OWVoting = class {
|
|
|
4819
5095
|
}
|
|
4820
5096
|
computeISP(votes, independentSubsets) {
|
|
4821
5097
|
if (independentSubsets.length === 0) {
|
|
4822
|
-
|
|
5098
|
+
logger2.info("No independent subsets, falling back to simple voting", {
|
|
4823
5099
|
reason: "no_independent_subsets"
|
|
4824
5100
|
});
|
|
4825
5101
|
return this.aggregateSimpleInternal(votes);
|
|
@@ -4847,7 +5123,7 @@ var OWVoting = class {
|
|
|
4847
5123
|
downweightedAgents,
|
|
4848
5124
|
reasoning: buildReasoning(decision, effectiveVoteCount, downweightedAgents, "isp")
|
|
4849
5125
|
};
|
|
4850
|
-
|
|
5126
|
+
logger2.info("ISP aggregation complete", {
|
|
4851
5127
|
decision,
|
|
4852
5128
|
subsetCount: independentSubsets.length,
|
|
4853
5129
|
posteriorApproval: posteriorApproval.toFixed(3)
|
|
@@ -4858,7 +5134,7 @@ var OWVoting = class {
|
|
|
4858
5134
|
const agentIds = Array.from(votes.keys());
|
|
4859
5135
|
if (!tracker.hasSufficientData(agentIds)) {
|
|
4860
5136
|
if (this.config.fallbackToSimpleVoting) {
|
|
4861
|
-
|
|
5137
|
+
logger2.info("Insufficient data for correlation analysis, using simple voting", {
|
|
4862
5138
|
agentCount: agentIds.length,
|
|
4863
5139
|
reason: "insufficient_tracker_data"
|
|
4864
5140
|
});
|
|
@@ -4873,7 +5149,7 @@ var OWVoting = class {
|
|
|
4873
5149
|
const owConfidence = Math.abs(owResult.posteriorApproval - 0.5) * 2;
|
|
4874
5150
|
const ispConfidence = Math.abs(ispResult.posteriorApproval - 0.5) * 2;
|
|
4875
5151
|
if (ispConfidence > owConfidence) {
|
|
4876
|
-
|
|
5152
|
+
logger2.debug("Using ISP result over OW due to higher confidence");
|
|
4877
5153
|
return ispResult;
|
|
4878
5154
|
}
|
|
4879
5155
|
}
|
|
@@ -5232,11 +5508,11 @@ var ConsensusEngine = class {
|
|
|
5232
5508
|
logger;
|
|
5233
5509
|
metrics;
|
|
5234
5510
|
voterExpansionCallback;
|
|
5235
|
-
constructor(config,
|
|
5511
|
+
constructor(config, logger12) {
|
|
5236
5512
|
this.config = { ...DEFAULT_CONSENSUS_CONFIG, ...config };
|
|
5237
5513
|
this.cacheConfig = { ...DEFAULT_PROPOSAL_CACHE_CONFIG, ...config?.proposalCache };
|
|
5238
5514
|
this.quorumConfig = { ...DEFAULT_INCREMENTAL_QUORUM_CONFIG, ...config?.incrementalQuorum };
|
|
5239
|
-
this.logger =
|
|
5515
|
+
this.logger = logger12 ?? createLogger({ component: "ConsensusEngine" });
|
|
5240
5516
|
this.strategyFactory = new VotingStrategyFactory();
|
|
5241
5517
|
this.metrics = this.createInitialMetrics();
|
|
5242
5518
|
}
|
|
@@ -5669,8 +5945,8 @@ var ConsensusEngine = class {
|
|
|
5669
5945
|
this.logger.debug("Proposal cache cleared");
|
|
5670
5946
|
}
|
|
5671
5947
|
};
|
|
5672
|
-
function createConsensusEngine(config,
|
|
5673
|
-
return new ConsensusEngine(config,
|
|
5948
|
+
function createConsensusEngine(config, logger12) {
|
|
5949
|
+
return new ConsensusEngine(config, logger12);
|
|
5674
5950
|
}
|
|
5675
5951
|
|
|
5676
5952
|
// src/consensus/quorum-validator.ts
|
|
@@ -5678,8 +5954,8 @@ var DEFAULT_MIN_TRUST = 0.3;
|
|
|
5678
5954
|
var DEFAULT_MIN_WEIGHT = 0.1;
|
|
5679
5955
|
var QuorumValidator = class {
|
|
5680
5956
|
logger;
|
|
5681
|
-
constructor(
|
|
5682
|
-
this.logger =
|
|
5957
|
+
constructor(logger12) {
|
|
5958
|
+
this.logger = logger12 ?? createLogger({ component: "QuorumValidator" });
|
|
5683
5959
|
}
|
|
5684
5960
|
validateQuorum(input) {
|
|
5685
5961
|
const { votes, config } = input;
|
|
@@ -5906,8 +6182,8 @@ var QuorumValidator = class {
|
|
|
5906
6182
|
};
|
|
5907
6183
|
}
|
|
5908
6184
|
};
|
|
5909
|
-
function createQuorumValidator(
|
|
5910
|
-
return new QuorumValidator(
|
|
6185
|
+
function createQuorumValidator(logger12) {
|
|
6186
|
+
return new QuorumValidator(logger12);
|
|
5911
6187
|
}
|
|
5912
6188
|
|
|
5913
6189
|
// src/consensus/voting-protocol-helpers.ts
|
|
@@ -6156,12 +6432,12 @@ function detectSycophancyPatterns(session) {
|
|
|
6156
6432
|
}
|
|
6157
6433
|
|
|
6158
6434
|
// src/consensus/voting-protocol.ts
|
|
6159
|
-
var
|
|
6435
|
+
var logger3 = createLogger({ component: "voting-protocol" });
|
|
6160
6436
|
var VotingProtocol = class {
|
|
6161
6437
|
sessions = /* @__PURE__ */ new Map();
|
|
6162
6438
|
logger;
|
|
6163
6439
|
constructor(customLogger) {
|
|
6164
|
-
this.logger = customLogger ??
|
|
6440
|
+
this.logger = customLogger ?? logger3;
|
|
6165
6441
|
}
|
|
6166
6442
|
/**
|
|
6167
6443
|
* Create a new voting session with a committee.
|
|
@@ -6614,7 +6890,7 @@ function applyOutcomeWeight(currentWeight, outcome, decayFactor, recoveryFactor)
|
|
|
6614
6890
|
}
|
|
6615
6891
|
|
|
6616
6892
|
// src/consensus/weighted-voting.ts
|
|
6617
|
-
var
|
|
6893
|
+
var logger4 = createLogger({ component: "weighted-voting" });
|
|
6618
6894
|
var WeightedVoting = class {
|
|
6619
6895
|
records = /* @__PURE__ */ new Map();
|
|
6620
6896
|
config;
|
|
@@ -6624,7 +6900,7 @@ var WeightedVoting = class {
|
|
|
6624
6900
|
this.config = { ...DEFAULT_WEIGHTED_VOTING_CONFIG, ...options.config };
|
|
6625
6901
|
this.eventBus = options.eventBus ?? void 0;
|
|
6626
6902
|
this.emitEvents = options.emitEvents ?? options.eventBus !== void 0;
|
|
6627
|
-
|
|
6903
|
+
logger4.info("WeightedVoting initialized", {
|
|
6628
6904
|
config: this.config,
|
|
6629
6905
|
eventsEnabled: this.emitEvents
|
|
6630
6906
|
});
|
|
@@ -6655,7 +6931,7 @@ var WeightedVoting = class {
|
|
|
6655
6931
|
);
|
|
6656
6932
|
updateDerivedMetrics(record);
|
|
6657
6933
|
this.emitWeightChange(agentId, previousWeight, record.weight, "performance_update");
|
|
6658
|
-
|
|
6934
|
+
logger4.debug("Performance updated", {
|
|
6659
6935
|
agentId,
|
|
6660
6936
|
outcome,
|
|
6661
6937
|
newWeight: record.weight,
|
|
@@ -6688,12 +6964,12 @@ var WeightedVoting = class {
|
|
|
6688
6964
|
}
|
|
6689
6965
|
registerAgent(agentId) {
|
|
6690
6966
|
if (this.records.has(agentId)) {
|
|
6691
|
-
|
|
6967
|
+
logger4.debug("Agent already registered", { agentId });
|
|
6692
6968
|
return;
|
|
6693
6969
|
}
|
|
6694
6970
|
const record = createAgentRecord(agentId, this.config.initialWeight);
|
|
6695
6971
|
this.records.set(agentId, record);
|
|
6696
|
-
|
|
6972
|
+
logger4.info("Agent registered", { agentId, initialWeight: this.config.initialWeight });
|
|
6697
6973
|
}
|
|
6698
6974
|
getAgentRecord(agentId) {
|
|
6699
6975
|
const record = this.records.get(agentId);
|
|
@@ -6703,7 +6979,7 @@ var WeightedVoting = class {
|
|
|
6703
6979
|
flagByzantine(agentId, reason) {
|
|
6704
6980
|
const record = this.records.get(agentId);
|
|
6705
6981
|
if (record === void 0) {
|
|
6706
|
-
|
|
6982
|
+
logger4.warn("Cannot flag unregistered agent", { agentId });
|
|
6707
6983
|
return;
|
|
6708
6984
|
}
|
|
6709
6985
|
const previousWeight = record.weight;
|
|
@@ -6714,7 +6990,7 @@ var WeightedVoting = class {
|
|
|
6714
6990
|
const canStillVote = this.canVote(agentId);
|
|
6715
6991
|
this.emitAgentFlaggedEvent(agentId, reason, previousWeight, canStillVote);
|
|
6716
6992
|
this.emitWeightChange(agentId, previousWeight, record.weight, "flag_penalty");
|
|
6717
|
-
|
|
6993
|
+
logger4.warn("Agent flagged for Byzantine behavior", {
|
|
6718
6994
|
agentId,
|
|
6719
6995
|
reason,
|
|
6720
6996
|
totalFlags: record.byzantineFlags,
|
|
@@ -6746,7 +7022,7 @@ var WeightedVoting = class {
|
|
|
6746
7022
|
updateDerivedMetrics(record);
|
|
6747
7023
|
this.emitWeightChange(record.agentId, previousWeight, record.weight, "recalibration");
|
|
6748
7024
|
}
|
|
6749
|
-
|
|
7025
|
+
logger4.info("Weights recalibrated", {
|
|
6750
7026
|
agentCount: this.records.size,
|
|
6751
7027
|
globalSuccessRate: globalSuccessRate.toFixed(3)
|
|
6752
7028
|
});
|
|
@@ -6760,7 +7036,7 @@ var WeightedVoting = class {
|
|
|
6760
7036
|
const breakdown = /* @__PURE__ */ new Map();
|
|
6761
7037
|
for (const [agentId, vote] of votes) {
|
|
6762
7038
|
if (!this.canVote(agentId)) {
|
|
6763
|
-
|
|
7039
|
+
logger4.warn("Agent cannot vote", { agentId, reason: "insufficient weight or trust" });
|
|
6764
7040
|
continue;
|
|
6765
7041
|
}
|
|
6766
7042
|
const weight = this.calculateWeight(agentId);
|
|
@@ -6774,7 +7050,7 @@ var WeightedVoting = class {
|
|
|
6774
7050
|
return { approval, rejection, total, agents, breakdown };
|
|
6775
7051
|
}
|
|
6776
7052
|
logConsensusResult(result) {
|
|
6777
|
-
|
|
7053
|
+
logger4.info("Weighted consensus calculated", {
|
|
6778
7054
|
decision: result.decision,
|
|
6779
7055
|
approval: result.weightedApproval.toFixed(3),
|
|
6780
7056
|
rejection: result.weightedRejection.toFixed(3),
|
|
@@ -6798,7 +7074,7 @@ var WeightedVoting = class {
|
|
|
6798
7074
|
record.trustScore = 0;
|
|
6799
7075
|
record.weight = 0;
|
|
6800
7076
|
this.emitWeightChange(record.agentId, weightBefore, 0, "flag_penalty");
|
|
6801
|
-
|
|
7077
|
+
logger4.warn("Agent excluded from voting due to Byzantine behavior", {
|
|
6802
7078
|
agentId: record.agentId,
|
|
6803
7079
|
flags: record.byzantineFlags
|
|
6804
7080
|
});
|
|
@@ -6967,7 +7243,7 @@ function partitionIntoIndependentGroups(agents, correlationMatrix, pairwiseHisto
|
|
|
6967
7243
|
}
|
|
6968
7244
|
|
|
6969
7245
|
// src/consensus/correlation-tracker.ts
|
|
6970
|
-
var
|
|
7246
|
+
var logger5 = createLogger({ component: "correlation-tracker" });
|
|
6971
7247
|
var CorrelationTracker = class {
|
|
6972
7248
|
config;
|
|
6973
7249
|
observations = /* @__PURE__ */ new Map();
|
|
@@ -6978,7 +7254,7 @@ var CorrelationTracker = class {
|
|
|
6978
7254
|
cachedSubsets = null;
|
|
6979
7255
|
constructor(config) {
|
|
6980
7256
|
this.config = { ...DEFAULT_HIGHER_ORDER_CONFIG, ...config };
|
|
6981
|
-
|
|
7257
|
+
logger5.info("CorrelationTracker initialized", {
|
|
6982
7258
|
maxObservationsPerAgent: this.config.maxObservationsPerAgent,
|
|
6983
7259
|
maxProposals: this.config.maxProposals
|
|
6984
7260
|
});
|
|
@@ -7015,7 +7291,7 @@ var CorrelationTracker = class {
|
|
|
7015
7291
|
this.proposalOrder.push(proposalId);
|
|
7016
7292
|
this.updatePairwiseCorrelations(proposalId, proposalObservations);
|
|
7017
7293
|
this.invalidateCache();
|
|
7018
|
-
|
|
7294
|
+
logger5.debug("Recorded proposal votes", {
|
|
7019
7295
|
proposalId,
|
|
7020
7296
|
agentCount: votes.size,
|
|
7021
7297
|
outcome,
|
|
@@ -7053,7 +7329,7 @@ var CorrelationTracker = class {
|
|
|
7053
7329
|
this.config
|
|
7054
7330
|
);
|
|
7055
7331
|
this.cachedSubsets = subsets;
|
|
7056
|
-
|
|
7332
|
+
logger5.debug("Identified independent subsets", {
|
|
7057
7333
|
agentCount: agents.length,
|
|
7058
7334
|
subsetCount: subsets.length
|
|
7059
7335
|
});
|
|
@@ -7109,7 +7385,7 @@ var CorrelationTracker = class {
|
|
|
7109
7385
|
this.agentProposals.clear();
|
|
7110
7386
|
this.proposalOrder.length = 0;
|
|
7111
7387
|
this.cachedSubsets = null;
|
|
7112
|
-
|
|
7388
|
+
logger5.info("CorrelationTracker cleared");
|
|
7113
7389
|
}
|
|
7114
7390
|
// ============================================================================
|
|
7115
7391
|
// Private helpers
|
|
@@ -7130,7 +7406,7 @@ var CorrelationTracker = class {
|
|
|
7130
7406
|
}
|
|
7131
7407
|
}
|
|
7132
7408
|
}
|
|
7133
|
-
|
|
7409
|
+
logger5.debug("Evicted oldest proposal", {
|
|
7134
7410
|
evictedProposalId,
|
|
7135
7411
|
reason: "maxProposals",
|
|
7136
7412
|
remainingProposals: this.proposalOrder.length
|
|
@@ -7154,7 +7430,7 @@ var CorrelationTracker = class {
|
|
|
7154
7430
|
}
|
|
7155
7431
|
if (oldestKey !== void 0) {
|
|
7156
7432
|
this.pairwiseHistory.delete(oldestKey);
|
|
7157
|
-
|
|
7433
|
+
logger5.debug("Evicted oldest pairwise history entry", {
|
|
7158
7434
|
evictedKey: oldestKey,
|
|
7159
7435
|
reason: "maxTrackedPairs",
|
|
7160
7436
|
remainingPairs: this.pairwiseHistory.size
|
|
@@ -7170,7 +7446,7 @@ var CorrelationTracker = class {
|
|
|
7170
7446
|
while (agentObs.length >= this.config.maxObservationsPerAgent) {
|
|
7171
7447
|
const evicted = agentObs.shift();
|
|
7172
7448
|
if (evicted !== void 0) {
|
|
7173
|
-
|
|
7449
|
+
logger5.debug("Evicted oldest observation for agent", {
|
|
7174
7450
|
agentId,
|
|
7175
7451
|
evictedProposalId: evicted.proposalId,
|
|
7176
7452
|
reason: "maxObservationsPerAgent"
|
|
@@ -7233,28 +7509,28 @@ function createCorrelationTracker(config) {
|
|
|
7233
7509
|
|
|
7234
7510
|
// src/consensus/correlation-persistence.ts
|
|
7235
7511
|
import * as fs from "fs";
|
|
7236
|
-
import { z as
|
|
7237
|
-
var
|
|
7512
|
+
import { z as z8 } from "zod";
|
|
7513
|
+
var logger6 = createLogger({ component: "correlation-persistence" });
|
|
7238
7514
|
var VOTING_SUBDIR = "voting";
|
|
7239
7515
|
var CORRELATIONS_FILE = "correlations.json";
|
|
7240
7516
|
var FILE_MODE = 384;
|
|
7241
7517
|
var DIR_MODE = 448;
|
|
7242
7518
|
var SCHEMA_VERSION = 1;
|
|
7243
|
-
var PersistedVoteSchema =
|
|
7244
|
-
agentId:
|
|
7245
|
-
decision:
|
|
7246
|
-
confidence:
|
|
7519
|
+
var PersistedVoteSchema = z8.object({
|
|
7520
|
+
agentId: z8.string(),
|
|
7521
|
+
decision: z8.enum(["approve", "reject", "abstain"]),
|
|
7522
|
+
confidence: z8.number().min(0).max(1)
|
|
7247
7523
|
});
|
|
7248
|
-
var PersistedProposalSchema =
|
|
7249
|
-
proposalId:
|
|
7250
|
-
votes:
|
|
7251
|
-
outcome:
|
|
7252
|
-
timestamp:
|
|
7524
|
+
var PersistedProposalSchema = z8.object({
|
|
7525
|
+
proposalId: z8.string(),
|
|
7526
|
+
votes: z8.array(PersistedVoteSchema),
|
|
7527
|
+
outcome: z8.enum(["approved", "rejected"]),
|
|
7528
|
+
timestamp: z8.iso.datetime()
|
|
7253
7529
|
});
|
|
7254
|
-
var PersistedCorrelationDataSchema =
|
|
7255
|
-
version:
|
|
7256
|
-
proposals:
|
|
7257
|
-
savedAt:
|
|
7530
|
+
var PersistedCorrelationDataSchema = z8.object({
|
|
7531
|
+
version: z8.number().int().positive(),
|
|
7532
|
+
proposals: z8.array(PersistedProposalSchema),
|
|
7533
|
+
savedAt: z8.iso.datetime()
|
|
7258
7534
|
});
|
|
7259
7535
|
function getCorrelationDataPath() {
|
|
7260
7536
|
return nexusDataPath(VOTING_SUBDIR, CORRELATIONS_FILE);
|
|
@@ -7304,7 +7580,7 @@ function saveCorrelationData(proposals, config = DEFAULT_HIGHER_ORDER_CONFIG) {
|
|
|
7304
7580
|
try {
|
|
7305
7581
|
fs.writeFileSync(tempPath, json, { encoding: "utf-8", mode: FILE_MODE });
|
|
7306
7582
|
fs.renameSync(tempPath, filePath);
|
|
7307
|
-
|
|
7583
|
+
logger6.info("Correlation data saved", {
|
|
7308
7584
|
path: filePath,
|
|
7309
7585
|
proposalCount: merged.length
|
|
7310
7586
|
});
|
|
@@ -7314,7 +7590,7 @@ function saveCorrelationData(proposals, config = DEFAULT_HIGHER_ORDER_CONFIG) {
|
|
|
7314
7590
|
fs.unlinkSync(tempPath);
|
|
7315
7591
|
} catch (cleanupErr) {
|
|
7316
7592
|
const msg = cleanupErr instanceof Error ? cleanupErr.message : String(cleanupErr);
|
|
7317
|
-
|
|
7593
|
+
logger6.debug("Failed to clean up temp file during correlation save", {
|
|
7318
7594
|
path: tempPath,
|
|
7319
7595
|
error: msg
|
|
7320
7596
|
});
|
|
@@ -7338,7 +7614,7 @@ function readAndParseFile(filePath) {
|
|
|
7338
7614
|
return ok(JSON.parse(rawContent));
|
|
7339
7615
|
} catch (cause) {
|
|
7340
7616
|
const error = cause instanceof Error ? cause : new Error(String(cause));
|
|
7341
|
-
|
|
7617
|
+
logger6.warn("Corrupt correlation data file, will start fresh", {
|
|
7342
7618
|
path: filePath,
|
|
7343
7619
|
error: error.message
|
|
7344
7620
|
});
|
|
@@ -7348,14 +7624,14 @@ function readAndParseFile(filePath) {
|
|
|
7348
7624
|
function validateCorrelationData(parsed, filePath) {
|
|
7349
7625
|
const validation = PersistedCorrelationDataSchema.safeParse(parsed);
|
|
7350
7626
|
if (!validation.success) {
|
|
7351
|
-
|
|
7627
|
+
logger6.warn("Invalid correlation data schema, will start fresh", {
|
|
7352
7628
|
path: filePath,
|
|
7353
7629
|
errors: validation.error.issues.map((issue) => issue.message)
|
|
7354
7630
|
});
|
|
7355
7631
|
return err(new Error(`Invalid correlation data schema: ${validation.error.message}`));
|
|
7356
7632
|
}
|
|
7357
7633
|
if (validation.data.version > SCHEMA_VERSION) {
|
|
7358
|
-
|
|
7634
|
+
logger6.warn("Correlation data from newer version, will start fresh", {
|
|
7359
7635
|
fileVersion: validation.data.version,
|
|
7360
7636
|
currentVersion: SCHEMA_VERSION
|
|
7361
7637
|
});
|
|
@@ -7373,7 +7649,7 @@ function loadCorrelationData() {
|
|
|
7373
7649
|
if (!parseResult.ok) return parseResult;
|
|
7374
7650
|
const validateResult = validateCorrelationData(parseResult.value, filePath);
|
|
7375
7651
|
if (!validateResult.ok) return validateResult;
|
|
7376
|
-
|
|
7652
|
+
logger6.info("Correlation data loaded", {
|
|
7377
7653
|
path: filePath,
|
|
7378
7654
|
proposalCount: validateResult.value.proposals.length,
|
|
7379
7655
|
savedAt: validateResult.value.savedAt
|
|
@@ -7400,13 +7676,13 @@ function createPersistentCorrelationTracker(config) {
|
|
|
7400
7676
|
const tracker = createCorrelationTracker(config);
|
|
7401
7677
|
const loadResult = loadCorrelationData();
|
|
7402
7678
|
if (!loadResult.ok) {
|
|
7403
|
-
|
|
7679
|
+
logger6.info("Starting with fresh correlation tracker", {
|
|
7404
7680
|
reason: loadResult.error.message
|
|
7405
7681
|
});
|
|
7406
7682
|
return tracker;
|
|
7407
7683
|
}
|
|
7408
7684
|
const replayedCount = replayProposals(tracker, loadResult.value.proposals);
|
|
7409
|
-
|
|
7685
|
+
logger6.info("Correlation tracker restored from persistence", {
|
|
7410
7686
|
replayedProposals: replayedCount,
|
|
7411
7687
|
stats: tracker.getStats()
|
|
7412
7688
|
});
|
|
@@ -7430,9 +7706,9 @@ function createPersistedProposal(proposalId, votes, outcome) {
|
|
|
7430
7706
|
}
|
|
7431
7707
|
|
|
7432
7708
|
// src/mcp/tools/consensus-vote-types.ts
|
|
7433
|
-
import { z as
|
|
7709
|
+
import { z as z9 } from "zod";
|
|
7434
7710
|
var MAX_PROPOSAL_LENGTH = 4e3;
|
|
7435
|
-
var VotingStrategySchema =
|
|
7711
|
+
var VotingStrategySchema = z9.enum([
|
|
7436
7712
|
"simple_majority",
|
|
7437
7713
|
"supermajority",
|
|
7438
7714
|
"unanimous",
|
|
@@ -7440,16 +7716,26 @@ var VotingStrategySchema = z8.enum([
|
|
|
7440
7716
|
"higher_order",
|
|
7441
7717
|
"opinion_wise"
|
|
7442
7718
|
]);
|
|
7443
|
-
var
|
|
7444
|
-
|
|
7445
|
-
|
|
7719
|
+
var ErrorPolicySchema = z9.enum(["reduce_denominator", "count_as_abstain", "fail_closed"]);
|
|
7720
|
+
var VoteThresholdSchema = z9.enum(["majority", "supermajority", "unanimous"]);
|
|
7721
|
+
var ERROR_FLOOR_FRACTION = 0.5;
|
|
7722
|
+
function getDefaultErrorPolicy(strategy) {
|
|
7723
|
+
if (strategy === "unanimous" || strategy === "higher_order") return "fail_closed";
|
|
7724
|
+
return "reduce_denominator";
|
|
7725
|
+
}
|
|
7726
|
+
var ConsensusVoteInputSchema = z9.object({
|
|
7727
|
+
proposal: z9.string().min(1).max(MAX_PROPOSAL_LENGTH).describe("Proposal text to vote on"),
|
|
7728
|
+
threshold: VoteThresholdSchema.optional().describe(
|
|
7446
7729
|
"Voting threshold (legacy): majority, supermajority, unanimous. Use strategy instead."
|
|
7447
7730
|
),
|
|
7448
7731
|
strategy: VotingStrategySchema.optional().describe(
|
|
7449
7732
|
"Voting strategy: simple_majority (default), supermajority, unanimous, proof_of_learning, or higher_order (Bayesian-optimal)"
|
|
7450
7733
|
),
|
|
7451
|
-
|
|
7452
|
-
|
|
7734
|
+
errorPolicy: ErrorPolicySchema.optional().describe(
|
|
7735
|
+
"How to treat voters that errored or timed out (#2630). Default: fail_closed for unanimous/higher_order, reduce_denominator otherwise. Regardless of policy, errors > 50% always fails."
|
|
7736
|
+
),
|
|
7737
|
+
quickMode: z9.boolean().optional().default(false).describe("Use 3 agents instead of 5 for faster execution"),
|
|
7738
|
+
simulateVotes: z9.boolean().optional().default(false).describe(
|
|
7453
7739
|
"TESTS ONLY \u2014 when true, voters return random decisions. Output must not be used for real decisions. (#2319)"
|
|
7454
7740
|
)
|
|
7455
7741
|
});
|
|
@@ -7515,12 +7801,49 @@ function buildResponse(input, result) {
|
|
|
7515
7801
|
return response;
|
|
7516
7802
|
}
|
|
7517
7803
|
|
|
7804
|
+
// src/mcp/tools/consensus-vote-error-policy.ts
|
|
7805
|
+
function isHardFloorTripped(errorCount, totalCount) {
|
|
7806
|
+
if (totalCount === 0) return false;
|
|
7807
|
+
return errorCount / totalCount > ERROR_FLOOR_FRACTION;
|
|
7808
|
+
}
|
|
7809
|
+
function applyErrorPolicy(votes, policy) {
|
|
7810
|
+
const errorVotes = votes.filter((v) => v.source === "error");
|
|
7811
|
+
const errorCount = errorVotes.length;
|
|
7812
|
+
const totalCount = votes.length;
|
|
7813
|
+
if (isHardFloorTripped(errorCount, totalCount)) {
|
|
7814
|
+
return {
|
|
7815
|
+
shortCircuit: true,
|
|
7816
|
+
reason: `Errors exceeded ${String(Math.round(ERROR_FLOOR_FRACTION * 100))}% of voters (${String(errorCount)}/${String(totalCount)})`,
|
|
7817
|
+
engineVotes: []
|
|
7818
|
+
};
|
|
7819
|
+
}
|
|
7820
|
+
if (policy === "fail_closed" && errorCount > 0) {
|
|
7821
|
+
return {
|
|
7822
|
+
shortCircuit: true,
|
|
7823
|
+
reason: `fail_closed: ${String(errorCount)} voter(s) errored`,
|
|
7824
|
+
engineVotes: []
|
|
7825
|
+
};
|
|
7826
|
+
}
|
|
7827
|
+
if (policy === "count_as_abstain") {
|
|
7828
|
+
return {
|
|
7829
|
+
shortCircuit: false,
|
|
7830
|
+
engineVotes: votes.map(
|
|
7831
|
+
(v) => v.source === "error" ? { ...v, vote: { ...v.vote, decision: "abstain" } } : v
|
|
7832
|
+
)
|
|
7833
|
+
};
|
|
7834
|
+
}
|
|
7835
|
+
return {
|
|
7836
|
+
shortCircuit: false,
|
|
7837
|
+
engineVotes: votes.filter((v) => v.source !== "error")
|
|
7838
|
+
};
|
|
7839
|
+
}
|
|
7840
|
+
|
|
7518
7841
|
// src/mcp/tools/tool-memory.ts
|
|
7519
7842
|
import * as fs3 from "fs";
|
|
7520
7843
|
import * as path2 from "path";
|
|
7521
7844
|
|
|
7522
7845
|
// src/context/belief-core-types.ts
|
|
7523
|
-
import { z as
|
|
7846
|
+
import { z as z10 } from "zod";
|
|
7524
7847
|
var BeliefConfidence = {
|
|
7525
7848
|
/** Strong evidence, short reasoning chain */
|
|
7526
7849
|
HIGH: "high",
|
|
@@ -7531,7 +7854,7 @@ var BeliefConfidence = {
|
|
|
7531
7854
|
/** Speculative or hypothetical */
|
|
7532
7855
|
SPECULATIVE: "speculative"
|
|
7533
7856
|
};
|
|
7534
|
-
var BeliefConfidenceSchema =
|
|
7857
|
+
var BeliefConfidenceSchema = z10.enum(["high", "medium", "low", "speculative"]);
|
|
7535
7858
|
var BeliefSourceType = {
|
|
7536
7859
|
/** Direct observation from environment */
|
|
7537
7860
|
OBSERVATION: "observation",
|
|
@@ -7546,7 +7869,7 @@ var BeliefSourceType = {
|
|
|
7546
7869
|
/** Default or prior belief */
|
|
7547
7870
|
PRIOR: "prior"
|
|
7548
7871
|
};
|
|
7549
|
-
var BeliefSourceTypeSchema =
|
|
7872
|
+
var BeliefSourceTypeSchema = z10.enum([
|
|
7550
7873
|
"observation",
|
|
7551
7874
|
"inference",
|
|
7552
7875
|
"external",
|
|
@@ -7554,26 +7877,26 @@ var BeliefSourceTypeSchema = z9.enum([
|
|
|
7554
7877
|
"hindsight",
|
|
7555
7878
|
"prior"
|
|
7556
7879
|
]);
|
|
7557
|
-
var BeliefSchema =
|
|
7558
|
-
beliefId:
|
|
7559
|
-
subject:
|
|
7560
|
-
predicate:
|
|
7561
|
-
object:
|
|
7880
|
+
var BeliefSchema = z10.object({
|
|
7881
|
+
beliefId: z10.string().min(1),
|
|
7882
|
+
subject: z10.string().min(1),
|
|
7883
|
+
predicate: z10.string().min(1),
|
|
7884
|
+
object: z10.string(),
|
|
7562
7885
|
confidence: BeliefConfidenceSchema,
|
|
7563
7886
|
sourceType: BeliefSourceTypeSchema,
|
|
7564
|
-
sourceRef:
|
|
7565
|
-
derivedFrom:
|
|
7566
|
-
version:
|
|
7567
|
-
createdAt:
|
|
7568
|
-
updatedAt:
|
|
7569
|
-
superseded:
|
|
7570
|
-
supersededBy:
|
|
7571
|
-
domain:
|
|
7572
|
-
metadata:
|
|
7887
|
+
sourceRef: z10.string().optional(),
|
|
7888
|
+
derivedFrom: z10.array(z10.string()).optional(),
|
|
7889
|
+
version: z10.number().int().min(1),
|
|
7890
|
+
createdAt: z10.date(),
|
|
7891
|
+
updatedAt: z10.date(),
|
|
7892
|
+
superseded: z10.boolean(),
|
|
7893
|
+
supersededBy: z10.string().optional(),
|
|
7894
|
+
domain: z10.string().optional(),
|
|
7895
|
+
metadata: z10.record(z10.string(), z10.unknown()).optional()
|
|
7573
7896
|
});
|
|
7574
7897
|
|
|
7575
7898
|
// src/context/belief-update-types.ts
|
|
7576
|
-
import { z as
|
|
7899
|
+
import { z as z11 } from "zod";
|
|
7577
7900
|
var BeliefUpdateType = {
|
|
7578
7901
|
/** Add a new belief (retain) */
|
|
7579
7902
|
RETAIN: "retain",
|
|
@@ -7588,7 +7911,7 @@ var BeliefUpdateType = {
|
|
|
7588
7911
|
/** Weaken belief based on contradicting evidence */
|
|
7589
7912
|
WEAKEN: "weaken"
|
|
7590
7913
|
};
|
|
7591
|
-
var BeliefUpdateTypeSchema =
|
|
7914
|
+
var BeliefUpdateTypeSchema = z11.enum([
|
|
7592
7915
|
"retain",
|
|
7593
7916
|
"revise",
|
|
7594
7917
|
"supersede",
|
|
@@ -7596,75 +7919,75 @@ var BeliefUpdateTypeSchema = z10.enum([
|
|
|
7596
7919
|
"reinforce",
|
|
7597
7920
|
"weaken"
|
|
7598
7921
|
]);
|
|
7599
|
-
var BeliefUpdateSchema =
|
|
7600
|
-
updateId:
|
|
7601
|
-
beliefId:
|
|
7922
|
+
var BeliefUpdateSchema = z11.object({
|
|
7923
|
+
updateId: z11.string().min(1),
|
|
7924
|
+
beliefId: z11.string().min(1),
|
|
7602
7925
|
updateType: BeliefUpdateTypeSchema,
|
|
7603
|
-
previousState:
|
|
7604
|
-
newState:
|
|
7605
|
-
reason:
|
|
7606
|
-
evidence:
|
|
7607
|
-
timestamp:
|
|
7608
|
-
updatedBy:
|
|
7926
|
+
previousState: z11.record(z11.string(), z11.unknown()).optional(),
|
|
7927
|
+
newState: z11.record(z11.string(), z11.unknown()),
|
|
7928
|
+
reason: z11.string().min(1),
|
|
7929
|
+
evidence: z11.string().optional(),
|
|
7930
|
+
timestamp: z11.date(),
|
|
7931
|
+
updatedBy: z11.string().optional()
|
|
7609
7932
|
});
|
|
7610
|
-
var BeliefQuerySchema =
|
|
7611
|
-
subject:
|
|
7612
|
-
predicate:
|
|
7613
|
-
domain:
|
|
7933
|
+
var BeliefQuerySchema = z11.object({
|
|
7934
|
+
subject: z11.string().optional(),
|
|
7935
|
+
predicate: z11.string().optional(),
|
|
7936
|
+
domain: z11.string().optional(),
|
|
7614
7937
|
minConfidence: BeliefConfidenceSchema.optional(),
|
|
7615
|
-
includeSuperseded:
|
|
7938
|
+
includeSuperseded: z11.boolean().optional(),
|
|
7616
7939
|
sourceType: BeliefSourceTypeSchema.optional(),
|
|
7617
|
-
limit:
|
|
7618
|
-
orderBy:
|
|
7619
|
-
orderDirection:
|
|
7940
|
+
limit: z11.number().int().positive().max(1e3).optional(),
|
|
7941
|
+
orderBy: z11.enum(["createdAt", "updatedAt", "confidence"]).optional(),
|
|
7942
|
+
orderDirection: z11.enum(["asc", "desc"]).optional()
|
|
7620
7943
|
});
|
|
7621
7944
|
|
|
7622
7945
|
// src/context/belief-hindsight-types.ts
|
|
7623
|
-
import { z as
|
|
7624
|
-
var CounterfactualSchema =
|
|
7625
|
-
counterfactualId:
|
|
7626
|
-
hypothesis:
|
|
7627
|
-
affectedBeliefs:
|
|
7628
|
-
predictedOutcomes:
|
|
7629
|
-
actualOutcomes:
|
|
7630
|
-
validated:
|
|
7631
|
-
createdAt:
|
|
7632
|
-
taskContext:
|
|
7946
|
+
import { z as z12 } from "zod";
|
|
7947
|
+
var CounterfactualSchema = z12.object({
|
|
7948
|
+
counterfactualId: z12.string().min(1),
|
|
7949
|
+
hypothesis: z12.string().min(1),
|
|
7950
|
+
affectedBeliefs: z12.array(z12.string()),
|
|
7951
|
+
predictedOutcomes: z12.array(z12.string()),
|
|
7952
|
+
actualOutcomes: z12.array(z12.string()).optional(),
|
|
7953
|
+
validated: z12.boolean(),
|
|
7954
|
+
createdAt: z12.date(),
|
|
7955
|
+
taskContext: z12.string().optional()
|
|
7633
7956
|
});
|
|
7634
|
-
var HindsightRecordSchema =
|
|
7635
|
-
hindsightId:
|
|
7636
|
-
taskId:
|
|
7637
|
-
priorBeliefs:
|
|
7638
|
-
expectedOutcome:
|
|
7639
|
-
actualOutcome:
|
|
7640
|
-
outcomeMatched:
|
|
7641
|
-
correctedBeliefs:
|
|
7642
|
-
newBeliefs:
|
|
7643
|
-
lessons:
|
|
7644
|
-
createdAt:
|
|
7957
|
+
var HindsightRecordSchema = z12.object({
|
|
7958
|
+
hindsightId: z12.string().min(1),
|
|
7959
|
+
taskId: z12.string().min(1),
|
|
7960
|
+
priorBeliefs: z12.array(z12.string()),
|
|
7961
|
+
expectedOutcome: z12.string(),
|
|
7962
|
+
actualOutcome: z12.string(),
|
|
7963
|
+
outcomeMatched: z12.boolean(),
|
|
7964
|
+
correctedBeliefs: z12.array(z12.string()),
|
|
7965
|
+
newBeliefs: z12.array(z12.string()),
|
|
7966
|
+
lessons: z12.array(z12.string()),
|
|
7967
|
+
createdAt: z12.date()
|
|
7645
7968
|
});
|
|
7646
7969
|
|
|
7647
7970
|
// src/context/belief-memory-interface.ts
|
|
7648
|
-
import { z as
|
|
7649
|
-
var BeliefMemoryStatsSchema =
|
|
7650
|
-
totalBeliefs:
|
|
7651
|
-
activeBeliefs:
|
|
7652
|
-
supersededBeliefs:
|
|
7653
|
-
beliefsByConfidence:
|
|
7654
|
-
beliefsBySource:
|
|
7655
|
-
totalUpdates:
|
|
7656
|
-
totalCounterfactuals:
|
|
7657
|
-
totalHindsightRecords:
|
|
7658
|
-
oldestBelief:
|
|
7659
|
-
newestBelief:
|
|
7971
|
+
import { z as z13 } from "zod";
|
|
7972
|
+
var BeliefMemoryStatsSchema = z13.object({
|
|
7973
|
+
totalBeliefs: z13.number().int().min(0),
|
|
7974
|
+
activeBeliefs: z13.number().int().min(0),
|
|
7975
|
+
supersededBeliefs: z13.number().int().min(0),
|
|
7976
|
+
beliefsByConfidence: z13.record(BeliefConfidenceSchema, z13.number().int().min(0)),
|
|
7977
|
+
beliefsBySource: z13.record(BeliefSourceTypeSchema, z13.number().int().min(0)),
|
|
7978
|
+
totalUpdates: z13.number().int().min(0),
|
|
7979
|
+
totalCounterfactuals: z13.number().int().min(0),
|
|
7980
|
+
totalHindsightRecords: z13.number().int().min(0),
|
|
7981
|
+
oldestBelief: z13.date().optional(),
|
|
7982
|
+
newestBelief: z13.date().optional()
|
|
7660
7983
|
});
|
|
7661
|
-
var BeliefMemoryConfigSchema =
|
|
7662
|
-
maxBeliefsPerSubject:
|
|
7663
|
-
maxTotalBeliefs:
|
|
7664
|
-
autoPruneAge:
|
|
7665
|
-
enableInference:
|
|
7984
|
+
var BeliefMemoryConfigSchema = z13.object({
|
|
7985
|
+
maxBeliefsPerSubject: z13.number().int().positive().optional(),
|
|
7986
|
+
maxTotalBeliefs: z13.number().int().positive().optional(),
|
|
7987
|
+
autoPruneAge: z13.number().positive().optional(),
|
|
7988
|
+
enableInference: z13.boolean().optional(),
|
|
7666
7989
|
defaultConfidence: BeliefConfidenceSchema.optional(),
|
|
7667
|
-
maxInferenceDepth:
|
|
7990
|
+
maxInferenceDepth: z13.number().int().positive().max(10).optional()
|
|
7668
7991
|
});
|
|
7669
7992
|
var DEFAULT_BELIEF_CONFIG = {
|
|
7670
7993
|
maxBeliefsPerSubject: 100,
|
|
@@ -8184,13 +8507,13 @@ var HindsightBeliefMemory = class {
|
|
|
8184
8507
|
domainIndex = /* @__PURE__ */ new Map();
|
|
8185
8508
|
config;
|
|
8186
8509
|
logger;
|
|
8187
|
-
constructor(config,
|
|
8510
|
+
constructor(config, logger12) {
|
|
8188
8511
|
const validation = BeliefMemoryConfigSchema.safeParse(config ?? {});
|
|
8189
8512
|
if (!validation.success) {
|
|
8190
8513
|
throw new MemoryError(`Invalid BeliefMemoryConfig: ${formatZodError(validation.error)}`);
|
|
8191
8514
|
}
|
|
8192
8515
|
this.config = { ...DEFAULT_BELIEF_CONFIG, ...config };
|
|
8193
|
-
this.logger =
|
|
8516
|
+
this.logger = logger12 ?? createLogger({ component: "HindsightBeliefMemory" });
|
|
8194
8517
|
this.logger.info("HindsightBeliefMemory initialized", { config: this.config });
|
|
8195
8518
|
}
|
|
8196
8519
|
get auditStores() {
|
|
@@ -8561,7 +8884,7 @@ var HindsightBeliefMemory = class {
|
|
|
8561
8884
|
};
|
|
8562
8885
|
|
|
8563
8886
|
// src/context/graph-memory-types.ts
|
|
8564
|
-
import { z as
|
|
8887
|
+
import { z as z14 } from "zod";
|
|
8565
8888
|
var RelationType = {
|
|
8566
8889
|
/** General association between memories */
|
|
8567
8890
|
RELATED_TO: "related_to",
|
|
@@ -8580,7 +8903,7 @@ var RelationType = {
|
|
|
8580
8903
|
/** Causal relationship */
|
|
8581
8904
|
CAUSES: "causes"
|
|
8582
8905
|
};
|
|
8583
|
-
var RelationTypeSchema =
|
|
8906
|
+
var RelationTypeSchema = z14.enum([
|
|
8584
8907
|
"related_to",
|
|
8585
8908
|
"derived_from",
|
|
8586
8909
|
"contradicts",
|
|
@@ -8590,28 +8913,28 @@ var RelationTypeSchema = z13.enum([
|
|
|
8590
8913
|
"precedes",
|
|
8591
8914
|
"causes"
|
|
8592
8915
|
]);
|
|
8593
|
-
var GraphEdgeSchema =
|
|
8594
|
-
from:
|
|
8595
|
-
to:
|
|
8916
|
+
var GraphEdgeSchema = z14.object({
|
|
8917
|
+
from: z14.string().min(1),
|
|
8918
|
+
to: z14.string().min(1),
|
|
8596
8919
|
type: RelationTypeSchema,
|
|
8597
|
-
weight:
|
|
8598
|
-
createdAt:
|
|
8599
|
-
metadata:
|
|
8920
|
+
weight: z14.number().min(0).max(1),
|
|
8921
|
+
createdAt: z14.date(),
|
|
8922
|
+
metadata: z14.record(z14.string(), z14.unknown()).optional()
|
|
8600
8923
|
});
|
|
8601
|
-
var TraversalOptionsSchema =
|
|
8602
|
-
maxDepth:
|
|
8603
|
-
relationTypes:
|
|
8604
|
-
minWeight:
|
|
8605
|
-
limit:
|
|
8606
|
-
includeStart:
|
|
8607
|
-
direction:
|
|
8924
|
+
var TraversalOptionsSchema = z14.object({
|
|
8925
|
+
maxDepth: z14.number().int().positive().optional(),
|
|
8926
|
+
relationTypes: z14.array(RelationTypeSchema).optional(),
|
|
8927
|
+
minWeight: z14.number().min(0).max(1).optional(),
|
|
8928
|
+
limit: z14.number().int().positive().optional(),
|
|
8929
|
+
includeStart: z14.boolean().optional(),
|
|
8930
|
+
direction: z14.enum(["outgoing", "incoming", "both"]).optional()
|
|
8608
8931
|
});
|
|
8609
|
-
var GraphMemoryConfigSchema =
|
|
8610
|
-
dbPath:
|
|
8611
|
-
markdownDir:
|
|
8612
|
-
defaultTraversalDepth:
|
|
8613
|
-
maxTraversalDepth:
|
|
8614
|
-
autoExpire:
|
|
8932
|
+
var GraphMemoryConfigSchema = z14.object({
|
|
8933
|
+
dbPath: z14.string().min(1),
|
|
8934
|
+
markdownDir: z14.string().min(1),
|
|
8935
|
+
defaultTraversalDepth: z14.number().int().positive().optional(),
|
|
8936
|
+
maxTraversalDepth: z14.number().int().positive().optional(),
|
|
8937
|
+
autoExpire: z14.boolean().optional()
|
|
8615
8938
|
});
|
|
8616
8939
|
var DEFAULT_GRAPH_MEMORY_CONFIG = {
|
|
8617
8940
|
defaultTraversalDepth: 2,
|
|
@@ -8767,7 +9090,7 @@ function findShortestPath(db, from, to, opts) {
|
|
|
8767
9090
|
}
|
|
8768
9091
|
|
|
8769
9092
|
// src/context/graph-memory.ts
|
|
8770
|
-
var
|
|
9093
|
+
var logger7 = createLogger({ component: "GraphMemoryBackend" });
|
|
8771
9094
|
var GraphMemoryBackend = class {
|
|
8772
9095
|
config;
|
|
8773
9096
|
log;
|
|
@@ -8782,7 +9105,7 @@ var GraphMemoryBackend = class {
|
|
|
8782
9105
|
throw new MemoryError(`Invalid GraphMemoryBackend config: ${msg}`);
|
|
8783
9106
|
}
|
|
8784
9107
|
this.config = { ...DEFAULT_GRAPH_MEMORY_CONFIG, ...config };
|
|
8785
|
-
this.log =
|
|
9108
|
+
this.log = logger7;
|
|
8786
9109
|
this.base = new HybridMemoryBackend({ dbPath: config.dbPath, markdownDir: config.markdownDir });
|
|
8787
9110
|
}
|
|
8788
9111
|
async initialize() {
|
|
@@ -8797,7 +9120,7 @@ var GraphMemoryBackend = class {
|
|
|
8797
9120
|
if (!baseInit.ok) return baseInit;
|
|
8798
9121
|
try {
|
|
8799
9122
|
const mod = await import("better-sqlite3").catch((cause) => {
|
|
8800
|
-
|
|
9123
|
+
logger7.debug("better-sqlite3 import failed", { error: String(cause) });
|
|
8801
9124
|
return null;
|
|
8802
9125
|
});
|
|
8803
9126
|
if (mod === null)
|
|
@@ -8969,11 +9292,11 @@ var GraphMemoryBackend = class {
|
|
|
8969
9292
|
};
|
|
8970
9293
|
|
|
8971
9294
|
// src/context/agentic-memory-types.ts
|
|
8972
|
-
import { z as
|
|
9295
|
+
import { z as z16 } from "zod";
|
|
8973
9296
|
|
|
8974
9297
|
// src/context/agentic-memory-primitives.ts
|
|
8975
|
-
import { z as
|
|
8976
|
-
var EntityTypeSchema =
|
|
9298
|
+
import { z as z15 } from "zod";
|
|
9299
|
+
var EntityTypeSchema = z15.enum([
|
|
8977
9300
|
"person",
|
|
8978
9301
|
"organization",
|
|
8979
9302
|
"concept",
|
|
@@ -8981,60 +9304,60 @@ var EntityTypeSchema = z14.enum([
|
|
|
8981
9304
|
"file",
|
|
8982
9305
|
"unknown"
|
|
8983
9306
|
]);
|
|
8984
|
-
var EntityReferenceSchema =
|
|
8985
|
-
name:
|
|
9307
|
+
var EntityReferenceSchema = z15.object({
|
|
9308
|
+
name: z15.string().min(1).max(200),
|
|
8986
9309
|
type: EntityTypeSchema
|
|
8987
9310
|
});
|
|
8988
|
-
var EvolutionTypeSchema =
|
|
9311
|
+
var EvolutionTypeSchema = z15.enum([
|
|
8989
9312
|
"refinement",
|
|
8990
9313
|
"contradiction",
|
|
8991
9314
|
"extension",
|
|
8992
9315
|
"supersession"
|
|
8993
9316
|
]);
|
|
8994
|
-
var EvolutionResultSchema =
|
|
9317
|
+
var EvolutionResultSchema = z15.object({
|
|
8995
9318
|
type: EvolutionTypeSchema,
|
|
8996
|
-
affectedKey:
|
|
8997
|
-
confidence:
|
|
8998
|
-
description:
|
|
9319
|
+
affectedKey: z15.string().min(1),
|
|
9320
|
+
confidence: z15.number().min(0).max(1),
|
|
9321
|
+
description: z15.string().max(500)
|
|
8999
9322
|
});
|
|
9000
|
-
var LinkSuggestionSchema =
|
|
9001
|
-
from:
|
|
9002
|
-
to:
|
|
9323
|
+
var LinkSuggestionSchema = z15.object({
|
|
9324
|
+
from: z15.string().min(1),
|
|
9325
|
+
to: z15.string().min(1),
|
|
9003
9326
|
relationType: RelationTypeSchema,
|
|
9004
|
-
reason:
|
|
9005
|
-
confidence:
|
|
9327
|
+
reason: z15.string().max(200),
|
|
9328
|
+
confidence: z15.number().min(0).max(1)
|
|
9006
9329
|
});
|
|
9007
9330
|
|
|
9008
9331
|
// src/context/agentic-memory-types.ts
|
|
9009
|
-
var MemoryAttributesSchema =
|
|
9010
|
-
keywords:
|
|
9011
|
-
semanticTags:
|
|
9012
|
-
contextDescription:
|
|
9013
|
-
entities:
|
|
9014
|
-
attributesUpdatedAt:
|
|
9332
|
+
var MemoryAttributesSchema = z16.object({
|
|
9333
|
+
keywords: z16.array(z16.string().max(100)).max(50),
|
|
9334
|
+
semanticTags: z16.array(z16.string().max(50)).max(20),
|
|
9335
|
+
contextDescription: z16.string().max(500),
|
|
9336
|
+
entities: z16.array(EntityReferenceSchema).max(30),
|
|
9337
|
+
attributesUpdatedAt: z16.date()
|
|
9015
9338
|
});
|
|
9016
|
-
var ExtractionConfigSchema =
|
|
9017
|
-
maxKeywords:
|
|
9018
|
-
maxSemanticTags:
|
|
9019
|
-
maxContextLength:
|
|
9020
|
-
maxEntities:
|
|
9339
|
+
var ExtractionConfigSchema = z16.object({
|
|
9340
|
+
maxKeywords: z16.number().int().positive().max(50),
|
|
9341
|
+
maxSemanticTags: z16.number().int().positive().max(20),
|
|
9342
|
+
maxContextLength: z16.number().int().positive().max(500),
|
|
9343
|
+
maxEntities: z16.number().int().positive().max(30)
|
|
9021
9344
|
});
|
|
9022
|
-
var LinkingConfigSchema =
|
|
9023
|
-
suggestionThreshold:
|
|
9024
|
-
maxSuggestions:
|
|
9025
|
-
allowedTypes:
|
|
9345
|
+
var LinkingConfigSchema = z16.object({
|
|
9346
|
+
suggestionThreshold: z16.number().min(0).max(1),
|
|
9347
|
+
maxSuggestions: z16.number().int().positive().max(20),
|
|
9348
|
+
allowedTypes: z16.array(RelationTypeSchema)
|
|
9026
9349
|
});
|
|
9027
|
-
var LinkingOptionsSchema =
|
|
9028
|
-
threshold:
|
|
9029
|
-
maxLinks:
|
|
9030
|
-
bidirectional:
|
|
9350
|
+
var LinkingOptionsSchema = z16.object({
|
|
9351
|
+
threshold: z16.number().min(0).max(1).optional(),
|
|
9352
|
+
maxLinks: z16.number().int().positive().optional(),
|
|
9353
|
+
bidirectional: z16.boolean().optional()
|
|
9031
9354
|
});
|
|
9032
|
-
var AgenticMemoryConfigSchema =
|
|
9033
|
-
dbPath:
|
|
9034
|
-
markdownDir:
|
|
9355
|
+
var AgenticMemoryConfigSchema = z16.object({
|
|
9356
|
+
dbPath: z16.string().min(1),
|
|
9357
|
+
markdownDir: z16.string().min(1),
|
|
9035
9358
|
extraction: ExtractionConfigSchema.partial().optional(),
|
|
9036
9359
|
linking: LinkingConfigSchema.partial().optional(),
|
|
9037
|
-
autoExpire:
|
|
9360
|
+
autoExpire: z16.boolean().optional()
|
|
9038
9361
|
});
|
|
9039
9362
|
var DEFAULT_EXTRACTION_CONFIG = {
|
|
9040
9363
|
maxKeywords: 10,
|
|
@@ -9287,7 +9610,7 @@ function mergeLinkingConfig(partial) {
|
|
|
9287
9610
|
}
|
|
9288
9611
|
|
|
9289
9612
|
// src/context/agentic-memory-db-helpers.ts
|
|
9290
|
-
var
|
|
9613
|
+
var logger8 = createLogger({ component: "AgenticMemoryDbHelpers" });
|
|
9291
9614
|
function safeExtractAttributes(amem) {
|
|
9292
9615
|
if (!Array.isArray(amem.keywords) || amem.attributesUpdatedAt === void 0) return null;
|
|
9293
9616
|
const updatedAt = amem.attributesUpdatedAt;
|
|
@@ -9312,7 +9635,7 @@ function memoryRowToAgenticEntry(row, extractionConfig) {
|
|
|
9312
9635
|
try {
|
|
9313
9636
|
parsedMeta = JSON.parse(row.metadata);
|
|
9314
9637
|
} catch {
|
|
9315
|
-
|
|
9638
|
+
logger8.warn("Corrupt metadata JSON in memory row, using fallback extraction", {
|
|
9316
9639
|
key: row.key
|
|
9317
9640
|
});
|
|
9318
9641
|
}
|
|
@@ -9345,7 +9668,7 @@ function getAttributesFromRow(row, extractionConfig) {
|
|
|
9345
9668
|
try {
|
|
9346
9669
|
meta = JSON.parse(row.metadata);
|
|
9347
9670
|
} catch {
|
|
9348
|
-
|
|
9671
|
+
logger8.warn("Corrupt metadata JSON in getAttributesFromRow, using value extraction", {
|
|
9349
9672
|
key: row.key
|
|
9350
9673
|
});
|
|
9351
9674
|
}
|
|
@@ -9357,7 +9680,7 @@ function getAttributesFromRow(row, extractionConfig) {
|
|
|
9357
9680
|
try {
|
|
9358
9681
|
parsedValue = JSON.parse(row.value);
|
|
9359
9682
|
} catch {
|
|
9360
|
-
|
|
9683
|
+
logger8.warn("Corrupt value JSON in getAttributesFromRow, using raw string", {
|
|
9361
9684
|
key: row.key
|
|
9362
9685
|
});
|
|
9363
9686
|
}
|
|
@@ -9447,7 +9770,7 @@ function buildAgenticEntry(key, value, metadata, attributes, createdAt) {
|
|
|
9447
9770
|
}
|
|
9448
9771
|
|
|
9449
9772
|
// src/context/agentic-memory.ts
|
|
9450
|
-
var
|
|
9773
|
+
var logger9 = createLogger({ component: "AgenticMemoryBackend" });
|
|
9451
9774
|
var AgenticMemoryBackend = class {
|
|
9452
9775
|
config;
|
|
9453
9776
|
log;
|
|
@@ -9465,7 +9788,7 @@ var AgenticMemoryBackend = class {
|
|
|
9465
9788
|
throw new MemoryError(`Invalid AgenticMemoryBackend config: ${msg}`);
|
|
9466
9789
|
}
|
|
9467
9790
|
this.config = config;
|
|
9468
|
-
this.log =
|
|
9791
|
+
this.log = logger9;
|
|
9469
9792
|
this.extractionConfig = mergeExtractionConfig(config.extraction);
|
|
9470
9793
|
this.linkingConfig = mergeLinkingConfig(config.linking);
|
|
9471
9794
|
this.base = new HybridMemoryBackend({
|
|
@@ -9717,74 +10040,74 @@ import * as fs2 from "fs";
|
|
|
9717
10040
|
import * as path from "path";
|
|
9718
10041
|
|
|
9719
10042
|
// src/context/belief-persistence-types.ts
|
|
9720
|
-
import { z as
|
|
9721
|
-
var BeliefSnapshotSchema =
|
|
9722
|
-
version:
|
|
9723
|
-
exportedAt:
|
|
9724
|
-
beliefs:
|
|
9725
|
-
|
|
9726
|
-
beliefId:
|
|
9727
|
-
subject:
|
|
9728
|
-
predicate:
|
|
9729
|
-
object:
|
|
10043
|
+
import { z as z17 } from "zod";
|
|
10044
|
+
var BeliefSnapshotSchema = z17.object({
|
|
10045
|
+
version: z17.number().int().min(1),
|
|
10046
|
+
exportedAt: z17.string(),
|
|
10047
|
+
beliefs: z17.array(
|
|
10048
|
+
z17.object({
|
|
10049
|
+
beliefId: z17.string(),
|
|
10050
|
+
subject: z17.string(),
|
|
10051
|
+
predicate: z17.string(),
|
|
10052
|
+
object: z17.string(),
|
|
9730
10053
|
confidence: BeliefConfidenceSchema,
|
|
9731
10054
|
sourceType: BeliefSourceTypeSchema,
|
|
9732
|
-
sourceRef:
|
|
9733
|
-
derivedFrom:
|
|
9734
|
-
version:
|
|
9735
|
-
createdAt:
|
|
9736
|
-
updatedAt:
|
|
9737
|
-
superseded:
|
|
9738
|
-
supersededBy:
|
|
9739
|
-
domain:
|
|
9740
|
-
metadata:
|
|
10055
|
+
sourceRef: z17.string().optional(),
|
|
10056
|
+
derivedFrom: z17.array(z17.string()).optional(),
|
|
10057
|
+
version: z17.number(),
|
|
10058
|
+
createdAt: z17.string(),
|
|
10059
|
+
updatedAt: z17.string(),
|
|
10060
|
+
superseded: z17.boolean(),
|
|
10061
|
+
supersededBy: z17.string().optional(),
|
|
10062
|
+
domain: z17.string().optional(),
|
|
10063
|
+
metadata: z17.record(z17.string(), z17.unknown()).optional()
|
|
9741
10064
|
})
|
|
9742
10065
|
),
|
|
9743
|
-
updates:
|
|
9744
|
-
|
|
9745
|
-
beliefId:
|
|
9746
|
-
records:
|
|
9747
|
-
|
|
9748
|
-
updateId:
|
|
9749
|
-
beliefId:
|
|
10066
|
+
updates: z17.array(
|
|
10067
|
+
z17.object({
|
|
10068
|
+
beliefId: z17.string(),
|
|
10069
|
+
records: z17.array(
|
|
10070
|
+
z17.object({
|
|
10071
|
+
updateId: z17.string(),
|
|
10072
|
+
beliefId: z17.string(),
|
|
9750
10073
|
updateType: BeliefUpdateTypeSchema,
|
|
9751
|
-
previousState:
|
|
9752
|
-
newState:
|
|
9753
|
-
reason:
|
|
9754
|
-
evidence:
|
|
9755
|
-
timestamp:
|
|
9756
|
-
updatedBy:
|
|
10074
|
+
previousState: z17.record(z17.string(), z17.unknown()).optional(),
|
|
10075
|
+
newState: z17.record(z17.string(), z17.unknown()),
|
|
10076
|
+
reason: z17.string().max(1e4),
|
|
10077
|
+
evidence: z17.string().max(1e4).optional(),
|
|
10078
|
+
timestamp: z17.string(),
|
|
10079
|
+
updatedBy: z17.string().optional()
|
|
9757
10080
|
})
|
|
9758
10081
|
)
|
|
9759
10082
|
})
|
|
9760
10083
|
),
|
|
9761
|
-
counterfactuals:
|
|
9762
|
-
|
|
9763
|
-
counterfactualId:
|
|
9764
|
-
hypothesis:
|
|
9765
|
-
affectedBeliefs:
|
|
9766
|
-
predictedOutcomes:
|
|
9767
|
-
actualOutcomes:
|
|
9768
|
-
validated:
|
|
9769
|
-
createdAt:
|
|
9770
|
-
taskContext:
|
|
10084
|
+
counterfactuals: z17.array(
|
|
10085
|
+
z17.object({
|
|
10086
|
+
counterfactualId: z17.string(),
|
|
10087
|
+
hypothesis: z17.string().max(1e4),
|
|
10088
|
+
affectedBeliefs: z17.array(z17.string()),
|
|
10089
|
+
predictedOutcomes: z17.array(z17.string()),
|
|
10090
|
+
actualOutcomes: z17.array(z17.string()).optional(),
|
|
10091
|
+
validated: z17.boolean(),
|
|
10092
|
+
createdAt: z17.string(),
|
|
10093
|
+
taskContext: z17.string().optional()
|
|
9771
10094
|
})
|
|
9772
10095
|
),
|
|
9773
|
-
hindsightRecords:
|
|
9774
|
-
|
|
9775
|
-
taskId:
|
|
9776
|
-
records:
|
|
9777
|
-
|
|
9778
|
-
hindsightId:
|
|
9779
|
-
taskId:
|
|
9780
|
-
priorBeliefs:
|
|
9781
|
-
expectedOutcome:
|
|
9782
|
-
actualOutcome:
|
|
9783
|
-
outcomeMatched:
|
|
9784
|
-
correctedBeliefs:
|
|
9785
|
-
newBeliefs:
|
|
9786
|
-
lessons:
|
|
9787
|
-
createdAt:
|
|
10096
|
+
hindsightRecords: z17.array(
|
|
10097
|
+
z17.object({
|
|
10098
|
+
taskId: z17.string(),
|
|
10099
|
+
records: z17.array(
|
|
10100
|
+
z17.object({
|
|
10101
|
+
hindsightId: z17.string(),
|
|
10102
|
+
taskId: z17.string(),
|
|
10103
|
+
priorBeliefs: z17.array(z17.string()),
|
|
10104
|
+
expectedOutcome: z17.string().max(1e4),
|
|
10105
|
+
actualOutcome: z17.string().max(1e4),
|
|
10106
|
+
outcomeMatched: z17.boolean(),
|
|
10107
|
+
correctedBeliefs: z17.array(z17.string()),
|
|
10108
|
+
newBeliefs: z17.array(z17.string()),
|
|
10109
|
+
lessons: z17.array(z17.string()),
|
|
10110
|
+
createdAt: z17.string()
|
|
9788
10111
|
})
|
|
9789
10112
|
)
|
|
9790
10113
|
})
|
|
@@ -9981,23 +10304,23 @@ function getSnapshotFiles() {
|
|
|
9981
10304
|
return [];
|
|
9982
10305
|
}
|
|
9983
10306
|
}
|
|
9984
|
-
function enforceRetention(
|
|
10307
|
+
function enforceRetention(logger12) {
|
|
9985
10308
|
try {
|
|
9986
10309
|
const files = getSnapshotFiles();
|
|
9987
10310
|
if (files.length <= MAX_SNAPSHOT_FILES) return;
|
|
9988
10311
|
const toDelete = files.slice(MAX_SNAPSHOT_FILES);
|
|
9989
10312
|
for (const file of toDelete) fs2.unlinkSync(path.join(getBeliefsDir(), file));
|
|
9990
|
-
|
|
10313
|
+
logger12.debug("Belief snapshot retention enforced", {
|
|
9991
10314
|
kept: MAX_SNAPSHOT_FILES,
|
|
9992
10315
|
deleted: toDelete.length
|
|
9993
10316
|
});
|
|
9994
10317
|
} catch (error) {
|
|
9995
|
-
|
|
10318
|
+
logger12.debug("Belief snapshot retention cleanup failed", {
|
|
9996
10319
|
error: getErrorMessage(error)
|
|
9997
10320
|
});
|
|
9998
10321
|
}
|
|
9999
10322
|
}
|
|
10000
|
-
function saveBeliefSnapshot(data,
|
|
10323
|
+
function saveBeliefSnapshot(data, logger12) {
|
|
10001
10324
|
try {
|
|
10002
10325
|
ensureBeliefsDir();
|
|
10003
10326
|
const snapshot = createSnapshot(data);
|
|
@@ -10005,20 +10328,20 @@ function saveBeliefSnapshot(data, logger11) {
|
|
|
10005
10328
|
const filename = `beliefs-${timestamp}.json`;
|
|
10006
10329
|
const filepath = path.join(getBeliefsDir(), filename);
|
|
10007
10330
|
fs2.writeFileSync(filepath, JSON.stringify(snapshot, null, 2), "utf-8");
|
|
10008
|
-
|
|
10009
|
-
enforceRetention(
|
|
10331
|
+
logger12.info("Belief memory snapshot saved", { filename, beliefs: snapshot.beliefs.length });
|
|
10332
|
+
enforceRetention(logger12);
|
|
10010
10333
|
return ok(filepath);
|
|
10011
10334
|
} catch (error) {
|
|
10012
10335
|
const message = getErrorMessage(error);
|
|
10013
10336
|
return err(new Error(`Failed to save belief snapshot: ${message}`));
|
|
10014
10337
|
}
|
|
10015
10338
|
}
|
|
10016
|
-
function loadBeliefSnapshot(
|
|
10339
|
+
function loadBeliefSnapshot(logger12) {
|
|
10017
10340
|
try {
|
|
10018
10341
|
ensureBeliefsDir();
|
|
10019
10342
|
const files = getSnapshotFiles();
|
|
10020
10343
|
if (files.length === 0) {
|
|
10021
|
-
|
|
10344
|
+
logger12.debug("No belief snapshots found");
|
|
10022
10345
|
return ok(null);
|
|
10023
10346
|
}
|
|
10024
10347
|
for (const file of files.slice(0, 3)) {
|
|
@@ -10027,20 +10350,20 @@ function loadBeliefSnapshot(logger11) {
|
|
|
10027
10350
|
const raw = JSON.parse(fs2.readFileSync(filepath, "utf-8"));
|
|
10028
10351
|
const validation = BeliefSnapshotSchema.safeParse(raw);
|
|
10029
10352
|
if (!validation.success) {
|
|
10030
|
-
|
|
10353
|
+
logger12.warn("Invalid belief snapshot file", { file, errors: validation.error.issues });
|
|
10031
10354
|
continue;
|
|
10032
10355
|
}
|
|
10033
10356
|
const hydrated = hydrateSnapshot(validation.data);
|
|
10034
|
-
|
|
10357
|
+
logger12.info("Belief memory snapshot loaded", { file, beliefs: hydrated.beliefs.size });
|
|
10035
10358
|
return ok(hydrated);
|
|
10036
10359
|
} catch (error) {
|
|
10037
|
-
|
|
10360
|
+
logger12.warn("Failed to load belief snapshot file", {
|
|
10038
10361
|
file,
|
|
10039
10362
|
error: getErrorMessage(error)
|
|
10040
10363
|
});
|
|
10041
10364
|
}
|
|
10042
10365
|
}
|
|
10043
|
-
|
|
10366
|
+
logger12.warn("All recent belief snapshots are invalid");
|
|
10044
10367
|
return ok(null);
|
|
10045
10368
|
} catch (error) {
|
|
10046
10369
|
const message = getErrorMessage(error);
|
|
@@ -10049,81 +10372,81 @@ function loadBeliefSnapshot(logger11) {
|
|
|
10049
10372
|
}
|
|
10050
10373
|
|
|
10051
10374
|
// src/context/memory-types.ts
|
|
10052
|
-
import { z as
|
|
10375
|
+
import { z as z19 } from "zod";
|
|
10053
10376
|
|
|
10054
10377
|
// src/context/memory-module-types.ts
|
|
10055
|
-
import { z as
|
|
10056
|
-
var CoreMemoryDataSchema =
|
|
10057
|
-
agentId:
|
|
10058
|
-
role:
|
|
10059
|
-
name:
|
|
10060
|
-
constraints:
|
|
10061
|
-
capabilities:
|
|
10062
|
-
systemPrompt:
|
|
10063
|
-
temperament:
|
|
10378
|
+
import { z as z18 } from "zod";
|
|
10379
|
+
var CoreMemoryDataSchema = z18.object({
|
|
10380
|
+
agentId: z18.string().min(1),
|
|
10381
|
+
role: z18.string(),
|
|
10382
|
+
name: z18.string().min(1),
|
|
10383
|
+
constraints: z18.array(z18.string()),
|
|
10384
|
+
capabilities: z18.array(z18.string()),
|
|
10385
|
+
systemPrompt: z18.string().max(5e4).optional(),
|
|
10386
|
+
temperament: z18.enum(["cautious", "balanced", "exploratory"]).optional()
|
|
10064
10387
|
});
|
|
10065
|
-
var EpisodeDataSchema =
|
|
10066
|
-
episodeId:
|
|
10067
|
-
taskId:
|
|
10068
|
-
agentId:
|
|
10069
|
-
action:
|
|
10070
|
-
outcome:
|
|
10071
|
-
context:
|
|
10072
|
-
learnings:
|
|
10073
|
-
timestamp:
|
|
10074
|
-
durationMs:
|
|
10388
|
+
var EpisodeDataSchema = z18.object({
|
|
10389
|
+
episodeId: z18.string().min(1),
|
|
10390
|
+
taskId: z18.string().min(1),
|
|
10391
|
+
agentId: z18.string().min(1),
|
|
10392
|
+
action: z18.string().min(1),
|
|
10393
|
+
outcome: z18.enum(["success", "failure", "partial"]),
|
|
10394
|
+
context: z18.record(z18.string(), z18.unknown()),
|
|
10395
|
+
learnings: z18.array(z18.string()).optional(),
|
|
10396
|
+
timestamp: z18.date(),
|
|
10397
|
+
durationMs: z18.number().positive().optional()
|
|
10075
10398
|
});
|
|
10076
|
-
var SemanticFactSchema =
|
|
10077
|
-
factId:
|
|
10078
|
-
domain:
|
|
10079
|
-
subject:
|
|
10080
|
-
predicate:
|
|
10081
|
-
object:
|
|
10082
|
-
confidence:
|
|
10083
|
-
source:
|
|
10084
|
-
validUntil:
|
|
10399
|
+
var SemanticFactSchema = z18.object({
|
|
10400
|
+
factId: z18.string().min(1),
|
|
10401
|
+
domain: z18.string().min(1),
|
|
10402
|
+
subject: z18.string().min(1),
|
|
10403
|
+
predicate: z18.string().min(1),
|
|
10404
|
+
object: z18.string(),
|
|
10405
|
+
confidence: z18.number().min(0).max(1),
|
|
10406
|
+
source: z18.string().optional(),
|
|
10407
|
+
validUntil: z18.date().optional()
|
|
10085
10408
|
});
|
|
10086
|
-
var ProcedureStepSchema =
|
|
10087
|
-
stepId:
|
|
10088
|
-
action:
|
|
10089
|
-
parameters:
|
|
10090
|
-
preconditions:
|
|
10091
|
-
postconditions:
|
|
10409
|
+
var ProcedureStepSchema = z18.object({
|
|
10410
|
+
stepId: z18.string().min(1),
|
|
10411
|
+
action: z18.string().min(1),
|
|
10412
|
+
parameters: z18.record(z18.string(), z18.unknown()).optional(),
|
|
10413
|
+
preconditions: z18.array(z18.string()).optional(),
|
|
10414
|
+
postconditions: z18.array(z18.string()).optional()
|
|
10092
10415
|
});
|
|
10093
|
-
var ProcedureSchema =
|
|
10094
|
-
procedureId:
|
|
10095
|
-
name:
|
|
10096
|
-
description:
|
|
10097
|
-
steps:
|
|
10098
|
-
triggerConditions:
|
|
10099
|
-
successRate:
|
|
10100
|
-
executionCount:
|
|
10101
|
-
averageDurationMs:
|
|
10102
|
-
tags:
|
|
10416
|
+
var ProcedureSchema = z18.object({
|
|
10417
|
+
procedureId: z18.string().min(1),
|
|
10418
|
+
name: z18.string().min(1),
|
|
10419
|
+
description: z18.string().max(1e4),
|
|
10420
|
+
steps: z18.array(ProcedureStepSchema).max(100),
|
|
10421
|
+
triggerConditions: z18.array(z18.string()),
|
|
10422
|
+
successRate: z18.number().min(0).max(1),
|
|
10423
|
+
executionCount: z18.number().int().min(0),
|
|
10424
|
+
averageDurationMs: z18.number().positive().optional(),
|
|
10425
|
+
tags: z18.array(z18.string()).optional()
|
|
10103
10426
|
});
|
|
10104
|
-
var ResourceReferenceSchema =
|
|
10105
|
-
resourceId:
|
|
10106
|
-
type:
|
|
10107
|
-
location:
|
|
10108
|
-
name:
|
|
10109
|
-
mimeType:
|
|
10110
|
-
size:
|
|
10111
|
-
hash:
|
|
10112
|
-
lastAccessed:
|
|
10113
|
-
lastModified:
|
|
10114
|
-
metadata:
|
|
10427
|
+
var ResourceReferenceSchema = z18.object({
|
|
10428
|
+
resourceId: z18.string().min(1),
|
|
10429
|
+
type: z18.enum(["file", "url", "api", "database", "other"]),
|
|
10430
|
+
location: z18.string().min(1),
|
|
10431
|
+
name: z18.string().min(1),
|
|
10432
|
+
mimeType: z18.string().optional(),
|
|
10433
|
+
size: z18.number().int().positive().optional(),
|
|
10434
|
+
hash: z18.string().optional(),
|
|
10435
|
+
lastAccessed: z18.date(),
|
|
10436
|
+
lastModified: z18.date().optional(),
|
|
10437
|
+
metadata: z18.record(z18.string(), z18.unknown()).optional()
|
|
10115
10438
|
});
|
|
10116
|
-
var VaultEntrySchema =
|
|
10117
|
-
vaultId:
|
|
10118
|
-
category:
|
|
10119
|
-
title:
|
|
10120
|
-
content:
|
|
10121
|
-
importance:
|
|
10122
|
-
createdAt:
|
|
10123
|
-
updatedAt:
|
|
10124
|
-
expiresAt:
|
|
10125
|
-
tags:
|
|
10126
|
-
relatedIds:
|
|
10439
|
+
var VaultEntrySchema = z18.object({
|
|
10440
|
+
vaultId: z18.string().min(1),
|
|
10441
|
+
category: z18.enum(["insight", "decision", "pattern", "config", "archive"]),
|
|
10442
|
+
title: z18.string().min(1),
|
|
10443
|
+
content: z18.unknown(),
|
|
10444
|
+
importance: z18.enum(["critical", "high", "normal"]),
|
|
10445
|
+
createdAt: z18.date(),
|
|
10446
|
+
updatedAt: z18.date(),
|
|
10447
|
+
expiresAt: z18.date().optional(),
|
|
10448
|
+
tags: z18.array(z18.string()).optional(),
|
|
10449
|
+
relatedIds: z18.array(z18.string()).optional()
|
|
10127
10450
|
});
|
|
10128
10451
|
|
|
10129
10452
|
// src/context/memory-types.ts
|
|
@@ -10137,7 +10460,7 @@ var MemoryType = {
|
|
|
10137
10460
|
/** Hindsight Belief Memory for reasoning agents (arXiv:2512.12818) */
|
|
10138
10461
|
BELIEF: "belief"
|
|
10139
10462
|
};
|
|
10140
|
-
var MemoryTypeSchema =
|
|
10463
|
+
var MemoryTypeSchema = z19.enum([
|
|
10141
10464
|
"core",
|
|
10142
10465
|
"episodic",
|
|
10143
10466
|
"semantic",
|
|
@@ -10436,7 +10759,7 @@ var KnowledgeVaultImpl = class {
|
|
|
10436
10759
|
};
|
|
10437
10760
|
|
|
10438
10761
|
// src/context/typed-memory.ts
|
|
10439
|
-
var
|
|
10762
|
+
var logger10 = createLogger({ component: "typed-memory" });
|
|
10440
10763
|
var TypedMemory = class {
|
|
10441
10764
|
core;
|
|
10442
10765
|
episodic;
|
|
@@ -10457,7 +10780,7 @@ var TypedMemory = class {
|
|
|
10457
10780
|
this.resource = new ResourceMemoryImpl(backend);
|
|
10458
10781
|
this.vault = new KnowledgeVaultImpl(backend);
|
|
10459
10782
|
this.belief = new HindsightBeliefMemory();
|
|
10460
|
-
|
|
10783
|
+
logger10.info("TypedMemory initialized");
|
|
10461
10784
|
}
|
|
10462
10785
|
async queryByType(type, query, limit = 20) {
|
|
10463
10786
|
const result = await this.backend.search(`${type} ${query}`, limit);
|
|
@@ -10499,7 +10822,7 @@ var TypedMemory = class {
|
|
|
10499
10822
|
async pruneExpired() {
|
|
10500
10823
|
const result = await this.backend.prune(new Date(getTimeProvider().now()));
|
|
10501
10824
|
if (!result.ok) return result;
|
|
10502
|
-
|
|
10825
|
+
logger10.info("Pruned expired entries", { count: result.value });
|
|
10503
10826
|
return ok({
|
|
10504
10827
|
prunedCount: result.value,
|
|
10505
10828
|
prunedByType: {
|
|
@@ -10542,11 +10865,11 @@ var MemoryPromoter = class {
|
|
|
10542
10865
|
agentic;
|
|
10543
10866
|
config;
|
|
10544
10867
|
log;
|
|
10545
|
-
constructor(beliefs, agentic, config = {},
|
|
10868
|
+
constructor(beliefs, agentic, config = {}, logger12) {
|
|
10546
10869
|
this.beliefs = beliefs;
|
|
10547
10870
|
this.agentic = agentic;
|
|
10548
10871
|
this.config = { ...DEFAULT_PROMOTION_CONFIG, ...config };
|
|
10549
|
-
this.log =
|
|
10872
|
+
this.log = logger12 ?? createLogger({ component: "MemoryPromoter" });
|
|
10550
10873
|
}
|
|
10551
10874
|
/**
|
|
10552
10875
|
* Promote high-confidence session learnings to structured beliefs.
|
|
@@ -10699,8 +11022,8 @@ var DEFAULT_DECAY_CONFIG = {
|
|
|
10699
11022
|
var CrossReferenceTracker = class {
|
|
10700
11023
|
references = /* @__PURE__ */ new Map();
|
|
10701
11024
|
log;
|
|
10702
|
-
constructor(
|
|
10703
|
-
this.log =
|
|
11025
|
+
constructor(logger12) {
|
|
11026
|
+
this.log = logger12 ?? createLogger({ component: "CrossReferenceTracker" });
|
|
10704
11027
|
}
|
|
10705
11028
|
/**
|
|
10706
11029
|
* Register a cross-reference between two memories.
|
|
@@ -10785,9 +11108,9 @@ var MemoryDecayManager = class {
|
|
|
10785
11108
|
agentic = null;
|
|
10786
11109
|
adaptive = null;
|
|
10787
11110
|
mobimem = null;
|
|
10788
|
-
constructor(config = {},
|
|
11111
|
+
constructor(config = {}, logger12) {
|
|
10789
11112
|
this.config = { ...DEFAULT_DECAY_CONFIG, ...config };
|
|
10790
|
-
this.log =
|
|
11113
|
+
this.log = logger12 ?? createLogger({ component: "MemoryDecayManager" });
|
|
10791
11114
|
this.tracker = new CrossReferenceTracker(this.log);
|
|
10792
11115
|
}
|
|
10793
11116
|
/**
|
|
@@ -11150,8 +11473,8 @@ var TYPED_DB_PATH = path2.join(MEMORY_BASE, "typed.db");
|
|
|
11150
11473
|
var MOBIMEM_DB_PATH = path2.join(MEMORY_BASE, "mobimem.db");
|
|
11151
11474
|
var MARKDOWN_DIR = path2.join(MEMORY_BASE, "markdown");
|
|
11152
11475
|
var sharedInstance = null;
|
|
11153
|
-
function getToolMemory(
|
|
11154
|
-
sharedInstance ??= new ToolMemoryManager(
|
|
11476
|
+
function getToolMemory(logger12) {
|
|
11477
|
+
sharedInstance ??= new ToolMemoryManager(logger12);
|
|
11155
11478
|
return sharedInstance;
|
|
11156
11479
|
}
|
|
11157
11480
|
function shutdownToolMemory() {
|
|
@@ -11172,8 +11495,8 @@ var ToolMemoryManager = class {
|
|
|
11172
11495
|
mobimem = null;
|
|
11173
11496
|
decayManager = null;
|
|
11174
11497
|
initPromise = null;
|
|
11175
|
-
constructor(
|
|
11176
|
-
this.log =
|
|
11498
|
+
constructor(logger12) {
|
|
11499
|
+
this.log = logger12 ?? createLogger({ component: "ToolMemory" });
|
|
11177
11500
|
this.memory = new SessionMemory({
|
|
11178
11501
|
memoryDir: DEFAULT_MEMORY_DIR,
|
|
11179
11502
|
logger: this.log
|
|
@@ -11859,10 +12182,10 @@ import { appendFileSync, readFileSync as readFileSync3, writeFileSync as writeFi
|
|
|
11859
12182
|
var PersistentOutcomeStore = class extends OutcomeStore {
|
|
11860
12183
|
filePath;
|
|
11861
12184
|
logger;
|
|
11862
|
-
constructor(config,
|
|
12185
|
+
constructor(config, logger12) {
|
|
11863
12186
|
super(config);
|
|
11864
12187
|
this.filePath = config?.filePath ?? getOutcomesFile();
|
|
11865
|
-
this.logger =
|
|
12188
|
+
this.logger = logger12 ?? createLogger({ component: "PersistentOutcomeStore" });
|
|
11866
12189
|
const dataDir = config?.dataDir;
|
|
11867
12190
|
ensureLearningDir(dataDir);
|
|
11868
12191
|
this.hydrate();
|
|
@@ -12003,11 +12326,11 @@ function emitTrendDetected(bus, detail) {
|
|
|
12003
12326
|
}
|
|
12004
12327
|
|
|
12005
12328
|
// src/mcp/tools/consensus-vote-recording.ts
|
|
12006
|
-
var
|
|
12329
|
+
var logger11 = createLogger({ tool: "consensus-vote" });
|
|
12007
12330
|
function recordVoteSuccess(proposal, strategy, outcome, duration, votes) {
|
|
12008
12331
|
const allSimulated = votes !== void 0 && votes.length > 0 && votes.every((v) => v.source === "simulation");
|
|
12009
12332
|
if (allSimulated) {
|
|
12010
|
-
|
|
12333
|
+
logger11.debug("Skipping memory + outcome recording \u2014 all votes simulated");
|
|
12011
12334
|
return;
|
|
12012
12335
|
}
|
|
12013
12336
|
try {
|
|
@@ -12024,10 +12347,10 @@ function recordVoteSuccess(proposal, strategy, outcome, duration, votes) {
|
|
|
12024
12347
|
source: "consensus-vote"
|
|
12025
12348
|
});
|
|
12026
12349
|
void memory.runPromotionPipeline().catch((error) => {
|
|
12027
|
-
|
|
12350
|
+
logger11.warn("Promotion pipeline failed", { error });
|
|
12028
12351
|
});
|
|
12029
12352
|
} catch (error) {
|
|
12030
|
-
|
|
12353
|
+
logger11.warn("Failed to record vote success to memory", { error: getErrorMessage(error) });
|
|
12031
12354
|
}
|
|
12032
12355
|
if (votes !== void 0) {
|
|
12033
12356
|
recordVoteOutcomes(votes);
|
|
@@ -12042,7 +12365,7 @@ function recordVoteError(proposal, errorMessage) {
|
|
|
12042
12365
|
filePattern: "mcp/tools/consensus-vote"
|
|
12043
12366
|
});
|
|
12044
12367
|
} catch (error) {
|
|
12045
|
-
|
|
12368
|
+
logger11.warn("Failed to record vote error", { error: getErrorMessage(error) });
|
|
12046
12369
|
}
|
|
12047
12370
|
}
|
|
12048
12371
|
function recordVoteOutcomes(votes) {
|
|
@@ -12069,7 +12392,7 @@ function recordVoteOutcomes(votes) {
|
|
|
12069
12392
|
});
|
|
12070
12393
|
}
|
|
12071
12394
|
} catch (error) {
|
|
12072
|
-
|
|
12395
|
+
logger11.debug("Best-effort vote outcome recording failed", { error: getErrorMessage(error) });
|
|
12073
12396
|
}
|
|
12074
12397
|
}
|
|
12075
12398
|
|
|
@@ -12078,15 +12401,327 @@ var WARNED = /* @__PURE__ */ new Set();
|
|
|
12078
12401
|
function isTestRunner() {
|
|
12079
12402
|
return process.env.VITEST === "true" || process.env.NODE_ENV === "test";
|
|
12080
12403
|
}
|
|
12081
|
-
function warnIfSimulatedOutsideTests(toolName,
|
|
12404
|
+
function warnIfSimulatedOutsideTests(toolName, logger12) {
|
|
12082
12405
|
if (isTestRunner()) return;
|
|
12083
12406
|
if (WARNED.has(toolName)) return;
|
|
12084
12407
|
WARNED.add(toolName);
|
|
12085
|
-
|
|
12408
|
+
logger12.warn(
|
|
12086
12409
|
`[${toolName}] simulateVotes=true: output is RANDOM and reserved for tests/demos. Do not treat the result as a real decision.`
|
|
12087
12410
|
);
|
|
12088
12411
|
}
|
|
12089
12412
|
|
|
12413
|
+
// src/mcp/tool-annotations.ts
|
|
12414
|
+
var TOOL_ANNOTATIONS = {
|
|
12415
|
+
// ============================================================================
|
|
12416
|
+
// Orchestration & expert lifecycle
|
|
12417
|
+
// ============================================================================
|
|
12418
|
+
/** Orchestrator coordinates expert agents; spawns workers that may mutate state. */
|
|
12419
|
+
orchestrate: {
|
|
12420
|
+
readOnlyHint: false,
|
|
12421
|
+
destructiveHint: false,
|
|
12422
|
+
idempotentHint: false,
|
|
12423
|
+
openWorldHint: true
|
|
12424
|
+
},
|
|
12425
|
+
/** Creates an expert and adds it to the in-memory expert registry. */
|
|
12426
|
+
create_expert: {
|
|
12427
|
+
readOnlyHint: false,
|
|
12428
|
+
destructiveHint: false,
|
|
12429
|
+
idempotentHint: false,
|
|
12430
|
+
openWorldHint: false
|
|
12431
|
+
},
|
|
12432
|
+
/** Executes a previously created expert; invokes external CLIs. */
|
|
12433
|
+
execute_expert: {
|
|
12434
|
+
readOnlyHint: false,
|
|
12435
|
+
destructiveHint: false,
|
|
12436
|
+
idempotentHint: false,
|
|
12437
|
+
openWorldHint: true
|
|
12438
|
+
},
|
|
12439
|
+
// ============================================================================
|
|
12440
|
+
// Workflow / pipeline execution
|
|
12441
|
+
// ============================================================================
|
|
12442
|
+
/** Runs a workflow template; steps may write to the registry or filesystem. */
|
|
12443
|
+
run_workflow: {
|
|
12444
|
+
readOnlyHint: false,
|
|
12445
|
+
destructiveHint: false,
|
|
12446
|
+
idempotentHint: false,
|
|
12447
|
+
openWorldHint: true
|
|
12448
|
+
},
|
|
12449
|
+
/** Runs a graph-based workflow with checkpointing. */
|
|
12450
|
+
run_graph_workflow: {
|
|
12451
|
+
readOnlyHint: false,
|
|
12452
|
+
destructiveHint: false,
|
|
12453
|
+
idempotentHint: false,
|
|
12454
|
+
openWorldHint: true
|
|
12455
|
+
},
|
|
12456
|
+
/** Runs a pipeline plugin by name. */
|
|
12457
|
+
run_pipeline: {
|
|
12458
|
+
readOnlyHint: false,
|
|
12459
|
+
destructiveHint: false,
|
|
12460
|
+
idempotentHint: false,
|
|
12461
|
+
openWorldHint: true
|
|
12462
|
+
},
|
|
12463
|
+
/** Full dev pipeline: research → plan → vote → implement → QA. */
|
|
12464
|
+
run_dev_pipeline: {
|
|
12465
|
+
readOnlyHint: false,
|
|
12466
|
+
destructiveHint: false,
|
|
12467
|
+
idempotentHint: false,
|
|
12468
|
+
openWorldHint: true
|
|
12469
|
+
},
|
|
12470
|
+
/** Executes an AI-software-factory spec pipeline. */
|
|
12471
|
+
execute_spec: {
|
|
12472
|
+
readOnlyHint: false,
|
|
12473
|
+
destructiveHint: false,
|
|
12474
|
+
idempotentHint: false,
|
|
12475
|
+
openWorldHint: true
|
|
12476
|
+
},
|
|
12477
|
+
// ============================================================================
|
|
12478
|
+
// Voting / decision
|
|
12479
|
+
// ============================================================================
|
|
12480
|
+
/** Records vote outcomes to the audit log; doesn't write to repo state. */
|
|
12481
|
+
consensus_vote: {
|
|
12482
|
+
readOnlyHint: false,
|
|
12483
|
+
destructiveHint: false,
|
|
12484
|
+
idempotentHint: false,
|
|
12485
|
+
openWorldHint: true
|
|
12486
|
+
},
|
|
12487
|
+
/** Per-axis tradeoff vote; records outcome to the store. */
|
|
12488
|
+
supply_chain_tradeoff_panel: {
|
|
12489
|
+
readOnlyHint: false,
|
|
12490
|
+
destructiveHint: false,
|
|
12491
|
+
idempotentHint: false,
|
|
12492
|
+
openWorldHint: true
|
|
12493
|
+
},
|
|
12494
|
+
/** Multi-voter PR review; may write review comments. */
|
|
12495
|
+
pr_review: {
|
|
12496
|
+
readOnlyHint: false,
|
|
12497
|
+
destructiveHint: false,
|
|
12498
|
+
idempotentHint: false,
|
|
12499
|
+
openWorldHint: true
|
|
12500
|
+
},
|
|
12501
|
+
// ============================================================================
|
|
12502
|
+
// Routing & introspection (read-only)
|
|
12503
|
+
// ============================================================================
|
|
12504
|
+
/** Returns a routing recommendation; doesn't execute. */
|
|
12505
|
+
delegate_to_model: {
|
|
12506
|
+
readOnlyHint: true,
|
|
12507
|
+
destructiveHint: false,
|
|
12508
|
+
idempotentHint: true,
|
|
12509
|
+
openWorldHint: false
|
|
12510
|
+
},
|
|
12511
|
+
/** Lists registered expert types. */
|
|
12512
|
+
list_experts: {
|
|
12513
|
+
readOnlyHint: true,
|
|
12514
|
+
destructiveHint: false,
|
|
12515
|
+
idempotentHint: true,
|
|
12516
|
+
openWorldHint: false
|
|
12517
|
+
},
|
|
12518
|
+
/** Lists registered workflow templates. */
|
|
12519
|
+
list_workflows: {
|
|
12520
|
+
readOnlyHint: true,
|
|
12521
|
+
destructiveHint: false,
|
|
12522
|
+
idempotentHint: true,
|
|
12523
|
+
openWorldHint: false
|
|
12524
|
+
},
|
|
12525
|
+
// ============================================================================
|
|
12526
|
+
// Research registry — reads
|
|
12527
|
+
// ============================================================================
|
|
12528
|
+
/** Queries the research registry. */
|
|
12529
|
+
research_query: {
|
|
12530
|
+
readOnlyHint: true,
|
|
12531
|
+
destructiveHint: false,
|
|
12532
|
+
idempotentHint: true,
|
|
12533
|
+
openWorldHint: false
|
|
12534
|
+
},
|
|
12535
|
+
/** Analyzes registry for gaps, trends, coverage. */
|
|
12536
|
+
research_analyze: {
|
|
12537
|
+
readOnlyHint: true,
|
|
12538
|
+
destructiveHint: false,
|
|
12539
|
+
idempotentHint: true,
|
|
12540
|
+
openWorldHint: false
|
|
12541
|
+
},
|
|
12542
|
+
/** Synthesizes registry into topic clusters. */
|
|
12543
|
+
research_synthesize: {
|
|
12544
|
+
readOnlyHint: true,
|
|
12545
|
+
destructiveHint: false,
|
|
12546
|
+
idempotentHint: true,
|
|
12547
|
+
openWorldHint: false
|
|
12548
|
+
},
|
|
12549
|
+
/** Discovers research items via external APIs; doesn't mutate registry. */
|
|
12550
|
+
research_discover: {
|
|
12551
|
+
readOnlyHint: true,
|
|
12552
|
+
destructiveHint: false,
|
|
12553
|
+
idempotentHint: true,
|
|
12554
|
+
openWorldHint: true
|
|
12555
|
+
},
|
|
12556
|
+
// ============================================================================
|
|
12557
|
+
// Research registry — mutations
|
|
12558
|
+
// ============================================================================
|
|
12559
|
+
/** Adds an arXiv paper to the registry. Dedup-checked but first call has effects. */
|
|
12560
|
+
research_add: {
|
|
12561
|
+
readOnlyHint: false,
|
|
12562
|
+
destructiveHint: false,
|
|
12563
|
+
idempotentHint: false,
|
|
12564
|
+
openWorldHint: true
|
|
12565
|
+
},
|
|
12566
|
+
/** Adds a non-paper source to the registry. */
|
|
12567
|
+
research_add_source: {
|
|
12568
|
+
readOnlyHint: false,
|
|
12569
|
+
destructiveHint: false,
|
|
12570
|
+
idempotentHint: false,
|
|
12571
|
+
openWorldHint: true
|
|
12572
|
+
},
|
|
12573
|
+
/** Reviews auto-cataloged research references; may approve/dismiss. */
|
|
12574
|
+
research_catalog_review: {
|
|
12575
|
+
readOnlyHint: false,
|
|
12576
|
+
destructiveHint: false,
|
|
12577
|
+
idempotentHint: false,
|
|
12578
|
+
openWorldHint: false
|
|
12579
|
+
},
|
|
12580
|
+
// ============================================================================
|
|
12581
|
+
// Transient lookups (no registry persistence)
|
|
12582
|
+
// ============================================================================
|
|
12583
|
+
/** Transient OSS search via GitHub API; no persistence. */
|
|
12584
|
+
survey_oss_landscape: {
|
|
12585
|
+
readOnlyHint: true,
|
|
12586
|
+
destructiveHint: false,
|
|
12587
|
+
idempotentHint: true,
|
|
12588
|
+
openWorldHint: true
|
|
12589
|
+
},
|
|
12590
|
+
/** Static lookup against curated vendor seed data. */
|
|
12591
|
+
vendor_publishing_audit: {
|
|
12592
|
+
readOnlyHint: true,
|
|
12593
|
+
destructiveHint: false,
|
|
12594
|
+
idempotentHint: true,
|
|
12595
|
+
openWorldHint: false
|
|
12596
|
+
},
|
|
12597
|
+
/** Diffs two YAML/JSON files; local-only. */
|
|
12598
|
+
compare_data_feeds: {
|
|
12599
|
+
readOnlyHint: true,
|
|
12600
|
+
destructiveHint: false,
|
|
12601
|
+
idempotentHint: true,
|
|
12602
|
+
openWorldHint: false
|
|
12603
|
+
},
|
|
12604
|
+
// ============================================================================
|
|
12605
|
+
// Memory
|
|
12606
|
+
// ============================================================================
|
|
12607
|
+
/** Reads from memory backends. */
|
|
12608
|
+
memory_query: {
|
|
12609
|
+
readOnlyHint: true,
|
|
12610
|
+
destructiveHint: false,
|
|
12611
|
+
idempotentHint: true,
|
|
12612
|
+
openWorldHint: false
|
|
12613
|
+
},
|
|
12614
|
+
/** Returns memory statistics. */
|
|
12615
|
+
memory_stats: {
|
|
12616
|
+
readOnlyHint: true,
|
|
12617
|
+
destructiveHint: false,
|
|
12618
|
+
idempotentHint: true,
|
|
12619
|
+
openWorldHint: false
|
|
12620
|
+
},
|
|
12621
|
+
/** Writes to a memory backend. */
|
|
12622
|
+
memory_write: {
|
|
12623
|
+
readOnlyHint: false,
|
|
12624
|
+
destructiveHint: false,
|
|
12625
|
+
idempotentHint: false,
|
|
12626
|
+
openWorldHint: false
|
|
12627
|
+
},
|
|
12628
|
+
// ============================================================================
|
|
12629
|
+
// Observability
|
|
12630
|
+
// ============================================================================
|
|
12631
|
+
/** Multi-CLI performance weather report; reads outcome store. */
|
|
12632
|
+
weather_report: {
|
|
12633
|
+
readOnlyHint: true,
|
|
12634
|
+
destructiveHint: false,
|
|
12635
|
+
idempotentHint: true,
|
|
12636
|
+
openWorldHint: false
|
|
12637
|
+
},
|
|
12638
|
+
/** Queries execution traces from disk. */
|
|
12639
|
+
query_trace: {
|
|
12640
|
+
readOnlyHint: true,
|
|
12641
|
+
destructiveHint: false,
|
|
12642
|
+
idempotentHint: true,
|
|
12643
|
+
openWorldHint: false
|
|
12644
|
+
},
|
|
12645
|
+
/** Queries structured task-state log. */
|
|
12646
|
+
query_task_state: {
|
|
12647
|
+
readOnlyHint: true,
|
|
12648
|
+
destructiveHint: false,
|
|
12649
|
+
idempotentHint: true,
|
|
12650
|
+
openWorldHint: false
|
|
12651
|
+
},
|
|
12652
|
+
/** Verifies hash chain of audit log files. */
|
|
12653
|
+
verify_audit_chain: {
|
|
12654
|
+
readOnlyHint: true,
|
|
12655
|
+
destructiveHint: false,
|
|
12656
|
+
idempotentHint: true,
|
|
12657
|
+
openWorldHint: false
|
|
12658
|
+
},
|
|
12659
|
+
/** Threshold-gated observability loop; may file GitHub issues when fileIssues=true. */
|
|
12660
|
+
improvement_review: {
|
|
12661
|
+
readOnlyHint: false,
|
|
12662
|
+
destructiveHint: false,
|
|
12663
|
+
idempotentHint: false,
|
|
12664
|
+
openWorldHint: true
|
|
12665
|
+
},
|
|
12666
|
+
// ============================================================================
|
|
12667
|
+
// Repository analysis
|
|
12668
|
+
// ============================================================================
|
|
12669
|
+
/** Analyzes a GitHub repository structure; doesn't write. */
|
|
12670
|
+
repo_analyze: {
|
|
12671
|
+
readOnlyHint: true,
|
|
12672
|
+
destructiveHint: false,
|
|
12673
|
+
idempotentHint: true,
|
|
12674
|
+
openWorldHint: true
|
|
12675
|
+
},
|
|
12676
|
+
/** Generates a security-scanning pipeline plan; returns plan, doesn't write it. */
|
|
12677
|
+
repo_security_plan: {
|
|
12678
|
+
readOnlyHint: true,
|
|
12679
|
+
destructiveHint: false,
|
|
12680
|
+
idempotentHint: true,
|
|
12681
|
+
openWorldHint: true
|
|
12682
|
+
},
|
|
12683
|
+
/** Extracts code symbols from source files. */
|
|
12684
|
+
extract_symbols: {
|
|
12685
|
+
readOnlyHint: true,
|
|
12686
|
+
destructiveHint: false,
|
|
12687
|
+
idempotentHint: true,
|
|
12688
|
+
openWorldHint: false
|
|
12689
|
+
},
|
|
12690
|
+
/** Searches codebase for patterns or symbols. */
|
|
12691
|
+
search_codebase: {
|
|
12692
|
+
readOnlyHint: true,
|
|
12693
|
+
destructiveHint: false,
|
|
12694
|
+
idempotentHint: true,
|
|
12695
|
+
openWorldHint: false
|
|
12696
|
+
},
|
|
12697
|
+
// ============================================================================
|
|
12698
|
+
// Issue triage & registry imports
|
|
12699
|
+
// ============================================================================
|
|
12700
|
+
/** Triages a GitHub issue; may write labels/comments when authorized. */
|
|
12701
|
+
issue_triage: {
|
|
12702
|
+
readOnlyHint: false,
|
|
12703
|
+
destructiveHint: false,
|
|
12704
|
+
idempotentHint: false,
|
|
12705
|
+
openWorldHint: true
|
|
12706
|
+
},
|
|
12707
|
+
/** Generates a draft model-registry entry; doesn't write. */
|
|
12708
|
+
registry_import: {
|
|
12709
|
+
readOnlyHint: true,
|
|
12710
|
+
destructiveHint: false,
|
|
12711
|
+
idempotentHint: true,
|
|
12712
|
+
openWorldHint: true
|
|
12713
|
+
}
|
|
12714
|
+
};
|
|
12715
|
+
function getToolAnnotations(name) {
|
|
12716
|
+
const a = TOOL_ANNOTATIONS[name];
|
|
12717
|
+
if (a === void 0) {
|
|
12718
|
+
throw new Error(
|
|
12719
|
+
`getToolAnnotations: no entry for tool "${name}". Add it to TOOL_ANNOTATIONS in src/mcp/tool-annotations.ts (#2648).`
|
|
12720
|
+
);
|
|
12721
|
+
}
|
|
12722
|
+
return a;
|
|
12723
|
+
}
|
|
12724
|
+
|
|
12090
12725
|
// src/mcp/tools/consensus-vote.ts
|
|
12091
12726
|
var persistentCorrelationTracker;
|
|
12092
12727
|
function getOrCreateCorrelationTracker() {
|
|
@@ -12133,6 +12768,21 @@ function createEmptyConsensusResult(proposal, algorithm) {
|
|
|
12133
12768
|
durationMs: 0
|
|
12134
12769
|
};
|
|
12135
12770
|
}
|
|
12771
|
+
function createPolicyFailedResult(proposal, algorithm, reason) {
|
|
12772
|
+
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
12773
|
+
return {
|
|
12774
|
+
proposalId: "error-policy-short-circuit",
|
|
12775
|
+
proposal: { title: `MCP Consensus Vote \u2014 ${reason}`, description: proposal, algorithm },
|
|
12776
|
+
outcome: "rejected",
|
|
12777
|
+
votes: /* @__PURE__ */ new Map(),
|
|
12778
|
+
voteCounts: { approve: 0, reject: 0, abstain: 0, total: 0 },
|
|
12779
|
+
approvalPercentage: 0,
|
|
12780
|
+
quorumReached: false,
|
|
12781
|
+
startedAt: now,
|
|
12782
|
+
closedAt: now,
|
|
12783
|
+
durationMs: 0
|
|
12784
|
+
};
|
|
12785
|
+
}
|
|
12136
12786
|
var CASCADE_THRESHOLDS = {
|
|
12137
12787
|
majority: 0.5,
|
|
12138
12788
|
supermajority: 0.67,
|
|
@@ -12159,9 +12809,8 @@ function detectEarlyCascade(algorithm, approvals, rejections, total) {
|
|
|
12159
12809
|
}
|
|
12160
12810
|
return { decided: false, reason: "" };
|
|
12161
12811
|
}
|
|
12162
|
-
async function processVotesThroughEngine(
|
|
12163
|
-
|
|
12164
|
-
if (validVotes.length === 0) return createEmptyConsensusResult(proposal, algorithm);
|
|
12812
|
+
async function processVotesThroughEngine(engineVotes, proposal, algorithm) {
|
|
12813
|
+
if (engineVotes.length === 0) return createEmptyConsensusResult(proposal, algorithm);
|
|
12165
12814
|
const engine = createConsensusEngine();
|
|
12166
12815
|
const engineProposal = {
|
|
12167
12816
|
title: "MCP Consensus Vote",
|
|
@@ -12174,7 +12823,7 @@ async function processVotesThroughEngine(votes, proposal, algorithm) {
|
|
|
12174
12823
|
cause: proposalResult.error
|
|
12175
12824
|
});
|
|
12176
12825
|
const proposalId = proposalResult.value;
|
|
12177
|
-
for (const { role, vote } of
|
|
12826
|
+
for (const { role, vote } of engineVotes) await engine.vote(proposalId, role, vote);
|
|
12178
12827
|
const resultRes = await engine.close(proposalId);
|
|
12179
12828
|
if (!resultRes.ok)
|
|
12180
12829
|
throw new Error(`Failed to close proposal: ${resultRes.error.message}`, {
|
|
@@ -12182,22 +12831,22 @@ async function processVotesThroughEngine(votes, proposal, algorithm) {
|
|
|
12182
12831
|
});
|
|
12183
12832
|
return resultRes.value;
|
|
12184
12833
|
}
|
|
12185
|
-
function runHigherOrderVoting(strategy, voteMap,
|
|
12834
|
+
function runHigherOrderVoting(strategy, voteMap, logger12) {
|
|
12186
12835
|
if (strategy !== "higher_order") return void 0;
|
|
12187
12836
|
const hovStrategy = new HigherOrderVotingStrategy();
|
|
12188
12837
|
const tracker = getOrCreateCorrelationTracker();
|
|
12189
12838
|
const result = hovStrategy.aggregate(voteMap, tracker);
|
|
12190
|
-
|
|
12839
|
+
logger12.info("Higher-Order Voting complete", {
|
|
12191
12840
|
method: result.method,
|
|
12192
12841
|
decision: result.decision,
|
|
12193
12842
|
posteriorApproval: result.posteriorApproval.toFixed(3)
|
|
12194
12843
|
});
|
|
12195
12844
|
return result;
|
|
12196
12845
|
}
|
|
12197
|
-
function recordVotesToTracker(votes, voteMap, outcome,
|
|
12846
|
+
function recordVotesToTracker(votes, voteMap, outcome, logger12) {
|
|
12198
12847
|
const allVotesReal = votes.every((v) => v.source === "llm");
|
|
12199
12848
|
if (!allVotesReal) {
|
|
12200
|
-
|
|
12849
|
+
logger12.warn("Skipping correlation recording due to non-LLM votes", {
|
|
12201
12850
|
count: votes.filter((v) => v.source !== "llm").length
|
|
12202
12851
|
});
|
|
12203
12852
|
return;
|
|
@@ -12205,22 +12854,21 @@ function recordVotesToTracker(votes, voteMap, outcome, logger11) {
|
|
|
12205
12854
|
const tracker = getOrCreateCorrelationTracker();
|
|
12206
12855
|
const id = `consensus-${String(getTimeProvider().now())}-${getRandomProvider().random().toString(36).slice(2, 9)}`;
|
|
12207
12856
|
tracker.recordProposalVotes(id, voteMap, outcome);
|
|
12208
|
-
|
|
12857
|
+
logger12.debug("Recorded votes to tracker", { proposalId: id, outcome });
|
|
12209
12858
|
try {
|
|
12210
12859
|
const persisted = createPersistedProposal(id, voteMap, outcome);
|
|
12211
12860
|
const saveResult = saveCorrelationData([persisted]);
|
|
12212
12861
|
if (!saveResult.ok) {
|
|
12213
|
-
|
|
12862
|
+
logger12.warn("Failed to persist correlation data", { error: saveResult.error.message });
|
|
12214
12863
|
}
|
|
12215
12864
|
} catch (error) {
|
|
12216
12865
|
const message = getErrorMessage(error);
|
|
12217
|
-
|
|
12866
|
+
logger12.warn("Error persisting correlation data", { error: message });
|
|
12218
12867
|
}
|
|
12219
12868
|
}
|
|
12220
|
-
async function processVotesWithCascade(
|
|
12221
|
-
const
|
|
12222
|
-
const
|
|
12223
|
-
const rejections = validVotes.filter((v) => v.vote.decision === "reject").length;
|
|
12869
|
+
async function processVotesWithCascade(engineVotes, opts) {
|
|
12870
|
+
const approvals = engineVotes.filter((v) => v.vote.decision === "approve").length;
|
|
12871
|
+
const rejections = engineVotes.filter((v) => v.vote.decision === "reject").length;
|
|
12224
12872
|
const cascadeInfo = detectEarlyCascade(opts.algorithm, approvals, rejections, opts.totalRoles);
|
|
12225
12873
|
if (cascadeInfo.decided) {
|
|
12226
12874
|
opts.log.info("Vote cascade: outcome decided early", {
|
|
@@ -12230,11 +12878,9 @@ async function processVotesWithCascade(votes, opts) {
|
|
|
12230
12878
|
reason: cascadeInfo.reason
|
|
12231
12879
|
});
|
|
12232
12880
|
}
|
|
12233
|
-
const engineResult = await processVotesThroughEngine(
|
|
12881
|
+
const engineResult = await processVotesThroughEngine(engineVotes, opts.proposal, opts.algorithm);
|
|
12234
12882
|
const voteMap = /* @__PURE__ */ new Map();
|
|
12235
|
-
for (const { role, vote
|
|
12236
|
-
if (source !== "error") voteMap.set(role, vote);
|
|
12237
|
-
}
|
|
12883
|
+
for (const { role, vote } of engineVotes) voteMap.set(role, vote);
|
|
12238
12884
|
const higherOrderResult = cascadeInfo.decided ? void 0 : runHigherOrderVoting(opts.strategy, voteMap, opts.log);
|
|
12239
12885
|
const outcome = engineResult.outcome === "approved" ? "approved" : "rejected";
|
|
12240
12886
|
return { engineResult, voteMap, higherOrderResult, outcome, cascaded: cascadeInfo.decided };
|
|
@@ -12242,7 +12888,7 @@ async function processVotesWithCascade(votes, opts) {
|
|
|
12242
12888
|
var CONTRARIAN_ESCALATION_THRESHOLD = 0.8;
|
|
12243
12889
|
async function runContrarianCheck(proposal, log) {
|
|
12244
12890
|
try {
|
|
12245
|
-
const { executeExpert } = await import("./expert-bridge-
|
|
12891
|
+
const { executeExpert } = await import("./expert-bridge-3AWQHR65.js");
|
|
12246
12892
|
const prompt = [
|
|
12247
12893
|
"You are a contrarian analyst. Your job is to find reasons this proposal should be REJECTED.",
|
|
12248
12894
|
"Look for: YAGNI (not needed), MISALIGNED (wrong tech/architecture), SECURITY_RISK, SCOPE_CREEP.",
|
|
@@ -12274,59 +12920,116 @@ async function runContrarianCheck(proposal, log) {
|
|
|
12274
12920
|
return { shouldEscalate: false, reason: "", confidence: 0 };
|
|
12275
12921
|
}
|
|
12276
12922
|
}
|
|
12277
|
-
|
|
12923
|
+
function buildPolicyShortCircuitResult(args) {
|
|
12924
|
+
args.logger.warn("Consensus vote short-circuited by error policy", {
|
|
12925
|
+
errorPolicy: args.errorPolicy,
|
|
12926
|
+
reason: args.reason
|
|
12927
|
+
});
|
|
12928
|
+
const totalTimeMs = getTimeProvider().now() - args.startTime;
|
|
12929
|
+
return {
|
|
12930
|
+
proposal: args.input.proposal,
|
|
12931
|
+
threshold: args.algorithm,
|
|
12932
|
+
result: createPolicyFailedResult(args.input.proposal, args.algorithm, args.reason),
|
|
12933
|
+
votes: args.votes,
|
|
12934
|
+
totalTimeMs,
|
|
12935
|
+
simulateVotes: args.input.simulateVotes,
|
|
12936
|
+
strategy: args.strategy
|
|
12937
|
+
};
|
|
12938
|
+
}
|
|
12939
|
+
async function maybeEscalateContrarian(input, outcome, logger12, opts) {
|
|
12940
|
+
if (!input.quickMode || outcome !== "approved" || input.simulateVotes) return void 0;
|
|
12941
|
+
const escalation = await runContrarianCheck(input.proposal, logger12);
|
|
12942
|
+
if (!escalation.shouldEscalate) return void 0;
|
|
12943
|
+
logger12.warn("Contrarian escalation: re-running with full vote", {
|
|
12944
|
+
reason: escalation.reason,
|
|
12945
|
+
confidence: escalation.confidence
|
|
12946
|
+
});
|
|
12947
|
+
return executeVoting({ ...input, quickMode: false }, logger12, opts);
|
|
12948
|
+
}
|
|
12949
|
+
async function executeVoting(input, logger12, opts) {
|
|
12278
12950
|
const strategy = resolveStrategy(input);
|
|
12279
12951
|
const algorithm = strategyToAlgorithm(strategy);
|
|
12280
12952
|
const roles = getVoterRoles(input.quickMode);
|
|
12281
12953
|
const startTime = getTimeProvider().now();
|
|
12282
|
-
|
|
12954
|
+
const errorPolicy = input.errorPolicy ?? getDefaultErrorPolicy(strategy);
|
|
12955
|
+
logger12.info("Starting consensus vote", {
|
|
12956
|
+
strategy,
|
|
12957
|
+
algorithm,
|
|
12958
|
+
roleCount: roles.length,
|
|
12959
|
+
errorPolicy
|
|
12960
|
+
});
|
|
12283
12961
|
const votes = await collectRealVotes({
|
|
12284
12962
|
roles,
|
|
12285
12963
|
proposal: input.proposal,
|
|
12286
|
-
simulate: input.simulateVotes
|
|
12964
|
+
simulate: input.simulateVotes,
|
|
12965
|
+
...opts?.voteTimeoutMs !== void 0 && { timeoutMs: opts.voteTimeoutMs }
|
|
12287
12966
|
});
|
|
12288
|
-
const
|
|
12967
|
+
const policyDecision = applyErrorPolicy(votes, errorPolicy);
|
|
12968
|
+
if (policyDecision.shortCircuit) {
|
|
12969
|
+
return buildPolicyShortCircuitResult({
|
|
12970
|
+
input,
|
|
12971
|
+
strategy,
|
|
12972
|
+
algorithm,
|
|
12973
|
+
votes,
|
|
12974
|
+
errorPolicy,
|
|
12975
|
+
reason: policyDecision.reason ?? "error policy short-circuit",
|
|
12976
|
+
startTime,
|
|
12977
|
+
logger: logger12
|
|
12978
|
+
});
|
|
12979
|
+
}
|
|
12980
|
+
const { engineResult, voteMap, higherOrderResult, outcome, cascaded } = await processVotesWithCascade(policyDecision.engineVotes, {
|
|
12289
12981
|
totalRoles: roles.length,
|
|
12290
12982
|
proposal: input.proposal,
|
|
12291
12983
|
algorithm,
|
|
12292
12984
|
strategy,
|
|
12293
|
-
log:
|
|
12985
|
+
log: logger12
|
|
12294
12986
|
});
|
|
12295
|
-
recordVotesToTracker(votes, voteMap, outcome,
|
|
12296
|
-
|
|
12297
|
-
|
|
12298
|
-
|
|
12299
|
-
|
|
12300
|
-
|
|
12301
|
-
|
|
12302
|
-
|
|
12303
|
-
|
|
12304
|
-
}
|
|
12305
|
-
}
|
|
12306
|
-
const totalTimeMs = getTimeProvider().now() - startTime;
|
|
12307
|
-
logger11.info("Consensus vote completed", { strategy, outcome, durationMs: totalTimeMs, cascaded });
|
|
12308
|
-
const result = {
|
|
12309
|
-
proposal: input.proposal,
|
|
12310
|
-
threshold: algorithm,
|
|
12311
|
-
result: engineResult,
|
|
12987
|
+
recordVotesToTracker(votes, voteMap, outcome, logger12);
|
|
12988
|
+
const escalated = await maybeEscalateContrarian(input, outcome, logger12, opts);
|
|
12989
|
+
if (escalated !== void 0) return escalated;
|
|
12990
|
+
return finalizeVotingResult({
|
|
12991
|
+
input,
|
|
12992
|
+
strategy,
|
|
12993
|
+
algorithm,
|
|
12994
|
+
engineResult,
|
|
12995
|
+
higherOrderResult,
|
|
12312
12996
|
votes,
|
|
12997
|
+
outcome,
|
|
12998
|
+
cascaded,
|
|
12999
|
+
startTime,
|
|
13000
|
+
logger: logger12
|
|
13001
|
+
});
|
|
13002
|
+
}
|
|
13003
|
+
function finalizeVotingResult(args) {
|
|
13004
|
+
const totalTimeMs = getTimeProvider().now() - args.startTime;
|
|
13005
|
+
args.logger.info("Consensus vote completed", {
|
|
13006
|
+
strategy: args.strategy,
|
|
13007
|
+
outcome: args.outcome,
|
|
13008
|
+
durationMs: totalTimeMs,
|
|
13009
|
+
cascaded: args.cascaded
|
|
13010
|
+
});
|
|
13011
|
+
const result = {
|
|
13012
|
+
proposal: args.input.proposal,
|
|
13013
|
+
threshold: args.algorithm,
|
|
13014
|
+
result: args.engineResult,
|
|
13015
|
+
votes: args.votes,
|
|
12313
13016
|
totalTimeMs,
|
|
12314
|
-
simulateVotes: input.simulateVotes,
|
|
12315
|
-
strategy
|
|
13017
|
+
simulateVotes: args.input.simulateVotes,
|
|
13018
|
+
strategy: args.strategy
|
|
12316
13019
|
};
|
|
12317
|
-
if (higherOrderResult !== void 0) result.higherOrderResult = higherOrderResult;
|
|
13020
|
+
if (args.higherOrderResult !== void 0) result.higherOrderResult = args.higherOrderResult;
|
|
12318
13021
|
return result;
|
|
12319
13022
|
}
|
|
12320
13023
|
async function handleConsensusVote(deps, args) {
|
|
12321
|
-
const
|
|
12322
|
-
if (args.simulateVotes) warnIfSimulatedOutsideTests("consensus_vote",
|
|
13024
|
+
const logger12 = deps.logger ?? createLogger({ tool: "consensus_vote" });
|
|
13025
|
+
if (args.simulateVotes) warnIfSimulatedOutsideTests("consensus_vote", logger12);
|
|
12323
13026
|
try {
|
|
12324
|
-
const result = await executeVoting(args,
|
|
13027
|
+
const result = await executeVoting(args, logger12);
|
|
12325
13028
|
const strategy = args.strategy ?? "simple_majority";
|
|
12326
13029
|
const errorVotes = result.votes.filter((v) => v.source === "error");
|
|
12327
13030
|
if (errorVotes.length === result.votes.length && result.votes.length > 0) {
|
|
12328
13031
|
const failures = errorVotes.map((v) => `${v.role}: ${v.error ?? "unknown error"}`).join("; ");
|
|
12329
|
-
|
|
13032
|
+
logger12.warn("All voters failed", { failureCount: errorVotes.length, failures });
|
|
12330
13033
|
recordVoteError(args.proposal, `All ${String(errorVotes.length)} voters failed: ${failures}`);
|
|
12331
13034
|
return {
|
|
12332
13035
|
ok: false,
|
|
@@ -12344,7 +13047,7 @@ async function handleConsensusVote(deps, args) {
|
|
|
12344
13047
|
} catch (error) {
|
|
12345
13048
|
const message = getErrorMessage(error);
|
|
12346
13049
|
const cause = error instanceof Error ? error : new Error(message);
|
|
12347
|
-
|
|
13050
|
+
logger12.error("Consensus vote failed", cause);
|
|
12348
13051
|
recordVoteError(args.proposal, message);
|
|
12349
13052
|
return { ok: false, error: `Voting failed: ${message}` };
|
|
12350
13053
|
}
|
|
@@ -12354,7 +13057,10 @@ function createConsensusVoteHandler(deps) {
|
|
|
12354
13057
|
return async (args, ctx) => {
|
|
12355
13058
|
const validationResult = ConsensusVoteInputSchema.safeParse(args);
|
|
12356
13059
|
if (!validationResult.success) {
|
|
12357
|
-
return
|
|
13060
|
+
return toolStructuredError({
|
|
13061
|
+
errorCategory: "validation",
|
|
13062
|
+
message: `Validation error: ${formatZodError(validationResult.error)}`
|
|
13063
|
+
});
|
|
12358
13064
|
}
|
|
12359
13065
|
const strategy = validationResult.data.strategy ?? "simple_majority";
|
|
12360
13066
|
ctx.logger.debug("Starting consensus vote", {
|
|
@@ -12372,7 +13078,7 @@ function createConsensusVoteHandler(deps) {
|
|
|
12372
13078
|
() => handleConsensusVote(deps, validationResult.data)
|
|
12373
13079
|
);
|
|
12374
13080
|
if (!result.ok) {
|
|
12375
|
-
return
|
|
13081
|
+
return toolStructuredError({ errorCategory: "internal", message: result.error });
|
|
12376
13082
|
}
|
|
12377
13083
|
for (const vote of result.value.votes) {
|
|
12378
13084
|
notifier.debug("consensus_vote", {
|
|
@@ -12395,27 +13101,27 @@ function createConsensusVoteHandler(deps) {
|
|
|
12395
13101
|
};
|
|
12396
13102
|
}
|
|
12397
13103
|
var CONSENSUS_VOTE_OUTPUT_SCHEMA = {
|
|
12398
|
-
proposal:
|
|
13104
|
+
proposal: z20.string(),
|
|
12399
13105
|
strategy: VotingStrategySchema,
|
|
12400
|
-
decision:
|
|
12401
|
-
approvalPercentage:
|
|
12402
|
-
voteCounts:
|
|
12403
|
-
approve:
|
|
12404
|
-
reject:
|
|
12405
|
-
abstain:
|
|
12406
|
-
error:
|
|
13106
|
+
decision: z20.enum(["approved", "rejected", "no_quorum"]),
|
|
13107
|
+
approvalPercentage: z20.number(),
|
|
13108
|
+
voteCounts: z20.object({
|
|
13109
|
+
approve: z20.number(),
|
|
13110
|
+
reject: z20.number(),
|
|
13111
|
+
abstain: z20.number(),
|
|
13112
|
+
error: z20.number()
|
|
12407
13113
|
}),
|
|
12408
|
-
votes:
|
|
12409
|
-
|
|
12410
|
-
role:
|
|
12411
|
-
decision:
|
|
12412
|
-
confidence:
|
|
12413
|
-
reasoning:
|
|
12414
|
-
simulated:
|
|
12415
|
-
error:
|
|
12416
|
-
modelUsed:
|
|
12417
|
-
rejectionCategories:
|
|
12418
|
-
|
|
13114
|
+
votes: z20.array(
|
|
13115
|
+
z20.object({
|
|
13116
|
+
role: z20.string().max(100),
|
|
13117
|
+
decision: z20.enum(["approve", "reject", "abstain"]),
|
|
13118
|
+
confidence: z20.number(),
|
|
13119
|
+
reasoning: z20.string().max(4e3),
|
|
13120
|
+
simulated: z20.boolean(),
|
|
13121
|
+
error: z20.boolean(),
|
|
13122
|
+
modelUsed: z20.string().max(100).optional(),
|
|
13123
|
+
rejectionCategories: z20.array(
|
|
13124
|
+
z20.enum([
|
|
12419
13125
|
"YAGNI",
|
|
12420
13126
|
"DRY_VIOLATION",
|
|
12421
13127
|
"OVER_ENGINEERING",
|
|
@@ -12427,50 +13133,55 @@ var CONSENSUS_VOTE_OUTPUT_SCHEMA = {
|
|
|
12427
13133
|
).optional()
|
|
12428
13134
|
})
|
|
12429
13135
|
),
|
|
12430
|
-
threshold:
|
|
12431
|
-
durationMs:
|
|
12432
|
-
simulateVotes:
|
|
12433
|
-
higherOrderMetadata:
|
|
12434
|
-
posteriorApproval:
|
|
12435
|
-
posteriorRejection:
|
|
12436
|
-
effectiveVoteCount:
|
|
12437
|
-
method:
|
|
12438
|
-
usedCorrelationData:
|
|
12439
|
-
improvementOverBaseline:
|
|
12440
|
-
downweightedAgents:
|
|
12441
|
-
reasoning:
|
|
13136
|
+
threshold: VoteThresholdSchema.optional(),
|
|
13137
|
+
durationMs: z20.number(),
|
|
13138
|
+
simulateVotes: z20.boolean(),
|
|
13139
|
+
higherOrderMetadata: z20.object({
|
|
13140
|
+
posteriorApproval: z20.number(),
|
|
13141
|
+
posteriorRejection: z20.number(),
|
|
13142
|
+
effectiveVoteCount: z20.number(),
|
|
13143
|
+
method: z20.enum(["ow", "isp", "simple"]),
|
|
13144
|
+
usedCorrelationData: z20.boolean(),
|
|
13145
|
+
improvementOverBaseline: z20.number(),
|
|
13146
|
+
downweightedAgents: z20.array(z20.string().max(100)).max(10),
|
|
13147
|
+
reasoning: z20.string().max(2e3)
|
|
12442
13148
|
}).optional()
|
|
12443
13149
|
};
|
|
12444
13150
|
function registerConsensusVoteTool(server, deps) {
|
|
12445
|
-
const
|
|
13151
|
+
const logger12 = deps.logger ?? createLogger({ tool: "consensus_vote" });
|
|
12446
13152
|
const notifier = deps.notifier ?? createMcpNotifier(server);
|
|
12447
13153
|
const depsWithNotifier = { ...deps, notifier };
|
|
12448
13154
|
const toolSchema = {
|
|
12449
|
-
proposal:
|
|
12450
|
-
threshold:
|
|
13155
|
+
proposal: z20.string().min(1).max(MAX_PROPOSAL_LENGTH).describe("Proposal text to vote on"),
|
|
13156
|
+
threshold: z20.enum(["majority", "supermajority", "unanimous"]).optional().describe("Voting threshold (legacy). Use strategy instead."),
|
|
12451
13157
|
strategy: VotingStrategySchema.optional().describe(
|
|
12452
13158
|
"Voting strategy: simple_majority (default), supermajority, unanimous, proof_of_learning, or higher_order"
|
|
12453
13159
|
),
|
|
12454
|
-
quickMode:
|
|
12455
|
-
simulateVotes:
|
|
13160
|
+
quickMode: z20.boolean().optional().default(false).describe("Use 3 agents instead of 7"),
|
|
13161
|
+
simulateVotes: z20.boolean().optional().default(false).describe("TESTS ONLY \u2014 random output, must not be used for real decisions (#2319)")
|
|
12456
13162
|
};
|
|
12457
13163
|
const description = "Execute multi-model consensus voting on a proposal. Uses 7 specialized agent roles (architect, security, devex, ai_ml, pm, catfish, scope_steward) to vote on proposals with configurable strategies. Supports higher_order strategy for Bayesian-optimal aggregation with correlation awareness (Issue #514).";
|
|
12458
13164
|
const secureHandler = createSecureHandler(createConsensusVoteHandler(depsWithNotifier), {
|
|
12459
13165
|
toolName: "consensus_vote",
|
|
12460
13166
|
rateLimiter: deps.rateLimiter,
|
|
12461
|
-
logger:
|
|
13167
|
+
logger: logger12
|
|
12462
13168
|
});
|
|
12463
13169
|
const timeoutMs = getToolTimeout("consensus_vote", deps.security);
|
|
12464
13170
|
const wrappedHandler = wrapToolWithTimeout("consensus_vote", secureHandler, {
|
|
12465
13171
|
timeoutMs,
|
|
12466
|
-
logger:
|
|
13172
|
+
logger: logger12
|
|
12467
13173
|
});
|
|
12468
13174
|
server.registerTool(
|
|
12469
13175
|
"consensus_vote",
|
|
12470
|
-
{
|
|
12471
|
-
|
|
13176
|
+
{
|
|
13177
|
+
description,
|
|
13178
|
+
inputSchema: toolSchema,
|
|
13179
|
+
outputSchema: CONSENSUS_VOTE_OUTPUT_SCHEMA,
|
|
13180
|
+
annotations: getToolAnnotations("consensus_vote")
|
|
13181
|
+
},
|
|
13182
|
+
toSdkCallbackWithBudgetCheck(wrappedHandler, "consensus_vote", timeoutMs, logger12)
|
|
12472
13183
|
);
|
|
12473
|
-
|
|
13184
|
+
logger12.info("Registered consensus_vote tool with secure handler and timeout protection");
|
|
12474
13185
|
}
|
|
12475
13186
|
|
|
12476
13187
|
export {
|
|
@@ -12486,6 +13197,8 @@ export {
|
|
|
12486
13197
|
getGlobalEventBus,
|
|
12487
13198
|
createEvent,
|
|
12488
13199
|
EventTopics,
|
|
13200
|
+
withModelNotFoundFallback,
|
|
13201
|
+
wrapResilientWithFallback,
|
|
12489
13202
|
createUnifiedRegistry,
|
|
12490
13203
|
getGlobalRegistry,
|
|
12491
13204
|
DEFAULT_RELEVANCE_CONFIG,
|
|
@@ -12508,6 +13221,10 @@ export {
|
|
|
12508
13221
|
logToolInvocationAudit,
|
|
12509
13222
|
logPolicyAudit,
|
|
12510
13223
|
logRateLimitAudit,
|
|
13224
|
+
toolSuccess,
|
|
13225
|
+
toolSuccessStructured,
|
|
13226
|
+
toolStructuredError,
|
|
13227
|
+
toolError,
|
|
12511
13228
|
createSecureHandler,
|
|
12512
13229
|
createMcpNotifier,
|
|
12513
13230
|
NOOP_NOTIFIER,
|
|
@@ -12517,9 +13234,8 @@ export {
|
|
|
12517
13234
|
getToolTimeout,
|
|
12518
13235
|
wrapToolWithTimeout,
|
|
12519
13236
|
toSdkCallback,
|
|
12520
|
-
|
|
12521
|
-
|
|
12522
|
-
toolError,
|
|
13237
|
+
toSdkCallbackWithBudgetCheck,
|
|
13238
|
+
getToolAnnotations,
|
|
12523
13239
|
getToolMemory,
|
|
12524
13240
|
shutdownToolMemory,
|
|
12525
13241
|
PersistentOutcomeStore,
|
|
@@ -12527,8 +13243,6 @@ export {
|
|
|
12527
13243
|
emitTrendDetected,
|
|
12528
13244
|
DEFAULT_VOTE_TIMEOUT_MS,
|
|
12529
13245
|
isRateLimitError,
|
|
12530
|
-
validateTimeout2 as validateTimeout,
|
|
12531
|
-
THRESHOLD_MAP,
|
|
12532
13246
|
VOTER_ROLES,
|
|
12533
13247
|
NoAdapterError,
|
|
12534
13248
|
collectRealVotes,
|
|
@@ -12587,6 +13301,8 @@ export {
|
|
|
12587
13301
|
CorrelationTracker,
|
|
12588
13302
|
createCorrelationTracker,
|
|
12589
13303
|
VotingStrategySchema,
|
|
13304
|
+
ErrorPolicySchema,
|
|
13305
|
+
VoteThresholdSchema,
|
|
12590
13306
|
ConsensusVoteInputSchema,
|
|
12591
13307
|
warnIfSimulatedOutsideTests,
|
|
12592
13308
|
resetCorrelationTracker,
|
|
@@ -12594,4 +13310,4 @@ export {
|
|
|
12594
13310
|
CONSENSUS_VOTE_OUTPUT_SCHEMA,
|
|
12595
13311
|
registerConsensusVoteTool
|
|
12596
13312
|
};
|
|
12597
|
-
//# sourceMappingURL=chunk-
|
|
13313
|
+
//# sourceMappingURL=chunk-T5VPZZYX.js.map
|